From c64108d45ca9288444293a3f8c1fe51291a610cf Mon Sep 17 00:00:00 2001 From: Jaeden Amero Date: Tue, 22 Jan 2019 16:09:24 +0000 Subject: [PATCH 1/6] tls/crypto: Make mbed-crypto importer independent Obtain the version of Mbed Crypto to use not from the Mbed TLS submodule, but independently through the Mbed Crypto importer instead. --- features/mbedtls/importer/Makefile | 44 ------- features/mbedtls/importer/adjust-config.sh | 2 +- .../mbedtls/mbed-crypto/importer/Makefile | 115 ++++++++++++++++++ .../importer/TARGET_IGNORE/.gitignore | 1 + 4 files changed, 117 insertions(+), 45 deletions(-) create mode 100644 features/mbedtls/mbed-crypto/importer/Makefile create mode 100644 features/mbedtls/mbed-crypto/importer/TARGET_IGNORE/.gitignore diff --git a/features/mbedtls/importer/Makefile b/features/mbedtls/importer/Makefile index a9adff62d3a..046e86405e3 100644 --- a/features/mbedtls/importer/Makefile +++ b/features/mbedtls/importer/Makefile @@ -32,34 +32,15 @@ MBED_TLS_REPO_URL ?= git@github.com:ARMmbed/mbedtls-restricted.git # Translate between mbed TLS namespace and mbed namespace TARGET_PREFIX:=../ -TARGET_PREFIX_CRYPTO:=../mbed-crypto/ TARGET_SRC:=$(TARGET_PREFIX)src TARGET_INC:=$(TARGET_PREFIX)inc TARGET_TESTS:=$(TARGET_PREFIX)TESTS -# New folder structure is introduced here for targets with Secured-Partition-Environment -# and Non-Secured-Partition-Environment, below documentation for each folder: -# COMPONENT_PSA_SRV_IMPL - include secure service business logic implementation -# code. For example Mbed Crypto or secure time core logic -TARGET_SRV_IMPL:=$(TARGET_PREFIX_CRYPTO)/platform/TARGET_PSA/COMPONENT_PSA_SRV_IMPL -# COMPONENT_SPE - include code that compiles ONLY to secure image and never -# compiles to non-secure image -TARGET_SPE:=$(TARGET_PREFIX_CRYPTO)/platform/TARGET_PSA/COMPONENT_SPE -# The folder contain specific target implementation using hardware. -TARGET_PSA_DRIVERS:=$(TARGET_PREFIX_CRYPTO)/targets -# COMPONENT_NSPE - include code that compiles ONLY to non-secure image and -# never compiles to secure image -TARGET_NSPE:=$(TARGET_SRV_IMPL)/COMPONENT_NSPE - # mbed TLS source directory - hidden from mbed via TARGET_IGNORE MBED_TLS_DIR:=TARGET_IGNORE/mbedtls MBED_TLS_API:=$(MBED_TLS_DIR)/include/mbedtls MBED_TLS_GIT_CFG=$(MBED_TLS_DIR)/.git/config -# Mbed Crypto directory - hidden from mbed via TARGET_IGNORE -MBED_CRYPTO_DIR:=$(MBED_TLS_DIR)/crypto -MBED_CRYPTO_API:=$(MBED_CRYPTO_DIR)/include/psa - .PHONY: all deploy deploy-tests rsync mbedtls clean update all: mbedtls @@ -81,23 +62,6 @@ rsync: cp $(MBED_TLS_DIR)/LICENSE $(TARGET_PREFIX) cp $(MBED_TLS_DIR)/apache-2.0.txt $(TARGET_PREFIX) # - # Create Mbed Crypto target folder - mkdir -p $(TARGET_PREFIX_CRYPTO) - # - # Copying Mbed Crypto into Mbed OS.. - rm -rf $(TARGET_SRV_IMPL) - rm -rf $(TARGET_SPE) - - mkdir -p $(TARGET_SRV_IMPL) - mkdir -p $(TARGET_SPE) - mkdir -p $(TARGET_NSPE) - mkdir -p $(TARGET_PSA_DRIVERS) - - rsync -a --delete --exclude='crypto_struct.h' $(MBED_CRYPTO_API) $(TARGET_INC) - rsync -a --delete $(MBED_CRYPTO_API)/crypto_struct.h $(TARGET_NSPE) - rsync -a --delete $(MBED_CRYPTO_API)/crypto_struct.h $(TARGET_SPE)/crypto_struct_spe.h - rsync -a --delete $(MBED_CRYPTO_DIR)/library/psa_*.c $(TARGET_SRV_IMPL) - rsync -a --delete $(MBED_CRYPTO_DIR)/library/psa_*.h $(TARGET_SRV_IMPL) deploy: rsync # @@ -128,14 +92,8 @@ update: $(MBED_TLS_GIT_CFG) $(MBED_TLS_HA_GIT_CFG) # Checking out the required release git -C $(MBED_TLS_DIR) checkout $(MBED_TLS_RELEASE) # - # Update and checkout git submodules - git -C $(MBED_TLS_DIR) submodule update --init --recursive - # # Updating checked out version tag echo $(MBED_TLS_RELEASE) > $(TARGET_PREFIX)VERSION.txt - # - # Updating Mbed Crypto checked out version tag - git -C $(MBED_CRYPTO_DIR) describe --tags --abbrev=12 --dirty --always >> $(TARGET_PREFIX)VERSION.txt $(MBED_TLS_GIT_CFG): rm -rf $(MBED_TLS_DIR) @@ -149,5 +107,3 @@ clean: rm -rf $(TARGET_SRC) rm -rf $(TARGET_INC) rm -rf $(MBED_TLS_DIR) - rm -rf $(TARGET_SRV_IMPL) - rm -rf $(TARGET_SPE) diff --git a/features/mbedtls/importer/adjust-config.sh b/features/mbedtls/importer/adjust-config.sh index 347ca5c1558..4d9bb1b30db 100755 --- a/features/mbedtls/importer/adjust-config.sh +++ b/features/mbedtls/importer/adjust-config.sh @@ -146,7 +146,7 @@ conf unset MBEDTLS_PLATFORM_TIME_TYPE_MACRO # which should fit RSA 4096 bit keys. conf set MBEDTLS_MPI_MAX_SIZE 512 -# The following configurations are a needed for Mbed Crypto submodule. +# The following configurations are needed for Mbed Crypto. # They are related to the persistent key storage feature. conf set MBEDTLS_PSA_CRYPTO_STORAGE_C conf set MBEDTLS_PSA_CRYPTO_STORAGE_ITS_C diff --git a/features/mbedtls/mbed-crypto/importer/Makefile b/features/mbedtls/mbed-crypto/importer/Makefile new file mode 100644 index 00000000000..d83e8b8f8d0 --- /dev/null +++ b/features/mbedtls/mbed-crypto/importer/Makefile @@ -0,0 +1,115 @@ +########################################################################### +# +# Copyright (c) 2016, ARM Limited, All Rights Reserved +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +########################################################################### + +# +# Use this file to import an Mbed Crypto release into Mbed OS as follows: +# +# 1) Set the CRYPTO_RELEASE variable to the required Mbed Crypto release +# tag +# 2) make update +# 3) make +# 4) commit and push changes via git +# + +# Set the Mbed Crypto release to import (this can/should be edited before +# import) +CRYPTO_RELEASE ?= mbedcrypto-0.1.0b2 +CRYPTO_REPO_URL ?= git@github.com:ARMmbed/mbed-crypto.git + +# Translate between Mbed Crypto namespace and Mbed OS namespace +TARGET_PREFIX:=.. +TARGET_INC:=$(TARGET_PREFIX)/inc + +# A folder structure is introduced here for targets that have both a Secure +# Processing Environment (SPE) targets and Non-secure Processing Environment +# (NSPE). Documentation for each folder as follows: +# COMPONENT_PSA_SRV_IMPL - Include secure service implementation code. For +# example PSA Crypto or PSA Secure Time implementations +TARGET_SRV_IMPL:=$(TARGET_PREFIX)/platform/TARGET_PSA/COMPONENT_PSA_SRV_IMPL +# COMPONENT_SPE - Include code that compiles ONLY to the SPE image and never +# compiles to the NSPE image +TARGET_SPE:=$(TARGET_PREFIX)/platform/TARGET_PSA/COMPONENT_SPE +# COMPONENT_NSPE - Include code that compiles ONLY to the NSPE image and never +# compiles to the SPE image +TARGET_NSPE:=$(TARGET_SRV_IMPL)/COMPONENT_NSPE + +# Mbed Crypto source directory - hidden from mbed via TARGET_IGNORE +CRYPTO_DIR:=TARGET_IGNORE/mbed-crypto +CRYPTO_API:=$(CRYPTO_DIR)/include/psa +CRYPTO_GIT_CFG=$(CRYPTO_DIR)/.git/config + + +.PHONY: all rsync clean update + +all: rsync + +rsync: + # + # Copying Mbed Crypto headers to includes... + rm -rf $(TARGET_INC) + mkdir -p $(TARGET_INC) + rsync -a --delete --exclude='crypto_struct.h' $(CRYPTO_API) $(TARGET_INC)/ + # + # Copying licenses + cp $(CRYPTO_DIR)/LICENSE $(TARGET_PREFIX)/ + cp $(CRYPTO_DIR)/apache-2.0.txt $(TARGET_PREFIX)/ + # + # Copying Mbed Crypto into Mbed OS... + rm -rf $(TARGET_SRV_IMPL) + rm -rf $(TARGET_SPE) + + mkdir -p $(TARGET_SRV_IMPL) + mkdir -p $(TARGET_SPE) + mkdir -p $(TARGET_NSPE) + + rsync -a --delete $(CRYPTO_API)/crypto_struct.h $(TARGET_NSPE)/ + rsync -a --delete $(CRYPTO_API)/crypto_struct.h $(TARGET_SPE)/crypto_struct_spe.h + rsync -a --delete $(CRYPTO_DIR)/library/psa_*.c $(TARGET_SRV_IMPL)/ + rsync -a --delete $(CRYPTO_DIR)/library/psa_*.h $(TARGET_SRV_IMPL)/ + +update: $(CRYPTO_GIT_CFG) + # + # Updating to the specified Mbed Crypto library version + # (If it is not an initial checkout we will start with the repository + # being in a detached head state) + git -C $(CRYPTO_DIR) checkout development + git -C $(CRYPTO_DIR) pull --rebase origin development + # + # Checking out the required release + git -C $(CRYPTO_DIR) checkout $(CRYPTO_RELEASE) + # + # Update and checkout git submodules + git -C $(CRYPTO_DIR) submodule update --init --recursive + # + # Updating Mbed Crypto checked out version tag + git -C $(CRYPTO_DIR) describe --tags --abbrev=12 --dirty --always > $(TARGET_PREFIX)/VERSION.txt + +$(CRYPTO_GIT_CFG): + rm -rf $(CRYPTO_DIR) + git clone $(CRYPTO_REPO_URL) $(CRYPTO_DIR) + +clean: + rm -f $(TARGET_PREFIX)/LICENSE + rm -f $(TARGET_PREFIX)/apache-2.0.txt + rm -f $(TARGET_PREFIX)/VERSION.txt + rm -f $(TARGET_PREFIX)/AUTHORS.txt + rm -rf $(TARGET_INC) + rm -rf $(CRYPTO_DIR) + rm -rf $(TARGET_SRV_IMPL) + rm -rf $(TARGET_SPE) diff --git a/features/mbedtls/mbed-crypto/importer/TARGET_IGNORE/.gitignore b/features/mbedtls/mbed-crypto/importer/TARGET_IGNORE/.gitignore new file mode 100644 index 00000000000..05fd348e289 --- /dev/null +++ b/features/mbedtls/mbed-crypto/importer/TARGET_IGNORE/.gitignore @@ -0,0 +1 @@ +mbed-crypto From 0f9f45fe1c9e5be4d754b5435a6eee83d831200b Mon Sep 17 00:00:00 2001 From: Jaeden Amero Date: Tue, 22 Jan 2019 16:58:00 +0000 Subject: [PATCH 2/6] crypto: Re-import Mbed Crypto 0.1.0b2 Use the Mbed-Crypto-specific importer script to re-import Mbed Crypto 0.1.0b2 to its new location. --- features/mbedtls/VERSION.txt | 1 - features/mbedtls/mbed-crypto/LICENSE | 2 + features/mbedtls/mbed-crypto/VERSION.txt | 1 + features/mbedtls/mbed-crypto/apache-2.0.txt | 202 ++++++++++++++++++ .../{ => mbed-crypto}/inc/psa/crypto.h | 0 .../{ => mbed-crypto}/inc/psa/crypto_driver.h | 0 .../{ => mbed-crypto}/inc/psa/crypto_extra.h | 0 .../inc/psa/crypto_platform.h | 0 .../{ => mbed-crypto}/inc/psa/crypto_sizes.h | 0 9 files changed, 205 insertions(+), 1 deletion(-) create mode 100644 features/mbedtls/mbed-crypto/LICENSE create mode 100644 features/mbedtls/mbed-crypto/VERSION.txt create mode 100644 features/mbedtls/mbed-crypto/apache-2.0.txt rename features/mbedtls/{ => mbed-crypto}/inc/psa/crypto.h (100%) rename features/mbedtls/{ => mbed-crypto}/inc/psa/crypto_driver.h (100%) rename features/mbedtls/{ => mbed-crypto}/inc/psa/crypto_extra.h (100%) rename features/mbedtls/{ => mbed-crypto}/inc/psa/crypto_platform.h (100%) rename features/mbedtls/{ => mbed-crypto}/inc/psa/crypto_sizes.h (100%) diff --git a/features/mbedtls/VERSION.txt b/features/mbedtls/VERSION.txt index a85e9b07f86..249c0cd89b5 100644 --- a/features/mbedtls/VERSION.txt +++ b/features/mbedtls/VERSION.txt @@ -1,2 +1 @@ mbedtls-2.15.1 -mbedcrypto-0.1.0b2 diff --git a/features/mbedtls/mbed-crypto/LICENSE b/features/mbedtls/mbed-crypto/LICENSE new file mode 100644 index 00000000000..546a8e631f5 --- /dev/null +++ b/features/mbedtls/mbed-crypto/LICENSE @@ -0,0 +1,2 @@ +Unless specifically indicated otherwise in a file, files are licensed +under the Apache 2.0 license, as can be found in: apache-2.0.txt diff --git a/features/mbedtls/mbed-crypto/VERSION.txt b/features/mbedtls/mbed-crypto/VERSION.txt new file mode 100644 index 00000000000..fb3017aa2fc --- /dev/null +++ b/features/mbedtls/mbed-crypto/VERSION.txt @@ -0,0 +1 @@ +mbedcrypto-0.1.0b2 diff --git a/features/mbedtls/mbed-crypto/apache-2.0.txt b/features/mbedtls/mbed-crypto/apache-2.0.txt new file mode 100644 index 00000000000..d6456956733 --- /dev/null +++ b/features/mbedtls/mbed-crypto/apache-2.0.txt @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/features/mbedtls/inc/psa/crypto.h b/features/mbedtls/mbed-crypto/inc/psa/crypto.h similarity index 100% rename from features/mbedtls/inc/psa/crypto.h rename to features/mbedtls/mbed-crypto/inc/psa/crypto.h diff --git a/features/mbedtls/inc/psa/crypto_driver.h b/features/mbedtls/mbed-crypto/inc/psa/crypto_driver.h similarity index 100% rename from features/mbedtls/inc/psa/crypto_driver.h rename to features/mbedtls/mbed-crypto/inc/psa/crypto_driver.h diff --git a/features/mbedtls/inc/psa/crypto_extra.h b/features/mbedtls/mbed-crypto/inc/psa/crypto_extra.h similarity index 100% rename from features/mbedtls/inc/psa/crypto_extra.h rename to features/mbedtls/mbed-crypto/inc/psa/crypto_extra.h diff --git a/features/mbedtls/inc/psa/crypto_platform.h b/features/mbedtls/mbed-crypto/inc/psa/crypto_platform.h similarity index 100% rename from features/mbedtls/inc/psa/crypto_platform.h rename to features/mbedtls/mbed-crypto/inc/psa/crypto_platform.h diff --git a/features/mbedtls/inc/psa/crypto_sizes.h b/features/mbedtls/mbed-crypto/inc/psa/crypto_sizes.h similarity index 100% rename from features/mbedtls/inc/psa/crypto_sizes.h rename to features/mbedtls/mbed-crypto/inc/psa/crypto_sizes.h From 66cbb32aa72e35e80f940e4da67118561878a09f Mon Sep 17 00:00:00 2001 From: Jaeden Amero Date: Tue, 22 Jan 2019 17:47:09 +0000 Subject: [PATCH 3/6] crypto: importer: Update with fetch Instead of doing a "pull --rebase" to update to the latest development branch, do a "fetch" followed by a "checkout" to update to the specified release. This enables us to get any new tags created since the last update to the development branch, and removes the noise of updating a local "development" branch. --- features/mbedtls/mbed-crypto/importer/Makefile | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/features/mbedtls/mbed-crypto/importer/Makefile b/features/mbedtls/mbed-crypto/importer/Makefile index d83e8b8f8d0..60f3a2ee393 100644 --- a/features/mbedtls/mbed-crypto/importer/Makefile +++ b/features/mbedtls/mbed-crypto/importer/Makefile @@ -29,7 +29,7 @@ # Set the Mbed Crypto release to import (this can/should be edited before # import) -CRYPTO_RELEASE ?= mbedcrypto-0.1.0b2 +CRYPTO_RELEASE ?= mbedcrypto-1.0.0d0 CRYPTO_REPO_URL ?= git@github.com:ARMmbed/mbed-crypto.git # Translate between Mbed Crypto namespace and Mbed OS namespace @@ -88,8 +88,7 @@ update: $(CRYPTO_GIT_CFG) # Updating to the specified Mbed Crypto library version # (If it is not an initial checkout we will start with the repository # being in a detached head state) - git -C $(CRYPTO_DIR) checkout development - git -C $(CRYPTO_DIR) pull --rebase origin development + git -C $(CRYPTO_DIR) fetch # # Checking out the required release git -C $(CRYPTO_DIR) checkout $(CRYPTO_RELEASE) From 9bcbfc532d67d1b08fd2e2069f52a4a07a6857b4 Mon Sep 17 00:00:00 2001 From: Jaeden Amero Date: Tue, 22 Jan 2019 17:53:11 +0000 Subject: [PATCH 4/6] crypto: Update to Mbed Crypto 1.0.0d1 --- features/mbedtls/mbed-crypto/VERSION.txt | 2 +- .../mbedtls/mbed-crypto/importer/Makefile | 2 +- features/mbedtls/mbed-crypto/inc/psa/crypto.h | 2170 ++++------------- .../mbed-crypto/inc/psa/crypto_accel_driver.h | 796 ++++++ .../inc/psa/crypto_driver_common.h | 54 + .../inc/psa/crypto_entropy_driver.h | 111 + .../mbed-crypto/inc/psa/crypto_platform.h | 4 +- .../{crypto_driver.h => crypto_se_driver.h} | 857 +------ .../mbed-crypto/inc/psa/crypto_sizes.h | 111 +- .../mbed-crypto/inc/psa/crypto_types.h | 101 + .../mbed-crypto/inc/psa/crypto_values.h | 1420 +++++++++++ .../COMPONENT_NSPE/crypto_struct.h | 29 + .../COMPONENT_PSA_SRV_IMPL/psa_crypto.c | 759 +++--- .../COMPONENT_PSA_SRV_IMPL/psa_crypto_core.h | 99 + .../psa_crypto_invasive.h | 79 + .../psa_crypto_slot_management.c | 291 +++ .../psa_crypto_slot_management.h | 58 + .../psa_crypto_storage.c | 4 +- .../psa_crypto_storage.h | 44 +- .../psa_crypto_storage_backend.h | 29 +- .../psa_crypto_storage_file.c | 29 +- .../psa_crypto_storage_its.c | 12 +- .../COMPONENT_SPE/crypto_struct_spe.h | 29 + 23 files changed, 4135 insertions(+), 2955 deletions(-) create mode 100644 features/mbedtls/mbed-crypto/inc/psa/crypto_accel_driver.h create mode 100644 features/mbedtls/mbed-crypto/inc/psa/crypto_driver_common.h create mode 100644 features/mbedtls/mbed-crypto/inc/psa/crypto_entropy_driver.h rename features/mbedtls/mbed-crypto/inc/psa/{crypto_driver.h => crypto_se_driver.h} (52%) create mode 100644 features/mbedtls/mbed-crypto/inc/psa/crypto_types.h create mode 100644 features/mbedtls/mbed-crypto/inc/psa/crypto_values.h create mode 100644 features/mbedtls/mbed-crypto/platform/TARGET_PSA/COMPONENT_PSA_SRV_IMPL/psa_crypto_core.h create mode 100644 features/mbedtls/mbed-crypto/platform/TARGET_PSA/COMPONENT_PSA_SRV_IMPL/psa_crypto_invasive.h create mode 100644 features/mbedtls/mbed-crypto/platform/TARGET_PSA/COMPONENT_PSA_SRV_IMPL/psa_crypto_slot_management.c create mode 100644 features/mbedtls/mbed-crypto/platform/TARGET_PSA/COMPONENT_PSA_SRV_IMPL/psa_crypto_slot_management.h diff --git a/features/mbedtls/mbed-crypto/VERSION.txt b/features/mbedtls/mbed-crypto/VERSION.txt index fb3017aa2fc..605916325f6 100644 --- a/features/mbedtls/mbed-crypto/VERSION.txt +++ b/features/mbedtls/mbed-crypto/VERSION.txt @@ -1 +1 @@ -mbedcrypto-0.1.0b2 +mbedcrypto-1.0.0d1 diff --git a/features/mbedtls/mbed-crypto/importer/Makefile b/features/mbedtls/mbed-crypto/importer/Makefile index 60f3a2ee393..6daef790f4d 100644 --- a/features/mbedtls/mbed-crypto/importer/Makefile +++ b/features/mbedtls/mbed-crypto/importer/Makefile @@ -29,7 +29,7 @@ # Set the Mbed Crypto release to import (this can/should be edited before # import) -CRYPTO_RELEASE ?= mbedcrypto-1.0.0d0 +CRYPTO_RELEASE ?= mbedcrypto-1.0.0d1 CRYPTO_REPO_URL ?= git@github.com:ARMmbed/mbed-crypto.git # Translate between Mbed Crypto namespace and Mbed OS namespace diff --git a/features/mbedtls/mbed-crypto/inc/psa/crypto.h b/features/mbedtls/mbed-crypto/inc/psa/crypto.h index 1ca64922e5e..06f9eb81f73 100644 --- a/features/mbedtls/mbed-crypto/inc/psa/crypto.h +++ b/features/mbedtls/mbed-crypto/inc/psa/crypto.h @@ -36,19 +36,15 @@ * @{ */ -/** \brief Key slot number. +/** \brief Key handle. * - * This type represents key slots. It must be an unsigned integral + * This type represents open handles to keys. It must be an unsigned integral * type. The choice of type is implementation-dependent. - * 0 is not a valid key slot number. The meaning of other values is - * implementation dependent. * - * At any given point in time, each key slot either contains a - * cryptographic object, or is empty. Key slots are persistent: - * once set, the cryptographic object remains in the key slot until - * explicitly destroyed. + * 0 is not a valid key handle. How other handle values are assigned is + * implementation-dependent. */ -typedef _unsigned_integral_type_ psa_key_slot_t; +typedef _unsigned_integral_type_ psa_key_handle_t; /**@}*/ #endif /* __DOXYGEN_ONLY__ */ @@ -57,262 +53,17 @@ typedef _unsigned_integral_type_ psa_key_slot_t; extern "C" { #endif -/** \defgroup basic Basic definitions - * @{ - */ - -#if defined(PSA_SUCCESS) -/* If PSA_SUCCESS is defined, assume that PSA crypto is being used - * together with PSA IPC, which also defines the identifier - * PSA_SUCCESS. We must not define PSA_SUCCESS ourselves in that case; - * the other error code names don't clash. Also define psa_status_t as - * an alias for the type used by PSA IPC. This is a temporary hack - * until we unify error reporting in PSA IPC and PSA crypto. - * - * Note that psa_defs.h must be included before this header! - */ -typedef psa_error_t psa_status_t; +/* The file "crypto_types.h" declares types that encode errors, + * algorithms, key types, policies, etc. */ +#include "crypto_types.h" -#else /* defined(PSA_SUCCESS) */ +/* The file "crypto_values.h" declares macros to build and analyze values + * of integral types defined in "crypto_types.h". */ +#include "crypto_values.h" -/** - * \brief Function return status. - * - * This is either #PSA_SUCCESS (which is zero), indicating success, - * or a nonzero value indicating that an error occurred. Errors are - * encoded as one of the \c PSA_ERROR_xxx values defined here. +/** \defgroup initialization Library initialization + * @{ */ -typedef int32_t psa_status_t; - -/** The action was completed successfully. */ -#define PSA_SUCCESS ((psa_status_t)0) - -#endif /* !defined(PSA_SUCCESS) */ - -/** 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_UNKNOWN_ERROR ((psa_status_t)1) - -/** 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)2) - -/** 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)3) - -/** 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)4) - -/** A slot is occupied, but must be empty to carry out the - * requested action. - * - * If the slot number is invalid (i.e. the requested action could - * not be performed even after erasing the slot's content), - * implementations shall return #PSA_ERROR_INVALID_ARGUMENT instead. */ -#define PSA_ERROR_OCCUPIED_SLOT ((psa_status_t)5) - -/** A slot is empty, but must be occupied to carry out the - * requested action. - * - * If the slot number is invalid (i.e. the requested action could - * not be performed even after creating appropriate content in the slot), - * implementations shall return #PSA_ERROR_INVALID_ARGUMENT instead. */ -#define PSA_ERROR_EMPTY_SLOT ((psa_status_t)6) - -/** 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 slot is occupied when it needs to be free or vice versa, - * but shall return #PSA_ERROR_OCCUPIED_SLOT or #PSA_ERROR_EMPTY_SLOT - * as applicable. */ -#define PSA_ERROR_BAD_STATE ((psa_status_t)7) - -/** 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 slot is occupied when it needs to be free or vice versa, - * but shall return #PSA_ERROR_OCCUPIED_SLOT or #PSA_ERROR_EMPTY_SLOT - * as applicable. */ -#define PSA_ERROR_INVALID_ARGUMENT ((psa_status_t)8) - -/** 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)9) - -/** 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)10) - -/** 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 whenver - * 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)11) - -/** 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_TAMPERING_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 canont 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)12) - -/** 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)13) - -/** 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_TAMPERING_DETECTED ((psa_status_t)14) - -/** 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)15) - -/** 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)16) - -/** 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)17) - -/** The generator has insufficient capacity left. - * - * Once a function returns this error, attempts to read from the - * generator will always return this error. */ -#define PSA_ERROR_INSUFFICIENT_CAPACITY ((psa_status_t)18) /** * \brief Library initialization. @@ -340,1064 +91,140 @@ typedef int32_t psa_status_t; */ psa_status_t psa_crypto_init(void); -#define PSA_BITS_TO_BYTES(bits) (((bits) + 7) / 8) -#define PSA_BYTES_TO_BITS(bytes) ((bytes) * 8) - /**@}*/ -/** \defgroup crypto_types Key and algorithm types +/** \defgroup key_management Key management * @{ */ -/** \brief Encoding of a key type. - */ -typedef uint32_t psa_key_type_t; - -/** An invalid key type value. - * - * Zero is not the encoding of any key type. - */ -#define PSA_KEY_TYPE_NONE ((psa_key_type_t)0x00000000) - -/** Vendor-defined 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)0x80000000) - -#define PSA_KEY_TYPE_CATEGORY_MASK ((psa_key_type_t)0x70000000) -#define PSA_KEY_TYPE_CATEGORY_SYMMETRIC ((psa_key_type_t)0x40000000) -#define PSA_KEY_TYPE_CATEGORY_RAW ((psa_key_type_t)0x50000000) -#define PSA_KEY_TYPE_CATEGORY_PUBLIC_KEY ((psa_key_type_t)0x60000000) -#define PSA_KEY_TYPE_CATEGORY_KEY_PAIR ((psa_key_type_t)0x70000000) - -#define PSA_KEY_TYPE_CATEGORY_FLAG_PAIR ((psa_key_type_t)0x10000000) - -/** Whether a key type is vendor-defined. */ -#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_t)0x10000000) == \ - 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_KEYPAIR(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_KEYPAIR_OF_PUBLIC_KEY(type) \ - ((type) | PSA_KEY_TYPE_CATEGORY_FLAG_PAIR) -/** The public key type corresponding to a key pair type. - * - * You may also pass a key pair type as \p type, it will be left unchanged. - * - * \param type A public key type or key pair type. - * - * \return The corresponding public key type. - * If \p type is not a public key or a key pair, - * the return value is undefined. - */ -#define PSA_KEY_TYPE_PUBLIC_KEY_OF_KEYPAIR(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)0x50000001) - -/** 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_SIZE(\c alg) where - * \c alg is the HMAC algorithm or the underlying hash algorithm. */ -#define PSA_KEY_TYPE_HMAC ((psa_key_type_t)0x51000000) - -/** A secret for key derivation. - * - * The key policy determines which key derivation algorithm the key - * can be used for. - */ -#define PSA_KEY_TYPE_DERIVE ((psa_key_type_t)0x52000000) - -/** Key for an 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)0x40000001) - -/** Key for a cipher or MAC algorithm based on DES or 3DES (Triple-DES). - * - * The size of the key can be 8 bytes (single DES), 16 bytes (2-key 3DES) or - * 24 bytes (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)0x40000002) - -/** Key for an cipher, AEAD or MAC algorithm based on the - * Camellia block cipher. */ -#define PSA_KEY_TYPE_CAMELLIA ((psa_key_type_t)0x40000003) - -/** Key for the RC4 stream cipher. - * - * Note that RC4 is weak and deprecated and should only be used in - * legacy protocols. */ -#define PSA_KEY_TYPE_ARC4 ((psa_key_type_t)0x40000004) - -/** RSA public key. */ -#define PSA_KEY_TYPE_RSA_PUBLIC_KEY ((psa_key_type_t)0x60010000) -/** RSA key pair (private and public key). */ -#define PSA_KEY_TYPE_RSA_KEYPAIR ((psa_key_type_t)0x70010000) -/** 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_KEYPAIR(type) == PSA_KEY_TYPE_RSA_PUBLIC_KEY) - -/** DSA public key. */ -#define PSA_KEY_TYPE_DSA_PUBLIC_KEY ((psa_key_type_t)0x60020000) -/** DSA key pair (private and public key). */ -#define PSA_KEY_TYPE_DSA_KEYPAIR ((psa_key_type_t)0x70020000) -/** Whether a key type is an DSA key (pair or public-only). */ -#define PSA_KEY_TYPE_IS_DSA(type) \ - (PSA_KEY_TYPE_PUBLIC_KEY_OF_KEYPAIR(type) == PSA_KEY_TYPE_DSA_PUBLIC_KEY) - -#define PSA_KEY_TYPE_ECC_PUBLIC_KEY_BASE ((psa_key_type_t)0x60030000) -#define PSA_KEY_TYPE_ECC_KEYPAIR_BASE ((psa_key_type_t)0x70030000) -#define PSA_KEY_TYPE_ECC_CURVE_MASK ((psa_key_type_t)0x0000ffff) -/** Elliptic curve key pair. */ -#define PSA_KEY_TYPE_ECC_KEYPAIR(curve) \ - (PSA_KEY_TYPE_ECC_KEYPAIR_BASE | (curve)) -/** Elliptic curve public key. */ -#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_KEYPAIR(type) & \ - ~PSA_KEY_TYPE_ECC_CURVE_MASK) == PSA_KEY_TYPE_ECC_PUBLIC_KEY_BASE) -#define PSA_KEY_TYPE_IS_ECC_KEYPAIR(type) \ - (((type) & ~PSA_KEY_TYPE_ECC_CURVE_MASK) == \ - PSA_KEY_TYPE_ECC_KEYPAIR_BASE) -#define PSA_KEY_TYPE_IS_ECC_PUBLIC_KEY(type) \ - (((type) & ~PSA_KEY_TYPE_ECC_CURVE_MASK) == \ - PSA_KEY_TYPE_ECC_PUBLIC_KEY_BASE) - -/** The type of PSA elliptic curve identifiers. */ -typedef uint16_t psa_ecc_curve_t; -/** Extract the curve from an elliptic curve key type. */ -#define PSA_KEY_TYPE_GET_CURVE(type) \ - ((psa_ecc_curve_t) (PSA_KEY_TYPE_IS_ECC(type) ? \ - ((type) & PSA_KEY_TYPE_ECC_CURVE_MASK) : \ - 0)) - -/* The encoding of curve identifiers is currently aligned with the - * TLS Supported Groups Registry (formerly known as the - * TLS EC Named Curve Registry) - * https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#tls-parameters-8 - * The values are defined by RFC 8422 and RFC 7027. */ -#define PSA_ECC_CURVE_SECT163K1 ((psa_ecc_curve_t) 0x0001) -#define PSA_ECC_CURVE_SECT163R1 ((psa_ecc_curve_t) 0x0002) -#define PSA_ECC_CURVE_SECT163R2 ((psa_ecc_curve_t) 0x0003) -#define PSA_ECC_CURVE_SECT193R1 ((psa_ecc_curve_t) 0x0004) -#define PSA_ECC_CURVE_SECT193R2 ((psa_ecc_curve_t) 0x0005) -#define PSA_ECC_CURVE_SECT233K1 ((psa_ecc_curve_t) 0x0006) -#define PSA_ECC_CURVE_SECT233R1 ((psa_ecc_curve_t) 0x0007) -#define PSA_ECC_CURVE_SECT239K1 ((psa_ecc_curve_t) 0x0008) -#define PSA_ECC_CURVE_SECT283K1 ((psa_ecc_curve_t) 0x0009) -#define PSA_ECC_CURVE_SECT283R1 ((psa_ecc_curve_t) 0x000a) -#define PSA_ECC_CURVE_SECT409K1 ((psa_ecc_curve_t) 0x000b) -#define PSA_ECC_CURVE_SECT409R1 ((psa_ecc_curve_t) 0x000c) -#define PSA_ECC_CURVE_SECT571K1 ((psa_ecc_curve_t) 0x000d) -#define PSA_ECC_CURVE_SECT571R1 ((psa_ecc_curve_t) 0x000e) -#define PSA_ECC_CURVE_SECP160K1 ((psa_ecc_curve_t) 0x000f) -#define PSA_ECC_CURVE_SECP160R1 ((psa_ecc_curve_t) 0x0010) -#define PSA_ECC_CURVE_SECP160R2 ((psa_ecc_curve_t) 0x0011) -#define PSA_ECC_CURVE_SECP192K1 ((psa_ecc_curve_t) 0x0012) -#define PSA_ECC_CURVE_SECP192R1 ((psa_ecc_curve_t) 0x0013) -#define PSA_ECC_CURVE_SECP224K1 ((psa_ecc_curve_t) 0x0014) -#define PSA_ECC_CURVE_SECP224R1 ((psa_ecc_curve_t) 0x0015) -#define PSA_ECC_CURVE_SECP256K1 ((psa_ecc_curve_t) 0x0016) -#define PSA_ECC_CURVE_SECP256R1 ((psa_ecc_curve_t) 0x0017) -#define PSA_ECC_CURVE_SECP384R1 ((psa_ecc_curve_t) 0x0018) -#define PSA_ECC_CURVE_SECP521R1 ((psa_ecc_curve_t) 0x0019) -#define PSA_ECC_CURVE_BRAINPOOL_P256R1 ((psa_ecc_curve_t) 0x001a) -#define PSA_ECC_CURVE_BRAINPOOL_P384R1 ((psa_ecc_curve_t) 0x001b) -#define PSA_ECC_CURVE_BRAINPOOL_P512R1 ((psa_ecc_curve_t) 0x001c) -#define PSA_ECC_CURVE_CURVE25519 ((psa_ecc_curve_t) 0x001d) -#define PSA_ECC_CURVE_CURVE448 ((psa_ecc_curve_t) 0x001e) - -/** 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_SIZE(type) \ - ( \ - (type) == PSA_KEY_TYPE_AES ? 16 : \ - (type) == PSA_KEY_TYPE_DES ? 8 : \ - (type) == PSA_KEY_TYPE_CAMELLIA ? 16 : \ - (type) == PSA_KEY_TYPE_ARC4 ? 1 : \ - 0) - -/** \brief Encoding of a cryptographic algorithm. - * - * 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. - */ -typedef uint32_t psa_algorithm_t; - -#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)0x01000000) -#define PSA_ALG_CATEGORY_MAC ((psa_algorithm_t)0x02000000) -#define PSA_ALG_CATEGORY_CIPHER ((psa_algorithm_t)0x04000000) -#define PSA_ALG_CATEGORY_AEAD ((psa_algorithm_t)0x06000000) -#define PSA_ALG_CATEGORY_SIGN ((psa_algorithm_t)0x10000000) -#define PSA_ALG_CATEGORY_ASYMMETRIC_ENCRYPTION ((psa_algorithm_t)0x12000000) -#define PSA_ALG_CATEGORY_KEY_AGREEMENT ((psa_algorithm_t)0x22000000) -#define PSA_ALG_CATEGORY_KEY_DERIVATION ((psa_algorithm_t)0x30000000) -#define PSA_ALG_CATEGORY_KEY_SELECTION ((psa_algorithm_t)0x31000000) - -#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 a public-key signature algorithm. - * - * \param alg An algorithm identifier (value of type #psa_algorithm_t). - * - * \return 1 if \p alg is a public-key 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 a public-key encryption algorithm. - * - * \param alg An algorithm identifier (value of type #psa_algorithm_t). - * - * \return 1 if \p alg is a public-key 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) - -#define PSA_ALG_KEY_SELECTION_FLAG ((psa_algorithm_t)0x01000000) -/** 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_KEY_SELECTION_FLAG) == \ - 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 selection algorithm. - * - * \param alg An algorithm identifier (value of type #psa_algorithm_t). - * - * \return 1 if \p alg is a key selection 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_SELECTION(alg) \ - (((alg) & PSA_ALG_CATEGORY_MASK) == PSA_ALG_CATEGORY_KEY_SELECTION) - -#define PSA_ALG_HASH_MASK ((psa_algorithm_t)0x000000ff) -#define PSA_ALG_MD2 ((psa_algorithm_t)0x01000001) -#define PSA_ALG_MD4 ((psa_algorithm_t)0x01000002) -#define PSA_ALG_MD5 ((psa_algorithm_t)0x01000003) -#define PSA_ALG_RIPEMD160 ((psa_algorithm_t)0x01000004) -#define PSA_ALG_SHA_1 ((psa_algorithm_t)0x01000005) -/** SHA2-224 */ -#define PSA_ALG_SHA_224 ((psa_algorithm_t)0x01000008) -/** SHA2-256 */ -#define PSA_ALG_SHA_256 ((psa_algorithm_t)0x01000009) -/** SHA2-384 */ -#define PSA_ALG_SHA_384 ((psa_algorithm_t)0x0100000a) -/** SHA2-512 */ -#define PSA_ALG_SHA_512 ((psa_algorithm_t)0x0100000b) -/** SHA2-512/224 */ -#define PSA_ALG_SHA_512_224 ((psa_algorithm_t)0x0100000c) -/** SHA2-512/256 */ -#define PSA_ALG_SHA_512_256 ((psa_algorithm_t)0x0100000d) -/** SHA3-224 */ -#define PSA_ALG_SHA3_224 ((psa_algorithm_t)0x01000010) -/** SHA3-256 */ -#define PSA_ALG_SHA3_256 ((psa_algorithm_t)0x01000011) -/** SHA3-384 */ -#define PSA_ALG_SHA3_384 ((psa_algorithm_t)0x01000012) -/** SHA3-512 */ -#define PSA_ALG_SHA3_512 ((psa_algorithm_t)0x01000013) - -#define PSA_ALG_MAC_SUBCATEGORY_MASK ((psa_algorithm_t)0x00c00000) -#define PSA_ALG_HMAC_BASE ((psa_algorithm_t)0x02800000) -/** 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 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)0x00003f00) -#define PSA_MAC_TRUNCATION_OFFSET 8 - -/** 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 alg A MAC algorithm identifier (value of type - * #psa_algorithm_t such that #PSA_ALG_IS_MAC(\p 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 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(alg, mac_length) \ - (((alg) & ~PSA_ALG_MAC_TRUNCATION_MASK) | \ - ((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 alg A MAC algorithm identifier (value of type - * #psa_algorithm_t such that #PSA_ALG_IS_MAC(\p alg) - * is true). This may be a truncated or untruncated - * MAC algorithm. - * - * \return The corresponding base MAC algorithm. - * \return Unspecified if \p alg is not a supported - * MAC algorithm. - */ -#define PSA_ALG_FULL_LENGTH_MAC(alg) \ - ((alg) & ~PSA_ALG_MAC_TRUNCATION_MASK) - -/** Length to which a MAC algorithm is truncated. - * - * \param alg A MAC algorithm identifier (value of type - * #psa_algorithm_t such that #PSA_ALG_IS_MAC(\p alg) - * is true). - * - * \return Length of the truncated MAC in bytes. - * \return 0 if \p alg is a non-truncated MAC algorithm. - * \return Unspecified if \p alg is not a supported - * MAC algorithm. - */ -#define PSA_MAC_TRUNCATED_LENGTH(alg) \ - (((alg) & PSA_ALG_MAC_TRUNCATION_MASK) >> PSA_MAC_TRUNCATION_OFFSET) - -#define PSA_ALG_CIPHER_MAC_BASE ((psa_algorithm_t)0x02c00000) -#define PSA_ALG_CBC_MAC ((psa_algorithm_t)0x02c00001) -#define PSA_ALG_CMAC ((psa_algorithm_t)0x02c00002) -#define PSA_ALG_GMAC ((psa_algorithm_t)0x02c00003) - -/** 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 ARC4 stream cipher algorithm. - */ -#define PSA_ALG_ARC4 ((psa_algorithm_t)0x04800001) - -/** 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)0x04c00001) - -#define PSA_ALG_CFB ((psa_algorithm_t)0x04c00002) - -#define PSA_ALG_OFB ((psa_algorithm_t)0x04c00003) - -/** 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)0x044000ff) - -/** 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)0x04600100) - -/** 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)0x04600101) - -#define PSA_ALG_CCM ((psa_algorithm_t)0x06001001) -#define PSA_ALG_GCM ((psa_algorithm_t)0x06001002) - -/* In the encoding of a 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)0x00003f00) -#define PSA_AEAD_TAG_LENGTH_OFFSET 8 - -/** 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 alg A AEAD algorithm identifier (value of type - * #psa_algorithm_t such that #PSA_ALG_IS_AEAD(\p 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 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_TAG_LENGTH(alg, tag_length) \ - (((alg) & ~PSA_ALG_AEAD_TAG_LENGTH_MASK) | \ - ((tag_length) << PSA_AEAD_TAG_LENGTH_OFFSET & \ - PSA_ALG_AEAD_TAG_LENGTH_MASK)) - -/** Calculate the corresponding AEAD algorithm with the default tag length. - * - * \param alg An AEAD algorithm (\c PSA_ALG_XXX value such that - * #PSA_ALG_IS_AEAD(\p alg) is true). - * - * \return The corresponding AEAD algorithm with the default tag length - * for that algorithm. - */ -#define PSA_ALG_AEAD_WITH_DEFAULT_TAG_LENGTH(alg) \ - ( \ - PSA__ALG_AEAD_WITH_DEFAULT_TAG_LENGTH__CASE(alg, PSA_ALG_CCM) \ - PSA__ALG_AEAD_WITH_DEFAULT_TAG_LENGTH__CASE(alg, PSA_ALG_GCM) \ - 0) -#define PSA__ALG_AEAD_WITH_DEFAULT_TAG_LENGTH__CASE(alg, ref) \ - PSA_ALG_AEAD_WITH_TAG_LENGTH(alg, 0) == \ - PSA_ALG_AEAD_WITH_TAG_LENGTH(ref, 0) ? \ - ref : - -#define PSA_ALG_RSA_PKCS1V15_SIGN_BASE ((psa_algorithm_t)0x10020000) -/** 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). - * - * \return The corresponding RSA PKCS#1 v1.5 signature algorithm. - * \return Unspecified if \p 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)0x10030000) -/** 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. 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). - * - * \return The corresponding RSA PSS signature algorithm. - * \return Unspecified if \p 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)) -#define PSA_ALG_IS_RSA_PSS(alg) \ - (((alg) & ~PSA_ALG_HASH_MASK) == PSA_ALG_RSA_PSS_BASE) - -#define PSA_ALG_DSA_BASE ((psa_algorithm_t)0x10040000) -/** 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). - * - * \return The corresponding DSA signature algorithm. - * \return Unspecified if \p 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)0x10050000) -#define PSA_ALG_DSA_DETERMINISTIC_FLAG ((psa_algorithm_t)0x00010000) -#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)) - -#define PSA_ALG_ECDSA_BASE ((psa_algorithm_t)0x10060000) -/** 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 concatentation 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). - * - * \return The corresponding ECDSA signature algorithm. - * \return Unspecified if \p 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)0x10070000) -/** 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). - * - * \return The corresponding deterministic ECDSA signature - * algorithm. - * \return Unspecified if \p 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_IS_ECDSA(alg) \ - (((alg) & ~PSA_ALG_HASH_MASK & ~PSA_ALG_DSA_DETERMINISTIC_FLAG) == \ - PSA_ALG_ECDSA_BASE) -#define PSA_ALG_ECDSA_IS_DETERMINISTIC(alg) \ - (((alg) & PSA_ALG_DSA_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)) - -/** 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_RSA_PSS(alg) || PSA_ALG_IS_RSA_PKCS1V15_SIGN(alg) || \ - PSA_ALG_IS_DSA(alg) || PSA_ALG_IS_ECDSA(alg) ? \ - ((alg) & PSA_ALG_HASH_MASK) == 0 ? /*"raw" algorithm*/ 0 : \ - ((alg) & PSA_ALG_HASH_MASK) | PSA_ALG_CATEGORY_HASH : \ - 0) - -/** RSA PKCS#1 v1.5 encryption. - */ -#define PSA_ALG_RSA_PKCS1V15_CRYPT ((psa_algorithm_t)0x12020000) - -#define PSA_ALG_RSA_OAEP_BASE ((psa_algorithm_t)0x12030000) -/** 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 signature algorithm. - * \return Unspecified if \p 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)0x30000100) -/** Macro to build an HKDF algorithm. - * - * For example, `PSA_ALG_HKDF(PSA_ALG_SHA256)` is HKDF 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 HKDF algorithm. - * \return Unspecified if \p 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_TLS12_PRF_BASE ((psa_algorithm_t)0x30000200) -/** 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. - * - * For the application to TLS-1.2, the salt and label arguments passed - * to psa_key_derivation() are what's called 'seed' and 'label' in RFC 5246, - * respectively. For example, for TLS key expansion, the salt is the - * concatenation of ServerHello.Random + ClientHello.Random, - * while the label is "key expansion". +/** \brief Retrieve the lifetime of an open key. * - * For example, `PSA_ALG_TLS12_PRF(PSA_ALG_SHA256)` 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). + * \param handle Handle to query. + * \param[out] lifetime On success, the lifetime value. * - * \return The corresponding TLS-1.2 PRF algorithm. - * \return Unspecified if \p alg is not a supported - * hash algorithm. + * \retval #PSA_SUCCESS + * Success. + * \retval #PSA_ERROR_INVALID_HANDLE + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_TAMPERING_DETECTED + * \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. */ -#define PSA_ALG_TLS12_PRF(hash_alg) \ - (PSA_ALG_TLS12_PRF_BASE | ((hash_alg) & PSA_ALG_HASH_MASK)) +psa_status_t psa_get_key_lifetime(psa_key_handle_t handle, + psa_key_lifetime_t *lifetime); -/** 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)0x30000300) -/** Macro to build a TLS-1.2 PSK-to-MasterSecret algorithm. +/** Allocate a key slot for a transient key, i.e. a key which is only stored + * in volatile memory. * - * 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. + * The allocated key slot and its handle remain valid until the + * application calls psa_close_key() or psa_destroy_key() or until the + * application terminates. * - * For the application to TLS-1.2, the salt passed to psa_key_derivation() - * (and forwarded to the TLS-1.2 PRF) is the concatenation of the - * ClientHello.Random + ServerHello.Random, while the label is "master secret" - * or "extended master secret". + * \param[out] handle On success, a handle to a volatile key slot. * - * For example, `PSA_ALG_TLS12_PSK_TO_MS(PSA_ALG_SHA256)` 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 alg is not a supported - * hash algorithm. + * \retval #PSA_SUCCESS + * Success. The application can now use the value of `*handle` + * to access the newly allocated key slot. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * There was not enough memory, or the maximum number of key slots + * has been reached. */ -#define PSA_ALG_TLS12_PSK_TO_MS(hash_alg) \ - (PSA_ALG_TLS12_PSK_TO_MS_BASE | ((hash_alg) & PSA_ALG_HASH_MASK)) +psa_status_t psa_allocate_key(psa_key_handle_t *handle); -/** Whether the specified algorithm is a TLS-1.2 PSK to MS algorithm. +/** Open a handle to an existing persistent key. * - * \param alg An algorithm identifier (value of type #psa_algorithm_t). + * Open a handle to a key which was previously created with psa_create_key(). * - * \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)) - -#define PSA_ALG_KEY_DERIVATION_MASK ((psa_algorithm_t)0x010fffff) - -/** Use a shared secret as is. + * \param lifetime The lifetime of the key. This designates a storage + * area where the key material is stored. This must not + * be #PSA_KEY_LIFETIME_VOLATILE. + * \param id The persistent identifier of the key. + * \param[out] handle On success, a handle to a key slot which contains + * the data and metadata loaded from the specified + * persistent location. * - * Specify this algorithm as the selection component of a key agreement - * to use the raw result of the key agreement as key material. + * \retval #PSA_SUCCESS + * Success. The application can now use the value of `*handle` + * to access the newly allocated key slot. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_EMPTY_SLOT + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \p lifetime is invalid, for example #PSA_KEY_LIFETIME_VOLATILE. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \p id is invalid for the specified lifetime. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \p lifetime is not supported. + * \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. + */ +psa_status_t psa_open_key(psa_key_lifetime_t lifetime, + psa_key_id_t id, + psa_key_handle_t *handle); + +/** Create a new persistent key slot. + * + * Create a new persistent key slot and return a handle to it. The handle + * remains valid until the application calls psa_close_key() or terminates. + * The application can open the key again with psa_open_key() until it + * removes the key by calling psa_destroy_key(). + * + * \param lifetime The lifetime of the key. This designates a storage + * area where the key material is stored. This must not + * be #PSA_KEY_LIFETIME_VOLATILE. + * \param id The persistent identifier of the key. + * \param[out] handle On success, a handle to the newly created key slot. + * When key material is later created in this key slot, + * it will be saved to the specified persistent location. * - * \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 can however be used as the secret - * input in a key derivation algorithm. + * \retval #PSA_SUCCESS + * Success. The application can now use the value of `*handle` + * to access the newly allocated key slot. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_INSUFFICIENT_STORAGE + * \retval #PSA_ERROR_OCCUPIED_SLOT + * There is already a key with the identifier \p id in the storage + * area designated by \p lifetime. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \p lifetime is invalid, for example #PSA_KEY_LIFETIME_VOLATILE. + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \p id is invalid for the specified lifetime. + * \retval #PSA_ERROR_NOT_SUPPORTED + * \p lifetime is not supported. + * \retval #PSA_ERROR_NOT_PERMITTED + * \p lifetime is valid, but the application does not have the + * permission to create a key there. */ -#define PSA_ALG_SELECT_RAW ((psa_algorithm_t)0x31000001) - -#define PSA_ALG_KEY_AGREEMENT_GET_KDF(alg) \ - (((alg) & PSA_ALG_KEY_DERIVATION_MASK) | PSA_ALG_CATEGORY_KEY_DERIVATION) +psa_status_t psa_create_key(psa_key_lifetime_t lifetime, + psa_key_id_t id, + psa_key_handle_t *handle); -#define PSA_ALG_KEY_AGREEMENT_GET_BASE(alg) \ - ((alg) & ~PSA_ALG_KEY_DERIVATION_MASK) - -#define PSA_ALG_FFDH_BASE ((psa_algorithm_t)0x22100000) -/** The Diffie-Hellman key agreement algorithm. - * - * This algorithm combines the finite-field Diffie-Hellman (DH) key - * agreement, also known as Diffie-Hellman-Merkle (DHM) key agreement, - * to produce a shared secret from a private key and the peer's - * public key, with a key selection or key derivation algorithm to produce - * one or more shared keys and other shared cryptographic material. - * - * The shared secret produced by key agreement and passed as input to the - * derivation or selection algorithm \p kdf_alg is the shared secret - * `g^{ab}` in big-endian format. - * It is `ceiling(m / 8)` bytes long where `m` is the size of the prime `p` - * in bits. - * - * \param kdf_alg A key derivation algorithm (\c PSA_ALG_XXX value such - * that #PSA_ALG_IS_KEY_DERIVATION(\p hash_alg) is true) - * or a key selection algorithm (\c PSA_ALG_XXX value such - * that #PSA_ALG_IS_KEY_SELECTION(\p hash_alg) is true). - * - * \return The Diffie-Hellman algorithm with the specified - * selection or derivation algorithm. - */ -#define PSA_ALG_FFDH(kdf_alg) \ - (PSA_ALG_FFDH_BASE | ((kdf_alg) & PSA_ALG_KEY_DERIVATION_MASK)) -/** Whether the specified algorithm is a finite field Diffie-Hellman algorithm. - * - * This includes every supported key selection or key agreement algorithm - * for the output of the Diffie-Hellman calculation. - * - * \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_BASE) - -#define PSA_ALG_ECDH_BASE ((psa_algorithm_t)0x22200000) -/** The elliptic curve Diffie-Hellman (ECDH) key agreement algorithm. - * - * This algorithm combines the elliptic curve Diffie-Hellman key - * agreement to produce a shared secret from a private key and the peer's - * public key, with a key selection or key derivation algorithm to produce - * one or more shared keys and other shared cryptographic material. - * - * The shared secret produced by key agreement and passed as input to the - * derivation or selection algorithm \p kdf_alg 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. +/** Close a key handle. * - * - For Montgomery curves (curve types `PSA_ECC_CURVE_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_CURVE_SECPXXX` and `PSA_ECC_CURVE_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_CURVE_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}`. - * - * \param kdf_alg A key derivation algorithm (\c PSA_ALG_XXX value such - * that #PSA_ALG_IS_KEY_DERIVATION(\p hash_alg) is true) - * or a selection algorithm (\c PSA_ALG_XXX value such - * that #PSA_ALG_IS_KEY_SELECTION(\p hash_alg) is true). - * - * \return The Diffie-Hellman algorithm with the specified - * selection or derivation algorithm. - */ -#define PSA_ALG_ECDH(kdf_alg) \ - (PSA_ALG_ECDH_BASE | ((kdf_alg) & PSA_ALG_KEY_DERIVATION_MASK)) -/** Whether the specified algorithm is an elliptic curve Diffie-Hellman - * algorithm. + * If the handle designates a volatile key, destroy the key material and + * free all associated resources, just like psa_destroy_key(). * - * This includes every supported key selection or key agreement algorithm - * for the output of the Diffie-Hellman calculation. + * If the handle designates a persistent key, free all resources associated + * with the key in volatile memory. The key slot in persistent storage is + * not affected and can be opened again later with psa_open_key(). * - * \param alg An algorithm identifier (value of type #psa_algorithm_t). + * \param handle The key handle to close. * - * \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. + * \retval #PSA_SUCCESS + * \retval #PSA_ERROR_INVALID_HANDLE + * \retval #PSA_ERROR_COMMUNICATION_FAILURE */ -#define PSA_ALG_IS_ECDH(alg) \ - (PSA_ALG_KEY_AGREEMENT_GET_BASE(alg) == PSA_ALG_ECDH_BASE) +psa_status_t psa_close_key(psa_key_handle_t handle); /**@}*/ -/** \defgroup key_management Key management +/** \defgroup import_export Key import and export * @{ */ @@ -1416,9 +243,10 @@ typedef uint32_t psa_algorithm_t; * minimize the risk that an invalid input is accidentally interpreted * according to a different format. * - * \param key 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 handle Handle to the slot where the key will be stored. + * It must have been obtained by calling + * psa_allocate_key() or psa_create_key() and must + * not contain key material yet. * \param type Key type (a \c PSA_KEY_TYPE_XXX value). On a successful * import, the key slot will contain a key of this type. * \param[in] data Buffer containing the key data. The content of this @@ -1430,6 +258,9 @@ typedef uint32_t psa_algorithm_t; * * \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_INVALID_HANDLE * \retval #PSA_ERROR_NOT_SUPPORTED * The key type or key size is not supported, either by the * implementation in general or in this particular slot. @@ -1449,31 +280,30 @@ typedef uint32_t psa_algorithm_t; * It is implementation-dependent whether a failure to initialize * results in this error code. */ -psa_status_t psa_import_key(psa_key_slot_t key, +psa_status_t psa_import_key(psa_key_handle_t handle, psa_key_type_t type, const uint8_t *data, size_t data_length); /** - * \brief Destroy a key and restore the slot to its default state. + * \brief Destroy a key. * * This function destroys the content of the key slot from both volatile * memory and, if applicable, non-volatile storage. Implementations shall * make a best effort to ensure that any previous content of the slot is * unrecoverable. * - * This function also erases any metadata such as policies. It returns the - * specified slot to its default state. + * This function also erases any metadata such as policies and frees all + * resources associated with the key. * - * \param key The key slot to erase. + * \param handle Handle to the key slot to erase. * * \retval #PSA_SUCCESS * The slot's content, if any, has been erased. * \retval #PSA_ERROR_NOT_PERMITTED * The slot holds content and cannot be erased because it is * read-only, either due to a policy or due to physical restrictions. - * \retval #PSA_ERROR_INVALID_ARGUMENT - * The specified slot number does not designate a valid slot. + * \retval #PSA_ERROR_INVALID_HANDLE * \retval #PSA_ERROR_COMMUNICATION_FAILURE * There was an failure in communication with the cryptoprocessor. * The key material may still be present in the cryptoprocessor. @@ -1491,13 +321,12 @@ psa_status_t psa_import_key(psa_key_slot_t key, * It is implementation-dependent whether a failure to initialize * results in this error code. */ -psa_status_t psa_destroy_key(psa_key_slot_t key); +psa_status_t psa_destroy_key(psa_key_handle_t handle); /** * \brief Get basic metadata about a key. * - * \param key Slot whose content is queried. This must - * be an occupied key slot. + * \param handle Handle to the key slot to query. * \param[out] type On success, the key type (a \c PSA_KEY_TYPE_XXX value). * This may be a null pointer, in which case the key type * is not written. @@ -1506,7 +335,9 @@ psa_status_t psa_destroy_key(psa_key_slot_t key); * is not written. * * \retval #PSA_SUCCESS + * \retval #PSA_ERROR_INVALID_HANDLE * \retval #PSA_ERROR_EMPTY_SLOT + * The handle is to a key slot which does not contain key material yet. * \retval #PSA_ERROR_COMMUNICATION_FAILURE * \retval #PSA_ERROR_HARDWARE_FAILURE * \retval #PSA_ERROR_TAMPERING_DETECTED @@ -1515,7 +346,7 @@ psa_status_t psa_destroy_key(psa_key_slot_t key); * It is implementation-dependent whether a failure to initialize * results in this error code. */ -psa_status_t psa_get_key_information(psa_key_slot_t key, +psa_status_t psa_get_key_information(psa_key_handle_t handle, psa_key_type_t *type, size_t *bits); @@ -1581,14 +412,14 @@ psa_status_t psa_get_key_information(psa_key_slot_t key, * - 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(). * - * \param key Slot whose content is to be exported. This must - * be an occupied key slot. + * \param handle Handle to 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 + * \retval #PSA_ERROR_INVALID_HANDLE * \retval #PSA_ERROR_EMPTY_SLOT * \retval #PSA_ERROR_NOT_PERMITTED * \retval #PSA_ERROR_NOT_SUPPORTED @@ -1606,7 +437,7 @@ psa_status_t psa_get_key_information(psa_key_slot_t key, * It is implementation-dependent whether a failure to initialize * results in this error code. */ -psa_status_t psa_export_key(psa_key_slot_t key, +psa_status_t psa_export_key(psa_key_handle_t handle, uint8_t *data, size_t data_size, size_t *data_length); @@ -1617,8 +448,32 @@ psa_status_t psa_export_key(psa_key_slot_t key, * The output of this function can be passed to psa_import_key() to * create an object that is equivalent to the public key. * - * The format is the DER representation defined by RFC 5280 as - * `SubjectPublicKeyInfo`, with the `subjectPublicKey` format + * 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 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 other public key types, the format is the DER representation defined by + * RFC 5280 as `SubjectPublicKeyInfo`, with the `subjectPublicKey` format * specified below. * ``` * SubjectPublicKeyInfo ::= SEQUENCE { @@ -1628,21 +483,6 @@ psa_status_t psa_export_key(psa_key_slot_t key, * algorithm OBJECT IDENTIFIER, * parameters ANY DEFINED BY algorithm OPTIONAL } * ``` - * - * - For RSA public keys (#PSA_KEY_TYPE_RSA_PUBLIC_KEY), - * the `subjectPublicKey` format is defined by RFC 3279 §2.3.1 as - * `RSAPublicKey`, - * with the OID `rsaEncryption`, - * and with the parameters `NULL`. - * ``` - * pkcs-1 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) - * rsadsi(113549) pkcs(1) 1 } - * rsaEncryption OBJECT IDENTIFIER ::= { pkcs-1 1 } - * - * RSAPublicKey ::= SEQUENCE { - * modulus INTEGER, -- n - * publicExponent INTEGER } -- e - * ``` * - For DSA public keys (#PSA_KEY_TYPE_DSA_PUBLIC_KEY), * the `subjectPublicKey` format is defined by RFC 3279 §2.3.2 as * `DSAPublicKey`, @@ -1658,39 +498,15 @@ psa_status_t psa_export_key(psa_key_slot_t key, * g INTEGER } * DSAPublicKey ::= INTEGER -- public key, Y * ``` - * - For elliptic curve public keys (key types for which - * #PSA_KEY_TYPE_IS_ECC_PUBLIC_KEY is true), - * the `subjectPublicKey` format is defined by RFC 3279 §2.3.5 as - * `ECPoint`, which contains the uncompressed - * representation defined by SEC1 §2.3.3. - * The OID is `id-ecPublicKey`, - * and the parameters must be given as a `namedCurve` OID as specified in - * RFC 5480 §2.1.1.1 or other applicable standards. - * ``` - * ansi-X9-62 OBJECT IDENTIFIER ::= - * { iso(1) member-body(2) us(840) 10045 } - * id-public-key-type OBJECT IDENTIFIER ::= { ansi-X9.62 2 } - * id-ecPublicKey OBJECT IDENTIFIER ::= { id-publicKeyType 1 } - * - * ECPoint ::= ... - * -- first 8 bits: 0x04; - * -- then x_P as a `ceiling(m/8)`-byte string, big endian; - * -- then y_P as a `ceiling(m/8)`-byte string, big endian; - * -- where `m` is the bit size associated with the curve, - * -- i.e. the bit size of `q` for a curve over `F_q`. - * - * EcpkParameters ::= CHOICE { -- other choices are not allowed - * namedCurve OBJECT IDENTIFIER } - * ``` * - * \param key Slot whose content is to be exported. This must - * be an occupied key slot. + * \param handle Handle to 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 + * \retval #PSA_ERROR_INVALID_HANDLE * \retval #PSA_ERROR_EMPTY_SLOT * \retval #PSA_ERROR_INVALID_ARGUMENT * The key is neither a public key nor a key pair. @@ -1709,7 +525,7 @@ psa_status_t psa_export_key(psa_key_slot_t key, * It is implementation-dependent whether a failure to initialize * results in this error code. */ -psa_status_t psa_export_public_key(psa_key_slot_t key, +psa_status_t psa_export_public_key(psa_key_handle_t handle, uint8_t *data, size_t data_size, size_t *data_length); @@ -1720,81 +536,51 @@ psa_status_t psa_export_public_key(psa_key_slot_t key, * @{ */ -/** \brief Encoding of permitted usage on a key. */ -typedef uint32_t psa_key_usage_t; - -/** 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 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 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 ((psa_key_usage_t)0x00000400) - -/** 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 by the key's type and policy. - * - * For a key pair, this concerns the public key. - */ -#define PSA_KEY_USAGE_VERIFY ((psa_key_usage_t)0x00000800) - -/** Whether the key may be used to derive other keys. - */ -#define PSA_KEY_USAGE_DERIVE ((psa_key_usage_t)0x00001000) - /** The type of the key policy data structure. + * + * Before calling any function on a key policy, the application must initialize + * it by any of the following means: + * - Set the structure to all-bits-zero, for example: + * \code + * psa_key_policy_t policy; + * memset(&policy, 0, sizeof(policy)); + * \endcode + * - Initialize the structure to logical zero values, for example: + * \code + * psa_key_policy_t policy = {0}; + * \endcode + * - Initialize the structure to the initializer #PSA_KEY_POLICY_INIT, + * for example: + * \code + * psa_key_policy_t policy = PSA_KEY_POLICY_INIT; + * \endcode + * - Assign the result of the function psa_key_policy_init() + * to the structure, for example: + * \code + * psa_key_policy_t policy; + * policy = psa_key_policy_init(); + * \endcode * * This is an implementation-defined \c struct. Applications should not * make any assumptions about the content of this structure except * as directed by the documentation of a specific implementation. */ typedef struct psa_key_policy_s psa_key_policy_t; -/** \brief Initialize a key policy structure to a default that forbids all - * usage of the key. +/** \def PSA_KEY_POLICY_INIT * - * \param[out] policy The policy object to initialize. + * This macro returns a suitable initializer for a key policy object of type + * #psa_key_policy_t. */ -void psa_key_policy_init(psa_key_policy_t *policy); +#ifdef __DOXYGEN_ONLY__ +/* This is an example definition for documentation purposes. + * Implementations should define a suitable value in `crypto_struct.h`. + */ +#define PSA_KEY_POLICY_INIT {0} +#endif + +/** Return an initial value for a key policy that forbids all usage of the key. + */ +static psa_key_policy_t psa_key_policy_init(void); /** \brief Set the standard fields of a policy structure. * @@ -1802,9 +588,11 @@ void psa_key_policy_init(psa_key_policy_t *policy); * parameters. The values are only checked when applying the policy to * a key slot with psa_set_key_policy(). * - * \param[out] policy The policy object to modify. - * \param usage The permitted uses for the key. - * \param alg The algorithm that the key may be used for. + * \param[in,out] policy The key policy to modify. It must have been + * initialized as per the documentation for + * #psa_key_policy_t. + * \param usage The permitted uses for the key. + * \param alg The algorithm that the key may be used for. */ void psa_key_policy_set_usage(psa_key_policy_t *policy, psa_key_usage_t usage, @@ -1835,10 +623,15 @@ psa_algorithm_t psa_key_policy_get_algorithm(const psa_key_policy_t *policy); * Implementations may set restrictions on supported key policies * depending on the key type and the key slot. * - * \param key The key slot whose policy is to be changed. + * \param handle Handle to the key whose policy is to be changed. * \param[in] policy The policy object to query. * * \retval #PSA_SUCCESS + * Success. + * If the key is persistent, it is implementation-defined whether + * the policy has been saved to persistent storage. Implementations + * may defer saving the policy until the key material is created. + * \retval #PSA_ERROR_INVALID_HANDLE * \retval #PSA_ERROR_OCCUPIED_SLOT * \retval #PSA_ERROR_NOT_SUPPORTED * \retval #PSA_ERROR_INVALID_ARGUMENT @@ -1850,15 +643,16 @@ psa_algorithm_t psa_key_policy_get_algorithm(const psa_key_policy_t *policy); * It is implementation-dependent whether a failure to initialize * results in this error code. */ -psa_status_t psa_set_key_policy(psa_key_slot_t key, +psa_status_t psa_set_key_policy(psa_key_handle_t handle, const psa_key_policy_t *policy); /** \brief Get the usage policy for a key slot. * - * \param key The key slot whose policy is being queried. + * \param handle Handle to the key slot whose policy is being queried. * \param[out] policy On success, the key's policy. * * \retval #PSA_SUCCESS + * \retval #PSA_ERROR_INVALID_HANDLE * \retval #PSA_ERROR_COMMUNICATION_FAILURE * \retval #PSA_ERROR_HARDWARE_FAILURE * \retval #PSA_ERROR_TAMPERING_DETECTED @@ -1867,142 +661,60 @@ psa_status_t psa_set_key_policy(psa_key_slot_t key, * It is implementation-dependent whether a failure to initialize * results in this error code. */ -psa_status_t psa_get_key_policy(psa_key_slot_t key, +psa_status_t psa_get_key_policy(psa_key_handle_t handle, psa_key_policy_t *policy); /**@}*/ -/** \defgroup persistence Key lifetime - * @{ - */ - -/** Encoding of key lifetimes. - */ -typedef uint32_t psa_key_lifetime_t; - -/** A volatile key slot retains its content as long as the application is - * running. It is guaranteed to be erased on a power reset. - */ -#define PSA_KEY_LIFETIME_VOLATILE ((psa_key_lifetime_t)0x00000000) - -/** A persistent key slot retains its content as long as it is not explicitly - * destroyed. - */ -#define PSA_KEY_LIFETIME_PERSISTENT ((psa_key_lifetime_t)0x00000001) - -/** A write-once key slot may not be modified once a key has been set. - * It will retain its content as long as the device remains operational. - */ -#define PSA_KEY_LIFETIME_WRITE_ONCE ((psa_key_lifetime_t)0x7fffffff) - -/** \brief Retrieve the lifetime of a key slot. - * - * The assignment of lifetimes to slots is implementation-dependent. - * - * \param key Slot to query. - * \param[out] lifetime On success, the lifetime value. - * - * \retval #PSA_SUCCESS - * Success. - * \retval #PSA_ERROR_INVALID_ARGUMENT - * The key slot is invalid. - * \retval #PSA_ERROR_COMMUNICATION_FAILURE - * \retval #PSA_ERROR_HARDWARE_FAILURE - * \retval #PSA_ERROR_TAMPERING_DETECTED - * \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_lifetime(psa_key_slot_t key, - psa_key_lifetime_t *lifetime); - -/** \brief Change the lifetime of a key slot. - * - * Whether the lifetime of a key slot can be changed at all, and if so - * whether the lifetime of an occupied key slot can be changed, is - * implementation-dependent. - * - * When creating a persistent key, you must call this function before creating - * the key material with psa_import_key(), psa_generate_key() or - * psa_generator_import_key(). To open an existing persistent key, you must - * call this function with the correct lifetime value before using the slot - * for a cryptographic operation. Once a slot's lifetime has been set, - * the lifetime remains associated with the slot until a subsequent call to - * psa_set_key_lifetime(), until the key is wiped with psa_destroy_key or - * until the application terminates (or disconnects from the cryptography - * service, if the implementation offers such a possibility). - * - * \param key Slot whose lifetime is to be changed. - * \param lifetime The lifetime value to set for the given key slot. - * - * \retval #PSA_SUCCESS - * Success. - * \retval #PSA_ERROR_INVALID_ARGUMENT - * The key slot is invalid, - * or the lifetime value is invalid. - * \retval #PSA_ERROR_NOT_SUPPORTED - * The implementation does not support the specified lifetime value, - * at least for the specified key slot. - * \retval #PSA_ERROR_OCCUPIED_SLOT - * The slot contains a key, and the implementation does not support - * changing the lifetime of an occupied slot. - * \retval #PSA_ERROR_COMMUNICATION_FAILURE - * \retval #PSA_ERROR_HARDWARE_FAILURE - * \retval #PSA_ERROR_TAMPERING_DETECTED - * \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_set_key_lifetime(psa_key_slot_t key, - psa_key_lifetime_t lifetime); - -/**@}*/ - /** \defgroup hash Message digests * @{ */ /** 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 except * as directed by the documentation of a specific implementation. */ typedef struct psa_hash_operation_s psa_hash_operation_t; -/** 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. - * An implementation may return either 0 or the correct size - * for a hash algorithm that it recognizes, but does not support. - */ -#define PSA_HASH_SIZE(alg) \ - ( \ - PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_MD2 ? 16 : \ - PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_MD4 ? 16 : \ - PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_MD5 ? 16 : \ - PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_RIPEMD160 ? 20 : \ - PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA_1 ? 20 : \ - PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA_224 ? 28 : \ - PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA_256 ? 32 : \ - PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA_384 ? 48 : \ - PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA_512 ? 64 : \ - PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA_512_224 ? 28 : \ - PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA_512_256 ? 32 : \ - PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA3_224 ? 28 : \ - PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA3_256 ? 32 : \ - PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA3_384 ? 48 : \ - PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA3_512 ? 64 : \ - 0) +/** \def PSA_HASH_OPERATION_INIT + * + * This macro returns a suitable initializer for a hash operation object + * of type #psa_hash_operation_t. + */ +#ifdef __DOXYGEN_ONLY__ +/* This is an example definition for documentation purposes. + * Implementations should define a suitable value in `crypto_struct.h`. + */ +#define PSA_HASH_OPERATION_INIT {0} +#endif + +/** Return an initial value for a hash operation object. + */ +static psa_hash_operation_t psa_hash_operation_init(void); /** Start a multipart hash operation. * @@ -2010,6 +722,8 @@ typedef struct psa_hash_operation_s psa_hash_operation_t; * 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 @@ -2018,7 +732,7 @@ typedef struct psa_hash_operation_s psa_hash_operation_t; * To compare the hash with an expected value, call psa_hash_verify(). * * The application may call psa_hash_abort() at any time after the operation - * has been initialized with psa_hash_setup(). + * has been initialized. * * After a successful call to psa_hash_setup(), the application must * eventually terminate the operation. The following events terminate an @@ -2026,7 +740,9 @@ typedef struct psa_hash_operation_s psa_hash_operation_t; * - A failed call to psa_hash_update(). * - A call to psa_hash_finish(), psa_hash_verify() or psa_hash_abort(). * - * \param[out] operation The operation object to use. + * \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). * @@ -2171,6 +887,33 @@ psa_status_t psa_hash_verify(psa_hash_operation_t *operation, */ 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 + * \retval #PSA_ERROR_BAD_STATE + * \p source_operation is not an active hash operation. + * \retval #PSA_ERROR_BAD_STATE + * \p target_operation is active. + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_TAMPERING_DETECTED + */ +psa_status_t psa_hash_clone(const psa_hash_operation_t *source_operation, + psa_hash_operation_t *target_operation); + /**@}*/ /** \defgroup MAC Message authentication codes @@ -2178,12 +921,51 @@ psa_status_t psa_hash_abort(psa_hash_operation_t *operation); */ /** 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 except * as directed by the documentation of a specific implementation. */ 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. + */ +#ifdef __DOXYGEN_ONLY__ +/* This is an example definition for documentation purposes. + * Implementations should define a suitable value in `crypto_struct.h`. + */ +#define PSA_MAC_OPERATION_INIT {0} +#endif + +/** Return an initial value for a MAC operation object. + */ +static psa_mac_operation_t psa_mac_operation_init(void); + /** Start a multipart MAC calculation operation. * * This function sets up the calculation of the MAC @@ -2194,6 +976,8 @@ typedef struct psa_mac_operation_s psa_mac_operation_t; * 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. * The key remains associated with the operation even if the content * of the key slot changes. @@ -2204,20 +988,23 @@ typedef struct psa_mac_operation_s psa_mac_operation_t; * calculating the MAC value and retrieve it. * * The application may call psa_mac_abort() at any time after the operation - * has been initialized with psa_mac_sign_setup(). + * 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 failed call to psa_mac_update(). * - A call to psa_mac_sign_finish() or psa_mac_abort(). * - * \param[out] operation The operation object to use. - * \param key Slot containing the key to use for the operation. + * \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 handle Handle to the key to use for the operation. * \param alg The MAC algorithm to compute (\c PSA_ALG_XXX value * such that #PSA_ALG_IS_MAC(alg) is true). * * \retval #PSA_SUCCESS * Success. + * \retval #PSA_ERROR_INVALID_HANDLE * \retval #PSA_ERROR_EMPTY_SLOT * \retval #PSA_ERROR_NOT_PERMITTED * \retval #PSA_ERROR_INVALID_ARGUMENT @@ -2234,7 +1021,7 @@ typedef struct psa_mac_operation_s psa_mac_operation_t; * results in this error code. */ psa_status_t psa_mac_sign_setup(psa_mac_operation_t *operation, - psa_key_slot_t key, + psa_key_handle_t handle, psa_algorithm_t alg); /** Start a multipart MAC verification operation. @@ -2245,6 +1032,8 @@ psa_status_t psa_mac_sign_setup(psa_mac_operation_t *operation, * 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. * The key remains associated with the operation even if the content * of the key slot changes. @@ -2256,20 +1045,23 @@ psa_status_t psa_mac_sign_setup(psa_mac_operation_t *operation, * the expected value. * * The application may call psa_mac_abort() at any time after the operation - * has been initialized with psa_mac_verify_setup(). + * 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 failed call to psa_mac_update(). * - A call to psa_mac_verify_finish() or psa_mac_abort(). * - * \param[out] operation The operation object to use. - * \param key Slot containing the key to use for the operation. + * \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 handle Handle to the key to use for the operation. * \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 * \retval #PSA_ERROR_EMPTY_SLOT * \retval #PSA_ERROR_NOT_PERMITTED * \retval #PSA_ERROR_INVALID_ARGUMENT @@ -2286,7 +1078,7 @@ psa_status_t psa_mac_sign_setup(psa_mac_operation_t *operation, * results in this error code. */ psa_status_t psa_mac_verify_setup(psa_mac_operation_t *operation, - psa_key_slot_t key, + psa_key_handle_t handle, psa_algorithm_t alg); /** Add a message fragment to a multipart MAC operation. @@ -2429,18 +1221,60 @@ psa_status_t psa_mac_abort(psa_mac_operation_t *operation); */ /** 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 except * as directed by the documentation of a specific implementation. */ 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. + */ +#ifdef __DOXYGEN_ONLY__ +/* This is an example definition for documentation purposes. + * Implementations should define a suitable value in `crypto_struct.h`. + */ +#define PSA_CIPHER_OPERATION_INIT {0} +#endif + +/** 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. * The key remains associated with the operation even if the content * of the key slot changes. @@ -2453,7 +1287,7 @@ typedef struct psa_cipher_operation_s psa_cipher_operation_t; * -# Call psa_cipher_finish(). * * The application may call psa_cipher_abort() at any time after the operation - * has been initialized with psa_cipher_encrypt_setup(). + * has been initialized. * * After a successful call to psa_cipher_encrypt_setup(), the application must * eventually terminate the operation. The following events terminate an @@ -2462,14 +1296,17 @@ typedef struct psa_cipher_operation_s psa_cipher_operation_t; * or psa_cipher_update(). * - A call to psa_cipher_finish() or psa_cipher_abort(). * - * \param[out] operation The operation object to use. - * \param key Slot containing the key to use for the operation. + * \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 handle Handle to the key to use for the operation. * \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 * \retval #PSA_ERROR_EMPTY_SLOT * \retval #PSA_ERROR_NOT_PERMITTED * \retval #PSA_ERROR_INVALID_ARGUMENT @@ -2486,7 +1323,7 @@ typedef struct psa_cipher_operation_s psa_cipher_operation_t; * results in this error code. */ psa_status_t psa_cipher_encrypt_setup(psa_cipher_operation_t *operation, - psa_key_slot_t key, + psa_key_handle_t handle, psa_algorithm_t alg); /** Set the key for a multipart symmetric decryption operation. @@ -2495,6 +1332,9 @@ psa_status_t psa_cipher_encrypt_setup(psa_cipher_operation_t *operation, * 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. * The key remains associated with the operation even if the content * of the key slot changes. @@ -2507,7 +1347,7 @@ psa_status_t psa_cipher_encrypt_setup(psa_cipher_operation_t *operation, * -# Call psa_cipher_finish(). * * The application may call psa_cipher_abort() at any time after the operation - * has been initialized with psa_cipher_decrypt_setup(). + * has been initialized. * * After a successful call to psa_cipher_decrypt_setup(), the application must * eventually terminate the operation. The following events terminate an @@ -2515,14 +1355,17 @@ psa_status_t psa_cipher_encrypt_setup(psa_cipher_operation_t *operation, * - A failed call to psa_cipher_update(). * - A call to psa_cipher_finish() or psa_cipher_abort(). * - * \param[out] operation The operation object to use. - * \param key Slot containing the key to use for the operation. + * \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 handle Handle to the key to use for the operation. * \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 * \retval #PSA_ERROR_EMPTY_SLOT * \retval #PSA_ERROR_NOT_PERMITTED * \retval #PSA_ERROR_INVALID_ARGUMENT @@ -2539,7 +1382,7 @@ psa_status_t psa_cipher_encrypt_setup(psa_cipher_operation_t *operation, * results in this error code. */ psa_status_t psa_cipher_decrypt_setup(psa_cipher_operation_t *operation, - psa_key_slot_t key, + psa_key_handle_t handle, psa_algorithm_t alg); /** Generate an IV for a symmetric encryption operation. @@ -2720,29 +1563,9 @@ psa_status_t psa_cipher_abort(psa_cipher_operation_t *operation); * @{ */ -/** The tag size for an AEAD algorithm, in bytes. - * - * \param alg An AEAD algorithm - * (\c PSA_ALG_XXX value such that - * #PSA_ALG_IS_AEAD(\p alg) is true). - * - * \return The tag size for the specified algorithm. - * If the AEAD algorithm does not have an identified - * tag that can be distinguished from the rest of - * the ciphertext, return 0. - * If the AEAD algorithm is not recognized, return 0. - * An implementation may return either 0 or a - * correct size for an AEAD algorithm that it - * recognizes, but does not support. - */ -#define PSA_AEAD_TAG_LENGTH(alg) \ - (PSA_ALG_IS_AEAD(alg) ? \ - (((alg) & PSA_ALG_AEAD_TAG_LENGTH_MASK) >> PSA_AEAD_TAG_LENGTH_OFFSET) : \ - 0) - /** Process an authenticated encryption operation. * - * \param key Slot containing the key to use. + * \param handle Handle to the key to use for the operation. * \param alg The AEAD algorithm to compute * (\c PSA_ALG_XXX value such that * #PSA_ALG_IS_AEAD(\p alg) is true). @@ -2770,6 +1593,7 @@ psa_status_t psa_cipher_abort(psa_cipher_operation_t *operation); * * \retval #PSA_SUCCESS * Success. + * \retval #PSA_ERROR_INVALID_HANDLE * \retval #PSA_ERROR_EMPTY_SLOT * \retval #PSA_ERROR_NOT_PERMITTED * \retval #PSA_ERROR_INVALID_ARGUMENT @@ -2785,7 +1609,7 @@ psa_status_t psa_cipher_abort(psa_cipher_operation_t *operation); * It is implementation-dependent whether a failure to initialize * results in this error code. */ -psa_status_t psa_aead_encrypt(psa_key_slot_t key, +psa_status_t psa_aead_encrypt(psa_key_handle_t handle, psa_algorithm_t alg, const uint8_t *nonce, size_t nonce_length, @@ -2799,7 +1623,7 @@ psa_status_t psa_aead_encrypt(psa_key_slot_t key, /** Process an authenticated decryption operation. * - * \param key Slot containing the key to use. + * \param handle Handle to the key to use for the operation. * \param alg The AEAD algorithm to compute * (\c PSA_ALG_XXX value such that * #PSA_ALG_IS_AEAD(\p alg) is true). @@ -2825,6 +1649,7 @@ psa_status_t psa_aead_encrypt(psa_key_slot_t key, * * \retval #PSA_SUCCESS * Success. + * \retval #PSA_ERROR_INVALID_HANDLE * \retval #PSA_ERROR_EMPTY_SLOT * \retval #PSA_ERROR_INVALID_SIGNATURE * The ciphertext is not authentic. @@ -2842,7 +1667,7 @@ psa_status_t psa_aead_encrypt(psa_key_slot_t key, * It is implementation-dependent whether a failure to initialize * results in this error code. */ -psa_status_t psa_aead_decrypt(psa_key_slot_t key, +psa_status_t psa_aead_decrypt(psa_key_handle_t handle, psa_algorithm_t alg, const uint8_t *nonce, size_t nonce_length, @@ -2860,17 +1685,6 @@ psa_status_t psa_aead_decrypt(psa_key_slot_t key, * @{ */ -/** - * \brief ECDSA signature size for a given curve bit size - * - * \param curve_bits Curve size in bits. - * \return Signature size in bytes. - * - * \note This macro returns a compile-time constant if its argument is one. - */ -#define PSA_ECDSA_SIGNATURE_SIZE(curve_bits) \ - (PSA_BITS_TO_BYTES(curve_bits) * 2) - /** * \brief Sign a hash or short message with a private key. * @@ -2880,7 +1694,8 @@ psa_status_t psa_aead_decrypt(psa_key_slot_t key, * parameter to this function. You can use #PSA_ALG_SIGN_GET_HASH(\p alg) * to determine the hash algorithm to use. * - * \param key Key slot containing an asymmetric key pair. + * \param handle Handle to the key to use for the operation. + * It must be an asymmetric key pair. * \param alg A signature algorithm that is compatible with * the type of \p key. * \param[in] hash The hash or message to sign. @@ -2909,7 +1724,7 @@ psa_status_t psa_aead_decrypt(psa_key_slot_t key, * It is implementation-dependent whether a failure to initialize * results in this error code. */ -psa_status_t psa_asymmetric_sign(psa_key_slot_t key, +psa_status_t psa_asymmetric_sign(psa_key_handle_t handle, psa_algorithm_t alg, const uint8_t *hash, size_t hash_length, @@ -2926,8 +1741,8 @@ psa_status_t psa_asymmetric_sign(psa_key_slot_t key, * parameter to this function. You can use #PSA_ALG_SIGN_GET_HASH(\p alg) * to determine the hash algorithm to use. * - * \param key Key slot containing a public key or an - * asymmetric key pair. + * \param handle Handle to the key to use for the operation. + * It must be a public key or an asymmetric key pair. * \param alg A signature algorithm that is compatible with * the type of \p key. * \param[in] hash The hash or message whose signature is to be @@ -2952,23 +1767,19 @@ psa_status_t psa_asymmetric_sign(psa_key_slot_t key, * It is implementation-dependent whether a failure to initialize * results in this error code. */ -psa_status_t psa_asymmetric_verify(psa_key_slot_t key, +psa_status_t psa_asymmetric_verify(psa_key_handle_t handle, psa_algorithm_t alg, const uint8_t *hash, size_t hash_length, const uint8_t *signature, size_t signature_length); -#define PSA_RSA_MINIMUM_PADDING_SIZE(alg) \ - (PSA_ALG_IS_RSA_OAEP(alg) ? \ - 2 * PSA_HASH_FINAL_SIZE(PSA_ALG_RSA_OAEP_GET_HASH(alg)) + 1 : \ - 11 /*PKCS#1v1.5*/) - /** * \brief Encrypt a short message with a public key. * - * \param key Key slot containing a public key or an - * asymmetric key pair. + * \param handle Handle to the key to use for the operation. + * It must be a public key or an asymmetric + * key pair. * \param alg An asymmetric encryption algorithm that is * compatible with the type of \p key. * \param[in] input The message to encrypt. @@ -3010,7 +1821,7 @@ psa_status_t psa_asymmetric_verify(psa_key_slot_t key, * It is implementation-dependent whether a failure to initialize * results in this error code. */ -psa_status_t psa_asymmetric_encrypt(psa_key_slot_t key, +psa_status_t psa_asymmetric_encrypt(psa_key_handle_t handle, psa_algorithm_t alg, const uint8_t *input, size_t input_length, @@ -3023,7 +1834,8 @@ psa_status_t psa_asymmetric_encrypt(psa_key_slot_t key, /** * \brief Decrypt a short message with a private key. * - * \param key Key slot containing an asymmetric key pair. + * \param handle Handle to the key to use for the operation. + * It must be an asymmetric key pair. * \param alg An asymmetric encryption algorithm that is * compatible with the type of \p key. * \param[in] input The message to decrypt. @@ -3066,7 +1878,7 @@ psa_status_t psa_asymmetric_encrypt(psa_key_slot_t key, * It is implementation-dependent whether a failure to initialize * results in this error code. */ -psa_status_t psa_asymmetric_decrypt(psa_key_slot_t key, +psa_status_t psa_asymmetric_decrypt(psa_key_handle_t handle, psa_algorithm_t alg, const uint8_t *input, size_t input_length, @@ -3137,9 +1949,9 @@ static psa_crypto_generator_t psa_crypto_generator_init(void); * \param[in] generator The generator to query. * \param[out] capacity On success, the capacity of the generator. * - * \retval PSA_SUCCESS - * \retval PSA_ERROR_BAD_STATE - * \retval PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_SUCCESS + * \retval #PSA_ERROR_BAD_STATE + * \retval #PSA_ERROR_COMMUNICATION_FAILURE */ psa_status_t psa_get_generator_capacity(const psa_crypto_generator_t *generator, size_t *capacity); @@ -3155,19 +1967,19 @@ psa_status_t psa_get_generator_capacity(const psa_crypto_generator_t *generator, * written. * \param output_length Number of bytes to output. * - * \retval PSA_SUCCESS - * \retval PSA_ERROR_INSUFFICIENT_CAPACITY + * \retval #PSA_SUCCESS + * \retval #PSA_ERROR_INSUFFICIENT_CAPACITY * There were fewer than \p output_length bytes * in the generator. Note that in this case, no * output is written to the output buffer. * The generator's capacity is set to 0, thus * subsequent calls to this function will not * succeed, even with a smaller output buffer. - * \retval PSA_ERROR_BAD_STATE - * \retval PSA_ERROR_INSUFFICIENT_MEMORY - * \retval PSA_ERROR_COMMUNICATION_FAILURE - * \retval PSA_ERROR_HARDWARE_FAILURE - * \retval PSA_ERROR_TAMPERING_DETECTED + * \retval #PSA_ERROR_BAD_STATE + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_TAMPERING_DETECTED */ psa_status_t psa_generator_read(psa_crypto_generator_t *generator, uint8_t *output, @@ -3185,42 +1997,44 @@ psa_status_t psa_generator_read(psa_crypto_generator_t *generator, * if the implementation provides an isolation boundary then * the key material is not exposed outside the isolation boundary. * - * \param key 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 handle Handle to the slot where the key will be stored. + * It must have been obtained by calling + * psa_allocate_key() or psa_create_key() and must + * not contain key material yet. * \param type Key type (a \c PSA_KEY_TYPE_XXX value). * This must be a symmetric key type. * \param bits Key size in bits. * \param[in,out] generator The generator object to read from. * - * \retval PSA_SUCCESS + * \retval #PSA_SUCCESS * Success. - * \retval PSA_ERROR_INSUFFICIENT_CAPACITY + * If the key is persistent, the key material and the key's metadata + * have been saved to persistent storage. + * \retval #PSA_ERROR_INSUFFICIENT_CAPACITY * There were fewer than \p output_length bytes * in the generator. Note that in this case, no * output is written to the output buffer. * The generator'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 + * \retval #PSA_ERROR_NOT_SUPPORTED * The key type or key size is not supported, either by the * implementation in general or in this particular slot. - * \retval PSA_ERROR_BAD_STATE - * \retval PSA_ERROR_INVALID_ARGUMENT - * The key slot is invalid. - * \retval PSA_ERROR_OCCUPIED_SLOT + * \retval #PSA_ERROR_BAD_STATE + * \retval #PSA_ERROR_INVALID_HANDLE + * \retval #PSA_ERROR_OCCUPIED_SLOT * There is already a key in the specified slot. - * \retval PSA_ERROR_INSUFFICIENT_MEMORY - * \retval PSA_ERROR_INSUFFICIENT_STORAGE - * \retval PSA_ERROR_COMMUNICATION_FAILURE - * \retval PSA_ERROR_HARDWARE_FAILURE - * \retval PSA_ERROR_TAMPERING_DETECTED + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_INSUFFICIENT_STORAGE + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_TAMPERING_DETECTED * \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_generator_import_key(psa_key_slot_t key, +psa_status_t psa_generator_import_key(psa_key_handle_t handle, psa_key_type_t type, size_t bits, psa_crypto_generator_t *generator); @@ -3241,11 +2055,11 @@ psa_status_t psa_generator_import_key(psa_key_slot_t key, * * \param[in,out] generator The generator to abort. * - * \retval PSA_SUCCESS - * \retval PSA_ERROR_BAD_STATE - * \retval PSA_ERROR_COMMUNICATION_FAILURE - * \retval PSA_ERROR_HARDWARE_FAILURE - * \retval PSA_ERROR_TAMPERING_DETECTED + * \retval #PSA_SUCCESS + * \retval #PSA_ERROR_BAD_STATE + * \retval #PSA_ERROR_COMMUNICATION_FAILURE + * \retval #PSA_ERROR_HARDWARE_FAILURE + * \retval #PSA_ERROR_TAMPERING_DETECTED */ psa_status_t psa_generator_abort(psa_crypto_generator_t *generator); @@ -3275,12 +2089,10 @@ psa_status_t psa_generator_abort(psa_crypto_generator_t *generator); * - For HKDF (#PSA_ALG_HKDF), \p salt is the salt used in the "extract" step * and \p label is the info string used in the "expand" step. * - * \param[in,out] generator The generator object to set up. It must - * have been initialized to all-bits-zero, - * a logical zero (`{0}`), - * \c PSA_CRYPTO_GENERATOR_INIT or - * psa_crypto_generator_init(). - * \param key Slot containing the secret key to use. + * \param[in,out] generator The generator object to set up. It must have + * been initialized as per the documentation for + * #psa_crypto_generator_t and not yet in use. + * \param handle Handle to the secret key. * \param alg The key derivation algorithm to compute * (\c PSA_ALG_XXX value such that * #PSA_ALG_IS_KEY_DERIVATION(\p alg) is true). @@ -3293,6 +2105,7 @@ psa_status_t psa_generator_abort(psa_crypto_generator_t *generator); * * \retval #PSA_SUCCESS * Success. + * \retval #PSA_ERROR_INVALID_HANDLE * \retval #PSA_ERROR_EMPTY_SLOT * \retval #PSA_ERROR_NOT_PERMITTED * \retval #PSA_ERROR_INVALID_ARGUMENT @@ -3310,7 +2123,7 @@ psa_status_t psa_generator_abort(psa_crypto_generator_t *generator); * results in this error code. */ psa_status_t psa_key_derivation(psa_crypto_generator_t *generator, - psa_key_slot_t key, + psa_key_handle_t handle, psa_algorithm_t alg, const uint8_t *salt, size_t salt_length, @@ -3328,24 +2141,32 @@ psa_status_t psa_key_derivation(psa_crypto_generator_t *generator, * The resulting generator always has the maximum capacity permitted by * the algorithm. * - * \param[in,out] generator The generator object to set up. It must - * have been initialized to all-bits-zero, - * a logical zero (`{0}`), - * \c PSA_CRYPTO_GENERATOR_INIT or - * psa_crypto_generator_init(). - * \param private_key Slot containing the private key to use. - * \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 alg The key agreement algorithm to compute - * (\c PSA_ALG_XXX value such that - * #PSA_ALG_IS_KEY_AGREEMENT(\p alg) is true). + * \param[in,out] generator The generator object to set up. It must have been + * initialized as per the documentation for + * #psa_crypto_generator_t and not yet in use. + * \param private_key Handle to the private key to use. + * \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 + * \p private_key. That is, this function performs the + * equivalent of + * `psa_import_key(internal_public_key_handle, + * PSA_KEY_TYPE_PUBLIC_KEY_OF_KEYPAIR(private_key_type), + * peer_key, peer_key_length)` where + * `private_key_type` is the type of \p private_key. + * For example, for EC keys, this means that \p + * peer_key is interpreted as a point on the curve + * that the private key is associated with. 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 alg The key agreement algorithm to compute + * (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_KEY_AGREEMENT(\p alg) is true). * * \retval #PSA_SUCCESS * Success. + * \retval #PSA_ERROR_INVALID_HANDLE * \retval #PSA_ERROR_EMPTY_SLOT * \retval #PSA_ERROR_NOT_PERMITTED * \retval #PSA_ERROR_INVALID_ARGUMENT @@ -3360,7 +2181,7 @@ psa_status_t psa_key_derivation(psa_crypto_generator_t *generator, * \retval #PSA_ERROR_TAMPERING_DETECTED */ psa_status_t psa_key_agreement(psa_crypto_generator_t *generator, - psa_key_slot_t private_key, + psa_key_handle_t private_key, const uint8_t *peer_key, size_t peer_key_length, psa_algorithm_t alg); @@ -3409,9 +2230,10 @@ typedef struct { /** * \brief Generate a key or key pair. * - * \param key 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 handle Handle to the slot where the key will be stored. + * It must have been obtained by calling + * psa_allocate_key() or psa_create_key() and must + * not contain key material yet. * \param type Key type (a \c PSA_KEY_TYPE_XXX value). * \param bits Key size in bits. * \param[in] extra Extra parameters for key generation. The @@ -3440,6 +2262,12 @@ typedef struct { * \c NULL then \p extra_size must be zero. * * \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_INVALID_HANDLE + * \retval #PSA_ERROR_OCCUPIED_SLOT + * There is already a key in the specified slot. * \retval #PSA_ERROR_NOT_SUPPORTED * \retval #PSA_ERROR_INVALID_ARGUMENT * \retval #PSA_ERROR_INSUFFICIENT_MEMORY @@ -3452,7 +2280,7 @@ typedef struct { * It is implementation-dependent whether a failure to initialize * results in this error code. */ -psa_status_t psa_generate_key(psa_key_slot_t key, +psa_status_t psa_generate_key(psa_key_handle_t handle, psa_key_type_t type, size_t bits, const void *extra, diff --git a/features/mbedtls/mbed-crypto/inc/psa/crypto_accel_driver.h b/features/mbedtls/mbed-crypto/inc/psa/crypto_accel_driver.h new file mode 100644 index 00000000000..b752fed8819 --- /dev/null +++ b/features/mbedtls/mbed-crypto/inc/psa/crypto_accel_driver.h @@ -0,0 +1,796 @@ +/** + * \file psa/crypto_accel_driver.h + * \brief PSA cryptography accelerator driver module + * + * This header declares types and function signatures for cryptography + * drivers that access key material directly. This is meant for + * on-chip cryptography accelerators. + * + * 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 (C) 2018, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef PSA_CRYPTO_ACCEL_DRIVER_H +#define PSA_CRYPTO_ACCEL_DRIVER_H + +#include "crypto_driver_common.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** \defgroup driver_digest Message Digests + * + * Generation and authentication of Message Digests (aka hashes) must be done + * in parts using the following sequence: + * - `psa_drv_hash_setup_t` + * - `psa_drv_hash_update_t` + * - ... + * - `psa_drv_hash_finish_t` + * + * If a previously started Message Digest operation needs to be terminated + * before the `psa_drv_hash_finish_t` operation is complete, it should be aborted + * by the `psa_drv_hash_abort_t`. Failure to do so may result in allocated + * resources not being freed or in other undefined behavior. + */ +/**@{*/ + +/** \brief The hardware-specific hash context structure + * + * The contents of this structure are implementation dependent and are + * therefore not described here + */ +typedef struct psa_drv_hash_context_s psa_drv_hash_context_t; + +/** \brief The function prototype for the start operation of a hash (message + * digest) operation + * + * Functions that implement the prototype should be named in the following + * convention: + * ~~~~~~~~~~~~~{.c} + * psa_drv_hash__setup + * ~~~~~~~~~~~~~ + * Where `ALGO` is the name of the underlying hash function + * + * \param[in,out] p_context A structure that will contain the + * hardware-specific hash context + * + * \retval PSA_SUCCESS Success. + */ +typedef psa_status_t (*psa_drv_hash_setup_t)(psa_drv_hash_context_t *p_context); + +/** \brief The function prototype for the update operation of a hash (message + * digest) operation + * + * Functions that implement the prototype should be named in the following + * convention: + * ~~~~~~~~~~~~~{.c} + * psa_drv_hash__update + * ~~~~~~~~~~~~~ + * Where `ALGO` is the name of the underlying algorithm + * + * \param[in,out] p_context A hardware-specific structure for the + * previously-established hash operation to be + * continued + * \param[in] p_input A buffer containing the message to be appended + * to the hash operation + * \param[in] input_length The size in bytes of the input message buffer + */ +typedef psa_status_t (*psa_drv_hash_update_t)(psa_drv_hash_context_t *p_context, + const uint8_t *p_input, + size_t input_length); + +/** \brief The prototype for the finish operation of a hash (message digest) + * operation + * + * Functions that implement the prototype should be named in the following + * convention: + * ~~~~~~~~~~~~~{.c} + * psa_drv_hash__finish + * ~~~~~~~~~~~~~ + * Where `ALGO` is the name of the underlying algorithm + * + * \param[in,out] p_context A hardware-specific structure for the + * previously started hash operation to be + * fiinished + * \param[out] p_output A buffer where the generated digest will be + * placed + * \param[in] output_size The size in bytes of the buffer that has been + * allocated for the `p_output` buffer + * \param[out] p_output_length The number of bytes placed in `p_output` after + * success + * + * \retval PSA_SUCCESS + * Success. + */ +typedef psa_status_t (*psa_drv_hash_finish_t)(psa_drv_hash_context_t *p_context, + uint8_t *p_output, + size_t output_size, + size_t *p_output_length); + +/** \brief The function prototype for the abort operation of a hash (message + * digest) operation + * + * Functions that implement the prototype should be named in the following + * convention: + * ~~~~~~~~~~~~~{.c} + * psa_drv_hash__abort + * ~~~~~~~~~~~~~ + * Where `ALGO` is the name of the underlying algorithm + * + * \param[in,out] p_context A hardware-specific structure for the previously + * started hash operation to be aborted + */ +typedef void (*psa_drv_hash_abort_t)(psa_drv_hash_context_t *p_context); + +/**@}*/ + +/** \defgroup transparent_mac Transparent Message Authentication Code + * Generation and authentication of Message Authentication Codes (MACs) using + * transparent keys can be done either as a single function call (via the + * `psa_drv_mac_transparent_generate_t` or `psa_drv_mac_transparent_verify_t` + * functions), or in parts using the following sequence: + * - `psa_drv_mac_transparent_setup_t` + * - `psa_drv_mac_transparent_update_t` + * - `psa_drv_mac_transparent_update_t` + * - ... + * - `psa_drv_mac_transparent_finish_t` or `psa_drv_mac_transparent_finish_verify_t` + * + * If a previously started Transparent MAC operation needs to be terminated, it + * should be done so by the `psa_drv_mac_transparent_abort_t`. Failure to do so may + * result in allocated resources not being freed or in other undefined + * behavior. + * + */ +/**@{*/ + +/** \brief The hardware-specific transparent-key MAC context structure + * + * The contents of this structure are implementation dependent and are + * therefore not described here. + */ +typedef struct psa_drv_mac_transparent_context_s psa_drv_mac_transparent_context_t; + +/** \brief The function prototype for the setup operation of a + * transparent-key MAC operation + * + * Functions that implement the prototype should be named in the following + * convention: + * ~~~~~~~~~~~~~{.c} + * psa_drv_mac_transparent___setup + * ~~~~~~~~~~~~~ + * Where `ALGO` is the name of the underlying primitive, and `MAC_VARIANT` + * is the specific variant of a MAC operation (such as HMAC or CMAC) + * + * \param[in,out] p_context A structure that will contain the + * hardware-specific MAC context + * \param[in] p_key A buffer containing the cleartext key material + * to be used in the operation + * \param[in] key_length The size in bytes of the key material + * + * \retval PSA_SUCCESS + * Success. + */ +typedef psa_status_t (*psa_drv_mac_transparent_setup_t)(psa_drv_mac_transparent_context_t *p_context, + const uint8_t *p_key, + size_t key_length); + +/** \brief The function prototype for the update operation of a + * transparent-key MAC operation + * + * Functions that implement the prototype should be named in the following + * convention: + * ~~~~~~~~~~~~~{.c} + * psa_drv_mac_transparent___update + * ~~~~~~~~~~~~~ + * Where `ALGO` is the name of the underlying algorithm, and `MAC_VARIANT` + * is the specific variant of a MAC operation (such as HMAC or CMAC) + * + * \param[in,out] p_context A hardware-specific structure for the + * previously-established MAC operation to be + * continued + * \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_mac_transparent_update_t)(psa_drv_mac_transparent_context_t *p_context, + const uint8_t *p_input, + size_t input_length); + +/** \brief The function prototype for the finish operation of a + * transparent-key MAC operation + * + * Functions that implement the prototype should be named in the following + * convention: + * ~~~~~~~~~~~~~{.c} + * psa_drv_mac_transparent___finish + * ~~~~~~~~~~~~~ + * Where `ALGO` is the name of the underlying algorithm, and `MAC_VARIANT` is + * the specific variant of a MAC operation (such as HMAC or CMAC) + * + * \param[in,out] p_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_length The size in bytes of the buffer that has been + * allocated for the `p_mac` buffer + * + * \retval PSA_SUCCESS + * Success. + */ +typedef psa_status_t (*psa_drv_mac_transparent_finish_t)(psa_drv_mac_transparent_context_t *p_context, + uint8_t *p_mac, + size_t mac_length); + +/** \brief The function prototype for the finish and verify operation of a + * transparent-key MAC operation + * + * Functions that implement the prototype should be named in the following + * convention: + * ~~~~~~~~~~~~~{.c} + * psa_drv_mac_transparent___finish_verify + * ~~~~~~~~~~~~~ + * Where `ALGO` is the name of the underlying algorithm, and `MAC_VARIANT` is + * the specific variant of a MAC operation (such as HMAC or CMAC) + * + * \param[in,out] p_context A hardware-specific structure for the + * previously started MAC operation to be + * verified and finished + * \param[in] p_mac A buffer containing the MAC that will be used + * for verification + * \param[in] mac_length The size in bytes of the data in the `p_mac` + * buffer + * + * \retval PSA_SUCCESS + * The operation completed successfully and the comparison matched + */ +typedef psa_status_t (*psa_drv_mac_transparent_finish_verify_t)(psa_drv_mac_transparent_context_t *p_context, + const uint8_t *p_mac, + size_t mac_length); + +/** \brief The function prototype for the abort operation for a previously + * started transparent-key MAC operation + * + * Functions that implement the prototype should be named in the following + * convention: + * ~~~~~~~~~~~~~{.c} + * psa_drv_mac_transparent___abort + * ~~~~~~~~~~~~~ + * Where `ALGO` is the name of the underlying algorithm, and `MAC_VARIANT` is + * the specific variant of a MAC operation (such as HMAC or CMAC) + * + * \param[in,out] p_context A hardware-specific structure for the + * previously started MAC operation to be + * aborted + * + */ +typedef psa_status_t (*psa_drv_mac_transparent_abort_t)(psa_drv_mac_transparent_context_t *p_context); + +/** \brief The function prototype for a one-shot operation of a transparent-key + * MAC operation + * + * Functions that implement the prototype should be named in the following + * convention: + * ~~~~~~~~~~~~~{.c} + * psa_drv_mac_transparent__ + * ~~~~~~~~~~~~~ + * Where `ALGO` is the name of the underlying algorithm, and `MAC_VARIANT` is + * the specific variant of a MAC operation (such as HMAC or CMAC) + * + * \param[in] p_input A buffer containing the data to be MACed + * \param[in] input_length The length in bytes of the `p_input` data + * \param[in] p_key A buffer containing the key material to be used + * for the MAC operation + * \param[in] key_length The length in bytes of the `p_key` data + * \param[in] alg The algorithm to be performed + * \param[out] p_mac The buffer where the resulting MAC will be placed + * upon success + * \param[in] mac_length The length in bytes of the `p_mac` buffer + */ +typedef psa_status_t (*psa_drv_mac_transparent_t)(const uint8_t *p_input, + size_t input_length, + const uint8_t *p_key, + size_t key_length, + psa_algorithm_t alg, + uint8_t *p_mac, + size_t mac_length); + +/** \brief The function prototype for a one-shot operation of a transparent-key + * MAC Verify operation + * + * Functions that implement the prototype should be named in the following + * convention: + * ~~~~~~~~~~~~~{.c} + * psa_drv_mac_transparent___verify + * ~~~~~~~~~~~~~ + * Where `ALGO` is the name of the underlying algorithm, and `MAC_VARIANT` is + * the specific variant of a MAC operation (such as HMAC or CMAC) + * + * \param[in] p_input A buffer containing the data to be MACed + * \param[in] input_length The length in bytes of the `p_input` data + * \param[in] p_key A buffer containing the key material to be used + * for the MAC operation + * \param[in] key_length The length in bytes of the `p_key` data + * \param[in] alg The algorithm to be performed + * \param[in] p_mac The MAC data to be compared + * \param[in] mac_length The length in bytes of the `p_mac` buffer + * + * \retval PSA_SUCCESS + * The operation completed successfully and the comparison matched + */ +typedef psa_status_t (*psa_drv_mac_transparent_verify_t)(const uint8_t *p_input, + size_t input_length, + const uint8_t *p_key, + size_t key_length, + psa_algorithm_t alg, + const uint8_t *p_mac, + size_t mac_length); +/**@}*/ + +/** \defgroup transparent_cipher Transparent Block Cipher + * Encryption and Decryption using transparent keys in block modes other than + * ECB must be done in multiple parts, using the following flow: + * - `psa_drv_cipher_transparent_setup_t` + * - `psa_drv_cipher_transparent_set_iv_t` (optional depending upon block mode) + * - `psa_drv_cipher_transparent_update_t` + * - ... + * - `psa_drv_cipher_transparent_finish_t` + + * If a previously started Transparent Cipher operation needs to be terminated, + * it should be done so by the `psa_drv_cipher_transparent_abort_t`. Failure to do + * so may result in allocated resources not being freed or in other undefined + * behavior. + */ +/**@{*/ + +/** \brief The hardware-specific transparent-key Cipher context structure + * + * The contents of this structure are implementation dependent and are + * therefore not described here. + */ +typedef struct psa_drv_cipher_transparent_context_s psa_drv_cipher_transparent_context_t; + +/** \brief The function prototype for the setup operation of transparent-key + * block cipher operations. + * Functions that implement the prototype should be named in the following + * conventions: + * ~~~~~~~~~~~~~{.c} + * psa_drv_cipher_transparent_setup__ + * ~~~~~~~~~~~~~ + * Where + * - `CIPHER_NAME` is the name of the underlying block cipher (i.e. AES or DES) + * - `MODE` is the block mode of the cipher operation (i.e. CBC or CTR) + * or for stream ciphers: + * ~~~~~~~~~~~~~{.c} + * psa_drv_cipher_transparent_setup_ + * ~~~~~~~~~~~~~ + * Where `CIPHER_NAME` is the name of a stream cipher (i.e. RC4) + * + * \param[in,out] p_context A structure that will contain the + * hardware-specific cipher context + * \param[in] direction Indicates if the operation is an encrypt or a + * decrypt + * \param[in] p_key_data A buffer containing the cleartext key material + * to be used in the operation + * \param[in] key_data_size The size in bytes of the key material + * + * \retval PSA_SUCCESS + */ +typedef psa_status_t (*psa_drv_cipher_transparent_setup_t)(psa_drv_cipher_transparent_context_t *p_context, + psa_encrypt_or_decrypt_t direction, + const uint8_t *p_key_data, + size_t key_data_size); + +/** \brief The function prototype for the set initialization vector operation + * of transparent-key block cipher operations + * Functions that implement the prototype should be named in the following + * convention: + * ~~~~~~~~~~~~~{.c} + * psa_drv_cipher_transparent_set_iv__ + * ~~~~~~~~~~~~~ + * Where + * - `CIPHER_NAME` is the name of the underlying block cipher (i.e. AES or DES) + * - `MODE` is the block mode of the cipher operation (i.e. CBC or CTR) + * + * \param[in,out] p_context A structure that contains the previously setup + * hardware-specific cipher context + * \param[in] p_iv A buffer containing the initialization vecotr + * \param[in] iv_length The size in bytes of the contents of `p_iv` + * + * \retval PSA_SUCCESS + */ +typedef psa_status_t (*psa_drv_cipher_transparent_set_iv_t)(psa_drv_cipher_transparent_context_t *p_context, + const uint8_t *p_iv, + size_t iv_length); + +/** \brief The function prototype for the update operation of transparent-key + * block cipher operations. + * + * Functions that implement the prototype should be named in the following + * convention: + * ~~~~~~~~~~~~~{.c} + * psa_drv_cipher_transparent_update__ + * ~~~~~~~~~~~~~ + * Where + * - `CIPHER_NAME` is the name of the underlying block cipher (i.e. AES or DES) + * - `MODE` is the block mode of the cipher operation (i.e. CBC or CTR) + * + * \param[in,out] p_context A hardware-specific structure for the + * previously started cipher operation + * \param[in] p_input A buffer containing the data to be + * encrypted or decrypted + * \param[in] input_size The size in bytes of the `p_input` buffer + * \param[out] p_output A caller-allocated buffer where the + * generated output will be placed + * \param[in] output_size The 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 + */ +typedef psa_status_t (*psa_drv_cipher_transparent_update_t)(psa_drv_cipher_transparent_context_t *p_context, + const uint8_t *p_input, + size_t input_size, + uint8_t *p_output, + size_t output_size, + size_t *p_output_length); + +/** \brief The function prototype for the finish operation of transparent-key + * block cipher operations. + * + * Functions that implement the prototype should be named in the following + * convention: + * ~~~~~~~~~~~~~{.c} + * psa_drv_cipher_transparent_finish__ + * ~~~~~~~~~~~~~ + * Where + * - `CIPHER_NAME` is the name of the underlying block cipher (i.e. AES or DES) + * - `MODE` is the block mode of the cipher operation (i.e. CBC or CTR) + * + * \param[in,out] p_context A hardware-specific structure for the + * previously started cipher operation + * \param[out] p_output A caller-allocated buffer where the generated + * output will be placed + * \param[in] output_size The 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 + */ +typedef psa_status_t (*psa_drv_cipher_transparent_finish_t)(psa_drv_cipher_transparent_context_t *p_context, + uint8_t *p_output, + size_t output_size, + size_t *p_output_length); + +/** \brief The function prototype for the abort operation of transparent-key + * block cipher operations. + * + * Functions that implement the following prototype should be named in the + * following convention: + * ~~~~~~~~~~~~~{.c} + * psa_drv_cipher_transparent_abort__ + * ~~~~~~~~~~~~~ + * Where + * - `CIPHER_NAME` is the name of the underlying block cipher (i.e. AES or DES) + * - `MODE` is the block mode of the cipher operation (i.e. CBC or CTR) + * + * \param[in,out] p_context A hardware-specific structure for the + * previously started cipher operation + * + * \retval PSA_SUCCESS + */ +typedef psa_status_t (*psa_drv_cipher_transparent_abort_t)(psa_drv_cipher_transparent_context_t *p_context); + +/**@}*/ + +/** \defgroup aead_transparent AEAD Transparent + * + * Authenticated Encryption with Additional Data (AEAD) operations with + * transparent keys 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. + */ +/**@{*/ + +/** Process an authenticated encryption operation using an opaque key. + * + * Functions that implement the prototype should be named in the following + * convention: + * ~~~~~~~~~~~~~{.c} + * psa_drv_aead__encrypt + * ~~~~~~~~~~~~~ + * Where `ALGO` is the name of the AEAD algorithm + * + * \param[in] p_key A pointer to the key material + * \param[in] key_length The size in bytes of the key material + * \param[in] alg The AEAD algorithm to compute + * (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_AEAD(`alg`) is true) + * \param[in] nonce Nonce or IV to use + * \param[in] nonce_length Size of the `nonce` buffer in bytes + * \param[in] additional_data Additional data that will be MACed + * but not encrypted. + * \param[in] additional_data_length Size of `additional_data` in bytes + * \param[in] plaintext Data that will be MACed and + * encrypted. + * \param[in] 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[in] ciphertext_size Size of the `ciphertext` buffer in + * bytes + * This must be at least + * #PSA_AEAD_ENCRYPT_OUTPUT_SIZE(`alg`, + * `plaintext_length`). + * \param[out] ciphertext_length On success, the size of the output in + * the `ciphertext` buffer + * + * \retval #PSA_SUCCESS + + */ +typedef psa_status_t (*psa_drv_aead_transparent_encrypt_t)(const uint8_t *p_key, + size_t key_length, + 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 using an opaque key. + * + * Functions that implement the prototype should be named in the following + * convention: + * ~~~~~~~~~~~~~{.c} + * psa_drv_aead__decrypt + * ~~~~~~~~~~~~~ + * Where `ALGO` is the name of the AEAD algorithm + * \param[in] p_key A pointer to the key material + * \param[in] key_length The size in bytes of the key material + * \param[in] alg The AEAD algorithm to compute + * (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_AEAD(`alg`) is true) + * \param[in] nonce Nonce or IV to use + * \param[in] nonce_length Size of the `nonce` buffer in bytes + * \param[in] additional_data Additional data that has been MACed + * but not encrypted + * \param[in] additional_data_length Size of `additional_data` in bytes + * \param[in] ciphertext Data that has been MACed 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 `ciphertext` in bytes + * \param[out] plaintext Output buffer for the decrypted data + * \param[in] plaintext_size Size of the `plaintext` buffer in + * bytes + * This must be at least + * #PSA_AEAD_DECRYPT_OUTPUT_SIZE(`alg`, + * `ciphertext_length`). + * \param[out] plaintext_length On success, the size of the output + * in the \b plaintext buffer + * + * \retval #PSA_SUCCESS + * Success. + */ +typedef psa_status_t (*psa_drv_aead_transparent_decrypt_t)(const uint8_t *p_key, + size_t key_length, + 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); + +/**@}*/ + +/** \defgroup transparent_asymmetric Transparent 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 + * transparent keys must be done in single function calls. + */ +/**@{*/ + + +/** + * \brief A function that signs a hash or short message with a transparent + * asymmetric private key + * + * Functions that implement the prototype should be named in the following + * convention: + * ~~~~~~~~~~~~~{.c} + * psa_drv_asymmetric__sign + * ~~~~~~~~~~~~~ + * Where `ALGO` is the name of the signing algorithm + * + * \param[in] p_key A buffer containing the private key + * material + * \param[in] key_size The size in bytes of the `p_key` data + * \param[in] alg A signature algorithm that is compatible + * with the type of `p_key` + * \param[in] p_hash The hash or message 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 + */ +typedef psa_status_t (*psa_drv_asymmetric_transparent_sign_t)(const uint8_t *p_key, + size_t key_size, + 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 + * a transparent asymmetric public key + * + * Functions that implement the prototype should be named in the following + * convention: + * ~~~~~~~~~~~~~{.c} + * psa_drv_asymmetric__verify + * ~~~~~~~~~~~~~ + * Where `ALGO` is the name of the signing algorithm + * + * \param[in] p_key A buffer containing the public key material + * \param[in] key_size The size in bytes of the `p_key` data + * \param[in] alg A signature algorithm that is compatible with + * the type of `key` + * \param[in] p_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] 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_asymmetric_transparent_verify_t)(const uint8_t *p_key, + size_t key_size, + 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 a transparent + * asymmetric public key + * + * Functions that implement the prototype should be named in the following + * convention: + * ~~~~~~~~~~~~~{.c} + * psa_drv_asymmetric__encrypt + * ~~~~~~~~~~~~~ + * Where `ALGO` is the name of the encryption algorithm + * + * \param[in] p_key A buffer containing the public key material + * \param[in] key_size The size in bytes of the `p_key` data + * \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 + */ +typedef psa_status_t (*psa_drv_asymmetric_transparent_encrypt_t)(const uint8_t *p_key, + size_t key_size, + 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 Decrypt a short message with a transparent asymmetric private key + * + * Functions that implement the prototype should be named in the following + * convention: + * ~~~~~~~~~~~~~{.c} + * psa_drv_asymmetric__decrypt + * ~~~~~~~~~~~~~ + * Where `ALGO` is the name of the encryption algorithm + * + * \param[in] p_key A buffer containing the private key material + * \param[in] key_size The size in bytes of the `p_key` data + * \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 + */ +typedef psa_status_t (*psa_drv_asymmetric_transparent_decrypt_t)(const uint8_t *p_key, + size_t key_size, + 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); + +/**@}*/ + +#ifdef __cplusplus +} +#endif + +#endif /* PSA_CRYPTO_ACCEL_DRIVER_H */ diff --git a/features/mbedtls/mbed-crypto/inc/psa/crypto_driver_common.h b/features/mbedtls/mbed-crypto/inc/psa/crypto_driver_common.h new file mode 100644 index 00000000000..6f1a5d5d9b1 --- /dev/null +++ b/features/mbedtls/mbed-crypto/inc/psa/crypto_driver_common.h @@ -0,0 +1,54 @@ +/** + * \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 driver for a chip that provides both a hardware + * random generator and an accelerator for some cryptographic algorithms, + * include `psa/crypto_entropy_driver.h` and `psa/crypto_accel_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 (C) 2018, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef PSA_CRYPTO_DRIVER_COMMON_H +#define PSA_CRYPTO_DRIVER_COMMON_H + +#include +#include + +/* Include type definitions (psa_status_t, psa_algorithm_t, + * psa_key_type_t, etc.) and macros to build and analyze values + * of these types. */ +#include "crypto_types.h" +#include "crypto_values.h" + +/** For encrypt-decrypt functions, whether the operation is an encryption + * or a decryption. */ +typedef enum { + PSA_CRYPTO_DRIVER_DECRYPT, + PSA_CRYPTO_DRIVER_ENCRYPT +} psa_encrypt_or_decrypt_t; + +#endif /* PSA_CRYPTO_DRIVER_COMMON_H */ diff --git a/features/mbedtls/mbed-crypto/inc/psa/crypto_entropy_driver.h b/features/mbedtls/mbed-crypto/inc/psa/crypto_entropy_driver.h new file mode 100644 index 00000000000..f5e383e6cb6 --- /dev/null +++ b/features/mbedtls/mbed-crypto/inc/psa/crypto_entropy_driver.h @@ -0,0 +1,111 @@ +/** + * \file psa/crypto_entropy_driver.h + * \brief PSA entropy source driver module + * + * This header declares types and function signatures for entropy sources. + * + * 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 (C) 2018, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#ifndef PSA_CRYPTO_ENTROPY_DRIVER_H +#define PSA_CRYPTO_ENTROPY_DRIVER_H + +#include "crypto_driver_common.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** \defgroup driver_rng Entropy Generation + */ +/**@{*/ + +/** \brief A hardware-specific structure for a entropy providing hardware + */ +typedef struct psa_drv_entropy_context_s psa_drv_entropy_context_t; + +/** \brief Initialize an entropy driver + * + * + * \param[in,out] p_context A hardware-specific structure + * containing any context information for + * the implementation + * + * \retval PSA_SUCCESS + */ +typedef psa_status_t (*psa_drv_entropy_init_t)(psa_drv_entropy_context_t *p_context); + +/** \brief Get a specified number of bits from the entropy source + * + * It retrives `buffer_size` bytes of data from the entropy source. The entropy + * source will always fill the provided buffer to its full size, however, most + * entropy sources have biases, and the actual amount of entropy contained in + * the buffer will be less than the number of bytes. + * The driver will return the actual number of bytes of entropy placed in the + * buffer in `p_received_entropy_bytes`. + * A PSA Crypto API implementation will likely feed the output of this function + * into a Digital Random Bit Generator (DRBG), and typically has a minimum + * amount of entropy that it needs. + * To accomplish this, the PSA Crypto implementation should be designed to call + * this function multiple times until it has received the required amount of + * entropy from the entropy source. + * + * \param[in,out] p_context A hardware-specific structure + * containing any context information + * for the implementation + * \param[out] p_buffer A caller-allocated buffer for the + * retrieved entropy to be placed in + * \param[in] buffer_size The allocated size of `p_buffer` + * \param[out] p_received_entropy_bits The amount of entropy (in bits) + * actually provided in `p_buffer` + * + * \retval PSA_SUCCESS + */ +typedef psa_status_t (*psa_drv_entropy_get_bits_t)(psa_drv_entropy_context_t *p_context, + uint8_t *p_buffer, + uint32_t buffer_size, + uint32_t *p_received_entropy_bits); + +/** + * \brief A struct containing all of the function pointers needed to interface + * to an entropy source + * + * 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 initialization for the entropy source */ + psa_drv_entropy_init_t *p_init; + /** Function that performs the get_bits operation for the entropy source + */ + psa_drv_entropy_get_bits_t *p_get_bits; +} psa_drv_entropy_t; +/**@}*/ + +#ifdef __cplusplus +} +#endif + +#endif /* PSA_CRYPTO_ENTROPY_DRIVER_H */ diff --git a/features/mbedtls/mbed-crypto/inc/psa/crypto_platform.h b/features/mbedtls/mbed-crypto/inc/psa/crypto_platform.h index 9af320d1e9a..50ca546fb62 100644 --- a/features/mbedtls/mbed-crypto/inc/psa/crypto_platform.h +++ b/features/mbedtls/mbed-crypto/inc/psa/crypto_platform.h @@ -46,7 +46,7 @@ /* PSA requires several types which C99 provides in stdint.h. */ #include -/* Integral type representing a key slot number. */ -typedef uint16_t psa_key_slot_t; +/* Integral type representing a key handle. */ +typedef uint16_t psa_key_handle_t; #endif /* PSA_CRYPTO_PLATFORM_H */ diff --git a/features/mbedtls/mbed-crypto/inc/psa/crypto_driver.h b/features/mbedtls/mbed-crypto/inc/psa/crypto_se_driver.h similarity index 52% rename from features/mbedtls/mbed-crypto/inc/psa/crypto_driver.h rename to features/mbedtls/mbed-crypto/inc/psa/crypto_se_driver.h index a52ecc427c1..05786644532 100644 --- a/features/mbedtls/mbed-crypto/inc/psa/crypto_driver.h +++ b/features/mbedtls/mbed-crypto/inc/psa/crypto_se_driver.h @@ -1,8 +1,14 @@ /** - * \file psa/crypto_driver.h - * \brief Platform Security Architecture cryptographic driver module + * \file psa/crypto_se_driver.h + * \brief PSA external cryptoprocessor driver module * - * This file describes the PSA Crypto Driver Model, containing functions for + * 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. + * + * 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 @@ -25,29 +31,19 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -#ifndef PSA_CRYPTO_DRIVER_H -#define PSA_CRYPTO_DRIVER_H +#ifndef PSA_CRYPTO_SE_DRIVER_H +#define PSA_CRYPTO_SE_DRIVER_H -#include -#include +#include "crypto_driver_common.h" #ifdef __cplusplus extern "C" { #endif -/** The following types are redefinitions from the psa/crypto.h file. - * It is intended that these will be moved to a new common header file to - * avoid duplication. They are included here for expediency in publication. - */ -typedef uint32_t psa_status_t; -typedef uint32_t psa_algorithm_t; -typedef uint8_t psa_encrypt_or_decrypt_t; +/** 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 uint32_t psa_key_slot_t; -typedef uint32_t psa_key_type_t; -typedef uint32_t psa_key_usage_t; - -#define PSA_CRYPTO_DRIVER_ENCRYPT 1 -#define PSA_CRYPTO_DRIVER_DECRYPT 0 /** \defgroup opaque_mac Opaque Message Authentication Code * Generation and authentication of Message Authentication Codes (MACs) using @@ -239,208 +235,6 @@ typedef struct { } psa_drv_mac_opaque_t; /**@}*/ -/** \defgroup transparent_mac Transparent Message Authentication Code - * Generation and authentication of Message Authentication Codes (MACs) using - * transparent keys can be done either as a single function call (via the - * `psa_drv_mac_transparent_generate_t` or `psa_drv_mac_transparent_verify_t` - * functions), or in parts using the following sequence: - * - `psa_drv_mac_transparent_setup_t` - * - `psa_drv_mac_transparent_update_t` - * - `psa_drv_mac_transparent_update_t` - * - ... - * - `psa_drv_mac_transparent_finish_t` or `psa_drv_mac_transparent_finish_verify_t` - * - * If a previously started Transparent MAC operation needs to be terminated, it - * should be done so by the `psa_drv_mac_transparent_abort_t`. Failure to do so may - * result in allocated resources not being freed or in other undefined - * behavior. - * - */ -/**@{*/ - -/** \brief The hardware-specific transparent-key MAC context structure - * - * The contents of this structure are implementation dependent and are - * therefore not described here. - */ -typedef struct psa_drv_mac_transparent_context_s psa_drv_mac_transparent_context_t; - -/** \brief The function prototype for the setup operation of a - * transparent-key MAC operation - * - * Functions that implement the prototype should be named in the following - * convention: - * ~~~~~~~~~~~~~{.c} - * psa_drv_mac_transparent___setup - * ~~~~~~~~~~~~~ - * Where `ALGO` is the name of the underlying primitive, and `MAC_VARIANT` - * is the specific variant of a MAC operation (such as HMAC or CMAC) - * - * \param[in,out] p_context A structure that will contain the - * hardware-specific MAC context - * \param[in] p_key A buffer containing the cleartext key material - * to be used in the operation - * \param[in] key_length The size in bytes of the key material - * - * \retval PSA_SUCCESS - * Success. - */ -typedef psa_status_t (*psa_drv_mac_transparent_setup_t)(psa_drv_mac_transparent_context_t *p_context, - const uint8_t *p_key, - size_t key_length); - -/** \brief The function prototype for the update operation of a - * transparent-key MAC operation - * - * Functions that implement the prototype should be named in the following - * convention: - * ~~~~~~~~~~~~~{.c} - * psa_drv_mac_transparent___update - * ~~~~~~~~~~~~~ - * Where `ALGO` is the name of the underlying algorithm, and `MAC_VARIANT` - * is the specific variant of a MAC operation (such as HMAC or CMAC) - * - * \param[in,out] p_context A hardware-specific structure for the - * previously-established MAC operation to be - * continued - * \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_mac_transparent_update_t)(psa_drv_mac_transparent_context_t *p_context, - const uint8_t *p_input, - size_t input_length); - -/** \brief The function prototype for the finish operation of a - * transparent-key MAC operation - * - * Functions that implement the prototype should be named in the following - * convention: - * ~~~~~~~~~~~~~{.c} - * psa_drv_mac_transparent___finish - * ~~~~~~~~~~~~~ - * Where `ALGO` is the name of the underlying algorithm, and `MAC_VARIANT` is - * the specific variant of a MAC operation (such as HMAC or CMAC) - * - * \param[in,out] p_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_length The size in bytes of the buffer that has been - * allocated for the `p_mac` buffer - * - * \retval PSA_SUCCESS - * Success. - */ -typedef psa_status_t (*psa_drv_mac_transparent_finish_t)(psa_drv_mac_transparent_context_t *p_context, - uint8_t *p_mac, - size_t mac_length); - -/** \brief The function prototype for the finish and verify operation of a - * transparent-key MAC operation - * - * Functions that implement the prototype should be named in the following - * convention: - * ~~~~~~~~~~~~~{.c} - * psa_drv_mac_transparent___finish_verify - * ~~~~~~~~~~~~~ - * Where `ALGO` is the name of the underlying algorithm, and `MAC_VARIANT` is - * the specific variant of a MAC operation (such as HMAC or CMAC) - * - * \param[in,out] p_context A hardware-specific structure for the - * previously started MAC operation to be - * verified and finished - * \param[in] p_mac A buffer containing the MAC that will be used - * for verification - * \param[in] mac_length The size in bytes of the data in the `p_mac` - * buffer - * - * \retval PSA_SUCCESS - * The operation completed successfully and the comparison matched - */ -typedef psa_status_t (*psa_drv_mac_transparent_finish_verify_t)(psa_drv_mac_transparent_context_t *p_context, - const uint8_t *p_mac, - size_t mac_length); - -/** \brief The function prototype for the abort operation for a previously - * started transparent-key MAC operation - * - * Functions that implement the prototype should be named in the following - * convention: - * ~~~~~~~~~~~~~{.c} - * psa_drv_mac_transparent___abort - * ~~~~~~~~~~~~~ - * Where `ALGO` is the name of the underlying algorithm, and `MAC_VARIANT` is - * the specific variant of a MAC operation (such as HMAC or CMAC) - * - * \param[in,out] p_context A hardware-specific structure for the - * previously started MAC operation to be - * aborted - * - */ -typedef psa_status_t (*psa_drv_mac_transparent_abort_t)(psa_drv_mac_transparent_context_t *p_context); - -/** \brief The function prototype for a one-shot operation of a transparent-key - * MAC operation - * - * Functions that implement the prototype should be named in the following - * convention: - * ~~~~~~~~~~~~~{.c} - * psa_drv_mac_transparent__ - * ~~~~~~~~~~~~~ - * Where `ALGO` is the name of the underlying algorithm, and `MAC_VARIANT` is - * the specific variant of a MAC operation (such as HMAC or CMAC) - * - * \param[in] p_input A buffer containing the data to be MACed - * \param[in] input_length The length in bytes of the `p_input` data - * \param[in] p_key A buffer containing the key material to be used - * for the MAC operation - * \param[in] key_length The length in bytes of the `p_key` data - * \param[in] alg The algorithm to be performed - * \param[out] p_mac The buffer where the resulting MAC will be placed - * upon success - * \param[in] mac_length The length in bytes of the `p_mac` buffer - */ -typedef psa_status_t (*psa_drv_mac_transparent_t)(const uint8_t *p_input, - size_t input_length, - const uint8_t *p_key, - size_t key_length, - psa_algorithm_t alg, - uint8_t *p_mac, - size_t mac_length); - -/** \brief The function prototype for a one-shot operation of a transparent-key - * MAC Verify operation - * - * Functions that implement the prototype should be named in the following - * convention: - * ~~~~~~~~~~~~~{.c} - * psa_drv_mac_transparent___verify - * ~~~~~~~~~~~~~ - * Where `ALGO` is the name of the underlying algorithm, and `MAC_VARIANT` is - * the specific variant of a MAC operation (such as HMAC or CMAC) - * - * \param[in] p_input A buffer containing the data to be MACed - * \param[in] input_length The length in bytes of the `p_input` data - * \param[in] p_key A buffer containing the key material to be used - * for the MAC operation - * \param[in] key_length The length in bytes of the `p_key` data - * \param[in] alg The algorithm to be performed - * \param[in] p_mac The MAC data to be compared - * \param[in] mac_length The length in bytes of the `p_mac` buffer - * - * \retval PSA_SUCCESS - * The operation completed successfully and the comparison matched - */ -typedef psa_status_t (*psa_drv_mac_transparent_verify_t)(const uint8_t *p_input, - size_t input_length, - const uint8_t *p_key, - size_t key_length, - psa_algorithm_t alg, - const uint8_t *p_mac, - size_t mac_length); -/**@}*/ - /** \defgroup opaque_cipher Opaque Symmetric Ciphers * * Encryption and Decryption using opaque keys in block modes other than ECB @@ -618,269 +412,6 @@ typedef struct { /**@}*/ -/** \defgroup transparent_cipher Transparent Block Cipher - * Encryption and Decryption using transparent keys in block modes other than - * ECB must be done in multiple parts, using the following flow: - * - `psa_drv_cipher_transparent_setup_t` - * - `psa_drv_cipher_transparent_set_iv_t` (optional depending upon block mode) - * - `psa_drv_cipher_transparent_update_t` - * - ... - * - `psa_drv_cipher_transparent_finish_t` - - * If a previously started Transparent Cipher operation needs to be terminated, - * it should be done so by the `psa_drv_cipher_transparent_abort_t`. Failure to do - * so may result in allocated resources not being freed or in other undefined - * behavior. - */ -/**@{*/ - -/** \brief The hardware-specific transparent-key Cipher context structure - * - * The contents of this structure are implementation dependent and are - * therefore not described here. - */ -typedef struct psa_drv_cipher_transparent_context_s psa_drv_cipher_transparent_context_t; - -/** \brief The function prototype for the setup operation of transparent-key - * block cipher operations. - * Functions that implement the prototype should be named in the following - * conventions: - * ~~~~~~~~~~~~~{.c} - * psa_drv_cipher_transparent_setup__ - * ~~~~~~~~~~~~~ - * Where - * - `CIPHER_NAME` is the name of the underlying block cipher (i.e. AES or DES) - * - `MODE` is the block mode of the cipher operation (i.e. CBC or CTR) - * or for stream ciphers: - * ~~~~~~~~~~~~~{.c} - * psa_drv_cipher_transparent_setup_ - * ~~~~~~~~~~~~~ - * Where `CIPHER_NAME` is the name of a stream cipher (i.e. RC4) - * - * \param[in,out] p_context A structure that will contain the - * hardware-specific cipher context - * \param[in] direction Indicates if the operation is an encrypt or a - * decrypt - * \param[in] p_key_data A buffer containing the cleartext key material - * to be used in the operation - * \param[in] key_data_size The size in bytes of the key material - * - * \retval PSA_SUCCESS - */ -typedef psa_status_t (*psa_drv_cipher_transparent_setup_t)(psa_drv_cipher_transparent_context_t *p_context, - psa_encrypt_or_decrypt_t direction, - const uint8_t *p_key_data, - size_t key_data_size); - -/** \brief The function prototype for the set initialization vector operation - * of transparent-key block cipher operations - * Functions that implement the prototype should be named in the following - * convention: - * ~~~~~~~~~~~~~{.c} - * psa_drv_cipher_transparent_set_iv__ - * ~~~~~~~~~~~~~ - * Where - * - `CIPHER_NAME` is the name of the underlying block cipher (i.e. AES or DES) - * - `MODE` is the block mode of the cipher operation (i.e. CBC or CTR) - * - * \param[in,out] p_context A structure that contains the previously setup - * hardware-specific cipher context - * \param[in] p_iv A buffer containing the initialization vecotr - * \param[in] iv_length The size in bytes of the contents of `p_iv` - * - * \retval PSA_SUCCESS - */ -typedef psa_status_t (*psa_drv_cipher_transparent_set_iv_t)(psa_drv_cipher_transparent_context_t *p_context, - const uint8_t *p_iv, - size_t iv_length); - -/** \brief The function prototype for the update operation of transparent-key - * block cipher operations. - * - * Functions that implement the prototype should be named in the following - * convention: - * ~~~~~~~~~~~~~{.c} - * psa_drv_cipher_transparent_update__ - * ~~~~~~~~~~~~~ - * Where - * - `CIPHER_NAME` is the name of the underlying block cipher (i.e. AES or DES) - * - `MODE` is the block mode of the cipher operation (i.e. CBC or CTR) - * - * \param[in,out] p_context A hardware-specific structure for the - * previously started cipher operation - * \param[in] p_input A buffer containing the data to be - * encrypted or decrypted - * \param[in] input_size The size in bytes of the `p_input` buffer - * \param[out] p_output A caller-allocated buffer where the - * generated output will be placed - * \param[in] output_size The 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 - */ -typedef psa_status_t (*psa_drv_cipher_transparent_update_t)(psa_drv_cipher_transparent_context_t *p_context, - const uint8_t *p_input, - size_t input_size, - uint8_t *p_output, - size_t output_size, - size_t *p_output_length); - -/** \brief The function prototype for the finish operation of transparent-key - * block cipher operations. - * - * Functions that implement the prototype should be named in the following - * convention: - * ~~~~~~~~~~~~~{.c} - * psa_drv_cipher_transparent_finish__ - * ~~~~~~~~~~~~~ - * Where - * - `CIPHER_NAME` is the name of the underlying block cipher (i.e. AES or DES) - * - `MODE` is the block mode of the cipher operation (i.e. CBC or CTR) - * - * \param[in,out] p_context A hardware-specific structure for the - * previously started cipher operation - * \param[out] p_output A caller-allocated buffer where the generated - * output will be placed - * \param[in] output_size The 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 - */ -typedef psa_status_t (*psa_drv_cipher_transparent_finish_t)(psa_drv_cipher_transparent_context_t *p_context, - uint8_t *p_output, - size_t output_size, - size_t *p_output_length); - -/** \brief The function prototype for the abort operation of transparent-key - * block cipher operations. - * - * Functions that implement the following prototype should be named in the - * following convention: - * ~~~~~~~~~~~~~{.c} - * psa_drv_cipher_transparent_abort__ - * ~~~~~~~~~~~~~ - * Where - * - `CIPHER_NAME` is the name of the underlying block cipher (i.e. AES or DES) - * - `MODE` is the block mode of the cipher operation (i.e. CBC or CTR) - * - * \param[in,out] p_context A hardware-specific structure for the - * previously started cipher operation - * - * \retval PSA_SUCCESS - */ -typedef psa_status_t (*psa_drv_cipher_transparent_abort_t)(psa_drv_cipher_transparent_context_t *p_context); - -/**@}*/ - -/** \defgroup driver_digest Message Digests - * - * Generation and authentication of Message Digests (aka hashes) must be done - * in parts using the following sequence: - * - `psa_drv_hash_setup_t` - * - `psa_drv_hash_update_t` - * - ... - * - `psa_drv_hash_finish_t` - * - * If a previously started Message Digest operation needs to be terminated - * before the `psa_drv_hash_finish_t` operation is complete, it should be aborted - * by the `psa_drv_hash_abort_t`. Failure to do so may result in allocated - * resources not being freed or in other undefined behavior. - */ -/**@{*/ - -/** \brief The hardware-specific hash context structure - * - * The contents of this structure are implementation dependent and are - * therefore not described here - */ -typedef struct psa_drv_hash_context_s psa_drv_hash_context_t; - -/** \brief The function prototype for the start operation of a hash (message - * digest) operation - * - * Functions that implement the prototype should be named in the following - * convention: - * ~~~~~~~~~~~~~{.c} - * psa_drv_hash__setup - * ~~~~~~~~~~~~~ - * Where `ALGO` is the name of the underlying hash function - * - * \param[in,out] p_context A structure that will contain the - * hardware-specific hash context - * - * \retval PSA_SUCCESS Success. - */ -typedef psa_status_t (*psa_drv_hash_setup_t)(psa_drv_hash_context_t *p_context); - -/** \brief The function prototype for the update operation of a hash (message - * digest) operation - * - * Functions that implement the prototype should be named in the following - * convention: - * ~~~~~~~~~~~~~{.c} - * psa_drv_hash__update - * ~~~~~~~~~~~~~ - * Where `ALGO` is the name of the underlying algorithm - * - * \param[in,out] p_context A hardware-specific structure for the - * previously-established hash operation to be - * continued - * \param[in] p_input A buffer containing the message to be appended - * to the hash operation - * \param[in] input_length The size in bytes of the input message buffer - */ -typedef psa_status_t (*psa_drv_hash_update_t)(psa_drv_hash_context_t *p_context, - const uint8_t *p_input, - size_t input_length); - -/** \brief The prototype for the finish operation of a hash (message digest) - * operation - * - * Functions that implement the prototype should be named in the following - * convention: - * ~~~~~~~~~~~~~{.c} - * psa_drv_hash__finish - * ~~~~~~~~~~~~~ - * Where `ALGO` is the name of the underlying algorithm - * - * \param[in,out] p_context A hardware-specific structure for the - * previously started hash operation to be - * fiinished - * \param[out] p_output A buffer where the generated digest will be - * placed - * \param[in] output_size The size in bytes of the buffer that has been - * allocated for the `p_output` buffer - * \param[out] p_output_length The number of bytes placed in `p_output` after - * success - * - * \retval PSA_SUCCESS - * Success. - */ -typedef psa_status_t (*psa_drv_hash_finish_t)(psa_drv_hash_context_t *p_context, - uint8_t *p_output, - size_t output_size, - size_t *p_output_length); - -/** \brief The function prototype for the abort operation of a hash (message - * digest) operation - * - * Functions that implement the prototype should be named in the following - * convention: - * ~~~~~~~~~~~~~{.c} - * psa_drv_hash__abort - * ~~~~~~~~~~~~~ - * Where `ALGO` is the name of the underlying algorithm - * - * \param[in,out] p_context A hardware-specific structure for the previously - * started hash operation to be aborted - */ -typedef void (*psa_drv_hash_abort_t)(psa_drv_hash_context_t *p_context); - -/**@}*/ - - /** \defgroup opaque_asymmetric Opaque Asymmetric Cryptography * * Since the amount of data that can (or should) be encrypted or signed using @@ -1033,176 +564,6 @@ typedef struct { /**@}*/ -/** \defgroup transparent_asymmetric Transparent 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 - * transparent keys must be done in single function calls. - */ -/**@{*/ - - -/** - * \brief A function that signs a hash or short message with a transparent - * asymmetric private key - * - * Functions that implement the prototype should be named in the following - * convention: - * ~~~~~~~~~~~~~{.c} - * psa_drv_asymmetric__sign - * ~~~~~~~~~~~~~ - * Where `ALGO` is the name of the signing algorithm - * - * \param[in] p_key A buffer containing the private key - * material - * \param[in] key_size The size in bytes of the `p_key` data - * \param[in] alg A signature algorithm that is compatible - * with the type of `p_key` - * \param[in] p_hash The hash or message 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 - */ -typedef psa_status_t (*psa_drv_asymmetric_transparent_sign_t)(const uint8_t *p_key, - size_t key_size, - 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 - * a transparent asymmetric public key - * - * Functions that implement the prototype should be named in the following - * convention: - * ~~~~~~~~~~~~~{.c} - * psa_drv_asymmetric__verify - * ~~~~~~~~~~~~~ - * Where `ALGO` is the name of the signing algorithm - * - * \param[in] p_key A buffer containing the public key material - * \param[in] key_size The size in bytes of the `p_key` data - * \param[in] alg A signature algorithm that is compatible with - * the type of `key` - * \param[in] p_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] 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_asymmetric_transparent_verify_t)(const uint8_t *p_key, - size_t key_size, - 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 a transparent - * asymmetric public key - * - * Functions that implement the prototype should be named in the following - * convention: - * ~~~~~~~~~~~~~{.c} - * psa_drv_asymmetric__encrypt - * ~~~~~~~~~~~~~ - * Where `ALGO` is the name of the encryption algorithm - * - * \param[in] p_key A buffer containing the public key material - * \param[in] key_size The size in bytes of the `p_key` data - * \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 - */ -typedef psa_status_t (*psa_drv_asymmetric_transparent_encrypt_t)(const uint8_t *p_key, - size_t key_size, - 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 Decrypt a short message with a transparent asymmetric private key - * - * Functions that implement the prototype should be named in the following - * convention: - * ~~~~~~~~~~~~~{.c} - * psa_drv_asymmetric__decrypt - * ~~~~~~~~~~~~~ - * Where `ALGO` is the name of the encryption algorithm - * - * \param[in] p_key A buffer containing the private key material - * \param[in] key_size The size in bytes of the `p_key` data - * \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 - */ -typedef psa_status_t (*psa_drv_asymmetric_transparent_decrypt_t)(const uint8_t *p_key, - size_t key_size, - 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); - -/**@}*/ - /** \defgroup aead_opaque AEAD Opaque * Authenticated Encryption with Additional Data (AEAD) operations with opaque * keys must be done in one function call. While this creates a burden for @@ -1310,192 +671,6 @@ typedef struct { } psa_drv_aead_opaque_t; /**@}*/ -/** \defgroup aead_transparent AEAD Transparent - * - * Authenticated Encryption with Additional Data (AEAD) operations with - * transparent keys 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. - */ -/**@{*/ - -/** Process an authenticated encryption operation using an opaque key. - * - * Functions that implement the prototype should be named in the following - * convention: - * ~~~~~~~~~~~~~{.c} - * psa_drv_aead__encrypt - * ~~~~~~~~~~~~~ - * Where `ALGO` is the name of the AEAD algorithm - * - * \param[in] p_key A pointer to the key material - * \param[in] key_length The size in bytes of the key material - * \param[in] alg The AEAD algorithm to compute - * (\c PSA_ALG_XXX value such that - * #PSA_ALG_IS_AEAD(`alg`) is true) - * \param[in] nonce Nonce or IV to use - * \param[in] nonce_length Size of the `nonce` buffer in bytes - * \param[in] additional_data Additional data that will be MACed - * but not encrypted. - * \param[in] additional_data_length Size of `additional_data` in bytes - * \param[in] plaintext Data that will be MACed and - * encrypted. - * \param[in] 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[in] ciphertext_size Size of the `ciphertext` buffer in - * bytes - * This must be at least - * #PSA_AEAD_ENCRYPT_OUTPUT_SIZE(`alg`, - * `plaintext_length`). - * \param[out] ciphertext_length On success, the size of the output in - * the `ciphertext` buffer - * - * \retval #PSA_SUCCESS - - */ -typedef psa_status_t (*psa_drv_aead_transparent_encrypt_t)(const uint8_t *p_key, - size_t key_length, - 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 using an opaque key. - * - * Functions that implement the prototype should be named in the following - * convention: - * ~~~~~~~~~~~~~{.c} - * psa_drv_aead__decrypt - * ~~~~~~~~~~~~~ - * Where `ALGO` is the name of the AEAD algorithm - * \param[in] p_key A pointer to the key material - * \param[in] key_length The size in bytes of the key material - * \param[in] alg The AEAD algorithm to compute - * (\c PSA_ALG_XXX value such that - * #PSA_ALG_IS_AEAD(`alg`) is true) - * \param[in] nonce Nonce or IV to use - * \param[in] nonce_length Size of the `nonce` buffer in bytes - * \param[in] additional_data Additional data that has been MACed - * but not encrypted - * \param[in] additional_data_length Size of `additional_data` in bytes - * \param[in] ciphertext Data that has been MACed 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 `ciphertext` in bytes - * \param[out] plaintext Output buffer for the decrypted data - * \param[in] plaintext_size Size of the `plaintext` buffer in - * bytes - * This must be at least - * #PSA_AEAD_DECRYPT_OUTPUT_SIZE(`alg`, - * `ciphertext_length`). - * \param[out] plaintext_length On success, the size of the output - * in the \b plaintext buffer - * - * \retval #PSA_SUCCESS - * Success. - */ -typedef psa_status_t (*psa_drv_aead_transparent_decrypt_t)(const uint8_t *p_key, - size_t key_length, - 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); - -/**@}*/ - - -/** \defgroup driver_rng Entropy Generation - */ -/**@{*/ - -/** \brief A hardware-specific structure for a entropy providing hardware - */ -typedef struct psa_drv_entropy_context_s psa_drv_entropy_context_t; - -/** \brief Initialize an entropy driver - * - * - * \param[in,out] p_context A hardware-specific structure - * containing any context information for - * the implementation - * - * \retval PSA_SUCCESS - */ -typedef psa_status_t (*psa_drv_entropy_init_t)(psa_drv_entropy_context_t *p_context); - -/** \brief Get a specified number of bits from the entropy source - * - * It retrives `buffer_size` bytes of data from the entropy source. The entropy - * source will always fill the provided buffer to its full size, however, most - * entropy sources have biases, and the actual amount of entropy contained in - * the buffer will be less than the number of bytes. - * The driver will return the actual number of bytes of entropy placed in the - * buffer in `p_received_entropy_bytes`. - * A PSA Crypto API implementation will likely feed the output of this function - * into a Digital Random Bit Generator (DRBG), and typically has a minimum - * amount of entropy that it needs. - * To accomplish this, the PSA Crypto implementation should be designed to call - * this function multiple times until it has received the required amount of - * entropy from the entropy source. - * - * \param[in,out] p_context A hardware-specific structure - * containing any context information - * for the implementation - * \param[out] p_buffer A caller-allocated buffer for the - * retrieved entropy to be placed in - * \param[in] buffer_size The allocated size of `p_buffer` - * \param[out] p_received_entropy_bits The amount of entropy (in bits) - * actually provided in `p_buffer` - * - * \retval PSA_SUCCESS - */ -typedef psa_status_t (*psa_drv_entropy_get_bits_t)(psa_drv_entropy_context_t *p_context, - uint8_t *p_buffer, - uint32_t buffer_size, - uint32_t *p_received_entropy_bits); - -/** - * \brief A struct containing all of the function pointers needed to interface - * to an entropy source - * - * 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 initialization for the entropy source */ - psa_drv_entropy_init_t *p_init; - /** Function that performs the get_bits operation for the entropy source - */ - psa_drv_entropy_get_bits_t *p_get_bits; -} psa_drv_entropy_t; -/**@}*/ - /** \defgroup driver_key_management Key Management * Currently, key management is limited to importing keys in the clear, * destroying keys, and exporting keys in the clear. @@ -1784,4 +959,4 @@ typedef struct { } #endif -#endif /* PSA_CRYPTO_DRIVER_H */ +#endif /* PSA_CRYPTO_SE_DRIVER_H */ diff --git a/features/mbedtls/mbed-crypto/inc/psa/crypto_sizes.h b/features/mbedtls/mbed-crypto/inc/psa/crypto_sizes.h index 7e179567367..9ad0536295c 100644 --- a/features/mbedtls/mbed-crypto/inc/psa/crypto_sizes.h +++ b/features/mbedtls/mbed-crypto/inc/psa/crypto_sizes.h @@ -50,6 +50,42 @@ #include MBEDTLS_CONFIG_FILE #endif +#define PSA_BITS_TO_BYTES(bits) (((bits) + 7) / 8) +#define PSA_BYTES_TO_BITS(bytes) ((bytes) * 8) + +/** 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. + * An implementation may return either 0 or the correct size + * for a hash algorithm that it recognizes, but does not support. + */ +#define PSA_HASH_SIZE(alg) \ + ( \ + PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_MD2 ? 16 : \ + PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_MD4 ? 16 : \ + PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_MD5 ? 16 : \ + PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_RIPEMD160 ? 20 : \ + PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA_1 ? 20 : \ + PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA_224 ? 28 : \ + PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA_256 ? 32 : \ + PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA_384 ? 48 : \ + PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA_512 ? 64 : \ + PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA_512_224 ? 28 : \ + PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA_512_256 ? 32 : \ + PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA3_224 ? 28 : \ + PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA3_256 ? 32 : \ + PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA3_384 ? 48 : \ + PSA_ALG_HMAC_GET_HASH(alg) == PSA_ALG_SHA3_512 ? 64 : \ + 0) + /** \def PSA_HASH_MAX_SIZE * * Maximum size of a hash. @@ -84,6 +120,26 @@ */ #define PSA_MAC_MAX_SIZE PSA_HASH_MAX_SIZE +/** The tag size for an AEAD algorithm, in bytes. + * + * \param alg An AEAD algorithm + * (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_AEAD(\p alg) is true). + * + * \return The tag size for the specified algorithm. + * If the AEAD algorithm does not have an identified + * tag that can be distinguished from the rest of + * the ciphertext, return 0. + * If the AEAD algorithm is not recognized, return 0. + * An implementation may return either 0 or a + * correct size for an AEAD algorithm that it + * recognizes, but does not support. + */ +#define PSA_AEAD_TAG_LENGTH(alg) \ + (PSA_ALG_IS_AEAD(alg) ? \ + (((alg) & PSA_ALG_AEAD_TAG_LENGTH_MASK) >> PSA_AEAD_TAG_LENGTH_OFFSET) : \ + 0) + /* The maximum size of an RSA key on this implementation, in bits. * This is a vendor-specific macro. * @@ -236,6 +292,22 @@ (plaintext_length) - PSA_AEAD_TAG_LENGTH(alg) : \ 0) +#define PSA_RSA_MINIMUM_PADDING_SIZE(alg) \ + (PSA_ALG_IS_RSA_OAEP(alg) ? \ + 2 * PSA_HASH_FINAL_SIZE(PSA_ALG_RSA_OAEP_GET_HASH(alg)) + 1 : \ + 11 /*PKCS#1v1.5*/) + +/** + * \brief ECDSA signature size for a given curve bit size + * + * \param curve_bits Curve size in bits. + * \return Signature size in bytes. + * + * \note This macro returns a compile-time constant if its argument is one. + */ +#define PSA_ECDSA_SIGNATURE_SIZE(curve_bits) \ + (PSA_BITS_TO_BYTES(curve_bits) * 2) + /** Safe signature buffer size for psa_asymmetric_sign(). * * This macro returns a safe buffer size for a signature using a key @@ -345,25 +417,16 @@ /* Maximum size of the export encoding of an RSA public key. * Assumes that the public exponent is less than 2^32. * - * SubjectPublicKeyInfo ::= SEQUENCE { - * algorithm AlgorithmIdentifier, - * subjectPublicKey BIT STRING } -- contains RSAPublicKey - * AlgorithmIdentifier ::= SEQUENCE { - * algorithm OBJECT IDENTIFIER, - * parameters NULL } * RSAPublicKey ::= SEQUENCE { * modulus INTEGER, -- n * publicExponent INTEGER } -- e * - * - 3 * 4 bytes of SEQUENCE overhead; - * - 1 + 1 + 9 bytes of algorithm (RSA OID); - * - 2 bytes of NULL; - * - 4 bytes of BIT STRING overhead; + * - 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) + 36) + (PSA_KEY_EXPORT_ASN1_INTEGER_MAX_SIZE(key_bits) + 11) /* Maximum size of the export encoding of an RSA key pair. * Assumes thatthe public exponent is less than 2^32 and that the size @@ -430,26 +493,16 @@ /* Maximum size of the export encoding of an ECC public key. * - * SubjectPublicKeyInfo ::= SEQUENCE { - * algorithm AlgorithmIdentifier, - * subjectPublicKey BIT STRING } -- contains ECPoint - * AlgorithmIdentifier ::= SEQUENCE { - * algorithm OBJECT IDENTIFIER, - * parameters OBJECT IDENTIFIER } -- namedCurve - * ECPoint ::= ... - * -- first 8 bits: 0x04; - * -- then x_P as a `ceiling(m/8)`-byte string, big endian; - * -- then y_P as a `ceiling(m/8)`-byte string, big endian; - * -- where `m` is the bit size associated with the curve. - * - * - 2 * 4 bytes of SEQUENCE overhead; - * - 1 + 1 + 7 bytes of algorithm (id-ecPublicKey OID); - * - 1 + 1 + 12 bytes of namedCurve OID; - * - 4 bytes of BIT STRING overhead; - * - 1 byte + 2 * point size in ECPoint. + * The representation of an ECC public key is: + * - The byte 0x04; + * - `x_P` as a `ceiling(m/8)`-byte string, big-endian; + * - `y_P` as a `ceiling(m/8)`-byte string, big-endian; + * - where m is the bit size associated with the curve. + * + * - 1 byte + 2 * point size. */ #define PSA_KEY_EXPORT_ECC_PUBLIC_KEY_MAX_SIZE(key_bits) \ - (2 * PSA_BITS_TO_BYTES(key_bits) + 36) + (2 * PSA_BITS_TO_BYTES(key_bits) + 1) /* Maximum size of the export encoding of an ECC key pair. * diff --git a/features/mbedtls/mbed-crypto/inc/psa/crypto_types.h b/features/mbedtls/mbed-crypto/inc/psa/crypto_types.h new file mode 100644 index 00000000000..9b44d6aef9e --- /dev/null +++ b/features/mbedtls/mbed-crypto/inc/psa/crypto_types.h @@ -0,0 +1,101 @@ +/** + * \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 (C) 2018, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ + +#ifndef PSA_CRYPTO_TYPES_H +#define PSA_CRYPTO_TYPES_H + +#include + +/** \defgroup error Error codes + * @{ + */ + +/** + * \brief Function return status. + * + * This is either #PSA_SUCCESS (which is zero), indicating success, + * or a nonzero value indicating that an error occurred. Errors are + * encoded as one of the \c PSA_ERROR_xxx values defined here. + */ +typedef int32_t psa_status_t; + +/**@}*/ + +/** \defgroup crypto_types Key and algorithm types + * @{ + */ + +/** \brief Encoding of a key type. + */ +typedef uint32_t psa_key_type_t; + +/** The type of PSA elliptic curve identifiers. */ +typedef uint16_t psa_ecc_curve_t; + +/** \brief Encoding of a cryptographic algorithm. + * + * 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. + */ +typedef uint32_t psa_algorithm_t; + +/**@}*/ + +/** \defgroup key_lifetimes Key lifetimes + * @{ + */ + +/** Encoding of key lifetimes. + */ +typedef uint32_t psa_key_lifetime_t; + +/** Encoding of identifiers of persistent keys. + */ +typedef uint32_t psa_key_id_t; + +/**@}*/ + +/** \defgroup policy Key policies + * @{ + */ + +/** \brief Encoding of permitted usage on a key. */ +typedef uint32_t psa_key_usage_t; + +/**@}*/ + +#endif /* PSA_CRYPTO_TYPES_H */ diff --git a/features/mbedtls/mbed-crypto/inc/psa/crypto_values.h b/features/mbedtls/mbed-crypto/inc/psa/crypto_values.h new file mode 100644 index 00000000000..4d25835be52 --- /dev/null +++ b/features/mbedtls/mbed-crypto/inc/psa/crypto_values.h @@ -0,0 +1,1420 @@ +/** + * \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. + * + * This header file only defines preprocessor macros. + */ +/* + * Copyright (C) 2018, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ + +#ifndef PSA_CRYPTO_VALUES_H +#define PSA_CRYPTO_VALUES_H + +/** \defgroup error Error codes + * @{ + */ + +#if !defined(PSA_SUCCESS) +/* If PSA_SUCCESS is defined, assume that PSA crypto is being used + * together with PSA IPC, which also defines the identifier + * PSA_SUCCESS. We must not define PSA_SUCCESS ourselves in that case; + * the other error code names don't clash. This is a temporary hack + * until we unify error reporting in PSA IPC and PSA crypto. + * + * Note that psa_defs.h must be included before this header! + */ +/** The action was completed successfully. */ +#define PSA_SUCCESS ((psa_status_t)0) +#endif /* !defined(PSA_SUCCESS) */ + +/** 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_UNKNOWN_ERROR ((psa_status_t)1) + +/** 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)2) + +/** 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)3) + +/** 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)4) + +/** A slot is occupied, but must be empty to carry out the + * requested action. + * + * If a handle is invalid, it does not designate an occupied slot. + * The error for an invalid handle is #PSA_ERROR_INVALID_HANDLE. + */ +#define PSA_ERROR_OCCUPIED_SLOT ((psa_status_t)5) + +/** A slot is empty, but must be occupied to carry out the + * requested action. + * + * If a handle is invalid, it does not designate an empty slot. + * The error for an invalid handle is #PSA_ERROR_INVALID_HANDLE. + */ +#define PSA_ERROR_EMPTY_SLOT ((psa_status_t)6) + +/** 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 slot is occupied when it needs to be free or vice versa, + * but shall return #PSA_ERROR_OCCUPIED_SLOT or #PSA_ERROR_EMPTY_SLOT + * as applicable. */ +#define PSA_ERROR_BAD_STATE ((psa_status_t)7) + +/** 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 slot is occupied when it needs to be free or vice versa, + * but shall return #PSA_ERROR_OCCUPIED_SLOT or #PSA_ERROR_EMPTY_SLOT + * as applicable. + * + * Implementation shall not return this error code to indicate that a + * key handle is invalid, but shall return #PSA_ERROR_INVALID_HANDLE + * instead. + */ +#define PSA_ERROR_INVALID_ARGUMENT ((psa_status_t)8) + +/** 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)9) + +/** 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)10) + +/** 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 whenver + * 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)11) + +/** 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_TAMPERING_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 canont 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)12) + +/** 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)13) + +/** 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_TAMPERING_DETECTED ((psa_status_t)14) + +/** 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)15) + +/** 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)16) + +/** 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)17) + +/** The generator has insufficient capacity left. + * + * Once a function returns this error, attempts to read from the + * generator will always return this error. */ +#define PSA_ERROR_INSUFFICIENT_CAPACITY ((psa_status_t)18) + +/** The key handle is not valid. + */ +#define PSA_ERROR_INVALID_HANDLE ((psa_status_t)19) + +/**@}*/ + +/** \defgroup crypto_types Key and algorithm types + * @{ + */ + +/** An invalid key type value. + * + * Zero is not the encoding of any key type. + */ +#define PSA_KEY_TYPE_NONE ((psa_key_type_t)0x00000000) + +/** Vendor-defined 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)0x80000000) + +#define PSA_KEY_TYPE_CATEGORY_MASK ((psa_key_type_t)0x70000000) +#define PSA_KEY_TYPE_CATEGORY_SYMMETRIC ((psa_key_type_t)0x40000000) +#define PSA_KEY_TYPE_CATEGORY_RAW ((psa_key_type_t)0x50000000) +#define PSA_KEY_TYPE_CATEGORY_PUBLIC_KEY ((psa_key_type_t)0x60000000) +#define PSA_KEY_TYPE_CATEGORY_KEY_PAIR ((psa_key_type_t)0x70000000) + +#define PSA_KEY_TYPE_CATEGORY_FLAG_PAIR ((psa_key_type_t)0x10000000) + +/** Whether a key type is vendor-defined. */ +#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_t)0x10000000) == \ + 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_KEYPAIR(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_KEYPAIR_OF_PUBLIC_KEY(type) \ + ((type) | PSA_KEY_TYPE_CATEGORY_FLAG_PAIR) +/** The public key type corresponding to a key pair type. + * + * You may also pass a key pair type as \p type, it will be left unchanged. + * + * \param type A public key type or key pair type. + * + * \return The corresponding public key type. + * If \p type is not a public key or a key pair, + * the return value is undefined. + */ +#define PSA_KEY_TYPE_PUBLIC_KEY_OF_KEYPAIR(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)0x50000001) + +/** 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_SIZE(\c alg) where + * \c alg is the HMAC algorithm or the underlying hash algorithm. */ +#define PSA_KEY_TYPE_HMAC ((psa_key_type_t)0x51000000) + +/** A secret for key derivation. + * + * The key policy determines which key derivation algorithm the key + * can be used for. + */ +#define PSA_KEY_TYPE_DERIVE ((psa_key_type_t)0x52000000) + +/** Key for an 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)0x40000001) + +/** Key for a cipher or MAC algorithm based on DES or 3DES (Triple-DES). + * + * The size of the key can be 8 bytes (single DES), 16 bytes (2-key 3DES) or + * 24 bytes (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)0x40000002) + +/** Key for an cipher, AEAD or MAC algorithm based on the + * Camellia block cipher. */ +#define PSA_KEY_TYPE_CAMELLIA ((psa_key_type_t)0x40000003) + +/** Key for the RC4 stream cipher. + * + * Note that RC4 is weak and deprecated and should only be used in + * legacy protocols. */ +#define PSA_KEY_TYPE_ARC4 ((psa_key_type_t)0x40000004) + +/** RSA public key. */ +#define PSA_KEY_TYPE_RSA_PUBLIC_KEY ((psa_key_type_t)0x60010000) +/** RSA key pair (private and public key). */ +#define PSA_KEY_TYPE_RSA_KEYPAIR ((psa_key_type_t)0x70010000) +/** 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_KEYPAIR(type) == PSA_KEY_TYPE_RSA_PUBLIC_KEY) + +/** DSA public key. */ +#define PSA_KEY_TYPE_DSA_PUBLIC_KEY ((psa_key_type_t)0x60020000) +/** DSA key pair (private and public key). */ +#define PSA_KEY_TYPE_DSA_KEYPAIR ((psa_key_type_t)0x70020000) +/** Whether a key type is an DSA key (pair or public-only). */ +#define PSA_KEY_TYPE_IS_DSA(type) \ + (PSA_KEY_TYPE_PUBLIC_KEY_OF_KEYPAIR(type) == PSA_KEY_TYPE_DSA_PUBLIC_KEY) + +#define PSA_KEY_TYPE_ECC_PUBLIC_KEY_BASE ((psa_key_type_t)0x60030000) +#define PSA_KEY_TYPE_ECC_KEYPAIR_BASE ((psa_key_type_t)0x70030000) +#define PSA_KEY_TYPE_ECC_CURVE_MASK ((psa_key_type_t)0x0000ffff) +/** Elliptic curve key pair. */ +#define PSA_KEY_TYPE_ECC_KEYPAIR(curve) \ + (PSA_KEY_TYPE_ECC_KEYPAIR_BASE | (curve)) +/** Elliptic curve public key. */ +#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_KEYPAIR(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_KEYPAIR(type) \ + (((type) & ~PSA_KEY_TYPE_ECC_CURVE_MASK) == \ + PSA_KEY_TYPE_ECC_KEYPAIR_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_GET_CURVE(type) \ + ((psa_ecc_curve_t) (PSA_KEY_TYPE_IS_ECC(type) ? \ + ((type) & PSA_KEY_TYPE_ECC_CURVE_MASK) : \ + 0)) + +/* The encoding of curve identifiers is currently aligned with the + * TLS Supported Groups Registry (formerly known as the + * TLS EC Named Curve Registry) + * https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#tls-parameters-8 + * The values are defined by RFC 8422 and RFC 7027. */ +#define PSA_ECC_CURVE_SECT163K1 ((psa_ecc_curve_t) 0x0001) +#define PSA_ECC_CURVE_SECT163R1 ((psa_ecc_curve_t) 0x0002) +#define PSA_ECC_CURVE_SECT163R2 ((psa_ecc_curve_t) 0x0003) +#define PSA_ECC_CURVE_SECT193R1 ((psa_ecc_curve_t) 0x0004) +#define PSA_ECC_CURVE_SECT193R2 ((psa_ecc_curve_t) 0x0005) +#define PSA_ECC_CURVE_SECT233K1 ((psa_ecc_curve_t) 0x0006) +#define PSA_ECC_CURVE_SECT233R1 ((psa_ecc_curve_t) 0x0007) +#define PSA_ECC_CURVE_SECT239K1 ((psa_ecc_curve_t) 0x0008) +#define PSA_ECC_CURVE_SECT283K1 ((psa_ecc_curve_t) 0x0009) +#define PSA_ECC_CURVE_SECT283R1 ((psa_ecc_curve_t) 0x000a) +#define PSA_ECC_CURVE_SECT409K1 ((psa_ecc_curve_t) 0x000b) +#define PSA_ECC_CURVE_SECT409R1 ((psa_ecc_curve_t) 0x000c) +#define PSA_ECC_CURVE_SECT571K1 ((psa_ecc_curve_t) 0x000d) +#define PSA_ECC_CURVE_SECT571R1 ((psa_ecc_curve_t) 0x000e) +#define PSA_ECC_CURVE_SECP160K1 ((psa_ecc_curve_t) 0x000f) +#define PSA_ECC_CURVE_SECP160R1 ((psa_ecc_curve_t) 0x0010) +#define PSA_ECC_CURVE_SECP160R2 ((psa_ecc_curve_t) 0x0011) +#define PSA_ECC_CURVE_SECP192K1 ((psa_ecc_curve_t) 0x0012) +#define PSA_ECC_CURVE_SECP192R1 ((psa_ecc_curve_t) 0x0013) +#define PSA_ECC_CURVE_SECP224K1 ((psa_ecc_curve_t) 0x0014) +#define PSA_ECC_CURVE_SECP224R1 ((psa_ecc_curve_t) 0x0015) +#define PSA_ECC_CURVE_SECP256K1 ((psa_ecc_curve_t) 0x0016) +#define PSA_ECC_CURVE_SECP256R1 ((psa_ecc_curve_t) 0x0017) +#define PSA_ECC_CURVE_SECP384R1 ((psa_ecc_curve_t) 0x0018) +#define PSA_ECC_CURVE_SECP521R1 ((psa_ecc_curve_t) 0x0019) +#define PSA_ECC_CURVE_BRAINPOOL_P256R1 ((psa_ecc_curve_t) 0x001a) +#define PSA_ECC_CURVE_BRAINPOOL_P384R1 ((psa_ecc_curve_t) 0x001b) +#define PSA_ECC_CURVE_BRAINPOOL_P512R1 ((psa_ecc_curve_t) 0x001c) +#define PSA_ECC_CURVE_CURVE25519 ((psa_ecc_curve_t) 0x001d) +#define PSA_ECC_CURVE_CURVE448 ((psa_ecc_curve_t) 0x001e) + +/** 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_SIZE(type) \ + ( \ + (type) == PSA_KEY_TYPE_AES ? 16 : \ + (type) == PSA_KEY_TYPE_DES ? 8 : \ + (type) == PSA_KEY_TYPE_CAMELLIA ? 16 : \ + (type) == PSA_KEY_TYPE_ARC4 ? 1 : \ + 0) + +#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)0x01000000) +#define PSA_ALG_CATEGORY_MAC ((psa_algorithm_t)0x02000000) +#define PSA_ALG_CATEGORY_CIPHER ((psa_algorithm_t)0x04000000) +#define PSA_ALG_CATEGORY_AEAD ((psa_algorithm_t)0x06000000) +#define PSA_ALG_CATEGORY_SIGN ((psa_algorithm_t)0x10000000) +#define PSA_ALG_CATEGORY_ASYMMETRIC_ENCRYPTION ((psa_algorithm_t)0x12000000) +#define PSA_ALG_CATEGORY_KEY_AGREEMENT ((psa_algorithm_t)0x22000000) +#define PSA_ALG_CATEGORY_KEY_DERIVATION ((psa_algorithm_t)0x30000000) +#define PSA_ALG_CATEGORY_KEY_SELECTION ((psa_algorithm_t)0x31000000) + +#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 a public-key signature algorithm. + * + * \param alg An algorithm identifier (value of type #psa_algorithm_t). + * + * \return 1 if \p alg is a public-key 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 a public-key encryption algorithm. + * + * \param alg An algorithm identifier (value of type #psa_algorithm_t). + * + * \return 1 if \p alg is a public-key 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) + +#define PSA_ALG_KEY_SELECTION_FLAG ((psa_algorithm_t)0x01000000) +/** 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_KEY_SELECTION_FLAG) == \ + 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 selection algorithm. + * + * \param alg An algorithm identifier (value of type #psa_algorithm_t). + * + * \return 1 if \p alg is a key selection 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_SELECTION(alg) \ + (((alg) & PSA_ALG_CATEGORY_MASK) == PSA_ALG_CATEGORY_KEY_SELECTION) + +#define PSA_ALG_HASH_MASK ((psa_algorithm_t)0x000000ff) +#define PSA_ALG_MD2 ((psa_algorithm_t)0x01000001) +#define PSA_ALG_MD4 ((psa_algorithm_t)0x01000002) +#define PSA_ALG_MD5 ((psa_algorithm_t)0x01000003) +#define PSA_ALG_RIPEMD160 ((psa_algorithm_t)0x01000004) +#define PSA_ALG_SHA_1 ((psa_algorithm_t)0x01000005) +/** SHA2-224 */ +#define PSA_ALG_SHA_224 ((psa_algorithm_t)0x01000008) +/** SHA2-256 */ +#define PSA_ALG_SHA_256 ((psa_algorithm_t)0x01000009) +/** SHA2-384 */ +#define PSA_ALG_SHA_384 ((psa_algorithm_t)0x0100000a) +/** SHA2-512 */ +#define PSA_ALG_SHA_512 ((psa_algorithm_t)0x0100000b) +/** SHA2-512/224 */ +#define PSA_ALG_SHA_512_224 ((psa_algorithm_t)0x0100000c) +/** SHA2-512/256 */ +#define PSA_ALG_SHA_512_256 ((psa_algorithm_t)0x0100000d) +/** SHA3-224 */ +#define PSA_ALG_SHA3_224 ((psa_algorithm_t)0x01000010) +/** SHA3-256 */ +#define PSA_ALG_SHA3_256 ((psa_algorithm_t)0x01000011) +/** SHA3-384 */ +#define PSA_ALG_SHA3_384 ((psa_algorithm_t)0x01000012) +/** SHA3-512 */ +#define PSA_ALG_SHA3_512 ((psa_algorithm_t)0x01000013) + +#define PSA_ALG_MAC_SUBCATEGORY_MASK ((psa_algorithm_t)0x00c00000) +#define PSA_ALG_HMAC_BASE ((psa_algorithm_t)0x02800000) +/** 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 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)0x00003f00) +#define PSA_MAC_TRUNCATION_OFFSET 8 + +/** 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 alg A MAC algorithm identifier (value of type + * #psa_algorithm_t such that #PSA_ALG_IS_MAC(\p 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 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(alg, mac_length) \ + (((alg) & ~PSA_ALG_MAC_TRUNCATION_MASK) | \ + ((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 alg A MAC algorithm identifier (value of type + * #psa_algorithm_t such that #PSA_ALG_IS_MAC(\p alg) + * is true). This may be a truncated or untruncated + * MAC algorithm. + * + * \return The corresponding base MAC algorithm. + * \return Unspecified if \p alg is not a supported + * MAC algorithm. + */ +#define PSA_ALG_FULL_LENGTH_MAC(alg) \ + ((alg) & ~PSA_ALG_MAC_TRUNCATION_MASK) + +/** Length to which a MAC algorithm is truncated. + * + * \param alg A MAC algorithm identifier (value of type + * #psa_algorithm_t such that #PSA_ALG_IS_MAC(\p alg) + * is true). + * + * \return Length of the truncated MAC in bytes. + * \return 0 if \p alg is a non-truncated MAC algorithm. + * \return Unspecified if \p alg is not a supported + * MAC algorithm. + */ +#define PSA_MAC_TRUNCATED_LENGTH(alg) \ + (((alg) & PSA_ALG_MAC_TRUNCATION_MASK) >> PSA_MAC_TRUNCATION_OFFSET) + +#define PSA_ALG_CIPHER_MAC_BASE ((psa_algorithm_t)0x02c00000) +#define PSA_ALG_CBC_MAC ((psa_algorithm_t)0x02c00001) +#define PSA_ALG_CMAC ((psa_algorithm_t)0x02c00002) +#define PSA_ALG_GMAC ((psa_algorithm_t)0x02c00003) + +/** 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 ARC4 stream cipher algorithm. + */ +#define PSA_ALG_ARC4 ((psa_algorithm_t)0x04800001) + +/** 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)0x04c00001) + +#define PSA_ALG_CFB ((psa_algorithm_t)0x04c00002) + +#define PSA_ALG_OFB ((psa_algorithm_t)0x04c00003) + +/** 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)0x044000ff) + +/** 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)0x04600100) + +/** 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)0x04600101) + +#define PSA_ALG_CCM ((psa_algorithm_t)0x06001001) +#define PSA_ALG_GCM ((psa_algorithm_t)0x06001002) + +/* In the encoding of a 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)0x00003f00) +#define PSA_AEAD_TAG_LENGTH_OFFSET 8 + +/** 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 alg A AEAD algorithm identifier (value of type + * #psa_algorithm_t such that #PSA_ALG_IS_AEAD(\p 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 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_TAG_LENGTH(alg, tag_length) \ + (((alg) & ~PSA_ALG_AEAD_TAG_LENGTH_MASK) | \ + ((tag_length) << PSA_AEAD_TAG_LENGTH_OFFSET & \ + PSA_ALG_AEAD_TAG_LENGTH_MASK)) + +/** Calculate the corresponding AEAD algorithm with the default tag length. + * + * \param alg An AEAD algorithm (\c PSA_ALG_XXX value such that + * #PSA_ALG_IS_AEAD(\p alg) is true). + * + * \return The corresponding AEAD algorithm with the default tag length + * for that algorithm. + */ +#define PSA_ALG_AEAD_WITH_DEFAULT_TAG_LENGTH(alg) \ + ( \ + PSA__ALG_AEAD_WITH_DEFAULT_TAG_LENGTH__CASE(alg, PSA_ALG_CCM) \ + PSA__ALG_AEAD_WITH_DEFAULT_TAG_LENGTH__CASE(alg, PSA_ALG_GCM) \ + 0) +#define PSA__ALG_AEAD_WITH_DEFAULT_TAG_LENGTH__CASE(alg, ref) \ + PSA_ALG_AEAD_WITH_TAG_LENGTH(alg, 0) == \ + PSA_ALG_AEAD_WITH_TAG_LENGTH(ref, 0) ? \ + ref : + +#define PSA_ALG_RSA_PKCS1V15_SIGN_BASE ((psa_algorithm_t)0x10020000) +/** 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). + * + * \return The corresponding RSA PKCS#1 v1.5 signature algorithm. + * \return Unspecified if \p 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)0x10030000) +/** 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. 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). + * + * \return The corresponding RSA PSS signature algorithm. + * \return Unspecified if \p 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)) +#define PSA_ALG_IS_RSA_PSS(alg) \ + (((alg) & ~PSA_ALG_HASH_MASK) == PSA_ALG_RSA_PSS_BASE) + +#define PSA_ALG_DSA_BASE ((psa_algorithm_t)0x10040000) +/** 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). + * + * \return The corresponding DSA signature algorithm. + * \return Unspecified if \p 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)0x10050000) +#define PSA_ALG_DSA_DETERMINISTIC_FLAG ((psa_algorithm_t)0x00010000) +#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)) + +#define PSA_ALG_ECDSA_BASE ((psa_algorithm_t)0x10060000) +/** 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 concatentation 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). + * + * \return The corresponding ECDSA signature algorithm. + * \return Unspecified if \p 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)0x10070000) +/** 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). + * + * \return The corresponding deterministic ECDSA signature + * algorithm. + * \return Unspecified if \p 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_IS_ECDSA(alg) \ + (((alg) & ~PSA_ALG_HASH_MASK & ~PSA_ALG_DSA_DETERMINISTIC_FLAG) == \ + PSA_ALG_ECDSA_BASE) +#define PSA_ALG_ECDSA_IS_DETERMINISTIC(alg) \ + (((alg) & PSA_ALG_DSA_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)) + +/** 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_RSA_PSS(alg) || PSA_ALG_IS_RSA_PKCS1V15_SIGN(alg) || \ + PSA_ALG_IS_DSA(alg) || PSA_ALG_IS_ECDSA(alg) ? \ + ((alg) & PSA_ALG_HASH_MASK) == 0 ? /*"raw" algorithm*/ 0 : \ + ((alg) & PSA_ALG_HASH_MASK) | PSA_ALG_CATEGORY_HASH : \ + 0) + +/** RSA PKCS#1 v1.5 encryption. + */ +#define PSA_ALG_RSA_PKCS1V15_CRYPT ((psa_algorithm_t)0x12020000) + +#define PSA_ALG_RSA_OAEP_BASE ((psa_algorithm_t)0x12030000) +/** 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 signature algorithm. + * \return Unspecified if \p 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)0x30000100) +/** Macro to build an HKDF algorithm. + * + * For example, `PSA_ALG_HKDF(PSA_ALG_SHA256)` is HKDF 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 HKDF algorithm. + * \return Unspecified if \p 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_TLS12_PRF_BASE ((psa_algorithm_t)0x30000200) +/** 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. + * + * For the application to TLS-1.2, the salt and label arguments passed + * to psa_key_derivation() are what's called 'seed' and 'label' in RFC 5246, + * respectively. For example, for TLS key expansion, the salt is the + * concatenation of ServerHello.Random + ClientHello.Random, + * while the label is "key expansion". + * + * For example, `PSA_ALG_TLS12_PRF(PSA_ALG_SHA256)` 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 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)0x30000300) +/** 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. + * + * For the application to TLS-1.2, the salt passed to psa_key_derivation() + * (and forwarded to the TLS-1.2 PRF) is the concatenation of the + * ClientHello.Random + ServerHello.Random, while the label is "master secret" + * or "extended master secret". + * + * For example, `PSA_ALG_TLS12_PSK_TO_MS(PSA_ALG_SHA256)` 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 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)) + +#define PSA_ALG_KEY_DERIVATION_MASK ((psa_algorithm_t)0x010fffff) + +/** Use a shared secret as is. + * + * Specify this algorithm as the selection component of a key agreement + * to use the raw result of the key agreement as key material. + * + * \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 can however be used as the secret + * input in a key derivation algorithm. + */ +#define PSA_ALG_SELECT_RAW ((psa_algorithm_t)0x31000001) + +#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_DERIVATION_MASK) + +#define PSA_ALG_FFDH_BASE ((psa_algorithm_t)0x22100000) +/** The Diffie-Hellman key agreement algorithm. + * + * This algorithm combines the finite-field Diffie-Hellman (DH) key + * agreement, also known as Diffie-Hellman-Merkle (DHM) key agreement, + * to produce a shared secret from a private key and the peer's + * public key, with a key selection or key derivation algorithm to produce + * one or more shared keys and other shared cryptographic material. + * + * The shared secret produced by key agreement and passed as input to the + * derivation or selection algorithm \p kdf_alg is the shared secret + * `g^{ab}` in big-endian format. + * It is `ceiling(m / 8)` bytes long where `m` is the size of the prime `p` + * in bits. + * + * \param kdf_alg A key derivation algorithm (\c PSA_ALG_XXX value such + * that #PSA_ALG_IS_KEY_DERIVATION(\p hash_alg) is true) + * or a key selection algorithm (\c PSA_ALG_XXX value such + * that #PSA_ALG_IS_KEY_SELECTION(\p hash_alg) is true). + * + * \return The Diffie-Hellman algorithm with the specified + * selection or derivation algorithm. + */ +#define PSA_ALG_FFDH(kdf_alg) \ + (PSA_ALG_FFDH_BASE | ((kdf_alg) & PSA_ALG_KEY_DERIVATION_MASK)) +/** Whether the specified algorithm is a finite field Diffie-Hellman algorithm. + * + * This includes every supported key selection or key agreement algorithm + * for the output of the Diffie-Hellman calculation. + * + * \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_BASE) + +#define PSA_ALG_ECDH_BASE ((psa_algorithm_t)0x22200000) +/** The elliptic curve Diffie-Hellman (ECDH) key agreement algorithm. + * + * This algorithm combines the elliptic curve Diffie-Hellman key + * agreement to produce a shared secret from a private key and the peer's + * public key, with a key selection or key derivation algorithm to produce + * one or more shared keys and other shared cryptographic material. + * + * The shared secret produced by key agreement and passed as input to the + * derivation or selection algorithm \p kdf_alg 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_CURVE_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_CURVE_SECPXXX` and `PSA_ECC_CURVE_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_CURVE_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}`. + * + * \param kdf_alg A key derivation algorithm (\c PSA_ALG_XXX value such + * that #PSA_ALG_IS_KEY_DERIVATION(\p hash_alg) is true) + * or a selection algorithm (\c PSA_ALG_XXX value such + * that #PSA_ALG_IS_KEY_SELECTION(\p hash_alg) is true). + * + * \return The Diffie-Hellman algorithm with the specified + * selection or derivation algorithm. + */ +#define PSA_ALG_ECDH(kdf_alg) \ + (PSA_ALG_ECDH_BASE | ((kdf_alg) & PSA_ALG_KEY_DERIVATION_MASK)) +/** Whether the specified algorithm is an elliptic curve Diffie-Hellman + * algorithm. + * + * This includes every supported key selection or key agreement algorithm + * for the output of the Diffie-Hellman calculation. + * + * \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_BASE) + +/**@}*/ + +/** \defgroup key_lifetimes Key lifetimes + * @{ + */ + +/** A volatile key only exists as long as the handle to it is not closed. + * The key material is guaranteed to be erased on a power reset. + */ +#define PSA_KEY_LIFETIME_VOLATILE ((psa_key_lifetime_t)0x00000000) + +/** The default storage area 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 implementations 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. Implementations may offer other storage areas designated + * by other lifetime values as implementation-specific extensions. + */ +#define PSA_KEY_LIFETIME_PERSISTENT ((psa_key_lifetime_t)0x00000001) + +/**@}*/ + +/** \defgroup policy Key policies + * @{ + */ + +/** 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 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 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 ((psa_key_usage_t)0x00000400) + +/** 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 by the key's type and policy. + * + * For a key pair, this concerns the public key. + */ +#define PSA_KEY_USAGE_VERIFY ((psa_key_usage_t)0x00000800) + +/** Whether the key may be used to derive other keys. + */ +#define PSA_KEY_USAGE_DERIVE ((psa_key_usage_t)0x00001000) + +/**@}*/ + +#endif /* PSA_CRYPTO_VALUES_H */ diff --git a/features/mbedtls/mbed-crypto/platform/TARGET_PSA/COMPONENT_PSA_SRV_IMPL/COMPONENT_NSPE/crypto_struct.h b/features/mbedtls/mbed-crypto/platform/TARGET_PSA/COMPONENT_PSA_SRV_IMPL/COMPONENT_NSPE/crypto_struct.h index 44a1a60572f..ee3ecd776cd 100644 --- a/features/mbedtls/mbed-crypto/platform/TARGET_PSA/COMPONENT_PSA_SRV_IMPL/COMPONENT_NSPE/crypto_struct.h +++ b/features/mbedtls/mbed-crypto/platform/TARGET_PSA/COMPONENT_PSA_SRV_IMPL/COMPONENT_NSPE/crypto_struct.h @@ -85,6 +85,13 @@ struct psa_hash_operation_s } ctx; }; +#define PSA_HASH_OPERATION_INIT {0, {0}} +static inline struct psa_hash_operation_s psa_hash_operation_init( void ) +{ + const struct psa_hash_operation_s v = PSA_HASH_OPERATION_INIT; + return( v ); +} + #if defined(MBEDTLS_MD_C) typedef struct { @@ -116,6 +123,13 @@ struct psa_mac_operation_s } ctx; }; +#define PSA_MAC_OPERATION_INIT {0, 0, 0, 0, 0, 0, 0, {0}} +static inline struct psa_mac_operation_s psa_mac_operation_init( void ) +{ + const struct psa_mac_operation_s v = PSA_MAC_OPERATION_INIT; + return( v ); +} + struct psa_cipher_operation_s { psa_algorithm_t alg; @@ -126,10 +140,18 @@ struct psa_cipher_operation_s uint8_t block_size; union { + unsigned dummy; /* Enable easier initializing of the union. */ mbedtls_cipher_context_t cipher; } ctx; }; +#define PSA_CIPHER_OPERATION_INIT {0, 0, 0, 0, 0, 0, {0}} +static inline struct psa_cipher_operation_s psa_cipher_operation_init( void ) +{ + const struct psa_cipher_operation_s v = PSA_CIPHER_OPERATION_INIT; + return( v ); +} + #if defined(MBEDTLS_MD_C) typedef struct { @@ -208,4 +230,11 @@ struct psa_key_policy_s psa_algorithm_t alg; }; +#define PSA_KEY_POLICY_INIT {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 ); +} + #endif /* PSA_CRYPTO_STRUCT_H */ diff --git a/features/mbedtls/mbed-crypto/platform/TARGET_PSA/COMPONENT_PSA_SRV_IMPL/psa_crypto.c b/features/mbedtls/mbed-crypto/platform/TARGET_PSA/COMPONENT_PSA_SRV_IMPL/psa_crypto.c index fc296d36557..58e82fa2e57 100644 --- a/features/mbedtls/mbed-crypto/platform/TARGET_PSA/COMPONENT_PSA_SRV_IMPL/psa_crypto.c +++ b/features/mbedtls/mbed-crypto/platform/TARGET_PSA/COMPONENT_PSA_SRV_IMPL/psa_crypto.c @@ -27,15 +27,16 @@ #if defined(MBEDTLS_PSA_CRYPTO_C) /* - * In case MBEDTLS_PSA_CRYPTO_SPM is defined the code is built for SPM (Secure - * Partition Manager) integration which separate the code into two parts - * NSPE (Non-Secure Process Environment) and SPE (Secure Process Environment). - * In this mode an additional header file should be included. + * 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) /* - * PSA_CRYPTO_SECURE means that this file is compiled to the SPE side. - * some headers will be affected by this flag. + * PSA_CRYPTO_SECURE means that this file is compiled for the SPE. + * Some headers will be affected by this flag. */ #define PSA_CRYPTO_SECURE 1 #include "crypto_spe.h" @@ -43,6 +44,9 @@ #include "psa/crypto.h" +#include "psa_crypto_core.h" +#include "psa_crypto_invasive.h" +#include "psa_crypto_slot_management.h" /* Include internal declarations that are useful for implementing persistently * stored keys. */ #include "psa_crypto_storage.h" @@ -58,6 +62,7 @@ #include "mbedtls/arc4.h" #include "mbedtls/asn1.h" +#include "mbedtls/asn1write.h" #include "mbedtls/bignum.h" #include "mbedtls/blowfish.h" #include "mbedtls/camellia.h" @@ -79,6 +84,7 @@ #include "mbedtls/md_internal.h" #include "mbedtls/pk.h" #include "mbedtls/pk_internal.h" +#include "mbedtls/platform_util.h" #include "mbedtls/ripemd160.h" #include "mbedtls/rsa.h" #include "mbedtls/sha1.h" @@ -92,12 +98,6 @@ #define ARRAY_LENGTH( array ) ( sizeof( array ) / sizeof( *( array ) ) ) -/* Implementation that should never be optimized out by the compiler */ -static void mbedtls_zeroize( void *v, size_t n ) -{ - volatile unsigned char *p = v; while( n-- ) *p++ = 0; -} - /* constant-time buffer comparison */ static inline int safer_memcmp( const uint8_t *a, const uint8_t *b, size_t n ) { @@ -116,42 +116,24 @@ static inline int safer_memcmp( const uint8_t *a, const uint8_t *b, size_t n ) /* Global data, support functions and library management */ /****************************************************************/ -/* Number of key slots (plus one because 0 is not used). - * The value is a compile-time constant for now, for simplicity. */ -#define PSA_KEY_SLOT_COUNT 32 - -typedef struct -{ - psa_key_type_t type; - psa_key_policy_t policy; - psa_key_lifetime_t lifetime; - union - { - struct raw_data - { - uint8_t *data; - size_t bytes; - } raw; -#if defined(MBEDTLS_RSA_C) - mbedtls_rsa_context *rsa; -#endif /* MBEDTLS_RSA_C */ -#if defined(MBEDTLS_ECP_C) - mbedtls_ecp_keypair *ecp; -#endif /* MBEDTLS_ECP_C */ - } data; -} key_slot_t; - 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 + typedef struct { - int initialized; + void (* entropy_init )( mbedtls_entropy_context *ctx ); + void (* entropy_free )( mbedtls_entropy_context *ctx ); mbedtls_entropy_context entropy; mbedtls_ctr_drbg_context ctr_drbg; - key_slot_t key_slots[PSA_KEY_SLOT_COUNT]; + unsigned initialized : 1; + unsigned rng_state : 2; } psa_global_data_t; static psa_global_data_t global_data; @@ -531,50 +513,112 @@ static psa_status_t psa_check_rsa_key_byte_aligned( return( status ); } -static psa_status_t psa_import_rsa_key( mbedtls_pk_context *pk, +static psa_status_t psa_import_rsa_key( psa_key_type_t type, + const uint8_t *data, + size_t data_length, mbedtls_rsa_context **p_rsa ) { - if( mbedtls_pk_get_type( pk ) != MBEDTLS_PK_RSA ) - return( PSA_ERROR_INVALID_ARGUMENT ); + psa_status_t status; + mbedtls_pk_context pk; + mbedtls_rsa_context *rsa; + size_t bits; + + mbedtls_pk_init( &pk ); + + /* Parse the data. */ + if( PSA_KEY_TYPE_IS_KEYPAIR( type ) ) + status = mbedtls_to_psa_error( + mbedtls_pk_parse_key( &pk, data, data_length, NULL, 0 ) ); else + status = mbedtls_to_psa_error( + mbedtls_pk_parse_public_key( &pk, data, data_length ) ); + if( status != PSA_SUCCESS ) + goto exit; + + /* We have something that the pkparse module recognizes. If it is a + * valid RSA key, store it. */ + if( mbedtls_pk_get_type( &pk ) != MBEDTLS_PK_RSA ) { - mbedtls_rsa_context *rsa = mbedtls_pk_rsa( *pk ); - /* 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. */ - size_t bits = PSA_BYTES_TO_BITS( mbedtls_rsa_get_len( rsa ) ); - psa_status_t status; - if( bits > PSA_VENDOR_RSA_MAX_KEY_BITS ) - return( PSA_ERROR_NOT_SUPPORTED ); - status = psa_check_rsa_key_byte_aligned( rsa ); - if( status != PSA_SUCCESS ) - return( status ); - *p_rsa = rsa; - return( PSA_SUCCESS ); + status = PSA_ERROR_INVALID_ARGUMENT; + goto exit; } + + rsa = mbedtls_pk_rsa( pk ); + /* 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( rsa ) ); + if( bits > PSA_VENDOR_RSA_MAX_KEY_BITS ) + { + status = PSA_ERROR_NOT_SUPPORTED; + goto exit; + } + status = psa_check_rsa_key_byte_aligned( rsa ); + +exit: + /* Free the content of the pk object only on error. */ + if( status != PSA_SUCCESS ) + { + mbedtls_pk_free( &pk ); + return( status ); + } + + /* On success, store the content of the object in the RSA context. */ + *p_rsa = rsa; + + return( PSA_SUCCESS ); } #endif /* defined(MBEDTLS_RSA_C) && defined(MBEDTLS_PK_PARSE_C) */ -#if defined(MBEDTLS_ECP_C) && defined(MBEDTLS_PK_PARSE_C) -/* Import an elliptic curve parsed by the mbedtls pk module. */ -static psa_status_t psa_import_ecp_key( psa_ecc_curve_t expected_curve, - mbedtls_pk_context *pk, - mbedtls_ecp_keypair **p_ecp ) +#if defined(MBEDTLS_ECP_C) + +/* Import a public key given as the uncompressed representation defined by SEC1 + * 2.3.3 as the content of an ECPoint. */ +static psa_status_t psa_import_ec_public_key( psa_ecc_curve_t curve, + const uint8_t *data, + size_t data_length, + mbedtls_ecp_keypair **p_ecp ) { - if( mbedtls_pk_get_type( pk ) != MBEDTLS_PK_ECKEY ) - return( PSA_ERROR_INVALID_ARGUMENT ); - else + psa_status_t status = PSA_ERROR_TAMPERING_DETECTED; + mbedtls_ecp_keypair *ecp = NULL; + mbedtls_ecp_group_id grp_id = mbedtls_ecc_group_of_psa( curve ); + + *p_ecp = NULL; + ecp = mbedtls_calloc( 1, sizeof( *ecp ) ); + if( ecp == NULL ) + return( PSA_ERROR_INSUFFICIENT_MEMORY ); + mbedtls_ecp_keypair_init( ecp ); + + /* Load the group. */ + status = mbedtls_to_psa_error( + mbedtls_ecp_group_load( &ecp->grp, grp_id ) ); + if( status != PSA_SUCCESS ) + goto exit; + /* 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; + + *p_ecp = ecp; + return( PSA_SUCCESS ); + +exit: + if( ecp != NULL ) { - mbedtls_ecp_keypair *ecp = mbedtls_pk_ec( *pk ); - psa_ecc_curve_t actual_curve = mbedtls_ecc_group_to_psa( ecp->grp.id ); - if( actual_curve != expected_curve ) - return( PSA_ERROR_INVALID_ARGUMENT ); - *p_ecp = ecp; - return( PSA_SUCCESS ); + mbedtls_ecp_keypair_free( ecp ); + mbedtls_free( ecp ); } + return( status ); } -#endif /* defined(MBEDTLS_ECP_C) && defined(MBEDTLS_PK_PARSE_C) */ +#endif /* defined(MBEDTLS_ECP_C) */ #if defined(MBEDTLS_ECP_C) /* Import a private key given as a byte string which is the private value @@ -592,6 +636,7 @@ static psa_status_t psa_import_ec_private_key( psa_ecc_curve_t curve, ecp = mbedtls_calloc( 1, sizeof( mbedtls_ecp_keypair ) ); if( ecp == NULL ) return( PSA_ERROR_INSUFFICIENT_MEMORY ); + mbedtls_ecp_keypair_init( ecp ); /* Load the group. */ status = mbedtls_to_psa_error( @@ -628,9 +673,12 @@ static psa_status_t psa_import_ec_private_key( psa_ecc_curve_t curve, } #endif /* defined(MBEDTLS_ECP_C) */ -static psa_status_t psa_import_key_into_slot( key_slot_t *slot, - const uint8_t *data, - size_t data_length ) +/** Import key data into a slot. `slot->type` must have been set + * previously. This function assumes that the slot does not contain + * any key material yet. On failure, the slot content is unchanged. */ +psa_status_t psa_import_key_into_slot( psa_key_slot_t *slot, + const uint8_t *data, + size_t data_length ) { psa_status_t status = PSA_SUCCESS; @@ -654,126 +702,42 @@ static psa_status_t psa_import_key_into_slot( key_slot_t *slot, status = psa_import_ec_private_key( PSA_KEY_TYPE_GET_CURVE( slot->type ), data, data_length, &slot->data.ecp ); - if( status != PSA_SUCCESS ) - return( status ); + } + else if( PSA_KEY_TYPE_IS_ECC_PUBLIC_KEY( slot->type ) ) + { + status = psa_import_ec_public_key( + PSA_KEY_TYPE_GET_CURVE( slot->type ), + data, data_length, + &slot->data.ecp ); } else #endif /* MBEDTLS_ECP_C */ -#if defined(MBEDTLS_PK_PARSE_C) - if( PSA_KEY_TYPE_IS_RSA( slot->type ) || - PSA_KEY_TYPE_IS_ECC( slot->type ) ) +#if defined(MBEDTLS_RSA_C) && defined(MBEDTLS_PK_PARSE_C) + if( PSA_KEY_TYPE_IS_RSA( slot->type ) ) { - int ret; - mbedtls_pk_context pk; - mbedtls_pk_init( &pk ); - - /* Parse the data. */ - if( PSA_KEY_TYPE_IS_KEYPAIR( slot->type ) ) - ret = mbedtls_pk_parse_key( &pk, data, data_length, NULL, 0 ); - else - ret = mbedtls_pk_parse_public_key( &pk, data, data_length ); - if( ret != 0 ) - return( mbedtls_to_psa_error( ret ) ); - - /* We have something that the pkparse module recognizes. - * If it has the expected type and passes any type-specific - * checks, store it. */ -#if defined(MBEDTLS_RSA_C) - if( PSA_KEY_TYPE_IS_RSA( slot->type ) ) - status = psa_import_rsa_key( &pk, &slot->data.rsa ); - else -#endif /* MBEDTLS_RSA_C */ -#if defined(MBEDTLS_ECP_C) - if( PSA_KEY_TYPE_IS_ECC( slot->type ) ) - status = psa_import_ecp_key( PSA_KEY_TYPE_GET_CURVE( slot->type ), - &pk, &slot->data.ecp ); - else -#endif /* MBEDTLS_ECP_C */ - { - status = PSA_ERROR_NOT_SUPPORTED; - } - - /* Free the content of the pk object only on error. On success, - * the content of the object has been stored in the slot. */ - if( status != PSA_SUCCESS ) - { - mbedtls_pk_free( &pk ); - return( status ); - } + status = psa_import_rsa_key( slot->type, + data, data_length, + &slot->data.rsa ); } else -#endif /* defined(MBEDTLS_PK_PARSE_C) */ +#endif /* defined(MBEDTLS_RSA_C) && defined(MBEDTLS_PK_PARSE_C) */ { return( PSA_ERROR_NOT_SUPPORTED ); } - return( PSA_SUCCESS ); -} - -#if defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) -static psa_status_t psa_load_persistent_key_into_slot( psa_key_slot_t key, - key_slot_t *p_slot ) -{ - psa_status_t status = PSA_SUCCESS; - uint8_t *key_data = NULL; - size_t key_data_length = 0; - - status = psa_load_persistent_key( key, &( p_slot )->type, - &( p_slot )->policy, &key_data, - &key_data_length ); - if( status != PSA_SUCCESS ) - goto exit; - status = psa_import_key_into_slot( p_slot, - key_data, key_data_length ); -exit: - psa_free_persistent_key_data( key_data, key_data_length ); return( status ); } -#endif /* defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) */ - -/* Retrieve a key slot, occupied or not. */ -static psa_status_t psa_get_key_slot( psa_key_slot_t key, - key_slot_t **p_slot ) -{ - GUARD_MODULE_INITIALIZED; - - /* 0 is not a valid slot number under any circumstance. This - * implementation provides slots number 1 to N where N is the - * number of available slots. */ - if( key == 0 || key > ARRAY_LENGTH( global_data.key_slots ) ) - return( PSA_ERROR_INVALID_ARGUMENT ); - - *p_slot = &global_data.key_slots[key - 1]; - -#if defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) - if( ( *p_slot )->lifetime == PSA_KEY_LIFETIME_PERSISTENT ) - { - /* There are two circumstances this can occur: the key material has - * not yet been created, or the key exists in storage but has not yet - * been loaded into memory. */ - if( ( *p_slot )->type == PSA_KEY_TYPE_NONE ) - { - psa_status_t status = PSA_SUCCESS; - status = psa_load_persistent_key_into_slot( key, *p_slot ); - if( status != PSA_ERROR_EMPTY_SLOT ) - return( status ); - } - } -#endif /* defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) */ - - return( PSA_SUCCESS ); -} /* Retrieve an empty key slot (slot with no key data, but possibly * with some metadata such as a policy). */ -static psa_status_t psa_get_empty_key_slot( psa_key_slot_t key, - key_slot_t **p_slot ) +static psa_status_t psa_get_empty_key_slot( psa_key_handle_t handle, + psa_key_slot_t **p_slot ) { psa_status_t status; - key_slot_t *slot = NULL; + psa_key_slot_t *slot = NULL; *p_slot = NULL; - status = psa_get_key_slot( key, &slot ); + status = psa_get_key_slot( handle, &slot ); if( status != PSA_SUCCESS ) return( status ); @@ -787,17 +751,17 @@ static psa_status_t psa_get_empty_key_slot( psa_key_slot_t key, /** Retrieve a slot which must contain a key. 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. */ -static psa_status_t psa_get_key_from_slot( psa_key_slot_t key, - key_slot_t **p_slot, +static psa_status_t psa_get_key_from_slot( psa_key_handle_t handle, + psa_key_slot_t **p_slot, psa_key_usage_t usage, psa_algorithm_t alg ) { psa_status_t status; - key_slot_t *slot = NULL; + psa_key_slot_t *slot = NULL; *p_slot = NULL; - status = psa_get_key_slot( key, &slot ); + status = psa_get_key_slot( handle, &slot ); if( status != PSA_SUCCESS ) return( status ); if( slot->type == PSA_KEY_TYPE_NONE ) @@ -818,7 +782,8 @@ static psa_status_t psa_get_key_from_slot( psa_key_slot_t key, return( PSA_SUCCESS ); } -static psa_status_t psa_remove_key_data_from_memory( key_slot_t *slot ) +/** Wipe key data from a slot. Preserve metadata such as the policy. */ +static psa_status_t psa_remove_key_data_from_memory( psa_key_slot_t *slot ) { if( slot->type == PSA_KEY_TYPE_NONE ) { @@ -854,15 +819,27 @@ static psa_status_t psa_remove_key_data_from_memory( key_slot_t *slot ) return( PSA_SUCCESS ); } -psa_status_t psa_import_key( psa_key_slot_t key, +/** 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 ); + /* 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. */ + memset( slot, 0, sizeof( *slot ) ); + return( status ); +} + +psa_status_t psa_import_key( psa_key_handle_t handle, psa_key_type_t type, const uint8_t *data, size_t data_length ) { - key_slot_t *slot; + psa_key_slot_t *slot; psa_status_t status; - status = psa_get_empty_key_slot( key, &slot ); + status = psa_get_empty_key_slot( handle, &slot ); if( status != PSA_SUCCESS ) return( status ); @@ -879,7 +856,8 @@ psa_status_t psa_import_key( psa_key_slot_t key, if( slot->lifetime == PSA_KEY_LIFETIME_PERSISTENT ) { /* Store in file location */ - status = psa_save_persistent_key( key, slot->type, &slot->policy, data, + status = psa_save_persistent_key( slot->persistent_storage_id, + slot->type, &slot->policy, data, data_length ); if( status != PSA_SUCCESS ) { @@ -892,31 +870,30 @@ psa_status_t psa_import_key( psa_key_slot_t key, return( status ); } -psa_status_t psa_destroy_key( psa_key_slot_t key ) +psa_status_t psa_destroy_key( psa_key_handle_t handle ) { - key_slot_t *slot; + psa_key_slot_t *slot; psa_status_t status = PSA_SUCCESS; psa_status_t storage_status = PSA_SUCCESS; - status = psa_get_key_slot( key, &slot ); + status = psa_get_key_slot( handle, &slot ); if( status != PSA_SUCCESS ) return( status ); #if defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) if( slot->lifetime == PSA_KEY_LIFETIME_PERSISTENT ) { - storage_status = psa_destroy_persistent_key( key ); + storage_status = + psa_destroy_persistent_key( slot->persistent_storage_id ); } #endif /* defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) */ - status = psa_remove_key_data_from_memory( slot ); - /* Zeroize the slot to wipe metadata such as policies. */ - mbedtls_zeroize( slot, sizeof( *slot ) ); + status = psa_wipe_key_slot( slot ); if( status != PSA_SUCCESS ) return( status ); return( storage_status ); } /* Return the size of the key in the given slot, in bits. */ -static size_t psa_get_key_bits( const key_slot_t *slot ) +static size_t psa_get_key_bits( const psa_key_slot_t *slot ) { if( key_type_is_raw_bytes( slot->type ) ) return( slot->data.raw.bytes * 8 ); @@ -932,18 +909,18 @@ static size_t psa_get_key_bits( const key_slot_t *slot ) return( 0 ); } -psa_status_t psa_get_key_information( psa_key_slot_t key, +psa_status_t psa_get_key_information( psa_key_handle_t handle, psa_key_type_t *type, size_t *bits ) { - key_slot_t *slot; + psa_key_slot_t *slot; psa_status_t status; if( type != NULL ) *type = 0; if( bits != NULL ) *bits = 0; - status = psa_get_key_slot( key, &slot ); + status = psa_get_key_slot( handle, &slot ); if( status != PSA_SUCCESS ) return( status ); @@ -956,7 +933,23 @@ psa_status_t psa_get_key_information( psa_key_slot_t key, return( PSA_SUCCESS ); } -static psa_status_t psa_internal_export_key( key_slot_t *slot, +#if defined(MBEDTLS_RSA_C) || defined(MBEDTLS_ECP_C) +static int pk_write_pubkey_simple( mbedtls_pk_context *key, + unsigned char *buf, size_t size ) +{ + int ret; + unsigned char *c; + size_t len = 0; + + c = buf + size; + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_pk_write_pubkey( &c, buf, key ) ); + + return( (int) len ); +} +#endif /* defined(MBEDTLS_RSA_C) || defined(MBEDTLS_ECP_C) */ + +static psa_status_t psa_internal_export_key( psa_key_slot_t *slot, uint8_t *data, size_t data_size, size_t *data_length, @@ -1026,9 +1019,13 @@ static psa_status_t psa_internal_export_key( key_slot_t *slot, #endif } if( export_public_key || PSA_KEY_TYPE_IS_PUBLIC_KEY( slot->type ) ) - ret = mbedtls_pk_write_pubkey_der( &pk, data, data_size ); + { + ret = pk_write_pubkey_simple( &pk, data, data_size ); + } else + { ret = mbedtls_pk_write_key_der( &pk, data, data_size ); + } if( ret < 0 ) { /* If data_size is 0 then data may be NULL and then the @@ -1064,12 +1061,12 @@ static psa_status_t psa_internal_export_key( key_slot_t *slot, } } -psa_status_t psa_export_key( psa_key_slot_t key, +psa_status_t psa_export_key( psa_key_handle_t handle, uint8_t *data, size_t data_size, size_t *data_length ) { - key_slot_t *slot; + psa_key_slot_t *slot; psa_status_t status; /* Set the key to empty now, so that even when there are errors, we always @@ -1081,19 +1078,19 @@ psa_status_t psa_export_key( psa_key_slot_t key, /* Export requires the EXPORT flag. There is an exception for public keys, * which don't require any flag, but psa_get_key_from_slot takes * care of this. */ - status = psa_get_key_from_slot( key, &slot, PSA_KEY_USAGE_EXPORT, 0 ); + status = psa_get_key_from_slot( handle, &slot, PSA_KEY_USAGE_EXPORT, 0 ); if( status != PSA_SUCCESS ) return( status ); return( psa_internal_export_key( slot, data, data_size, data_length, 0 ) ); } -psa_status_t psa_export_public_key( psa_key_slot_t key, +psa_status_t psa_export_public_key( psa_key_handle_t handle, uint8_t *data, size_t data_size, size_t *data_length ) { - key_slot_t *slot; + psa_key_slot_t *slot; psa_status_t status; /* Set the key to empty now, so that even when there are errors, we always @@ -1103,7 +1100,7 @@ psa_status_t psa_export_public_key( psa_key_slot_t key, *data_length = 0; /* Exporting a public key doesn't require a usage flag. */ - status = psa_get_key_from_slot( key, &slot, 0, 0 ); + status = psa_get_key_from_slot( handle, &slot, 0, 0 ); if( status != PSA_SUCCESS ) return( status ); return( psa_internal_export_key( slot, data, data_size, @@ -1111,8 +1108,7 @@ psa_status_t psa_export_public_key( psa_key_slot_t key, } #if defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) -static psa_status_t psa_save_generated_persistent_key( psa_key_slot_t key, - key_slot_t *slot, +static psa_status_t psa_save_generated_persistent_key( psa_key_slot_t *slot, size_t bits ) { psa_status_t status; @@ -1130,14 +1126,15 @@ static psa_status_t psa_save_generated_persistent_key( psa_key_slot_t key, goto exit; } /* Store in file location */ - status = psa_save_persistent_key( key, slot->type, &slot->policy, + status = psa_save_persistent_key( slot->persistent_storage_id, + slot->type, &slot->policy, data, key_length ); if( status != PSA_SUCCESS ) { slot->type = PSA_KEY_TYPE_NONE; } exit: - mbedtls_zeroize( data, key_length ); + mbedtls_platform_zeroize( data, key_length ); mbedtls_free( data ); return( status ); } @@ -1479,6 +1476,67 @@ psa_status_t psa_hash_verify( psa_hash_operation_t *operation, return( PSA_SUCCESS ); } +psa_status_t psa_hash_clone( const psa_hash_operation_t *source_operation, + psa_hash_operation_t *target_operation ) +{ + if( target_operation->alg != 0 ) + return( PSA_ERROR_BAD_STATE ); + + switch( source_operation->alg ) + { + case 0: + return( PSA_ERROR_BAD_STATE ); +#if defined(MBEDTLS_MD2_C) + case PSA_ALG_MD2: + mbedtls_md2_clone( &target_operation->ctx.md2, + &source_operation->ctx.md2 ); + break; +#endif +#if defined(MBEDTLS_MD4_C) + case PSA_ALG_MD4: + mbedtls_md4_clone( &target_operation->ctx.md4, + &source_operation->ctx.md4 ); + break; +#endif +#if defined(MBEDTLS_MD5_C) + case PSA_ALG_MD5: + mbedtls_md5_clone( &target_operation->ctx.md5, + &source_operation->ctx.md5 ); + break; +#endif +#if defined(MBEDTLS_RIPEMD160_C) + case PSA_ALG_RIPEMD160: + mbedtls_ripemd160_clone( &target_operation->ctx.ripemd160, + &source_operation->ctx.ripemd160 ); + break; +#endif +#if defined(MBEDTLS_SHA1_C) + case PSA_ALG_SHA_1: + mbedtls_sha1_clone( &target_operation->ctx.sha1, + &source_operation->ctx.sha1 ); + break; +#endif +#if defined(MBEDTLS_SHA256_C) + case PSA_ALG_SHA_224: + case PSA_ALG_SHA_256: + mbedtls_sha256_clone( &target_operation->ctx.sha256, + &source_operation->ctx.sha256 ); + break; +#endif +#if defined(MBEDTLS_SHA512_C) + case PSA_ALG_SHA_384: + case PSA_ALG_SHA_512: + mbedtls_sha512_clone( &target_operation->ctx.sha512, + &source_operation->ctx.sha512 ); + break; +#endif + default: + return( PSA_ERROR_NOT_SUPPORTED ); + } + + target_operation->alg = source_operation->alg; + return( PSA_SUCCESS ); +} /****************************************************************/ @@ -1644,7 +1702,7 @@ static psa_status_t psa_mac_init( psa_mac_operation_t *operation, #if defined(MBEDTLS_MD_C) static psa_status_t psa_hmac_abort_internal( psa_hmac_internal_data *hmac ) { - mbedtls_zeroize( hmac->opad, sizeof( hmac->opad ) ); + mbedtls_platform_zeroize( hmac->opad, sizeof( hmac->opad ) ); return( psa_hash_abort( &hmac->hash_ctx ) ); } @@ -1706,7 +1764,7 @@ psa_status_t psa_mac_abort( psa_mac_operation_t *operation ) #if defined(MBEDTLS_CMAC_C) static int psa_cmac_setup( psa_mac_operation_t *operation, size_t key_bits, - key_slot_t *slot, + psa_key_slot_t *slot, const mbedtls_cipher_info_t *cipher_info ) { int ret; @@ -1788,19 +1846,19 @@ static psa_status_t psa_hmac_setup_internal( psa_hmac_internal_data *hmac, status = psa_hash_update( &hmac->hash_ctx, ipad, block_size ); cleanup: - mbedtls_zeroize( ipad, key_length ); + mbedtls_platform_zeroize( ipad, key_length ); return( status ); } #endif /* MBEDTLS_MD_C */ static psa_status_t psa_mac_setup( psa_mac_operation_t *operation, - psa_key_slot_t key, + psa_key_handle_t handle, psa_algorithm_t alg, int is_sign ) { psa_status_t status; - key_slot_t *slot; + psa_key_slot_t *slot; size_t key_bits; psa_key_usage_t usage = is_sign ? PSA_KEY_USAGE_SIGN : PSA_KEY_USAGE_VERIFY; @@ -1813,7 +1871,7 @@ static psa_status_t psa_mac_setup( psa_mac_operation_t *operation, if( is_sign ) operation->is_sign = 1; - status = psa_get_key_from_slot( key, &slot, usage, alg ); + status = psa_get_key_from_slot( handle, &slot, usage, alg ); if( status != PSA_SUCCESS ) goto exit; key_bits = psa_get_key_bits( slot ); @@ -1906,17 +1964,17 @@ static psa_status_t psa_mac_setup( psa_mac_operation_t *operation, } psa_status_t psa_mac_sign_setup( psa_mac_operation_t *operation, - psa_key_slot_t key, + psa_key_handle_t handle, psa_algorithm_t alg ) { - return( psa_mac_setup( operation, key, alg, 1 ) ); + return( psa_mac_setup( operation, handle, alg, 1 ) ); } psa_status_t psa_mac_verify_setup( psa_mac_operation_t *operation, - psa_key_slot_t key, + psa_key_handle_t handle, psa_algorithm_t alg ) { - return( psa_mac_setup( operation, key, alg, 0 ) ); + return( psa_mac_setup( operation, handle, alg, 0 ) ); } psa_status_t psa_mac_update( psa_mac_operation_t *operation, @@ -1994,7 +2052,7 @@ static psa_status_t psa_hmac_finish_internal( psa_hmac_internal_data *hmac, memcpy( mac, tmp, mac_size ); exit: - mbedtls_zeroize( tmp, hash_size ); + mbedtls_platform_zeroize( tmp, hash_size ); return( status ); } #endif /* MBEDTLS_MD_C */ @@ -2018,7 +2076,7 @@ static psa_status_t psa_mac_finish_internal( psa_mac_operation_t *operation, int ret = mbedtls_cipher_cmac_finish( &operation->ctx.cmac, tmp ); if( ret == 0 ) memcpy( mac, tmp, operation->mac_size ); - mbedtls_zeroize( tmp, sizeof( tmp ) ); + mbedtls_platform_zeroize( tmp, sizeof( tmp ) ); return( mbedtls_to_psa_error( ret ) ); } else @@ -2106,7 +2164,7 @@ psa_status_t psa_mac_verify_finish( psa_mac_operation_t *operation, else psa_mac_abort( operation ); - mbedtls_zeroize( actual_mac, sizeof( actual_mac ) ); + mbedtls_platform_zeroize( actual_mac, sizeof( actual_mac ) ); return( status ); } @@ -2373,7 +2431,7 @@ static psa_status_t psa_ecdsa_verify( mbedtls_ecp_keypair *ecp, } #endif /* MBEDTLS_ECDSA_C */ -psa_status_t psa_asymmetric_sign( psa_key_slot_t key, +psa_status_t psa_asymmetric_sign( psa_key_handle_t handle, psa_algorithm_t alg, const uint8_t *hash, size_t hash_length, @@ -2381,12 +2439,12 @@ psa_status_t psa_asymmetric_sign( psa_key_slot_t key, size_t signature_size, size_t *signature_length ) { - key_slot_t *slot; + psa_key_slot_t *slot; psa_status_t status; *signature_length = signature_size; - status = psa_get_key_from_slot( key, &slot, PSA_KEY_USAGE_SIGN, alg ); + status = psa_get_key_from_slot( handle, &slot, PSA_KEY_USAGE_SIGN, alg ); if( status != PSA_SUCCESS ) goto exit; if( ! PSA_KEY_TYPE_IS_KEYPAIR( slot->type ) ) @@ -2449,17 +2507,17 @@ psa_status_t psa_asymmetric_sign( psa_key_slot_t key, return( status ); } -psa_status_t psa_asymmetric_verify( psa_key_slot_t key, +psa_status_t psa_asymmetric_verify( psa_key_handle_t handle, psa_algorithm_t alg, const uint8_t *hash, size_t hash_length, const uint8_t *signature, size_t signature_length ) { - key_slot_t *slot; + psa_key_slot_t *slot; psa_status_t status; - status = psa_get_key_from_slot( key, &slot, PSA_KEY_USAGE_VERIFY, alg ); + status = psa_get_key_from_slot( handle, &slot, PSA_KEY_USAGE_VERIFY, alg ); if( status != PSA_SUCCESS ) return( status ); @@ -2505,7 +2563,7 @@ static void psa_rsa_oaep_set_padding_mode( psa_algorithm_t alg, } #endif /* defined(MBEDTLS_RSA_C) && defined(MBEDTLS_PKCS1_V21) */ -psa_status_t psa_asymmetric_encrypt( psa_key_slot_t key, +psa_status_t psa_asymmetric_encrypt( psa_key_handle_t handle, psa_algorithm_t alg, const uint8_t *input, size_t input_length, @@ -2515,7 +2573,7 @@ psa_status_t psa_asymmetric_encrypt( psa_key_slot_t key, size_t output_size, size_t *output_length ) { - key_slot_t *slot; + psa_key_slot_t *slot; psa_status_t status; (void) input; @@ -2529,7 +2587,7 @@ psa_status_t psa_asymmetric_encrypt( psa_key_slot_t key, if( ! PSA_ALG_IS_RSA_OAEP( alg ) && salt_length != 0 ) return( PSA_ERROR_INVALID_ARGUMENT ); - status = psa_get_key_from_slot( key, &slot, PSA_KEY_USAGE_ENCRYPT, alg ); + status = psa_get_key_from_slot( handle, &slot, PSA_KEY_USAGE_ENCRYPT, alg ); if( status != PSA_SUCCESS ) return( status ); if( ! ( PSA_KEY_TYPE_IS_PUBLIC_KEY( slot->type ) || @@ -2585,7 +2643,7 @@ psa_status_t psa_asymmetric_encrypt( psa_key_slot_t key, } } -psa_status_t psa_asymmetric_decrypt( psa_key_slot_t key, +psa_status_t psa_asymmetric_decrypt( psa_key_handle_t handle, psa_algorithm_t alg, const uint8_t *input, size_t input_length, @@ -2595,7 +2653,7 @@ psa_status_t psa_asymmetric_decrypt( psa_key_slot_t key, size_t output_size, size_t *output_length ) { - key_slot_t *slot; + psa_key_slot_t *slot; psa_status_t status; (void) input; @@ -2609,7 +2667,7 @@ psa_status_t psa_asymmetric_decrypt( psa_key_slot_t key, if( ! PSA_ALG_IS_RSA_OAEP( alg ) && salt_length != 0 ) return( PSA_ERROR_INVALID_ARGUMENT ); - status = psa_get_key_from_slot( key, &slot, PSA_KEY_USAGE_DECRYPT, alg ); + status = psa_get_key_from_slot( handle, &slot, PSA_KEY_USAGE_DECRYPT, alg ); if( status != PSA_SUCCESS ) return( status ); if( ! PSA_KEY_TYPE_IS_KEYPAIR( slot->type ) ) @@ -2695,13 +2753,13 @@ static psa_status_t psa_cipher_init( psa_cipher_operation_t *operation, } static psa_status_t psa_cipher_setup( psa_cipher_operation_t *operation, - psa_key_slot_t key, + psa_key_handle_t handle, psa_algorithm_t alg, mbedtls_operation_t cipher_operation ) { int ret = MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE; psa_status_t status; - key_slot_t *slot; + psa_key_slot_t *slot; size_t key_bits; const mbedtls_cipher_info_t *cipher_info = NULL; psa_key_usage_t usage = ( cipher_operation == MBEDTLS_ENCRYPT ? @@ -2712,7 +2770,7 @@ static psa_status_t psa_cipher_setup( psa_cipher_operation_t *operation, if( status != PSA_SUCCESS ) return( status ); - status = psa_get_key_from_slot( key, &slot, usage, alg); + status = psa_get_key_from_slot( handle, &slot, usage, alg); if( status != PSA_SUCCESS ) return( status ); key_bits = psa_get_key_bits( slot ); @@ -2787,17 +2845,17 @@ static psa_status_t psa_cipher_setup( psa_cipher_operation_t *operation, } psa_status_t psa_cipher_encrypt_setup( psa_cipher_operation_t *operation, - psa_key_slot_t key, + psa_key_handle_t handle, psa_algorithm_t alg ) { - return( psa_cipher_setup( operation, key, alg, MBEDTLS_ENCRYPT ) ); + return( psa_cipher_setup( operation, handle, alg, MBEDTLS_ENCRYPT ) ); } psa_status_t psa_cipher_decrypt_setup( psa_cipher_operation_t *operation, - psa_key_slot_t key, + psa_key_handle_t handle, psa_algorithm_t alg ) { - return( psa_cipher_setup( operation, key, alg, MBEDTLS_DECRYPT ) ); + return( psa_cipher_setup( operation, handle, alg, MBEDTLS_DECRYPT ) ); } psa_status_t psa_cipher_generate_iv( psa_cipher_operation_t *operation, @@ -2947,7 +3005,7 @@ psa_status_t psa_cipher_finish( psa_cipher_operation_t *operation, goto error; } - mbedtls_zeroize( temp_output_buffer, sizeof( temp_output_buffer ) ); + mbedtls_platform_zeroize( temp_output_buffer, sizeof( temp_output_buffer ) ); status = psa_cipher_abort( operation ); return( status ); @@ -2956,7 +3014,7 @@ psa_status_t psa_cipher_finish( psa_cipher_operation_t *operation, *output_length = 0; - mbedtls_zeroize( temp_output_buffer, sizeof( temp_output_buffer ) ); + mbedtls_platform_zeroize( temp_output_buffer, sizeof( temp_output_buffer ) ); (void) psa_cipher_abort( operation ); return( status ); @@ -2996,11 +3054,6 @@ psa_status_t psa_cipher_abort( psa_cipher_operation_t *operation ) /****************************************************************/ #if !defined(MBEDTLS_PSA_CRYPTO_SPM) -void psa_key_policy_init( psa_key_policy_t *policy ) -{ - memset( policy, 0, sizeof( *policy ) ); -} - void psa_key_policy_set_usage( psa_key_policy_t *policy, psa_key_usage_t usage, psa_algorithm_t alg ) @@ -3020,16 +3073,16 @@ psa_algorithm_t psa_key_policy_get_algorithm( const psa_key_policy_t *policy ) } #endif /* !defined(MBEDTLS_PSA_CRYPTO_SPM) */ -psa_status_t psa_set_key_policy( psa_key_slot_t key, +psa_status_t psa_set_key_policy( psa_key_handle_t handle, const psa_key_policy_t *policy ) { - key_slot_t *slot; + psa_key_slot_t *slot; psa_status_t status; if( policy == NULL ) return( PSA_ERROR_INVALID_ARGUMENT ); - status = psa_get_empty_key_slot( key, &slot ); + status = psa_get_empty_key_slot( handle, &slot ); if( status != PSA_SUCCESS ) return( status ); @@ -3046,16 +3099,16 @@ psa_status_t psa_set_key_policy( psa_key_slot_t key, return( PSA_SUCCESS ); } -psa_status_t psa_get_key_policy( psa_key_slot_t key, +psa_status_t psa_get_key_policy( psa_key_handle_t handle, psa_key_policy_t *policy ) { - key_slot_t *slot; + psa_key_slot_t *slot; psa_status_t status; if( policy == NULL ) return( PSA_ERROR_INVALID_ARGUMENT ); - status = psa_get_key_slot( key, &slot ); + status = psa_get_key_slot( handle, &slot ); if( status != PSA_SUCCESS ) return( status ); @@ -3070,13 +3123,13 @@ psa_status_t psa_get_key_policy( psa_key_slot_t key, /* Key Lifetime */ /****************************************************************/ -psa_status_t psa_get_key_lifetime( psa_key_slot_t key, +psa_status_t psa_get_key_lifetime( psa_key_handle_t handle, psa_key_lifetime_t *lifetime ) { - key_slot_t *slot; + psa_key_slot_t *slot; psa_status_t status; - status = psa_get_key_slot( key, &slot ); + status = psa_get_key_slot( handle, &slot ); if( status != PSA_SUCCESS ) return( status ); @@ -3085,34 +3138,6 @@ psa_status_t psa_get_key_lifetime( psa_key_slot_t key, return( PSA_SUCCESS ); } -psa_status_t psa_set_key_lifetime( psa_key_slot_t key, - psa_key_lifetime_t lifetime ) -{ - key_slot_t *slot; - psa_status_t status; - - if( lifetime != PSA_KEY_LIFETIME_VOLATILE && - lifetime != PSA_KEY_LIFETIME_PERSISTENT && - lifetime != PSA_KEY_LIFETIME_WRITE_ONCE ) - return( PSA_ERROR_INVALID_ARGUMENT ); - - status = psa_get_empty_key_slot( key, &slot ); - if( status != PSA_SUCCESS ) - return( status ); - - if( lifetime == PSA_KEY_LIFETIME_WRITE_ONCE ) - return( PSA_ERROR_NOT_SUPPORTED ); - -#if !defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) - if( lifetime == PSA_KEY_LIFETIME_PERSISTENT ) - return( PSA_ERROR_NOT_SUPPORTED ); -#endif - - slot->lifetime = lifetime; - - return( PSA_SUCCESS ); -} - /****************************************************************/ @@ -3121,7 +3146,7 @@ psa_status_t psa_set_key_lifetime( psa_key_slot_t key, typedef struct { - key_slot_t *slot; + psa_key_slot_t *slot; const mbedtls_cipher_info_t *cipher_info; union { @@ -3155,7 +3180,7 @@ static void psa_aead_abort( aead_operation_t *operation ) } static psa_status_t psa_aead_setup( aead_operation_t *operation, - psa_key_slot_t key, + psa_key_handle_t handle, psa_key_usage_t usage, psa_algorithm_t alg ) { @@ -3163,7 +3188,7 @@ static psa_status_t psa_aead_setup( aead_operation_t *operation, size_t key_bits; mbedtls_cipher_id_t cipher_id; - status = psa_get_key_from_slot( key, &operation->slot, usage, alg ); + status = psa_get_key_from_slot( handle, &operation->slot, usage, alg ); if( status != PSA_SUCCESS ) return( status ); @@ -3228,7 +3253,7 @@ static psa_status_t psa_aead_setup( aead_operation_t *operation, return( status ); } -psa_status_t psa_aead_encrypt( psa_key_slot_t key, +psa_status_t psa_aead_encrypt( psa_key_handle_t handle, psa_algorithm_t alg, const uint8_t *nonce, size_t nonce_length, @@ -3246,7 +3271,7 @@ psa_status_t psa_aead_encrypt( psa_key_slot_t key, *ciphertext_length = 0; - status = psa_aead_setup( &operation, key, PSA_KEY_USAGE_ENCRYPT, alg ); + status = psa_aead_setup( &operation, handle, PSA_KEY_USAGE_ENCRYPT, alg ); if( status != PSA_SUCCESS ) return( status ); @@ -3322,7 +3347,7 @@ static psa_status_t psa_aead_unpadded_locate_tag( size_t tag_length, return( PSA_SUCCESS ); } -psa_status_t psa_aead_decrypt( psa_key_slot_t key, +psa_status_t psa_aead_decrypt( psa_key_handle_t handle, psa_algorithm_t alg, const uint8_t *nonce, size_t nonce_length, @@ -3340,7 +3365,7 @@ psa_status_t psa_aead_decrypt( psa_key_slot_t key, *plaintext_length = 0; - status = psa_aead_setup( &operation, key, PSA_KEY_USAGE_DECRYPT, alg ); + status = psa_aead_setup( &operation, handle, PSA_KEY_USAGE_DECRYPT, alg ); if( status != PSA_SUCCESS ) return( status ); @@ -3418,7 +3443,7 @@ psa_status_t psa_generator_abort( psa_crypto_generator_t *generator ) { if( generator->ctx.buffer.data != NULL ) { - mbedtls_zeroize( generator->ctx.buffer.data, + mbedtls_platform_zeroize( generator->ctx.buffer.data, generator->ctx.buffer.size ); mbedtls_free( generator->ctx.buffer.data ); } @@ -3436,14 +3461,14 @@ psa_status_t psa_generator_abort( psa_crypto_generator_t *generator ) { if( generator->ctx.tls12_prf.key != NULL ) { - mbedtls_zeroize( generator->ctx.tls12_prf.key, + mbedtls_platform_zeroize( generator->ctx.tls12_prf.key, generator->ctx.tls12_prf.key_len ); mbedtls_free( generator->ctx.tls12_prf.key ); } if( generator->ctx.tls12_prf.Ai_with_seed != NULL ) { - mbedtls_zeroize( generator->ctx.tls12_prf.Ai_with_seed, + mbedtls_platform_zeroize( generator->ctx.tls12_prf.Ai_with_seed, generator->ctx.tls12_prf.Ai_with_seed_len ); mbedtls_free( generator->ctx.tls12_prf.Ai_with_seed ); } @@ -3769,7 +3794,7 @@ static void psa_des_set_key_parity( uint8_t *data, size_t data_size ) } #endif /* MBEDTLS_DES_C */ -psa_status_t psa_generator_import_key( psa_key_slot_t key, +psa_status_t psa_generator_import_key( psa_key_handle_t handle, psa_key_type_t type, size_t bits, psa_crypto_generator_t *generator ) @@ -3793,7 +3818,7 @@ psa_status_t psa_generator_import_key( psa_key_slot_t key, if( type == PSA_KEY_TYPE_DES ) psa_des_set_key_parity( data, bytes ); #endif /* MBEDTLS_DES_C */ - status = psa_import_key( key, type, data, bytes ); + status = psa_import_key( handle, type, data, bytes ); exit: mbedtls_free( data ); @@ -3945,7 +3970,7 @@ static psa_status_t psa_generator_tls12_psk_to_ms_setup( salt, salt_length, label, label_length ); - mbedtls_zeroize( pms, sizeof( pms ) ); + mbedtls_platform_zeroize( pms, sizeof( pms ) ); return( status ); } #endif /* MBEDTLS_MD_C */ @@ -4050,7 +4075,7 @@ static psa_status_t psa_key_derivation_internal( } psa_status_t psa_key_derivation( psa_crypto_generator_t *generator, - psa_key_slot_t key, + psa_key_handle_t handle, psa_algorithm_t alg, const uint8_t *salt, size_t salt_length, @@ -4058,7 +4083,7 @@ psa_status_t psa_key_derivation( psa_crypto_generator_t *generator, size_t label_length, size_t capacity ) { - key_slot_t *slot; + psa_key_slot_t *slot; psa_status_t status; if( generator->alg != 0 ) @@ -4070,7 +4095,7 @@ psa_status_t psa_key_derivation( psa_crypto_generator_t *generator, if( ! PSA_ALG_IS_KEY_DERIVATION( alg ) ) return( PSA_ERROR_INVALID_ARGUMENT ); - status = psa_get_key_from_slot( key, &slot, PSA_KEY_USAGE_DERIVE, alg ); + status = psa_get_key_from_slot( handle, &slot, PSA_KEY_USAGE_DERIVE, alg ); if( status != PSA_SUCCESS ) return( status ); @@ -4103,49 +4128,39 @@ static psa_status_t psa_key_agreement_ecdh( const uint8_t *peer_key, size_t shared_secret_size, size_t *shared_secret_length ) { - mbedtls_pk_context pk; mbedtls_ecp_keypair *their_key = NULL; mbedtls_ecdh_context ecdh; - int ret; + psa_status_t status; mbedtls_ecdh_init( &ecdh ); - mbedtls_pk_init( &pk ); - ret = mbedtls_pk_parse_public_key( &pk, peer_key, peer_key_length ); - if( ret != 0 ) - goto exit; - switch( mbedtls_pk_get_type( &pk ) ) - { - case MBEDTLS_PK_ECKEY: - case MBEDTLS_PK_ECKEY_DH: - break; - default: - ret = MBEDTLS_ERR_ECP_INVALID_KEY; - goto exit; - } - their_key = mbedtls_pk_ec( pk ); - if( their_key->grp.id != our_key->grp.id ) - { - ret = MBEDTLS_ERR_ECP_INVALID_KEY; + status = psa_import_ec_public_key( + mbedtls_ecc_group_to_psa( our_key->grp.id ), + peer_key, peer_key_length, + &their_key ); + if( status != PSA_SUCCESS ) goto exit; - } - ret = mbedtls_ecdh_get_params( &ecdh, their_key, MBEDTLS_ECDH_THEIRS ); - if( ret != 0 ) + status = mbedtls_to_psa_error( + mbedtls_ecdh_get_params( &ecdh, their_key, MBEDTLS_ECDH_THEIRS ) ); + if( status != PSA_SUCCESS ) goto exit; - ret = mbedtls_ecdh_get_params( &ecdh, our_key, MBEDTLS_ECDH_OURS ); - if( ret != 0 ) + status = mbedtls_to_psa_error( + mbedtls_ecdh_get_params( &ecdh, our_key, MBEDTLS_ECDH_OURS ) ); + if( status != PSA_SUCCESS ) goto exit; - ret = mbedtls_ecdh_calc_secret( &ecdh, - shared_secret_length, - shared_secret, shared_secret_size, - mbedtls_ctr_drbg_random, - &global_data.ctr_drbg ); + status = mbedtls_to_psa_error( + mbedtls_ecdh_calc_secret( &ecdh, + shared_secret_length, + shared_secret, shared_secret_size, + mbedtls_ctr_drbg_random, + &global_data.ctr_drbg ) ); exit: - mbedtls_pk_free( &pk ); mbedtls_ecdh_free( &ecdh ); - return( mbedtls_to_psa_error( ret ) ); + mbedtls_ecp_keypair_free( their_key ); + mbedtls_free( their_key ); + return( status ); } #endif /* MBEDTLS_ECDH_C */ @@ -4155,7 +4170,7 @@ static psa_status_t psa_key_agreement_ecdh( const uint8_t *peer_key, * to potentially free embedded data structures and wipe confidential data. */ static psa_status_t psa_key_agreement_internal( psa_crypto_generator_t *generator, - key_slot_t *private_key, + psa_key_slot_t *private_key, const uint8_t *peer_key, size_t peer_key_length, psa_algorithm_t alg ) @@ -4196,17 +4211,17 @@ static psa_status_t psa_key_agreement_internal( psa_crypto_generator_t *generato NULL, 0, NULL, 0, PSA_GENERATOR_UNBRIDLED_CAPACITY ); exit: - mbedtls_zeroize( shared_secret, shared_secret_length ); + mbedtls_platform_zeroize( shared_secret, shared_secret_length ); return( status ); } psa_status_t psa_key_agreement( psa_crypto_generator_t *generator, - psa_key_slot_t private_key, + psa_key_handle_t private_key, const uint8_t *peer_key, size_t peer_key_length, psa_algorithm_t alg ) { - key_slot_t *slot; + psa_key_slot_t *slot; psa_status_t status; if( ! PSA_ALG_IS_KEY_AGREEMENT( alg ) ) return( PSA_ERROR_INVALID_ARGUMENT ); @@ -4306,19 +4321,19 @@ psa_status_t mbedtls_psa_inject_entropy( const unsigned char *seed, } #endif -psa_status_t psa_generate_key( psa_key_slot_t key, +psa_status_t psa_generate_key( psa_key_handle_t handle, psa_key_type_t type, size_t bits, const void *extra, size_t extra_size ) { - key_slot_t *slot; + psa_key_slot_t *slot; psa_status_t status; if( extra == NULL && extra_size != 0 ) return( PSA_ERROR_INVALID_ARGUMENT ); - status = psa_get_empty_key_slot( key, &slot ); + status = psa_get_empty_key_slot( handle, &slot ); if( status != PSA_SUCCESS ) return( status ); @@ -4427,7 +4442,7 @@ psa_status_t psa_generate_key( psa_key_slot_t key, #if defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) if( slot->lifetime == PSA_KEY_LIFETIME_PERSISTENT ) { - return( psa_save_generated_persistent_key( key, slot, bits ) ); + return( psa_save_generated_persistent_key( slot, bits ) ); } #endif /* defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) */ @@ -4439,51 +4454,71 @@ psa_status_t psa_generate_key( psa_key_slot_t key, /* Module setup */ /****************************************************************/ -void mbedtls_psa_crypto_free( void ) +psa_status_t mbedtls_psa_crypto_configure_entropy_sources( + void (* entropy_init )( mbedtls_entropy_context *ctx ), + void (* entropy_free )( mbedtls_entropy_context *ctx ) ) { - psa_key_slot_t key; - key_slot_t *slot; - psa_status_t status; + if( global_data.rng_state != RNG_NOT_INITIALIZED ) + return( PSA_ERROR_BAD_STATE ); + global_data.entropy_init = entropy_init; + global_data.entropy_free = entropy_free; + return( PSA_SUCCESS ); +} - for( key = 1; key <= PSA_KEY_SLOT_COUNT; key++ ) +void mbedtls_psa_crypto_free( void ) +{ + psa_wipe_all_key_slots( ); + if( global_data.rng_state != RNG_NOT_INITIALIZED ) { - status = psa_get_key_slot( key, &slot ); - if( status != PSA_SUCCESS ) - continue; - psa_remove_key_data_from_memory( slot ); - /* Zeroize the slot to wipe metadata such as policies. */ - mbedtls_zeroize( slot, sizeof( *slot ) ); + mbedtls_ctr_drbg_free( &global_data.ctr_drbg ); + global_data.entropy_free( &global_data.entropy ); } - mbedtls_ctr_drbg_free( &global_data.ctr_drbg ); - mbedtls_entropy_free( &global_data.entropy ); - mbedtls_zeroize( &global_data, sizeof( global_data ) ); + /* Wipe all remaining data, including configuration. + * In particular, this sets all state indicator to the value + * indicating "uninitialized". */ + mbedtls_platform_zeroize( &global_data, sizeof( global_data ) ); } psa_status_t psa_crypto_init( void ) { - int ret; + psa_status_t status; const unsigned char drbg_seed[] = "PSA"; + /* Double initialization is explicitly allowed. */ if( global_data.initialized != 0 ) return( PSA_SUCCESS ); - mbedtls_zeroize( &global_data, sizeof( global_data ) ); - mbedtls_entropy_init( &global_data.entropy ); + /* Set default configuration if + * mbedtls_psa_crypto_configure_entropy_sources() hasn't been called. */ + if( global_data.entropy_init == NULL ) + global_data.entropy_init = mbedtls_entropy_init; + if( global_data.entropy_free == NULL ) + global_data.entropy_free = mbedtls_entropy_free; + + /* Initialize the random generator. */ + global_data.entropy_init( &global_data.entropy ); mbedtls_ctr_drbg_init( &global_data.ctr_drbg ); + global_data.rng_state = RNG_INITIALIZED; + status = mbedtls_to_psa_error( + mbedtls_ctr_drbg_seed( &global_data.ctr_drbg, + mbedtls_entropy_func, + &global_data.entropy, + drbg_seed, sizeof( drbg_seed ) - 1 ) ); + if( status != PSA_SUCCESS ) + goto exit; + global_data.rng_state = RNG_SEEDED; - ret = mbedtls_ctr_drbg_seed( &global_data.ctr_drbg, - mbedtls_entropy_func, - &global_data.entropy, - drbg_seed, sizeof( drbg_seed ) - 1 ); - if( ret != 0 ) + status = psa_initialize_key_slots( ); + if( status != PSA_SUCCESS ) goto exit; + /* All done. */ global_data.initialized = 1; exit: - if( ret != 0 ) + if( status != PSA_SUCCESS ) mbedtls_psa_crypto_free( ); - return( mbedtls_to_psa_error( ret ) ); + return( status ); } #endif /* MBEDTLS_PSA_CRYPTO_C */ diff --git a/features/mbedtls/mbed-crypto/platform/TARGET_PSA/COMPONENT_PSA_SRV_IMPL/psa_crypto_core.h b/features/mbedtls/mbed-crypto/platform/TARGET_PSA/COMPONENT_PSA_SRV_IMPL/psa_crypto_core.h new file mode 100644 index 00000000000..c2896819734 --- /dev/null +++ b/features/mbedtls/mbed-crypto/platform/TARGET_PSA/COMPONENT_PSA_SRV_IMPL/psa_crypto_core.h @@ -0,0 +1,99 @@ +/* + * PSA crypto core internal interfaces + */ +/* Copyright (C) 2018, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ + +#ifndef PSA_CRYPTO_CORE_H +#define PSA_CRYPTO_CORE_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include "psa/crypto.h" + +#include "mbedtls/ecp.h" +#include "mbedtls/rsa.h" + +/** The data structure representing a key slot, containing key material + * and metadata for one key. + */ +typedef struct +{ + psa_key_type_t type; + psa_key_policy_t policy; + psa_key_lifetime_t lifetime; + psa_key_id_t persistent_storage_id; + unsigned allocated : 1; + union + { + struct raw_data + { + uint8_t *data; + size_t bytes; + } raw; +#if defined(MBEDTLS_RSA_C) + mbedtls_rsa_context *rsa; +#endif /* MBEDTLS_RSA_C */ +#if defined(MBEDTLS_ECP_C) + mbedtls_ecp_keypair *ecp; +#endif /* MBEDTLS_ECP_C */ + } data; +} psa_key_slot_t; + +/** Completely wipe a slot in memory, including its policy. + * + * Persistent storage is not affected. + * + * \param[in,out] slot The key slot to wipe. + * + * \retval PSA_SUCCESS + * Success. This includes the case of a key slot that was + * already fully wiped. + * \retval PSA_ERROR_TAMPERING_DETECTED + */ +psa_status_t psa_wipe_key_slot( psa_key_slot_t *slot ); + +/** Import key data into a slot. + * + * `slot->type` must have been set previously. + * This function assumes that the slot does not contain any key material yet. + * On failure, the slot content is unchanged. + * + * Persistent storage is not affected. + * + * \param[in,out] slot The key slot to import data into. + * Its `type` field must have previously been set to + * the desired key type. + * It must not contain any key material yet. + * \param[in] data Buffer containing the key material to parse and import. + * \param data_length Size of \p data in bytes. + * + * \retval PSA_SUCCESS + * \retval PSA_ERROR_INVALID_ARGUMENT + * \retval PSA_ERROR_NOT_SUPPORTED + * \retval PSA_ERROR_INSUFFICIENT_MEMORY + */ +psa_status_t psa_import_key_into_slot( psa_key_slot_t *slot, + const uint8_t *data, + size_t data_length ); + +#endif /* PSA_CRYPTO_CORE_H */ diff --git a/features/mbedtls/mbed-crypto/platform/TARGET_PSA/COMPONENT_PSA_SRV_IMPL/psa_crypto_invasive.h b/features/mbedtls/mbed-crypto/platform/TARGET_PSA/COMPONENT_PSA_SRV_IMPL/psa_crypto_invasive.h new file mode 100644 index 00000000000..642652a4796 --- /dev/null +++ b/features/mbedtls/mbed-crypto/platform/TARGET_PSA/COMPONENT_PSA_SRV_IMPL/psa_crypto_invasive.h @@ -0,0 +1,79 @@ +/** + * \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 (C) 2018, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ + +#ifndef PSA_CRYPTO_INVASIVE_H +#define PSA_CRYPTO_INVASIVE_H + +#if defined(MBEDTLS_CONFIG_FILE) +#include MBEDTLS_CONFIG_FILE +#else +#include "mbedtls/config.h" +#endif + +#include "psa/crypto.h" + +#include "mbedtls/entropy.h" + +/** \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 /* PSA_CRYPTO_INVASIVE_H */ diff --git a/features/mbedtls/mbed-crypto/platform/TARGET_PSA/COMPONENT_PSA_SRV_IMPL/psa_crypto_slot_management.c b/features/mbedtls/mbed-crypto/platform/TARGET_PSA/COMPONENT_PSA_SRV_IMPL/psa_crypto_slot_management.c new file mode 100644 index 00000000000..c151c5eee7e --- /dev/null +++ b/features/mbedtls/mbed-crypto/platform/TARGET_PSA/COMPONENT_PSA_SRV_IMPL/psa_crypto_slot_management.c @@ -0,0 +1,291 @@ +/* + * PSA crypto layer on top of Mbed TLS crypto + */ +/* Copyright (C) 2018, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_PSA_CRYPTO_C) +/* + * 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) +/* + * PSA_CRYPTO_SECURE means that this file is compiled for the SPE. + * Some headers will be affected by this flag. + */ +#define PSA_CRYPTO_SECURE 1 +#include "crypto_spe.h" +#endif + +#include "psa/crypto.h" + +#include "psa_crypto_core.h" +#include "psa_crypto_slot_management.h" +#include "psa_crypto_storage.h" + +#include +#include +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif + +#define ARRAY_LENGTH( array ) ( sizeof( array ) / sizeof( *( array ) ) ) + +typedef struct +{ + psa_key_slot_t key_slots[PSA_KEY_SLOT_COUNT]; + unsigned key_slots_initialized : 1; +} psa_global_data_t; + +static psa_global_data_t global_data; + +/* Access a key slot at the given handle. The handle of a key slot is + * the index of the slot in the global slot array, plus one so that handles + * start at 1 and not 0. */ +psa_status_t psa_get_key_slot( psa_key_handle_t handle, + psa_key_slot_t **p_slot ) +{ + psa_key_slot_t *slot = NULL; + + if( ! global_data.key_slots_initialized ) + return( PSA_ERROR_BAD_STATE ); + + /* 0 is not a valid handle under any circumstance. This + * implementation provides slots number 1 to N where N is the + * number of available slots. */ + if( handle == 0 || handle > ARRAY_LENGTH( global_data.key_slots ) ) + return( PSA_ERROR_INVALID_HANDLE ); + slot = &global_data.key_slots[handle - 1]; + + /* If the slot hasn't been allocated, the handle is invalid. */ + if( ! slot->allocated ) + return( PSA_ERROR_INVALID_HANDLE ); + + *p_slot = slot; + return( PSA_SUCCESS ); +} + +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. */ + global_data.key_slots_initialized = 1; + return( PSA_SUCCESS ); +} + +void psa_wipe_all_key_slots( void ) +{ + psa_key_handle_t key; + for( key = 1; key <= PSA_KEY_SLOT_COUNT; key++ ) + { + psa_key_slot_t *slot = &global_data.key_slots[key - 1]; + (void) psa_wipe_key_slot( slot ); + } + global_data.key_slots_initialized = 0; +} + +/** Find a free key slot and mark it as in use. + * + * \param[out] handle On success, a slot number that is not in use. This + * value can be used as a handle to the slot. + * + * \retval #PSA_SUCCESS + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + */ +static psa_status_t psa_internal_allocate_key_slot( psa_key_handle_t *handle ) +{ + for( *handle = PSA_KEY_SLOT_COUNT; *handle != 0; --( *handle ) ) + { + psa_key_slot_t *slot = &global_data.key_slots[*handle - 1]; + if( ! slot->allocated ) + { + slot->allocated = 1; + return( PSA_SUCCESS ); + } + } + return( PSA_ERROR_INSUFFICIENT_MEMORY ); +} + +/** Wipe a key slot and mark it as available. + * + * This does not affect persistent storage. + * + * \param handle The handle to the key slot to release. + * + * \retval #PSA_SUCCESS + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \retval #PSA_ERROR_TAMPERING_DETECTED + */ +static psa_status_t psa_internal_release_key_slot( psa_key_handle_t handle ) +{ + psa_key_slot_t *slot; + psa_status_t status; + + status = psa_get_key_slot( handle, &slot ); + if( status != PSA_SUCCESS ) + return( status ); + + return( psa_wipe_key_slot( slot ) ); +} + +psa_status_t psa_allocate_key( psa_key_handle_t *handle ) +{ + *handle = 0; + return( psa_internal_allocate_key_slot( handle ) ); +} + +#if defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) +static psa_status_t psa_load_persistent_key_into_slot( psa_key_slot_t *p_slot ) +{ + psa_status_t status = PSA_SUCCESS; + uint8_t *key_data = NULL; + size_t key_data_length = 0; + + status = psa_load_persistent_key( p_slot->persistent_storage_id, + &( p_slot )->type, + &( p_slot )->policy, &key_data, + &key_data_length ); + if( status != PSA_SUCCESS ) + goto exit; + status = psa_import_key_into_slot( p_slot, + key_data, key_data_length ); +exit: + psa_free_persistent_key_data( key_data, key_data_length ); + return( status ); +} +#endif /* defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) */ + +/** Declare a slot as persistent and load it from storage. + * + * This function may only be called immediately after a successful call + * to psa_internal_allocate_key_slot(). + * + * \param handle A handle to a key slot freshly allocated with + * psa_internal_allocate_key_slot(). + * + * \retval #PSA_SUCCESS + * The slot content was loaded successfully. + * \retval #PSA_ERROR_EMPTY_SLOT + * There is no content for this slot in persistent storage. + * \retval #PSA_ERROR_INVALID_HANDLE + * \retval #PSA_ERROR_INVALID_ARGUMENT + * \p id is not acceptable. + * \retval #PSA_ERROR_INSUFFICIENT_MEMORY + * \retval #PSA_ERROR_STORAGE_FAILURE + */ +static psa_status_t psa_internal_make_key_persistent( psa_key_handle_t handle, + psa_key_id_t id ) +{ +#if defined(MBEDTLS_PSA_CRYPTO_STORAGE_C) + psa_key_slot_t *slot; + psa_status_t status; + + /* Reject id=0 because by general library conventions, 0 is an invalid + * value wherever possible. */ + if( id == 0 ) + return( PSA_ERROR_INVALID_ARGUMENT ); + /* Reject high values because the file names are reserved for the + * library's internal use. */ + if( id >= PSA_MAX_PERSISTENT_KEY_IDENTIFIER ) + return( PSA_ERROR_INVALID_ARGUMENT ); + + status = psa_get_key_slot( handle, &slot ); + if( status != PSA_SUCCESS ) + return( status ); + + slot->lifetime = PSA_KEY_LIFETIME_PERSISTENT; + slot->persistent_storage_id = id; + status = psa_load_persistent_key_into_slot( slot ); + + return( status ); + +#else /* MBEDTLS_PSA_CRYPTO_STORAGE_C */ + (void) handle; + (void) id; + return( PSA_ERROR_NOT_SUPPORTED ); +#endif /* !MBEDTLS_PSA_CRYPTO_STORAGE_C */ +} + +static psa_status_t persistent_key_setup( psa_key_lifetime_t lifetime, + psa_key_id_t id, + psa_key_handle_t *handle, + psa_status_t wanted_load_status ) +{ + psa_status_t status; + + *handle = 0; + + if( lifetime != PSA_KEY_LIFETIME_PERSISTENT ) + return( PSA_ERROR_INVALID_ARGUMENT ); + + status = psa_internal_allocate_key_slot( handle ); + if( status != PSA_SUCCESS ) + return( status ); + + status = psa_internal_make_key_persistent( *handle, id ); + if( status != wanted_load_status ) + { + psa_internal_release_key_slot( *handle ); + *handle = 0; + } + return( status ); +} + +psa_status_t psa_open_key( psa_key_lifetime_t lifetime, + psa_key_id_t id, + psa_key_handle_t *handle ) +{ + return( persistent_key_setup( lifetime, id, handle, PSA_SUCCESS ) ); +} + +psa_status_t psa_create_key( psa_key_lifetime_t lifetime, + psa_key_id_t id, + psa_key_handle_t *handle ) +{ + psa_status_t status; + + status = persistent_key_setup( lifetime, id, handle, + PSA_ERROR_EMPTY_SLOT ); + switch( status ) + { + case PSA_SUCCESS: return( PSA_ERROR_OCCUPIED_SLOT ); + case PSA_ERROR_EMPTY_SLOT: return( PSA_SUCCESS ); + default: return( status ); + } +} + +psa_status_t psa_close_key( psa_key_handle_t handle ) +{ + return( psa_internal_release_key_slot( handle ) ); +} + +#endif /* MBEDTLS_PSA_CRYPTO_C */ diff --git a/features/mbedtls/mbed-crypto/platform/TARGET_PSA/COMPONENT_PSA_SRV_IMPL/psa_crypto_slot_management.h b/features/mbedtls/mbed-crypto/platform/TARGET_PSA/COMPONENT_PSA_SRV_IMPL/psa_crypto_slot_management.h new file mode 100644 index 00000000000..6746bad91d6 --- /dev/null +++ b/features/mbedtls/mbed-crypto/platform/TARGET_PSA/COMPONENT_PSA_SRV_IMPL/psa_crypto_slot_management.h @@ -0,0 +1,58 @@ +/* + * PSA crypto layer on top of Mbed TLS crypto + */ +/* Copyright (C) 2018, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ + +#ifndef PSA_CRYPTO_SLOT_MANAGEMENT_H +#define PSA_CRYPTO_SLOT_MANAGEMENT_H + +/* Number of key slots (plus one because 0 is not used). + * The value is a compile-time constant for now, for simplicity. */ +#define PSA_KEY_SLOT_COUNT 32 + +/** Access a key slot at the given handle. + * + * \param handle Key handle to query. + * \param[out] p_slot On success, `*p_slot` contains a pointer to the + * key slot in memory designated by \p handle. + * + * \retval PSA_SUCCESS + * Success: \p handle is a handle to `*p_slot`. Note that `*p_slot` + * may be empty or occupied. + * \retval PSA_ERROR_INVALID_HANDLE + * \p handle is out of range or is not in use. + * \retval PSA_ERROR_BAD_STATE + * The library has not been initialized. + */ +psa_status_t psa_get_key_slot( psa_key_handle_t handle, + 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 does not affect persistent storage. */ +void psa_wipe_all_key_slots( void ); + +#endif /* PSA_CRYPTO_SLOT_MANAGEMENT_H */ diff --git a/features/mbedtls/mbed-crypto/platform/TARGET_PSA/COMPONENT_PSA_SRV_IMPL/psa_crypto_storage.c b/features/mbedtls/mbed-crypto/platform/TARGET_PSA/COMPONENT_PSA_SRV_IMPL/psa_crypto_storage.c index 0a5805b62b4..687269b079e 100644 --- a/features/mbedtls/mbed-crypto/platform/TARGET_PSA/COMPONENT_PSA_SRV_IMPL/psa_crypto_storage.c +++ b/features/mbedtls/mbed-crypto/platform/TARGET_PSA/COMPONENT_PSA_SRV_IMPL/psa_crypto_storage.c @@ -147,7 +147,7 @@ psa_status_t psa_parse_key_data_from_storage( const uint8_t *storage_data, return( PSA_SUCCESS ); } -psa_status_t psa_save_persistent_key( const psa_key_slot_t key, +psa_status_t psa_save_persistent_key( const psa_key_id_t key, const psa_key_type_t type, const psa_key_policy_t *policy, const uint8_t *data, @@ -185,7 +185,7 @@ void psa_free_persistent_key_data( uint8_t *key_data, size_t key_data_length ) mbedtls_free( key_data ); } -psa_status_t psa_load_persistent_key( psa_key_slot_t key, +psa_status_t psa_load_persistent_key( psa_key_id_t key, psa_key_type_t *type, psa_key_policy_t *policy, uint8_t **data, diff --git a/features/mbedtls/mbed-crypto/platform/TARGET_PSA/COMPONENT_PSA_SRV_IMPL/psa_crypto_storage.h b/features/mbedtls/mbed-crypto/platform/TARGET_PSA/COMPONENT_PSA_SRV_IMPL/psa_crypto_storage.h index 167b0db0586..85881c16440 100644 --- a/features/mbedtls/mbed-crypto/platform/TARGET_PSA/COMPONENT_PSA_SRV_IMPL/psa_crypto_storage.h +++ b/features/mbedtls/mbed-crypto/platform/TARGET_PSA/COMPONENT_PSA_SRV_IMPL/psa_crypto_storage.h @@ -44,6 +44,23 @@ extern "C" { * inadvertently store an obscene amount of data) */ #define PSA_CRYPTO_MAX_STORAGE_SIZE ( 30 * 1024 ) +/** 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 #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 0xffff0000 + /** * \brief Format key data and metadata and save to a location for given key * slot. @@ -56,20 +73,20 @@ extern "C" { * already occupied non-persistent key, as well as validating the key data. * * - * \param key Slot number of the key to be stored. This must be a - * valid slot for a key of the chosen type. This should be - * an occupied key slot with an unoccupied corresponding - * storage location. + * \param key Persistent identifier of the key to be stored. This + * should be an unoccupied storage location. * \param type Key type (a \c PSA_KEY_TYPE_XXX value). * \param[in] policy The key policy to save. * \param[in] data Buffer containing the key data. * \param data_length The number of bytes that make up the key data. * * \retval PSA_SUCCESS + * \retval PSA_ERROR_INSUFFICIENT_MEMORY * \retval PSA_ERROR_INSUFFICIENT_STORAGE * \retval PSA_ERROR_STORAGE_FAILURE + * \retval PSA_ERROR_OCCUPIED_SLOT */ -psa_status_t psa_save_persistent_key( const psa_key_slot_t key, +psa_status_t psa_save_persistent_key( const psa_key_id_t key, const psa_key_type_t type, const psa_key_policy_t *policy, const uint8_t *data, @@ -87,10 +104,8 @@ psa_status_t psa_save_persistent_key( const psa_key_slot_t key, * this function to zeroize and free this buffer, regardless of whether this * function succeeds or fails. * - * \param key Slot number whose content is to be loaded. This - * must be an unoccupied key slot with an occupied - * corresponding storage location. The key slot - * lifetime must be set to persistent. + * \param key Persistent identifier of the key to be loaded. This + * should be an occupied storage location. * \param[out] type On success, the key type (a \c PSA_KEY_TYPE_XXX * value). * \param[out] policy On success, the key's policy. @@ -100,8 +115,9 @@ psa_status_t psa_save_persistent_key( const psa_key_slot_t key, * \retval PSA_SUCCESS * \retval PSA_ERROR_INSUFFICIENT_MEMORY * \retval PSA_ERROR_STORAGE_FAILURE + * \retval PSA_ERROR_EMPTY_SLOT */ -psa_status_t psa_load_persistent_key( psa_key_slot_t key, +psa_status_t psa_load_persistent_key( psa_key_id_t key, psa_key_type_t *type, psa_key_policy_t *policy, uint8_t **data, @@ -110,16 +126,18 @@ psa_status_t psa_load_persistent_key( psa_key_slot_t key, /** * \brief Remove persistent data for the given key slot number. * - * \param key Slot number whose content is to be removed + * \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_STORAGE_FAILURE */ -psa_status_t psa_destroy_persistent_key( const psa_key_slot_t key ); +psa_status_t psa_destroy_persistent_key( const psa_key_id_t key ); /** - * \brief Zeroizes and frees the given buffer. + * \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. diff --git a/features/mbedtls/mbed-crypto/platform/TARGET_PSA/COMPONENT_PSA_SRV_IMPL/psa_crypto_storage_backend.h b/features/mbedtls/mbed-crypto/platform/TARGET_PSA/COMPONENT_PSA_SRV_IMPL/psa_crypto_storage_backend.h index 3ca9a1d74fc..47896b8726d 100644 --- a/features/mbedtls/mbed-crypto/platform/TARGET_PSA/COMPONENT_PSA_SRV_IMPL/psa_crypto_storage_backend.h +++ b/features/mbedtls/mbed-crypto/platform/TARGET_PSA/COMPONENT_PSA_SRV_IMPL/psa_crypto_storage_backend.h @@ -47,15 +47,16 @@ extern "C" { * This function reads data from a storage backend and returns the data in a * buffer. * - * \param key Slot number whose content is to be loaded. This must - * be a key slot whose lifetime is set to persistent. - * \param[out] data Buffer where the data is to be written. - * \param data_size Size of the \c data buffer in bytes. + * \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 * \retval PSA_ERROR_STORAGE_FAILURE + * \retval PSA_ERROR_EMPTY_SLOT */ -psa_status_t psa_crypto_storage_load( const psa_key_slot_t key, uint8_t *data, +psa_status_t psa_crypto_storage_load( const psa_key_id_t key, uint8_t *data, size_t data_size ); /** @@ -63,7 +64,8 @@ psa_status_t psa_crypto_storage_load( const psa_key_slot_t key, uint8_t *data, * * This function stores the given data buffer to a persistent storage. * - * \param key Slot number whose content is to be stored. + * \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. @@ -71,8 +73,9 @@ psa_status_t psa_crypto_storage_load( const psa_key_slot_t key, uint8_t *data, * \retval PSA_SUCCESS * \retval PSA_ERROR_INSUFFICIENT_STORAGE * \retval PSA_ERROR_STORAGE_FAILURE + * \retval PSA_ERROR_OCCUPIED_SLOT */ -psa_status_t psa_crypto_storage_store( const psa_key_slot_t key, +psa_status_t psa_crypto_storage_store( const psa_key_id_t key, const uint8_t *data, size_t data_length ); @@ -82,26 +85,26 @@ psa_status_t psa_crypto_storage_store( const psa_key_slot_t key, * This function checks if any key data or metadata exists for the key slot in * the persistent storage. * - * \param key Slot number whose content is to be checked. + * \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 psa_key_slot_t key ); +int psa_is_key_present_in_storage( const psa_key_id_t key ); /** * \brief Get data length for given key slot number. * - * \param key Slot number whose stored data length is to be obtained. - * \param[out] data_length The number of bytes - * that make up the data. + * \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 * \retval PSA_ERROR_STORAGE_FAILURE */ -psa_status_t psa_crypto_storage_get_data_length( const psa_key_slot_t key, +psa_status_t psa_crypto_storage_get_data_length( const psa_key_id_t key, size_t *data_length ); diff --git a/features/mbedtls/mbed-crypto/platform/TARGET_PSA/COMPONENT_PSA_SRV_IMPL/psa_crypto_storage_file.c b/features/mbedtls/mbed-crypto/platform/TARGET_PSA/COMPONENT_PSA_SRV_IMPL/psa_crypto_storage_file.c index 03c711af306..87420be98a5 100644 --- a/features/mbedtls/mbed-crypto/platform/TARGET_PSA/COMPONENT_PSA_SRV_IMPL/psa_crypto_storage_file.c +++ b/features/mbedtls/mbed-crypto/platform/TARGET_PSA/COMPONENT_PSA_SRV_IMPL/psa_crypto_storage_file.c @@ -48,15 +48,16 @@ enum { MAX_LOCATION_LEN = sizeof(CRYPTO_STORAGE_FILE_LOCATION) + 40 }; -static void key_slot_to_location( const psa_key_slot_t key, - char *location, - size_t location_size ) +static void key_id_to_location( const psa_key_id_t key, + char *location, + size_t location_size ) { mbedtls_snprintf( location, location_size, - CRYPTO_STORAGE_FILE_LOCATION "psa_key_slot_%d", key ); + CRYPTO_STORAGE_FILE_LOCATION "psa_key_slot_%lu", + (unsigned long) key ); } -psa_status_t psa_crypto_storage_load( const psa_key_slot_t key, uint8_t *data, +psa_status_t psa_crypto_storage_load( const psa_key_id_t key, uint8_t *data, size_t data_size ) { psa_status_t status = PSA_SUCCESS; @@ -64,7 +65,7 @@ psa_status_t psa_crypto_storage_load( const psa_key_slot_t key, uint8_t *data, size_t num_read; char slot_location[MAX_LOCATION_LEN]; - key_slot_to_location( key, slot_location, MAX_LOCATION_LEN ); + key_id_to_location( key, slot_location, MAX_LOCATION_LEN ); file = fopen( slot_location, "rb" ); if( file == NULL ) { @@ -81,12 +82,12 @@ psa_status_t psa_crypto_storage_load( const psa_key_slot_t key, uint8_t *data, return( status ); } -int psa_is_key_present_in_storage( const psa_key_slot_t key ) +int psa_is_key_present_in_storage( const psa_key_id_t key ) { char slot_location[MAX_LOCATION_LEN]; FILE *file; - key_slot_to_location( key, slot_location, MAX_LOCATION_LEN ); + key_id_to_location( key, slot_location, MAX_LOCATION_LEN ); file = fopen( slot_location, "r" ); if( file == NULL ) @@ -99,7 +100,7 @@ int psa_is_key_present_in_storage( const psa_key_slot_t key ) return( 1 ); } -psa_status_t psa_crypto_storage_store( const psa_key_slot_t key, +psa_status_t psa_crypto_storage_store( const psa_key_id_t key, const uint8_t *data, size_t data_length ) { @@ -114,7 +115,7 @@ psa_status_t psa_crypto_storage_store( const psa_key_slot_t key, * affect actual keys. */ const char *temp_location = CRYPTO_STORAGE_FILE_LOCATION "psa_key_slot_0"; - key_slot_to_location( key, slot_location, MAX_LOCATION_LEN ); + key_id_to_location( key, slot_location, MAX_LOCATION_LEN ); if( psa_is_key_present_in_storage( key ) == 1 ) return( PSA_ERROR_OCCUPIED_SLOT ); @@ -154,12 +155,12 @@ psa_status_t psa_crypto_storage_store( const psa_key_slot_t key, return( status ); } -psa_status_t psa_destroy_persistent_key( const psa_key_slot_t key ) +psa_status_t psa_destroy_persistent_key( const psa_key_id_t key ) { FILE *file; char slot_location[MAX_LOCATION_LEN]; - key_slot_to_location( key, slot_location, MAX_LOCATION_LEN ); + key_id_to_location( key, slot_location, MAX_LOCATION_LEN ); /* Only try remove the file if it exists */ file = fopen( slot_location, "rb" ); @@ -173,7 +174,7 @@ psa_status_t psa_destroy_persistent_key( const psa_key_slot_t key ) return( PSA_SUCCESS ); } -psa_status_t psa_crypto_storage_get_data_length( const psa_key_slot_t key, +psa_status_t psa_crypto_storage_get_data_length( const psa_key_id_t key, size_t *data_length ) { psa_status_t status = PSA_SUCCESS; @@ -181,7 +182,7 @@ psa_status_t psa_crypto_storage_get_data_length( const psa_key_slot_t key, long file_size; char slot_location[MAX_LOCATION_LEN]; - key_slot_to_location( key, slot_location, MAX_LOCATION_LEN ); + key_id_to_location( key, slot_location, MAX_LOCATION_LEN ); file = fopen( slot_location, "rb" ); if( file == NULL ) diff --git a/features/mbedtls/mbed-crypto/platform/TARGET_PSA/COMPONENT_PSA_SRV_IMPL/psa_crypto_storage_its.c b/features/mbedtls/mbed-crypto/platform/TARGET_PSA/COMPONENT_PSA_SRV_IMPL/psa_crypto_storage_its.c index 35caa39adcd..d53467a1aa6 100644 --- a/features/mbedtls/mbed-crypto/platform/TARGET_PSA/COMPONENT_PSA_SRV_IMPL/psa_crypto_storage_its.c +++ b/features/mbedtls/mbed-crypto/platform/TARGET_PSA/COMPONENT_PSA_SRV_IMPL/psa_crypto_storage_its.c @@ -68,12 +68,12 @@ static psa_status_t its_to_psa_error( psa_its_status_t ret ) } } -static uint32_t psa_its_identifier_of_slot( psa_key_slot_t key ) +static uint32_t psa_its_identifier_of_slot( psa_key_id_t key ) { return( key ); } -psa_status_t psa_crypto_storage_load( const psa_key_slot_t key, uint8_t *data, +psa_status_t psa_crypto_storage_load( const psa_key_id_t key, uint8_t *data, size_t data_size ) { psa_its_status_t ret; @@ -92,7 +92,7 @@ psa_status_t psa_crypto_storage_load( const psa_key_slot_t key, uint8_t *data, return( status ); } -int psa_is_key_present_in_storage( const psa_key_slot_t key ) +int psa_is_key_present_in_storage( const psa_key_id_t key ) { psa_its_status_t ret; uint32_t data_identifier = psa_its_identifier_of_slot( key ); @@ -105,7 +105,7 @@ int psa_is_key_present_in_storage( const psa_key_slot_t key ) return( 1 ); } -psa_status_t psa_crypto_storage_store( const psa_key_slot_t key, +psa_status_t psa_crypto_storage_store( const psa_key_id_t key, const uint8_t *data, size_t data_length ) { @@ -143,7 +143,7 @@ psa_status_t psa_crypto_storage_store( const psa_key_slot_t key, return( status ); } -psa_status_t psa_destroy_persistent_key( const psa_key_slot_t key ) +psa_status_t psa_destroy_persistent_key( const psa_key_id_t key ) { psa_its_status_t ret; uint32_t data_identifier = psa_its_identifier_of_slot( key ); @@ -163,7 +163,7 @@ psa_status_t psa_destroy_persistent_key( const psa_key_slot_t key ) return( PSA_SUCCESS ); } -psa_status_t psa_crypto_storage_get_data_length( const psa_key_slot_t key, +psa_status_t psa_crypto_storage_get_data_length( const psa_key_id_t key, size_t *data_length ) { psa_its_status_t ret; diff --git a/features/mbedtls/mbed-crypto/platform/TARGET_PSA/COMPONENT_SPE/crypto_struct_spe.h b/features/mbedtls/mbed-crypto/platform/TARGET_PSA/COMPONENT_SPE/crypto_struct_spe.h index 44a1a60572f..ee3ecd776cd 100644 --- a/features/mbedtls/mbed-crypto/platform/TARGET_PSA/COMPONENT_SPE/crypto_struct_spe.h +++ b/features/mbedtls/mbed-crypto/platform/TARGET_PSA/COMPONENT_SPE/crypto_struct_spe.h @@ -85,6 +85,13 @@ struct psa_hash_operation_s } ctx; }; +#define PSA_HASH_OPERATION_INIT {0, {0}} +static inline struct psa_hash_operation_s psa_hash_operation_init( void ) +{ + const struct psa_hash_operation_s v = PSA_HASH_OPERATION_INIT; + return( v ); +} + #if defined(MBEDTLS_MD_C) typedef struct { @@ -116,6 +123,13 @@ struct psa_mac_operation_s } ctx; }; +#define PSA_MAC_OPERATION_INIT {0, 0, 0, 0, 0, 0, 0, {0}} +static inline struct psa_mac_operation_s psa_mac_operation_init( void ) +{ + const struct psa_mac_operation_s v = PSA_MAC_OPERATION_INIT; + return( v ); +} + struct psa_cipher_operation_s { psa_algorithm_t alg; @@ -126,10 +140,18 @@ struct psa_cipher_operation_s uint8_t block_size; union { + unsigned dummy; /* Enable easier initializing of the union. */ mbedtls_cipher_context_t cipher; } ctx; }; +#define PSA_CIPHER_OPERATION_INIT {0, 0, 0, 0, 0, 0, {0}} +static inline struct psa_cipher_operation_s psa_cipher_operation_init( void ) +{ + const struct psa_cipher_operation_s v = PSA_CIPHER_OPERATION_INIT; + return( v ); +} + #if defined(MBEDTLS_MD_C) typedef struct { @@ -208,4 +230,11 @@ struct psa_key_policy_s psa_algorithm_t alg; }; +#define PSA_KEY_POLICY_INIT {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 ); +} + #endif /* PSA_CRYPTO_STRUCT_H */ From d422fe8cbc0e14c5c496a0ccea75e3618626a1ef Mon Sep 17 00:00:00 2001 From: itayzafrir Date: Thu, 24 Jan 2019 12:10:21 +0200 Subject: [PATCH 5/6] crypto: Update tests to use key handles Update tests in TESTS/mbed-crypto/sanity/main.cpp --- TESTS/mbed-crypto/sanity/main.cpp | 80 ++++++++++++++++++------------- 1 file changed, 47 insertions(+), 33 deletions(-) diff --git a/TESTS/mbed-crypto/sanity/main.cpp b/TESTS/mbed-crypto/sanity/main.cpp index 4d9c972a54d..80df340bde4 100644 --- a/TESTS/mbed-crypto/sanity/main.cpp +++ b/TESTS/mbed-crypto/sanity/main.cpp @@ -85,7 +85,7 @@ void test_crypto_random(void) void test_crypto_asymmetric_encrypt_decrypt(void) { psa_status_t status = PSA_SUCCESS; - psa_key_slot_t slot = 1; + psa_key_handle_t key_handle = 0; psa_key_type_t key_type = PSA_KEY_TYPE_RSA_KEYPAIR; psa_algorithm_t alg = PSA_ALG_RSA_PKCS1V15_CRYPT; size_t key_bits = 512, got_bits = 0, output_length; @@ -94,21 +94,23 @@ void test_crypto_asymmetric_encrypt_decrypt(void) unsigned char encrypted[64]; unsigned char decrypted[sizeof(input)]; - psa_key_policy_init(&policy); + TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_allocate_key(&key_handle)); + + policy = psa_key_policy_init(); psa_key_policy_set_usage(&policy, PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT, alg); - TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_set_key_policy(slot, &policy)); + TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_set_key_policy(key_handle, &policy)); - status = psa_generate_key(slot, key_type, key_bits, NULL, 0); + status = psa_generate_key(key_handle, key_type, key_bits, NULL, 0); TEST_SKIP_UNLESS_MESSAGE(status != PSA_ERROR_NOT_SUPPORTED, "RSA key generation is not supported"); TEST_ASSERT_EQUAL(PSA_SUCCESS, status); - TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_get_key_information(slot, NULL, &got_bits)); + TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_get_key_information(key_handle, NULL, &got_bits)); TEST_ASSERT_EQUAL(key_bits, got_bits); - TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_asymmetric_encrypt(slot, alg, input, sizeof(input), NULL, 0, + TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_asymmetric_encrypt(key_handle, alg, input, sizeof(input), NULL, 0, encrypted, sizeof(encrypted), &output_length)); TEST_ASSERT_EQUAL(sizeof(encrypted), output_length); - TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_asymmetric_decrypt(slot, alg, encrypted, sizeof(encrypted), NULL, 0, + TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_asymmetric_decrypt(key_handle, alg, encrypted, sizeof(encrypted), NULL, 0, decrypted, sizeof(decrypted), &output_length)); - TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_destroy_key(slot)); + TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_destroy_key(key_handle)); TEST_ASSERT_EQUAL(sizeof(input), output_length); TEST_ASSERT_EQUAL_UINT8_ARRAY(input, decrypted, output_length); } @@ -124,6 +126,7 @@ void test_crypto_hash_verify(void) 0xa4, 0x95, 0x99, 0x1b, 0x78, 0x52, 0xb8, 0x55 }; + operation = psa_hash_operation_init(); TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_hash_setup(&operation, alg)); TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_hash_verify(&operation, hash, sizeof(hash))); TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_hash_abort(&operation)); @@ -131,7 +134,7 @@ void test_crypto_hash_verify(void) void test_crypto_symmetric_cipher_encrypt_decrypt(void) { - psa_key_slot_t slot = 1; + psa_key_handle_t key_handle = 0; psa_key_type_t key_type = PSA_KEY_TYPE_AES; psa_algorithm_t alg = PSA_ALG_CBC_NO_PADDING; psa_cipher_operation_t operation; @@ -151,12 +154,16 @@ void test_crypto_symmetric_cipher_encrypt_decrypt(void) }; unsigned char encrypted[sizeof(input)], decrypted[sizeof(input)], iv[16]; + TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_allocate_key(&key_handle)); + memset(iv, 0x2a, sizeof(iv)); - psa_key_policy_init(&policy); + policy = psa_key_policy_init(); psa_key_policy_set_usage(&policy, PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT, alg); - TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_set_key_policy(slot, &policy)); - TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_import_key(slot, key_type, key, sizeof(key))); - TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_cipher_encrypt_setup(&operation, slot, alg)); + TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_set_key_policy(key_handle, &policy)); + TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_import_key(key_handle, key_type, key, sizeof(key))); + + operation = psa_cipher_operation_init(); + TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_cipher_encrypt_setup(&operation, key_handle, alg)); TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_cipher_set_iv(&operation, iv, sizeof(iv))); TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_cipher_update(&operation, input, sizeof(input), encrypted, sizeof(encrypted), &output_len)); @@ -165,20 +172,21 @@ void test_crypto_symmetric_cipher_encrypt_decrypt(void) TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_cipher_abort(&operation)); TEST_ASSERT_EQUAL_HEX8_ARRAY(expected_encryption, encrypted, sizeof(expected_encryption)); - TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_cipher_decrypt_setup(&operation, slot, alg)); + operation = psa_cipher_operation_init(); + TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_cipher_decrypt_setup(&operation, key_handle, alg)); TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_cipher_set_iv(&operation, iv, sizeof(iv))); TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_cipher_update(&operation, encrypted, sizeof(encrypted), decrypted, sizeof(decrypted), &output_len)); TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_cipher_finish(&operation, decrypted + output_len, sizeof(decrypted) - output_len, &output_len)); TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_cipher_abort(&operation)); - TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_destroy_key(slot)); + TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_destroy_key(key_handle)); TEST_ASSERT_EQUAL_HEX8_ARRAY(input, decrypted, sizeof(input)); } void test_crypto_asymmetric_sign_verify(void) { - psa_key_slot_t slot = 1; + psa_key_handle_t key_handle = 0; psa_key_type_t key_type = PSA_KEY_TYPE_RSA_KEYPAIR; psa_algorithm_t alg = PSA_ALG_RSA_PKCS1V15_SIGN_RAW; psa_key_policy_t policy; @@ -252,45 +260,51 @@ void test_crypto_asymmetric_sign_verify(void) unsigned char signature[sizeof(expected_signature)]; size_t signature_len; - psa_key_policy_init(&policy); + TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_allocate_key(&key_handle)); + + policy = psa_key_policy_init(); psa_key_policy_set_usage(&policy, PSA_KEY_USAGE_SIGN | PSA_KEY_USAGE_VERIFY, alg); - TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_set_key_policy(slot, &policy)); - TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_import_key(slot, key_type, key, sizeof(key))); - TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_asymmetric_sign(slot, alg, input, sizeof(input), + TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_set_key_policy(key_handle, &policy)); + TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_import_key(key_handle, key_type, key, sizeof(key))); + TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_asymmetric_sign(key_handle, alg, input, sizeof(input), signature, sizeof(signature), &signature_len)); TEST_ASSERT_EQUAL(sizeof(signature), signature_len); TEST_ASSERT_EQUAL_HEX8_ARRAY(expected_signature, signature, signature_len); - TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_asymmetric_verify(slot, alg, input, sizeof(input), + TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_asymmetric_verify(key_handle, alg, input, sizeof(input), signature, signature_len)); - TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_destroy_key(slot)); + TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_destroy_key(key_handle)); } void test_crypto_key_derivation(void) { - psa_key_slot_t slot = 1, derived_slot = 2; + psa_key_handle_t key_handle = 0, derived_key_handle = 0; psa_algorithm_t alg = PSA_ALG_HKDF(PSA_ALG_SHA_256), derived_alg = PSA_ALG_CTR; - psa_key_type_t derived_key_type = PSA_KEY_TYPE_AES, got_type; + psa_key_type_t key_type = PSA_KEY_TYPE_DERIVE, derived_key_type = PSA_KEY_TYPE_AES, got_type; psa_key_policy_t policy; psa_crypto_generator_t generator = PSA_CRYPTO_GENERATOR_INIT; size_t key_bits = 512, derived_key_bits = 256, got_bits; - psa_key_policy_init(&policy); + TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_allocate_key(&key_handle)); + + policy = psa_key_policy_init(); psa_key_policy_set_usage(&policy, PSA_KEY_USAGE_DERIVE, alg); - TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_set_key_policy(slot, &policy)); - TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_generate_key(slot, PSA_KEY_TYPE_DERIVE, key_bits, NULL, 0)); - TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_key_derivation(&generator, slot, alg, NULL, 0, NULL, 0, + TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_set_key_policy(key_handle, &policy)); + TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_generate_key(key_handle, key_type, key_bits, NULL, 0)); + TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_key_derivation(&generator, key_handle, alg, NULL, 0, NULL, 0, PSA_BITS_TO_BYTES(derived_key_bits))); + + TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_allocate_key(&derived_key_handle)); psa_key_policy_set_usage(&policy, PSA_KEY_USAGE_ENCRYPT, derived_alg); - TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_set_key_policy(derived_slot, &policy)); - TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_generator_import_key(derived_slot, derived_key_type, + TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_set_key_policy(derived_key_handle, &policy)); + TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_generator_import_key(derived_key_handle, derived_key_type, derived_key_bits, &generator)); - TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_get_key_information(derived_slot, &got_type, &got_bits)); + TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_get_key_information(derived_key_handle, &got_type, &got_bits)); TEST_ASSERT_EQUAL(derived_key_type, got_type); TEST_ASSERT_EQUAL(derived_key_bits, got_bits); TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_generator_abort(&generator)); - TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_destroy_key(slot)); - TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_destroy_key(derived_slot)); + TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_destroy_key(key_handle)); + TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_destroy_key(derived_key_handle)); } From bd0037fe49f9d2cb57423d34b8ec1dc6eac74cae Mon Sep 17 00:00:00 2001 From: itayzafrir Date: Thu, 24 Jan 2019 12:17:33 +0200 Subject: [PATCH 6/6] crypto: Add test of key handles Test key handles by adding a test to TESTS/mbed-crypto/sanity/main.cpp --- TESTS/mbed-crypto/sanity/main.cpp | 46 +++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/TESTS/mbed-crypto/sanity/main.cpp b/TESTS/mbed-crypto/sanity/main.cpp index 80df340bde4..8a26305c2d4 100644 --- a/TESTS/mbed-crypto/sanity/main.cpp +++ b/TESTS/mbed-crypto/sanity/main.cpp @@ -307,6 +307,51 @@ void test_crypto_key_derivation(void) TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_destroy_key(derived_key_handle)); } +void test_crypto_key_handles(void) +{ + psa_key_id_t id = 999; + psa_key_type_t type = PSA_KEY_TYPE_AES; + size_t bits = 256; + psa_key_usage_t usage = PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT; + psa_algorithm_t alg = PSA_ALG_CBC_NO_PADDING; + psa_key_handle_t key_handle; + psa_key_policy_t policy; + + key_handle = 0; + TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_allocate_key(&key_handle)); + TEST_ASSERT_NOT_EQUAL(0, key_handle); + policy = psa_key_policy_init(); + psa_key_policy_set_usage(&policy, usage, alg); + TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_set_key_policy(key_handle, &policy)); + TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_generate_key(key_handle, type, bits, NULL, 0)); + TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_close_key(key_handle)); + + key_handle = 0; + TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_allocate_key(&key_handle)); + TEST_ASSERT_NOT_EQUAL(0, key_handle); + policy = psa_key_policy_init(); + psa_key_policy_set_usage(&policy, usage, alg); + TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_set_key_policy(key_handle, &policy)); + TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_generate_key(key_handle, type, bits, NULL, 0)); + TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_destroy_key(key_handle)); + + key_handle = 0; + TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_create_key(PSA_KEY_LIFETIME_PERSISTENT, id, &key_handle)); + TEST_ASSERT_NOT_EQUAL(0, key_handle); + policy = psa_key_policy_init(); + psa_key_policy_set_usage(&policy, usage, alg); + TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_set_key_policy(key_handle, &policy)); + TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_generate_key(key_handle, type, bits, NULL, 0)); + TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_close_key(key_handle)); + + key_handle = 0; + TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_open_key(PSA_KEY_LIFETIME_PERSISTENT, id, &key_handle)); + TEST_ASSERT_NOT_EQUAL(0, key_handle); + TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_destroy_key(key_handle)); + + key_handle = 0; + TEST_ASSERT_EQUAL(PSA_ERROR_EMPTY_SLOT, psa_open_key(PSA_KEY_LIFETIME_PERSISTENT, id, &key_handle)); +} utest::v1::status_t case_setup_handler(const Case *const source, const size_t index_of_case) { @@ -340,6 +385,7 @@ Case cases[] = { Case("mbed-crypto symmetric cipher encrypt/decrypt", case_setup_handler, test_crypto_symmetric_cipher_encrypt_decrypt, case_teardown_handler), Case("mbed-crypto asymmetric sign/verify", case_setup_handler, test_crypto_asymmetric_sign_verify, case_teardown_handler), Case("mbed-crypto key derivation", case_setup_handler, test_crypto_key_derivation, case_teardown_handler), + Case("mbed-crypto key handles", case_setup_handler, test_crypto_key_handles, case_teardown_handler), }; Specification specification(test_setup, cases);