diff options
author | Android Build Coastguard Worker <android-build-coastguard-worker@google.com> | 2023-09-21 21:58:51 +0000 |
---|---|---|
committer | Android Build Coastguard Worker <android-build-coastguard-worker@google.com> | 2023-09-21 21:58:51 +0000 |
commit | b2901a849084f878d6e35c99d9776e9d24913723 (patch) | |
tree | 0424cd7b8d1a5cd647d08da5968f3555725ede44 | |
parent | 43ccd41451205e7b1d7f2ebd90586d56bc2f46ce (diff) | |
parent | e1489ec2e2b7d3027bcb7dbd8605c7a59105ca23 (diff) | |
download | open-dice-b2901a849084f878d6e35c99d9776e9d24913723.tar.gz |
Snap for 10843824 from e1489ec2e2b7d3027bcb7dbd8605c7a59105ca23 to 24Q1-release
Change-Id: I118edcc8e62609cc7df3e697004e47d3c2f9cc42
49 files changed, 1410 insertions, 661 deletions
@@ -3,3 +3,4 @@ compile_commands.json out build_overrides/pigweed_environment.gni +environment @@ -13,3 +13,4 @@ # the License. buildconfig = "//BUILDCONFIG.gn" +export_compile_commands = [ "//*" ] @@ -134,17 +134,17 @@ cc_library_static { } filegroup { - name: "libopen_dice_bcc_srcs", + name: "libopen_dice_android_srcs", srcs: [ "src/cbor_reader.c", - "src/android/bcc.c", + "src/android.c", ], } cc_library { - name: "libopen_dice_bcc", + name: "libopen_dice_android", defaults: ["libopen_dice.cc_defaults"], - srcs: [":libopen_dice_bcc_srcs"], + srcs: [":libopen_dice_android_srcs"], export_shared_lib_headers: ["libopen_dice_cbor"], shared_libs: [ "libcrypto", @@ -153,8 +153,8 @@ cc_library { } cc_library_static { - name: "libopen_dice_bcc_baremetal", - srcs: [":libopen_dice_bcc_srcs"], + name: "libopen_dice_android_baremetal", + srcs: [":libopen_dice_android_srcs"], export_static_lib_headers: ["libopen_dice_cbor_baremetal"], static_libs: [ "libcrypto_baremetal", @@ -163,11 +163,11 @@ cc_library_static { } cc_library_static { - name: "libopen_dice_bcc_p384", + name: "libopen_dice_android_p384", defaults: ["libopen_dice.cc_defaults"], srcs: [ "src/cbor_reader.c", - "src/android/bcc.c", + "src/android.c", ], static_libs: ["libopen_dice_cbor_p384"], export_static_lib_headers: ["libopen_dice_cbor_p384"], @@ -225,7 +225,7 @@ cc_test { host_supported: true, cflags: ["-DDICE_USE_GTEST"], srcs: ["src/cbor_reader_test.cc"], - static_libs: ["libopen_dice_bcc"], + static_libs: ["libopen_dice_android"], } cc_test { @@ -233,16 +233,16 @@ cc_test { host_supported: true, cflags: ["-DDICE_USE_GTEST"], srcs: ["src/cbor_reader_test.cc"], - static_libs: ["libopen_dice_bcc_p384"], + static_libs: ["libopen_dice_android_p384"], } cc_test { - name: "libopen_dice_bcc_test", + name: "libopen_dice_android_test", host_supported: true, cflags: ["-DDICE_USE_GTEST"], - srcs: ["src/android/bcc_test.cc"], + srcs: ["src/android_test.cc"], static_libs: [ - "libopen_dice_bcc", + "libopen_dice_android", "libopen_dice_cbor", ], shared_libs: ["libcrypto"], @@ -268,14 +268,14 @@ cc_fuzz { name: "libopen_dice_cbor_reader_fuzzer", host_supported: true, srcs: ["src/cbor_reader_fuzzer.cc"], - static_libs: ["libopen_dice_bcc"], + static_libs: ["libopen_dice_android"], } cc_fuzz { name: "libopen_dice_cbor_reader_p384_fuzzer", host_supported: true, srcs: ["src/cbor_reader_fuzzer.cc"], - static_libs: ["libopen_dice_bcc_p384"], + static_libs: ["libopen_dice_android_p384"], } cc_fuzz { @@ -295,22 +295,22 @@ cc_fuzz { } cc_fuzz { - name: "libopen_dice_bcc_fuzzer", + name: "libopen_dice_android_fuzzer", host_supported: true, - srcs: ["src/android/bcc_fuzzer.cc"], + srcs: ["src/android_fuzzer.cc"], static_libs: [ - "libopen_dice_bcc", + "libopen_dice_android", "libopen_dice_cbor", ], shared_libs: ["libcrypto"], } cc_fuzz { - name: "libopen_dice_bcc_p384_fuzzer", + name: "libopen_dice_android_p384_fuzzer", host_supported: true, - srcs: ["src/android/bcc_fuzzer.cc"], + srcs: ["src/android_fuzzer.cc"], static_libs: [ - "libopen_dice_bcc_p384", + "libopen_dice_android_p384", "libopen_dice_cbor_p384", ], shared_libs: ["libcrypto"], @@ -14,6 +14,9 @@ import("//build_overrides/pigweed.gni") import("$dir_pw_bloat/bloat.gni") +import("$dir_pw_build/python.gni") +import("$dir_pw_build/python_dist.gni") +import("$dir_pw_build/python_venv.gni") import("$dir_pw_build/target_types.gni") import("$dir_pw_unit_test/test.gni") @@ -21,6 +24,7 @@ group("default") { deps = [ ":fuzzers(//toolchains:host_fuzz)", ":optimized_libs(//toolchains:host_optimized)", + ":python.install", ":tests.run(//toolchains:host_debug)", ] } @@ -83,8 +87,8 @@ pw_static_library("dice_with_boringssl_p384_ops") { ] sources = [ "src/boringssl_cert_op.c", - "src/boringssl_p384_ops.c", "src/boringssl_hash_kdf_ops.c", + "src/boringssl_p384_ops.c", "src/clear_memory.c", "src/dice.c", "src/utils.c", @@ -134,17 +138,14 @@ pw_static_library("dice_with_cbor_ed25519_cert") { all_dependent_configs = [ ":boringssl_ed25519_ops_config" ] } - pw_static_library("boringssl_ecdsa_utils") { public = [ "include/dice/boringssl_ecdsa_utils.h", + "include/dice/dice.h", + "include/dice/utils.h", ] - sources = [ - "src/boringssl_ecdsa_utils.c", - ] - deps = [ - "//third_party/boringssl:crypto", - ] + sources = [ "src/boringssl_ecdsa_utils.c" ] + deps = [ "//third_party/boringssl:crypto" ] } pw_static_library("dice_with_cbor_p384_cert") { @@ -160,16 +161,13 @@ pw_static_library("dice_with_cbor_p384_cert") { "src/clear_memory.c", "src/dice.c", "src/utils.c", - "src/boringssl_ecdsa_utils.c", ] deps = [ - ":cbor_writer", ":boringssl_ecdsa_utils", + ":cbor_writer", "//third_party/boringssl:crypto", ] - all_dependent_configs = [ - ":boringssl_ecdsa_p384_ops_config", - ] + all_dependent_configs = [ ":boringssl_ecdsa_p384_ops_config" ] } pw_static_library("dice_with_cbor_template_ed25519_cert") { @@ -207,6 +205,10 @@ pw_static_library("dice_with_x509_template_cert") { } pw_source_set("fuzzer") { + public = [ + "include/dice/dice.h", + "include/dice/utils.h", + ] sources = [ "src/fuzzer.cc" ] } @@ -244,8 +246,8 @@ pw_test("boringssl_ed25519_ops_test") { "src/test_utils.cc", ] deps = [ - ":dice_with_boringssl_ed25519_ops", ":boringssl_ecdsa_utils", + ":dice_with_boringssl_ed25519_ops", "$dir_pw_string:pw_string", "//third_party/boringssl:crypto", "//third_party/cose-c:cose-c_ed25519", @@ -272,8 +274,8 @@ pw_test("template_cert_op_test") { "src/test_utils.cc", ] deps = [ - ":dice_with_x509_template_cert", ":boringssl_ecdsa_utils", + ":dice_with_x509_template_cert", "$dir_pw_string:pw_string", "//third_party/boringssl:crypto", "//third_party/cose-c:cose-c_ed25519", @@ -293,8 +295,8 @@ pw_test("cbor_ed25519_cert_op_test") { "src/test_utils.cc", ] deps = [ - ":dice_with_cbor_ed25519_cert", ":boringssl_ecdsa_utils", + ":dice_with_cbor_ed25519_cert", "$dir_pw_string:pw_string", "//third_party/boringssl:crypto", "//third_party/cose-c:cose-c_ed25519", @@ -307,11 +309,11 @@ pw_test("cbor_p384_cert_op_test") { "src/test_utils.cc", ] deps = [ - ":dice_with_cbor_p384_cert", ":boringssl_ecdsa_utils", + ":dice_with_cbor_p384_cert", + "$dir_pw_string:pw_string", "//third_party/boringssl:crypto", "//third_party/cose-c:cose-c_p384", - "$dir_pw_string:pw_string", ] } @@ -328,8 +330,8 @@ pw_test("template_cbor_ed25519_cert_op_test") { "src/test_utils.cc", ] deps = [ - ":dice_with_cbor_template_ed25519_cert", ":boringssl_ecdsa_utils", + ":dice_with_cbor_template_ed25519_cert", "$dir_pw_string:pw_string", "//third_party/boringssl:crypto", "//third_party/cose-c:cose-c_ed25519", @@ -349,8 +351,8 @@ pw_test("mbedtls_ops_test") { "src/test_utils.cc", ] deps = [ - ":dice_with_mbedtls_ops", ":boringssl_ecdsa_utils", + ":dice_with_mbedtls_ops", "$dir_pw_string:pw_string", "//third_party/boringssl:crypto", "//third_party/cose-c:cose-c_ed25519", @@ -364,8 +366,32 @@ pw_executable("mbedtls_ops_fuzzer") { ] } +pw_static_library("dice_android") { + public = [ + "//include/dice/dice.h", + "//include/dice/utils.h", + ] + sources = [ "src/android.c" ] + deps = [ + ":cbor_reader", + ":cbor_writer", + ":dice_with_cbor_ed25519_cert", + ] +} + +pw_test("android_test") { + sources = [ "src/android_test.cc" ] + deps = [ ":dice_android" ] +} + +pw_executable("android_fuzzer") { + sources = [ "src/android_fuzzer.cc" ] + deps = [ ":dice_android" ] +} + pw_test_group("tests") { tests = [ + ":android_test", ":boringssl_ed25519_ops_test", ":cbor_ed25519_cert_op_test", ":cbor_p384_cert_op_test", @@ -375,12 +401,12 @@ pw_test_group("tests") { ":mbedtls_ops_test", ":template_cbor_ed25519_cert_op_test", ":template_cert_op_test", - "//src/android:bcc_test", ] } group("fuzzers") { deps = [ + ":android_fuzzer", ":boringssl_ed25519_ops_fuzzer", ":boringssl_p384_ops_fuzzer", ":cbor_ed25519_cert_op_fuzzer", @@ -389,7 +415,6 @@ group("fuzzers") { ":mbedtls_ops_fuzzer", ":template_cbor_ed25519_cert_op_fuzzer", ":template_cert_op_fuzzer", - "//src/android:bcc_fuzzer", ] } @@ -406,6 +431,10 @@ pw_executable("dice_standalone_main") { } pw_source_set("dice_main") { + public = [ + "include/dice/dice.h", + "include/dice/utils.h", + ] sources = [ "src/dice_main.c" ] } @@ -523,6 +552,7 @@ pw_size_diff("library_size_report") { group("optimized_libs") { deps = [ + ":dice_android", ":dice_standalone", ":dice_with_boringssl_ed25519_ops", ":dice_with_cbor_ed25519_cert", @@ -532,6 +562,55 @@ group("optimized_libs") { ":dice_with_x509_template_cert", ":executable_size_report", ":library_size_report", - "//src/android:bcc", ] } + +# This group is built during bootstrap to setup the interactive Python +# environment. +pw_python_group("python") { + python_deps = [ ":pip_install_open_dice_tools" ] +} + +# In-tree Python packages +_open_dice_python_packages = [ "//tools:tools" ] + +# Pigweed Python packages to include +_pigweed_python_packages = [ "$dir_pw_env_setup:core_pigweed_python_packages" ] + +_all_python_packages = _open_dice_python_packages + _pigweed_python_packages + +# The default venv for Python actions in GN +# Set this gn arg in a declare_args block in this file 'BUILD.gn' or in '.gn' to +# use this venv. +# +# pw_build_PYTHON_BUILD_VENV = "//:open_dice_build_venv" +# +pw_python_venv("open_dice_build_venv") { + path = "$root_build_dir/python-venv" + constraints = pw_build_PIP_CONSTRAINTS + requirements = pw_build_PIP_REQUIREMENTS + + # Ensure all third party Python dependencies are installed into this venv. + # This works by checking the setup.cfg files for all packages listed here and + # installing the packages listed in the [options].install_requires field. + source_packages = _all_python_packages +} + +# This template collects all python packages and their dependencies into a +# single super Python package for installation into the bootstrapped virtual +# environment. +pw_python_distribution("generate_open_dice_tools_python_distribution") { + packages = _all_python_packages + generate_setup_cfg = { + name = "open-dice-tools" + version = "0.0.1" + append_date_to_version = true + include_default_pyproject_file = true + } +} + +# Install the open-dice-tools super Python package into the bootstrapped Python +# venv. +pw_internal_pip_install("pip_install_open_dice_tools") { + packages = [ ":generate_open_dice_tools_python_distribution" ] +} @@ -43,15 +43,30 @@ Disclaimer: This is not an officially supported Google product. Different implementations use different third party libraries. The third\_party directory contains build files and git submodules for each of these. The -[bootstrap](bootstrap.sh) script will automatically initialize all submodules. +submodules must be initialized once after cloning the repo, using `git submodule +update --init`, and updated after pulling commits that roll the submodules using +`git submodule update`. ### Building and Running Tests +#### Quick setup + +To setup the build environment the first time: + ```bash +$ git submodule update --init $ source bootstrap.sh +$ gn gen out +``` + +To build and run tests: + +```bash $ ninja -C out ``` +#### More details + The easiest way, and currently the only supported way, to build and run tests is from a [Pigweed](https://pigweed.googlesource.com/pigweed/pigweed/) environment on Linux. Pigweed does support other host platforms so it shouldn't be too hard diff --git a/activate.sh b/activate.sh index 2cfc4c2..eba5389 100755..120000 --- a/activate.sh +++ b/activate.sh @@ -1,20 +1 @@ -# Copyright 2020 Google LLC -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may not -# use this file except in compliance with the License. You may obtain a copy of -# the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations under -# the License. - -# Reactivates an environment previously bootstrapped. -# -# Usage: source activate.sh - -# Activate the pigweed environment. -. third_party/pigweed/src/activate.sh +bootstrap.sh
\ No newline at end of file diff --git a/banner.txt b/banner.txt new file mode 100644 index 0000000..cda6557 --- /dev/null +++ b/banner.txt @@ -0,0 +1,2 @@ + [0m[33m  █▀█ █▀█ █▀▀ █▄░█ ▄ █▀▄ █░▄▀▀ █▀▀ [0m █▀███ █████ + [0m[33m  █▄█ █▀▀░██▄ █░▀█ ▀ █▄▀ █ ▀▄▄ ██▄░[0m ███▄█ ██▄██ diff --git a/bootstrap.sh b/bootstrap.sh index 181daec..53a4a63 100755..100644 --- a/bootstrap.sh +++ b/bootstrap.sh @@ -12,27 +12,125 @@ # License for the specific language governing permissions and limitations under # the License. -# Sets up an environment ready to build and run tests. For example, 'pw watch' -# should work in this environment. +# This script must be sourced, not executed. # -# Usage: source bootstrap.sh - -# Update submodules, initializing if necessary. This will pin all submodules to -# the committed revision so don't run this with uncommitted changes in a -# submodule. By convention, submodules are pinned to an upstream revision and -# any changes should be submitted upstream. Local changes to submodules are not -# carried long term, but patches waiting to land upstream may be applied -# manually. -git submodule update --init - -# Bootstrap the pigweed environment. -. third_party/pigweed/src/bootstrap.sh - -# Copy the pigweed environment config with a path fixup. -sed s/environment/third_party\\\/pigweed\\\/src\\\/environment/g \ - < third_party/pigweed/src/build_overrides/pigweed_environment.gni \ - > build_overrides/pigweed_environment.gni -gn format build_overrides/pigweed_environment.gni - -# Setup the build. -gn gen --export-compile-commands out +# Create a new environment: +# +# source bootstrap.sh +# +# Activate an existing environment: +# +# source activate.sh + +_bootstrap_abspath () { + $(command -v python3 || command -v python2 || command -v python) -c "import os.path; print(os.path.abspath('$@'))" +} + +# Shell: bash. +if test -n "$BASH"; then + _BOOTSTRAP_PATH="$(_bootstrap_abspath "$BASH_SOURCE")" +# Shell: zsh. +elif test -n "$ZSH_NAME"; then + _BOOTSTRAP_PATH="$(_bootstrap_abspath "${(%):-%N}")" +# Shell: dash. +elif test ${0##*/} = dash; then + _BOOTSTRAP_PATH="$(_bootstrap_abspath \ + "$(lsof -p $$ -Fn0 | tail -1 | sed 's#^[^/]*##;')")" +# If everything else fails, try $0. It could work. +else + _BOOTSTRAP_PATH="$(_bootstrap_abspath "$0")" +fi + +# Check if this file is being executed or sourced. +_pw_sourced=0 +if [ -n "$SWARMING_BOT_ID" ]; then + # If set we're running on swarming and don't need this check. + _pw_sourced=1 +elif [ -n "$ZSH_EVAL_CONTEXT" ]; then + case $ZSH_EVAL_CONTEXT in *:file) _pw_sourced=1;; esac +elif [ -n "$KSH_VERSION" ]; then + [ "$(cd $(dirname -- $0) && pwd -P)/$(basename -- $0)" != \ + "$(cd $(dirname -- ${.sh.file}) && pwd -P)/$(basename -- ${.sh.file})" ] \ + && _pw_sourced=1 +elif [ -n "$BASH_VERSION" ]; then + (return 0 2>/dev/null) && _pw_sourced=1 +else # All other shells: examine $0 for known shell binary filenames + # Detects `sh` and `dash`; add additional shell filenames as needed. + case ${0##*/} in sh|dash) _pw_sourced=1;; esac +fi + +# Downstream projects need to set something other than PW_ROOT here, like +# YOUR_PROJECT_ROOT. Please also set PW_PROJECT_ROOT and PW_ROOT before +# invoking pw_bootstrap or pw_activate. +######### BEGIN PROJECT-SPECIFIC CODE ######### +OPEN_DICE_ROOT="$(_bootstrap_abspath "$(dirname "$_BOOTSTRAP_PATH")")" +export OPEN_DICE_ROOT +PW_PROJECT_ROOT="$OPEN_DICE_ROOT" +PW_ROOT="$OPEN_DICE_ROOT/third_party/pigweed/src" + +# Set your project's banner and color. +PW_BRANDING_BANNER="$OPEN_DICE_ROOT/banner.txt" +export PW_BRANDING_BANNER +PW_BRANDING_BANNER_COLOR=magenta +export PW_BRANDING_BANNER_COLOR + +open_dice_banner() { + cat "$PW_BRANDING_BANNER" + echo +} + +PW_BANNER_FUNC="open_dice_banner" +########## END PROJECT-SPECIFIC CODE ########## +export PW_BANNER_FUNC +export PW_PROJECT_ROOT +export PW_ROOT + +_util_sh="$PW_ROOT/pw_env_setup/util.sh" + +# Double-check that the Pigweed submodule has been checked out. +if [ ! -e "$_util_sh" ]; then + echo "Error: $_util_sh not found." + echo "Did you forget to initialize the git submodules?" + echo "To setup the git submodules run:" + echo " git submodule update --init" + return +fi + +. "$_util_sh" + +pw_deactivate +pw_eval_sourced "$_pw_sourced" +pw_check_root "$PW_ROOT" +_PW_ACTUAL_ENVIRONMENT_ROOT="$(pw_get_env_root)" +export _PW_ACTUAL_ENVIRONMENT_ROOT +SETUP_SH="$_PW_ACTUAL_ENVIRONMENT_ROOT/activate.sh" + +# Run full bootstrap when invoked as bootstrap, or env file is missing/empty. +if [ "$(basename "$_BOOTSTRAP_PATH")" = "bootstrap.sh" ] || \ + [ ! -f "$SETUP_SH" ] || \ + [ ! -s "$SETUP_SH" ]; then +# This is where pw_bootstrap is called. Most small projects will include +# --use-pigweed-defaults. +######### BEGIN PROJECT-SPECIFIC CODE ######### + pw_bootstrap --shell-file "$SETUP_SH" --install-dir "$_PW_ACTUAL_ENVIRONMENT_ROOT" --config-file "$PW_PROJECT_ROOT/pigweed.json" +########## END PROJECT-SPECIFIC CODE ########## + pw_finalize bootstrap "$SETUP_SH" +else + pw_activate + pw_finalize activate "$SETUP_SH" +fi + +if [ "$_PW_ENV_SETUP_STATUS" -eq 0 ]; then +# This is where any additional checks about the environment should go. +######### BEGIN PROJECT-SPECIFIC CODE ######### + echo -n +########## END PROJECT-SPECIFIC CODE ########## +fi + +unset _pw_sourced +unset _BOOTSTRAP_PATH +unset SETUP_SH +unset _bootstrap_abspath +unset _util_sh + +pw_cleanup diff --git a/docs/android.md b/docs/android.md new file mode 100644 index 0000000..f41e6b1 --- /dev/null +++ b/docs/android.md @@ -0,0 +1,151 @@ +# Android Profile for DICE + +[TOC] + +## Background + +The Android Profile for DICE is a specialization of the [Open Profile for +DICE](specification.md) that provides additional detail around algorithms, +certificates, and configuration descriptor. The choices are made to meet the +needs of the Android ecosystem. + +This profile is not always a strict refinement of the Open Profile for DICE as +it also forced to address practical concerns such as workarounds for errata in +ROMs that require a relaxation of the base specification. However, the objective +is to avoid these where practical. + +## Cryptographic Algorithms + +The choice of algorithm must remain consistent with any given certificate e.g. +if SHA-256 is the hash algorithm used for the code hash then the authority hash, +config hash, etc. must also use SHA-256. + +See the Open Profile for DICE's [acceptable cryptographic +algorithms](specification.md#acceptable-cryptographic-algorithms) for more +detail on specific algorithms. + +### Hash Algorithms + +Acceptable hash algorithms are: + +* SHA-256, SHA-384, SHA-512 + +Unlike the Open Profile for DICE, digests can be used as DICE inputs at their +output size without needing to be resized to 64 bytes. The value that is used as +the DICE input must be listed in the certificate. E.g. SHA-256 digests can be +used as 32-byte DICE inputs with the same 32 bytes encoded as a byte string in +the certificate. + +### Key Derivation Functions + +HKDF with a [supported hash algorithm](#hash-algorithms), or +[CKDF](https://datatracker.ietf.org/doc/html/draft-agl-ckdf-00) for all key +derivation. + +### Digital Signatures + +Ed25519 is recommended for performance and memory usage reasons. ECDSA with +curves P-256 or P-384 are acceptable. + +## Certificate Details + +Only CBOR certificates are allowed by this profile. Other certificate types, +such as X.509, must not be used. + +### Mode + +A certificate must only set the mode to `normal` when all of the following +conditions are met when loading and verifying the software component that is +being described by the certificate: + +* secure/verified boot with anti-rollback protection is enabled +* only the secure/verified boot authorities for production images are enabled +* debug ports, fuses, or other debug facilities are disabled +* device booted software from the normal primary source e.g. internal flash + +The mode should never be `not configured`. + +### Configuration descriptor + +The configuration descriptor is a CBOR map. Only key values less than -65536 +are used as this is conventionally reserved for private use in IANA +assignments. The key value range \[-70000, -70999\] is reserved for use by this +profile. Implementation-specific fields may be added using key values outside +of the reserved range. + +Unless explicitly stated as required in the [versions](#versions) section, each +field is optional. If no fields are relevant, an empty map should be encoded. + +``` +| Name | Key | Value type | Meaning | +| ----------------- | ------ | ---------- | -----------------------------------| +| Component name | -70002 | tstr | Name of the component | +| Component version | -70003 | int / tstr | Version of the component | +| Resettable | -70004 | null | If present, key changes on factory | +: : : : reset : +| Security version | -70005 | uint | Machine-comparable, monotonically | +: : : : increasing version of the component: +: : : : where a greater value indicates a : +: : : : newer version, for example, the : +: : : : anti-rollback counter : +``` + +### Versions + +Android is an evolving ecosystem with compatibility requirements that enable +devices to continue being updated. Explicit versioning of certificates in the +DICE chain allows continued compatibility between higher-level software that +updates and lower-level software (such as ROM) that might not update. + +Versions of this profile are identified by their profile name which is composed +of the prefix `"android."` followed by the Android version number it aligns +with. If no profile name is included in the certificate, `"android.14"` is +assumed. + +Within a DICE chain, the version of the profile used in each certificate must +be the same or greater than the version used in the previous certificate. This +ensures the all certificates are aware of, and can maintain, any chain +invariants that can be added in any version of the profile. + +Android provides the [`hwtrust`](hwtrust-tool) tool which can validate that +certificate chains conform to this profile and can assist in diagnosing +problems. + +[hwtrust-tool]: https://cs.android.com/android/platform/superproject/main/+/main:tools/security/remote_provisioning/hwtrust/README.md + +The version-specific details listed below are non-cumulative so only apply to +the version they are listed under. + +#### `"android.14"` + +The profile named `"android.14"` aligns with Android 14. + +* Based on the [Open Profile for DICE v2.4][open-dice-v2.4]. +* The `configurationHash` field is permitted to be missing rather than being + required, as specified by the Open Profile for DICE. +* The `mode` field is permitted to be encoded as an integer rather than the + byte string that is specified by the Open Profile for DICE. +* The `keyUsage` field is permitted to be encoded in big-endian byte order as + well as the little-endian byte order that is specified by the Open Profile + for DICE. As a result of this erratum workaround, the value is ambiguous and + verifiers might not be able to rely on this value. + +#### `"android.15"` + +The profile named `"android.15"` aligns with Android 15. + +* Based on the [Open Profile for DICE v2.5][open-dice-v2.5]. +* The `configurationHash` field is permitted to be missing rather than being + required, as specified by the Open Profile for DICE. + +#### `"android.16"` + +The profile named `"android.16"` aligns with Android 16 and is still subject to +change. + +* Based on the [Open Profile for DICE v2.5][open-dice-v2.5]. +* The security version field of the [configuration + descriptor](#configuration-descriptor) is required. + +[open-dice-v2.4]: https://pigweed.googlesource.com/open-dice/+/f9f454ae493bfe76ec2af8011eb7543c20c5ffc2/docs/specification.md +[open-dice-v2.5]: https://pigweed.googlesource.com/open-dice/+/0b5044098bf9b40128927d675dea4ec1fb75c510/docs/specification.md diff --git a/docs/specification.md b/docs/specification.md index 60206b2..3348c62 100644 --- a/docs/specification.md +++ b/docs/specification.md @@ -1,6 +1,6 @@ # Open Profile for DICE -v2.4 +v2.5 [TOC] @@ -62,6 +62,10 @@ specification considers out of scope. In particular, this document specifies: * Additional requirements, including asymmetric key derivation and certification +Known specializations of this profile include: + +* [Android Profile for DICE](android.md) + #### Goals The main goals of this document are: @@ -692,6 +696,7 @@ OpenDiceInput ::= SEQUENCE { authorityHash [4] EXPLICIT OCTET STRING OPTIONAL, authorityDescriptor [5] EXPLICIT OCTET STRING OPTIONAL, mode [6] EXPLICIT Mode OPTIONAL, + profileName [7] EXPLICIT UTF8String OPTIONAL, } ``` @@ -721,6 +726,8 @@ extensibility in the format itself. The actual semantics are as follows: here must have been used to compute authorityHash; i.e. a change in this value implies a change in authorityHash. * **mode** - Required. This is the mode input value. +* **profileName** - Optional. This is the name of the DICE profile that + defines the contents of this certificate. ### CBOR UDS Certificates @@ -772,17 +779,18 @@ The following table lists additional entries in the CWT. By convention, the private fields in the map are labeled using negative integers starting at -4670545. -Field | CBOR Label ------------------------ | ---------- -codeHash | -4670545 -codeDescriptor | -4670546 -configurationHash | -4670547 -configurationDescriptor | -4670548 -authorityHash | -4670549 -authorityDescriptor | -4670550 -mode | -4670551 -subjectPublicKey | -4670552 -keyUsage | -4670553 +Field | CBOR Label | Major Type +----------------------- | ---------- | ---------- +codeHash | -4670545 | 2 (bstr) +codeDescriptor | -4670546 | 2 (bstr) +configurationHash | -4670547 | 2 (bstr) +configurationDescriptor | -4670548 | 2 (bstr) +authorityHash | -4670549 | 2 (bstr) +authorityDescriptor | -4670550 | 2 (bstr) +mode | -4670551 | 2 (bstr) +subjectPublicKey | -4670552 | 2 (bstr) +keyUsage | -4670553 | 2 (bstr) +profileName | -4670554 | 3 (tstr) The *subjectPublicKey* field contains the public key associated with the subject in the form of a COSE\_Key structure encoded to a CBOR byte string. @@ -793,10 +801,10 @@ in little-endian byte order (i.e. bit 0 is the low-order bit of the first byte). For CDI certificates this should have only the keyCertSign bit set. All other fields have identical semantics to their counterparts in the -[X.509 custom extension](#custom-extension-format). The encoding for each is a -CBOR byte string including *mode* which is a CBOR byte string holding a single -byte (the advantage to using a byte string here is a consistent encoding size -regardless of the value of mode). +[X.509 custom extension](#custom-extension-format). The *mode* field is encoded +as a byte string holding a single byte. The advantage of using a byte string as +opposed to an integer type is a consistent encoding size for all possible +values. # Appendix A: Implementing on Existing Hardware diff --git a/generate_test_values.py b/generate_test_values.py index f4afd4f..41be12f 100644 --- a/generate_test_values.py +++ b/generate_test_values.py @@ -39,7 +39,8 @@ from absl import flags FLAGS = flags.FLAGS -_FILE_HEADER = textwrap.dedent("""\ +_FILE_HEADER = textwrap.dedent( + """\ // Copyright 2020 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); you may not @@ -65,66 +66,88 @@ _FILE_HEADER = textwrap.dedent("""\ namespace dice { namespace test { - """) + """ +) -_FILE_FOOTER = textwrap.dedent("""\ +_FILE_FOOTER = textwrap.dedent( + """\ } // namespace test } // namespace dice #endif // DICE_KNOWN_TEST_VALUES_H_ - """) + """ +) def _to_camel_case(s): - return ''.join(tmp.capitalize() for tmp in s.split('_')) + return "".join(tmp.capitalize() for tmp in s.split("_")) def _read_file(name): try: - with open(name, 'rb') as f: + with open(name, "rb") as f: return f.read() except OSError: - return '' + return "" def _generate_array(name, data): - return 'constexpr uint8_t %s[%d] = {%s};\n\n' % ( - name, len(data), ', '.join('0x%02x' % tmp for tmp in data)) + return "constexpr uint8_t %s[%d] = {%s};\n\n" % ( + name, + len(data), + ", ".join("0x%02x" % tmp for tmp in data), + ) def _generate_cert_comment(data): - return re.sub('^', - '// ', - subprocess.run([ - 'openssl', 'x509', '-inform', 'DER', '-noout', '-text', - '-certopt', 'ext_parse' - ], - input=data, - capture_output=True, - check=True).stdout.decode(), - flags=re.MULTILINE)[:-3] + return re.sub( + "^", + "// ", + subprocess.run( + [ + "openssl", + "x509", + "-inform", + "DER", + "-noout", + "-text", + "-certopt", + "ext_parse", + ], + input=data, + capture_output=True, + check=True, + ).stdout.decode(), + flags=re.MULTILINE, + )[:-3] def _generate_c(name): """Generates C declarations from dumps identified by |name|.""" - content = '' - attest_cdi_data = _read_file('_attest_cdi_%s.bin' % name) - content += _generate_array('kExpectedCdiAttest_%s' % _to_camel_case(name), - attest_cdi_data) - seal_cdi_data = _read_file('_seal_cdi_%s.bin' % name) - content += _generate_array('kExpectedCdiSeal_%s' % _to_camel_case(name), - seal_cdi_data) - for cert_type in ('X509', 'CBOR'): - for key_type in ('Ed25519', 'P256', 'P384'): - var_name = 'kExpected%s%sCert_%s' % (_to_camel_case(cert_type), - _to_camel_case(key_type), - _to_camel_case(name)) - cert_data = _read_file('_%s_%s_cert_%s.cert' % - (cert_type, key_type, name)) - if cert_type == 'X509' and key_type != 'P384': + content = "" + attest_cdi_data = _read_file("_attest_cdi_%s.bin" % name) + content += _generate_array( + "kExpectedCdiAttest_%s" % _to_camel_case(name), attest_cdi_data + ) + seal_cdi_data = _read_file("_seal_cdi_%s.bin" % name) + content += _generate_array( + "kExpectedCdiSeal_%s" % _to_camel_case(name), seal_cdi_data + ) + for cert_type in ("X509", "CBOR"): + for key_type in ("Ed25519", "P256", "P384"): + var_name = "kExpected%s%sCert_%s" % ( + _to_camel_case(cert_type), + _to_camel_case(key_type), + _to_camel_case(name), + ) + cert_data = _read_file( + "_%s_%s_cert_%s.cert" % (cert_type, key_type, name) + ) + if cert_type == "X509" and key_type != "P384": content += ( - '// $ openssl x509 -inform DER -noout -text -certopt ' - 'ext_parse\n') + "// $ openssl x509 -inform DER -noout -text -certopt " + "ext_parse\n" + ) content += _generate_cert_comment(cert_data) content += _generate_array(var_name, cert_data) return content @@ -132,17 +155,17 @@ def _generate_c(name): def main(argv): if len(argv) > 1: - raise app.UsageError('Too many command-line arguments.') + raise app.UsageError("Too many command-line arguments.") content = _FILE_HEADER - content += _generate_c('zero_input') - content += _generate_c('hash_only_input') - content += _generate_c('descriptor_input') + content += _generate_c("zero_input") + content += _generate_c("hash_only_input") + content += _generate_c("descriptor_input") content += _FILE_FOOTER - subprocess.run(['clang-format', '--style=file'], - input=content.encode(), - check=True) + subprocess.run( + ["clang-format", "--style=file"], input=content.encode(), check=True + ) -if __name__ == '__main__': +if __name__ == "__main__": app.run(main) diff --git a/include/dice/android.h b/include/dice/android.h new file mode 100644 index 0000000..5ca1f8b --- /dev/null +++ b/include/dice/android.h @@ -0,0 +1,111 @@ +// Copyright 2021 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); you may not +// use this file except in compliance with the License. You may obtain a copy of +// the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +// 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 DICE_ANDROID_H_ +#define DICE_ANDROID_H_ + +#include <stdbool.h> + +#include "dice/dice.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define DICE_ANDROID_CONFIG_COMPONENT_NAME (1 << 0) +#define DICE_ANDROID_CONFIG_COMPONENT_VERSION (1 << 1) +#define DICE_ANDROID_CONFIG_RESETTABLE (1 << 2) +#define DICE_ANDROID_CONFIG_SECURITY_VERSION (1 << 3) + +// Contains the input values used to construct the Android Profile for DICE +// configuration descriptor. Optional fields are selected in the |inputs| +// bitfield. +// +// Fields: +// configs: A bitfield selecting the config fields to include. +// component_name: Name of the component. +// component_version: Version of the component. +// security_version: Monotonically increasing version of the component. +typedef struct DiceAndroidConfigValues_ { + uint32_t configs; + const char* component_name; + uint64_t component_version; + uint64_t security_version; +} DiceAndroidConfigValues; + +// Formats a configuration descriptor following the Android Profile for DICE +// specification. On success, |actual_size| is set to the number of bytes used. +// If kDiceResultBufferTooSmall is returned |actual_size| will be set to the +// required size of the buffer. +DiceResult DiceAndroidFormatConfigDescriptor( + const DiceAndroidConfigValues* config_values, size_t buffer_size, + uint8_t* buffer, size_t* actual_size); + +// Executes the main Android DICE flow. +// +// Call this instead of DiceMainFlow when the next certificate should be +// appended to an existing Android DICE chain. However, when using +// the Android DICE handover format, use DiceAndroidHandoverMainFlow instead. +// +// Given the current CDIs, a full set of input values, and the current Android +// DICE chain, computes the next CDIs and the extended DICE chain. On success, +// |actual_size| is set to the number of bytes used. If +// kDiceResultBufferTooSmall is returned |actual_size| will be set to the +// required size of the buffer. +DiceResult DiceAndroidMainFlow(void* context, + const uint8_t current_cdi_attest[DICE_CDI_SIZE], + const uint8_t current_cdi_seal[DICE_CDI_SIZE], + const uint8_t* chain, size_t chain_size, + const DiceInputValues* input_values, + size_t buffer_size, uint8_t* buffer, + size_t* actual_size, + uint8_t next_cdi_attest[DICE_CDI_SIZE], + uint8_t next_cdi_seal[DICE_CDI_SIZE]); + +// Executes the main Android DICE handover flow. +// +// Call this instead of DiceAndroidMainFlow when using the Android DICE handover +// format to combine the Android DICE chain and CDIs in a single CBOR object. +// +// Given a full set of input values and the current Android DICE handover +// object, computes the handover data for the next stage. On success, +// |actual_size| is set to the number of bytes used. If +// kDiceResultBufferTooSmall is returned |actual_size| will be set to the +// required size of the buffer. +// +// Using the Android DICE handover object is one option for passing the values +// between boot stages. Passing the bytes between stages is a problem left to +// the caller. +DiceResult DiceAndroidHandoverMainFlow(void* context, const uint8_t* handover, + size_t handover_size, + const DiceInputValues* input_values, + size_t buffer_size, uint8_t* buffer, + size_t* actual_size); + +// Parses an Android DICE handover object to extract the fields. +// +// Given a pointer to an Android DICE handover object, returns pointers to the +// CDIs and DICE chain. If the DICE chain is not included in the handover +// object, the pointer is NULL and the size is 0. +DiceResult DiceAndroidHandoverParse(const uint8_t* handover, + size_t handover_size, + const uint8_t** cdi_attest, + const uint8_t** cdi_seal, + const uint8_t** chain, size_t* chain_size); + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // DICE_ANDROID_H_ diff --git a/include/dice/android/bcc.h b/include/dice/android/bcc.h deleted file mode 100644 index 366c51f..0000000 --- a/include/dice/android/bcc.h +++ /dev/null @@ -1,106 +0,0 @@ -// Copyright 2021 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); you may not -// use this file except in compliance with the License. You may obtain a copy of -// the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -// 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 DICE_ANDROID_BCC_H_ -#define DICE_ANDROID_BCC_H_ - -#include <stdbool.h> - -#include "dice/dice.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#define BCC_INPUT_COMPONENT_NAME (1 << 0) -#define BCC_INPUT_COMPONENT_VERSION (1 << 1) -#define BCC_INPUT_RESETTABLE (1 << 2) - -// Contains the input values used to construct the BCC configuration -// descriptor. Optional fields are selected in the |inputs| bitfield. -// -// Fields: -// inputs: A bitfield selecting which BCC inputs to include. -// component_name: Optional. Name of firmware component / boot stage. -// component_version: Optional. Version of firmware component / boot stage. -typedef struct BccConfigValues_ { - uint32_t inputs; - const char* component_name; - uint64_t component_version; -} BccConfigValues; - -// Formats a configuration descriptor following the BCC's specification. On -// success, |actual_size| is set to the number of bytes used. If -// kDiceResultBufferTooSmall is returned |actual_size| will be set to the -// required size of the buffer. -DiceResult BccFormatConfigDescriptor(const BccConfigValues* input_values, - size_t buffer_size, uint8_t* buffer, - size_t* actual_size); - -// Executes the main BCC flow. -// -// Call this instead of DiceMainFlow when the next certificate should be -// appended to an existing boot certificate chain (BCC). However, when using -// the BCC handover format, use BccHandoverMainFlow instead. -// -// Given a full set of input values along with the current BCC and CDI values, -// computes the next CDI values and matching updated BCC. On success, -// |actual_size| is set to the number of bytes used. If -// kDiceResultBufferTooSmall is returned |actual_size| will be set to the -// required size of the buffer. -DiceResult BccMainFlow(void* context, - const uint8_t current_cdi_attest[DICE_CDI_SIZE], - const uint8_t current_cdi_seal[DICE_CDI_SIZE], - const uint8_t* bcc, size_t bcc_size, - const DiceInputValues* input_values, size_t buffer_size, - uint8_t* buffer, size_t* actual_size, - uint8_t next_cdi_attest[DICE_CDI_SIZE], - uint8_t next_cdi_seal[DICE_CDI_SIZE]); - -// Executes the main BCC handover flow. -// -// Call this instead of BccMainFlow when using the BCC handover format to -// combine the BCC and CDIs in a single CBOR object. -// -// Given a full set of input values and the current BCC handover data, computes -// the next BCC handover data. On success, |actual_size| is set to the number -// of bytes used. If kDiceResultBufferTooSmall is returned |actual_size| will -// be set to the required size of the buffer. -// -// Using a CBOR object to bundle is one option for passing the values passed -// between boot stages. This function can take the current boot stage's bundle -// and produce a bundle for the next stage. Passing the bundle between stages -// is a problem left to the caller. -DiceResult BccHandoverMainFlow(void* context, const uint8_t* bcc_handover, - size_t bcc_handover_size, - const DiceInputValues* input_values, - size_t buffer_size, uint8_t* buffer, - size_t* actual_size); - -// Parses a BCC handover to extract the fields. -// -// Given a pointer to a BCC handover, pointers to the CDIs and, optionally, the -// BCC in the buffer are returned. If the BCC is not included in the handover, -// the pointer is NULL and the size is 0. -DiceResult BccHandoverParse(const uint8_t* bcc_handover, - size_t bcc_handover_size, - const uint8_t** cdi_attest, - const uint8_t** cdi_seal, const uint8_t** bcc, - size_t* bcc_size); - -#ifdef __cplusplus -} // extern "C" -#endif - -#endif // DICE_ANDROID_BCC_H_ diff --git a/include/dice/boringssl_ecdsa_utils.h b/include/dice/boringssl_ecdsa_utils.h index 229926a..f044d37 100644 --- a/include/dice/boringssl_ecdsa_utils.h +++ b/include/dice/boringssl_ecdsa_utils.h @@ -12,8 +12,8 @@ // License for the specific language governing permissions and limitations under // the License. -#ifndef BORINGSSL_ECDSA_UTILS_H_ -#define BORINGSSL_ECDSA_UTILS_H_ +#ifndef DICE_BORINGSSL_ECDSA_UTILS_H_ +#define DICE_BORINGSSL_ECDSA_UTILS_H_ #include <stddef.h> #include <stdint.h> @@ -54,4 +54,4 @@ int P384Verify(const uint8_t* message, size_t message_size, } // extern "C" #endif -#endif // BORINGSSL_ECDSA_UTILS_H_ +#endif // DICE_BORINGSSL_ECDSA_UTILS_H_ diff --git a/include/dice/config/boringssl_ecdsa_p384/dice/config.h b/include/dice/config/boringssl_ecdsa_p384/dice/config.h index a0f9583..e5deb98 100644 --- a/include/dice/config/boringssl_ecdsa_p384/dice/config.h +++ b/include/dice/config/boringssl_ecdsa_p384/dice/config.h @@ -12,8 +12,8 @@ // License for the specific language governing permissions and limitations under // the License. -#ifndef DICE_CONFIG_H_ -#define DICE_CONFIG_H_ +#ifndef DICE_CONFIG_BORINGSSL_ECDSA_P384_DICE_CONFIG_H_ +#define DICE_CONFIG_BORINGSSL_ECDSA_P384_DICE_CONFIG_H_ // ECDSA P384 // From table 1 of RFC 9053 @@ -21,5 +21,6 @@ #define DICE_PUBLIC_KEY_SIZE 96 #define DICE_PRIVATE_KEY_SIZE 48 #define DICE_SIGNATURE_SIZE 96 +#define DICE_PROFILE_NAME "opendice.example.p384" -#endif // DICE_DICE_CONFIG_H_ +#endif // DICE_CONFIG_BORINGSSL_ECDSA_P384_DICE_DICE_CONFIG_H_ diff --git a/include/dice/config/boringssl_ed25519/dice/config.h b/include/dice/config/boringssl_ed25519/dice/config.h index 02097c4..ce5a8be 100644 --- a/include/dice/config/boringssl_ed25519/dice/config.h +++ b/include/dice/config/boringssl_ed25519/dice/config.h @@ -12,8 +12,8 @@ // License for the specific language governing permissions and limitations under // the License. -#ifndef DICE_CONFIG_H_ -#define DICE_CONFIG_H_ +#ifndef DICE_CONFIG_BORINGSSL_ED25519_DICE_CONFIG_H_ +#define DICE_CONFIG_BORINGSSL_ED25519_DICE_CONFIG_H_ // Ed25519 // COSE Key alg value from Table 2 of RFC9053 @@ -21,5 +21,6 @@ #define DICE_PUBLIC_KEY_SIZE 32 #define DICE_PRIVATE_KEY_SIZE 64 #define DICE_SIGNATURE_SIZE 64 +#define DICE_PROFILE_NAME NULL -#endif // DICE_DICE_CONFIG_H_ +#endif // DICE_CONFIG_BORINGSSL_ED25519_DICE_DICE_CONFIG_H_ diff --git a/include/dice/config/mbedtls_ecdsa_p256/dice/config.h b/include/dice/config/mbedtls_ecdsa_p256/dice/config.h index 11f4875..107e4d5 100644 --- a/include/dice/config/mbedtls_ecdsa_p256/dice/config.h +++ b/include/dice/config/mbedtls_ecdsa_p256/dice/config.h @@ -12,12 +12,13 @@ // License for the specific language governing permissions and limitations under // the License. -#ifndef DICE_CONFIG_H_ -#define DICE_CONFIG_H_ +#ifndef DICE_CONFIG_MBEDTLS_ECDSA_P256_DICE_CONFIG_H_ +#define DICE_CONFIG_MBEDTLS_ECDSA_P256_DICE_CONFIG_H_ // ECDSA-P256 #define DICE_PUBLIC_KEY_SIZE 33 #define DICE_PRIVATE_KEY_SIZE 32 #define DICE_SIGNATURE_SIZE 64 +#define DICE_PROFILE_NAME "openssl.example.p256" -#endif // DICE_DICE_CONFIG_H_ +#endif // DICE_CONFIG_MBEDTLS_ECDSA_P256_DICE_DICE_CONFIG_H_ diff --git a/include/dice/config/standalone/dice/config.h b/include/dice/config/standalone/dice/config.h index 5f6188f..d71ec76 100644 --- a/include/dice/config/standalone/dice/config.h +++ b/include/dice/config/standalone/dice/config.h @@ -12,8 +12,8 @@ // License for the specific language governing permissions and limitations under // the License. -#ifndef DICE_CONFIG_H_ -#define DICE_CONFIG_H_ +#ifndef DICE_CONFIG_STANDALONE_DICE_CONFIG_H_ +#define DICE_CONFIG_STANDALONE_DICE_CONFIG_H_ // The standalone config is only used for testing. In particular, it is used // for tests that focus on the core aspects of the library and not the ops. @@ -22,5 +22,6 @@ #define DICE_PUBLIC_KEY_SIZE 1 #define DICE_PRIVATE_KEY_SIZE 1 #define DICE_SIGNATURE_SIZE 1 +#define DICE_PROFILE_NAME NULL -#endif // DICE_DICE_CONFIG_H_ +#endif // DICE_CONFIG_STANDALONE_DICE_CONFIG_H_ diff --git a/include/dice/fuzz_utils.h b/include/dice/fuzz_utils.h index dfc483d..26a45c6 100644 --- a/include/dice/fuzz_utils.h +++ b/include/dice/fuzz_utils.h @@ -12,6 +12,9 @@ // License for the specific language governing permissions and limitations under // the License. +#ifndef DICE_FUZZ_UTILS_H_ +#define DICE_FUZZ_UTILS_H_ + #include <cstdint> #include <vector> @@ -70,3 +73,5 @@ struct FuzzedInputValues { } // namespace fuzz } // namespace dice + +#endif // DICE_FUZZ_UTILS_H_ diff --git a/include/dice/known_test_values.h b/include/dice/known_test_values.h index cb0925b..a74ed1d 100644 --- a/include/dice/known_test_values.h +++ b/include/dice/known_test_values.h @@ -179,7 +179,7 @@ constexpr uint8_t kExpectedX509Ed25519Cert_ZeroInput[638] = { // X509v3 Basic Constraints: critical // CA:TRUE // 1.3.6.1.4.1.11129.2.1.24: critical -// 0:d=0 hl=3 l= 209 cons: SEQUENCE +// 0:d=0 hl=3 l= 233 cons: SEQUENCE // 3:d=1 hl=2 l= 66 cons: cont [ 0 ] // 5:d=2 hl=2 l= 64 prim: OCTET STRING // 0000 - 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ @@ -200,15 +200,17 @@ constexpr uint8_t kExpectedX509Ed25519Cert_ZeroInput[638] = { // 0030 - 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ // 207:d=1 hl=2 l= 3 cons: cont [ 6 ] // 209:d=2 hl=2 l= 1 prim: ENUMERATED :00 +// 212:d=1 hl=2 l= 22 cons: cont [ 7 ] +// 214:d=2 hl=2 l= 20 prim: UTF8STRING :openssl.example.p256 // // Signature Algorithm: ecdsa-with-SHA512 // Signature Value: -// 30:44:02:20:5c:20:d4:32:af:59:4b:44:fc:49:e5:d4:5d:b6: -// fe:9c:ac:55:02:74:8b:66:c8:8c:f5:9a:70:8a:97:3c:bc:e0: -// 02:20:66:83:d1:78:8c:75:44:83:90:c7:1e:d7:4c:98:1f:10: -// 7f:14:6a:45:c0:1c:48:99:ce:6e:8f:6d:d3:dc:f3:93 -constexpr uint8_t kExpectedX509P256Cert_ZeroInput[705] = { - 0x30, 0x82, 0x02, 0xbd, 0x30, 0x82, 0x02, 0x62, 0xa0, 0x03, 0x02, 0x01, +// 30:46:02:21:00:a8:d1:e1:d1:7b:89:bf:a3:f1:8c:fa:43:fa: +// 77:bf:83:ef:28:cb:54:d1:f5:29:e4:f3:05:99:e2:7a:d0:33: +// 13:02:21:00:d7:9c:82:91:6b:a0:ca:70:48:76:03:95:1c:a4: +// 6d:f0:44:ed:ba:02:2d:9a:e4:bf:f2:92:f6:78:ce:08:01:26 +constexpr uint8_t kExpectedX509P256Cert_ZeroInput[731] = { + 0x30, 0x82, 0x02, 0xd7, 0x30, 0x82, 0x02, 0x7a, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x14, 0x7c, 0x7d, 0xc0, 0xa3, 0xc1, 0xe7, 0x8d, 0x4e, 0x68, 0xbc, 0xc1, 0xa2, 0x32, 0x9e, 0xf9, 0x1c, 0xa8, 0x12, 0x44, 0x91, 0x30, 0x0c, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x04, 0x05, @@ -231,7 +233,7 @@ constexpr uint8_t kExpectedX509P256Cert_ZeroInput[705] = { 0x06, 0x02, 0xae, 0xc2, 0x69, 0x54, 0x1c, 0x6b, 0xe7, 0xeb, 0x40, 0x19, 0xab, 0x55, 0xc6, 0x6b, 0xc8, 0x8b, 0xb8, 0xb4, 0x69, 0xad, 0x7e, 0xe8, 0x58, 0x9e, 0x07, 0xd2, 0xf8, 0xbc, 0x88, 0x8e, 0xb3, 0x11, 0xc2, 0xdf, - 0x97, 0x3b, 0x1b, 0x4a, 0xa3, 0x82, 0x01, 0x4e, 0x30, 0x82, 0x01, 0x4a, + 0x97, 0x3b, 0x1b, 0x4a, 0xa3, 0x82, 0x01, 0x66, 0x30, 0x82, 0x01, 0x62, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0x4c, 0x51, 0x4d, 0x88, 0xdb, 0x0f, 0x81, 0xd5, 0x7b, 0xeb, 0x96, 0x17, 0x7e, 0x3d, 0x7e, 0xa4, 0xaa, 0x58, 0x1e, 0x66, 0x30, 0x1d, 0x06, @@ -240,9 +242,9 @@ constexpr uint8_t kExpectedX509P256Cert_ZeroInput[705] = { 0xa8, 0x12, 0x44, 0x91, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, 0x03, 0x02, 0x02, 0x04, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, - 0xff, 0x30, 0x81, 0xe6, 0x06, 0x0a, 0x2b, 0x06, 0x01, 0x04, 0x01, 0xd6, - 0x79, 0x02, 0x01, 0x18, 0x01, 0x01, 0xff, 0x04, 0x81, 0xd4, 0x30, 0x81, - 0xd1, 0xa0, 0x42, 0x04, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xff, 0x30, 0x81, 0xfe, 0x06, 0x0a, 0x2b, 0x06, 0x01, 0x04, 0x01, 0xd6, + 0x79, 0x02, 0x01, 0x18, 0x01, 0x01, 0xff, 0x04, 0x81, 0xec, 0x30, 0x81, + 0xe9, 0xa0, 0x42, 0x04, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, @@ -259,14 +261,16 @@ constexpr uint8_t kExpectedX509P256Cert_ZeroInput[705] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0xa6, 0x03, 0x0a, 0x01, 0x00, 0x30, 0x0c, 0x06, 0x08, 0x2a, 0x86, - 0x48, 0xce, 0x3d, 0x04, 0x03, 0x04, 0x05, 0x00, 0x03, 0x47, 0x00, 0x30, - 0x44, 0x02, 0x20, 0x5c, 0x20, 0xd4, 0x32, 0xaf, 0x59, 0x4b, 0x44, 0xfc, - 0x49, 0xe5, 0xd4, 0x5d, 0xb6, 0xfe, 0x9c, 0xac, 0x55, 0x02, 0x74, 0x8b, - 0x66, 0xc8, 0x8c, 0xf5, 0x9a, 0x70, 0x8a, 0x97, 0x3c, 0xbc, 0xe0, 0x02, - 0x20, 0x66, 0x83, 0xd1, 0x78, 0x8c, 0x75, 0x44, 0x83, 0x90, 0xc7, 0x1e, - 0xd7, 0x4c, 0x98, 0x1f, 0x10, 0x7f, 0x14, 0x6a, 0x45, 0xc0, 0x1c, 0x48, - 0x99, 0xce, 0x6e, 0x8f, 0x6d, 0xd3, 0xdc, 0xf3, 0x93}; + 0x00, 0xa6, 0x03, 0x0a, 0x01, 0x00, 0xa7, 0x16, 0x0c, 0x14, 0x6f, 0x70, + 0x65, 0x6e, 0x73, 0x73, 0x6c, 0x2e, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, + 0x65, 0x2e, 0x70, 0x32, 0x35, 0x36, 0x30, 0x0c, 0x06, 0x08, 0x2a, 0x86, + 0x48, 0xce, 0x3d, 0x04, 0x03, 0x04, 0x05, 0x00, 0x03, 0x49, 0x00, 0x30, + 0x46, 0x02, 0x21, 0x00, 0xa8, 0xd1, 0xe1, 0xd1, 0x7b, 0x89, 0xbf, 0xa3, + 0xf1, 0x8c, 0xfa, 0x43, 0xfa, 0x77, 0xbf, 0x83, 0xef, 0x28, 0xcb, 0x54, + 0xd1, 0xf5, 0x29, 0xe4, 0xf3, 0x05, 0x99, 0xe2, 0x7a, 0xd0, 0x33, 0x13, + 0x02, 0x21, 0x00, 0xd7, 0x9c, 0x82, 0x91, 0x6b, 0xa0, 0xca, 0x70, 0x48, + 0x76, 0x03, 0x95, 0x1c, 0xa4, 0x6d, 0xf0, 0x44, 0xed, 0xba, 0x02, 0x2d, + 0x9a, 0xe4, 0xbf, 0xf2, 0x92, 0xf6, 0x78, 0xce, 0x08, 0x01, 0x26}; constexpr uint8_t kExpectedX509P384Cert_ZeroInput[0] = {}; @@ -311,8 +315,8 @@ constexpr uint8_t kExpectedCborEd25519Cert_ZeroInput[441] = { constexpr uint8_t kExpectedCborP256Cert_ZeroInput[0] = {}; -constexpr uint8_t kExpectedCborP384Cert_ZeroInput[542] = { - 0x84, 0x44, 0xa1, 0x01, 0x38, 0x22, 0xa0, 0x59, 0x01, 0xb2, 0xa8, 0x01, +constexpr uint8_t kExpectedCborP384Cert_ZeroInput[569] = { + 0x84, 0x44, 0xa1, 0x01, 0x38, 0x22, 0xa0, 0x59, 0x01, 0xcd, 0xa9, 0x01, 0x78, 0x28, 0x30, 0x34, 0x63, 0x32, 0x36, 0x35, 0x66, 0x65, 0x30, 0x36, 0x66, 0x66, 0x32, 0x33, 0x30, 0x65, 0x33, 0x39, 0x62, 0x36, 0x33, 0x32, 0x32, 0x65, 0x65, 0x61, 0x39, 0x65, 0x30, 0x31, 0x30, 0x37, 0x31, 0x31, @@ -349,15 +353,17 @@ constexpr uint8_t kExpectedCborP384Cert_ZeroInput[542] = { 0xfc, 0xe0, 0x3c, 0xdc, 0x5d, 0x1b, 0x58, 0x16, 0x69, 0xdd, 0x44, 0x24, 0x67, 0xbf, 0x21, 0xd7, 0x47, 0xf3, 0x13, 0xd1, 0x47, 0x6c, 0x4b, 0xd3, 0x05, 0xb5, 0x29, 0xa0, 0xf1, 0x3a, 0x00, 0x47, 0x44, 0x58, 0x41, 0x20, - 0x58, 0x60, 0x2b, 0xe7, 0xe6, 0xee, 0xd2, 0x40, 0xa4, 0xf6, 0x2b, 0x30, - 0xda, 0x0d, 0x60, 0x89, 0xa4, 0x0c, 0x99, 0xa6, 0x95, 0x85, 0x77, 0xae, - 0xe8, 0x7f, 0xcd, 0x66, 0x81, 0xca, 0xd1, 0x5c, 0x56, 0xcf, 0x62, 0x05, - 0xa8, 0xb8, 0x66, 0x66, 0x46, 0x39, 0xc7, 0x9a, 0x7a, 0x47, 0xe4, 0x64, - 0xee, 0x36, 0xd9, 0x40, 0x8d, 0xd4, 0x88, 0x82, 0xbf, 0x24, 0x70, 0x56, - 0x03, 0x23, 0x6a, 0x45, 0x39, 0x38, 0xa2, 0xdd, 0x02, 0x18, 0x7e, 0x72, - 0x89, 0xe5, 0xf9, 0x38, 0xfe, 0xef, 0x50, 0xf4, 0x31, 0xae, 0xb4, 0xbe, - 0x33, 0xb2, 0x22, 0xd4, 0x34, 0x16, 0xa6, 0x53, 0x49, 0xe1, 0x54, 0x1a, - 0x9d, 0x3e}; + 0x3a, 0x00, 0x47, 0x44, 0x59, 0x75, 0x6f, 0x70, 0x65, 0x6e, 0x64, 0x69, + 0x63, 0x65, 0x2e, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x70, + 0x33, 0x38, 0x34, 0x58, 0x60, 0x19, 0x40, 0xb7, 0x32, 0x81, 0xdd, 0x03, + 0x7b, 0x0f, 0x35, 0xd2, 0x5a, 0x01, 0x85, 0x5b, 0xbc, 0xea, 0xb4, 0x0d, + 0x83, 0xec, 0x6a, 0x33, 0x6d, 0x2d, 0xa0, 0x7d, 0xa6, 0x2e, 0xe8, 0x64, + 0xdc, 0x51, 0x71, 0xa0, 0x76, 0x3e, 0x5b, 0x4e, 0xee, 0x4a, 0xa1, 0x1a, + 0xd2, 0xd4, 0xaf, 0x38, 0x86, 0xa7, 0xd8, 0x62, 0xce, 0x55, 0xdc, 0x14, + 0x8c, 0x08, 0xda, 0xcb, 0x0a, 0x82, 0x1f, 0x89, 0x6e, 0x75, 0x08, 0xa1, + 0x14, 0xe8, 0x74, 0xdf, 0xf9, 0x01, 0x6b, 0x1b, 0x69, 0xb5, 0xba, 0x6e, + 0xec, 0x4b, 0x27, 0x04, 0xcf, 0xff, 0x5f, 0x07, 0xbe, 0x60, 0xf2, 0x8d, + 0x07, 0x4a, 0xe6, 0xa1, 0xa3}; constexpr uint8_t kExpectedCdiAttest_HashOnlyInput[32] = { 0x08, 0x4e, 0xf4, 0x06, 0xc6, 0x9b, 0xa7, 0x4b, 0x1e, 0x24, 0xd0, @@ -515,7 +521,7 @@ constexpr uint8_t kExpectedX509Ed25519Cert_HashOnlyInput[638] = { // X509v3 Basic Constraints: critical // CA:TRUE // 1.3.6.1.4.1.11129.2.1.24: critical -// 0:d=0 hl=3 l= 209 cons: SEQUENCE +// 0:d=0 hl=3 l= 233 cons: SEQUENCE // 3:d=1 hl=2 l= 66 cons: cont [ 0 ] // 5:d=2 hl=2 l= 64 prim: OCTET STRING // 0000 - b7 d4 0c cb 22 5b a5 78-8f 98 ff 9e 86 93 75 f6 ...."[.x......u. @@ -536,15 +542,17 @@ constexpr uint8_t kExpectedX509Ed25519Cert_HashOnlyInput[638] = { // 0030 - 94 4f be 1b 21 f9 cc 23-73 41 b6 b9 b6 98 d0 bc .O..!..#sA...... // 207:d=1 hl=2 l= 3 cons: cont [ 6 ] // 209:d=2 hl=2 l= 1 prim: ENUMERATED :00 +// 212:d=1 hl=2 l= 22 cons: cont [ 7 ] +// 214:d=2 hl=2 l= 20 prim: UTF8STRING :openssl.example.p256 // // Signature Algorithm: ecdsa-with-SHA512 // Signature Value: -// 30:46:02:21:00:d0:ff:60:84:d4:74:47:eb:f4:29:86:c5:2a: -// 12:01:f9:7e:5b:ab:fd:fe:d3:11:75:bc:26:63:71:57:2b:b1: -// c8:02:21:00:e0:16:72:65:b0:4a:92:ca:c6:c9:e2:0f:50:f0: -// 1c:70:01:64:a7:8d:7d:51:e9:59:fe:e6:7f:31:28:30:04:04 -constexpr uint8_t kExpectedX509P256Cert_HashOnlyInput[707] = { - 0x30, 0x82, 0x02, 0xbf, 0x30, 0x82, 0x02, 0x62, 0xa0, 0x03, 0x02, 0x01, +// 30:44:02:20:2a:d1:3e:6f:ee:42:e2:d0:64:b8:1c:bd:de:fe: +// 49:2f:2e:4f:80:3c:66:52:05:95:2a:d9:87:7a:6d:47:44:bf: +// 02:20:6e:1c:5a:a0:62:00:17:61:f9:c3:93:17:72:1a:ce:28: +// 3d:c7:7d:35:22:de:b3:d6:3d:b2:6e:75:c9:f0:c1:73 +constexpr uint8_t kExpectedX509P256Cert_HashOnlyInput[729] = { + 0x30, 0x82, 0x02, 0xd5, 0x30, 0x82, 0x02, 0x7a, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x14, 0x68, 0x49, 0x58, 0xd9, 0xae, 0xa7, 0x2e, 0xbf, 0x7c, 0x06, 0xaf, 0x20, 0x03, 0xb6, 0x44, 0x47, 0x82, 0x4a, 0x62, 0x71, 0x30, 0x0c, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x04, 0x05, @@ -567,7 +575,7 @@ constexpr uint8_t kExpectedX509P256Cert_HashOnlyInput[707] = { 0xfb, 0x6d, 0x57, 0x18, 0xfc, 0x8f, 0x6f, 0x0b, 0x09, 0x1a, 0x19, 0xea, 0x10, 0x7e, 0xa9, 0x38, 0xf4, 0x45, 0x33, 0xc1, 0x66, 0x5b, 0xbc, 0xfc, 0x0a, 0x6e, 0x98, 0x99, 0x72, 0x88, 0xc1, 0xad, 0x0e, 0x15, 0xc2, 0x85, - 0x77, 0x75, 0x00, 0x0b, 0xa3, 0x82, 0x01, 0x4e, 0x30, 0x82, 0x01, 0x4a, + 0x77, 0x75, 0x00, 0x0b, 0xa3, 0x82, 0x01, 0x66, 0x30, 0x82, 0x01, 0x62, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0x1b, 0xe5, 0x68, 0x79, 0x33, 0xdb, 0x3d, 0x9c, 0xd5, 0xfc, 0xa7, 0x29, 0xe8, 0x1d, 0x66, 0x85, 0x46, 0x5a, 0x7b, 0xf1, 0x30, 0x1d, 0x06, @@ -576,9 +584,9 @@ constexpr uint8_t kExpectedX509P256Cert_HashOnlyInput[707] = { 0x82, 0x4a, 0x62, 0x71, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, 0x03, 0x02, 0x02, 0x04, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, - 0xff, 0x30, 0x81, 0xe6, 0x06, 0x0a, 0x2b, 0x06, 0x01, 0x04, 0x01, 0xd6, - 0x79, 0x02, 0x01, 0x18, 0x01, 0x01, 0xff, 0x04, 0x81, 0xd4, 0x30, 0x81, - 0xd1, 0xa0, 0x42, 0x04, 0x40, 0xb7, 0xd4, 0x0c, 0xcb, 0x22, 0x5b, 0xa5, + 0xff, 0x30, 0x81, 0xfe, 0x06, 0x0a, 0x2b, 0x06, 0x01, 0x04, 0x01, 0xd6, + 0x79, 0x02, 0x01, 0x18, 0x01, 0x01, 0xff, 0x04, 0x81, 0xec, 0x30, 0x81, + 0xe9, 0xa0, 0x42, 0x04, 0x40, 0xb7, 0xd4, 0x0c, 0xcb, 0x22, 0x5b, 0xa5, 0x78, 0x8f, 0x98, 0xff, 0x9e, 0x86, 0x93, 0x75, 0xf6, 0x90, 0xac, 0x50, 0xcf, 0x9e, 0xbd, 0x0a, 0xfe, 0xb1, 0xd9, 0xc2, 0x4e, 0x52, 0x19, 0xe4, 0xde, 0x29, 0xe5, 0x61, 0xf3, 0xf9, 0x29, 0xe8, 0x40, 0x87, 0x7a, 0xdd, @@ -595,14 +603,16 @@ constexpr uint8_t kExpectedX509P256Cert_HashOnlyInput[707] = { 0x6a, 0x4e, 0x36, 0xd7, 0x6a, 0x61, 0x39, 0x08, 0x21, 0xd4, 0xfe, 0x92, 0x5f, 0x36, 0x2d, 0xeb, 0x5d, 0xbb, 0x32, 0x8b, 0xe3, 0x94, 0x4f, 0xbe, 0x1b, 0x21, 0xf9, 0xcc, 0x23, 0x73, 0x41, 0xb6, 0xb9, 0xb6, 0x98, 0xd0, - 0xbc, 0xa6, 0x03, 0x0a, 0x01, 0x00, 0x30, 0x0c, 0x06, 0x08, 0x2a, 0x86, - 0x48, 0xce, 0x3d, 0x04, 0x03, 0x04, 0x05, 0x00, 0x03, 0x49, 0x00, 0x30, - 0x46, 0x02, 0x21, 0x00, 0xd0, 0xff, 0x60, 0x84, 0xd4, 0x74, 0x47, 0xeb, - 0xf4, 0x29, 0x86, 0xc5, 0x2a, 0x12, 0x01, 0xf9, 0x7e, 0x5b, 0xab, 0xfd, - 0xfe, 0xd3, 0x11, 0x75, 0xbc, 0x26, 0x63, 0x71, 0x57, 0x2b, 0xb1, 0xc8, - 0x02, 0x21, 0x00, 0xe0, 0x16, 0x72, 0x65, 0xb0, 0x4a, 0x92, 0xca, 0xc6, - 0xc9, 0xe2, 0x0f, 0x50, 0xf0, 0x1c, 0x70, 0x01, 0x64, 0xa7, 0x8d, 0x7d, - 0x51, 0xe9, 0x59, 0xfe, 0xe6, 0x7f, 0x31, 0x28, 0x30, 0x04, 0x04}; + 0xbc, 0xa6, 0x03, 0x0a, 0x01, 0x00, 0xa7, 0x16, 0x0c, 0x14, 0x6f, 0x70, + 0x65, 0x6e, 0x73, 0x73, 0x6c, 0x2e, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, + 0x65, 0x2e, 0x70, 0x32, 0x35, 0x36, 0x30, 0x0c, 0x06, 0x08, 0x2a, 0x86, + 0x48, 0xce, 0x3d, 0x04, 0x03, 0x04, 0x05, 0x00, 0x03, 0x47, 0x00, 0x30, + 0x44, 0x02, 0x20, 0x2a, 0xd1, 0x3e, 0x6f, 0xee, 0x42, 0xe2, 0xd0, 0x64, + 0xb8, 0x1c, 0xbd, 0xde, 0xfe, 0x49, 0x2f, 0x2e, 0x4f, 0x80, 0x3c, 0x66, + 0x52, 0x05, 0x95, 0x2a, 0xd9, 0x87, 0x7a, 0x6d, 0x47, 0x44, 0xbf, 0x02, + 0x20, 0x6e, 0x1c, 0x5a, 0xa0, 0x62, 0x00, 0x17, 0x61, 0xf9, 0xc3, 0x93, + 0x17, 0x72, 0x1a, 0xce, 0x28, 0x3d, 0xc7, 0x7d, 0x35, 0x22, 0xde, 0xb3, + 0xd6, 0x3d, 0xb2, 0x6e, 0x75, 0xc9, 0xf0, 0xc1, 0x73}; constexpr uint8_t kExpectedX509P384Cert_HashOnlyInput[0] = {}; @@ -647,8 +657,8 @@ constexpr uint8_t kExpectedCborEd25519Cert_HashOnlyInput[441] = { constexpr uint8_t kExpectedCborP256Cert_HashOnlyInput[0] = {}; -constexpr uint8_t kExpectedCborP384Cert_HashOnlyInput[542] = { - 0x84, 0x44, 0xa1, 0x01, 0x38, 0x22, 0xa0, 0x59, 0x01, 0xb2, 0xa8, 0x01, +constexpr uint8_t kExpectedCborP384Cert_HashOnlyInput[569] = { + 0x84, 0x44, 0xa1, 0x01, 0x38, 0x22, 0xa0, 0x59, 0x01, 0xcd, 0xa9, 0x01, 0x78, 0x28, 0x35, 0x64, 0x38, 0x62, 0x36, 0x62, 0x65, 0x37, 0x63, 0x65, 0x33, 0x65, 0x64, 0x65, 0x36, 0x61, 0x32, 0x34, 0x31, 0x38, 0x30, 0x31, 0x34, 0x35, 0x32, 0x33, 0x65, 0x36, 0x63, 0x39, 0x64, 0x63, 0x38, 0x37, @@ -685,15 +695,17 @@ constexpr uint8_t kExpectedCborP384Cert_HashOnlyInput[542] = { 0x5c, 0x90, 0xfb, 0x4b, 0x6d, 0x96, 0x42, 0x77, 0xe2, 0xf6, 0x58, 0x3d, 0x37, 0xa7, 0x3d, 0x2e, 0xca, 0xd1, 0x2c, 0xa4, 0xd4, 0xa7, 0xaf, 0x25, 0xc3, 0xb2, 0xe7, 0x34, 0xf5, 0x3a, 0x00, 0x47, 0x44, 0x58, 0x41, 0x20, - 0x58, 0x60, 0xd3, 0xbc, 0x6f, 0x53, 0x2c, 0x6a, 0x35, 0x3b, 0x2d, 0x7c, - 0x4f, 0x1e, 0x1f, 0x06, 0xcf, 0x52, 0x87, 0xc2, 0xbe, 0x1c, 0x2c, 0xd1, - 0x12, 0xd8, 0x13, 0x8e, 0xe4, 0xc8, 0x15, 0x65, 0x89, 0x97, 0xba, 0xc4, - 0x80, 0xd2, 0xaf, 0xd2, 0xd0, 0xf8, 0x4b, 0xa1, 0xf6, 0x24, 0x5a, 0xd2, - 0x25, 0x59, 0x7e, 0xb5, 0x6d, 0xe2, 0xae, 0x0a, 0x37, 0x4d, 0x50, 0x31, - 0x8e, 0xc3, 0x21, 0xee, 0xf4, 0xf6, 0x7f, 0x16, 0xfd, 0xa3, 0x06, 0x27, - 0x56, 0x0f, 0x74, 0xb7, 0xf8, 0x4c, 0xba, 0xb0, 0xc5, 0x93, 0xce, 0xe3, - 0x24, 0x9c, 0x04, 0xdb, 0xac, 0x26, 0x14, 0xc6, 0x05, 0x04, 0xdb, 0x49, - 0x5f, 0xe0}; + 0x3a, 0x00, 0x47, 0x44, 0x59, 0x75, 0x6f, 0x70, 0x65, 0x6e, 0x64, 0x69, + 0x63, 0x65, 0x2e, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x70, + 0x33, 0x38, 0x34, 0x58, 0x60, 0x08, 0x82, 0x40, 0x67, 0xcb, 0x0b, 0x5d, + 0x98, 0x3b, 0x7b, 0xf0, 0x9c, 0x5f, 0x32, 0x47, 0xb4, 0x5d, 0xb9, 0x7a, + 0xce, 0x1c, 0x55, 0x35, 0xc2, 0x18, 0x2d, 0xcb, 0x4b, 0xc1, 0xa7, 0xd2, + 0xfa, 0x1e, 0x17, 0xa9, 0x61, 0xd5, 0x2a, 0x9f, 0x8c, 0x8e, 0x72, 0xc7, + 0x60, 0x2e, 0x11, 0x59, 0x3a, 0xe9, 0x7d, 0x90, 0x00, 0x03, 0x67, 0xb7, + 0x17, 0xc1, 0x95, 0x07, 0x04, 0xec, 0x81, 0x11, 0x21, 0x19, 0x4b, 0x22, + 0x35, 0xbe, 0x93, 0xc8, 0xb8, 0x78, 0xb5, 0x16, 0xb9, 0x6e, 0x7b, 0xf6, + 0x50, 0xe8, 0xf4, 0x81, 0xc2, 0xf4, 0x1c, 0x4b, 0xe2, 0x8d, 0x9d, 0x80, + 0xcb, 0x34, 0x15, 0xc5, 0x63}; constexpr uint8_t kExpectedCdiAttest_DescriptorInput[32] = { 0x20, 0xd5, 0x0c, 0x68, 0x5a, 0xd9, 0xe2, 0xdf, 0x77, 0x60, 0x78, @@ -890,7 +902,7 @@ constexpr uint8_t kExpectedX509Ed25519Cert_DescriptorInput[858] = { // X509v3 Basic Constraints: critical // CA:TRUE // 1.3.6.1.4.1.11129.2.1.24: critical -// 0:d=0 hl=4 l= 426 cons: SEQUENCE +// 0:d=0 hl=4 l= 450 cons: SEQUENCE // 4:d=1 hl=2 l= 66 cons: cont [ 0 ] // 6:d=2 hl=2 l= 64 prim: OCTET STRING // 0000 - b7 d4 0c cb 22 5b a5 78-8f 98 ff 9e 86 93 75 f6 ...."[.x......u. @@ -932,15 +944,17 @@ constexpr uint8_t kExpectedX509Ed25519Cert_DescriptorInput[858] = { // 0040 - a2 . // 425:d=1 hl=2 l= 3 cons: cont [ 6 ] // 427:d=2 hl=2 l= 1 prim: ENUMERATED :00 +// 430:d=1 hl=2 l= 22 cons: cont [ 7 ] +// 432:d=2 hl=2 l= 20 prim: UTF8STRING :openssl.example.p256 // // Signature Algorithm: ecdsa-with-SHA512 // Signature Value: -// 30:46:02:21:00:a9:57:7d:ac:e0:80:8e:1c:7a:e1:4d:7d:2a: -// 52:d2:5e:fb:5a:7d:45:1e:fa:67:17:04:9e:b3:05:c2:34:f0: -// 7a:02:21:00:b7:3a:31:25:ae:1d:2b:06:8b:ba:44:d9:3a:bf: -// 8b:e2:3f:89:e2:a6:14:0c:fa:c2:b1:dd:0c:0a:78:ac:60:19 -constexpr uint8_t kExpectedX509P256Cert_DescriptorInput[927] = { - 0x30, 0x82, 0x03, 0x9b, 0x30, 0x82, 0x03, 0x3e, 0xa0, 0x03, 0x02, 0x01, +// 30:45:02:20:4f:55:9a:0c:2a:48:d5:51:fe:a1:b9:40:e7:95: +// 97:d0:48:0a:de:71:bf:aa:19:5f:51:3d:d9:4c:df:a8:69:a8: +// 02:21:00:d4:8c:28:58:8e:3c:4e:b6:98:76:24:2b:92:c5:8c: +// 42:8c:88:a7:58:35:3d:b5:0e:18:a5:6f:2d:d3:0c:4c:33 +constexpr uint8_t kExpectedX509P256Cert_DescriptorInput[950] = { + 0x30, 0x82, 0x03, 0xb2, 0x30, 0x82, 0x03, 0x56, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x14, 0x2c, 0x0d, 0xe9, 0x55, 0xc4, 0xfa, 0x08, 0x2c, 0x2c, 0x3a, 0x0b, 0x40, 0x66, 0x59, 0xaf, 0xa1, 0xc1, 0xc0, 0x84, 0x6c, 0x30, 0x0c, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x04, 0x05, @@ -963,7 +977,7 @@ constexpr uint8_t kExpectedX509P256Cert_DescriptorInput[927] = { 0x9b, 0x27, 0xf3, 0x87, 0x97, 0xb3, 0xe7, 0x36, 0xe6, 0x42, 0x87, 0x8c, 0x72, 0xde, 0xf7, 0xaf, 0x2d, 0xc6, 0x23, 0x00, 0xb1, 0x2b, 0x4e, 0x1c, 0xf3, 0xaf, 0x67, 0xf0, 0x9b, 0x88, 0x40, 0x79, 0x3b, 0x09, 0x78, 0x30, - 0x51, 0x65, 0x38, 0x61, 0xa3, 0x82, 0x02, 0x2a, 0x30, 0x82, 0x02, 0x26, + 0x51, 0x65, 0x38, 0x61, 0xa3, 0x82, 0x02, 0x42, 0x30, 0x82, 0x02, 0x3e, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0x1b, 0xe5, 0x68, 0x79, 0x33, 0xdb, 0x3d, 0x9c, 0xd5, 0xfc, 0xa7, 0x29, 0xe8, 0x1d, 0x66, 0x85, 0x46, 0x5a, 0x7b, 0xf1, 0x30, 0x1d, 0x06, @@ -972,9 +986,9 @@ constexpr uint8_t kExpectedX509P256Cert_DescriptorInput[927] = { 0xc1, 0xc0, 0x84, 0x6c, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, 0x03, 0x02, 0x02, 0x04, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, - 0xff, 0x30, 0x82, 0x01, 0xc1, 0x06, 0x0a, 0x2b, 0x06, 0x01, 0x04, 0x01, - 0xd6, 0x79, 0x02, 0x01, 0x18, 0x01, 0x01, 0xff, 0x04, 0x82, 0x01, 0xae, - 0x30, 0x82, 0x01, 0xaa, 0xa0, 0x42, 0x04, 0x40, 0xb7, 0xd4, 0x0c, 0xcb, + 0xff, 0x30, 0x82, 0x01, 0xd9, 0x06, 0x0a, 0x2b, 0x06, 0x01, 0x04, 0x01, + 0xd6, 0x79, 0x02, 0x01, 0x18, 0x01, 0x01, 0xff, 0x04, 0x82, 0x01, 0xc6, + 0x30, 0x82, 0x01, 0xc2, 0xa0, 0x42, 0x04, 0x40, 0xb7, 0xd4, 0x0c, 0xcb, 0x22, 0x5b, 0xa5, 0x78, 0x8f, 0x98, 0xff, 0x9e, 0x86, 0x93, 0x75, 0xf6, 0x90, 0xac, 0x50, 0xcf, 0x9e, 0xbd, 0x0a, 0xfe, 0xb1, 0xd9, 0xc2, 0x4e, 0x52, 0x19, 0xe4, 0xde, 0x29, 0xe5, 0x61, 0xf3, 0xf9, 0x29, 0xe8, 0x40, @@ -1009,15 +1023,17 @@ constexpr uint8_t kExpectedX509P256Cert_DescriptorInput[927] = { 0x11, 0x2d, 0x08, 0x4d, 0x7c, 0x39, 0x76, 0xdc, 0x73, 0xe7, 0x1c, 0x16, 0x62, 0xd5, 0x59, 0xd7, 0x49, 0x2b, 0x6a, 0xa2, 0x36, 0x67, 0x57, 0xd1, 0xf2, 0xf9, 0xaf, 0x13, 0xd7, 0xa3, 0xe4, 0xd3, 0x39, 0x5b, 0x02, 0x78, - 0xb1, 0xe0, 0x09, 0x70, 0xa2, 0xa6, 0x03, 0x0a, 0x01, 0x00, 0x30, 0x0c, + 0xb1, 0xe0, 0x09, 0x70, 0xa2, 0xa6, 0x03, 0x0a, 0x01, 0x00, 0xa7, 0x16, + 0x0c, 0x14, 0x6f, 0x70, 0x65, 0x6e, 0x73, 0x73, 0x6c, 0x2e, 0x65, 0x78, + 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x70, 0x32, 0x35, 0x36, 0x30, 0x0c, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x04, 0x05, 0x00, - 0x03, 0x49, 0x00, 0x30, 0x46, 0x02, 0x21, 0x00, 0xa9, 0x57, 0x7d, 0xac, - 0xe0, 0x80, 0x8e, 0x1c, 0x7a, 0xe1, 0x4d, 0x7d, 0x2a, 0x52, 0xd2, 0x5e, - 0xfb, 0x5a, 0x7d, 0x45, 0x1e, 0xfa, 0x67, 0x17, 0x04, 0x9e, 0xb3, 0x05, - 0xc2, 0x34, 0xf0, 0x7a, 0x02, 0x21, 0x00, 0xb7, 0x3a, 0x31, 0x25, 0xae, - 0x1d, 0x2b, 0x06, 0x8b, 0xba, 0x44, 0xd9, 0x3a, 0xbf, 0x8b, 0xe2, 0x3f, - 0x89, 0xe2, 0xa6, 0x14, 0x0c, 0xfa, 0xc2, 0xb1, 0xdd, 0x0c, 0x0a, 0x78, - 0xac, 0x60, 0x19}; + 0x03, 0x48, 0x00, 0x30, 0x45, 0x02, 0x20, 0x4f, 0x55, 0x9a, 0x0c, 0x2a, + 0x48, 0xd5, 0x51, 0xfe, 0xa1, 0xb9, 0x40, 0xe7, 0x95, 0x97, 0xd0, 0x48, + 0x0a, 0xde, 0x71, 0xbf, 0xaa, 0x19, 0x5f, 0x51, 0x3d, 0xd9, 0x4c, 0xdf, + 0xa8, 0x69, 0xa8, 0x02, 0x21, 0x00, 0xd4, 0x8c, 0x28, 0x58, 0x8e, 0x3c, + 0x4e, 0xb6, 0x98, 0x76, 0x24, 0x2b, 0x92, 0xc5, 0x8c, 0x42, 0x8c, 0x88, + 0xa7, 0x58, 0x35, 0x3d, 0xb5, 0x0e, 0x18, 0xa5, 0x6f, 0x2d, 0xd3, 0x0c, + 0x4c, 0x33}; constexpr uint8_t kExpectedX509P384Cert_DescriptorInput[0] = {}; @@ -1081,8 +1097,8 @@ constexpr uint8_t kExpectedCborEd25519Cert_DescriptorInput[667] = { constexpr uint8_t kExpectedCborP256Cert_DescriptorInput[0] = {}; -constexpr uint8_t kExpectedCborP384Cert_DescriptorInput[768] = { - 0x84, 0x44, 0xa1, 0x01, 0x38, 0x22, 0xa0, 0x59, 0x02, 0x94, 0xab, 0x01, +constexpr uint8_t kExpectedCborP384Cert_DescriptorInput[795] = { + 0x84, 0x44, 0xa1, 0x01, 0x38, 0x22, 0xa0, 0x59, 0x02, 0xaf, 0xac, 0x01, 0x78, 0x28, 0x35, 0x64, 0x38, 0x62, 0x36, 0x62, 0x65, 0x37, 0x63, 0x65, 0x33, 0x65, 0x64, 0x65, 0x36, 0x61, 0x32, 0x34, 0x31, 0x38, 0x30, 0x31, 0x34, 0x35, 0x32, 0x33, 0x65, 0x36, 0x63, 0x39, 0x64, 0x63, 0x38, 0x37, @@ -1137,15 +1153,18 @@ constexpr uint8_t kExpectedCborP384Cert_DescriptorInput[768] = { 0x1a, 0xc2, 0x29, 0xb5, 0x80, 0x2f, 0x7b, 0x2b, 0x0a, 0x27, 0x96, 0xb3, 0xb2, 0xc1, 0xc6, 0x6f, 0xb4, 0x16, 0xa4, 0x78, 0x76, 0x73, 0x6f, 0xcb, 0xf5, 0x7d, 0x26, 0xc2, 0x37, 0xe9, 0x58, 0x98, 0xeb, 0xef, 0x11, 0x7c, - 0x8d, 0x1d, 0x4b, 0x3a, 0x00, 0x47, 0x44, 0x58, 0x41, 0x20, 0x58, 0x60, - 0x6d, 0x1f, 0xb6, 0xd3, 0x9f, 0xfa, 0xaa, 0x73, 0xcf, 0x2d, 0x59, 0x99, - 0x9d, 0xef, 0x0f, 0x20, 0xc4, 0xeb, 0x31, 0x99, 0xa8, 0x9c, 0xae, 0xeb, - 0x85, 0x02, 0x34, 0x51, 0x24, 0x1a, 0x68, 0xc9, 0xfd, 0x87, 0xfd, 0x3d, - 0xc8, 0xe4, 0x88, 0x16, 0x8a, 0x31, 0x67, 0xa5, 0x95, 0xec, 0x2d, 0x4d, - 0x41, 0x08, 0x52, 0x3c, 0x26, 0x44, 0x3f, 0xca, 0xc8, 0xa3, 0x79, 0xc5, - 0x56, 0x40, 0xc0, 0x62, 0x0d, 0x5c, 0xd4, 0xcf, 0x69, 0x22, 0x05, 0x94, - 0xf2, 0x66, 0xcb, 0x1e, 0x8a, 0xdf, 0x98, 0xc4, 0xcd, 0x26, 0x4b, 0xd5, - 0xc6, 0x3d, 0x08, 0xf5, 0x5a, 0xa7, 0xde, 0x21, 0xbe, 0x5d, 0x04, 0x94}; + 0x8d, 0x1d, 0x4b, 0x3a, 0x00, 0x47, 0x44, 0x58, 0x41, 0x20, 0x3a, 0x00, + 0x47, 0x44, 0x59, 0x75, 0x6f, 0x70, 0x65, 0x6e, 0x64, 0x69, 0x63, 0x65, + 0x2e, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x70, 0x33, 0x38, + 0x34, 0x58, 0x60, 0xe4, 0x8c, 0x6b, 0x6b, 0x24, 0xb2, 0xc6, 0x17, 0xcf, + 0xfb, 0xb0, 0x8b, 0x28, 0x81, 0x8c, 0xb7, 0xc0, 0xed, 0x46, 0x9d, 0xb7, + 0xb6, 0x7f, 0xfd, 0xc6, 0xdd, 0xb8, 0x61, 0xb9, 0x03, 0xbc, 0x66, 0x01, + 0xb2, 0x7e, 0x9d, 0x4e, 0x62, 0x7b, 0xb0, 0x41, 0x39, 0x81, 0x7f, 0x30, + 0x64, 0x4e, 0x5b, 0x33, 0x22, 0x1c, 0xa4, 0xac, 0x88, 0x33, 0x87, 0xe1, + 0x7b, 0x0f, 0xa1, 0x55, 0xaa, 0x8a, 0x4e, 0xbd, 0x50, 0xec, 0xc0, 0x35, + 0x28, 0xb4, 0xaa, 0xaa, 0x2a, 0x78, 0x42, 0x5f, 0xcb, 0x76, 0xa7, 0x84, + 0xa1, 0xca, 0xf2, 0xda, 0xdb, 0x14, 0x6a, 0x87, 0x05, 0x11, 0xa8, 0xfa, + 0x09, 0x30, 0x9c}; } // namespace test } // namespace dice diff --git a/include/dice/test_utils.h b/include/dice/test_utils.h index afc400a..70469c4 100644 --- a/include/dice/test_utils.h +++ b/include/dice/test_utils.h @@ -12,6 +12,9 @@ // License for the specific language governing permissions and limitations under // the License. +#ifndef DICE_TEST_UTILS_H_ +#define DICE_TEST_UTILS_H_ + #include <stddef.h> #include <stdint.h> @@ -72,3 +75,5 @@ bool VerifyCertificateChain(CertificateType cert_type, } // namespace test } // namespace dice + +#endif // DICE_TEST_UTILS_ diff --git a/pigweed.json b/pigweed.json new file mode 100644 index 0000000..11071ff --- /dev/null +++ b/pigweed.json @@ -0,0 +1,34 @@ +{ + "pw": { + "pw_cli": { + "plugins": { + "presubmit": { + "module": "open_dice_tools.presubmit", + "function": "main" + } + } + }, + "pw_presubmit": { + "format": { + "python_formatter": "black", + "exclude": [ + "third_party/.*/src", + "third_party/boringssl/err_data.c" + ] + } + }, + "pw_env_setup": { + "root_variable": "OPEN_DICE_ROOT", + "cipd_package_files": [ + "third_party/pigweed/src/pw_env_setup/py/pw_env_setup/cipd_setup/default.json" + ], + "virtualenv": { + "gn_root": ".", + "gn_targets": [ + ":python.install" + ] + }, + "gni_file": "build_overrides/pigweed_environment.gni" + } + } +} diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..36318de --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,17 @@ +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may not +# use this file except in compliance with the License. You may obtain a copy of +# the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations under +# the License. + +[tool.black] +line-length = 80 +exclude = '^/(out|\.?environment)' @@ -19,7 +19,7 @@ LOCAL_DIR := $(GET_LOCAL_DIR) MODULE := $(LOCAL_DIR) MODULE_SRCS := \ - $(LOCAL_DIR)/src/android/bcc.c \ + $(LOCAL_DIR)/src/android.c \ $(LOCAL_DIR)/src/boringssl_hash_kdf_ops.c \ $(LOCAL_DIR)/src/boringssl_ed25519_ops.c \ $(LOCAL_DIR)/src/cbor_cert_op.c \ diff --git a/src/android/bcc.c b/src/android.c index 262e6d3..39ee7d0 100644 --- a/src/android/bcc.c +++ b/src/android.c @@ -12,7 +12,9 @@ // License for the specific language governing permissions and limitations under // the License. -#include "dice/android/bcc.h" +// For more information on the Android Profile for DICE, see docs/android.md. + +#include "dice/android.h" #include <string.h> @@ -29,34 +31,39 @@ static size_t PopulationCount(uint32_t n) { return (((n + (n >> 4)) & 0x0F0F0F0F) * 0x01010101) >> 24; } -DiceResult BccFormatConfigDescriptor(const BccConfigValues* input_values, - size_t buffer_size, uint8_t* buffer, - size_t* actual_size) { +DiceResult DiceAndroidFormatConfigDescriptor( + const DiceAndroidConfigValues* config_values, size_t buffer_size, + uint8_t* buffer, size_t* actual_size) { static const int64_t kComponentNameLabel = -70002; static const int64_t kComponentVersionLabel = -70003; static const int64_t kResettableLabel = -70004; + static const int64_t kSecurityVersion = -70005; - // BccConfigDescriptor = { + // AndroidConfigDescriptor = { // ? -70002 : tstr, ; Component name // ? -70003 : int, ; Component version // ? -70004 : null, ; Resettable // } struct CborOut out; CborOutInit(buffer, buffer_size, &out); - CborWriteMap(PopulationCount(input_values->inputs), &out); - if (input_values->inputs & BCC_INPUT_COMPONENT_NAME && - input_values->component_name) { + CborWriteMap(PopulationCount(config_values->configs), &out); + if (config_values->configs & DICE_ANDROID_CONFIG_COMPONENT_NAME && + config_values->component_name) { CborWriteInt(kComponentNameLabel, &out); - CborWriteTstr(input_values->component_name, &out); + CborWriteTstr(config_values->component_name, &out); } - if (input_values->inputs & BCC_INPUT_COMPONENT_VERSION) { + if (config_values->configs & DICE_ANDROID_CONFIG_COMPONENT_VERSION) { CborWriteInt(kComponentVersionLabel, &out); - CborWriteUint(input_values->component_version, &out); + CborWriteUint(config_values->component_version, &out); } - if (input_values->inputs & BCC_INPUT_RESETTABLE) { + if (config_values->configs & DICE_ANDROID_CONFIG_RESETTABLE) { CborWriteInt(kResettableLabel, &out); CborWriteNull(&out); } + if (config_values->configs & DICE_ANDROID_CONFIG_SECURITY_VERSION) { + CborWriteInt(kSecurityVersion, &out); + CborWriteUint(config_values->security_version, &out); + } *actual_size = CborOutSize(&out); if (CborOutOverflowed(&out)) { return kDiceResultBufferTooSmall; @@ -64,74 +71,76 @@ DiceResult BccFormatConfigDescriptor(const BccConfigValues* input_values, return kDiceResultOk; } -DiceResult BccMainFlow(void* context, - const uint8_t current_cdi_attest[DICE_CDI_SIZE], - const uint8_t current_cdi_seal[DICE_CDI_SIZE], - const uint8_t* bcc, size_t bcc_size, - const DiceInputValues* input_values, size_t buffer_size, - uint8_t* buffer, size_t* actual_size, - uint8_t next_cdi_attest[DICE_CDI_SIZE], - uint8_t next_cdi_seal[DICE_CDI_SIZE]) { +DiceResult DiceAndroidMainFlow(void* context, + const uint8_t current_cdi_attest[DICE_CDI_SIZE], + const uint8_t current_cdi_seal[DICE_CDI_SIZE], + const uint8_t* chain, size_t chain_size, + const DiceInputValues* input_values, + size_t buffer_size, uint8_t* buffer, + size_t* actual_size, + uint8_t next_cdi_attest[DICE_CDI_SIZE], + uint8_t next_cdi_seal[DICE_CDI_SIZE]) { DiceResult result; enum CborReadResult res; struct CborIn in; - size_t bcc_item_count; + size_t chain_item_count; - // The BCC has a more detailed internal structure, but those details aren't - // relevant to the work of this function. + // The Android DICE chain has a more detailed internal structure, but those + // details aren't relevant to the work of this function. // - // Bcc = [ + // DiceCertChain = [ // COSE_Key, ; Root public key - // + COSE_Sign1, ; Bcc entries + // + COSE_Sign1, ; DICE chain entries // ] - CborInInit(bcc, bcc_size, &in); - res = CborReadArray(&in, &bcc_item_count); + CborInInit(chain, chain_size, &in); + res = CborReadArray(&in, &chain_item_count); if (res != CBOR_READ_RESULT_OK) { return kDiceResultInvalidInput; } - if (bcc_item_count < 2 || bcc_item_count == SIZE_MAX) { + if (chain_item_count < 2 || chain_item_count == SIZE_MAX) { // There should at least be the public key and one entry. return kDiceResultInvalidInput; } - // Measure the existing BCC entries. - size_t bcc_items_offset = CborInOffset(&in); - for (size_t bcc_pos = 0; bcc_pos < bcc_item_count; ++bcc_pos) { + // Measure the existing chain entries. + size_t chain_items_offset = CborInOffset(&in); + for (size_t chain_pos = 0; chain_pos < chain_item_count; ++chain_pos) { res = CborReadSkip(&in); if (res != CBOR_READ_RESULT_OK) { return kDiceResultInvalidInput; } } - size_t bcc_items_size = CborInOffset(&in) - bcc_items_offset; + size_t chain_items_size = CborInOffset(&in) - chain_items_offset; - // Copy to the new buffer, with space in the BCC for one more entry. + // Copy to the new buffer, with space in the chain for one more entry. struct CborOut out; CborOutInit(buffer, buffer_size, &out); - CborWriteArray(bcc_item_count + 1, &out); + CborWriteArray(chain_item_count + 1, &out); if (CborOutOverflowed(&out) || - bcc_items_size > buffer_size - CborOutSize(&out)) { + chain_items_size > buffer_size - CborOutSize(&out)) { // Continue with an empty buffer to measure the required size. buffer_size = 0; } else { - memcpy(buffer + CborOutSize(&out), bcc + bcc_items_offset, bcc_items_size); - buffer += CborOutSize(&out) + bcc_items_size; - buffer_size -= CborOutSize(&out) + bcc_items_size; + memcpy(buffer + CborOutSize(&out), chain + chain_items_offset, + chain_items_size); + buffer += CborOutSize(&out) + chain_items_size; + buffer_size -= CborOutSize(&out) + chain_items_size; } size_t certificate_size; result = DiceMainFlow(context, current_cdi_attest, current_cdi_seal, input_values, buffer_size, buffer, &certificate_size, next_cdi_attest, next_cdi_seal); - *actual_size = CborOutSize(&out) + bcc_items_size + certificate_size; + *actual_size = CborOutSize(&out) + chain_items_size + certificate_size; return result; } -static DiceResult BccMainFlowWithNewBcc( +static DiceResult DiceAndroidMainFlowWithNewDiceChain( void* context, const uint8_t current_cdi_attest[DICE_CDI_SIZE], const uint8_t current_cdi_seal[DICE_CDI_SIZE], const DiceInputValues* input_values, size_t buffer_size, uint8_t* buffer, - size_t* bcc_size, uint8_t next_cdi_attest[DICE_CDI_SIZE], + size_t* chain_size, uint8_t next_cdi_attest[DICE_CDI_SIZE], uint8_t next_cdi_seal[DICE_CDI_SIZE]) { uint8_t current_cdi_private_key_seed[DICE_PRIVATE_KEY_SEED_SIZE]; uint8_t attestation_public_key[DICE_PUBLIC_KEY_SIZE]; @@ -150,7 +159,7 @@ static DiceResult BccMainFlowWithNewBcc( goto out; } - // Consruct the BCC from the attestation public key and the next CDI + // Consruct the DICE chain from the attestation public key and the next CDI // certificate. struct CborOut out; CborOutInit(buffer, buffer_size, &out); @@ -178,9 +187,9 @@ static DiceResult BccMainFlowWithNewBcc( } result = DiceMainFlow(context, current_cdi_attest, current_cdi_seal, - input_values, buffer_size, buffer, bcc_size, + input_values, buffer_size, buffer, chain_size, next_cdi_attest, next_cdi_seal); - *bcc_size += encoded_size_used + encoded_pub_key_size; + *chain_size += encoded_size_used + encoded_pub_key_size; if (result != kDiceResultOk) { return result; } @@ -194,24 +203,29 @@ out: return result; } +// AndroidDiceHandover = { +// 1 : bstr .size 32, ; CDI_Attest +// 2 : bstr .size 32, ; CDI_Seal +// ? 3 : DiceCertChain, ; Android DICE chain +// } static const int64_t kCdiAttestLabel = 1; static const int64_t kCdiSealLabel = 2; -static const int64_t kBccLabel = 3; +static const int64_t kDiceChainLabel = 3; -DiceResult BccHandoverMainFlow(void* context, const uint8_t* bcc_handover, - size_t bcc_handover_size, - const DiceInputValues* input_values, - size_t buffer_size, uint8_t* buffer, - size_t* actual_size) { +DiceResult DiceAndroidHandoverMainFlow(void* context, const uint8_t* handover, + size_t handover_size, + const DiceInputValues* input_values, + size_t buffer_size, uint8_t* buffer, + size_t* actual_size) { DiceResult result; const uint8_t* current_cdi_attest; const uint8_t* current_cdi_seal; - const uint8_t* bcc; - size_t bcc_size; + const uint8_t* chain; + size_t chain_size; result = - BccHandoverParse(bcc_handover, bcc_handover_size, ¤t_cdi_attest, - ¤t_cdi_seal, &bcc, &bcc_size); + DiceAndroidHandoverParse(handover, handover_size, ¤t_cdi_attest, + ¤t_cdi_seal, &chain, &chain_size); if (result != kDiceResultOk) { return kDiceResultInvalidInput; } @@ -224,7 +238,7 @@ DiceResult BccHandoverMainFlow(void* context, const uint8_t* bcc_handover, uint8_t* next_cdi_attest = CborAllocBstr(DICE_CDI_SIZE, &out); CborWriteInt(kCdiSealLabel, &out); uint8_t* next_cdi_seal = CborAllocBstr(DICE_CDI_SIZE, &out); - CborWriteInt(kBccLabel, &out); + CborWriteInt(kDiceChainLabel, &out); uint8_t ignored_cdi_attest[DICE_CDI_SIZE]; uint8_t ignored_cdi_seal[DICE_CDI_SIZE]; @@ -239,40 +253,36 @@ DiceResult BccHandoverMainFlow(void* context, const uint8_t* bcc_handover, buffer_size -= CborOutSize(&out); } - if (bcc_size != 0) { - // If BCC is present in the bcc_handover, append the next certificate to the - // existing BCC. - result = BccMainFlow(context, current_cdi_attest, current_cdi_seal, bcc, - bcc_size, input_values, buffer_size, buffer, &bcc_size, - next_cdi_attest, next_cdi_seal); + if (chain_size != 0) { + // If the DICE chain is present in the handover, append the next certificate + // to the existing DICE chain. + result = DiceAndroidMainFlow(context, current_cdi_attest, current_cdi_seal, + chain, chain_size, input_values, buffer_size, + buffer, &chain_size, next_cdi_attest, + next_cdi_seal); } else { - // If BCC is not present in the bcc_handover, construct BCC from the public - // key derived from the current CDI attest and the next CDI certificate. - result = BccMainFlowWithNewBcc( + // If DICE chain is not present in the handover, construct the DICE chain + // from the public key derived from the current CDI attest and the next CDI + // certificate. + result = DiceAndroidMainFlowWithNewDiceChain( context, current_cdi_attest, current_cdi_seal, input_values, - buffer_size, buffer, &bcc_size, next_cdi_attest, next_cdi_seal); + buffer_size, buffer, &chain_size, next_cdi_attest, next_cdi_seal); } - *actual_size = CborOutSize(&out) + bcc_size; + *actual_size = CborOutSize(&out) + chain_size; return result; } -DiceResult BccHandoverParse(const uint8_t* bcc_handover, - size_t bcc_handover_size, - const uint8_t** cdi_attest, - const uint8_t** cdi_seal, const uint8_t** bcc, - size_t* bcc_size) { +DiceResult DiceAndroidHandoverParse(const uint8_t* handover, + size_t handover_size, + const uint8_t** cdi_attest, + const uint8_t** cdi_seal, + const uint8_t** chain, size_t* chain_size) { // Extract details from the handover data. - // - // BccHandover = { - // 1 : bstr .size 32, ; CDI_Attest - // 2 : bstr .size 32, ; CDI_Seal - // ? 3 : Bcc, ; Certificate chain - // } struct CborIn in; int64_t label; size_t num_pairs; size_t item_size; - CborInInit(bcc_handover, bcc_handover_size, &in); + CborInInit(handover, handover_size, &in); if (CborReadMap(&in, &num_pairs) != CBOR_READ_RESULT_OK || num_pairs < 2 || // Read the attestation CDI. CborReadInt(&in, &label) != CBOR_READ_RESULT_OK || @@ -287,17 +297,17 @@ DiceResult BccHandoverParse(const uint8_t* bcc_handover, return kDiceResultInvalidInput; } - *bcc = NULL; - *bcc_size = 0; + *chain = NULL; + *chain_size = 0; if (num_pairs >= 3 && CborReadInt(&in, &label) == CBOR_READ_RESULT_OK) { - if (label == kBccLabel) { - // Calculate the BCC size, if the BCC is present in the BccHandover. - size_t bcc_start = CborInOffset(&in); + if (label == kDiceChainLabel) { + // Calculate the DICE chain size, if it is present in the handover object. + size_t chain_start = CborInOffset(&in); if (CborReadSkip(&in) != CBOR_READ_RESULT_OK) { return kDiceResultInvalidInput; } - *bcc = bcc_handover + bcc_start; - *bcc_size = CborInOffset(&in) - bcc_start; + *chain = handover + chain_start; + *chain_size = CborInOffset(&in) - chain_start; } } diff --git a/src/android/README.md b/src/android/README.md deleted file mode 100644 index 99d9395..0000000 --- a/src/android/README.md +++ /dev/null @@ -1,8 +0,0 @@ -# The Boot Certificate Chain (BCC) - -The Boot Certificate Chain (BCC) is an application of the Open Profile for DICE -used by Android that conforms to the specification and goes further to more -strictly define the configuration descriptor. - -A [CDDL](https://tools.ietf.org/html/rfc8610) definition of the BCC can be -found int the [KeyMint AIDL definitions](https://cs.android.com/android/platform/superproject/+/master:hardware/interfaces/security/keymint/aidl/android/hardware/security/keymint/ProtectedData.aidl). diff --git a/src/android/bcc_fuzzer.cc b/src/android_fuzzer.cc index 8c4934d..baa0cd2 100644 --- a/src/android/bcc_fuzzer.cc +++ b/src/android_fuzzer.cc @@ -12,7 +12,7 @@ // License for the specific language governing permissions and limitations under // the License. -#include "dice/android/bcc.h" +#include "dice/android.h" #include "dice/fuzz_utils.h" #include "dice/utils.h" #include "fuzzer/FuzzedDataProvider.h" @@ -30,21 +30,20 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { // Prepare the fuzzed inputs. auto input_values = FuzzedInputValues::ConsumeFrom(fdp); - auto bcc_handover = ConsumeRandomLengthStringAsBytesFrom(fdp); + auto handover = ConsumeRandomLengthStringAsBytesFrom(fdp); // Initialize output parameters with fuzz data in case they are wrongly being // read from. - constexpr size_t kNextBccHandoverBufferSize = 1024; - auto next_bcc_handover_actual_size = fdp.ConsumeIntegral<size_t>(); - uint8_t next_bcc_handover[kNextBccHandoverBufferSize] = {}; + constexpr size_t kNextHandoverBufferSize = 1024; + auto next_handover_actual_size = fdp.ConsumeIntegral<size_t>(); + uint8_t next_handover[kNextHandoverBufferSize] = {}; - fdp.ConsumeData(&next_bcc_handover, kNextBccHandoverBufferSize); + fdp.ConsumeData(&next_handover, kNextHandoverBufferSize); // Fuzz the main flow. - BccHandoverMainFlow(/*context=*/NULL, bcc_handover.data(), - bcc_handover.size(), input_values, - kNextBccHandoverBufferSize, next_bcc_handover, - &next_bcc_handover_actual_size); + DiceAndroidHandoverMainFlow( + /*context=*/NULL, handover.data(), handover.size(), input_values, + kNextHandoverBufferSize, next_handover, &next_handover_actual_size); return 0; } diff --git a/src/android/bcc_test.cc b/src/android_test.cc index ba062b9..c90bed1 100644 --- a/src/android/bcc_test.cc +++ b/src/android_test.cc @@ -12,7 +12,7 @@ // License for the specific language governing permissions and limitations under // the License. -#include "dice/android/bcc.h" +#include "dice/android.h" #include "dice/test_framework.h" @@ -20,88 +20,92 @@ namespace { extern "C" { -TEST(BccConfigTest, NoInputs) { - BccConfigValues input_values = {}; +TEST(DiceAndroidConfigTest, NoConfigFields) { + DiceAndroidConfigValues input_values = {}; uint8_t buffer[10]; size_t buffer_size; - DiceResult result = BccFormatConfigDescriptor(&input_values, sizeof(buffer), - buffer, &buffer_size); + DiceResult result = DiceAndroidFormatConfigDescriptor( + &input_values, sizeof(buffer), buffer, &buffer_size); EXPECT_EQ(kDiceResultOk, result); EXPECT_EQ(1u, buffer_size); EXPECT_EQ(0xa0, buffer[0]); } -TEST(BccConfigTest, NoInputsMeasurement) { - BccConfigValues input_values = {}; +TEST(DiceAndroidConfigTest, NoConfigFieldsMeasurement) { + DiceAndroidConfigValues config_values = {}; size_t buffer_size; DiceResult result = - BccFormatConfigDescriptor(&input_values, 0, NULL, &buffer_size); + DiceAndroidFormatConfigDescriptor(&config_values, 0, NULL, &buffer_size); EXPECT_EQ(kDiceResultBufferTooSmall, result); EXPECT_EQ(1u, buffer_size); } -TEST(BccConfigTest, AllInputs) { - BccConfigValues input_values = { - .inputs = BCC_INPUT_COMPONENT_NAME | BCC_INPUT_COMPONENT_VERSION | - BCC_INPUT_RESETTABLE, +TEST(DiceAndroidConfigTest, AllConfigFields) { + DiceAndroidConfigValues config_values = { + .configs = DICE_ANDROID_CONFIG_COMPONENT_NAME | + DICE_ANDROID_CONFIG_COMPONENT_VERSION | + DICE_ANDROID_CONFIG_RESETTABLE | + DICE_ANDROID_CONFIG_SECURITY_VERSION, .component_name = "Test Component Name", .component_version = 0x232a13dec90f42b5, + .security_version = 0xfab777c1, }; size_t buffer_size; DiceResult result = - BccFormatConfigDescriptor(&input_values, 0, NULL, &buffer_size); + DiceAndroidFormatConfigDescriptor(&config_values, 0, NULL, &buffer_size); EXPECT_EQ(kDiceResultBufferTooSmall, result); std::vector<uint8_t> buffer(buffer_size); const uint8_t expected[] = { - 0xa3, 0x3a, 0x00, 0x01, 0x11, 0x71, 0x73, 'T', 'e', 's', 't', ' ', + 0xa4, 0x3a, 0x00, 0x01, 0x11, 0x71, 0x73, 'T', 'e', 's', 't', ' ', 'C', 'o', 'm', 'p', 'o', 'n', 'e', 'n', 't', ' ', 'N', 'a', 'm', 'e', 0x3a, 0x00, 0x01, 0x11, 0x72, 0x1b, 0x23, 0x2a, 0x13, 0xde, - 0xc9, 0x0f, 0x42, 0xb5, 0x3a, 0x00, 0x01, 0x11, 0x73, 0xf6}; + 0xc9, 0x0f, 0x42, 0xb5, 0x3a, 0x00, 0x01, 0x11, 0x73, 0xf6, 0x3a, 0x00, + 0x01, 0x11, 0x74, 0x1a, 0xfa, 0xb7, 0x77, 0xc1}; EXPECT_EQ(sizeof(expected), buffer.size()); - result = BccFormatConfigDescriptor(&input_values, buffer.size(), - buffer.data(), &buffer_size); + result = DiceAndroidFormatConfigDescriptor(&config_values, buffer.size(), + buffer.data(), &buffer_size); EXPECT_EQ(sizeof(expected), buffer_size); EXPECT_EQ(0, memcmp(expected, buffer.data(), buffer.size())); } -TEST(BccTest, PreservesPreviousEntries) { - const uint8_t bcc[] = { - // Fake BCC with the root public key and two entries. +TEST(DiceAndroidTest, PreservesPreviousEntries) { + const uint8_t chain[] = { + // Fake DICE chain with the root public key and two entries. 0x83, // Fake public key. 0xa6, 0x01, 0x02, 0x03, 0x27, 0x04, 0x02, 0x20, 0x01, 0x21, 0x40, 0x22, 0x40, - // Fake BCC entry. + // Fake DICE chain entry. 0x84, 0x40, 0xa0, 0x40, 0x40, - // Fake BCC entry. + // Fake DICE chain entry. 0x84, 0x41, 0x55, 0xa0, 0x42, 0x11, 0x22, 0x40, - // 8-bytes of trailing data that aren't part of the BCC. + // 8-bytes of trailing data that aren't part of the DICE chain. 0x84, 0x41, 0x55, 0xa0, 0x42, 0x11, 0x22, 0x40}; const uint8_t fake_cdi_attest[DICE_CDI_SIZE] = {}; const uint8_t fake_cdi_seal[DICE_CDI_SIZE] = {}; DiceInputValues input_values = {}; - size_t next_bcc_size; + size_t next_chain_size; uint8_t next_cdi_attest[DICE_CDI_SIZE]; uint8_t next_cdi_seal[DICE_CDI_SIZE]; - DiceResult result = BccMainFlow( - /*context=*/NULL, fake_cdi_attest, fake_cdi_seal, bcc, sizeof(bcc), - &input_values, 0, NULL, &next_bcc_size, next_cdi_attest, next_cdi_seal); + DiceResult result = DiceAndroidMainFlow( + /*context=*/NULL, fake_cdi_attest, fake_cdi_seal, chain, sizeof(chain), + &input_values, 0, NULL, &next_chain_size, next_cdi_attest, next_cdi_seal); EXPECT_EQ(kDiceResultBufferTooSmall, result); - EXPECT_GT(next_bcc_size, sizeof(bcc)); - std::vector<uint8_t> next_bcc(next_bcc_size); - result = - BccMainFlow(/*context=*/NULL, fake_cdi_attest, fake_cdi_seal, bcc, - sizeof(bcc), &input_values, next_bcc.size(), next_bcc.data(), - &next_bcc_size, next_cdi_attest, next_cdi_seal); + EXPECT_GT(next_chain_size, sizeof(chain)); + std::vector<uint8_t> next_chain(next_chain_size); + result = DiceAndroidMainFlow( + /*context=*/NULL, fake_cdi_attest, fake_cdi_seal, chain, sizeof(chain), + &input_values, next_chain.size(), next_chain.data(), &next_chain_size, + next_cdi_attest, next_cdi_seal); EXPECT_EQ(kDiceResultOk, result); - EXPECT_EQ(next_bcc_size, next_bcc.size()); - EXPECT_EQ(0x84, next_bcc[0]); - EXPECT_NE(0, memcmp(next_bcc.data() + 1, bcc + 1, sizeof(bcc) - 1)); - EXPECT_EQ(0, memcmp(next_bcc.data() + 1, bcc + 1, sizeof(bcc) - 8 - 1)); + EXPECT_EQ(next_chain_size, next_chain.size()); + EXPECT_EQ(0x84, next_chain[0]); + EXPECT_NE(0, memcmp(next_chain.data() + 1, chain + 1, sizeof(chain) - 1)); + EXPECT_EQ(0, memcmp(next_chain.data() + 1, chain + 1, sizeof(chain) - 8 - 1)); } -TEST(BccHandoverTest, PreservesPreviousEntries) { - const uint8_t bcc_handover[] = { +TEST(DiceAndroidHandoverTest, PreservesPreviousEntries) { + const uint8_t handover[] = { 0xa3, // CDI attest 0x01, 0x58, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, @@ -111,35 +115,35 @@ TEST(BccHandoverTest, PreservesPreviousEntries) { 0x02, 0x58, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - // BCC + // DICE chain 0x03, 0x82, 0xa6, 0x01, 0x02, 0x03, 0x27, 0x04, 0x02, 0x20, 0x01, 0x21, 0x40, 0x22, 0x40, 0x84, 0x40, 0xa0, 0x40, 0x40, - // 8-bytes of trailing data that aren't part of the BCC. + // 8-bytes of trailing data that aren't part of the DICE chain. 0x84, 0x41, 0x55, 0xa0, 0x42, 0x11, 0x22, 0x40}; DiceInputValues input_values = {}; - size_t next_bcc_handover_size; - DiceResult result = BccHandoverMainFlow( - /*context=*/NULL, bcc_handover, sizeof(bcc_handover), &input_values, 0, - NULL, &next_bcc_handover_size); + size_t next_handover_size; + DiceResult result = DiceAndroidHandoverMainFlow( + /*context=*/NULL, handover, sizeof(handover), &input_values, 0, NULL, + &next_handover_size); EXPECT_EQ(kDiceResultBufferTooSmall, result); - EXPECT_GT(next_bcc_handover_size, sizeof(bcc_handover)); - std::vector<uint8_t> next_bcc_handover(next_bcc_handover_size); - result = BccHandoverMainFlow( - /*context=*/NULL, bcc_handover, sizeof(bcc_handover), &input_values, - next_bcc_handover.size(), next_bcc_handover.data(), - &next_bcc_handover_size); + EXPECT_GT(next_handover_size, sizeof(handover)); + std::vector<uint8_t> next_handover(next_handover_size); + result = DiceAndroidHandoverMainFlow( + /*context=*/NULL, handover, sizeof(handover), &input_values, + next_handover.size(), next_handover.data(), &next_handover_size); EXPECT_EQ(kDiceResultOk, result); - EXPECT_EQ(next_bcc_handover_size, next_bcc_handover.size()); - EXPECT_EQ(0xa3, next_bcc_handover[0]); - EXPECT_EQ(0x83, next_bcc_handover[72]); - EXPECT_NE(0, memcmp(next_bcc_handover.data() + 73, bcc_handover + 73, - sizeof(bcc_handover) - 73)); - EXPECT_EQ(0, memcmp(next_bcc_handover.data() + 73, bcc_handover + 73, - sizeof(bcc_handover) - 8 - 73)); + EXPECT_EQ(next_handover_size, next_handover.size()); + EXPECT_EQ(0xa3, next_handover[0]); + EXPECT_EQ(0x83, next_handover[72]); + EXPECT_NE(0, memcmp(next_handover.data() + 73, handover + 73, + sizeof(handover) - 73)); + EXPECT_EQ(0, memcmp(next_handover.data() + 73, handover + 73, + sizeof(handover) - 8 - 73)); } -TEST(BccHandoverTest, InHandoverWithoutBccOutHandoverWithBcc) { - const uint8_t bcc_handover[] = { +TEST(DiceAndroidHandoverTest, + InHandoverWithoutDiceChainOutHandoverWithDiceChain) { + const uint8_t handover[] = { 0xa2, // CDI attest 0x01, 0x58, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, @@ -149,27 +153,27 @@ TEST(BccHandoverTest, InHandoverWithoutBccOutHandoverWithBcc) { 0x02, 0x58, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - // 8-bytes of trailing data that aren't part of the BCC. + // 8-bytes of trailing data that aren't part of the DICE chain. 0x00, 0x41, 0x55, 0xa0, 0x42, 0x11, 0x22, 0x40}; DiceInputValues input_values = {}; - size_t next_bcc_handover_size; - DiceResult result = BccHandoverMainFlow( - /*context=*/NULL, bcc_handover, sizeof(bcc_handover), &input_values, 0, - NULL, &next_bcc_handover_size); + size_t next_handover_size; + DiceResult result = DiceAndroidHandoverMainFlow( + /*context=*/NULL, handover, sizeof(handover), &input_values, 0, NULL, + &next_handover_size); EXPECT_EQ(kDiceResultBufferTooSmall, result); - EXPECT_GT(next_bcc_handover_size, sizeof(bcc_handover)); - std::vector<uint8_t> next_bcc_handover(next_bcc_handover_size); - result = BccHandoverMainFlow( - /*context=*/NULL, bcc_handover, sizeof(bcc_handover), &input_values, - next_bcc_handover.size(), next_bcc_handover.data(), - &next_bcc_handover_size); + EXPECT_GT(next_handover_size, sizeof(handover)); + std::vector<uint8_t> next_handover(next_handover_size); + result = DiceAndroidHandoverMainFlow( + /*context=*/NULL, handover, sizeof(handover), &input_values, + next_handover.size(), next_handover.data(), &next_handover_size); EXPECT_EQ(kDiceResultOk, result); - EXPECT_EQ(next_bcc_handover_size, next_bcc_handover.size()); - EXPECT_EQ(0xa3, next_bcc_handover[0]); + EXPECT_EQ(next_handover_size, next_handover.size()); + EXPECT_EQ(0xa3, next_handover[0]); } -TEST(BccHandoverTest, InHandoverWithoutBccButUnknownFieldOutHandoverWithBcc) { - const uint8_t bcc_handover[] = { +TEST(DiceAndroidHandoverTest, + InHandoverWithoutDiceChainButUnknownFieldOutHandoverWithDiceChain) { + const uint8_t handover[] = { 0xa3, // CDI attest 0x01, 0x58, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, @@ -181,27 +185,26 @@ TEST(BccHandoverTest, InHandoverWithoutBccButUnknownFieldOutHandoverWithBcc) { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Ignored unknown field 0x04, 0x01, - // 8-bytes of trailing data that aren't part of the BCC. + // 8-bytes of trailing data that aren't part of the DICE chain. 0x00, 0x41, 0x55, 0xa0, 0x42, 0x11, 0x22, 0x40}; DiceInputValues input_values = {}; - size_t next_bcc_handover_size; - DiceResult result = BccHandoverMainFlow( - /*context=*/NULL, bcc_handover, sizeof(bcc_handover), &input_values, 0, - NULL, &next_bcc_handover_size); + size_t next_handover_size; + DiceResult result = DiceAndroidHandoverMainFlow( + /*context=*/NULL, handover, sizeof(handover), &input_values, 0, NULL, + &next_handover_size); EXPECT_EQ(kDiceResultBufferTooSmall, result); - EXPECT_GT(next_bcc_handover_size, sizeof(bcc_handover)); - std::vector<uint8_t> next_bcc_handover(next_bcc_handover_size); - result = BccHandoverMainFlow( - /*context=*/NULL, bcc_handover, sizeof(bcc_handover), &input_values, - next_bcc_handover.size(), next_bcc_handover.data(), - &next_bcc_handover_size); + EXPECT_GT(next_handover_size, sizeof(handover)); + std::vector<uint8_t> next_handover(next_handover_size); + result = DiceAndroidHandoverMainFlow( + /*context=*/NULL, handover, sizeof(handover), &input_values, + next_handover.size(), next_handover.data(), &next_handover_size); EXPECT_EQ(kDiceResultOk, result); - EXPECT_EQ(next_bcc_handover_size, next_bcc_handover.size()); - EXPECT_EQ(0xa3, next_bcc_handover[0]); + EXPECT_EQ(next_handover_size, next_handover.size()); + EXPECT_EQ(0xa3, next_handover[0]); } -TEST(BccHandoverTest, ParseHandover) { - const uint8_t bcc_handover[] = { +TEST(DiceAndroidHandoverTest, ParseHandover) { + const uint8_t handover[] = { 0xa3, // CDI attest 0x01, 0x58, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, @@ -211,26 +214,26 @@ TEST(BccHandoverTest, ParseHandover) { 0x02, 0x58, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - // BCC + // DICE chain 0x03, 0x82, 0xa6, 0x01, 0x02, 0x03, 0x27, 0x04, 0x02, 0x20, 0x01, 0x21, 0x40, 0x22, 0x40, 0x84, 0x40, 0xa0, 0x40, 0x40, - // 8-bytes of trailing data that aren't part of the BCC. + // 8-bytes of trailing data that aren't part of the DICE chain. 0x00, 0x41, 0x55, 0xa0, 0x42, 0x11, 0x22, 0x40}; const uint8_t *cdi_attest; const uint8_t *cdi_seal; - const uint8_t *bcc; - size_t bcc_size; - DiceResult result = BccHandoverParse(bcc_handover, sizeof(bcc_handover), - &cdi_attest, &cdi_seal, &bcc, &bcc_size); + const uint8_t *chain; + size_t chain_size; + DiceResult result = DiceAndroidHandoverParse( + handover, sizeof(handover), &cdi_attest, &cdi_seal, &chain, &chain_size); EXPECT_EQ(kDiceResultOk, result); - EXPECT_EQ(bcc_handover + 4, cdi_attest); - EXPECT_EQ(bcc_handover + 39, cdi_seal); - EXPECT_EQ(bcc_handover + 72, bcc); - EXPECT_EQ(19u, bcc_size); + EXPECT_EQ(handover + 4, cdi_attest); + EXPECT_EQ(handover + 39, cdi_seal); + EXPECT_EQ(handover + 72, chain); + EXPECT_EQ(19u, chain_size); } -TEST(BccHandoverTest, ParseHandoverWithoutBcc) { - const uint8_t bcc_handover[] = { +TEST(DiceAndroidHandoverTest, ParseHandoverWithoutDiceChain) { + const uint8_t handover[] = { 0xa2, // CDI attest 0x01, 0x58, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, @@ -240,23 +243,23 @@ TEST(BccHandoverTest, ParseHandoverWithoutBcc) { 0x02, 0x58, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - // 8-bytes of trailing data that aren't part of the BCC. + // 8-bytes of trailing data that aren't part of the DICE chain. 0x00, 0x41, 0x55, 0xa0, 0x42, 0x11, 0x22, 0x40}; const uint8_t *cdi_attest; const uint8_t *cdi_seal; - const uint8_t *bcc; - size_t bcc_size; - DiceResult result = BccHandoverParse(bcc_handover, sizeof(bcc_handover), - &cdi_attest, &cdi_seal, &bcc, &bcc_size); + const uint8_t *chain; + size_t chain_size; + DiceResult result = DiceAndroidHandoverParse( + handover, sizeof(handover), &cdi_attest, &cdi_seal, &chain, &chain_size); EXPECT_EQ(kDiceResultOk, result); - EXPECT_EQ(bcc_handover + 4, cdi_attest); - EXPECT_EQ(bcc_handover + 39, cdi_seal); - EXPECT_EQ(nullptr, bcc); - EXPECT_EQ(0u, bcc_size); + EXPECT_EQ(handover + 4, cdi_attest); + EXPECT_EQ(handover + 39, cdi_seal); + EXPECT_EQ(nullptr, chain); + EXPECT_EQ(0u, chain_size); } -TEST(BccHandoverTest, ParseHandoverWithoutBccButUnknownField) { - const uint8_t bcc_handover[] = { +TEST(DiceAndroidHandoverTest, ParseHandoverWithoutDiceChainButUnknownField) { + const uint8_t handover[] = { 0xa3, // CDI attest 0x01, 0x58, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, @@ -268,23 +271,23 @@ TEST(BccHandoverTest, ParseHandoverWithoutBccButUnknownField) { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Ignored unknown field 0x04, 0x01, - // 8-bytes of trailing data that aren't part of the BCC. + // 8-bytes of trailing data that aren't part of the DICE chain. 0x00, 0x41, 0x55, 0xa0, 0x42, 0x11, 0x22, 0x40}; const uint8_t *cdi_attest; const uint8_t *cdi_seal; - const uint8_t *bcc; - size_t bcc_size; - DiceResult result = BccHandoverParse(bcc_handover, sizeof(bcc_handover), - &cdi_attest, &cdi_seal, &bcc, &bcc_size); + const uint8_t *chain; + size_t chain_size; + DiceResult result = DiceAndroidHandoverParse( + handover, sizeof(handover), &cdi_attest, &cdi_seal, &chain, &chain_size); EXPECT_EQ(kDiceResultOk, result); - EXPECT_EQ(bcc_handover + 4, cdi_attest); - EXPECT_EQ(bcc_handover + 39, cdi_seal); - EXPECT_EQ(nullptr, bcc); - EXPECT_EQ(0u, bcc_size); + EXPECT_EQ(handover + 4, cdi_attest); + EXPECT_EQ(handover + 39, cdi_seal); + EXPECT_EQ(nullptr, chain); + EXPECT_EQ(0u, chain_size); } -TEST(BccHandoverTest, ParseHandoverCdiTooLarge) { - const uint8_t bcc_handover[] = { +TEST(DiceAndroidHandoverTest, ParseHandoverCdiTooLarge) { + const uint8_t handover[] = { 0xa2, // CDI attest 0x01, 0x58, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, @@ -294,14 +297,14 @@ TEST(BccHandoverTest, ParseHandoverCdiTooLarge) { 0x02, 0x58, 0x21, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - // 8-bytes of trailing data that aren't part of the BCC. + // 8-bytes of trailing data that aren't part of the DICE chain. 0x00, 0x41, 0x55, 0xa0, 0x42, 0x11, 0x22, 0x40}; const uint8_t *cdi_attest; const uint8_t *cdi_seal; - const uint8_t *bcc; - size_t bcc_size; - DiceResult result = BccHandoverParse(bcc_handover, sizeof(bcc_handover), - &cdi_attest, &cdi_seal, &bcc, &bcc_size); + const uint8_t *chain; + size_t chain_size; + DiceResult result = DiceAndroidHandoverParse( + handover, sizeof(handover), &cdi_attest, &cdi_seal, &chain, &chain_size); EXPECT_EQ(kDiceResultInvalidInput, result); } } diff --git a/src/boringssl_cert_op.c b/src/boringssl_cert_op.c index 432294c..9ece559 100644 --- a/src/boringssl_cert_op.c +++ b/src/boringssl_cert_op.c @@ -17,6 +17,7 @@ // HKDF-SHA512, and Ed25519-SHA512. #include <stdint.h> +#include <string.h> #include "dice/dice.h" #include "dice/ops.h" @@ -41,6 +42,7 @@ typedef struct DiceExtensionAsn1 { ASN1_OCTET_STRING* authority_hash; ASN1_OCTET_STRING* authority_descriptor; ASN1_ENUMERATED* mode; + ASN1_UTF8STRING* profile_name; } DiceExtensionAsn1; // clang-format off @@ -52,6 +54,7 @@ ASN1_SEQUENCE(DiceExtensionAsn1) = { ASN1_EXP_OPT(DiceExtensionAsn1, authority_hash, ASN1_OCTET_STRING, 4), ASN1_EXP_OPT(DiceExtensionAsn1, authority_descriptor, ASN1_OCTET_STRING, 5), ASN1_EXP_OPT(DiceExtensionAsn1, mode, ASN1_ENUMERATED, 6), + ASN1_EXP_OPT(DiceExtensionAsn1, profile_name, ASN1_UTF8STRING, 7), } ASN1_SEQUENCE_END(DiceExtensionAsn1) DECLARE_ASN1_FUNCTIONS(DiceExtensionAsn1) IMPLEMENT_ASN1_FUNCTIONS(DiceExtensionAsn1) @@ -426,6 +429,20 @@ static DiceResult GetDiceExtensionData(const DiceInputValues* input_values, goto out; } + // Encode profile name. + if (DICE_PROFILE_NAME) { + asn1->profile_name = ASN1_UTF8STRING_new(); + if (!asn1->profile_name) { + result = kDiceResultPlatformError; + goto out; + } + if (!ASN1_STRING_set(asn1->profile_name, DICE_PROFILE_NAME, + strlen(DICE_PROFILE_NAME))) { + result = kDiceResultPlatformError; + goto out; + } + } + *actual_size = i2d_DiceExtensionAsn1(asn1, NULL); if (buffer_size < *actual_size) { result = kDiceResultBufferTooSmall; diff --git a/src/boringssl_ecdsa_utils.c b/src/boringssl_ecdsa_utils.c index ef31812..876e87f 100644 --- a/src/boringssl_ecdsa_utils.c +++ b/src/boringssl_ecdsa_utils.c @@ -55,7 +55,7 @@ out: } static int hmac3(uint8_t k[64], uint8_t in1[64], uint8_t in2, - const uint8_t *in3, unsigned int in3_len, uint8_t out[64]) { + const uint8_t *in3, unsigned int in3_len, uint8_t out[64]) { int ret = 0; HMAC_CTX ctx; @@ -154,7 +154,8 @@ int P384KeypairFromSeed(uint8_t public_key[P384_PUBLIC_KEY_SIZE], goto out; } - pD = derivePrivateKey(group, seed, DICE_PRIVATE_KEY_SEED_SIZE, P384_PRIVATE_KEY_SIZE); + pD = derivePrivateKey(group, seed, DICE_PRIVATE_KEY_SEED_SIZE, + P384_PRIVATE_KEY_SIZE); if (!pD) { goto out; } @@ -178,14 +179,13 @@ int P384KeypairFromSeed(uint8_t public_key[P384_PUBLIC_KEY_SIZE], if (1 != EC_POINT_get_affine_coordinates_GFp(group, publicKey, x, y, NULL)) { goto out; } - if (BN_num_bytes(x) > P384_PRIVATE_KEY_SIZE) { + if (1 != BN_bn2bin_padded(&public_key[0], P384_PUBLIC_KEY_SIZE / 2, x)) { goto out; } - BN_bn2bin(x, &public_key[0]); - if (BN_num_bytes(y) > P384_PRIVATE_KEY_SIZE) { + if (1 != BN_bn2bin_padded(&public_key[P384_PUBLIC_KEY_SIZE / 2], + P384_PUBLIC_KEY_SIZE / 2, y)) { goto out; } - BN_bn2bin(y, &public_key[P384_PRIVATE_KEY_SIZE]); ret = 1; out: @@ -223,15 +223,13 @@ int P384Sign(uint8_t signature[P384_SIGNATURE_SIZE], const uint8_t *message, if (!sig) { goto out; } - - if (BN_num_bytes(sig->r) > P384_PRIVATE_KEY_SIZE) { + if (1 != BN_bn2bin_padded(&signature[0], P384_SIGNATURE_SIZE / 2, sig->r)) { goto out; } - BN_bn2bin(sig->r, &signature[0]); - if (BN_num_bytes(sig->s) > P384_PRIVATE_KEY_SIZE) { + if (1 != BN_bn2bin_padded(&signature[P384_SIGNATURE_SIZE / 2], + P384_SIGNATURE_SIZE / 2, sig->s)) { goto out; } - BN_bn2bin(sig->s, &signature[P384_PRIVATE_KEY_SIZE]); ret = 1; out: @@ -269,7 +267,8 @@ int P384Verify(const uint8_t *message, size_t message_size, if (!y) { goto out; } - bn_ret = BN_bin2bn(&public_key[P384_PUBLIC_KEY_SIZE / 2], P384_PUBLIC_KEY_SIZE / 2, y); + bn_ret = BN_bin2bn(&public_key[P384_PUBLIC_KEY_SIZE / 2], + P384_PUBLIC_KEY_SIZE / 2, y); if (!bn_ret) { goto out; } @@ -277,7 +276,6 @@ int P384Verify(const uint8_t *message, size_t message_size, goto out; } - sig = ECDSA_SIG_new(); if (!sig) { goto out; @@ -286,8 +284,8 @@ int P384Verify(const uint8_t *message, size_t message_size, if (!bn_ret) { goto out; } - bn_ret = BN_bin2bn(&signature[P384_SIGNATURE_SIZE / 2], P384_SIGNATURE_SIZE / 2, - sig->s); + bn_ret = BN_bin2bn(&signature[P384_SIGNATURE_SIZE / 2], + P384_SIGNATURE_SIZE / 2, sig->s); if (!bn_ret) { goto out; } diff --git a/src/cbor_cert_op.c b/src/cbor_cert_op.c index d0670de..4b6d171 100644 --- a/src/cbor_cert_op.c +++ b/src/cbor_cert_op.c @@ -172,6 +172,7 @@ static DiceResult EncodeCwt(void* context, const DiceInputValues* input_values, const int64_t kModeLabel = -4670551; const int64_t kSubjectPublicKeyLabel = -4670552; const int64_t kKeyUsageLabel = -4670553; + const int64_t kProfileNameLabel = -4670554; // Key usage constant per RFC 5280. const uint8_t kKeyUsageCertSign = 32; @@ -188,6 +189,9 @@ static DiceResult EncodeCwt(void* context, const DiceInputValues* input_values, if (input_values->authority_descriptor_size > 0) { map_pairs += 1; } + if (DICE_PROFILE_NAME) { + map_pairs += 1; + } struct CborOut out; CborOutInit(buffer, buffer_size, &out); @@ -247,6 +251,11 @@ static DiceResult EncodeCwt(void* context, const DiceInputValues* input_values, // Add the key usage. CborWriteInt(kKeyUsageLabel, &out); CborWriteBstr(/*data_size=*/1, &key_usage, &out); + // Add the profile name + if (DICE_PROFILE_NAME) { + CborWriteInt(kProfileNameLabel, &out); + CborWriteTstr(DICE_PROFILE_NAME, &out); + } *encoded_size = CborOutSize(&out); if (CborOutOverflowed(&out)) { return kDiceResultBufferTooSmall; diff --git a/src/cbor_reader_test.cc b/src/cbor_reader_test.cc index 7b14475..9d2332b 100644 --- a/src/cbor_reader_test.cc +++ b/src/cbor_reader_test.cc @@ -250,22 +250,22 @@ TEST(CborReaderTest, NullEncoding) { } TEST(CborReaderTest, TagEncoding) { - const uint8_t buffer[] = {0xcf, 0xd8, 0x18, 0xd9, 0xd9, 0xf8, 0xda, 0x4f, - 0x50, 0x53, 0x4e, 0xdb, 0x10, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00}; + const uint8_t buffer[] = {0xcf, 0xd8, 0x18, 0xd9, 0xd9, 0xf8, 0xda, + 0x4f, 0x50, 0x53, 0x4e, 0xdb, 0x10, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; CborIn in; uint64_t tag; CborInInit(buffer, sizeof(buffer), &in); EXPECT_EQ(CBOR_READ_RESULT_OK, CborReadTag(&in, &tag)); - EXPECT_EQ(/* Unassigned */15u, tag); + EXPECT_EQ(/* Unassigned */ 15u, tag); EXPECT_EQ(CBOR_READ_RESULT_OK, CborReadTag(&in, &tag)); - EXPECT_EQ(/* COSE_Sign1 */24u, tag); + EXPECT_EQ(/* COSE_Sign1 */ 24u, tag); EXPECT_EQ(CBOR_READ_RESULT_OK, CborReadTag(&in, &tag)); - EXPECT_EQ(/* Byte string */0xd9f8u, tag); + EXPECT_EQ(/* Byte string */ 0xd9f8u, tag); EXPECT_EQ(CBOR_READ_RESULT_OK, CborReadTag(&in, &tag)); - EXPECT_EQ(/* Openswan cfg */0x4f50534eu, tag); + EXPECT_EQ(/* Openswan cfg */ 0x4f50534eu, tag); EXPECT_EQ(CBOR_READ_RESULT_OK, CborReadTag(&in, &tag)); - EXPECT_EQ(/* Unassigned */0x1000000000000000u, tag); + EXPECT_EQ(/* Unassigned */ 0x1000000000000000u, tag); EXPECT_TRUE(CborInAtEnd(&in)); } @@ -274,8 +274,8 @@ TEST(CborReaderTest, TagInvalid) { // Reference https://www.iana.org/assignments/cbor-tags/cbor-tags.xhtml. const uint8_t invalid16[] = {0xd9, 0xff, 0xff}; const uint8_t invalid32[] = {0xda, 0xff, 0xff, 0xff, 0xff}; - const uint8_t invalid64[] = {0xdb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff}; + const uint8_t invalid64[] = {0xdb, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff}; CborIn in; uint64_t tag; CborInInit(invalid16, sizeof(invalid16), &in); diff --git a/src/dice_test.cc b/src/dice_test.cc index a5d3b9e..b7a34d9 100644 --- a/src/dice_test.cc +++ b/src/dice_test.cc @@ -191,7 +191,7 @@ TEST(DiceTest, NoExtraneousOps) { sizeof(next_state.certificate), next_state.certificate, &next_state.certificate_size, next_state.cdi_attest, next_state.cdi_seal); EXPECT_EQ(kDiceResultOk, result); - // These are brittle, but can act as a good sanity check that we're not + // These are brittle, but can act as an effective check that we're not // regressing in how many expensive operations we call. EXPECT_LE(ops.hash_count_, 2); EXPECT_LE(ops.kdf_count_, 4); diff --git a/src/mbedtls_ops.c b/src/mbedtls_ops.c index 4dbf2dd..b3d5e57 100644 --- a/src/mbedtls_ops.c +++ b/src/mbedtls_ops.c @@ -151,6 +151,45 @@ static uint8_t GetFieldTag(uint8_t tag) { } // Can be used with MBEDTLS_ASN1_CHK_ADD. +static int WriteExplicitModeField(uint8_t tag, int value, uint8_t** pos, + uint8_t* start) { + // ASN.1 constants not defined by mbedtls. + const uint8_t kEnumTypeTag = 10; + + int ret = 0; // Used by MBEDTLS_ASN1_CHK_ADD. + int field_length = 0; + MBEDTLS_ASN1_CHK_ADD(field_length, mbedtls_asn1_write_int(pos, start, value)); + // Overwrite the 'int' type. + ++(*pos); + --field_length; + MBEDTLS_ASN1_CHK_ADD(field_length, + mbedtls_asn1_write_tag(pos, start, kEnumTypeTag)); + + // Explicitly tagged, so add the field tag too. + MBEDTLS_ASN1_CHK_ADD(field_length, + mbedtls_asn1_write_len(pos, start, field_length)); + MBEDTLS_ASN1_CHK_ADD(field_length, + mbedtls_asn1_write_tag(pos, start, GetFieldTag(tag))); + return field_length; +} + +// Can be used with MBEDTLS_ASN1_CHK_ADD. +static int WriteExplicitUtf8StringField(uint8_t tag, const void* value, + size_t value_size, uint8_t** pos, + uint8_t* start) { + int ret = 0; // Used by MBEDTLS_ASN1_CHK_ADD. + int field_length = 0; + MBEDTLS_ASN1_CHK_ADD(field_length, mbedtls_asn1_write_utf8_string( + pos, start, value, value_size)); + // Explicitly tagged, so add the field tag too. + MBEDTLS_ASN1_CHK_ADD(field_length, + mbedtls_asn1_write_len(pos, start, field_length)); + MBEDTLS_ASN1_CHK_ADD(field_length, + mbedtls_asn1_write_tag(pos, start, GetFieldTag(tag))); + return field_length; +} + +// Can be used with MBEDTLS_ASN1_CHK_ADD. static int WriteExplicitOctetStringField(uint8_t tag, const uint8_t* value, size_t value_size, uint8_t** pos, uint8_t* start) { @@ -168,8 +207,6 @@ static int WriteExplicitOctetStringField(uint8_t tag, const uint8_t* value, static int GetDiceExtensionDataHelper(const DiceInputValues* input_values, uint8_t** pos, uint8_t* start) { - // ASN.1 constants not defined by mbedtls. - const uint8_t kEnumTypeTag = 10; // ASN.1 tags for extension fields. const uint8_t kDiceFieldCodeHash = 0; const uint8_t kDiceFieldCodeDescriptor = 1; @@ -178,24 +215,23 @@ static int GetDiceExtensionDataHelper(const DiceInputValues* input_values, const uint8_t kDiceFieldAuthorityHash = 4; const uint8_t kDiceFieldAuthorityDescriptor = 5; const uint8_t kDiceFieldMode = 6; + const uint8_t kDiceFieldProfileName = 7; // Build up the extension ASN.1 in reverse order. int ret = 0; // Used by MBEDTLS_ASN1_CHK_ADD. int length = 0; - // Add the mode field. - MBEDTLS_ASN1_CHK_ADD(length, - mbedtls_asn1_write_int(pos, start, input_values->mode)); - // Overwrite the 'int' type. - ++(*pos); - --length; - MBEDTLS_ASN1_CHK_ADD(length, - mbedtls_asn1_write_tag(pos, start, kEnumTypeTag)); + // Add the profile name field. + if (DICE_PROFILE_NAME) { + MBEDTLS_ASN1_CHK_ADD(length, WriteExplicitUtf8StringField( + kDiceFieldProfileName, DICE_PROFILE_NAME, + strlen(DICE_PROFILE_NAME), pos, start)); + } - // Explicitly tagged, so add the field tag too. - MBEDTLS_ASN1_CHK_ADD(length, mbedtls_asn1_write_len(pos, start, length)); + // Add the mode field. MBEDTLS_ASN1_CHK_ADD( - length, mbedtls_asn1_write_tag(pos, start, GetFieldTag(kDiceFieldMode))); + length, + WriteExplicitModeField(kDiceFieldMode, input_values->mode, pos, start)); // Add the authorityDescriptor field, if applicable. if (input_values->authority_descriptor_size > 0) { diff --git a/src/template_cbor_cert_op.c b/src/template_cbor_cert_op.c index 641e83b..c935dfb 100644 --- a/src/template_cbor_cert_op.c +++ b/src/template_cbor_cert_op.c @@ -167,7 +167,7 @@ DiceResult DiceGenerateCertificate( // Variable length descriptors are not supported. if (input_values->code_descriptor_size > 0 || input_values->config_type != kDiceConfigTypeInline || - input_values->authority_descriptor_size > 0) { + input_values->authority_descriptor_size > 0 || DICE_PROFILE_NAME) { return kDiceResultInvalidInput; } diff --git a/src/template_cert_op.c b/src/template_cert_op.c index daa4317..7dcb16f 100644 --- a/src/template_cert_op.c +++ b/src/template_cert_op.c @@ -177,7 +177,7 @@ DiceResult DiceGenerateCertificate( // Variable length descriptors are not supported. if (input_values->code_descriptor_size > 0 || input_values->config_type != kDiceConfigTypeInline || - input_values->authority_descriptor_size > 0) { + input_values->authority_descriptor_size > 0 || DICE_PROFILE_NAME) { return kDiceResultInvalidInput; } diff --git a/src/test_utils.cc b/src/test_utils.cc index cb21d3f..12663cc 100644 --- a/src/test_utils.cc +++ b/src/test_utils.cc @@ -535,7 +535,7 @@ ScopedCbor ExtractCwtFromCborCertificate(const uint8_t* certificate, return nullptr; } ScopedCbor cwt(cn_cbor_decode(payload->v.bytes, payload->length, &error)); - if (cwt && cwt->type != CN_CBOR_MAP) { + if (!cwt || cwt->type != CN_CBOR_MAP) { return nullptr; } return cwt; diff --git a/third_party/cose-c/cose_ed25519_deps.cc b/third_party/cose-c/cose_ed25519_deps.cc index 1eb8a15..3d78b60 100644 --- a/third_party/cose-c/cose_ed25519_deps.cc +++ b/third_party/cose-c/cose_ed25519_deps.cc @@ -23,7 +23,8 @@ // Gets the public key from a well-formed Ed25519 COSE_Key. On success populates // |public_key| and returns true. -static bool GetPublicKeyFromCbor(const cn_cbor *key, uint8_t public_key[PUBLIC_KEY_SIZE]) { +static bool GetPublicKeyFromCbor(const cn_cbor *key, + uint8_t public_key[PUBLIC_KEY_SIZE]) { const int64_t kCoseKeyAlgLabel = 3; const int64_t kCoseKeyOpsLabel = 4; const uint64_t kCoseKeyOpsVerify = 2; diff --git a/third_party/cose-c/cose_p384_deps.cc b/third_party/cose-c/cose_p384_deps.cc index 795b080..3b9a9d9 100644 --- a/third_party/cose-c/cose_p384_deps.cc +++ b/third_party/cose-c/cose_p384_deps.cc @@ -28,8 +28,8 @@ #include "openssl/sha.h" // Gets the public key from a well-formed ECDSA P-384 COSE_Key. On -// success populates |public_key| and returns true; public_key must hold 96 bytes -// (uncompressed format). +// success populates |public_key| and returns true; public_key must hold 96 +// bytes (uncompressed format). static bool GetPublicKeyFromCbor(const cn_cbor *key, uint8_t *public_key) { const int64_t kCoseKeyAlgLabel = 3; const int64_t kCoseKeyOpsLabel = 4; @@ -101,7 +101,8 @@ bool ECDSA_Verify(COSE *cose_signer, int signature_index, COSE_KEY *cose_key, if (!signature || !key) { return false; } - if (signature->type != CN_CBOR_BYTES || signature->length != PUBLIC_KEY_SIZE) { + if (signature->type != CN_CBOR_BYTES || + signature->length != PUBLIC_KEY_SIZE) { return false; } uint8_t public_key[PUBLIC_KEY_SIZE]; diff --git a/third_party/cose-c/include/ed25519/cose/cose_configure.h b/third_party/cose-c/include/ed25519/cose/cose_configure.h index f6d91a2..b487905 100644 --- a/third_party/cose-c/include/ed25519/cose/cose_configure.h +++ b/third_party/cose-c/include/ed25519/cose/cose_configure.h @@ -1,3 +1,6 @@ +#ifndef THIRD_PARTY_COSE_C_ED25519_COSE_COSE_CONFIGURE_H_ +#define THIRD_PARTY_COSE_C_ED25519_COSE_COSE_CONFIGURE_H_ + #define USE_EDDSA #define PUBLIC_KEY_SIZE 32 @@ -9,3 +12,5 @@ #define INCLUDE_SIGN1 1 #define INCLUDE_COUNTERSIGNATURE 0 #define INCLUDE_COUNTERSIGNATURE1 0 + +#endif // THIRD_PARTY_COSE_C_ED25519_COSE_COSE_CONFIGURE_H_ diff --git a/third_party/cose-c/include/p384/cose/cose_configure.h b/third_party/cose-c/include/p384/cose/cose_configure.h index ebb4469..5ddf8d7 100644 --- a/third_party/cose-c/include/p384/cose/cose_configure.h +++ b/third_party/cose-c/include/p384/cose/cose_configure.h @@ -1,3 +1,6 @@ +#ifndef THIRD_PARTY_COSE_C_P384_COSE_COSE_CONFIGURE_H_ +#define THIRD_PARTY_COSE_C_P384_COSE_COSE_CONFIGURE_H_ + #define USE_ECDSA_SHA_384 #define PUBLIC_KEY_SIZE 96 @@ -9,3 +12,5 @@ #define INCLUDE_SIGN1 1 #define INCLUDE_COUNTERSIGNATURE 0 #define INCLUDE_COUNTERSIGNATURE1 0 + +#endif // THIRD_PARTY_COSE_C_P384_COSE_COSE_CONFIGURE_H_ diff --git a/third_party/mbedtls/custom_config.h b/third_party/mbedtls/custom_config.h index 24d5418..3044667 100644 --- a/third_party/mbedtls/custom_config.h +++ b/third_party/mbedtls/custom_config.h @@ -12,8 +12,8 @@ // License for the specific language governing permissions and limitations under // the License. -#ifndef MBEDTLS_CONFIG_H -#define MBEDTLS_CONFIG_H +#ifndef THIRD_PARTY_MBEDTLS_CUSTOM_CONFIG_H_ +#define THIRD_PARTY_MBEDTLS_CUSTOM_CONFIG_H_ /* mbed TLS feature support */ #define MBEDTLS_DEPRECATED_REMOVED @@ -40,4 +40,4 @@ #include "mbedtls/check_config.h" -#endif /* MBEDTLS_CONFIG_H */ +#endif /* THIRD_PARTY_MBEDTLS_CUSTOM_CONFIG_H_ */ diff --git a/toolchains/BUILD.gn b/toolchains/BUILD.gn index 16abe57..93bc01e 100644 --- a/toolchains/BUILD.gn +++ b/toolchains/BUILD.gn @@ -34,7 +34,7 @@ config("enable_sanitizers") { filter_path = rebase_path("sanitize_filter.txt", root_build_dir) cflags = [ "-fsanitize=address,undefined,integer", - "-fsanitize-blacklist=$filter_path", + "-fsanitize-blacklist=$filter_path", # inclusive-language: ignore ] ldflags = cflags inputs = [ "sanitize_filter.txt" ] diff --git a/src/android/BUILD.gn b/tools/BUILD.gn index b9b9574..fdf4ba9 100644 --- a/src/android/BUILD.gn +++ b/tools/BUILD.gn @@ -1,4 +1,4 @@ -# Copyright 2021 Google LLC +# Copyright 2023 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); you may not # use this file except in compliance with the License. You may obtain a copy of @@ -13,24 +13,22 @@ # the License. import("//build_overrides/pigweed.gni") -import("$dir_pw_build/target_types.gni") -import("$dir_pw_unit_test/test.gni") -pw_source_set("bcc") { - sources = [ "bcc.c" ] - deps = [ - "//:cbor_reader", - "//:cbor_writer", - "//:dice_with_cbor_ed25519_cert", - ] -} - -pw_test("bcc_test") { - sources = [ "bcc_test.cc" ] - deps = [ ":bcc" ] -} +import("$dir_pw_build/python.gni") -pw_executable("bcc_fuzzer") { - sources = [ "bcc_fuzzer.cc" ] - deps = [ ":bcc" ] +pw_python_package("tools") { + setup = [ + "pyproject.toml", + "setup.cfg", + "setup.py", + ] + sources = [ + "open_dice_tools/__init__.py", + "open_dice_tools/presubmit.py", + ] + python_deps = [ + "$dir_pw_cli/py", + "$dir_pw_presubmit/py", + ] + pylintrc = "$dir_pigweed/.pylintrc" } diff --git a/tools/open_dice_tools/__init__.py b/tools/open_dice_tools/__init__.py new file mode 100644 index 0000000..241f8ac --- /dev/null +++ b/tools/open_dice_tools/__init__.py @@ -0,0 +1,13 @@ +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may not +# use this file except in compliance with the License. You may obtain a copy of +# the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# 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/tools/open_dice_tools/presubmit.py b/tools/open_dice_tools/presubmit.py new file mode 100644 index 0000000..48752ae --- /dev/null +++ b/tools/open_dice_tools/presubmit.py @@ -0,0 +1,149 @@ +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may not +# use this file except in compliance with the License. You may obtain a copy of +# the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations under +# the License. +"""Presubmit script.""" + +import argparse +import logging +import os +from pathlib import Path +import re +import sys + +import pw_cli.log +import pw_presubmit +from pw_presubmit import ( + build, + cli, + cpp_checks, + format_code, + git_repo, + inclusive_language, + install_hook, + keep_sorted, + presubmit_context, + python_checks, +) + +_LOG = logging.getLogger(__name__) + +# Set up variables for key project paths. +try: + PROJECT_ROOT = Path(os.environ["PW_PROJECT_ROOT"]) +except KeyError: + print( + "ERROR: The presubmit checks must be run in the Open Dice project's " + "root directory", + file=sys.stderr, + ) + sys.exit(2) + +PIGWEED_ROOT = PROJECT_ROOT / "third_party" / "pigweed" / "src" + +# Rerun the build if files with these extensions change. +_BUILD_EXTENSIONS = frozenset( + [".rst", ".gn", ".gni", *format_code.C_FORMAT.extensions] +) + +default_build = build.GnGenNinja(name="default_build") + +EXCLUSIONS = presubmit_context.FormatOptions.load().exclude + +OTHER_CHECKS = (build.gn_gen_check,) + +_FORMAT = (format_code.presubmit_checks(exclude=EXCLUSIONS),) + +QUICK = ( + default_build, + _FORMAT, +) + + +def include_guard(path: Path) -> str: + path = path.relative_to(PROJECT_ROOT) + exclude = ("include",) + transform = {"ulib": "lib"} + parts = [transform.get(x, x) for x in path.parts if x not in exclude] + return re.sub(r"[.-]", "_", "".join(f"{x}_" for x in parts).upper()) + + +LINTFORMAT = ( + _FORMAT, + cpp_checks.include_guard_check(include_guard).with_filter( + exclude=EXCLUSIONS + ), + inclusive_language.presubmit_check.with_filter(exclude=EXCLUSIONS), + keep_sorted.presubmit_check.with_filter(exclude=EXCLUSIONS), + python_checks.gn_python_lint, +) + +FULL = ( + QUICK, # Add all checks from the 'quick' program + LINTFORMAT, + # Use the upstream Python checks, with custom path filters applied. + python_checks.gn_python_check, +) + +PROGRAMS = pw_presubmit.Programs( + # keep-sorted: start + full=FULL, + lintformat=LINTFORMAT, + other_checks=OTHER_CHECKS, + quick=QUICK, + # keep-sorted: end +) + + +def run(install: bool, exclude: list, **presubmit_args) -> int: + """Process the --install argument then invoke pw_presubmit.""" + + # Install the presubmit Git pre-push hook, if requested. + if install: + install_hook.install_git_hook( + "pre-push", + [ + "python", + "-m", + "sample_project_tools.presubmit_checks", + "--base", + "origin/main..HEAD", + "--program", + "quick", + ], + ) + return 0 + + repos = git_repo.discover_submodules(superproject_dir=PROJECT_ROOT) + return cli.run( + root=PROJECT_ROOT, repositories=repos, exclude=exclude, **presubmit_args + ) + + +def main() -> int: + """Run the presubmit checks for this repository.""" + parser = argparse.ArgumentParser(description=__doc__) + cli.add_arguments(parser, PROGRAMS, "quick") + + # Define an option for installing a Git pre-push hook for this script. + parser.add_argument( + "--install", + action="store_true", + help="Install the presubmit as a Git pre-push hook and exit.", + ) + + return run(**vars(parser.parse_args())) + + +if __name__ == "__main__": + pw_cli.log.install(logging.INFO) + sys.exit(main()) diff --git a/tools/pyproject.toml b/tools/pyproject.toml new file mode 100644 index 0000000..60f1f5f --- /dev/null +++ b/tools/pyproject.toml @@ -0,0 +1,16 @@ +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may not +# use this file except in compliance with the License. You may obtain a copy of +# the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations under +# the License. +[build-system] +requires = ['setuptools', 'wheel'] +build-backend = 'setuptools.build_meta' diff --git a/tools/setup.cfg b/tools/setup.cfg new file mode 100644 index 0000000..71345ad --- /dev/null +++ b/tools/setup.cfg @@ -0,0 +1,31 @@ +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may not +# use this file except in compliance with the License. You may obtain a copy of +# the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations under +# the License. +[metadata] +name = open_dice_tools +version = 0.0.1 +author = Google LLC +description = Utilities for Open Dice development + +[options] +packages = find: +zip_safe = False +install_requires = + +[options.entry_points] +console_scripts = + find-files = open_dice_tools.find_files:main + +[options.package_data] +open_dice_tools = + py.typed diff --git a/tools/setup.py b/tools/setup.py new file mode 100644 index 0000000..838717a --- /dev/null +++ b/tools/setup.py @@ -0,0 +1,18 @@ +# Copyright 2023 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may not +# use this file except in compliance with the License. You may obtain a copy of +# the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations under +# the License. +"""Utilities for Open Dice development.""" + +import setuptools # type: ignore + +setuptools.setup() # Package definition in setup.cfg |