├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── docs └── project-kirkland.pdf ├── fmd ├── README.md ├── doc │ └── fmd_design_v0_3.pdf ├── inc │ └── fmd │ │ ├── fmd.h │ │ ├── generate.h │ │ ├── parse.h │ │ └── util.h ├── lib │ ├── Makefile │ ├── generate.c │ └── parse.c └── samples │ └── create_parse │ ├── Makefile │ └── main.c ├── omc └── open_mailbox_communications.pdf ├── redfish └── redfish_signed_measurements.pptx └── spdm_lite ├── CMakeLists.txt ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── everparse ├── SPDM.3d └── build.sh ├── include └── spdm_lite │ ├── common │ ├── algorithms.h │ ├── capabilities.h │ ├── config.h │ ├── crypto.h │ ├── crypto_types.h │ ├── defs.h │ ├── error.h │ ├── key_schedule.h │ ├── messages.h │ ├── session.h │ ├── session_types.h │ ├── sign.h │ ├── transcript.h │ ├── utils.h │ ├── vendor_defined_pub_key.h │ └── version.h │ ├── crypto_impl │ ├── mbedtls_crypto.h │ ├── mbedtls_sign.h │ ├── raw_serialize.h │ └── tpmt_public_serialize.h │ ├── everparse │ └── SPDMWrapper.h │ ├── requester │ └── requester.h │ └── responder │ └── responder.h ├── library ├── common │ ├── algorithms.c │ ├── crypto.c │ ├── crypto_types.c │ ├── error.c │ ├── key_schedule.c │ ├── session.c │ ├── sign.c │ ├── transcript.c │ ├── utils.c │ └── vendor_defined_pub_key.c ├── crypto_impl │ ├── mbedtls_crypto.c │ ├── mbedtls_helpers.c │ ├── mbedtls_helpers.h │ ├── mbedtls_sign.c │ ├── raw_serialize.c │ └── tpmt_public_serialize.c ├── everparse │ ├── EverParse.h │ ├── EverParseEndianness.h │ ├── SPDM.c │ ├── SPDM.h │ └── SPDMWrapper.c ├── requester │ ├── requester.c │ ├── requester_finish.c │ ├── requester_functions.h │ ├── requester_get_capabilities.c │ ├── requester_get_pub_key.c │ ├── requester_get_version.c │ ├── requester_give_pub_key.c │ ├── requester_key_exchange.c │ ├── requester_negotiate_algorithms.c │ ├── send_request.c │ └── send_request.h └── responder │ ├── responder.c │ ├── state_need_requester_key.c │ ├── state_session_established.c │ ├── state_waiting_for_finish.c │ ├── state_waiting_for_get_capabilities.c │ ├── state_waiting_for_get_version.c │ ├── state_waiting_for_key_exchange.c │ └── state_waiting_for_negotiate_algorithms.c ├── samples ├── include │ └── spdm_lite │ │ └── samples │ │ ├── requester_app.h │ │ └── responder_app.h ├── requester_app.c └── responder_app.c └── testing ├── include └── spdm_lite │ └── testing │ ├── add_2_app.h │ ├── dummy_crypto.h │ ├── host_context.h │ └── utils.h ├── library ├── add_2_app.c ├── dummy_crypto.c ├── host_context.c └── utils.cc ├── requester_test.cc ├── sample_app_test.cc ├── spdm_parser_test.cc ├── state_need_requester_key_test.cc ├── state_session_established_test.cc ├── state_waiting_for_finish_test.cc ├── state_waiting_for_get_capabilities_test.cc ├── state_waiting_for_get_version_test.cc ├── state_waiting_for_key_exchange_test.cc ├── state_waiting_for_negotiate_algorithms_test.cc └── tpmt_public_serialize_test.cc /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # How to Contribute 2 | 3 | We'd love to accept your patches and contributions to this project. There are 4 | just a few small guidelines you need to follow. 5 | 6 | ## Contributor License Agreement 7 | 8 | Contributions to this project must be accompanied by a Contributor License 9 | Agreement (CLA). You (or your employer) retain the copyright to your 10 | contribution; this simply gives us permission to use and redistribute your 11 | contributions as part of the project. Head over to 12 | to see your current agreements on file or 13 | to sign a new one. 14 | 15 | You generally only need to submit a CLA once, so if you've already submitted one 16 | (even if it was for a different project), you probably don't need to do it 17 | again. 18 | 19 | ## Code Reviews 20 | 21 | All submissions, including submissions by project members, require review. We 22 | use GitHub pull requests for this purpose. Consult 23 | [GitHub Help](https://help.github.com/articles/about-pull-requests/) for more 24 | information on using pull requests. 25 | 26 | ## Community Guidelines 27 | 28 | This project follows 29 | [Google's Open Source Community Guidelines](https://opensource.google/conduct/). 30 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # PINT (Platform Integrity) 2 | 3 | PINT is a set of formats and protocols for attesting and securing platform software 4 | in datacenter environments. This includes: 5 | 6 | * Peripheral (GPU, NIC, etc.) firmware 7 | * Main board firmware (BIOS) 8 | * Operating system components (bootloader, kernel, system services) 9 | 10 | This is not an officially supported Google product. 11 | 12 | ## Projects 13 | 14 | PINT currently defines the following primitives for securing system software: 15 | 16 | | Project Name | Description | 17 | | --------------------------------------- | ----------- | 18 | | [Firmware Measurement Descriptor](fmd/) | A binary header which describes how an Root of Trust should measure a firmware image | 19 | | [Redfish](redfish/) | Draft proposals for the Redfish specification in DMTF | 20 | | [Open Mailbox Communications](omc/) | An exploration for point-to-point communications using open protocols | 21 | | [SPDM-Lite](spdm_lite/) | A light-weight implementation of SPDM 1.2 secure sessions | 22 | -------------------------------------------------------------------------------- /docs/project-kirkland.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/google/PINT/c5b2102bebcc2abc2e1b17494e46eaff97ae9444/docs/project-kirkland.pdf -------------------------------------------------------------------------------- /fmd/README.md: -------------------------------------------------------------------------------- 1 | # Firmware Measurement Descriptor 2 | 3 | The Firmware Measurement Descriptor (FMD) is a file header which provides 4 | metadata about how the image should be measured (such as by a hardware 5 | Root of Trust) during boot. 6 | 7 | ## Format and Design 8 | 9 | See the [FMD design doc](doc/fmd_design_v0_3.pdf) for details about the 10 | motivation, goals, and high level design concepts related to FMD. 11 | 12 | ## Reference Library 13 | 14 | In addition to the descriptor format, a reference library is also provided for 15 | creating and parsing the descriptor. 16 | 17 | Source for the library can be found in the [lib](lib/) directory. Public 18 | headers are in [inc/fmd](inc/fmd/). 19 | 20 | ### Samples 21 | 22 | The [samples directory](samples/) contains example code which uses the 23 | reference library to do common FMD-related tasks. 24 | 25 | * **create\_parse**: Generate, serialize, and parse an FMD descriptor 26 | -------------------------------------------------------------------------------- /fmd/doc/fmd_design_v0_3.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/google/PINT/c5b2102bebcc2abc2e1b17494e46eaff97ae9444/fmd/doc/fmd_design_v0_3.pdf -------------------------------------------------------------------------------- /fmd/inc/fmd/generate.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #ifndef __FMD_GENERATE_H 18 | #define __FMD_GENERATE_H 19 | 20 | #include "fmd/fmd.h" 21 | #include "fmd/util.h" 22 | 23 | #include 24 | 25 | int create_descriptor(const struct fmd_region* regions, size_t region_count, 26 | int hash_type, struct image_fmd *out); 27 | 28 | #endif // __FMD_GENERATE_H 29 | -------------------------------------------------------------------------------- /fmd/inc/fmd/parse.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #ifndef __FMD_PARSE_H 18 | #define __FMD_PARSE_H 19 | 20 | #include "fmd/fmd.h" 21 | #include "fmd/util.h" 22 | 23 | int parse_descriptor(void *flash_addr, struct image_fmd *descriptor); 24 | 25 | #endif // __FMD_PARSE_H 26 | -------------------------------------------------------------------------------- /fmd/inc/fmd/util.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #ifndef _UTIL_H 18 | #define _UTIL_H 19 | 20 | #include "fmd.h" 21 | 22 | #define MAX_REGION_COUNT 0xFF 23 | 24 | #define FMD_SUCCESS 0x0 25 | #define FMD_ERROR_INVALID_FORMAT 0x1 26 | #define FMD_ERROR_INVALID_ARGUMENT 0x2 27 | #define FMD_ERROR_UNKNOWN_VERSION 0x2 28 | #define FMD_ERROR_UNKNOWN 0x2 29 | 30 | struct image_fmd { 31 | struct fmd_header header; 32 | struct fmd_region_info region_info; 33 | struct fmd_region regions[MAX_REGION_COUNT]; 34 | }; 35 | 36 | #endif // _UTIL_H 37 | -------------------------------------------------------------------------------- /fmd/lib/Makefile: -------------------------------------------------------------------------------- 1 | CC = gcc 2 | AR = ar 3 | 4 | LIBFMD = libfmd.a 5 | CFLAGS = -I../inc -Wall -Werror 6 | 7 | OBJECTS = parse.o generate.o 8 | 9 | all: $(LIBFMD) 10 | 11 | %.o: %.c 12 | $(CC) -c -o $@ $< $(CFLAGS) 13 | 14 | $(LIBFMD): $(OBJECTS) 15 | ar -crv $@ $^ 16 | 17 | clean: 18 | rm -f *.a *.o 19 | -------------------------------------------------------------------------------- /fmd/lib/generate.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #include "fmd/generate.h" 18 | 19 | #include 20 | 21 | int create_descriptor(const struct fmd_region* regions, size_t region_count, 22 | int hash_type, struct image_fmd *out) { 23 | // Populate header 24 | out->header.tlv.tag = FMD_HEADER_TAG; 25 | out->header.tlv.length = sizeof(out->header); 26 | out->header.tlv.version = FMD_HEADER_VERSION; 27 | out->header.magic = FMD_MAGIC; 28 | out->header.descriptor_offset = 0; 29 | out->header.descriptor_area_size = sizeof(out->header) + 30 | sizeof(out->region_info) + 31 | (region_count * sizeof(struct fmd_region)); 32 | 33 | // Populate region info 34 | out->region_info.tlv.tag = FMD_REGION_INFO_TAG; 35 | out->region_info.tlv.length = sizeof(out->region_info); 36 | out->region_info.tlv.version = FMD_REGION_INFO_VERSION; 37 | out->region_info.region_count = region_count; 38 | out->region_info.hash_type = hash_type; 39 | 40 | memcpy(out->regions, regions, sizeof(struct fmd_region) * region_count); 41 | 42 | return FMD_SUCCESS; 43 | } 44 | 45 | -------------------------------------------------------------------------------- /fmd/lib/parse.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #include "fmd/parse.h" 18 | #include "fmd/util.h" 19 | 20 | #include 21 | 22 | int parse_region_info(struct fmd_region_info *region_info, struct image_fmd *descriptor) { 23 | if (region_info->tlv.version != FMD_REGION_INFO_VERSION) { 24 | return FMD_ERROR_UNKNOWN_VERSION; 25 | } 26 | 27 | memcpy(&descriptor->region_info, region_info, sizeof(struct fmd_region_info)); 28 | 29 | return FMD_SUCCESS; 30 | } 31 | 32 | int parse_payload_region(struct fmd_region *region, uint32_t region_idx, 33 | struct image_fmd *descriptor) { 34 | 35 | if (region->tlv.version != FMD_REGION_VERSION) { 36 | return FMD_ERROR_UNKNOWN_VERSION; 37 | } 38 | 39 | if (region_idx >= MAX_REGION_COUNT) { 40 | return FMD_ERROR_INVALID_FORMAT; 41 | } 42 | 43 | memcpy(&descriptor->regions[region_idx], region, sizeof(struct fmd_region)); 44 | 45 | return FMD_SUCCESS; 46 | } 47 | 48 | int parse_header(struct fmd_header *header, struct image_fmd *descriptor) { 49 | if (header->tlv.version != FMD_HEADER_VERSION) { 50 | return FMD_ERROR_UNKNOWN_VERSION; 51 | } 52 | 53 | // Header is assumed to be the first TLV structure. Fail if this structure is 54 | // not the descriptor header. 55 | if (header->tlv.tag != FMD_HEADER_TAG || header->magic != FMD_MAGIC) { 56 | return FMD_ERROR_INVALID_FORMAT; 57 | } 58 | 59 | memcpy(&descriptor->header, header, sizeof(struct fmd_header)); 60 | 61 | return FMD_SUCCESS; 62 | } 63 | 64 | int parse_descriptor(void *flash_addr, struct image_fmd *descriptor) { 65 | int rc = parse_header((struct fmd_header *)flash_addr, descriptor); 66 | 67 | // Loop through TLV sections. Handle those which are known to this parser, 68 | // while skipping any unknown sections. 69 | uint32_t region_idx = 0; 70 | void *offset = flash_addr + descriptor->header.tlv.length; 71 | while (offset < flash_addr + descriptor->header.descriptor_area_size) { 72 | struct tlv_header *tlv = (struct tlv_header*)offset; 73 | 74 | switch (tlv->tag) { 75 | case FMD_REGION_INFO_TAG: 76 | rc = parse_region_info((struct fmd_region_info *)offset, descriptor); 77 | break; 78 | case FMD_REGION_TAG: 79 | rc = parse_payload_region((struct fmd_region *)offset, region_idx, 80 | descriptor); 81 | region_idx++; 82 | break; 83 | default: 84 | // Skip any unknown sections 85 | rc = FMD_SUCCESS; 86 | break; 87 | } 88 | 89 | if (rc != FMD_SUCCESS) { 90 | return rc; 91 | } 92 | 93 | offset += tlv->length; 94 | } 95 | 96 | // Number of region TLVs found in the descriptor must match the region count 97 | if (descriptor->region_info.region_count != region_idx) { 98 | return FMD_ERROR_INVALID_FORMAT; 99 | } 100 | 101 | return FMD_SUCCESS; 102 | } 103 | -------------------------------------------------------------------------------- /fmd/samples/create_parse/Makefile: -------------------------------------------------------------------------------- 1 | CC = gcc 2 | 3 | PROJECT_ROOT = ../.. 4 | 5 | LIBFMD = $(PROJECT_ROOT)/lib/libfmd.a 6 | SAMPLE = create_parse 7 | CFLAGS = -I$(PROJECT_ROOT)/inc -Wall -Werror -MD 8 | 9 | OBJECTS = main.o 10 | 11 | all: $(SAMPLE) 12 | 13 | %.o: %.c 14 | $(CC) -c -o $@ $< $(CFLAGS) 15 | 16 | $(LIBFMD): 17 | make -C $(PROJECT_ROOT)/lib 18 | 19 | $(SAMPLE): $(OBJECTS) $(LIBFMD) 20 | $(CC) -o $@ $^ 21 | 22 | clean: 23 | rm -f *.o *.d $(SAMPLE) 24 | 25 | -include $(OBJECTS:.o=.d) 26 | -------------------------------------------------------------------------------- /fmd/samples/create_parse/main.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2021 Google LLC 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | #include 18 | #include 19 | 20 | #include 21 | #include 22 | #include 23 | #include 24 | 25 | #define IMAGE_REGION_BASE 0x1000 26 | 27 | #define ARRAYSIZE(x) (sizeof(x) / sizeof(*x)) 28 | 29 | static const struct tlv_header region_tlv_header = { 30 | .tag = FMD_REGION_TAG, 31 | .length = sizeof(struct fmd_region), 32 | .version = FMD_REGION_VERSION, 33 | }; 34 | 35 | static const struct fmd_region global_regions[] = { 36 | { 37 | .tlv = region_tlv_header, 38 | .region_name = "region1", 39 | .region_offset = IMAGE_REGION_BASE, 40 | .region_size = 0x1000 41 | }, 42 | { 43 | .tlv = region_tlv_header, 44 | .region_name = "region2", 45 | .region_offset = IMAGE_REGION_BASE + 0x1000, 46 | .region_size = 0x1000 47 | }, 48 | { 49 | .tlv = region_tlv_header, 50 | .region_name = "region3", 51 | .region_offset = IMAGE_REGION_BASE + 0x2000, 52 | .region_size = 0x1000 53 | }, 54 | }; 55 | 56 | int main() { 57 | int rc; 58 | 59 | // Write a descriptor to a file 60 | struct image_fmd desc; 61 | rc = create_descriptor(global_regions, ARRAYSIZE(global_regions), FMD_HASH_SHA256, 62 | &desc); 63 | if (rc != FMD_SUCCESS) { 64 | printf("ERROR: Failed to create image descriptor, error code=%d\n", rc); 65 | return rc; 66 | } 67 | 68 | printf("Successfully generated an image descriptor!\n"); 69 | 70 | // Read the descriptor back 71 | struct image_fmd out_desc; 72 | rc = parse_descriptor(&desc, &out_desc); 73 | if (rc != FMD_SUCCESS) { 74 | printf("ERROR: Failed to parse image descriptor, error code=%d\n", rc); 75 | return rc; 76 | } 77 | 78 | printf("Successfully parsed the generated image descriptor!\n"); 79 | 80 | return 0; 81 | } 82 | -------------------------------------------------------------------------------- /omc/open_mailbox_communications.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/google/PINT/c5b2102bebcc2abc2e1b17494e46eaff97ae9444/omc/open_mailbox_communications.pdf -------------------------------------------------------------------------------- /redfish/redfish_signed_measurements.pptx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/google/PINT/c5b2102bebcc2abc2e1b17494e46eaff97ae9444/redfish/redfish_signed_measurements.pptx -------------------------------------------------------------------------------- /spdm_lite/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.10) 2 | 3 | project(spdm_lite) 4 | 5 | set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DCMAKE_BUILD -I${CMAKE_CURRENT_SOURCE_DIR}/include") 6 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DCMAKE_BUILD -I${CMAKE_CURRENT_SOURCE_DIR}/include") 7 | 8 | set(TEST_INCLUDES "${CMAKE_CURRENT_SOURCE_DIR}/testing/include") 9 | set(SAMPLE_INCLUDES "${CMAKE_CURRENT_SOURCE_DIR}/samples/include") 10 | 11 | # GoogleTest requires at least C++14 12 | set(CMAKE_CXX_STANDARD 14) 13 | 14 | include(FetchContent) 15 | FetchContent_Declare( 16 | googletest 17 | GIT_REPOSITORY https://github.com/google/googletest.git 18 | GIT_TAG release-1.12.1 19 | ) 20 | # For Windows: Prevent overriding the parent project's compiler/linker settings 21 | set(gtest_force_shared_crt ON CACHE BOOL "" FORCE) 22 | FetchContent_MakeAvailable(googletest) 23 | 24 | ## Declare libraries ## 25 | 26 | add_library(utils STATIC 27 | library/common/utils.c) 28 | 29 | 30 | add_library(everparse STATIC 31 | library/everparse/SPDM.c 32 | library/everparse/SPDMWrapper.c) 33 | 34 | target_link_libraries(everparse 35 | utils) 36 | 37 | 38 | add_library(common STATIC 39 | library/common/algorithms.c 40 | library/common/crypto.c 41 | library/common/crypto_types.c 42 | library/common/error.c 43 | library/common/key_schedule.c 44 | library/common/session.c 45 | library/common/sign.c 46 | library/common/transcript.c 47 | library/common/vendor_defined_pub_key.c) 48 | 49 | target_link_libraries(common 50 | everparse 51 | utils) 52 | 53 | 54 | add_library(requester STATIC 55 | library/requester/requester.c 56 | library/requester/requester_finish.c 57 | library/requester/requester_get_capabilities.c 58 | library/requester/requester_get_pub_key.c 59 | library/requester/requester_get_version.c 60 | library/requester/requester_give_pub_key.c 61 | library/requester/requester_key_exchange.c 62 | library/requester/requester_negotiate_algorithms.c 63 | library/requester/send_request.c) 64 | 65 | target_link_libraries(requester 66 | common 67 | everparse 68 | utils) 69 | 70 | 71 | add_library(responder STATIC 72 | library/responder/responder.c 73 | library/responder/state_need_requester_key.c 74 | library/responder/state_session_established.c 75 | library/responder/state_waiting_for_finish.c 76 | library/responder/state_waiting_for_get_capabilities.c 77 | library/responder/state_waiting_for_get_version.c 78 | library/responder/state_waiting_for_key_exchange.c 79 | library/responder/state_waiting_for_negotiate_algorithms.c) 80 | 81 | target_link_libraries(responder 82 | common 83 | everparse 84 | utils) 85 | 86 | 87 | add_library(raw_serialize STATIC 88 | library/crypto_impl/raw_serialize.c) 89 | 90 | add_library(mbedtls_crypto STATIC 91 | library/crypto_impl/mbedtls_crypto.c 92 | library/crypto_impl/mbedtls_helpers.c 93 | library/crypto_impl/mbedtls_sign.c) 94 | 95 | target_link_libraries(mbedtls_crypto 96 | common 97 | mbedcrypto 98 | pthread) 99 | 100 | add_library(tpmt_public_serialize STATIC 101 | library/crypto_impl/tpmt_public_serialize.c) 102 | 103 | target_link_libraries(tpmt_public_serialize 104 | common 105 | libtss2-mu.so) 106 | 107 | add_library(sample_app STATIC 108 | samples/requester_app.c 109 | samples/responder_app.c) 110 | 111 | target_link_libraries(sample_app 112 | common 113 | mbedtls_crypto 114 | raw_serialize 115 | requester 116 | responder) 117 | 118 | target_include_directories(sample_app PUBLIC ${SAMPLE_INCLUDES}) 119 | 120 | add_library(testing STATIC 121 | testing/library/add_2_app.c 122 | testing/library/dummy_crypto.c 123 | testing/library/host_context.c 124 | testing/library/utils.cc) 125 | 126 | target_link_libraries(testing 127 | common 128 | requester 129 | responder 130 | utils 131 | mbedtls_crypto 132 | raw_serialize) 133 | 134 | target_include_directories(testing PUBLIC ${TEST_INCLUDES}) 135 | 136 | ## Declare tests ## 137 | 138 | set(TESTS 139 | requester_test 140 | spdm_parser_test 141 | sample_app_test 142 | state_waiting_for_get_version_test 143 | state_waiting_for_get_capabilities_test 144 | state_waiting_for_negotiate_algorithms_test 145 | state_waiting_for_key_exchange_test 146 | state_need_requester_key_test 147 | state_waiting_for_finish_test 148 | state_session_established_test 149 | tpmt_public_serialize_test) 150 | 151 | set(TEST_LIBS 152 | testing 153 | common 154 | everparse 155 | requester 156 | responder 157 | mbedtls_crypto 158 | raw_serialize 159 | sample_app 160 | tpmt_public_serialize 161 | GTest::gtest_main) 162 | 163 | enable_testing() 164 | 165 | include(GoogleTest) 166 | 167 | foreach(TEST ${TESTS}) 168 | add_executable(${TEST} testing/${TEST}.cc) 169 | target_include_directories(${TEST} PUBLIC ${TEST_INCLUDES} ${SAMPLE_INCLUDES}) 170 | target_link_libraries(${TEST} ${TEST_LIBS}) 171 | gtest_discover_tests(${TEST}) 172 | endforeach() 173 | -------------------------------------------------------------------------------- /spdm_lite/CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | ## Contributor License Agreement 2 | 3 | Contributions to this project must be accompanied by a Contributor License 4 | Agreement (CLA). You (or your employer) retain the copyright to your 5 | contribution; this simply gives us permission to use and redistribute your 6 | contributions as part of the project. Head over to 7 | to see your current agreements on file or 8 | to sign a new one. 9 | 10 | You generally only need to submit a CLA once, so if you've already submitted one 11 | (even if it was for a different project), you probably don't need to do it 12 | again. 13 | 14 | ## Code Reviews 15 | 16 | All submissions, including submissions by project members, require review. We 17 | use GitHub pull requests for this purpose. Consult 18 | [GitHub Help](https://help.github.com/articles/about-pull-requests/) for more 19 | information on using pull requests. 20 | 21 | ## Community Guidelines 22 | 23 | This project follows 24 | [Google's Open Source Community Guidelines](https://opensource.google/conduct/). 25 | -------------------------------------------------------------------------------- /spdm_lite/README.md: -------------------------------------------------------------------------------- 1 | # SPDM-Lite 2 | 3 | This library implements SPDM 1.2 secure sessions. 4 | 5 | This is not an official Google product. 6 | 7 | ## Build 8 | 9 | ### Install Dependencies 10 | 11 | On Debian and Ubuntu install the following packages: 12 | 13 | ``` 14 | $ sudo apt install libmbedtls-dev libtss2-dev cmake 15 | ``` 16 | 17 | Note that mbedtls and libtss2 are only needed for tests. The core spdm-lite 18 | library does not take a direct dependency on any external libraries. 19 | 20 | ### Build and run tests 21 | 22 | ``` 23 | $ cmake -B build 24 | $ cmake --build build 25 | $ ctest --test-dir build 26 | ``` 27 | 28 | ## User guide 29 | 30 | ### Requesters 31 | 32 | Requesters are expected to call `spdm_establish_session`, and then 33 | `spdm_dispatch_app_request` for each subsequent message sent over the secure 34 | session. Requesters can tear down the session by calling `spdm_end_session`. 35 | 36 | Requesters are expected to initialize and provide an `SpdmDispatchRequestCtx`, 37 | which provides both a function pointer used to dispatch messages to the 38 | Responder, as well as scratch memory used for staging encrypted requests and 39 | responses. The scratch memory should be as large as 40 | `(max request or response size + SPDM_SECURE_MESSAGE_OVERHEAD)` 41 | 42 | See `samples/requester_app.c` which illustrates how this can be done. 43 | 44 | ### Responders 45 | 46 | Responders are expected to call `spdm_dispatch_request` upon receipt of an SPDM 47 | request. The transport binding used by the Responder must indicate whether or 48 | not the given SPDM request is encrypted. 49 | 50 | In addition, Responders are expected to provide a callback function of type 51 | `spdm_app_dispatch_request_fn`, which will be invoked upon receipt of a 52 | vendor-defined command sent within an established secure session. 53 | 54 | This implementation currently only supports one active session at a time. 55 | 56 | See `samples/responder_app.c` which illustrates how this can be done. 57 | 58 | ### Mutual authentication 59 | 60 | This implementation requires mutual authentication. Certificate exchange is out 61 | of scope. As SPDM 1.2 currently does not support a mechanism for exchanging raw 62 | public keys, this implementation provides a pair of custom vendor-defined 63 | commands for this purpose. See `common/vendor_defined_pub_key.h` for the message 64 | structure. 65 | 66 | ### Crypto 67 | 68 | Requesters and Responders are expected to implement an instance of 69 | `SpdmCryptoSpec`. 70 | 71 | These instances contain function pointers for low-level crypto primitives, as 72 | well as serialization and deserialization functions for asymmetric public keys. 73 | 74 | Users should override `SPDM_MAX_SERIALIZED_ASYM_PUB_KEY_SIZE` in 75 | `include/spdm_lite/common/config.h` when providing a public key serialization 76 | routine. 77 | 78 | ### Timing 79 | 80 | This library does not implement timing-related functionality. 81 | 82 | ## Parsers 83 | 84 | This library parses SPDM messages using 85 | [EverParse](https://project-everest.github.io/everparse/). See 86 | `everparse/SPDM.3d` for a description of each message, expressed in EverParse's 87 | [Dependent Data Description language](https://project-everest.github.io/everparse/3d-lang.html). 88 | `everparse/build.sh` will generate the parser functions. 89 | `everparse/SPDMWrapper.{h,c}` contains manually-created wrapper functions to 90 | better integrate with the type system used in spdm-lite. 91 | 92 | ## TODO 93 | 94 | * Endian conversion 95 | * Error codes / debug messages 96 | * Max message size enforcement 97 | * Customizable algorithm negotiation routine 98 | * GET_CERTIFICATE / KEY_UPDATE / HEARTBEAT / CHUNK_SEND etc. 99 | -------------------------------------------------------------------------------- /spdm_lite/everparse/build.sh: -------------------------------------------------------------------------------- 1 | # Copyright 2022 Google LLC. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | #!/bin/bash 16 | 17 | set -e 18 | 19 | # From https://github.com/project-everest/everparse/releases/download/v2022.06.13/everparse_v2022.06.13_Linux_x86_64.tar.gz 20 | EVERPARSE="~/everparse/everparse.sh" 21 | 22 | TEMP_D=`mktemp -d` 23 | 24 | in_file="SPDM.3d" 25 | 26 | # Strip path and extension 27 | filename=`basename -- "${in_file}"` 28 | filename="${filename%.*}" 29 | 30 | dir="`dirname -- "${in_file}"`/../library/everparse" 31 | 32 | eval "${EVERPARSE} --odir ${TEMP_D} ${in_file}" 33 | 34 | mv "${TEMP_D}/${filename}.c" "${dir}/" 35 | mv "${TEMP_D}/${filename}.h" "${dir}/" 36 | 37 | rm -rf "${TEMP_D}" 38 | -------------------------------------------------------------------------------- /spdm_lite/include/spdm_lite/common/algorithms.h: -------------------------------------------------------------------------------- 1 | // Copyright 2022 Google LLC. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #ifndef SPDM_LITE_COMMON_ALGORITHMS_H_ 16 | #define SPDM_LITE_COMMON_ALGORITHMS_H_ 17 | 18 | #include 19 | 20 | #include "spdm_lite/common/crypto_types.h" 21 | #include "spdm_lite/common/messages.h" 22 | #include "spdm_lite/common/utils.h" 23 | 24 | #ifdef __cplusplus 25 | extern "C" { 26 | #endif // __cplusplus 27 | 28 | // Filter out signing algs that our key doesn't support. 29 | void spdm_get_my_supported_algs(const SpdmCryptoSpec* crypto_spec, 30 | const SpdmAsymPubKey* my_pub_key, 31 | SpdmSupportedAlgs* supported_algs); 32 | 33 | int spdm_get_their_supported_algs(const SPDM_AsymHashAlgs* asym_hash_algs, 34 | buffer alg_structs, 35 | uint32_t alg_structs_count, bool is_resp, 36 | SpdmSupportedAlgs* supported_algs, 37 | bool* supports_spdm_key_schedule); 38 | 39 | void spdm_get_negotiated_algs(const SpdmSupportedAlgs* my_algs, 40 | const SpdmSupportedAlgs* their_algs, 41 | SpdmSupportedAlgs* common_algs, 42 | SpdmNegotiatedAlgs* negotiated_algs); 43 | 44 | void spdm_write_algs(const SpdmSupportedAlgs* algs, bool is_resp, 45 | bool support_spdm_key_schedule, 46 | SPDM_AsymHashAlgs* algs_msg, SPDM_AlgStruct_DHE* dhe_msg, 47 | SPDM_AlgStruct_AEAD* aead_msg, 48 | SPDM_AlgStruct_BaseAsym* asym_msg, 49 | SPDM_AlgStruct_KeySchedule* keysched_msg); 50 | 51 | #ifdef __cplusplus 52 | } 53 | #endif // __cplusplus 54 | 55 | #endif // SPDM_LITE_COMMON_ALGORITHMS_H_ 56 | -------------------------------------------------------------------------------- /spdm_lite/include/spdm_lite/common/capabilities.h: -------------------------------------------------------------------------------- 1 | // Copyright 2022 Google LLC. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #ifndef SPDM_LITE_COMMON_CAPABILITIES_H_ 16 | #define SPDM_LITE_COMMON_CAPABILITIES_H_ 17 | 18 | #include 19 | 20 | typedef struct { 21 | // The maximum size of an SPDM payload, whether plaintext or encrypted. 22 | uint32_t data_transfer_size; 23 | } SpdmCapabilities; 24 | 25 | #endif // SPDM_LITE_COMMON_CAPABILITIES_H_ 26 | -------------------------------------------------------------------------------- /spdm_lite/include/spdm_lite/common/config.h: -------------------------------------------------------------------------------- 1 | // Copyright 2022 Google LLC. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #ifndef SPDM_LITE_COMMON_CONFIG_H_ 16 | #define SPDM_LITE_COMMON_CONFIG_H_ 17 | 18 | // This file contains configuration values for SPDM-Lite. They can be overridden 19 | // by defining an `SPDM_CONFIG_FILE`. 20 | 21 | #ifdef SPDM_CONFIG_FILE 22 | #include SPDM_CONFIG_FILE 23 | #endif 24 | 25 | #ifndef SPDM_MAX_HASH_CTX_SIZE 26 | // Enough space for a reasonable implementation to hold a SHA512 hash context. 27 | #define SPDM_MAX_HASH_CTX_SIZE 256 28 | #endif 29 | 30 | #ifndef SPDM_MAX_SERIALIZED_ASYM_PUB_KEY_SIZE 31 | // An (x || y) pair of ECDSA P521 coordinates. 32 | #define SPDM_MAX_SERIALIZED_ASYM_PUB_KEY_SIZE (2 * 66) 33 | #endif 34 | 35 | #endif // SPDM_LITE_COMMON_CONFIG_H_ 36 | -------------------------------------------------------------------------------- /spdm_lite/include/spdm_lite/common/crypto.h: -------------------------------------------------------------------------------- 1 | // Copyright 2022 Google LLC. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #ifndef SPDM_LITE_COMMON_CRYPTO_H_ 16 | #define SPDM_LITE_COMMON_CRYPTO_H_ 17 | 18 | #include 19 | #include 20 | #include 21 | 22 | #include "spdm_lite/common/crypto_types.h" 23 | 24 | #ifdef __cplusplus 25 | extern "C" { 26 | #endif // __cplusplus 27 | 28 | int spdm_get_random(const SpdmCryptoSpec* crypto_spec, uint8_t* data, 29 | uint32_t len); 30 | int spdm_initialize_hash_struct(const SpdmCryptoSpec* crypto_spec, 31 | SpdmHashAlgorithm alg, SpdmHash* hash); 32 | void spdm_initialize_hash(SpdmHash* hash); 33 | void spdm_extend_hash(SpdmHash* hash, const void* data, uint32_t len); 34 | int spdm_get_hash(const SpdmHash* hash, SpdmHashResult* digest); 35 | int spdm_get_hash_destructive(SpdmHash* hash, SpdmHashResult* digest); 36 | int spdm_hash(const SpdmCryptoSpec* crypto_spec, SpdmHashAlgorithm alg, 37 | const uint8_t* data, uint32_t len, SpdmHashResult* digest); 38 | 39 | // Holds a serialized version of a public key. 40 | typedef struct { 41 | SpdmAsymAlgorithm alg; 42 | uint16_t size; 43 | uint8_t data[SPDM_MAX_SERIALIZED_ASYM_PUB_KEY_SIZE]; 44 | } SpdmSerializedAsymPubKey; 45 | 46 | int spdm_serialize_asym_key(const SpdmCryptoSpec* crypto_spec, 47 | const SpdmAsymPubKey* pub_key, 48 | SpdmHashAlgorithm hash_alg, 49 | SpdmSerializedAsymPubKey* out); 50 | int spdm_deserialize_asym_key(const SpdmCryptoSpec* spec, 51 | SpdmAsymAlgorithm asym_alg, 52 | SpdmHashAlgorithm hash_alg, const uint8_t* in, 53 | uint32_t size, SpdmAsymPubKey* pub_key); 54 | int spdm_validate_asym_pubkey(const SpdmCryptoSpec* spec, 55 | const SpdmAsymPubKey* pub_key); 56 | int spdm_validate_dhe_pubkey(const SpdmCryptoSpec* spec, 57 | const SpdmDhePubKey* pub_key); 58 | int spdm_gen_dhe_keypair(const SpdmCryptoSpec* spec, SpdmDheAlgorithm alg, 59 | SpdmDhePrivKey* priv_key, SpdmDhePubKey* pub_key); 60 | int spdm_gen_dhe_secret(const SpdmCryptoSpec* spec, 61 | const SpdmDhePrivKey* priv_key, 62 | const SpdmDhePubKey* pub_key, 63 | SpdmDheSecret* shared_secret); 64 | int spdm_sign_with_private_key(const SpdmCryptoSpec* spec, 65 | SpdmAsymAlgorithm alg, void* ctx, 66 | const SpdmHashResult* input, uint8_t* sig, 67 | uint32_t sig_len); 68 | int spdm_verify_with_pub_key(const SpdmCryptoSpec* spec, 69 | const SpdmAsymPubKey* pub_key, 70 | const SpdmHashResult* input, const uint8_t* sig, 71 | uint32_t sig_len); 72 | int spdm_hmac(const SpdmCryptoSpec* spec, const SpdmHashResult* key, 73 | const SpdmHashResult* data, SpdmHashResult* out); 74 | int spdm_hmac_raw(const SpdmCryptoSpec* spec, const SpdmHashResult* key, 75 | const uint8_t* data, uint16_t data_size, SpdmHashResult* out); 76 | int spdm_validate_hmac(const SpdmCryptoSpec* spec, const SpdmHashResult* key, 77 | const SpdmHashResult* data, const uint8_t* mac); 78 | int spdm_hkdf_expand(const SpdmCryptoSpec* spec, const SpdmHashResult* prk, 79 | const uint8_t* info, uint32_t info_len, 80 | SpdmHashResult* out); 81 | int spdm_hkdf_expand_raw(const SpdmCryptoSpec* spec, SpdmHashAlgorithm alg, 82 | const uint8_t* prk, uint32_t prk_len, 83 | const uint8_t* info, uint32_t info_len, uint8_t* out, 84 | uint32_t out_len); 85 | int spdm_aes_gcm_encrypt(const SpdmCryptoSpec* spec, const SpdmAeadKey* key, 86 | const SpdmAeadIv* iv, const uint8_t* plaintext, 87 | uint32_t plaintext_len, const uint8_t* aad, 88 | uint32_t aad_len, uint8_t* ciphertext, uint8_t* mac, 89 | uint32_t mac_len); 90 | int spdm_aes_gcm_decrypt(const SpdmCryptoSpec* spec, const SpdmAeadKey* key, 91 | const SpdmAeadIv* iv, const uint8_t* ciphertext, 92 | uint32_t ciphertext_len, const uint8_t* aad, 93 | uint32_t aad_len, const uint8_t* mac, uint32_t mac_len, 94 | uint8_t* plaintext); 95 | 96 | int spdm_extend_hash_with_pub_key(const SpdmCryptoSpec* spec, SpdmHash* hash, 97 | const SpdmAsymPubKey* pub_key); 98 | 99 | int constant_memcmp(const uint8_t* a, const uint8_t* b, uint32_t n); 100 | 101 | #ifdef __cplusplus 102 | } 103 | #endif // __cplusplus 104 | 105 | #endif // SPDM_LITE_COMMON_CRYPTO_H_ 106 | -------------------------------------------------------------------------------- /spdm_lite/include/spdm_lite/common/defs.h: -------------------------------------------------------------------------------- 1 | // Copyright 2022 Google LLC. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #ifndef SPDM_LITE_COMMON_DEFS_H_ 16 | #define SPDM_LITE_COMMON_DEFS_H_ 17 | 18 | #ifndef BUILD_ASSERT 19 | #define _BA1_(cond, line) \ 20 | extern int __build_assertion_##line[1 - 2 * !(cond)] __attribute__((unused)) 21 | #define _BA0_(c, x) _BA1_(c, x) 22 | #define BUILD_ASSERT(cond) _BA0_(cond, __LINE__) 23 | #endif 24 | 25 | #ifndef PACKED 26 | #define PACKED __attribute__((__packed__)) 27 | #endif 28 | 29 | // TODO(jeffandersen): Remove when all endian todos are resolved. 30 | BUILD_ASSERT(__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__); 31 | 32 | #endif // SPDM_LITE_COMMON_DEFS_H_ 33 | -------------------------------------------------------------------------------- /spdm_lite/include/spdm_lite/common/error.h: -------------------------------------------------------------------------------- 1 | // Copyright 2022 Google LLC. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #ifndef SPDM_LITE_COMMON_ERROR_H_ 16 | #define SPDM_LITE_COMMON_ERROR_H_ 17 | 18 | #include 19 | 20 | #include "spdm_lite/common/utils.h" 21 | 22 | #ifdef __cplusplus 23 | extern "C" { 24 | #endif // __cplusplus 25 | 26 | // Table 48 27 | enum SpdmErrorCode { 28 | SPDM_ERR_INVALID_REQUEST = 0x01, 29 | SPDM_ERR_BUSY = 0x03, 30 | SPDM_ERR_UNSPECIFIED = 0x05, 31 | SPDM_ERR_VERSION_MISMATCH = 0x41, 32 | SPDM_ERR_SESSION_REQURED = 0x0B, 33 | // TODO(jeffandersen): fill in. 34 | }; 35 | 36 | // Writes an SPDM ERROR message to the given output buffer, with no extended 37 | // error data. 38 | int spdm_write_error(uint8_t code, byte_writer* output); 39 | 40 | #ifdef __cplusplus 41 | } 42 | #endif // __cplusplus 43 | 44 | #endif // SPDM_LITE_COMMON_ERROR_H_ 45 | -------------------------------------------------------------------------------- /spdm_lite/include/spdm_lite/common/key_schedule.h: -------------------------------------------------------------------------------- 1 | // Copyright 2022 Google LLC. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #ifndef SPDM_LITE_COMMON_KEY_SCHEDULE_H_ 16 | #define SPDM_LITE_COMMON_KEY_SCHEDULE_H_ 17 | 18 | #include 19 | 20 | #include "spdm_lite/common/crypto_types.h" 21 | #include "spdm_lite/common/session_types.h" 22 | #include "spdm_lite/common/utils.h" 23 | 24 | #ifdef __cplusplus 25 | extern "C" { 26 | #endif // __cplusplus 27 | 28 | typedef struct { 29 | SpdmHashResult request_direction; 30 | SpdmHashResult response_direction; 31 | } SpdmMessageSecrets; 32 | 33 | typedef struct { 34 | SpdmAeadKeys req_keys; 35 | SpdmAeadKeys rsp_keys; 36 | } SpdmSessionAeadKeys; 37 | 38 | int spdm_generate_message_secrets(const SpdmCryptoSpec* crypto_spec, 39 | const SpdmSessionParams* session, 40 | SpdmSessionPhase phase, 41 | SpdmMessageSecrets* secrets); 42 | 43 | int spdm_generate_finished_key(const SpdmCryptoSpec* crypto_spec, 44 | SPDMRole originator, 45 | const SpdmMessageSecrets* secrets, 46 | SpdmHashResult* key); 47 | 48 | int spdm_generate_aead_keys(const SpdmCryptoSpec* crypto_spec, 49 | SpdmAeadAlgorithm alg, 50 | const SpdmMessageSecrets* secrets, 51 | uint64_t req_seq_num, uint64_t rsp_seq_num, 52 | SpdmSessionAeadKeys* keys); 53 | 54 | #ifdef __cplusplus 55 | } 56 | #endif // __cplusplus 57 | 58 | #endif // SPDM_LITE_COMMON_KEY_SCHEDULE_H_ 59 | -------------------------------------------------------------------------------- /spdm_lite/include/spdm_lite/common/session.h: -------------------------------------------------------------------------------- 1 | // Copyright 2022 Google LLC. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #ifndef SPDM_LITE_COMMON_SESSION_H_ 16 | #define SPDM_LITE_COMMON_SESSION_H_ 17 | 18 | #include 19 | 20 | #include "spdm_lite/common/crypto_types.h" 21 | #include "spdm_lite/common/session_types.h" 22 | #include "spdm_lite/common/utils.h" 23 | 24 | #ifdef __cplusplus 25 | extern "C" { 26 | #endif // __cplusplus 27 | 28 | int spdm_generate_session_params(const SpdmCryptoSpec* spec, 29 | SpdmDheAlgorithm alg, 30 | SpdmSelfKeyExchangeParams* my_params); 31 | 32 | void spdm_generate_session_id(SPDMRole my_role, const uint8_t my_part[2], 33 | const uint8_t their_part[2], 34 | SpdmSessionId* session_id); 35 | 36 | // `header` must contain sizeof(SPDM_SecuredMessageRecord) bytes and precede 37 | // `input`, which must precede `footer`. 38 | int spdm_encrypt_secure_message(const SpdmCryptoSpec* spec, 39 | const SpdmSessionId* session_id, 40 | uint64_t seq_num, const SpdmAeadKeys* keys, 41 | uint8_t* header, buffer input, 42 | byte_writer* footer); 43 | 44 | // `message` is updated to point to the decrypted-in-place plaintext message. 45 | int spdm_decrypt_secure_message(const SpdmCryptoSpec* spec, 46 | const SpdmSessionId* session_id, 47 | uint64_t seq_num, const SpdmAeadKeys* keys, 48 | buffer* message); 49 | 50 | #ifdef __cplusplus 51 | } 52 | #endif // __cplusplus 53 | 54 | #endif // SPDM_LITE_COMMON_SESSION_H_ 55 | -------------------------------------------------------------------------------- /spdm_lite/include/spdm_lite/common/session_types.h: -------------------------------------------------------------------------------- 1 | // Copyright 2022 Google LLC. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #ifndef SPDM_LITE_COMMON_SESSION_TYPES_H_ 16 | #define SPDM_LITE_COMMON_SESSION_TYPES_H_ 17 | 18 | #include 19 | 20 | #include "spdm_lite/common/crypto_types.h" 21 | #include "spdm_lite/common/messages.h" 22 | 23 | #ifdef __cplusplus 24 | extern "C" { 25 | #endif // __cplusplus 26 | 27 | typedef struct { 28 | uint8_t my_session_id_part[2]; 29 | SpdmDhePrivKey my_priv_key; 30 | SpdmDhePubKey my_pub_key; 31 | } SpdmSelfKeyExchangeParams; 32 | 33 | typedef struct { 34 | uint8_t id[4]; 35 | } SpdmSessionId; 36 | 37 | typedef struct { 38 | SpdmSessionId session_id; 39 | SpdmNegotiatedAlgs negotiated_algs; 40 | SpdmAsymPubKey peer_pub_key; 41 | } SpdmSessionInfo; 42 | 43 | typedef struct { 44 | SpdmSessionInfo info; 45 | SpdmDheSecret shared_key; 46 | SpdmHashResult th_1; 47 | SpdmHashResult th_2; 48 | uint64_t req_seq_num; 49 | uint64_t rsp_seq_num; 50 | } SpdmSessionParams; 51 | 52 | typedef enum { 53 | SPDM_NO_SESSION = 0, 54 | SPDM_HANDSHAKE_PHASE, 55 | SPDM_DATA_PHASE, 56 | } SpdmSessionPhase; 57 | 58 | #define SPDM_MAX_SECURE_MESSAGE_RAND_LEN 16 59 | #define SPDM_MAX_SECURE_MESSAGE_FOOTER_LEN \ 60 | (SPDM_MAX_SECURE_MESSAGE_RAND_LEN + AES_GCM_MAC_SIZE) 61 | #define SPDM_SECURE_MESSAGE_OVERHEAD \ 62 | (sizeof(SPDM_SecuredMessageRecord) + SPDM_MAX_SECURE_MESSAGE_FOOTER_LEN) 63 | 64 | #ifdef __cplusplus 65 | } 66 | #endif // __cplusplus 67 | 68 | #endif // SPDM_LITE_COMMON_SESSION_TYPES_H_ 69 | -------------------------------------------------------------------------------- /spdm_lite/include/spdm_lite/common/sign.h: -------------------------------------------------------------------------------- 1 | // Copyright 2022 Google LLC. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #ifndef SPDM_LITE_COMMON_SIGN_H_ 16 | #define SPDM_LITE_COMMON_SIGN_H_ 17 | 18 | #include 19 | 20 | #include "spdm_lite/common/crypto_types.h" 21 | #include "spdm_lite/common/utils.h" 22 | 23 | #ifdef __cplusplus 24 | extern "C" { 25 | #endif // __cplusplus 26 | 27 | int spdm_sign(const SpdmCryptoSpec* crypto_spec, SpdmAsymAlgorithm alg, 28 | void* priv_key_ctx, SPDMRole my_role, 29 | const SpdmHashResult* message_hash, const char* context, 30 | uint8_t* out, uint32_t out_len); 31 | 32 | int spdm_verify(const SpdmCryptoSpec* crypto_spec, 33 | const SpdmAsymPubKey* pub_key, SPDMRole signer_role, 34 | const SpdmHashResult* message_hash, const char* context, 35 | const uint8_t* sig, uint32_t sig_len); 36 | 37 | #ifdef __cplusplus 38 | } 39 | #endif // __cplusplus 40 | 41 | #endif // SPDM_LITE_COMMON_SIGN_H_ 42 | -------------------------------------------------------------------------------- /spdm_lite/include/spdm_lite/common/transcript.h: -------------------------------------------------------------------------------- 1 | // Copyright 2022 Google LLC. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #ifndef SPDM_LITE_COMMON_TRANSCRIPT_H_ 16 | #define SPDM_LITE_COMMON_TRANSCRIPT_H_ 17 | 18 | #include 19 | 20 | #include "spdm_lite/common/crypto_types.h" 21 | #include "spdm_lite/common/messages.h" 22 | 23 | #define SPDM_MAX_VERSION_NUMBER_ENTRIES 16 24 | 25 | // A request/response without extended algorithms doesn't exceed 52 bytes. 26 | #define SPDM_MAX_ALG_MSG_SIZE 80 27 | 28 | #define SPDM_VERSION_CAPABILITIES_TRANSCRIPT_SIZE \ 29 | (sizeof(SPDM_GET_VERSION) + sizeof(SPDM_VERSION) + \ 30 | (SPDM_MAX_VERSION_NUMBER_ENTRIES * sizeof(SPDM_VersionNumberEntry)) + \ 31 | sizeof(SPDM_GET_CAPABILITIES) + sizeof(SPDM_CAPABILITIES) + \ 32 | SPDM_MAX_ALG_MSG_SIZE + SPDM_MAX_ALG_MSG_SIZE) 33 | 34 | typedef struct { 35 | uint32_t size; 36 | uint8_t data[SPDM_VERSION_CAPABILITIES_TRANSCRIPT_SIZE]; 37 | } SpdmNegotiationTranscript; 38 | 39 | int spdm_append_to_transcript(SpdmNegotiationTranscript* transcript, 40 | const void* data, uint32_t size); 41 | 42 | int spdm_initialize_transcript_hash( 43 | const SpdmCryptoSpec* crypto_spec, SpdmHashAlgorithm alg, 44 | const SpdmNegotiationTranscript* transcript, 45 | SpdmHash* transcript_hash); 46 | 47 | #endif // SPDM_LITE_COMMON_TRANSCRIPT_H_ 48 | -------------------------------------------------------------------------------- /spdm_lite/include/spdm_lite/common/utils.h: -------------------------------------------------------------------------------- 1 | // Copyright 2022 Google LLC. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #ifndef SPDM_LITE_COMMON_UTILS_H_ 16 | #define SPDM_LITE_COMMON_UTILS_H_ 17 | 18 | #include 19 | #include 20 | 21 | #ifdef __cplusplus 22 | extern "C" { 23 | #endif // __cplusplus 24 | 25 | #ifndef MAX 26 | #define MAX(a, b) ((a) > (b) ? (a) : (b)) 27 | #endif 28 | 29 | typedef enum { 30 | SPDM_REQUESTER, 31 | SPDM_RESPONDER, 32 | } SPDMRole; 33 | 34 | typedef struct { 35 | const uint8_t* data; 36 | uint32_t size; 37 | } buffer; 38 | 39 | // This structure holds the details of a "byte writer", an object used to write 40 | // bytes to a fixed size buffer. 41 | typedef struct { 42 | uint8_t* data; 43 | uint32_t size; 44 | uint32_t bytes_written; 45 | } byte_writer; 46 | 47 | // Copy `len` bytes from `buf` into `out`, reducing its size by `len`. Both 48 | // `buf` and `out` must have `len` bytes available. 49 | void consume_from_buffer(buffer* buf, void* out, uint32_t len); 50 | 51 | // Initializes `writer` to point to a given buffer of data. 52 | void init_writer(byte_writer* writer, void* data, size_t size); 53 | void buffer_to_writer(buffer buf, byte_writer* writer); 54 | 55 | // Reserves `size` bytes for writing. Returns a pointer to the reserved bytes, 56 | // or NULL if there was insufficient room in `writer`. 57 | uint8_t* reserve_from_writer(byte_writer* writer, size_t size); 58 | 59 | // Writes `size` bytes from `data` to the next bytes in `writer`. Returns 0 on 60 | // success, or an error code if there are not `size` bytes available in the 61 | // buffer for writing. 62 | int write_to_writer(byte_writer* writer, const void* data, size_t size); 63 | 64 | #ifdef __cplusplus 65 | } 66 | #endif // __cplusplus 67 | 68 | #endif // SPDM_LITE_COMMON_UTILS_H_ 69 | -------------------------------------------------------------------------------- /spdm_lite/include/spdm_lite/common/vendor_defined_pub_key.h: -------------------------------------------------------------------------------- 1 | // Copyright 2022 Google LLC. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #ifndef SPDM_LITE_COMMON_VENDOR_DEFINED_PUB_KEY_H_ 16 | #define SPDM_LITE_COMMON_VENDOR_DEFINED_PUB_KEY_H_ 17 | 18 | // This header defines VENDOR_DEFINED_REQUEST/RESPONSE messages for exchanging 19 | // public keys, rather than full certificates. 20 | // 21 | // GET_PUB_KEY must only be sent after the VCA handshake. GIVE_PUB_KEY must be 22 | // sent after KEY_EXCHANGE and before FINISH. 23 | // 24 | // Note: these vendor-defined commands have not been endorsed by DMTF or any 25 | // other standards body. 26 | // 27 | // The GET_PUB_KEY request message has the following field values: 28 | // 29 | // * StandardID = 0 (DMTF) 30 | // * Len = 0 31 | // * ReqLength = 5 32 | // * VendorDefinedReqPayload[0] = 1 33 | // * VendorDefinedReqPayload[1..8] = "GET_PUBK" 34 | // 35 | // The GET_PUB_KEY response message has the following field values: 36 | // 37 | // * StandardID = 0 (DMTF) 38 | // * Len = 0 39 | // * ReqLength = 5 + D 40 | // * VendorDefinedReqPayload[0] = 1 41 | // * VendorDefinedReqPayload[1..8] = "GET_PUBK" 42 | // * VendorDefinedReqPayload[9..] = public key of length D, as selected during 43 | // algorithm negotiation. 44 | // 45 | // The GIVE_PUB_KEY request message has the following field values: 46 | // 47 | // * StandardID = 0 (DMTF) 48 | // * Len = 0 49 | // * ReqLength = 5 + D 50 | // * VendorDefinedReqPayload[0] = 1 51 | // * VendorDefinedReqPayload[1..8] = "GIVE_PUB" 52 | // * VendorDefinedReqPayload[9..] = public key of length D, as selected during 53 | // algorithm negotiation. 54 | // 55 | // The GIVE_PUB_KEY response message has the following field values: 56 | // 57 | // * StandardID = 0 (DMTF) 58 | // * Len = 0 59 | // * ReqLength = 5 60 | // * VendorDefinedReqPayload[0] = 1 61 | // * VendorDefinedReqPayload[1..8] = "GIVE_PUB" 62 | 63 | #include 64 | 65 | #include "spdm_lite/common/crypto_types.h" 66 | #include "spdm_lite/common/utils.h" 67 | 68 | #define DMTF_STANDARD_ID 0 69 | #define DMTF_VD_ID 1 70 | #define DMTF_VD_GET_PUBKEY_CODE 0x4B4255505F544547 // "GET_PUBK" 71 | #define DMTF_VD_GIVE_PUBKEY_CODE 0x4255505F45564947 // "GIVE_PUB" 72 | 73 | // Either a GET_PUB_KEY request or a GIVE_PUB_KEY response. 74 | typedef struct { 75 | uint8_t vd_id; // DMTF_VD_ID 76 | uint64_t vd_req_rsp; // DMTF_VD_[GET/GIVE]_PUBKEY_CODE 77 | } SPDM_VendorDefinedPubKeyEmptyMsg; 78 | 79 | // Either a GET_PUB_KEY response or a GIVE_PUB_KEY request. 80 | typedef struct { 81 | uint8_t vd_id; // DMTF_VD_ID 82 | uint64_t vd_req_rsp; // DMTF_VD_[GET/GIVE]_PUBKEY_CODE 83 | // uint8_t vd_pubkey[D]; 84 | } SPDM_VendorDefinedPubKeyMsg; 85 | 86 | int spdm_write_get_pub_key_req(byte_writer* output); 87 | int spdm_check_get_pub_key_req(buffer input); 88 | 89 | int spdm_write_get_pub_key_rsp(const SpdmCryptoSpec* crypto_spec, 90 | const SpdmAsymPubKey* pub_key, 91 | SpdmHashAlgorithm hash_alg, byte_writer* output); 92 | int spdm_check_get_pub_key_rsp(const SpdmCryptoSpec* crypto_spec, buffer input, 93 | SpdmAsymAlgorithm asym_alg, 94 | SpdmHashAlgorithm hash_alg, 95 | SpdmAsymPubKey* pub_key); 96 | 97 | int spdm_write_give_pub_key_req(const SpdmCryptoSpec* crypto_spec, 98 | const SpdmAsymPubKey* pub_key, 99 | SpdmHashAlgorithm hash_alg, 100 | byte_writer* output); 101 | int spdm_check_give_pub_key_req(const SpdmCryptoSpec* crypto_spec, buffer input, 102 | SpdmAsymAlgorithm asym_alg, 103 | SpdmHashAlgorithm hash_alg, 104 | SpdmAsymPubKey* pub_key); 105 | 106 | int spdm_write_give_pub_key_rsp(byte_writer* output); 107 | int spdm_check_give_pub_key_rsp(buffer input); 108 | 109 | #endif // SPDM_LITE_COMMON_VENDOR_DEFINED_PUB_KEY_H_ 110 | -------------------------------------------------------------------------------- /spdm_lite/include/spdm_lite/common/version.h: -------------------------------------------------------------------------------- 1 | // Copyright 2022 Google LLC. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #ifndef SPDM_LITE_COMMON_VERSION_H_ 16 | #define SPDM_LITE_COMMON_VERSION_H_ 17 | 18 | #ifdef __cplusplus 19 | extern "C" { 20 | #endif // __cplusplus 21 | 22 | // This implementation only supports SPDM 1.2. 23 | #define SPDM_THIS_VER 0x12 24 | 25 | #ifdef __cplusplus 26 | } 27 | #endif // __cplusplus 28 | 29 | #endif // SPDM_LITE_COMMON_VERSION_H_ 30 | -------------------------------------------------------------------------------- /spdm_lite/include/spdm_lite/crypto_impl/mbedtls_crypto.h: -------------------------------------------------------------------------------- 1 | // Copyright 2022 Google LLC. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #ifndef SPDM_LITE_CRYPTO_IMPL_MBEDTLS_CRYPTO_H_ 16 | #define SPDM_LITE_CRYPTO_IMPL_MBEDTLS_CRYPTO_H_ 17 | 18 | #include "spdm_lite/common/crypto_types.h" 19 | 20 | #ifdef __cplusplus 21 | extern "C" { 22 | #endif // __cplusplus 23 | 24 | // Provides base functionality for low-level crypto primitives used by 25 | // spdm-lite. Does not provide asymmetric signing or public key serialization. 26 | // See `mbedtls_sign.h` and `raw_serialize.h` for that functionality. Users may 27 | // bring their own as well. 28 | extern const SpdmCryptoSpec MBEDTLS_BASE_CRYPTO_SPEC; 29 | 30 | #ifdef __cplusplus 31 | } 32 | #endif // __cplusplus 33 | 34 | #endif // SPDM_LITE_CRYPTO_IMPL_MBEDTLS_CRYPTO_H_ 35 | -------------------------------------------------------------------------------- /spdm_lite/include/spdm_lite/crypto_impl/mbedtls_sign.h: -------------------------------------------------------------------------------- 1 | // Copyright 2022 Google LLC. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #ifndef SPDM_LITE_CRYPTO_IMPL_MBEDTLS_SIGN_H_ 16 | #define SPDM_LITE_CRYPTO_IMPL_MBEDTLS_SIGN_H_ 17 | 18 | #include "spdm_lite/common/crypto_types.h" 19 | 20 | #ifdef __cplusplus 21 | extern "C" { 22 | #endif // __cplusplus 23 | 24 | // Flexible container for holding private keys. 25 | typedef struct { 26 | SpdmAsymAlgorithm alg; 27 | union { 28 | uint8_t ecdsa_p256[P256_COORD_SIZE]; 29 | uint8_t ecdsa_p384[P384_COORD_SIZE]; 30 | uint8_t ecdsa_p521[P521_COORD_SIZE]; 31 | uint8_t data[1]; 32 | }; 33 | } SpdmAsymPrivKey; 34 | 35 | // Generates a random keypair. 36 | int spdm_generate_asym_keypair(SpdmAsymAlgorithm alg, SpdmAsymPrivKey* priv_key, 37 | SpdmAsymPubKey* pub_key); 38 | 39 | // Expects `ctx` to be an instance of SpdmAsymPrivKey. 40 | int spdm_mbedtls_sign_with_priv_key(SpdmAsymAlgorithm alg, void* ctx, 41 | const uint8_t* input, uint32_t input_len, 42 | uint8_t* sig, uint32_t sig_len); 43 | 44 | #ifdef __cplusplus 45 | } 46 | #endif // __cplusplus 47 | 48 | #endif // SPDM_LITE_CRYPTO_IMPL_MBEDTLS_SIGN_H_ 49 | -------------------------------------------------------------------------------- /spdm_lite/include/spdm_lite/crypto_impl/raw_serialize.h: -------------------------------------------------------------------------------- 1 | // Copyright 2022 Google LLC. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #ifndef SPDM_LITE_CRYPTO_IMPL_RAW_SERIALIZE_H_ 16 | #define SPDM_LITE_CRYPTO_IMPL_RAW_SERIALIZE_H_ 17 | 18 | #include 19 | 20 | #include "spdm_lite/common/crypto_types.h" 21 | 22 | // This function is both a serialization and deserialization handler. It copies 23 | // `in` to `out`, and ignores `asym_alg` and `hash_alg`. 24 | int spdm_raw_serialize_asym_key(SpdmAsymAlgorithm asym_alg, 25 | SpdmHashAlgorithm hash_alg, const uint8_t* in, 26 | uint16_t in_size, uint8_t* out, 27 | uint16_t* out_size); 28 | 29 | #endif // SPDM_LITE_CRYPTO_IMPL_RAW_SERIALIZE_H_ 30 | -------------------------------------------------------------------------------- /spdm_lite/include/spdm_lite/crypto_impl/tpmt_public_serialize.h: -------------------------------------------------------------------------------- 1 | // Copyright 2022 Google LLC. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #ifndef SPDM_LITE_CRYPTO_IMPL_TPMT_PUBLIC_SERIALIZE_H_ 16 | #define SPDM_LITE_CRYPTO_IMPL_TPMT_PUBLIC_SERIALIZE_H_ 17 | 18 | #include "spdm_lite/common/crypto_types.h" 19 | 20 | #ifdef __cplusplus 21 | extern "C" { 22 | #endif // __cplusplus 23 | 24 | // Handlers for serializing and deserializing an SPDM-Lite public key as a 25 | // marshalled TPMT_PUBLIC. 26 | 27 | // `in` is expected to be a raw byte buffer holding an SPDM-Lite internal 28 | // representation of a public key, adhering to `asym_alg` and `hash_alg`. `out` 29 | // will hold a marshalled TPMT_PUBLIC. `*out_size` should be at least 30 | // sizeof(TPMT_PUBLIC), as that is the upper limit on the size of a marshalled 31 | // instance. 32 | int spdm_serialize_asym_pub_to_tpmt_public(SpdmAsymAlgorithm asym_alg, 33 | SpdmHashAlgorithm hash_alg, 34 | const uint8_t* in, uint16_t in_size, 35 | uint8_t* out, uint16_t* out_size); 36 | 37 | // `in` is expected to be a marshalled TPMT_PUBLIC. `out` is expected to point 38 | // to a raw byte buffer for an SPDM-Lite internal representation of a public 39 | // key, adhering to `asym_alg` and `hash_alg`. 40 | int spdm_deserialize_asym_pub_from_tpmt_public(SpdmAsymAlgorithm asym_alg, 41 | SpdmHashAlgorithm hash_alg, 42 | const uint8_t* in, 43 | uint16_t in_size, uint8_t* out, 44 | uint16_t* out_size); 45 | 46 | #ifdef __cplusplus 47 | } 48 | #endif // __cplusplus 49 | 50 | #endif // SPDM_LITE_CRYPTO_IMPL_TPMT_PUBLIC_SERIALIZE_H_ 51 | -------------------------------------------------------------------------------- /spdm_lite/include/spdm_lite/requester/requester.h: -------------------------------------------------------------------------------- 1 | // Copyright 2022 Google LLC. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #ifndef SPDM_LITE_REQUESTER_REQUESTER_H_ 16 | #define SPDM_LITE_REQUESTER_REQUESTER_H_ 17 | 18 | #include 19 | #include 20 | 21 | #include "spdm_lite/common/capabilities.h" 22 | #include "spdm_lite/common/crypto_types.h" 23 | #include "spdm_lite/common/session_types.h" 24 | 25 | #ifdef __cplusplus 26 | extern "C" { 27 | #endif // __cplusplus 28 | 29 | typedef int (*spdm_dispatch_request_fn)(void* ctx, bool is_secure_msg, 30 | const uint8_t* req, size_t req_size, 31 | uint8_t* rsp, size_t* rsp_size); 32 | 33 | // Holds function pointers needed to perform crypto operations and communicate 34 | // with the Responder. 35 | typedef struct { 36 | SpdmCryptoSpec crypto_spec; 37 | spdm_dispatch_request_fn dispatch_fn; 38 | void* dispatch_ctx; // Passed to `dispatch_fn`. 39 | } SpdmDispatchRequestCtx; 40 | 41 | // Used to stage encrypted requests and responses. Should be at least as large 42 | // as `(max request or response size + SPDM_SECURE_MESSAGE_OVERHEAD)`. 43 | typedef struct { 44 | uint8_t* data; 45 | size_t size; 46 | } SpdmScratchSpace; 47 | 48 | typedef struct { 49 | const SpdmDispatchRequestCtx* dispatch_ctx; 50 | SpdmScratchSpace scratch; 51 | SpdmCapabilities requester_caps; 52 | SpdmAsymPubKey requester_pub_key; 53 | void* requester_priv_key_ctx; 54 | } SpdmRequesterSessionParams; 55 | 56 | int spdm_establish_session(const SpdmRequesterSessionParams* requester_params, 57 | SpdmSessionParams* session); 58 | 59 | int spdm_dispatch_app_request(const SpdmDispatchRequestCtx* dispatch_ctx, 60 | SpdmScratchSpace scratch_space, 61 | SpdmSessionParams* session, uint16_t standard_id, 62 | const uint8_t* vendor_id, size_t vendor_id_size, 63 | const void* req, size_t req_size, void* rsp, 64 | size_t* rsp_size); 65 | 66 | // Will zero out `session` on success. 67 | int spdm_end_session(const SpdmDispatchRequestCtx* dispatch_ctx, 68 | SpdmScratchSpace scratch_space, 69 | SpdmSessionParams* session); 70 | 71 | #ifdef __cplusplus 72 | } 73 | #endif // __cplusplus 74 | 75 | #endif // SPDM_LITE_REQUESTER_REQUESTER_H_ 76 | -------------------------------------------------------------------------------- /spdm_lite/include/spdm_lite/responder/responder.h: -------------------------------------------------------------------------------- 1 | // Copyright 2022 Google LLC. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #ifndef SPDM_LITE_RESPONDER_RESPONDER_H_ 16 | #define SPDM_LITE_RESPONDER_RESPONDER_H_ 17 | 18 | #include 19 | 20 | #include "spdm_lite/common/capabilities.h" 21 | #include "spdm_lite/common/crypto_types.h" 22 | #include "spdm_lite/common/session_types.h" 23 | #include "spdm_lite/common/transcript.h" 24 | 25 | #ifdef __cplusplus 26 | extern "C" { 27 | #endif // __cplusplus 28 | 29 | /* 30 | .-----------. .-----------. 31 | | Requester | | Responder | [Responder state] 32 | .-----------. .-----------. 33 | | | WAITING_FOR_GET_VERSION 34 | |--------------GET_VERSION-------------->| 35 | |<-----------------VERSION---------------| 36 | | | WAITING_FOR_GET_CAPABILITIES 37 | |-----------GET_CAPABILITIES------------>| 38 | |<--------------CAPABILITIES-------------| 39 | | | WAITING_FOR_NEGOTIATE_ALGORITHMS 40 | |----------NEGOTIATE_ALGORITHMS--------->| 41 | |<-------------------ALGORITHMS----------| 42 | | | WAITING_FOR_KEY_EXCHANGE 43 | |-------------GET_PUB_KEY--------------->| 44 | |<------------GET_PUB_KEY_RSP------------| 45 | | | 46 | |------------KEY_EXCHANGE--------------->| 47 | |<-----------KEY_EXCHANGE_RSP------------| 48 | | | MUTUAL_AUTH_NEED_REQUESTER_KEY 49 | |-------------GIVE_PUB_KEY-------------->| 50 | |<------------GIVE_PUB_KEY_RSP-----------| 51 | | | MUTUAL_AUTH_WAITING_FOR_FINISH 52 | |----------------FINISH----------------->| 53 | |<---------------FINISH_RSP--------------| 54 | | | SESSION_ESTABLISHED 55 | */ 56 | 57 | typedef enum { 58 | STATE_WAITING_FOR_GET_VERSION = 0, 59 | STATE_WAITING_FOR_GET_CAPABILITIES, 60 | STATE_WAITING_FOR_NEGOTIATE_ALGORITHMS, 61 | STATE_WAITING_FOR_KEY_EXCHANGE, 62 | STATE_MUTUAL_AUTH_NEED_REQUESTER_KEY, 63 | STATE_MUTUAL_AUTH_WAITING_FOR_FINISH, 64 | STATE_SESSION_ESTABLISHED, 65 | } SpdmResponderState; 66 | 67 | typedef int (*spdm_app_dispatch_request_fn)( 68 | const SpdmSessionInfo* session_info, uint16_t standard_id, 69 | const uint8_t* vendor_id, size_t vendor_id_size, const uint8_t* payload, 70 | size_t payload_size, uint8_t* output, size_t* output_size); 71 | 72 | typedef struct { 73 | SpdmSessionParams params; 74 | SpdmHash transcript_hash; 75 | } SpdmResponderSession; 76 | 77 | typedef struct { 78 | // Populated at initialization 79 | SpdmResponderState state; 80 | SpdmCryptoSpec crypto_spec; 81 | SpdmCapabilities responder_caps; 82 | SpdmAsymPubKey responder_pub_key; 83 | void* responder_priv_key_ctx; 84 | spdm_app_dispatch_request_fn app_dispatch_fn; 85 | 86 | SpdmNegotiationTranscript negotiation_transcript; 87 | 88 | // Populated from `GET_CAPABILITIES` 89 | SpdmCapabilities requester_caps; 90 | 91 | // Populated from `NEGOTIATE_ALGORITHMS` 92 | SpdmNegotiatedAlgs negotiated_algs; 93 | 94 | // Populated from `KEY_EXCHANGE` 95 | SpdmResponderSession session; 96 | } SpdmResponderContext; 97 | 98 | int spdm_initialize_responder_context( 99 | SpdmResponderContext* ctx, const SpdmCryptoSpec* crypto_spec, 100 | const SpdmCapabilities* responder_caps, 101 | const SpdmAsymPubKey* responder_pub_key, void* responder_priv_key_ctx, 102 | spdm_app_dispatch_request_fn app_dispatch_fn); 103 | 104 | // Top-level request dispatcher. Ensures the version matches before invoking one 105 | // of the state-specific handlers. `is_secure` indicates whether the incoming 106 | // command is an encrypted SPDM request. 107 | int spdm_dispatch_request(SpdmResponderContext* ctx, bool is_secure, 108 | const uint8_t* req, size_t req_size, uint8_t* rsp, 109 | size_t* rsp_size); 110 | 111 | #ifdef __cplusplus 112 | } 113 | #endif // __cplusplus 114 | 115 | #endif // SPDM_LITE_RESPONDER_RESPONDER_H_ 116 | -------------------------------------------------------------------------------- /spdm_lite/library/common/crypto_types.c: -------------------------------------------------------------------------------- 1 | // Copyright 2022 Google LLC. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #include "spdm_lite/common/crypto_types.h" 16 | 17 | #include 18 | 19 | static uint16_t spdm_get_asym_pub_key_size(SpdmAsymAlgorithm alg) { 20 | switch (alg) { 21 | case SPDM_ASYM_ECDSA_ECC_NIST_P256: 22 | return P256_SERIALIZED_POINT_SIZE; 23 | case SPDM_ASYM_ECDSA_ECC_NIST_P384: 24 | return P384_SERIALIZED_POINT_SIZE; 25 | case SPDM_ASYM_ECDSA_ECC_NIST_P521: 26 | return P521_SERIALIZED_POINT_SIZE; 27 | case SPDM_ASYM_UNSUPPORTED: 28 | default: 29 | return 0; 30 | } 31 | } 32 | 33 | void spdm_init_asym_pub_key(SpdmAsymPubKey* key, SpdmAsymAlgorithm alg) { 34 | key->alg = alg; 35 | key->size = spdm_get_asym_pub_key_size(alg); 36 | } 37 | 38 | void spdm_init_hash_result(SpdmHashResult* hash, SpdmHashAlgorithm alg) { 39 | hash->alg = alg; 40 | hash->size = spdm_get_hash_size(alg); 41 | } 42 | 43 | void spdm_init_dhe_pub_key(SpdmDhePubKey* key, SpdmDheAlgorithm alg) { 44 | key->alg = alg; 45 | key->size = spdm_get_dhe_pub_key_size(alg); 46 | } 47 | 48 | void spdm_init_dhe_priv_key(SpdmDhePrivKey* key, SpdmDheAlgorithm alg) { 49 | key->alg = alg; 50 | key->size = spdm_get_dhe_priv_key_size(alg); 51 | } 52 | 53 | void spdm_init_dhe_secret(SpdmDheSecret* secret, SpdmDheAlgorithm alg) { 54 | secret->alg = alg; 55 | secret->size = spdm_get_dhe_secret_size(alg); 56 | } 57 | 58 | void spdm_init_aead_key(SpdmAeadKey* key, SpdmAeadAlgorithm alg) { 59 | key->alg = alg; 60 | key->size = spdm_get_aead_key_size(alg); 61 | } 62 | 63 | void spdm_init_aead_iv(SpdmAeadIv* iv, SpdmAeadAlgorithm alg) { 64 | iv->alg = alg; 65 | iv->size = spdm_get_aead_iv_size(alg); 66 | } 67 | 68 | uint16_t spdm_get_asym_signature_size(SpdmAsymAlgorithm alg) { 69 | switch (alg) { 70 | case SPDM_ASYM_ECDSA_ECC_NIST_P256: 71 | return P256_SERIALIZED_POINT_SIZE; 72 | case SPDM_ASYM_ECDSA_ECC_NIST_P384: 73 | return P384_SERIALIZED_POINT_SIZE; 74 | case SPDM_ASYM_ECDSA_ECC_NIST_P521: 75 | return P521_SERIALIZED_POINT_SIZE; 76 | case SPDM_ASYM_UNSUPPORTED: 77 | default: 78 | return 0; 79 | } 80 | } 81 | 82 | uint16_t spdm_get_hash_size(SpdmHashAlgorithm alg) { 83 | switch (alg) { 84 | case SPDM_HASH_SHA256: 85 | return SHA256_DIGEST_SIZE; 86 | case SPDM_HASH_SHA384: 87 | return SHA384_DIGEST_SIZE; 88 | case SPDM_HASH_SHA512: 89 | return SHA512_DIGEST_SIZE; 90 | case SPDM_HASH_UNSUPPORTED: 91 | default: 92 | return 0; 93 | } 94 | } 95 | 96 | uint16_t spdm_get_dhe_pub_key_size(SpdmDheAlgorithm alg) { 97 | switch (alg) { 98 | case SPDM_DHE_SECP256R1: 99 | return P256_SERIALIZED_POINT_SIZE; 100 | case SPDM_DHE_SECP384R1: 101 | return P384_SERIALIZED_POINT_SIZE; 102 | case SPDM_DHE_SECP521R1: 103 | return P521_SERIALIZED_POINT_SIZE; 104 | case SPDM_DHE_UNSUPPORTED: 105 | default: 106 | return 0; 107 | } 108 | } 109 | 110 | uint16_t spdm_get_dhe_priv_key_size(SpdmDheAlgorithm alg) { 111 | switch (alg) { 112 | case SPDM_DHE_SECP256R1: 113 | return P256_COORD_SIZE; 114 | case SPDM_DHE_SECP384R1: 115 | return P384_COORD_SIZE; 116 | case SPDM_DHE_SECP521R1: 117 | return P521_COORD_SIZE; 118 | case SPDM_DHE_UNSUPPORTED: 119 | default: 120 | return 0; 121 | } 122 | } 123 | 124 | uint16_t spdm_get_dhe_secret_size(SpdmDheAlgorithm alg) { 125 | switch (alg) { 126 | case SPDM_DHE_SECP256R1: 127 | return P256_COORD_SIZE; 128 | case SPDM_DHE_SECP384R1: 129 | return P384_COORD_SIZE; 130 | case SPDM_DHE_SECP521R1: 131 | return P521_COORD_SIZE; 132 | case SPDM_DHE_UNSUPPORTED: 133 | default: 134 | return 0; 135 | } 136 | } 137 | 138 | uint16_t spdm_get_aead_key_size(SpdmAeadAlgorithm alg) { 139 | switch (alg) { 140 | case SPDM_AEAD_AES_128_GCM: 141 | return AES_GCM_128_KEY_SIZE; 142 | case SPDM_AEAD_AES_256_GCM: 143 | return AES_GCM_256_KEY_SIZE; 144 | case SPDM_AEAD_UNSUPPORTED: 145 | default: 146 | return 0; 147 | } 148 | } 149 | 150 | uint16_t spdm_get_aead_iv_size(SpdmAeadAlgorithm alg) { 151 | switch (alg) { 152 | case SPDM_AEAD_AES_128_GCM: 153 | return AES_GCM_128_IV_SIZE; 154 | case SPDM_AEAD_AES_256_GCM: 155 | return AES_GCM_256_IV_SIZE; 156 | case SPDM_AEAD_UNSUPPORTED: 157 | default: 158 | return 0; 159 | } 160 | } 161 | -------------------------------------------------------------------------------- /spdm_lite/library/common/error.c: -------------------------------------------------------------------------------- 1 | // Copyright 2022 Google LLC. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #include "spdm_lite/common/error.h" 16 | 17 | #include "spdm_lite/common/messages.h" 18 | #include "spdm_lite/common/utils.h" 19 | #include "spdm_lite/common/version.h" 20 | 21 | int spdm_write_error(uint8_t code, byte_writer* output) { 22 | SDPM_ERROR err_msg = {}; 23 | 24 | err_msg.preamble.version = SPDM_THIS_VER; 25 | err_msg.preamble.request_response_code = SPDM_CODE_ERROR; 26 | err_msg.param_1_error_code = code; 27 | 28 | return write_to_writer(output, &err_msg, sizeof(err_msg)); 29 | } 30 | -------------------------------------------------------------------------------- /spdm_lite/library/common/session.c: -------------------------------------------------------------------------------- 1 | // Copyright 2022 Google LLC. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #include "spdm_lite/common/session.h" 16 | 17 | #include 18 | 19 | #include "spdm_lite/common/crypto.h" 20 | #include "spdm_lite/common/messages.h" 21 | #include "spdm_lite/common/utils.h" 22 | #include "spdm_lite/everparse/SPDMWrapper.h" 23 | 24 | int spdm_generate_session_params(const SpdmCryptoSpec* spec, 25 | SpdmDheAlgorithm alg, 26 | SpdmSelfKeyExchangeParams* my_params) { 27 | int rc = spdm_get_random(spec, my_params->my_session_id_part, 28 | sizeof(my_params->my_session_id_part)); 29 | if (rc != 0) { 30 | return rc; 31 | } 32 | 33 | return spdm_gen_dhe_keypair(spec, alg, &my_params->my_priv_key, 34 | &my_params->my_pub_key); 35 | } 36 | 37 | void spdm_generate_session_id(SPDMRole my_role, const uint8_t my_part[2], 38 | const uint8_t their_part[2], 39 | SpdmSessionId* session_id) { 40 | const uint8_t *first_part, *second_part; 41 | 42 | if (my_role == SPDM_REQUESTER) { 43 | first_part = my_part; 44 | second_part = their_part; 45 | } else { 46 | first_part = their_part; 47 | second_part = my_part; 48 | } 49 | 50 | memcpy(session_id->id, first_part, 2); 51 | memcpy(session_id->id + 2, second_part, 2); 52 | } 53 | 54 | int spdm_encrypt_secure_message(const SpdmCryptoSpec* spec, 55 | const SpdmSessionId* session_id, 56 | uint64_t seq_num, const SpdmAeadKeys* keys, 57 | uint8_t* header_buf, buffer input, 58 | byte_writer* footer) { 59 | uint8_t rand_len; 60 | int rc = spdm_get_random(spec, &rand_len, 1); 61 | if (rc != 0) { 62 | return rc; 63 | } 64 | 65 | // 1-16 bytes of randomness. 66 | rand_len &= 0x0F; 67 | rand_len++; 68 | 69 | uint8_t* footer_bytes = 70 | reserve_from_writer(footer, rand_len + AES_GCM_MAC_SIZE); 71 | if (footer_bytes == NULL) { 72 | return -1; 73 | } 74 | 75 | rc = spdm_get_random(spec, footer_bytes, rand_len); 76 | if (rc != 0) { 77 | return rc; 78 | } 79 | 80 | uint8_t* mac = footer_bytes + rand_len; 81 | 82 | SPDM_SecuredMessageRecord header = {}; 83 | 84 | memcpy(&header.session_id, session_id->id, sizeof(header.session_id)); 85 | header.seq_num = seq_num; 86 | header.len = 87 | sizeof(header.app_data_len) + input.size + rand_len + AES_GCM_MAC_SIZE; 88 | header.app_data_len = input.size; 89 | 90 | memcpy(header_buf, &header, sizeof(header)); 91 | 92 | uint8_t* aad = header_buf; 93 | size_t aad_size = sizeof(header) - sizeof(header.app_data_len); 94 | 95 | // Encrypt app_data_len along with app data. 96 | uint8_t* plaintext = aad + aad_size; 97 | size_t plaintext_size = sizeof(header.app_data_len) + input.size + rand_len; 98 | 99 | rc = spdm_aes_gcm_encrypt(spec, &keys->key, &keys->iv, plaintext, 100 | plaintext_size, aad, aad_size, plaintext, mac, 101 | AES_GCM_MAC_SIZE); 102 | 103 | return rc; 104 | } 105 | 106 | int spdm_decrypt_secure_message(const SpdmCryptoSpec* spec, 107 | const SpdmSessionId* session_id, 108 | uint64_t seq_num, const SpdmAeadKeys* keys, 109 | buffer* message) { 110 | uint32_t record_session_id; 111 | const uint8_t* seq_num_ptr; 112 | const uint8_t* ciphertext; 113 | uint32_t ciphertext_size; 114 | const uint8_t* mac; 115 | 116 | int rc = SpdmCheckSecuredMessageRecord( 117 | message, /*rest=*/NULL, 118 | /*seq_num_len=*/sizeof(uint64_t), /*mac_len=*/AES_GCM_MAC_SIZE, 119 | &record_session_id, &seq_num_ptr, &ciphertext, &ciphertext_size, 120 | &mac); 121 | if (rc != 0) { 122 | return rc; 123 | } 124 | 125 | if (memcmp(&record_session_id, session_id->id, sizeof(record_session_id)) != 126 | 0) { 127 | return -1; 128 | } 129 | 130 | // TODO(jeffandersen): endianness. 131 | if (memcmp(seq_num_ptr, &seq_num, sizeof(seq_num)) != 0) { 132 | return -1; 133 | } 134 | 135 | buffer aad = {message->data, sizeof(*session_id) + sizeof(uint64_t) + 2}; 136 | 137 | uint8_t* plaintext = (uint8_t*)message->data; 138 | 139 | rc = spdm_aes_gcm_decrypt(spec, &keys->key, &keys->iv, ciphertext, 140 | ciphertext_size, aad.data, aad.size, mac, 141 | AES_GCM_MAC_SIZE, plaintext); 142 | if (rc != 0) { 143 | return rc; 144 | } 145 | 146 | // Strip off app_data_len and randomness. 147 | uint16_t app_data_len; 148 | if (ciphertext_size < sizeof(app_data_len)) { 149 | return -1; 150 | } 151 | 152 | // TODO(jeffandersen): endianness. 153 | memcpy(&app_data_len, message->data, sizeof(app_data_len)); 154 | 155 | if ((ciphertext_size - sizeof(app_data_len)) < app_data_len) { 156 | return -1; 157 | } 158 | 159 | uint8_t* message_start = plaintext + sizeof(app_data_len); 160 | 161 | message->data = message_start; 162 | message->size = app_data_len; 163 | 164 | return 0; 165 | } 166 | -------------------------------------------------------------------------------- /spdm_lite/library/common/sign.c: -------------------------------------------------------------------------------- 1 | // Copyright 2022 Google LLC. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #include "spdm_lite/common/sign.h" 16 | 17 | #include 18 | 19 | #include "spdm_lite/common/crypto.h" 20 | #include "spdm_lite/common/utils.h" 21 | #include "spdm_lite/common/version.h" 22 | 23 | #define COMBINED_PREFIX_LEN 100 24 | 25 | static int make_spdm_combined_prefix(SPDMRole my_role, const char* context, 26 | uint8_t output[COMBINED_PREFIX_LEN]) { 27 | uint32_t remaining = COMBINED_PREFIX_LEN; 28 | const char* dmtf_str = "dmtf-spdm-v"; 29 | const uint32_t dmtf_str_len = strlen(dmtf_str); 30 | 31 | const char* spdm_context_prefix_requester = "requester-"; 32 | const char* spdm_context_prefix_responder = "responder-"; 33 | const uint32_t spdm_context_prefix_len = 34 | strlen(spdm_context_prefix_requester); 35 | 36 | const uint32_t context_len = strlen(context); 37 | 38 | for (int i = 0; i < 4; ++i) { 39 | memcpy(output, dmtf_str, dmtf_str_len); 40 | output += dmtf_str_len; 41 | remaining -= dmtf_str_len; 42 | 43 | output[0] = (SPDM_THIS_VER >> 4) + '0'; 44 | output[1] = '.'; 45 | output[2] = (SPDM_THIS_VER & 0x0F) + '0'; 46 | output[3] = '.'; 47 | output[4] = '*'; 48 | 49 | output += 5; 50 | remaining -= 5; 51 | } 52 | 53 | output[0] = 0; 54 | output += 1; 55 | remaining -= 1; 56 | 57 | if (context_len > (remaining - spdm_context_prefix_len)) { 58 | return -1; 59 | } 60 | 61 | uint32_t pad_len = remaining - spdm_context_prefix_len - context_len; 62 | memset(output, 0, pad_len); 63 | 64 | output += pad_len; 65 | remaining -= pad_len; 66 | 67 | if (my_role == SPDM_REQUESTER) { 68 | memcpy(output, spdm_context_prefix_requester, spdm_context_prefix_len); 69 | } else { 70 | memcpy(output, spdm_context_prefix_responder, spdm_context_prefix_len); 71 | } 72 | 73 | output += spdm_context_prefix_len; 74 | memcpy(output, context, context_len); 75 | 76 | return 0; 77 | } 78 | 79 | static int make_message_to_sign(const SpdmCryptoSpec* crypto_spec, 80 | SPDMRole signer_role, 81 | const SpdmHashResult* message_hash, 82 | const char* context, SpdmHashResult* out) { 83 | uint8_t combined_prefix[COMBINED_PREFIX_LEN]; 84 | SpdmHash hash; 85 | 86 | int rc = make_spdm_combined_prefix(signer_role, context, combined_prefix); 87 | if (rc != 0) { 88 | return rc; 89 | } 90 | 91 | rc = spdm_initialize_hash_struct(crypto_spec, message_hash->alg, &hash); 92 | if (rc != 0) { 93 | return rc; 94 | } 95 | 96 | spdm_initialize_hash(&hash); 97 | spdm_extend_hash(&hash, combined_prefix, sizeof(combined_prefix)); 98 | spdm_extend_hash(&hash, message_hash->data, message_hash->size); 99 | 100 | return spdm_get_hash_destructive(&hash, out); 101 | } 102 | 103 | int spdm_sign(const SpdmCryptoSpec* crypto_spec, SpdmAsymAlgorithm asym_alg, 104 | void* priv_key_ctx, SPDMRole my_role, 105 | const SpdmHashResult* message_hash, const char* context, 106 | uint8_t* out, uint32_t out_len) { 107 | SpdmHashResult to_sign; 108 | 109 | int rc = make_message_to_sign(crypto_spec, my_role, message_hash, context, 110 | &to_sign); 111 | if (rc != 0) { 112 | return rc; 113 | } 114 | 115 | return spdm_sign_with_private_key(crypto_spec, asym_alg, priv_key_ctx, 116 | &to_sign, out, out_len); 117 | } 118 | 119 | int spdm_verify(const SpdmCryptoSpec* crypto_spec, 120 | const SpdmAsymPubKey* pub_key, SPDMRole signer_role, 121 | const SpdmHashResult* message_hash, const char* context, 122 | const uint8_t* sig, uint32_t sig_len) { 123 | SpdmHashResult signed_hash; 124 | 125 | int rc = make_message_to_sign(crypto_spec, signer_role, message_hash, context, 126 | &signed_hash); 127 | if (rc != 0) { 128 | return rc; 129 | } 130 | 131 | return spdm_verify_with_pub_key(crypto_spec, pub_key, &signed_hash, sig, 132 | sig_len); 133 | } 134 | -------------------------------------------------------------------------------- /spdm_lite/library/common/transcript.c: -------------------------------------------------------------------------------- 1 | // Copyright 2022 Google LLC. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #include "spdm_lite/common/transcript.h" 16 | 17 | #include 18 | 19 | #include "spdm_lite/common/crypto.h" 20 | 21 | int spdm_append_to_transcript(SpdmNegotiationTranscript* transcript, 22 | const void* data, uint32_t size) { 23 | if (sizeof(transcript->data) - transcript->size < size) { 24 | return -1; 25 | } 26 | 27 | memcpy(transcript->data + transcript->size, data, size); 28 | transcript->size += size; 29 | 30 | return 0; 31 | } 32 | 33 | int spdm_initialize_transcript_hash( 34 | const SpdmCryptoSpec* crypto_spec, SpdmHashAlgorithm alg, 35 | const SpdmNegotiationTranscript* transcript, 36 | SpdmHash* transcript_hash) { 37 | int rc = spdm_initialize_hash_struct(crypto_spec, alg, transcript_hash); 38 | if (rc != 0) { 39 | return rc; 40 | } 41 | 42 | spdm_initialize_hash(transcript_hash); 43 | spdm_extend_hash(transcript_hash, transcript->data, transcript->size); 44 | 45 | return 0; 46 | } 47 | -------------------------------------------------------------------------------- /spdm_lite/library/common/utils.c: -------------------------------------------------------------------------------- 1 | // Copyright 2022 Google LLC. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #include "spdm_lite/common/utils.h" 16 | 17 | #include 18 | 19 | void consume_from_buffer(buffer* buf, void* out, uint32_t len) { 20 | memcpy(out, buf->data, len); 21 | buf->data += len; 22 | buf->size -= len; 23 | } 24 | 25 | void spdm_init_writer(byte_writer* writer, void* data, size_t size) { 26 | writer->data = data; 27 | writer->size = size; 28 | writer->bytes_written = 0; 29 | } 30 | 31 | void buffer_to_writer(buffer buf, byte_writer* writer) { 32 | spdm_init_writer(writer, (uint8_t*)buf.data, buf.size); 33 | } 34 | 35 | uint8_t* reserve_from_writer(byte_writer* writer, size_t size) { 36 | size_t bytes_available; 37 | uint8_t* reserved_bytes; 38 | 39 | if (writer->bytes_written > writer->size) { 40 | return NULL; 41 | } 42 | 43 | bytes_available = writer->size - writer->bytes_written; 44 | 45 | if (bytes_available < size) { 46 | return NULL; 47 | } 48 | 49 | reserved_bytes = writer->data + writer->bytes_written; 50 | writer->bytes_written += size; 51 | 52 | return reserved_bytes; 53 | } 54 | 55 | int write_to_writer(byte_writer* writer, const void* data, size_t size) { 56 | void* reserved_bytes = reserve_from_writer(writer, size); 57 | 58 | if (reserved_bytes == NULL) { 59 | return -1; 60 | } 61 | 62 | memcpy(reserved_bytes, data, size); 63 | 64 | return 0; 65 | } 66 | -------------------------------------------------------------------------------- /spdm_lite/library/crypto_impl/mbedtls_helpers.c: -------------------------------------------------------------------------------- 1 | // Copyright 2022 Google LLC. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #include "mbedtls_helpers.h" 16 | 17 | #include "mbedtls/ctr_drbg.h" 18 | #include "mbedtls/ecp.h" 19 | #include "mbedtls/entropy.h" 20 | #include "spdm_lite/common/crypto_types.h" 21 | 22 | uint16_t get_coord_size(mbedtls_ecp_group_id group_id) { 23 | uint16_t bit_size = mbedtls_ecp_curve_info_from_grp_id(group_id)->bit_size; 24 | return (bit_size / 8) + ((bit_size % 8) != 0); 25 | } 26 | 27 | void make_blinding_drbg(mbedtls_ctr_drbg_context* ctr_drbg) { 28 | mbedtls_entropy_context entropy; 29 | 30 | mbedtls_ctr_drbg_init(ctr_drbg); 31 | mbedtls_entropy_init(&entropy); 32 | 33 | const char context[] = "spdm_lite"; 34 | mbedtls_ctr_drbg_seed(ctr_drbg, mbedtls_entropy_func, &entropy, context, 35 | sizeof(context)); 36 | 37 | mbedtls_entropy_free(&entropy); 38 | } 39 | 40 | mbedtls_ecp_group_id get_asym_group_id(SpdmAsymAlgorithm alg) { 41 | switch (alg) { 42 | case SPDM_ASYM_ECDSA_ECC_NIST_P256: 43 | return MBEDTLS_ECP_DP_SECP256R1; 44 | case SPDM_ASYM_ECDSA_ECC_NIST_P384: 45 | return MBEDTLS_ECP_DP_SECP384R1; 46 | case SPDM_ASYM_ECDSA_ECC_NIST_P521: 47 | return MBEDTLS_ECP_DP_SECP521R1; 48 | case SPDM_ASYM_UNSUPPORTED: 49 | default: 50 | return MBEDTLS_ECP_DP_NONE; 51 | } 52 | } 53 | 54 | int generate_keypair(mbedtls_ecp_group_id group_id, uint8_t* pub_key_data, 55 | uint8_t* priv_key_data) { 56 | mbedtls_ecp_group g; 57 | mbedtls_ecp_group_init(&g); 58 | 59 | mbedtls_mpi d; 60 | mbedtls_mpi_init(&d); 61 | 62 | mbedtls_ecp_point p; 63 | mbedtls_ecp_point_init(&p); 64 | 65 | mbedtls_ctr_drbg_context ctr_drbg; 66 | make_blinding_drbg(&ctr_drbg); 67 | 68 | uint16_t coord_size = get_coord_size(group_id); 69 | 70 | int rc = mbedtls_ecp_group_load(&g, group_id); 71 | if (rc != 0) { 72 | goto cleanup; 73 | } 74 | 75 | rc = mbedtls_ecp_gen_keypair(&g, &d, &p, mbedtls_ctr_drbg_random, &ctr_drbg); 76 | if (rc != 0) { 77 | goto cleanup; 78 | } 79 | 80 | rc = mbedtls_mpi_write_binary(&d, priv_key_data, coord_size); 81 | if (rc != 0) { 82 | goto cleanup; 83 | } 84 | 85 | rc = mbedtls_mpi_write_binary(&p.X, pub_key_data, coord_size); 86 | if (rc != 0) { 87 | return rc; 88 | } 89 | 90 | rc = mbedtls_mpi_write_binary(&p.Y, pub_key_data + coord_size, coord_size); 91 | if (rc != 0) { 92 | return rc; 93 | } 94 | 95 | cleanup: 96 | mbedtls_ecp_group_free(&g); 97 | mbedtls_ecp_point_free(&p); 98 | mbedtls_mpi_free(&d); 99 | mbedtls_ctr_drbg_free(&ctr_drbg); 100 | 101 | return rc; 102 | } 103 | -------------------------------------------------------------------------------- /spdm_lite/library/crypto_impl/mbedtls_helpers.h: -------------------------------------------------------------------------------- 1 | // Copyright 2022 Google LLC. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #ifndef SPDM_LITE_LIBRARY_CRYPTO_IMPL_MBEDTLS_HELPERS_H_ 16 | #define SPDM_LITE_LIBRARY_CRYPTO_IMPL_MBEDTLS_HELPERS_H_ 17 | 18 | // Provides functions used to work with mbedtls keys. 19 | 20 | #include 21 | 22 | #include "mbedtls/ctr_drbg.h" 23 | #include "mbedtls/ecp.h" 24 | 25 | #include "spdm_lite/common/crypto_types.h" 26 | 27 | #ifdef __cplusplus 28 | extern "C" { 29 | #endif // __cplusplus 30 | 31 | // Get the EC coordinate size based on the given group. 32 | uint16_t get_coord_size(mbedtls_ecp_group_id group_id); 33 | 34 | // Initialize a DRBG suitable for use in keygen and signing. 35 | void make_blinding_drbg(mbedtls_ctr_drbg_context* ctr_drbg); 36 | 37 | // Map an spdm-lite alg to an mbedtls group ID. 38 | mbedtls_ecp_group_id get_asym_group_id(SpdmAsymAlgorithm alg); 39 | 40 | // Generate an EC key. 41 | int generate_keypair(mbedtls_ecp_group_id group_id, uint8_t* pub_key_data, 42 | uint8_t* priv_key_data); 43 | 44 | #ifdef __cplusplus 45 | } 46 | #endif // __cplusplus 47 | 48 | #endif // SPDM_LITE_LIBRARY_CRYPTO_IMPL_MBEDTLS_HELPERS_H_ 49 | -------------------------------------------------------------------------------- /spdm_lite/library/crypto_impl/mbedtls_sign.c: -------------------------------------------------------------------------------- 1 | // Copyright 2022 Google LLC. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #include "spdm_lite/crypto_impl/mbedtls_sign.h" 16 | 17 | #include 18 | 19 | #include "mbedtls/ecdsa.h" 20 | #include "mbedtls/ecp.h" 21 | 22 | #include "mbedtls_helpers.h" 23 | #include "spdm_lite/common/crypto_types.h" 24 | 25 | int spdm_generate_asym_keypair(SpdmAsymAlgorithm alg, SpdmAsymPrivKey* priv_key, 26 | SpdmAsymPubKey* pub_key) { 27 | spdm_init_asym_pub_key(pub_key, alg); 28 | priv_key->alg = alg; 29 | 30 | // Detect bad alg. 31 | if (pub_key->size == 0) { 32 | return -1; 33 | } 34 | 35 | return generate_keypair(get_asym_group_id(alg), pub_key->data, 36 | priv_key->data); 37 | } 38 | 39 | int spdm_mbedtls_sign_with_priv_key(SpdmAsymAlgorithm alg, void* priv_key_ctx, 40 | const uint8_t* input, uint32_t input_len, 41 | uint8_t* sig, uint32_t sig_len) { 42 | SpdmAsymPrivKey* priv_key = (SpdmAsymPrivKey*)priv_key_ctx; 43 | 44 | if (alg != priv_key->alg) { 45 | return -1; 46 | } 47 | 48 | mbedtls_ecp_group_id group_id = get_asym_group_id(alg); 49 | if (group_id == MBEDTLS_ECP_DP_NONE) { 50 | return -1; 51 | } 52 | 53 | uint16_t coord_size = get_coord_size(group_id); 54 | 55 | if (sig_len != spdm_get_asym_signature_size(alg)) { 56 | return -1; 57 | } 58 | 59 | mbedtls_ecp_group g; 60 | mbedtls_ecp_group_init(&g); 61 | 62 | mbedtls_mpi r, s, d; 63 | mbedtls_mpi_init(&r); 64 | mbedtls_mpi_init(&s); 65 | mbedtls_mpi_init(&d); 66 | 67 | mbedtls_ctr_drbg_context ctr_drbg; 68 | make_blinding_drbg(&ctr_drbg); 69 | 70 | int rc = mbedtls_ecp_group_load(&g, group_id); 71 | if (rc != 0) { 72 | goto cleanup; 73 | } 74 | 75 | rc = mbedtls_mpi_read_binary(&d, (unsigned char*)priv_key->data, coord_size); 76 | if (rc != 0) { 77 | goto cleanup; 78 | } 79 | 80 | rc = mbedtls_ecdsa_sign_det_ext(&g, &r, &s, &d, (const unsigned char*)input, 81 | input_len, MBEDTLS_MD_SHA384, 82 | mbedtls_ctr_drbg_random, &ctr_drbg); 83 | if (rc != 0) { 84 | goto cleanup; 85 | } 86 | 87 | rc = mbedtls_mpi_write_binary(&r, (unsigned char*)sig, coord_size); 88 | if (rc != 0) { 89 | goto cleanup; 90 | } 91 | 92 | rc = mbedtls_mpi_write_binary(&s, (unsigned char*)(sig + coord_size), 93 | coord_size); 94 | if (rc != 0) { 95 | goto cleanup; 96 | } 97 | 98 | cleanup: 99 | mbedtls_ecp_group_free(&g); 100 | mbedtls_mpi_free(&r); 101 | mbedtls_mpi_free(&s); 102 | mbedtls_mpi_free(&d); 103 | mbedtls_ctr_drbg_free(&ctr_drbg); 104 | 105 | return rc; 106 | } 107 | -------------------------------------------------------------------------------- /spdm_lite/library/crypto_impl/raw_serialize.c: -------------------------------------------------------------------------------- 1 | // Copyright 2022 Google LLC. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #include "spdm_lite/crypto_impl/raw_serialize.h" 16 | 17 | #include 18 | 19 | #include "spdm_lite/common/crypto_types.h" 20 | 21 | int spdm_raw_serialize_asym_key(SpdmAsymAlgorithm asym_alg, 22 | SpdmHashAlgorithm hash_alg, const uint8_t* in, 23 | uint16_t in_size, uint8_t* out, 24 | uint16_t* out_size) { 25 | if (*out_size < in_size) { 26 | return -1; 27 | } 28 | 29 | memcpy(out, in, in_size); 30 | 31 | *out_size = in_size; 32 | 33 | return 0; 34 | } 35 | -------------------------------------------------------------------------------- /spdm_lite/library/crypto_impl/tpmt_public_serialize.c: -------------------------------------------------------------------------------- 1 | // Copyright 2022 Google LLC. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #include "spdm_lite/crypto_impl/tpmt_public_serialize.h" 16 | 17 | #include 18 | 19 | #include "spdm_lite/common/crypto_types.h" 20 | #include "tss2/tss2_mu.h" 21 | #include "tss2/tss2_tpm2_types.h" 22 | 23 | static TPMI_ALG_HASH get_hash_alg(SpdmHashAlgorithm alg) { 24 | switch (alg) { 25 | case SPDM_HASH_SHA256: 26 | return TPM2_ALG_SHA256; 27 | case SPDM_HASH_SHA384: 28 | return TPM2_ALG_SHA384; 29 | case SPDM_HASH_SHA512: 30 | return TPM2_ALG_SHA512; 31 | default: 32 | return TPM2_ALG_NULL; 33 | } 34 | } 35 | 36 | static TPMI_ECC_CURVE get_curve_id(SpdmAsymAlgorithm alg) { 37 | switch (alg) { 38 | case SPDM_ASYM_ECDSA_ECC_NIST_P256: 39 | return TPM2_ECC_NIST_P256; 40 | case SPDM_ASYM_ECDSA_ECC_NIST_P384: 41 | return TPM2_ECC_NIST_P384; 42 | case SPDM_ASYM_ECDSA_ECC_NIST_P521: 43 | return TPM2_ECC_NIST_P521; 44 | default: 45 | return TPM2_ECC_NONE; 46 | } 47 | } 48 | 49 | static uint16_t get_coord_size(TPMI_ECC_CURVE curve_id) { 50 | switch (curve_id) { 51 | case TPM2_ECC_NIST_P256: 52 | return P256_COORD_SIZE; 53 | case TPM2_ECC_NIST_P384: 54 | return P384_COORD_SIZE; 55 | case TPM2_ECC_NIST_P521: 56 | return P521_COORD_SIZE; 57 | default: 58 | return 0; 59 | } 60 | } 61 | 62 | int spdm_serialize_asym_pub_to_tpmt_public(SpdmAsymAlgorithm asym_alg, 63 | SpdmHashAlgorithm hash_alg, 64 | const uint8_t* in, uint16_t in_size, 65 | uint8_t* out, uint16_t* out_size) { 66 | TPMT_PUBLIC tpmt_public = { 67 | .type = TPM2_ALG_ECC, 68 | .nameAlg = TPM2_ALG_NULL, 69 | .objectAttributes = TPMA_OBJECT_SIGN_ENCRYPT, 70 | .parameters = 71 | { 72 | .eccDetail = 73 | { 74 | .symmetric = {.algorithm = TPM2_ALG_NULL}, 75 | .scheme = {.scheme = TPM2_ALG_ECDSA, 76 | .details = {.ecdsa = {.hashAlg = get_hash_alg( 77 | hash_alg)}}}, 78 | .curveID = get_curve_id(asym_alg), 79 | .kdf = {.scheme = TPM2_ALG_NULL}, 80 | }, 81 | }, 82 | }; 83 | 84 | TPMS_ECC_POINT* ecc = &tpmt_public.unique.ecc; 85 | uint16_t coord_size = 86 | get_coord_size(tpmt_public.parameters.eccDetail.curveID); 87 | 88 | memcpy(ecc->x.buffer, in, coord_size); 89 | memcpy(ecc->y.buffer, in + coord_size, coord_size); 90 | 91 | ecc->x.size = coord_size; 92 | ecc->y.size = coord_size; 93 | 94 | size_t offset = 0; 95 | 96 | TSS2_RC tss_rc = 97 | Tss2_MU_TPMT_PUBLIC_Marshal(&tpmt_public, out, *out_size, &offset); 98 | if (tss_rc != TSS2_RC_SUCCESS) { 99 | return -1; 100 | } 101 | 102 | *out_size = offset; 103 | 104 | return 0; 105 | } 106 | 107 | int spdm_deserialize_asym_pub_from_tpmt_public(SpdmAsymAlgorithm asym_alg, 108 | SpdmHashAlgorithm hash_alg, 109 | const uint8_t* in, 110 | uint16_t in_size, uint8_t* out, 111 | uint16_t* out_size) { 112 | TPMT_PUBLIC tpmt_public; 113 | TSS2_RC tss_rc = Tss2_MU_TPMT_PUBLIC_Unmarshal(in, in_size, 114 | /*offset=*/NULL, &tpmt_public); 115 | if (tss_rc != TSS2_RC_SUCCESS) { 116 | return -1; 117 | } 118 | 119 | if (tpmt_public.type != TPM2_ALG_ECC || 120 | tpmt_public.nameAlg != TPM2_ALG_NULL || 121 | tpmt_public.objectAttributes != TPMA_OBJECT_SIGN_ENCRYPT || 122 | tpmt_public.authPolicy.size != 0) { 123 | return -1; 124 | } 125 | 126 | const TPMS_ECC_PARMS* params = &tpmt_public.parameters.eccDetail; 127 | 128 | if (params->symmetric.algorithm != TPM2_ALG_NULL || 129 | params->scheme.scheme != TPM2_ALG_ECDSA || 130 | params->scheme.details.ecdsa.hashAlg != get_hash_alg(hash_alg) || 131 | params->kdf.scheme != TPM2_ALG_NULL) { 132 | return -1; 133 | } 134 | 135 | const TPMS_ECC_POINT* ecc = &tpmt_public.unique.ecc; 136 | 137 | if (get_curve_id(asym_alg) != params->curveID) { 138 | return -1; 139 | } 140 | 141 | uint16_t coord_size = get_coord_size(params->curveID); 142 | 143 | if (ecc->x.size != coord_size || ecc->y.size != coord_size) { 144 | return -1; 145 | } 146 | 147 | if (*out_size < 2 * coord_size) { 148 | return -1; 149 | } 150 | 151 | *out_size = 2 * coord_size; 152 | 153 | memcpy(out, ecc->x.buffer, coord_size); 154 | memcpy(out + coord_size, ecc->y.buffer, coord_size); 155 | 156 | return 0; 157 | } 158 | -------------------------------------------------------------------------------- /spdm_lite/library/requester/requester.c: -------------------------------------------------------------------------------- 1 | // Copyright 2022 Google LLC. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #include "spdm_lite/requester/requester.h" 16 | 17 | #include 18 | 19 | #include "requester_functions.h" 20 | #include "send_request.h" 21 | #include "spdm_lite/common/crypto.h" 22 | #include "spdm_lite/common/messages.h" 23 | #include "spdm_lite/common/session_types.h" 24 | #include "spdm_lite/common/utils.h" 25 | #include "spdm_lite/common/version.h" 26 | #include "spdm_lite/everparse/SPDMWrapper.h" 27 | 28 | int spdm_establish_session(const SpdmRequesterSessionParams* params, 29 | SpdmSessionParams* session) { 30 | int rc = spdm_validate_asym_pubkey(¶ms->dispatch_ctx->crypto_spec, 31 | ¶ms->requester_pub_key); 32 | if (rc != 0) { 33 | return rc; 34 | } 35 | 36 | SpdmRequesterContext ctx = {}; 37 | ctx.params = params; 38 | 39 | memset(session, 0, sizeof(*session)); 40 | 41 | rc = spdm_get_version(&ctx); 42 | if (rc != 0) { 43 | goto cleanup; 44 | } 45 | 46 | rc = spdm_get_capabilities(&ctx); 47 | if (rc != 0) { 48 | goto cleanup; 49 | } 50 | 51 | rc = spdm_negotiate_algorithms(&ctx, session); 52 | if (rc != 0) { 53 | goto cleanup; 54 | } 55 | 56 | rc = spdm_get_pub_key(&ctx, session); 57 | if (rc != 0) { 58 | goto cleanup; 59 | } 60 | 61 | rc = spdm_key_exchange(&ctx, session); 62 | if (rc != 0) { 63 | goto cleanup; 64 | } 65 | 66 | rc = spdm_give_pub_key(&ctx, session); 67 | if (rc != 0) { 68 | goto cleanup; 69 | } 70 | 71 | rc = spdm_finish(&ctx, session); 72 | if (rc != 0) { 73 | goto cleanup; 74 | } 75 | 76 | cleanup: 77 | if (rc != 0) { 78 | memset(session, 0, sizeof(*session)); 79 | } 80 | 81 | return rc; 82 | } 83 | 84 | int spdm_dispatch_app_request(const SpdmDispatchRequestCtx* dispatch_ctx, 85 | SpdmScratchSpace scratch_space, 86 | SpdmSessionParams* session, uint16_t standard_id, 87 | const uint8_t* vendor_id, size_t vendor_id_size, 88 | const void* req, size_t req_size, void* rsp, 89 | size_t* rsp_size) { 90 | SPDM_VENDOR_DEFINED_REQ_RSP req_msg = {}; 91 | 92 | byte_writer writer = {scratch_space.data, scratch_space.size, 0}; 93 | 94 | uint8_t* out = reserve_from_writer( 95 | &writer, sizeof(req_msg) + vendor_id_size + sizeof(uint16_t) + req_size); 96 | if (out == NULL) { 97 | return -1; 98 | } 99 | 100 | req_msg.preamble.version = SPDM_THIS_VER; 101 | req_msg.preamble.request_response_code = SPDM_CODE_VENDOR_DEFINED_REQUEST; 102 | req_msg.standard_id = standard_id; 103 | req_msg.vendor_id_len = vendor_id_size; 104 | 105 | uint16_t req_len = req_size; 106 | 107 | memmove(out + sizeof(req_msg) + vendor_id_size + sizeof(req_len), req, 108 | req_size); 109 | 110 | memcpy(out, &req_msg, sizeof(req_msg)); 111 | out += sizeof(req_msg); 112 | 113 | memcpy(out, vendor_id, vendor_id_size); 114 | out += vendor_id_size; 115 | 116 | memcpy(out, &req_len, sizeof(req_len)); 117 | out += sizeof(req_len); 118 | 119 | buffer vendor_req = {writer.data, writer.bytes_written}; 120 | buffer rsp_buf; 121 | 122 | int rc = spdm_send_secure_request(dispatch_ctx, scratch_space, session, 123 | SPDM_DATA_PHASE, vendor_req, &rsp_buf); 124 | 125 | if (rc != 0) { 126 | return rc; 127 | } 128 | 129 | uint16_t rsp_standard_id; 130 | buffer rsp_vendor_id; 131 | buffer payload; 132 | 133 | rc = SpdmCheckVendorDefinedResponse(&rsp_buf, /*rest=*/NULL, &rsp_standard_id, 134 | &rsp_vendor_id.data, &rsp_vendor_id.size, 135 | &payload.data, &payload.size); 136 | if (rc != 0) { 137 | return rc; 138 | } 139 | 140 | if (rsp_standard_id != standard_id || rsp_vendor_id.size != vendor_id_size) { 141 | return -1; 142 | } 143 | 144 | if (memcmp(rsp_vendor_id.data, vendor_id, vendor_id_size) != 0) { 145 | return -1; 146 | } 147 | 148 | if (payload.size > *rsp_size) { 149 | return -1; 150 | } 151 | 152 | memcpy(rsp, payload.data, payload.size); 153 | *rsp_size = payload.size; 154 | 155 | return 0; 156 | } 157 | 158 | int spdm_end_session(const SpdmDispatchRequestCtx* dispatch_ctx, 159 | SpdmScratchSpace scratch_space, 160 | SpdmSessionParams* session) { 161 | SPDM_END_SESSION req_msg = {}; 162 | 163 | req_msg.preamble.version = SPDM_THIS_VER; 164 | req_msg.preamble.request_response_code = SPDM_CODE_END_SESSION; 165 | 166 | buffer req_buf = {(uint8_t*)&req_msg, sizeof(req_msg)}; 167 | buffer rsp_buf; 168 | 169 | int rc = spdm_send_secure_request(dispatch_ctx, scratch_space, session, 170 | SPDM_DATA_PHASE, req_buf, &rsp_buf); 171 | if (rc != 0) { 172 | return rc; 173 | } 174 | 175 | rc = SpdmCheckEndSessionAck(&rsp_buf, /*rest=*/NULL); 176 | if (rc != 0) { 177 | return rc; 178 | } 179 | 180 | memset(session, 0, sizeof(*session)); 181 | 182 | return 0; 183 | } 184 | -------------------------------------------------------------------------------- /spdm_lite/library/requester/requester_functions.h: -------------------------------------------------------------------------------- 1 | // Copyright 2022 Google LLC. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #ifndef SPDM_LITE_LIBRARY_REQUESTER_REQUESTER_FUNCTIONS_H_ 16 | #define SPDM_LITE_LIBRARY_REQUESTER_REQUESTER_FUNCTIONS_H_ 17 | 18 | #include "spdm_lite/common/capabilities.h" 19 | #include "spdm_lite/common/crypto_types.h" 20 | #include "spdm_lite/common/session_types.h" 21 | #include "spdm_lite/common/transcript.h" 22 | #include "spdm_lite/requester/requester.h" 23 | 24 | // Holds data needed to establish a session with a Responder. 25 | typedef struct { 26 | const SpdmRequesterSessionParams* params; 27 | 28 | SpdmNegotiationTranscript negotiation_transcript; 29 | 30 | SpdmHash transcript_hash; 31 | 32 | // Populated from `CAPABILITIES` 33 | SpdmCapabilities responder_caps; 34 | } SpdmRequesterContext; 35 | 36 | int spdm_get_version(SpdmRequesterContext* ctx); 37 | int spdm_get_capabilities(SpdmRequesterContext* ctx); 38 | int spdm_negotiate_algorithms(SpdmRequesterContext* ctx, 39 | SpdmSessionParams* session); 40 | int spdm_get_pub_key(SpdmRequesterContext* ctx, SpdmSessionParams* session); 41 | int spdm_key_exchange(SpdmRequesterContext* ctx, SpdmSessionParams* session); 42 | int spdm_give_pub_key(SpdmRequesterContext* ctx, SpdmSessionParams* session); 43 | int spdm_finish(SpdmRequesterContext* ctx, SpdmSessionParams* session); 44 | 45 | #endif // SPDM_LITE_LIBRARY_REQUESTER_REQUESTER_FUNCTIONS_H_ 46 | -------------------------------------------------------------------------------- /spdm_lite/library/requester/requester_get_capabilities.c: -------------------------------------------------------------------------------- 1 | // Copyright 2022 Google LLC. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #include 16 | 17 | #include "requester_functions.h" 18 | #include "send_request.h" 19 | #include "spdm_lite/common/messages.h" 20 | #include "spdm_lite/common/version.h" 21 | #include "spdm_lite/everparse/SPDMWrapper.h" 22 | #include "spdm_lite/requester/requester.h" 23 | 24 | int spdm_get_capabilities(SpdmRequesterContext* ctx) { 25 | const SpdmRequesterSessionParams* params = ctx->params; 26 | 27 | SPDM_GET_CAPABILITIES msg = {}; 28 | 29 | msg.preamble.version = SPDM_THIS_VER; 30 | msg.preamble.request_response_code = SPDM_CODE_GET_CAPABILITIES; 31 | 32 | msg.ct_exponent = 0; 33 | msg.data_transfer_size = params->requester_caps.data_transfer_size; 34 | msg.max_spdm_message_size = params->requester_caps.data_transfer_size; 35 | msg.flags_ENCRYPT_CAP = 1; 36 | msg.flags_MAC_CAP = 1; 37 | msg.flags_KEY_EX_CAP = 1; 38 | 39 | buffer req = {(const uint8_t*)&msg, sizeof(msg)}; 40 | buffer rsp; 41 | 42 | int rc = spdm_send_request(params->dispatch_ctx, params->scratch, 43 | /*is_secure_msg=*/false, req, &rsp); 44 | if (rc != 0) { 45 | return rc; 46 | } 47 | 48 | rc = SpdmCheckCapabilities(&rsp, /*rest=*/NULL); 49 | if (rc != 0) { 50 | return rc; 51 | } 52 | 53 | SPDM_CAPABILITIES caps; 54 | memcpy(&caps, rsp.data, sizeof(caps)); 55 | 56 | memset(&ctx->responder_caps, 0, sizeof(ctx->responder_caps)); 57 | ctx->responder_caps.data_transfer_size = caps.data_transfer_size; 58 | 59 | if (caps.flags_ENCRYPT_CAP != 1 || caps.flags_MAC_CAP != 1 || 60 | caps.flags_KEY_EX_CAP != 1) { 61 | return -1; 62 | } 63 | 64 | rc = spdm_append_to_transcript(&ctx->negotiation_transcript, req.data, 65 | req.size); 66 | if (rc != 0) { 67 | return rc; 68 | } 69 | 70 | return spdm_append_to_transcript(&ctx->negotiation_transcript, rsp.data, 71 | rsp.size); 72 | } 73 | -------------------------------------------------------------------------------- /spdm_lite/library/requester/requester_get_pub_key.c: -------------------------------------------------------------------------------- 1 | // Copyright 2022 Google LLC. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #include 16 | 17 | #include "requester_functions.h" 18 | #include "send_request.h" 19 | #include "spdm_lite/common/crypto.h" 20 | #include "spdm_lite/common/utils.h" 21 | #include "spdm_lite/common/vendor_defined_pub_key.h" 22 | #include "spdm_lite/requester/requester.h" 23 | 24 | int spdm_get_pub_key(SpdmRequesterContext* ctx, SpdmSessionParams* session) { 25 | const SpdmRequesterSessionParams* params = ctx->params; 26 | 27 | byte_writer writer = {params->scratch.data, params->scratch.size, 0}; 28 | 29 | int rc = spdm_write_get_pub_key_req(&writer); 30 | if (rc != 0) { 31 | return rc; 32 | } 33 | 34 | buffer req = {writer.data, writer.bytes_written}; 35 | buffer rsp; 36 | 37 | rc = spdm_send_request(params->dispatch_ctx, params->scratch, 38 | /*is_secure_msg=*/false, req, &rsp); 39 | if (rc != 0) { 40 | return rc; 41 | } 42 | 43 | SpdmAsymPubKey pub_key_in_response; 44 | rc = spdm_check_get_pub_key_rsp(¶ms->dispatch_ctx->crypto_spec, rsp, 45 | session->info.negotiated_algs.asym_verify_alg, 46 | session->info.negotiated_algs.hash_alg, 47 | &pub_key_in_response); 48 | if (rc != 0) { 49 | return rc; 50 | } 51 | 52 | rc = spdm_validate_asym_pubkey(¶ms->dispatch_ctx->crypto_spec, 53 | &pub_key_in_response); 54 | if (rc != 0) { 55 | return rc; 56 | } 57 | 58 | session->info.peer_pub_key = pub_key_in_response; 59 | 60 | return 0; 61 | } 62 | -------------------------------------------------------------------------------- /spdm_lite/library/requester/requester_get_version.c: -------------------------------------------------------------------------------- 1 | // Copyright 2022 Google LLC. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #include 16 | 17 | #include "requester_functions.h" 18 | #include "send_request.h" 19 | #include "spdm_lite/common/messages.h" 20 | #include "spdm_lite/common/transcript.h" 21 | #include "spdm_lite/common/version.h" 22 | #include "spdm_lite/everparse/SPDMWrapper.h" 23 | #include "spdm_lite/requester/requester.h" 24 | 25 | static int check_version(uint8_t entry_count, const uint8_t* entries) { 26 | for (int i = 0; i < entry_count; ++i) { 27 | SPDM_VersionNumberEntry entry; 28 | memcpy(&entry, entries, sizeof(entry)); 29 | entries += sizeof(entry); 30 | 31 | if (entry.major_version != SPDM_THIS_VER >> 4) { 32 | continue; 33 | } 34 | 35 | // TODO(jeffandersen): allow minor version skew? 36 | if (entry.minor_version != (SPDM_THIS_VER & 0x0F)) { 37 | continue; 38 | } 39 | 40 | if (entry.alpha != 0) { 41 | continue; 42 | } 43 | 44 | return 0; 45 | } 46 | 47 | return -1; 48 | } 49 | 50 | int spdm_get_version(SpdmRequesterContext* ctx) { 51 | const SpdmRequesterSessionParams* params = ctx->params; 52 | 53 | SPDM_GET_VERSION msg = {}; 54 | 55 | msg.preamble.version = 0x10; 56 | msg.preamble.request_response_code = SPDM_CODE_GET_VERSION; 57 | 58 | buffer req = {(const uint8_t*)&msg, sizeof(msg)}; 59 | buffer rsp; 60 | 61 | int rc = spdm_send_request(params->dispatch_ctx, params->scratch, 62 | /*is_secure_msg=*/false, req, &rsp); 63 | if (rc != 0) { 64 | return rc; 65 | } 66 | 67 | uint8_t entry_count; 68 | const uint8_t* entries; 69 | 70 | rc = SpdmCheckVersion(&rsp, /*rest=*/NULL, &entry_count, &entries); 71 | if (rc != 0) { 72 | return rc; 73 | } 74 | 75 | rc = check_version(entry_count, entries); 76 | if (rc != 0) { 77 | return rc; 78 | } 79 | 80 | rc = spdm_append_to_transcript(&ctx->negotiation_transcript, req.data, 81 | req.size); 82 | if (rc != 0) { 83 | return rc; 84 | } 85 | 86 | return spdm_append_to_transcript(&ctx->negotiation_transcript, rsp.data, 87 | rsp.size); 88 | } 89 | -------------------------------------------------------------------------------- /spdm_lite/library/requester/requester_give_pub_key.c: -------------------------------------------------------------------------------- 1 | // Copyright 2022 Google LLC. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #include 16 | #include 17 | 18 | #include "requester_functions.h" 19 | #include "send_request.h" 20 | #include "spdm_lite/common/utils.h" 21 | #include "spdm_lite/common/vendor_defined_pub_key.h" 22 | #include "spdm_lite/requester/requester.h" 23 | 24 | int spdm_give_pub_key(SpdmRequesterContext* ctx, SpdmSessionParams* session) { 25 | const SpdmRequesterSessionParams* params = ctx->params; 26 | 27 | byte_writer writer = {params->scratch.data, params->scratch.size, 0}; 28 | 29 | int rc = spdm_write_give_pub_key_req( 30 | ¶ms->dispatch_ctx->crypto_spec, ¶ms->requester_pub_key, 31 | session->info.negotiated_algs.hash_alg, &writer); 32 | if (rc != 0) { 33 | return rc; 34 | } 35 | 36 | buffer req = {writer.data, writer.bytes_written}; 37 | buffer rsp; 38 | 39 | rc = spdm_send_secure_request(params->dispatch_ctx, params->scratch, session, 40 | SPDM_HANDSHAKE_PHASE, req, &rsp); 41 | if (rc != 0) { 42 | return rc; 43 | } 44 | 45 | return spdm_check_give_pub_key_rsp(rsp); 46 | } 47 | -------------------------------------------------------------------------------- /spdm_lite/library/requester/send_request.c: -------------------------------------------------------------------------------- 1 | // Copyright 2022 Google LLC. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #include "send_request.h" 16 | 17 | #include 18 | 19 | #include "spdm_lite/common/key_schedule.h" 20 | #include "spdm_lite/common/messages.h" 21 | #include "spdm_lite/common/session.h" 22 | #include "spdm_lite/common/utils.h" 23 | #include "spdm_lite/requester/requester.h" 24 | 25 | static int generate_session_keys(const SpdmCryptoSpec* crypto_spec, 26 | SpdmSessionParams* session, 27 | SpdmSessionPhase phase, uint64_t req_seq_num, 28 | uint64_t rsp_seq_num, 29 | SpdmSessionAeadKeys* keys) { 30 | SpdmMessageSecrets secrets; 31 | 32 | int rc = spdm_generate_message_secrets(crypto_spec, session, phase, &secrets); 33 | if (rc != 0) { 34 | goto cleanup; 35 | } 36 | 37 | rc = spdm_generate_aead_keys(crypto_spec, 38 | session->info.negotiated_algs.aead_alg, &secrets, 39 | req_seq_num, rsp_seq_num, keys); 40 | if (rc != 0) { 41 | goto cleanup; 42 | } 43 | 44 | cleanup: 45 | memset(&secrets, 0, sizeof(secrets)); 46 | return rc; 47 | } 48 | 49 | int spdm_send_request(const SpdmDispatchRequestCtx* ctx, 50 | SpdmScratchSpace scratch_space, bool is_secure_msg, 51 | buffer req, buffer* rsp) { 52 | uint8_t* rsp_data = scratch_space.data; 53 | size_t rsp_size = scratch_space.size; 54 | 55 | int rc = ctx->dispatch_fn(ctx->dispatch_ctx, is_secure_msg, req.data, 56 | req.size, rsp_data, &rsp_size); 57 | if (rc != 0) { 58 | return rc; 59 | } 60 | 61 | rsp->data = rsp_data; 62 | rsp->size = rsp_size; 63 | 64 | return 0; 65 | } 66 | 67 | int spdm_send_secure_request(const SpdmDispatchRequestCtx* ctx, 68 | SpdmScratchSpace scratch_space, 69 | SpdmSessionParams* session, SpdmSessionPhase phase, 70 | buffer req, buffer* rsp) { 71 | SpdmSessionAeadKeys keys; 72 | int rc = 0; 73 | 74 | if (scratch_space.size < req.size + SPDM_SECURE_MESSAGE_OVERHEAD) { 75 | rc = -1; 76 | goto cleanup; 77 | } 78 | 79 | uint8_t* header = scratch_space.data; 80 | 81 | uint8_t* plaintext_start = header + sizeof(SPDM_SecuredMessageRecord); 82 | memmove(plaintext_start, req.data, req.size); 83 | 84 | byte_writer footer = {plaintext_start + req.size, 85 | SPDM_MAX_SECURE_MESSAGE_FOOTER_LEN, 0}; 86 | 87 | rc = generate_session_keys(&ctx->crypto_spec, session, phase, 88 | session->req_seq_num, session->rsp_seq_num, &keys); 89 | if (rc != 0) { 90 | goto cleanup; 91 | } 92 | 93 | buffer msg_buf = {plaintext_start, req.size}; 94 | 95 | rc = spdm_encrypt_secure_message(&ctx->crypto_spec, &session->info.session_id, 96 | session->req_seq_num, &keys.req_keys, header, 97 | msg_buf, &footer); 98 | if (rc != 0) { 99 | goto cleanup; 100 | } 101 | 102 | session->req_seq_num++; 103 | 104 | uint32_t encrypted_msg_len = 105 | sizeof(SPDM_SecuredMessageRecord) + req.size + footer.bytes_written; 106 | 107 | buffer encrypted_req = {header, encrypted_msg_len}; 108 | 109 | rc = spdm_send_request(ctx, scratch_space, 110 | /*is_secure_msg=*/true, encrypted_req, rsp); 111 | if (rc != 0) { 112 | goto cleanup; 113 | } 114 | 115 | rc = spdm_decrypt_secure_message(&ctx->crypto_spec, &session->info.session_id, 116 | session->rsp_seq_num, &keys.rsp_keys, rsp); 117 | if (rc != 0) { 118 | goto cleanup; 119 | } 120 | 121 | session->rsp_seq_num++; 122 | 123 | cleanup: 124 | memset(&keys, 0, sizeof(keys)); 125 | 126 | return rc; 127 | } 128 | -------------------------------------------------------------------------------- /spdm_lite/library/requester/send_request.h: -------------------------------------------------------------------------------- 1 | // Copyright 2022 Google LLC. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #ifndef SPDM_LITE_LIBRARY_REQUESTER_SEND_REQUEST_H_ 16 | #define SPDM_LITE_LIBRARY_REQUESTER_SEND_REQUEST_H_ 17 | 18 | #include 19 | 20 | #include "spdm_lite/common/session_types.h" 21 | #include "spdm_lite/common/utils.h" 22 | #include "spdm_lite/requester/requester.h" 23 | 24 | #ifdef __cplusplus 25 | extern "C" { 26 | #endif // __cplusplus 27 | 28 | // The response is stored in `ctx->scratch_buffer` 29 | int spdm_send_request(const SpdmDispatchRequestCtx* ctx, 30 | SpdmScratchSpace scratch_space, bool is_secure_msg, 31 | buffer req, buffer* rsp); 32 | 33 | // The response is stored in `ctx->scratch_buffer` 34 | int spdm_send_secure_request(const SpdmDispatchRequestCtx* ctx, 35 | SpdmScratchSpace scratch_space, 36 | SpdmSessionParams* session, SpdmSessionPhase phase, 37 | buffer req, buffer* rsp); 38 | 39 | #ifdef __cplusplus 40 | } 41 | #endif // __cplusplus 42 | 43 | #endif // SPDM_LITE_LIBRARY_REQUESTER_SEND_REQUEST_H_ 44 | -------------------------------------------------------------------------------- /spdm_lite/library/responder/state_need_requester_key.c: -------------------------------------------------------------------------------- 1 | // Copyright 2022 Google LLC. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #include 16 | 17 | #include "spdm_lite/common/crypto.h" 18 | #include "spdm_lite/common/error.h" 19 | #include "spdm_lite/common/session_types.h" 20 | #include "spdm_lite/common/utils.h" 21 | #include "spdm_lite/common/vendor_defined_pub_key.h" 22 | #include "spdm_lite/responder/responder.h" 23 | 24 | int spdm_dispatch_request_need_requester_key(SpdmResponderContext* ctx, 25 | uint8_t code, buffer input, 26 | byte_writer* output) { 27 | int rc; 28 | SpdmSessionInfo* session_info = &ctx->session.params.info; 29 | 30 | if (ctx->state != STATE_MUTUAL_AUTH_NEED_REQUESTER_KEY) { 31 | return -1; 32 | } 33 | 34 | SpdmAsymPubKey pub_key_in_request; 35 | rc = spdm_check_give_pub_key_req( 36 | &ctx->crypto_spec, input, session_info->negotiated_algs.asym_verify_alg, 37 | session_info->negotiated_algs.hash_alg, &pub_key_in_request); 38 | if (rc != 0) { 39 | return spdm_write_error(SPDM_ERR_INVALID_REQUEST, output); 40 | } 41 | 42 | rc = spdm_validate_asym_pubkey(&ctx->crypto_spec, &pub_key_in_request); 43 | if (rc != 0) { 44 | return rc; 45 | } 46 | 47 | rc = spdm_write_give_pub_key_rsp(output); 48 | if (rc != 0) { 49 | return rc; 50 | } 51 | 52 | session_info->peer_pub_key = pub_key_in_request; 53 | ctx->state = STATE_MUTUAL_AUTH_WAITING_FOR_FINISH; 54 | 55 | return 0; 56 | } 57 | -------------------------------------------------------------------------------- /spdm_lite/library/responder/state_session_established.c: -------------------------------------------------------------------------------- 1 | // Copyright 2022 Google LLC. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #include 16 | 17 | #include "spdm_lite/common/crypto.h" 18 | #include "spdm_lite/common/error.h" 19 | #include "spdm_lite/common/messages.h" 20 | #include "spdm_lite/common/utils.h" 21 | #include "spdm_lite/common/version.h" 22 | #include "spdm_lite/everparse/SPDMWrapper.h" 23 | #include "spdm_lite/responder/responder.h" 24 | 25 | static int handle_end_session(SpdmResponderContext* ctx, buffer input, 26 | byte_writer* output, bool* end_session) { 27 | bool preserve_negotiated_state; // Will ignore this as we don't support 28 | // caching negotiated state. 29 | SPDM_END_SESSION_ACK ack = {}; 30 | 31 | int rc = 32 | SpdmCheckEndSession(&input, /*rest=*/NULL, &preserve_negotiated_state); 33 | if (rc != 0) { 34 | return spdm_write_error(SPDM_ERR_INVALID_REQUEST, output); 35 | } 36 | 37 | ack.preamble.version = SPDM_THIS_VER; 38 | ack.preamble.request_response_code = SPDM_CODE_END_SESSION_ACK; 39 | 40 | rc = write_to_writer(output, &ack, sizeof(ack)); 41 | if (rc != 0) { 42 | return rc; 43 | } 44 | 45 | *end_session = true; 46 | 47 | return 0; 48 | } 49 | 50 | static int handle_vendor_defined_req(SpdmResponderContext* ctx, buffer input, 51 | byte_writer* output) { 52 | uint16_t standard_id; 53 | buffer vendor_id; 54 | buffer payload; 55 | 56 | int rc = SpdmCheckVendorDefinedRequest(&input, /*rest=*/NULL, &standard_id, 57 | &vendor_id.data, &vendor_id.size, 58 | &payload.data, &payload.size); 59 | if (rc != 0) { 60 | return spdm_write_error(SPDM_ERR_INVALID_REQUEST, output); 61 | } 62 | 63 | if (ctx->app_dispatch_fn == NULL) { 64 | return spdm_write_error(SPDM_ERR_UNSPECIFIED, output); 65 | } 66 | 67 | SPDM_VENDOR_DEFINED_REQ_RSP vendor_defined_rsp = {}; 68 | uint16_t rsp_len; 69 | 70 | uint32_t header_len = 71 | sizeof(vendor_defined_rsp) + vendor_id.size + sizeof(rsp_len); 72 | 73 | uint8_t* header = reserve_from_writer(output, header_len); 74 | if (header == NULL) { 75 | return -1; 76 | } 77 | 78 | vendor_defined_rsp.preamble.version = SPDM_THIS_VER; 79 | vendor_defined_rsp.preamble.request_response_code = 80 | SPDM_CODE_VENDOR_DEFINED_RESPONSE; 81 | vendor_defined_rsp.standard_id = standard_id; 82 | vendor_defined_rsp.vendor_id_len = vendor_id.size; 83 | 84 | uint8_t* rsp_bytes = output->data + output->bytes_written; 85 | size_t rsp_bytes_written = output->size - output->bytes_written; 86 | 87 | rc = ctx->app_dispatch_fn(&ctx->session.params.info, standard_id, 88 | vendor_id.data, vendor_id.size, payload.data, 89 | payload.size, rsp_bytes, &rsp_bytes_written); 90 | if (rc != 0) { 91 | return spdm_write_error(SPDM_ERR_UNSPECIFIED, output); 92 | } 93 | 94 | output->bytes_written += rsp_bytes_written; 95 | rsp_len = rsp_bytes_written; 96 | 97 | memcpy(header, &vendor_defined_rsp, sizeof(vendor_defined_rsp)); 98 | header += sizeof(vendor_defined_rsp); 99 | 100 | memcpy(header, vendor_id.data, vendor_id.size); 101 | header += vendor_id.size; 102 | 103 | // TODO(jeffandersen): endianness. 104 | memcpy(header, &rsp_len, sizeof(rsp_len)); 105 | header += sizeof(rsp_len); 106 | 107 | return 0; 108 | } 109 | 110 | int spdm_dispatch_request_session_established(SpdmResponderContext* ctx, 111 | uint8_t code, buffer input, 112 | byte_writer* output, 113 | bool* end_session) { 114 | *end_session = false; 115 | 116 | if (ctx->state != STATE_SESSION_ESTABLISHED) { 117 | return -1; 118 | } 119 | 120 | switch (code) { 121 | case SPDM_CODE_END_SESSION: 122 | return handle_end_session(ctx, input, output, end_session); 123 | case SPDM_CODE_VENDOR_DEFINED_REQUEST: 124 | return handle_vendor_defined_req(ctx, input, output); 125 | default: 126 | return spdm_write_error(SPDM_ERR_INVALID_REQUEST, output); 127 | } 128 | } 129 | -------------------------------------------------------------------------------- /spdm_lite/library/responder/state_waiting_for_finish.c: -------------------------------------------------------------------------------- 1 | // Copyright 2022 Google LLC. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #include 16 | 17 | #include "spdm_lite/common/crypto.h" 18 | #include "spdm_lite/common/error.h" 19 | #include "spdm_lite/common/key_schedule.h" 20 | #include "spdm_lite/common/messages.h" 21 | #include "spdm_lite/common/sign.h" 22 | #include "spdm_lite/common/utils.h" 23 | #include "spdm_lite/common/version.h" 24 | #include "spdm_lite/everparse/SPDMWrapper.h" 25 | #include "spdm_lite/responder/responder.h" 26 | 27 | static int generate_finish_key(const SpdmCryptoSpec* crypto_spec, 28 | const SpdmSessionParams* session, 29 | SPDMRole originator, SpdmHashResult* key) { 30 | SpdmMessageSecrets handshake_secrets; 31 | 32 | int rc = spdm_generate_message_secrets( 33 | crypto_spec, session, SPDM_HANDSHAKE_PHASE, &handshake_secrets); 34 | if (rc != 0) { 35 | goto cleanup; 36 | } 37 | 38 | rc = spdm_generate_finished_key(crypto_spec, originator, &handshake_secrets, 39 | key); 40 | if (rc != 0) { 41 | goto cleanup; 42 | } 43 | 44 | cleanup: 45 | memset(&handshake_secrets, 0, sizeof(handshake_secrets)); 46 | 47 | return rc; 48 | } 49 | 50 | static int validate_finish_hmac(const SpdmCryptoSpec* crypto_spec, 51 | const SpdmSessionParams* session, 52 | const SpdmHashResult* transcript_hash, 53 | const uint8_t* mac) { 54 | SpdmHashResult finish_key; 55 | 56 | int rc = generate_finish_key(crypto_spec, session, 57 | /*originator=*/SPDM_REQUESTER, &finish_key); 58 | if (rc != 0) { 59 | goto cleanup; 60 | } 61 | 62 | rc = spdm_validate_hmac(crypto_spec, &finish_key, transcript_hash, mac); 63 | if (rc != 0) { 64 | goto cleanup; 65 | } 66 | 67 | cleanup: 68 | memset(&finish_key, 0, sizeof(finish_key)); 69 | 70 | return rc; 71 | } 72 | 73 | static int write_finish_rsp(const SpdmCryptoSpec* crypto_spec, 74 | const SpdmSessionParams* session, 75 | SpdmHash* transcript_hash, byte_writer* output) { 76 | SPDM_FINISH_RSP msg; 77 | 78 | memset(&msg, 0, sizeof(msg)); 79 | 80 | msg.preamble.version = SPDM_THIS_VER; 81 | msg.preamble.request_response_code = SPDM_CODE_FINISH_RSP; 82 | 83 | uint8_t* out = reserve_from_writer(output, sizeof(msg)); 84 | if (out == NULL) { 85 | return -1; 86 | } 87 | 88 | memcpy(out, &msg, sizeof(msg)); 89 | 90 | spdm_extend_hash(transcript_hash, &msg, sizeof(msg)); 91 | 92 | return 0; 93 | } 94 | 95 | int spdm_dispatch_request_waiting_for_finish(SpdmResponderContext* ctx, 96 | uint8_t code, buffer input, 97 | byte_writer* output) { 98 | if (ctx->state != STATE_MUTUAL_AUTH_WAITING_FOR_FINISH) { 99 | return -1; 100 | } 101 | 102 | bool sig_included; 103 | uint8_t slot_id; 104 | const uint8_t *sig, *verify_data; 105 | 106 | const uint16_t hash_len = spdm_get_hash_size(ctx->negotiated_algs.hash_alg); 107 | const uint16_t sig_len = 108 | spdm_get_asym_signature_size(ctx->negotiated_algs.asym_verify_alg); 109 | 110 | int rc = SpdmCheckFinish(&input, /*rest=*/NULL, hash_len, sig_len, 111 | &sig_included, &slot_id, &sig, &verify_data); 112 | if (rc != 0) { 113 | return spdm_write_error(SPDM_ERR_INVALID_REQUEST, output); 114 | } 115 | 116 | if (!sig_included) { 117 | return spdm_write_error(SPDM_ERR_INVALID_REQUEST, output); 118 | } 119 | 120 | if (slot_id != 0xFF) { 121 | return spdm_write_error(SPDM_ERR_INVALID_REQUEST, output); 122 | } 123 | 124 | SpdmHash transcript_hash = ctx->session.transcript_hash; 125 | 126 | rc = spdm_extend_hash_with_pub_key(&ctx->crypto_spec, &transcript_hash, 127 | &ctx->session.params.info.peer_pub_key); 128 | if (rc != 0) { 129 | return rc; 130 | } 131 | 132 | spdm_extend_hash(&transcript_hash, input.data, sizeof(SPDM_FINISH)); 133 | 134 | SpdmHashResult transcript_hash_result; 135 | rc = spdm_get_hash(&transcript_hash, &transcript_hash_result); 136 | if (rc != 0) { 137 | return rc; 138 | } 139 | 140 | rc = spdm_verify(&ctx->crypto_spec, &ctx->session.params.info.peer_pub_key, 141 | /*signer_role=*/SPDM_REQUESTER, &transcript_hash_result, 142 | /*context=*/"finish signing", sig, sig_len); 143 | if (rc != 0) { 144 | return spdm_write_error(SPDM_ERR_INVALID_REQUEST, output); 145 | } 146 | 147 | spdm_extend_hash(&transcript_hash, sig, sig_len); 148 | rc = spdm_get_hash(&transcript_hash, &transcript_hash_result); 149 | if (rc != 0) { 150 | return rc; 151 | } 152 | 153 | rc = validate_finish_hmac(&ctx->crypto_spec, &ctx->session.params, 154 | &transcript_hash_result, verify_data); 155 | if (rc != 0) { 156 | return spdm_write_error(SPDM_ERR_INVALID_REQUEST, output); 157 | } 158 | 159 | spdm_extend_hash(&transcript_hash, verify_data, hash_len); 160 | 161 | rc = write_finish_rsp(&ctx->crypto_spec, &ctx->session.params, 162 | &transcript_hash, output); 163 | if (rc != 0) { 164 | return rc; 165 | } 166 | 167 | // Finalize TH2. 168 | rc = spdm_get_hash(&transcript_hash, &ctx->session.params.th_2); 169 | if (rc != 0) { 170 | return rc; 171 | } 172 | 173 | ctx->session.transcript_hash = transcript_hash; 174 | ctx->state = STATE_SESSION_ESTABLISHED; 175 | 176 | return 0; 177 | } 178 | -------------------------------------------------------------------------------- /spdm_lite/library/responder/state_waiting_for_get_capabilities.c: -------------------------------------------------------------------------------- 1 | // Copyright 2022 Google LLC. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #include 16 | 17 | #include "spdm_lite/common/error.h" 18 | #include "spdm_lite/common/messages.h" 19 | #include "spdm_lite/common/transcript.h" 20 | #include "spdm_lite/common/utils.h" 21 | #include "spdm_lite/common/version.h" 22 | #include "spdm_lite/everparse/SPDMWrapper.h" 23 | #include "spdm_lite/responder/responder.h" 24 | 25 | static int write_capabilities(SpdmResponderContext* ctx, 26 | byte_writer* output) { 27 | SPDM_CAPABILITIES msg; 28 | int rc; 29 | 30 | memset(&msg, 0, sizeof(msg)); 31 | 32 | msg.preamble.version = SPDM_THIS_VER; 33 | msg.preamble.request_response_code = SPDM_CODE_CAPABILITIES; 34 | msg.ct_exponent = 0; 35 | msg.data_transfer_size = ctx->responder_caps.data_transfer_size; 36 | msg.max_spdm_message_size = msg.data_transfer_size; 37 | 38 | msg.flags_ENCRYPT_CAP = 1; 39 | msg.flags_MAC_CAP = 1; 40 | msg.flags_KEY_EX_CAP = 1; 41 | msg.flags_ALIAS_CERT_CAP = 1; 42 | 43 | rc = write_to_writer(output, &msg, sizeof(msg)); 44 | if (rc != 0) { 45 | return rc; 46 | } 47 | 48 | return spdm_append_to_transcript(&ctx->negotiation_transcript, &msg, 49 | sizeof(msg)); 50 | } 51 | 52 | int spdm_dispatch_request_waiting_for_get_capabilities( 53 | SpdmResponderContext* ctx, uint8_t code, buffer input, 54 | byte_writer* output) { 55 | int rc; 56 | SPDM_GET_CAPABILITIES msg; 57 | 58 | if (ctx->state != STATE_WAITING_FOR_GET_CAPABILITIES) { 59 | return -1; 60 | } 61 | 62 | if (code != SPDM_CODE_GET_CAPABILITIES) { 63 | return spdm_write_error(SPDM_ERR_INVALID_REQUEST, output); 64 | } 65 | 66 | rc = SpdmCheckGetCapabilities(&input, /*rest=*/NULL); 67 | if (rc != 0) { 68 | return spdm_write_error(SPDM_ERR_INVALID_REQUEST, output); 69 | } 70 | 71 | memcpy(&msg, input.data, sizeof(msg)); 72 | 73 | memset(&ctx->requester_caps, 0, sizeof(ctx->requester_caps)); 74 | ctx->requester_caps.data_transfer_size = msg.data_transfer_size; 75 | 76 | rc = spdm_append_to_transcript(&ctx->negotiation_transcript, input.data, 77 | input.size); 78 | 79 | rc = write_capabilities(ctx, output); 80 | if (rc != 0) { 81 | return spdm_write_error(SPDM_ERR_UNSPECIFIED, output); 82 | } 83 | 84 | ctx->state = STATE_WAITING_FOR_NEGOTIATE_ALGORITHMS; 85 | 86 | return 0; 87 | } 88 | -------------------------------------------------------------------------------- /spdm_lite/library/responder/state_waiting_for_get_version.c: -------------------------------------------------------------------------------- 1 | // Copyright 2022 Google LLC. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #include 16 | 17 | #include "spdm_lite/common/error.h" 18 | #include "spdm_lite/common/messages.h" 19 | #include "spdm_lite/common/transcript.h" 20 | #include "spdm_lite/common/utils.h" 21 | #include "spdm_lite/everparse/SPDMWrapper.h" 22 | #include "spdm_lite/responder/responder.h" 23 | 24 | static int write_version(SpdmResponderContext* ctx, byte_writer* output) { 25 | SPDM_VERSION version_msg = {}; 26 | SPDM_VersionNumberEntry version_entry_msg = {}; 27 | uint32_t output_len; 28 | uint8_t* output_buf; 29 | uint8_t* output_ptr; 30 | 31 | version_msg.preamble.version = 0x10; 32 | version_msg.preamble.request_response_code = SPDM_CODE_VERSION; 33 | version_msg.version_number_entry_count = 1; 34 | version_entry_msg.major_version = 1; 35 | version_entry_msg.minor_version = 2; 36 | 37 | output_len = sizeof(version_msg) + sizeof(version_entry_msg); 38 | 39 | output_buf = reserve_from_writer(output, output_len); 40 | if (output_buf == NULL) { 41 | return -1; 42 | } 43 | 44 | output_ptr = output_buf; 45 | 46 | memcpy(output_ptr, &version_msg, sizeof(version_msg)); 47 | output_ptr += sizeof(version_msg); 48 | 49 | memcpy(output_ptr, &version_entry_msg, sizeof(version_entry_msg)); 50 | output_ptr += sizeof(version_entry_msg); 51 | 52 | return spdm_append_to_transcript(&ctx->negotiation_transcript, output_buf, 53 | output_len); 54 | } 55 | 56 | int spdm_dispatch_request_waiting_for_get_version(SpdmResponderContext* ctx, 57 | uint8_t code, buffer input, 58 | byte_writer* output) { 59 | int rc; 60 | 61 | if (ctx->state != STATE_WAITING_FOR_GET_VERSION) { 62 | return -1; 63 | } 64 | 65 | if (code != SPDM_CODE_GET_VERSION) { 66 | return spdm_write_error(SPDM_ERR_INVALID_REQUEST, output); 67 | } 68 | 69 | rc = SpdmCheckGetVersion(&input, /*rest=*/NULL); 70 | if (rc != 0) { 71 | return spdm_write_error(SPDM_ERR_INVALID_REQUEST, output); 72 | } 73 | 74 | rc = spdm_append_to_transcript(&ctx->negotiation_transcript, input.data, 75 | input.size); 76 | if (rc != 0) { 77 | return rc; 78 | } 79 | 80 | rc = write_version(ctx, output); 81 | if (rc != 0) { 82 | return spdm_write_error(SPDM_ERR_UNSPECIFIED, output); 83 | } 84 | 85 | ctx->state = STATE_WAITING_FOR_GET_CAPABILITIES; 86 | 87 | return 0; 88 | } 89 | -------------------------------------------------------------------------------- /spdm_lite/library/responder/state_waiting_for_negotiate_algorithms.c: -------------------------------------------------------------------------------- 1 | // Copyright 2022 Google LLC. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #include 16 | #include 17 | 18 | #include "spdm_lite/common/algorithms.h" 19 | #include "spdm_lite/common/error.h" 20 | #include "spdm_lite/common/messages.h" 21 | #include "spdm_lite/common/transcript.h" 22 | #include "spdm_lite/common/utils.h" 23 | #include "spdm_lite/common/version.h" 24 | #include "spdm_lite/everparse/SPDMWrapper.h" 25 | #include "spdm_lite/responder/responder.h" 26 | 27 | static int write_algorithms(const SpdmSupportedAlgs* negotiated_algs, 28 | byte_writer* output, bool support_opaque_data_fmt_1, 29 | bool support_spdm_key_schedule, buffer* written) { 30 | SPDM_ALGORITHMS algs_msg = {}; 31 | SPDM_AlgStruct_DHE dhe_msg; 32 | SPDM_AlgStruct_AEAD aead_msg; 33 | SPDM_AlgStruct_BaseAsym asym_msg; 34 | SPDM_AlgStruct_KeySchedule keyschedule_msg; 35 | uint8_t* output_ptr; 36 | 37 | algs_msg.preamble.version = SPDM_THIS_VER; 38 | algs_msg.preamble.request_response_code = SPDM_CODE_ALGORITHMS; 39 | algs_msg.param_1_alg_struct_count = 4; 40 | algs_msg.length = sizeof(algs_msg) + sizeof(dhe_msg) + sizeof(aead_msg) + 41 | sizeof(asym_msg) + sizeof(keyschedule_msg); 42 | 43 | if (support_opaque_data_fmt_1) { 44 | algs_msg.other_params_opaque_data_fmt_1 = 1; 45 | } 46 | 47 | spdm_write_algs(negotiated_algs, /*is_resp=*/true, support_spdm_key_schedule, 48 | &algs_msg.asym_hash_algs, &dhe_msg, &aead_msg, &asym_msg, 49 | &keyschedule_msg); 50 | 51 | output_ptr = reserve_from_writer(output, algs_msg.length); 52 | if (output_ptr == NULL) { 53 | return -1; 54 | } 55 | 56 | written->data = output_ptr; 57 | written->size = algs_msg.length; 58 | 59 | memcpy(output_ptr, &algs_msg, sizeof(algs_msg)); 60 | output_ptr += sizeof(algs_msg); 61 | 62 | memcpy(output_ptr, &dhe_msg, sizeof(dhe_msg)); 63 | output_ptr += sizeof(dhe_msg); 64 | 65 | memcpy(output_ptr, &aead_msg, sizeof(aead_msg)); 66 | output_ptr += sizeof(aead_msg); 67 | 68 | memcpy(output_ptr, &asym_msg, sizeof(asym_msg)); 69 | output_ptr += sizeof(asym_msg); 70 | 71 | memcpy(output_ptr, &keyschedule_msg, sizeof(keyschedule_msg)); 72 | output_ptr += sizeof(keyschedule_msg); 73 | 74 | return 0; 75 | } 76 | 77 | int spdm_dispatch_request_waiting_for_negotiate_algorithms( 78 | SpdmResponderContext* ctx, uint8_t code, buffer input, 79 | byte_writer* output) { 80 | int rc; 81 | SPDM_NEGOTIATE_ALGORITHMS msg; 82 | const uint8_t* ext_asym_algs; 83 | uint32_t ext_asym_count; 84 | const uint8_t* ext_hash_algs; 85 | uint32_t ext_hash_algs_count; 86 | buffer alg_structs; 87 | uint32_t alg_structs_count; 88 | SpdmSupportedAlgs my_algs; 89 | SpdmSupportedAlgs their_algs; 90 | SpdmSupportedAlgs common_algs; 91 | bool support_opaque_data_fmt_1; 92 | bool support_spdm_key_schedule; 93 | buffer written; 94 | 95 | if (ctx->state != STATE_WAITING_FOR_NEGOTIATE_ALGORITHMS) { 96 | return -1; 97 | } 98 | 99 | if (code != SPDM_CODE_NEGOTIATE_ALGORITHMS) { 100 | return spdm_write_error(SPDM_ERR_INVALID_REQUEST, output); 101 | } 102 | 103 | rc = SpdmCheckNegotiateAlgorithms(&input, /*rest=*/NULL, &ext_asym_algs, 104 | &ext_asym_count, &ext_hash_algs, 105 | &ext_hash_algs_count, &alg_structs.data, 106 | &alg_structs_count, &alg_structs.size); 107 | if (rc != 0) { 108 | return spdm_write_error(SPDM_ERR_INVALID_REQUEST, output); 109 | } 110 | 111 | memcpy(&msg, input.data, sizeof(msg)); 112 | 113 | support_opaque_data_fmt_1 = (msg.other_params_opaque_data_fmt_1 == 1); 114 | 115 | spdm_get_my_supported_algs(&ctx->crypto_spec, &ctx->responder_pub_key, 116 | &my_algs); 117 | rc = spdm_get_their_supported_algs( 118 | &msg.asym_hash_algs, alg_structs, alg_structs_count, 119 | /*is_resp=*/false, &their_algs, &support_spdm_key_schedule); 120 | if (rc != 0) { 121 | return spdm_write_error(SPDM_ERR_INVALID_REQUEST, output); 122 | } 123 | 124 | spdm_get_negotiated_algs(&my_algs, &their_algs, &common_algs, 125 | &ctx->negotiated_algs); 126 | 127 | rc = spdm_append_to_transcript(&ctx->negotiation_transcript, input.data, 128 | input.size); 129 | if (rc != 0) { 130 | return rc; 131 | } 132 | 133 | rc = write_algorithms(&common_algs, output, support_opaque_data_fmt_1, 134 | support_spdm_key_schedule, &written); 135 | if (rc != 0) { 136 | return spdm_write_error(SPDM_ERR_UNSPECIFIED, output); 137 | } 138 | 139 | rc = spdm_append_to_transcript(&ctx->negotiation_transcript, written.data, 140 | written.size); 141 | if (rc != 0) { 142 | return rc; 143 | } 144 | 145 | ctx->state = STATE_WAITING_FOR_KEY_EXCHANGE; 146 | 147 | return 0; 148 | } 149 | -------------------------------------------------------------------------------- /spdm_lite/samples/include/spdm_lite/samples/requester_app.h: -------------------------------------------------------------------------------- 1 | // Copyright 2022 Google LLC. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #ifndef SPDM_LITE_SAMPLES_REQUESTER_APP_H_ 16 | #define SPDM_LITE_SAMPLES_REQUESTER_APP_H_ 17 | 18 | #include 19 | 20 | #ifdef __cplusplus 21 | extern "C" { 22 | #endif // __cplusplus 23 | 24 | // Should be called first. Initializes the session. 25 | int sample_app_initialize_spdm_session(void); 26 | 27 | // Passes `input` to the Responder via a secure SPDM channel, which performs 28 | // ROT128 on the input. Writes the result to `output`. 29 | int sample_app_rot128_byte(uint8_t input, uint8_t* output); 30 | 31 | // Tears down the session. 32 | int sample_app_end_spdm_session(void); 33 | 34 | #ifdef __cplusplus 35 | } 36 | #endif // __cplusplus 37 | 38 | #endif // SPDM_LITE_SAMPLES_REQUESTER_APP_H_ 39 | -------------------------------------------------------------------------------- /spdm_lite/samples/include/spdm_lite/samples/responder_app.h: -------------------------------------------------------------------------------- 1 | // Copyright 2022 Google LLC. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #ifndef SPDM_LITE_SAMPLES_RESPONDER_APP_H_ 16 | #define SPDM_LITE_SAMPLES_RESPONDER_APP_H_ 17 | 18 | // This file declares an entry-point for a sample SPDM app that performs ROT-128 19 | // on a given uint8_t and returns the result. 20 | // 21 | // Application requests are required to be encapsulated within a vendor-defined 22 | // command whose standard_id is 0x1701 and whose vendor_id is 0x42. 23 | 24 | #include 25 | #include 26 | #include 27 | 28 | #define SAMPLE_APP_STANDARD_ID 0x1701 29 | #define SAMPLE_APP_VENDOR_ID 0x42 30 | 31 | #ifdef __cplusplus 32 | extern "C" { 33 | #endif // __cplusplus 34 | 35 | // Dispatches an incoming SPDM request. `is_secure` indicates whether `req` 36 | // holds an encrypted or plaintext SPDM request. `rsp_size` is an input/output 37 | // argument. 38 | int sample_app_dispatch_spdm_request(bool is_secure, const uint8_t* req, 39 | size_t req_size, uint8_t* rsp, 40 | size_t* rsp_size); 41 | 42 | #ifdef __cplusplus 43 | } 44 | #endif // __cplusplus 45 | 46 | #endif // SPDM_LITE_SAMPLES_RESPONDER_APP_H_ 47 | -------------------------------------------------------------------------------- /spdm_lite/samples/requester_app.c: -------------------------------------------------------------------------------- 1 | // Copyright 2022 Google LLC. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #include "spdm_lite/samples/requester_app.h" 16 | 17 | #include 18 | 19 | #include "spdm_lite/samples/responder_app.h" 20 | #include "spdm_lite/common/crypto_types.h" 21 | #include "spdm_lite/crypto_impl/mbedtls_crypto.h" 22 | #include "spdm_lite/crypto_impl/mbedtls_sign.h" 23 | #include "spdm_lite/crypto_impl/raw_serialize.h" 24 | #include "spdm_lite/requester/requester.h" 25 | 26 | static SpdmSessionParams global_session; 27 | static bool global_session_initialized; 28 | 29 | // Amount of memory to allocate for scratch-space for each request. 30 | #define SCRATCH_SIZE 384 31 | 32 | // Sends a request to the Responder. `is_secure_msg` indicates whether `req` 33 | // holds an encrypted payload or whether it is a plaintext SPDM request. This 34 | // value should be reflected onto the transport, so the Responder can properly 35 | // handle the request. 36 | int dispatch_spdm_request(void* ctx, bool is_secure_msg, const uint8_t* req, 37 | size_t req_size, uint8_t* rsp, size_t* rsp_size) { 38 | // This implementation ignores `ctx`, as it is unneeded. 39 | 40 | return sample_app_dispatch_spdm_request(is_secure_msg, req, req_size, rsp, 41 | rsp_size); 42 | } 43 | 44 | static SpdmDispatchRequestCtx* get_global_requester_ctx(void) { 45 | static SpdmDispatchRequestCtx req_ctx; 46 | static bool initialized = false; 47 | 48 | if (!initialized) { 49 | req_ctx.crypto_spec = MBEDTLS_BASE_CRYPTO_SPEC; 50 | req_ctx.crypto_spec.sign_with_priv_key = spdm_mbedtls_sign_with_priv_key; 51 | req_ctx.crypto_spec.serialize_pub_key = spdm_raw_serialize_asym_key; 52 | req_ctx.crypto_spec.deserialize_pub_key = spdm_raw_serialize_asym_key; 53 | 54 | req_ctx.dispatch_fn = dispatch_spdm_request; 55 | req_ctx.dispatch_ctx = NULL; // Unused by `dispatch_spdm_request`. 56 | 57 | initialized = true; 58 | } 59 | 60 | return &req_ctx; 61 | } 62 | 63 | int sample_app_initialize_spdm_session(void) { 64 | if (global_session_initialized) { 65 | fprintf(stderr, 66 | "sample_app_initialize_spdm_session failed: global session already " 67 | "initialized\n"); 68 | return -1; 69 | } 70 | 71 | SpdmAsymPrivKey requester_priv_key; 72 | uint8_t scratch_mem[SCRATCH_SIZE]; 73 | 74 | SpdmRequesterSessionParams params = { 75 | .dispatch_ctx = get_global_requester_ctx(), 76 | .requester_priv_key_ctx = &requester_priv_key, 77 | .scratch = {scratch_mem, sizeof(scratch_mem)}, 78 | }; 79 | 80 | int rc = spdm_generate_asym_keypair(SPDM_ASYM_ECDSA_ECC_NIST_P256, 81 | &requester_priv_key, 82 | ¶ms.requester_pub_key); 83 | if (rc != 0) { 84 | fprintf(stderr, "spdm_generate_asym_keypair failed on line %d, err %d\n", 85 | __LINE__, rc); 86 | return rc; 87 | } 88 | 89 | rc = spdm_establish_session(¶ms, &global_session); 90 | if (rc != 0) { 91 | fprintf(stderr, "spdm_establish_session failed on line %d, err %d\n", 92 | __LINE__, rc); 93 | return rc; 94 | } 95 | 96 | global_session_initialized = true; 97 | 98 | return 0; 99 | } 100 | 101 | int sample_app_rot128_byte(uint8_t input, uint8_t* output) { 102 | if (!global_session_initialized) { 103 | fprintf(stderr, 104 | "sample_app_rot128_byte failed: global session not initialized\n"); 105 | return -1; 106 | } 107 | 108 | uint8_t scratch_mem[SCRATCH_SIZE]; 109 | SpdmScratchSpace scratch_space = {scratch_mem, sizeof(scratch_mem)}; 110 | 111 | uint16_t standard_id = SAMPLE_APP_STANDARD_ID; 112 | uint8_t vendor_id = SAMPLE_APP_VENDOR_ID; 113 | 114 | size_t output_size = sizeof(*output); 115 | 116 | int rc = spdm_dispatch_app_request(get_global_requester_ctx(), scratch_space, 117 | &global_session, standard_id, &vendor_id, 118 | sizeof(vendor_id), &input, sizeof(input), 119 | output, &output_size); 120 | if (rc != 0) { 121 | fprintf(stderr, "spdm_dispatch_app_request failed on line %d, err %d\n", 122 | __LINE__, rc); 123 | return rc; 124 | } 125 | 126 | if (output_size != sizeof(*output)) { 127 | fprintf( 128 | stderr, 129 | "sample_app_rot128_byte failed: not enough data written (expected %lu, " 130 | "got %zu\n", 131 | sizeof(*output), output_size); 132 | return -1; 133 | } 134 | 135 | return 0; 136 | } 137 | 138 | int sample_app_end_spdm_session(void) { 139 | if (!global_session_initialized) { 140 | fprintf( 141 | stderr, 142 | "sample_app_end_spdm_session failed: global session not initialized\n"); 143 | return -1; 144 | } 145 | 146 | uint8_t scratch_mem[SCRATCH_SIZE]; 147 | SpdmScratchSpace scratch_space = {scratch_mem, sizeof(scratch_mem)}; 148 | 149 | int rc = spdm_end_session(get_global_requester_ctx(), scratch_space, 150 | &global_session); 151 | if (rc != 0) { 152 | fprintf(stderr, "spdm_end_session failed on line %d, err %d\n", __LINE__, 153 | rc); 154 | return rc; 155 | } 156 | 157 | global_session_initialized = false; 158 | 159 | return 0; 160 | } 161 | -------------------------------------------------------------------------------- /spdm_lite/samples/responder_app.c: -------------------------------------------------------------------------------- 1 | // Copyright 2022 Google LLC. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #include "spdm_lite/samples/responder_app.h" 16 | 17 | #include 18 | 19 | #include "spdm_lite/crypto_impl/mbedtls_crypto.h" 20 | #include "spdm_lite/crypto_impl/mbedtls_sign.h" 21 | #include "spdm_lite/crypto_impl/raw_serialize.h" 22 | #include "spdm_lite/responder/responder.h" 23 | 24 | // Handle application requests that comes over a secure SPDM session. 25 | // `session_info` holds information such as the peer's public key and the 26 | // negotiated algorithms. 27 | static int handle_rot13_request(const SpdmSessionInfo* session_info, 28 | uint16_t standard_id, const uint8_t* vendor_id, 29 | size_t vendor_id_size, const uint8_t* payload, 30 | size_t payload_size, uint8_t* output, 31 | size_t* output_size) { 32 | if (standard_id != SAMPLE_APP_STANDARD_ID) { 33 | fprintf(stderr, 34 | "handle_rot13_request failed, expected standard_id %d, got %d\n", 35 | SAMPLE_APP_STANDARD_ID, standard_id); 36 | return -1; 37 | } 38 | 39 | if (vendor_id_size != 1 || vendor_id[0] != SAMPLE_APP_VENDOR_ID) { 40 | fprintf(stderr, 41 | "handle_rot13_request failed, expected vendor_id %d, got %zu bytes " 42 | "starting with %d\n", 43 | SAMPLE_APP_VENDOR_ID, vendor_id_size, vendor_id[0]); 44 | return -1; 45 | } 46 | 47 | if (payload_size != 1 || *output_size < 1) { 48 | fprintf(stderr, 49 | "handle_rot13_request failed, expected payload size %d, got %zu " 50 | "with output buffer size %zu\n", 51 | 1, payload_size, *output_size); 52 | return -1; 53 | } 54 | 55 | // Perform ROT-128 on the input. 56 | uint8_t input_val = payload[0]; 57 | uint8_t output_val = input_val + 128; 58 | 59 | *output = output_val; 60 | *output_size = 1; 61 | 62 | return 0; 63 | } 64 | 65 | static SpdmResponderContext* get_global_responder_ctx(void) { 66 | static SpdmResponderContext ctx; 67 | static SpdmAsymPrivKey responder_priv_key; 68 | static bool initialized; 69 | 70 | if (!initialized) { 71 | SpdmCryptoSpec crypto_spec = MBEDTLS_BASE_CRYPTO_SPEC; 72 | crypto_spec.sign_with_priv_key = spdm_mbedtls_sign_with_priv_key; 73 | crypto_spec.serialize_pub_key = spdm_raw_serialize_asym_key; 74 | crypto_spec.deserialize_pub_key = spdm_raw_serialize_asym_key; 75 | 76 | // Place-holder for unimplemented features like max transport size. 77 | SpdmCapabilities responder_caps = {}; 78 | 79 | SpdmAsymPubKey responder_pub_key; 80 | int rc = spdm_generate_asym_keypair( 81 | SPDM_ASYM_ECDSA_ECC_NIST_P256, &responder_priv_key, &responder_pub_key); 82 | if (rc != 0) { 83 | fprintf(stderr, "spdm_generate_asym_keypair failed on line %d, err %d\n", 84 | __LINE__, rc); 85 | return NULL; 86 | } 87 | 88 | rc = spdm_initialize_responder_context( 89 | &ctx, &crypto_spec, &responder_caps, &responder_pub_key, 90 | &responder_priv_key, handle_rot13_request); 91 | if (rc != 0) { 92 | fprintf(stderr, 93 | "spdm_initialize_responder_context failed on line %d, err %d\n", 94 | __LINE__, rc); 95 | return NULL; 96 | } 97 | 98 | initialized = true; 99 | } 100 | 101 | return &ctx; 102 | } 103 | 104 | int sample_app_dispatch_spdm_request(bool is_secure, const uint8_t* req, 105 | size_t req_size, uint8_t* rsp, 106 | size_t* rsp_size) { 107 | SpdmResponderContext* ctx = get_global_responder_ctx(); 108 | if (ctx == NULL) { 109 | return -1; 110 | } 111 | 112 | return spdm_dispatch_request(ctx, is_secure, req, req_size, rsp, rsp_size); 113 | } 114 | -------------------------------------------------------------------------------- /spdm_lite/testing/include/spdm_lite/testing/add_2_app.h: -------------------------------------------------------------------------------- 1 | // Copyright 2022 Google LLC. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #ifndef SPDM_LITE_TESTING_ADD_2_APP_H_ 16 | #define SPDM_LITE_TESTING_ADD_2_APP_H_ 17 | 18 | #include "spdm_lite/common/crypto_types.h" 19 | #include "spdm_lite/common/defs.h" 20 | #include "spdm_lite/common/session_types.h" 21 | 22 | #ifdef __cplusplus 23 | extern "C" { 24 | #endif // __cplusplus 25 | 26 | typedef struct { 27 | SpdmSessionId session_id; 28 | uint8_t asym_sign_alg; 29 | uint8_t asym_verify_alg; 30 | uint8_t hash_alg; 31 | uint8_t dhe_alg; 32 | uint8_t aead_alg; 33 | uint32_t num; 34 | // uint8_t pub_key[...] 35 | } PACKED Add2AppResponse; 36 | 37 | // App that echoes back the session ID, negotiated algs, and public key, as well 38 | // as the given uint32 double-incremented. 39 | int add_2_app_fn(const SpdmSessionInfo* session_info, uint16_t standard_id, 40 | const uint8_t* vendor_id, size_t vendor_id_size, 41 | const uint8_t* payload, size_t payload_size, uint8_t* output, 42 | size_t* output_size); 43 | 44 | #ifdef __cplusplus 45 | } 46 | #endif // __cplusplus 47 | 48 | #endif // SPDM_LITE_TESTING_ADD_2_APP_H_ 49 | -------------------------------------------------------------------------------- /spdm_lite/testing/include/spdm_lite/testing/dummy_crypto.h: -------------------------------------------------------------------------------- 1 | // Copyright 2022 Google LLC. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #ifndef SPDM_LITE_TESTING_DUMMY_CRYPTO_H_ 16 | #define SPDM_LITE_TESTING_DUMMY_CRYPTO_H_ 17 | 18 | #include "spdm_lite/common/crypto_types.h" 19 | 20 | #ifdef __cplusplus 21 | extern "C" { 22 | #endif // __cplusplus 23 | 24 | // Initializes a dummy P256 key. 25 | int spdm_fill_dummy_asym_p256_keypair(SpdmAsymPubKey* pub_key); 26 | 27 | // An implementation of the spdm-lite crypto spec that does no real 28 | // cryptography. Includes serialization routines that mirror the internal 29 | // representation onto the wire. 30 | extern const SpdmCryptoSpec DUMMY_CRYPTO_SPEC; 31 | 32 | #ifdef __cplusplus 33 | } 34 | #endif // __cplusplus 35 | 36 | #endif // SPDM_LITE_TESTING_DUMMY_CRYPTO_H_ 37 | -------------------------------------------------------------------------------- /spdm_lite/testing/include/spdm_lite/testing/host_context.h: -------------------------------------------------------------------------------- 1 | // Copyright 2022 Google LLC. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #ifndef SPDM_LITE_TESTING_HOST_CONTEXT_H_ 16 | #define SPDM_LITE_TESTING_HOST_CONTEXT_H_ 17 | 18 | #include "spdm_lite/common/crypto_types.h" 19 | #include "spdm_lite/crypto_impl/mbedtls_sign.h" 20 | #include "spdm_lite/requester/requester.h" 21 | #include "spdm_lite/responder/responder.h" 22 | 23 | #ifdef __cplusplus 24 | extern "C" { 25 | #endif // __cplusplus 26 | 27 | #define SPDM_HOST_DATA_TRANSFER_SIZE 1024 28 | 29 | const SpdmCapabilities HOST_CAPS = { 30 | .data_transfer_size = SPDM_HOST_DATA_TRANSFER_SIZE, 31 | }; 32 | 33 | // Returns a pointer to a crypto spec that includes the base mbedtls 34 | // functionality, along with the signing and serialization helpers. 35 | const SpdmCryptoSpec* get_mbedtls_crypto_spec(void); 36 | 37 | void initialize_dispatch_req_ctx(SpdmResponderContext* target_responder, 38 | SpdmDispatchRequestCtx* req_ctx); 39 | 40 | void initialize_host_responder_context( 41 | SpdmAsymPrivKey* priv_key, SpdmAsymPubKey* pub_key, 42 | SpdmResponderContext* ctx, 43 | spdm_app_dispatch_request_fn app_fn); 44 | 45 | #ifdef __cplusplus 46 | } 47 | #endif // __cplusplus 48 | 49 | #endif // SPDM_LITE_TESTING_HOST_CONTEXT_H_ 50 | -------------------------------------------------------------------------------- /spdm_lite/testing/include/spdm_lite/testing/utils.h: -------------------------------------------------------------------------------- 1 | // Copyright 2022 Google LLC. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #ifndef SPDM_LITE_TESTING_UTILS_H_ 16 | #define SPDM_LITE_TESTING_UTILS_H_ 17 | 18 | #include 19 | #include 20 | 21 | #include "spdm_lite/common/crypto_types.h" 22 | #include "spdm_lite/common/session_types.h" 23 | #include "spdm_lite/common/utils.h" 24 | #include "spdm_lite/crypto_impl/mbedtls_sign.h" 25 | #include "spdm_lite/responder/responder.h" 26 | 27 | void ExtendHash(SpdmHash* hash, const std::vector& b); 28 | std::vector GetDigest(const uint8_t* data, uint32_t len); 29 | std::vector GetDigest(const SpdmHash& hash); 30 | SpdmHashResult GetHashResult(const std::vector& digest); 31 | 32 | template ::value>> 33 | inline buffer MakeBuffer(T& t) { 34 | return {reinterpret_cast(&t), sizeof(t)}; 35 | } 36 | 37 | buffer MakeBuffer(std::vector& vec); 38 | byte_writer MakeWriter(std::vector& vec); 39 | 40 | int DispatchRequest(SpdmResponderContext* ctx, std::vector& req, 41 | std::vector* rsp = nullptr); 42 | 43 | int DispatchSecureRequest(SpdmResponderContext* ctx, SpdmSessionPhase phase, 44 | std::vector& req, 45 | std::vector* rsp = nullptr); 46 | 47 | std::vector MakeGetVersion(); 48 | std::vector MakeGetCapabilities(); 49 | std::vector MakeNegotiateAlgorithms(); 50 | std::vector MakeGetPubKey(); 51 | std::vector MakeGivePubKey(const SpdmAsymPubKey& pub_key); 52 | std::vector MakeKeyExchange(uint8_t req_session_id[2], 53 | const SpdmDhePubKey& dhe_pub_key); 54 | std::vector MakeFinish(SpdmHash* transcript_hash, 55 | const SpdmSessionParams& session, 56 | SpdmAsymPrivKey& req_priv_key); 57 | std::vector MakeEndSession(); 58 | 59 | int GetSecureMessageKeys(const SpdmSessionParams& session, SPDMRole originator, 60 | SpdmSessionPhase phase, SpdmAeadKeys* keys); 61 | 62 | int EncryptMessage(const std::vector& message, 63 | const SpdmSessionParams& session, SPDMRole my_role, 64 | SpdmSessionPhase phase, std::vector* output); 65 | 66 | #endif // SPDM_LITE_TESTING_UTILS_H_ 67 | -------------------------------------------------------------------------------- /spdm_lite/testing/library/add_2_app.c: -------------------------------------------------------------------------------- 1 | // Copyright 2022 Google LLC. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #include "spdm_lite/testing/add_2_app.h" 16 | 17 | #include 18 | 19 | #include "spdm_lite/common/crypto_types.h" 20 | 21 | int add_2_app_fn(const SpdmSessionInfo* session_info, uint16_t standard_id, 22 | const uint8_t* vendor_id, size_t vendor_id_size, 23 | const uint8_t* payload, size_t payload_size, uint8_t* output, 24 | size_t* output_size) { 25 | Add2AppResponse rsp = {}; 26 | 27 | if (payload_size != sizeof(rsp.num)) { 28 | return -1; 29 | } 30 | 31 | memcpy(&rsp.num, payload, sizeof(rsp.num)); 32 | 33 | rsp.num += 2; 34 | 35 | rsp.session_id = session_info->session_id; 36 | rsp.asym_sign_alg = session_info->negotiated_algs.asym_sign_alg; 37 | rsp.asym_verify_alg = session_info->negotiated_algs.asym_verify_alg; 38 | rsp.hash_alg = session_info->negotiated_algs.hash_alg; 39 | rsp.dhe_alg = session_info->negotiated_algs.dhe_alg; 40 | rsp.aead_alg = session_info->negotiated_algs.aead_alg; 41 | 42 | const SpdmAsymPubKey* peer_key = &session_info->peer_pub_key; 43 | 44 | uint32_t rsp_size = sizeof(rsp) + peer_key->size; 45 | if (*output_size < rsp_size) { 46 | return -1; 47 | } 48 | 49 | memcpy(output, &rsp, sizeof(rsp)); 50 | output += sizeof(rsp); 51 | 52 | // Don't perform any serialization, just bounce the peer's public key over the 53 | // wire in its internal representation. 54 | memcpy(output, peer_key->data, peer_key->size); 55 | 56 | *output_size = rsp_size; 57 | 58 | return 0; 59 | } 60 | -------------------------------------------------------------------------------- /spdm_lite/testing/library/dummy_crypto.c: -------------------------------------------------------------------------------- 1 | // Copyright 2022 Google LLC. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #include "spdm_lite/testing/dummy_crypto.h" 16 | 17 | #include 18 | 19 | #include "spdm_lite/common/crypto_types.h" 20 | #include "spdm_lite/crypto_impl/raw_serialize.h" 21 | 22 | static int NonRandom(uint8_t* data, uint32_t len) { 23 | for (int i = 0; i < len; ++i) { 24 | data[i] = i; 25 | } 26 | return 0; 27 | } 28 | 29 | static void InitializeHash(void* ctx, SpdmHashAlgorithm alg) {} 30 | 31 | static void ExtendHash(void* ctx, SpdmHashAlgorithm alg, const uint8_t* data, 32 | uint32_t len) {} 33 | 34 | static int GetHash(void* ctx, SpdmHashAlgorithm alg, uint8_t* digest) { 35 | return NonRandom(digest, spdm_get_hash_size(alg)); 36 | } 37 | 38 | static int ValidateAsymKey(const SpdmAsymPubKey* pub_key) { return 0; } 39 | static int ValidateDheKey(const SpdmDhePubKey* pub_key) { return 0; } 40 | 41 | static int GenerateDheKeypair(SpdmDheAlgorithm alg, uint8_t* priv_key, 42 | uint8_t* pub_key) { 43 | NonRandom(priv_key, spdm_get_dhe_priv_key_size(alg)); 44 | NonRandom(pub_key, spdm_get_dhe_pub_key_size(alg)); 45 | 46 | return 0; 47 | } 48 | 49 | static int GenerateDheSecret(const SpdmDhePrivKey* priv_key, 50 | const SpdmDhePubKey* pub_key, 51 | uint8_t* shared_secret) { 52 | NonRandom(shared_secret, spdm_get_dhe_secret_size(priv_key->alg)); 53 | 54 | return 0; 55 | } 56 | 57 | static int VerifyWithPublicKey(const SpdmAsymPubKey* pub_key, 58 | const uint8_t* input, uint32_t input_len, 59 | const uint8_t* sig, uint32_t sig_len) { 60 | return 0; 61 | } 62 | 63 | static int SignWithPrivateKey(SpdmAsymAlgorithm alg, void* priv_key_ctx, 64 | const uint8_t* input, uint32_t input_len, 65 | uint8_t* sig, uint32_t sig_len) { 66 | return NonRandom(sig, sig_len); 67 | } 68 | 69 | static int Hmac(SpdmHashAlgorithm alg, const uint8_t* key, uint32_t key_len, 70 | const uint8_t* data, uint32_t data_len, uint8_t* out) { 71 | return NonRandom(out, spdm_get_hash_size(alg)); 72 | } 73 | 74 | static int HkdfExpand(SpdmHashAlgorithm alg, const uint8_t* key, 75 | uint32_t key_len, const uint8_t* context, 76 | uint32_t context_len, uint8_t* out, uint32_t out_len) { 77 | return NonRandom(out, out_len); 78 | } 79 | 80 | static int AesGcmEncrypt(const SpdmAeadKey* key, const SpdmAeadIv* iv, 81 | const uint8_t* plaintext, uint32_t plaintext_len, 82 | const uint8_t* aad, uint32_t aad_len, 83 | uint8_t* ciphertext, uint8_t* mac, uint32_t mac_len) { 84 | memmove(ciphertext, plaintext, plaintext_len); 85 | 86 | for (int i = 0; i < plaintext_len; ++i) { 87 | ciphertext[i] = ciphertext[i] + 128; 88 | } 89 | 90 | return NonRandom(mac, mac_len); 91 | } 92 | 93 | static int AesGcmDecrypt(const SpdmAeadKey* key, const SpdmAeadIv* iv, 94 | const uint8_t* ciphertext, uint32_t ciphertext_len, 95 | const uint8_t* aad, uint32_t aad_len, 96 | const uint8_t* mac, uint32_t mac_len, 97 | uint8_t* plaintext) { 98 | memmove(plaintext, ciphertext, ciphertext_len); 99 | 100 | for (int i = 0; i < ciphertext_len; ++i) { 101 | plaintext[i] = plaintext[i] + 128; 102 | } 103 | 104 | return 0; 105 | } 106 | 107 | int spdm_fill_dummy_asym_p256_keypair(SpdmAsymPubKey* pub_key) { 108 | spdm_init_asym_pub_key(pub_key, SPDM_ASYM_ECDSA_ECC_NIST_P256); 109 | 110 | return NonRandom(pub_key->data, pub_key->size); 111 | } 112 | 113 | const SpdmCryptoSpec DUMMY_CRYPTO_SPEC = { 114 | .supported_algs = 115 | { 116 | .asym_sign = 117 | { 118 | .ecdsa_ecc_nist_p384 = true, 119 | }, 120 | .asym_verify = 121 | { 122 | .ecdsa_ecc_nist_p384 = true, 123 | }, 124 | .hash_sha384 = true, 125 | .dhe_secp384r1 = true, 126 | .aead_aes_256_gcm = true, 127 | }, 128 | .get_random = NonRandom, 129 | .hash_ctx_size = 0, 130 | .initialize_hash = InitializeHash, 131 | .extend_hash = ExtendHash, 132 | .get_hash = GetHash, 133 | .validate_asym_key = ValidateAsymKey, 134 | .validate_dhe_key = ValidateDheKey, 135 | .gen_dhe_keypair = GenerateDheKeypair, 136 | .gen_dhe_secret = GenerateDheSecret, 137 | .verify_with_pub_key = VerifyWithPublicKey, 138 | .serialize_pub_key = spdm_raw_serialize_asym_key, 139 | .deserialize_pub_key = spdm_raw_serialize_asym_key, 140 | .sign_with_priv_key = SignWithPrivateKey, 141 | .hmac = Hmac, 142 | .hkdf_expand = HkdfExpand, 143 | .aes_gcm_encrypt = AesGcmEncrypt, 144 | .aes_gcm_decrypt = AesGcmDecrypt, 145 | }; 146 | -------------------------------------------------------------------------------- /spdm_lite/testing/library/host_context.c: -------------------------------------------------------------------------------- 1 | // Copyright 2022 Google LLC. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #include "spdm_lite/testing/host_context.h" 16 | 17 | #include 18 | #include 19 | #include 20 | 21 | #include "spdm_lite/common/crypto_types.h" 22 | #include "spdm_lite/crypto_impl/mbedtls_crypto.h" 23 | #include "spdm_lite/crypto_impl/mbedtls_sign.h" 24 | #include "spdm_lite/crypto_impl/raw_serialize.h" 25 | #include "spdm_lite/requester/requester.h" 26 | #include "spdm_lite/responder/responder.h" 27 | 28 | static int dispatch_request(void* ctx, bool is_secure_msg, const uint8_t* req, 29 | size_t req_size, uint8_t* rsp, size_t* rsp_size) { 30 | return spdm_dispatch_request((SpdmResponderContext*)ctx, is_secure_msg, req, 31 | req_size, rsp, rsp_size); 32 | } 33 | 34 | void initialize_dispatch_req_ctx(SpdmResponderContext* target_responder, 35 | SpdmDispatchRequestCtx* req_ctx) { 36 | req_ctx->crypto_spec = *get_mbedtls_crypto_spec(); 37 | req_ctx->dispatch_fn = dispatch_request, 38 | req_ctx->dispatch_ctx = target_responder; 39 | } 40 | 41 | const SpdmCryptoSpec* get_mbedtls_crypto_spec(void) { 42 | static SpdmCryptoSpec spec; 43 | static bool initialized = false; 44 | 45 | if (!initialized) { 46 | spec = MBEDTLS_BASE_CRYPTO_SPEC; 47 | spec.serialize_pub_key = spdm_raw_serialize_asym_key; 48 | spec.deserialize_pub_key = spdm_raw_serialize_asym_key; 49 | spec.sign_with_priv_key = spdm_mbedtls_sign_with_priv_key; 50 | 51 | initialized = true; 52 | } 53 | 54 | return &spec; 55 | } 56 | 57 | void initialize_host_responder_context(SpdmAsymPrivKey* priv_key, 58 | SpdmAsymPubKey* pub_key, 59 | SpdmResponderContext* ctx, 60 | spdm_app_dispatch_request_fn app_fn) { 61 | spdm_generate_asym_keypair(SPDM_ASYM_ECDSA_ECC_NIST_P256, priv_key, pub_key); 62 | 63 | int rc = spdm_initialize_responder_context( 64 | ctx, get_mbedtls_crypto_spec(), &HOST_CAPS, pub_key, priv_key, app_fn); 65 | assert(rc == 0); 66 | (void)rc; 67 | } 68 | -------------------------------------------------------------------------------- /spdm_lite/testing/requester_test.cc: -------------------------------------------------------------------------------- 1 | // Copyright 2022 Google LLC. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #include "spdm_lite/requester/requester.h" 16 | 17 | #include 18 | 19 | #include "spdm_lite/common/crypto_types.h" 20 | #include "spdm_lite/crypto_impl/mbedtls_sign.h" 21 | #include "spdm_lite/responder/responder.h" 22 | #include "spdm_lite/testing/add_2_app.h" 23 | #include "spdm_lite/testing/host_context.h" 24 | 25 | #include "gtest/gtest.h" 26 | 27 | namespace { 28 | 29 | TEST(SpdmRequester, EstablishSession) { 30 | SpdmAsymPrivKey rsp_priv_key; 31 | SpdmAsymPubKey rsp_pub_key; 32 | SpdmResponderContext rsp_ctx; 33 | initialize_host_responder_context(&rsp_priv_key, &rsp_pub_key, &rsp_ctx, 34 | add_2_app_fn); 35 | 36 | SpdmDispatchRequestCtx req_dispatch_ctx; 37 | initialize_dispatch_req_ctx(&rsp_ctx, &req_dispatch_ctx); 38 | 39 | SpdmRequesterSessionParams req_session_params = {}; 40 | req_session_params.dispatch_ctx = &req_dispatch_ctx; 41 | 42 | SpdmAsymPrivKey req_priv_key; 43 | ASSERT_EQ(0, spdm_generate_asym_keypair( 44 | SPDM_ASYM_ECDSA_ECC_NIST_P256, &req_priv_key, 45 | &req_session_params.requester_pub_key)); 46 | 47 | req_session_params.requester_priv_key_ctx = &req_priv_key; 48 | 49 | std::vector scratch_mem(1024); 50 | req_session_params.scratch = {scratch_mem.data(), scratch_mem.size()}; 51 | 52 | SpdmSessionParams session; 53 | ASSERT_EQ(0, spdm_establish_session(&req_session_params, &session)); 54 | 55 | uint16_t standard_id = 4; 56 | std::vector vendor_id = {0x01, 0x02, 0x03, 0x04}; 57 | uint32_t req_num = 1701; 58 | std::vector rsp(sizeof(Add2AppResponse) + 59 | req_session_params.requester_pub_key.size); 60 | size_t rsp_size = rsp.size(); 61 | 62 | ASSERT_EQ(0, spdm_dispatch_app_request( 63 | &req_dispatch_ctx, req_session_params.scratch, &session, 64 | standard_id, vendor_id.data(), vendor_id.size(), &req_num, 65 | sizeof(req_num), rsp.data(), &rsp_size)); 66 | 67 | ASSERT_EQ(rsp_size, rsp.size()); 68 | 69 | const auto* response = reinterpret_cast(rsp.data()); 70 | 71 | EXPECT_EQ(response->num, req_num + 2); 72 | EXPECT_EQ(0, memcmp(response->session_id.id, session.info.session_id.id, 73 | sizeof(response->session_id.id))); 74 | EXPECT_EQ(0, memcmp(rsp.data() + sizeof(*response), 75 | req_session_params.requester_pub_key.data, 76 | req_session_params.requester_pub_key.size)); 77 | 78 | const SpdmNegotiatedAlgs* session_algs = &session.info.negotiated_algs; 79 | EXPECT_EQ(response->asym_sign_alg, session_algs->asym_sign_alg); 80 | EXPECT_EQ(response->asym_verify_alg, session_algs->asym_verify_alg); 81 | EXPECT_EQ(response->hash_alg, session_algs->hash_alg); 82 | EXPECT_EQ(response->dhe_alg, session_algs->dhe_alg); 83 | EXPECT_EQ(response->aead_alg, session_algs->aead_alg); 84 | 85 | // Tear down session 86 | ASSERT_EQ(0, spdm_end_session(&req_dispatch_ctx, req_session_params.scratch, 87 | &session)); 88 | 89 | SpdmResponderSession zeroed_session = {}; 90 | EXPECT_EQ(0, memcmp(&zeroed_session.params, &session, sizeof(session))); 91 | EXPECT_EQ(0, 92 | memcmp(&zeroed_session, &rsp_ctx.session, sizeof(rsp_ctx.session))); 93 | 94 | EXPECT_EQ(rsp_ctx.state, STATE_WAITING_FOR_GET_VERSION); 95 | 96 | // Start a new one. 97 | ASSERT_EQ(0, spdm_establish_session(&req_session_params, &session)); 98 | 99 | req_num = 42; 100 | ASSERT_EQ(0, spdm_dispatch_app_request( 101 | &req_dispatch_ctx, req_session_params.scratch, &session, 102 | standard_id, vendor_id.data(), vendor_id.size(), &req_num, 103 | sizeof(req_num), rsp.data(), &rsp_size)); 104 | 105 | ASSERT_EQ(rsp_size, rsp.size()); 106 | 107 | response = reinterpret_cast(rsp.data()); 108 | EXPECT_EQ(response->num, req_num + 2); 109 | } 110 | 111 | } // namespace 112 | -------------------------------------------------------------------------------- /spdm_lite/testing/sample_app_test.cc: -------------------------------------------------------------------------------- 1 | // Copyright 2022 Google LLC. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #include "spdm_lite/samples/requester_app.h" 16 | 17 | #include "gtest/gtest.h" 18 | 19 | namespace { 20 | 21 | TEST(SampleApp, RunSampleApp) { 22 | ASSERT_EQ(0, sample_app_initialize_spdm_session()); 23 | 24 | const uint8_t start_num = 42; 25 | const uint8_t end_num = 170; 26 | 27 | uint8_t output; 28 | 29 | ASSERT_EQ(0, sample_app_rot128_byte(start_num, &output)); 30 | EXPECT_EQ(output, end_num); 31 | 32 | ASSERT_EQ(0, sample_app_rot128_byte(end_num, &output)); 33 | EXPECT_EQ(output, start_num); 34 | 35 | ASSERT_EQ(0, sample_app_end_spdm_session()); 36 | } 37 | 38 | } // namespace 39 | -------------------------------------------------------------------------------- /spdm_lite/testing/spdm_parser_test.cc: -------------------------------------------------------------------------------- 1 | // Copyright 2022 Google LLC. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #include 16 | #include 17 | 18 | #include "spdm_lite/common/messages.h" 19 | #include "spdm_lite/everparse/SPDMWrapper.h" 20 | 21 | #include "gtest/gtest.h" 22 | 23 | namespace { 24 | 25 | TEST(SpdmTest, ParseVersion) { 26 | std::vector buf{ 27 | 0x12, // version 28 | 0x04, // request_response_code 29 | 0x00, // param_1 30 | 0x00, // param_2 31 | 0x00, // reserved 32 | 0x02, // Two version entries 33 | 0x23, 0x45, // v4.5.2.3 34 | 0x67, 0x89, // v8.9.6.7 35 | }; 36 | 37 | buffer input{buf.data(), static_cast(buf.size())}; 38 | 39 | uint8_t entry_count; 40 | const uint8_t *entries; 41 | 42 | int res = SpdmCheckVersion(&input, /*rest=*/nullptr, &entry_count, &entries); 43 | ASSERT_EQ(res, 0); 44 | 45 | ASSERT_EQ(entry_count, 2); 46 | ASSERT_EQ(entries, buf.data() + 6); 47 | 48 | SPDM_VersionNumberEntry entry; 49 | memcpy(&entry, entries, sizeof(entry)); 50 | EXPECT_EQ(entry.major_version, 4); 51 | EXPECT_EQ(entry.minor_version, 5); 52 | EXPECT_EQ(entry.update_version, 2); 53 | EXPECT_EQ(entry.alpha, 3); 54 | 55 | memcpy(&entry, entries + sizeof(entry), sizeof(entry)); 56 | EXPECT_EQ(entry.major_version, 8); 57 | EXPECT_EQ(entry.minor_version, 9); 58 | EXPECT_EQ(entry.update_version, 6); 59 | EXPECT_EQ(entry.alpha, 7); 60 | } 61 | 62 | TEST(SpdmTest, ParseVersionFailure) { 63 | std::vector buf{ 64 | 0x12, // version 65 | 0x04, // request_response_code 66 | 0x00, // param_1 67 | 0x00, // param_2 68 | 0x00, // reserved 69 | 0x01, // One version entry 70 | }; // But no entries 71 | 72 | buffer input{buf.data(), static_cast(buf.size())}; 73 | 74 | uint8_t entry_count; 75 | const uint8_t *entries; 76 | 77 | int res = SpdmCheckVersion(&input, /*rest=*/nullptr, &entry_count, &entries); 78 | EXPECT_EQ(res, -1); 79 | 80 | buf[5] = 0; // Now we're saying there's no entries. 81 | res = SpdmCheckVersion(&input, /*rest=*/nullptr, &entry_count, &entries); 82 | EXPECT_EQ(res, 0); 83 | } 84 | 85 | } // namespace 86 | -------------------------------------------------------------------------------- /spdm_lite/testing/state_need_requester_key_test.cc: -------------------------------------------------------------------------------- 1 | // Copyright 2022 Google LLC. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #include 16 | #include 17 | #include 18 | #include 19 | 20 | #include "spdm_lite/common/crypto.h" 21 | #include "spdm_lite/common/utils.h" 22 | #include "spdm_lite/common/vendor_defined_pub_key.h" 23 | #include "spdm_lite/everparse/SPDMWrapper.h" 24 | #include "spdm_lite/responder/responder.h" 25 | #include "spdm_lite/testing/host_context.h" 26 | #include "spdm_lite/testing/utils.h" 27 | 28 | #include "gtest/gtest.h" 29 | 30 | namespace { 31 | 32 | TEST(NeedRequesterKey, GetRequesterKey) { 33 | SpdmAsymPrivKey rsp_priv_key; 34 | SpdmAsymPubKey rsp_pub_key; 35 | SpdmResponderContext ctx; 36 | initialize_host_responder_context(&rsp_priv_key, &rsp_pub_key, &ctx, 37 | /*app_fn=*/nullptr); 38 | 39 | SpdmAsymPrivKey req_priv_key; 40 | SpdmAsymPubKey req_pub_key; 41 | ASSERT_EQ(0, spdm_generate_asym_keypair(SPDM_ASYM_ECDSA_ECC_NIST_P256, 42 | &req_priv_key, &req_pub_key)); 43 | 44 | SpdmDhePrivKey req_key_ex_priv_key; 45 | SpdmDhePubKey req_key_ex_pub_key; 46 | ASSERT_EQ(0, 47 | spdm_gen_dhe_keypair(get_mbedtls_crypto_spec(), SPDM_DHE_SECP521R1, 48 | &req_key_ex_priv_key, &req_key_ex_pub_key)); 49 | 50 | uint8_t req_session_id[2]; 51 | ASSERT_EQ(0, spdm_get_random(&ctx.crypto_spec, req_session_id, 52 | sizeof(req_session_id))); 53 | 54 | std::vector get_version_msg = MakeGetVersion(); 55 | std::vector get_caps_msg = MakeGetCapabilities(); 56 | std::vector negotiate_algs_msg = MakeNegotiateAlgorithms(); 57 | std::vector key_exchange_msg = 58 | MakeKeyExchange(req_session_id, req_key_ex_pub_key); 59 | std::vector give_pub_key_msg = MakeGivePubKey(req_pub_key); 60 | 61 | ASSERT_EQ(0, DispatchRequest(&ctx, get_version_msg)); 62 | ASSERT_EQ(0, DispatchRequest(&ctx, get_caps_msg)); 63 | ASSERT_EQ(0, DispatchRequest(&ctx, negotiate_algs_msg)); 64 | ASSERT_EQ(0, DispatchRequest(&ctx, key_exchange_msg)); 65 | 66 | std::vector rsp; 67 | ASSERT_EQ(0, DispatchSecureRequest(&ctx, SPDM_HANDSHAKE_PHASE, 68 | give_pub_key_msg, &rsp)); 69 | 70 | buffer output_msg = MakeBuffer(rsp); 71 | 72 | uint16_t standard_id; 73 | buffer vendor_id; 74 | buffer payload; 75 | 76 | ASSERT_EQ(0, SpdmCheckVendorDefinedResponse( 77 | &output_msg, /*rest=*/nullptr, &standard_id, &vendor_id.data, 78 | &vendor_id.size, &payload.data, &payload.size)); 79 | 80 | EXPECT_EQ(standard_id, DMTF_STANDARD_ID); 81 | EXPECT_EQ(vendor_id.size, 0); 82 | EXPECT_EQ(payload.size, sizeof(SPDM_VendorDefinedPubKeyMsg)); 83 | 84 | auto* pub_key_rsp = 85 | reinterpret_cast(payload.data); 86 | 87 | // TODO(jeffandersen): endianness 88 | ASSERT_EQ(pub_key_rsp->vd_id, DMTF_VD_ID); 89 | ASSERT_EQ(pub_key_rsp->vd_req_rsp, DMTF_VD_GIVE_PUBKEY_CODE); 90 | 91 | ASSERT_EQ(ctx.session.params.info.peer_pub_key.alg, req_pub_key.alg); 92 | 93 | ASSERT_EQ(0, 94 | memcmp(ctx.session.params.info.peer_pub_key.data, req_pub_key.data, 95 | ctx.session.params.info.peer_pub_key.size)); 96 | ASSERT_EQ(ctx.state, STATE_MUTUAL_AUTH_WAITING_FOR_FINISH); 97 | } 98 | 99 | } // namespace 100 | -------------------------------------------------------------------------------- /spdm_lite/testing/state_waiting_for_finish_test.cc: -------------------------------------------------------------------------------- 1 | // Copyright 2022 Google LLC. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #include 16 | #include 17 | #include 18 | #include 19 | 20 | #include "spdm_lite/common/crypto.h" 21 | #include "spdm_lite/common/key_schedule.h" 22 | #include "spdm_lite/common/messages.h" 23 | #include "spdm_lite/common/session_types.h" 24 | #include "spdm_lite/common/utils.h" 25 | #include "spdm_lite/everparse/SPDMWrapper.h" 26 | #include "spdm_lite/responder/responder.h" 27 | #include "spdm_lite/testing/host_context.h" 28 | #include "spdm_lite/testing/utils.h" 29 | 30 | #include "gtest/gtest.h" 31 | 32 | namespace { 33 | 34 | TEST(WaitingForFinish, Finish) { 35 | SpdmAsymPrivKey rsp_priv_key; 36 | SpdmAsymPubKey rsp_pub_key; 37 | SpdmResponderContext ctx; 38 | initialize_host_responder_context(&rsp_priv_key, &rsp_pub_key, &ctx, 39 | /*app_fn=*/nullptr); 40 | 41 | SpdmAsymPrivKey req_priv_key; 42 | SpdmAsymPubKey req_pub_key; 43 | ASSERT_EQ(0, spdm_generate_asym_keypair(SPDM_ASYM_ECDSA_ECC_NIST_P256, 44 | &req_priv_key, &req_pub_key)); 45 | 46 | SpdmDhePrivKey req_key_ex_priv_key; 47 | SpdmDhePubKey req_key_ex_pub_key; 48 | ASSERT_EQ(0, 49 | spdm_gen_dhe_keypair(get_mbedtls_crypto_spec(), SPDM_DHE_SECP521R1, 50 | &req_key_ex_priv_key, &req_key_ex_pub_key)); 51 | 52 | uint8_t req_session_id[2]; 53 | spdm_get_random(&ctx.crypto_spec, req_session_id, sizeof(req_session_id)); 54 | 55 | std::vector get_version_msg = MakeGetVersion(); 56 | std::vector get_caps_msg = MakeGetCapabilities(); 57 | std::vector negotiate_algs_msg = MakeNegotiateAlgorithms(); 58 | std::vector key_exchange_msg = 59 | MakeKeyExchange(req_session_id, req_key_ex_pub_key); 60 | std::vector give_pub_key_msg = MakeGivePubKey(req_pub_key); 61 | 62 | std::vector rsp; 63 | 64 | SpdmHash target_digest; 65 | ASSERT_EQ(0, spdm_initialize_hash_struct(get_mbedtls_crypto_spec(), 66 | SPDM_HASH_SHA512, &target_digest)); 67 | spdm_initialize_hash(&target_digest); 68 | 69 | ASSERT_EQ(0, DispatchRequest(&ctx, get_version_msg, &rsp)); 70 | ExtendHash(&target_digest, get_version_msg); 71 | ExtendHash(&target_digest, rsp); 72 | 73 | ASSERT_EQ(0, DispatchRequest(&ctx, get_caps_msg, &rsp)); 74 | ExtendHash(&target_digest, get_caps_msg); 75 | ExtendHash(&target_digest, rsp); 76 | 77 | ASSERT_EQ(0, DispatchRequest(&ctx, negotiate_algs_msg, &rsp)); 78 | ExtendHash(&target_digest, negotiate_algs_msg); 79 | ExtendHash(&target_digest, rsp); 80 | 81 | ASSERT_EQ(0, DispatchRequest(&ctx, key_exchange_msg, &rsp)); 82 | 83 | std::vector pub_key_digest = 84 | GetDigest(rsp_pub_key.data, rsp_pub_key.size); 85 | 86 | ExtendHash(&target_digest, pub_key_digest); 87 | ExtendHash(&target_digest, key_exchange_msg); 88 | ExtendHash(&target_digest, rsp); 89 | 90 | // Check the transcript before proceeding. 91 | std::vector transcript_digest = GetDigest(target_digest); 92 | SpdmHashResult actual_transcript_digest; 93 | ASSERT_EQ(0, spdm_get_hash(&ctx.session.transcript_hash, 94 | &actual_transcript_digest)); 95 | ASSERT_EQ(0, memcmp(transcript_digest.data(), actual_transcript_digest.data, 96 | transcript_digest.size())); 97 | 98 | std::vector digest = GetDigest(req_pub_key.data, req_pub_key.size); 99 | ExtendHash(&target_digest, digest); 100 | 101 | std::vector finish_msg = 102 | MakeFinish(&target_digest, ctx.session.params, req_priv_key); 103 | 104 | ASSERT_EQ( 105 | 0, DispatchSecureRequest(&ctx, SPDM_HANDSHAKE_PHASE, give_pub_key_msg)); 106 | ASSERT_EQ( 107 | 0, DispatchSecureRequest(&ctx, SPDM_HANDSHAKE_PHASE, finish_msg, &rsp)); 108 | 109 | buffer output_msg = MakeBuffer(rsp); 110 | const uint8_t* responder_verify_data; 111 | ASSERT_EQ(0, SpdmCheckFinishRsp(&output_msg, /*rest=*/nullptr, 112 | /*hash_len=*/SHA512_DIGEST_SIZE, 113 | /*responder_verify_data_expected=*/false, 114 | &responder_verify_data)); 115 | 116 | spdm_extend_hash(&target_digest, reinterpret_cast(rsp.data()), 117 | sizeof(SPDM_FINISH_RSP)); 118 | 119 | transcript_digest = GetDigest(target_digest); 120 | EXPECT_EQ(0, memcmp(transcript_digest.data(), ctx.session.params.th_2.data, 121 | transcript_digest.size())); 122 | 123 | EXPECT_EQ(ctx.state, STATE_SESSION_ESTABLISHED); 124 | } 125 | 126 | } // namespace 127 | -------------------------------------------------------------------------------- /spdm_lite/testing/state_waiting_for_get_capabilities_test.cc: -------------------------------------------------------------------------------- 1 | // Copyright 2022 Google LLC. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #include 16 | #include 17 | 18 | #include "spdm_lite/common/crypto.h" 19 | #include "spdm_lite/common/messages.h" 20 | #include "spdm_lite/common/utils.h" 21 | #include "spdm_lite/everparse/SPDMWrapper.h" 22 | #include "spdm_lite/responder/responder.h" 23 | #include "spdm_lite/testing/host_context.h" 24 | #include "spdm_lite/testing/utils.h" 25 | 26 | #include "gtest/gtest.h" 27 | 28 | namespace { 29 | 30 | TEST(WaitingForGetCapabilities, GetCapabilities) { 31 | std::vector get_version_msg = MakeGetVersion(); 32 | std::vector get_caps_msg = MakeGetCapabilities(); 33 | 34 | std::vector rsp; 35 | 36 | SpdmHash target_digest; 37 | ASSERT_EQ(0, spdm_initialize_hash_struct(get_mbedtls_crypto_spec(), 38 | SPDM_HASH_SHA512, &target_digest)); 39 | spdm_initialize_hash(&target_digest); 40 | 41 | SpdmAsymPrivKey rsp_priv_key; 42 | SpdmAsymPubKey rsp_pub_key; 43 | SpdmResponderContext ctx; 44 | initialize_host_responder_context(&rsp_priv_key, &rsp_pub_key, &ctx, 45 | /*app_fn=*/nullptr); 46 | 47 | // Send GET_VERSION 48 | ASSERT_EQ(0, DispatchRequest(&ctx, get_version_msg, &rsp)); 49 | 50 | // Hash GET_VERSION/VERSION 51 | ExtendHash(&target_digest, get_version_msg); 52 | ExtendHash(&target_digest, rsp); 53 | 54 | // Send GET_CAPABILITIES 55 | ASSERT_EQ(0, DispatchRequest(&ctx, get_caps_msg, &rsp)); 56 | 57 | // Hash GET_CAPABILITIES/CAPABILITIES 58 | ExtendHash(&target_digest, get_caps_msg); 59 | ExtendHash(&target_digest, rsp); 60 | 61 | buffer output_msg = MakeBuffer(rsp); 62 | ASSERT_EQ(0, SpdmCheckCapabilities(&output_msg, /*rest=*/nullptr)); 63 | 64 | SPDM_CAPABILITIES caps; 65 | memcpy(&caps, output_msg.data, sizeof(caps)); 66 | EXPECT_EQ(caps.ct_exponent, 0); 67 | EXPECT_EQ(caps.flags_ENCRYPT_CAP, 1); 68 | EXPECT_EQ(caps.flags_MAC_CAP, 1); 69 | EXPECT_EQ(caps.flags_MUT_AUTH_CAP, 0); 70 | EXPECT_EQ(caps.flags_KEY_EX_CAP, 1); 71 | EXPECT_EQ(caps.flags_ALIAS_CERT_CAP, 1); 72 | EXPECT_EQ(caps.data_transfer_size, SPDM_HOST_DATA_TRANSFER_SIZE); 73 | EXPECT_EQ(caps.max_spdm_message_size, SPDM_HOST_DATA_TRANSFER_SIZE); 74 | 75 | // Compare digests 76 | std::vector ctx_digest = GetDigest(ctx.negotiation_transcript.data, 77 | ctx.negotiation_transcript.size); 78 | std::vector expected_digest = GetDigest(target_digest); 79 | EXPECT_EQ(ctx_digest, expected_digest); 80 | 81 | EXPECT_EQ(ctx.state, STATE_WAITING_FOR_NEGOTIATE_ALGORITHMS); 82 | EXPECT_EQ(ctx.requester_caps.data_transfer_size, 83 | SPDM_HOST_DATA_TRANSFER_SIZE); 84 | } 85 | 86 | // TODO(jeffandersen): Add negative test 87 | 88 | } // namespace 89 | -------------------------------------------------------------------------------- /spdm_lite/testing/state_waiting_for_get_version_test.cc: -------------------------------------------------------------------------------- 1 | // Copyright 2022 Google LLC. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #include 16 | #include 17 | 18 | #include "spdm_lite/common/crypto.h" 19 | #include "spdm_lite/common/error.h" 20 | #include "spdm_lite/common/messages.h" 21 | #include "spdm_lite/common/utils.h" 22 | #include "spdm_lite/everparse/SPDMWrapper.h" 23 | #include "spdm_lite/responder/responder.h" 24 | #include "spdm_lite/testing/host_context.h" 25 | #include "spdm_lite/testing/utils.h" 26 | 27 | #include "gtest/gtest.h" 28 | 29 | namespace { 30 | 31 | TEST(WaitingForGetVersion, GetVersion) { 32 | SpdmAsymPrivKey rsp_priv_key; 33 | SpdmAsymPubKey rsp_pub_key; 34 | SpdmResponderContext ctx; 35 | initialize_host_responder_context(&rsp_priv_key, &rsp_pub_key, &ctx, 36 | /*app_fn=*/nullptr); 37 | 38 | std::vector get_version_msg = MakeGetVersion(); 39 | 40 | std::vector rsp; 41 | 42 | SpdmHash target_digest; 43 | ASSERT_EQ(0, spdm_initialize_hash_struct(get_mbedtls_crypto_spec(), 44 | SPDM_HASH_SHA512, &target_digest)); 45 | spdm_initialize_hash(&target_digest); 46 | 47 | // Send GET_VERSION 48 | ASSERT_EQ(0, DispatchRequest(&ctx, get_version_msg, &rsp)); 49 | 50 | // Hash GET_VERSION/VERSION 51 | ExtendHash(&target_digest, get_version_msg); 52 | ExtendHash(&target_digest, rsp); 53 | 54 | uint8_t entry_count; 55 | const uint8_t* entries; 56 | 57 | buffer output_msg = MakeBuffer(rsp); 58 | ASSERT_EQ(0, SpdmCheckVersion(&output_msg, /*rest=*/nullptr, &entry_count, 59 | &entries)); 60 | ASSERT_EQ(entry_count, 1); 61 | 62 | SPDM_VersionNumberEntry entry; 63 | memcpy(&entry, entries, sizeof(entry)); 64 | EXPECT_EQ(entry.major_version, 1); 65 | EXPECT_EQ(entry.minor_version, 2); 66 | EXPECT_EQ(entry.update_version, 0); 67 | EXPECT_EQ(entry.alpha, 0); 68 | 69 | // Compare digests 70 | std::vector ctx_digest = GetDigest(ctx.negotiation_transcript.data, 71 | ctx.negotiation_transcript.size); 72 | std::vector expected_digest = GetDigest(target_digest); 73 | EXPECT_EQ(ctx_digest, expected_digest); 74 | 75 | // Test that we can re-start the flow with another GET_VERSION. 76 | ASSERT_EQ(0, DispatchRequest(&ctx, get_version_msg, &rsp)); 77 | 78 | ctx_digest = GetDigest(ctx.negotiation_transcript.data, 79 | ctx.negotiation_transcript.size); 80 | EXPECT_EQ(ctx_digest, expected_digest); 81 | 82 | EXPECT_EQ(ctx.state, STATE_WAITING_FOR_GET_CAPABILITIES); 83 | } 84 | 85 | TEST(WaitingForGetVersion, InvalidGetVersion) { 86 | SpdmAsymPrivKey rsp_priv_key; 87 | SpdmAsymPubKey rsp_pub_key; 88 | SpdmResponderContext ctx; 89 | initialize_host_responder_context(&rsp_priv_key, &rsp_pub_key, &ctx, 90 | /*app_fn=*/nullptr); 91 | 92 | SPDM_GET_VERSION get_version_msg = {}; 93 | 94 | get_version_msg.preamble.version = 0x10; 95 | get_version_msg.preamble.request_response_code = SPDM_CODE_VERSION; // Wrong 96 | 97 | std::vector output(256); 98 | size_t output_size = output.size(); 99 | 100 | ASSERT_EQ(0, spdm_dispatch_request( 101 | &ctx, /*is_secure=*/false, 102 | reinterpret_cast(&get_version_msg), 103 | sizeof(get_version_msg), output.data(), &output_size)); 104 | 105 | buffer output_msg = {output.data(), (uint32_t)output_size}; 106 | 107 | uint8_t error_code, error_data; 108 | ASSERT_EQ(0, SpdmCheckError(&output_msg, /*rest=*/nullptr, &error_code, 109 | &error_data)); 110 | 111 | EXPECT_EQ(error_code, SPDM_ERR_VERSION_MISMATCH); 112 | EXPECT_EQ(error_data, 0); 113 | 114 | EXPECT_EQ(ctx.state, STATE_WAITING_FOR_GET_VERSION); 115 | } 116 | 117 | } // namespace 118 | -------------------------------------------------------------------------------- /spdm_lite/testing/state_waiting_for_negotiate_algorithms_test.cc: -------------------------------------------------------------------------------- 1 | // Copyright 2022 Google LLC. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #include 16 | #include 17 | 18 | #include "spdm_lite/common/crypto.h" 19 | #include "spdm_lite/common/messages.h" 20 | #include "spdm_lite/common/utils.h" 21 | #include "spdm_lite/everparse/SPDMWrapper.h" 22 | #include "spdm_lite/responder/responder.h" 23 | #include "spdm_lite/testing/host_context.h" 24 | #include "spdm_lite/testing/utils.h" 25 | 26 | #include "gtest/gtest.h" 27 | 28 | namespace { 29 | 30 | TEST(WaitingForNegotiateAlgorithms, NegotiateAlgorithms) { 31 | SpdmAsymPrivKey rsp_priv_key; 32 | SpdmAsymPubKey rsp_pub_key; 33 | SpdmResponderContext ctx; 34 | initialize_host_responder_context(&rsp_priv_key, &rsp_pub_key, &ctx, 35 | /*app_fn=*/nullptr); 36 | 37 | std::vector get_version_msg = MakeGetVersion(); 38 | std::vector get_caps_msg = MakeGetCapabilities(); 39 | std::vector negotiate_algs_msg = MakeNegotiateAlgorithms(); 40 | 41 | std::vector rsp; 42 | 43 | SpdmHash target_digest; 44 | ASSERT_EQ(0, spdm_initialize_hash_struct(get_mbedtls_crypto_spec(), 45 | SPDM_HASH_SHA512, &target_digest)); 46 | spdm_initialize_hash(&target_digest); 47 | 48 | // Send GET_VERSION 49 | ASSERT_EQ(0, DispatchRequest(&ctx, get_version_msg, &rsp)); 50 | 51 | // Hash GET_VERSION/VERSION 52 | ExtendHash(&target_digest, get_version_msg); 53 | ExtendHash(&target_digest, rsp); 54 | 55 | // Send GET_CAPABILITIES 56 | ASSERT_EQ(0, DispatchRequest(&ctx, get_caps_msg, &rsp)); 57 | 58 | // Hash GET_CAPABILITIES/CAPABILITIES 59 | ExtendHash(&target_digest, get_caps_msg); 60 | ExtendHash(&target_digest, rsp); 61 | 62 | // Send NEGOTIATE_ALGORITHMS 63 | ASSERT_EQ(0, DispatchRequest(&ctx, negotiate_algs_msg, &rsp)); 64 | 65 | // Hash NEGOTIATE_ALGORITHMS/ALGORITHMS 66 | ExtendHash(&target_digest, negotiate_algs_msg); 67 | ExtendHash(&target_digest, rsp); 68 | 69 | buffer output_msg = MakeBuffer(rsp); 70 | 71 | const uint8_t* ext_asym_algs; 72 | uint32_t ext_asym_algs_count; 73 | const uint8_t* ext_hash_algs; 74 | uint32_t ext_hash_algs_count; 75 | buffer alg_structs; 76 | uint32_t alg_structs_count; 77 | 78 | ASSERT_EQ(0, SpdmCheckAlgorithms( 79 | &output_msg, /*rest=*/nullptr, &ext_asym_algs, 80 | &ext_asym_algs_count, &ext_hash_algs, &ext_hash_algs_count, 81 | &alg_structs.data, &alg_structs_count, &alg_structs.size)); 82 | 83 | auto* algs_msg = reinterpret_cast(output_msg.data); 84 | EXPECT_EQ(algs_msg->other_params_opaque_data_fmt_1, 1); 85 | EXPECT_EQ(algs_msg->asym_hash_algs.base_asym_alg_ecdsa_ecc_nist_p256, 1); 86 | EXPECT_EQ(algs_msg->asym_hash_algs.base_hash_algo_sha_512, 1); 87 | 88 | ASSERT_EQ(ext_asym_algs_count, 0); 89 | ASSERT_EQ(ext_hash_algs_count, 0); 90 | ASSERT_EQ(alg_structs_count, 4); 91 | 92 | buffer rest; 93 | uint32_t alg_count_extended; 94 | 95 | // Check DHE algs 96 | ASSERT_EQ(0, SpdmCheckDheAlg(&alg_structs, &rest, /*is_resp=*/true, 97 | &alg_count_extended)); 98 | ASSERT_EQ(alg_count_extended, 0); 99 | EXPECT_EQ(reinterpret_cast(alg_structs.data) 100 | ->alg_supported_secp521r1, 101 | 1); 102 | 103 | // Check AEAD algs 104 | alg_structs = rest; 105 | ASSERT_EQ(0, SpdmCheckAeadAlg(&alg_structs, &rest, /*is_resp=*/true, 106 | &alg_count_extended)); 107 | ASSERT_EQ(alg_count_extended, 0); 108 | EXPECT_EQ(reinterpret_cast(alg_structs.data) 109 | ->alg_supported_aes_256_gcm, 110 | 1); 111 | 112 | // Check asym algs 113 | alg_structs = rest; 114 | ASSERT_EQ(0, SpdmCheckAsymAlg(&alg_structs, &rest, /*is_resp=*/true, 115 | &alg_count_extended)); 116 | ASSERT_EQ(alg_count_extended, 0); 117 | EXPECT_EQ(reinterpret_cast(alg_structs.data) 118 | ->alg_supported_ecdsa_ecc_nist_p256, 119 | 1); 120 | 121 | // Check key schedule algs 122 | alg_structs = rest; 123 | ASSERT_EQ(0, SpdmCheckKeySchedule(&alg_structs, &rest, /*is_resp=*/true, 124 | &alg_count_extended)); 125 | ASSERT_EQ(alg_count_extended, 0); 126 | EXPECT_EQ( 127 | reinterpret_cast(alg_structs.data) 128 | ->alg_supported_spdm_key_schedule, 129 | 1); 130 | 131 | // Compare digests 132 | std::vector ctx_digest = GetDigest(ctx.negotiation_transcript.data, 133 | ctx.negotiation_transcript.size); 134 | std::vector expected_digest = GetDigest(target_digest); 135 | EXPECT_EQ(ctx_digest, expected_digest); 136 | 137 | EXPECT_EQ(ctx.state, STATE_WAITING_FOR_KEY_EXCHANGE); 138 | } 139 | 140 | // TODO(jeffandersen): Add negative test 141 | 142 | } // namespace 143 | -------------------------------------------------------------------------------- /spdm_lite/testing/tpmt_public_serialize_test.cc: -------------------------------------------------------------------------------- 1 | // Copyright 2022 Google LLC. 2 | // 3 | // Licensed under the Apache License, Version 2.0 (the "License"); 4 | // you may not use this file except in compliance with the License. 5 | // You may obtain a copy of the License at 6 | // 7 | // http://www.apache.org/licenses/LICENSE-2.0 8 | // 9 | // Unless required by applicable law or agreed to in writing, software 10 | // distributed under the License is distributed on an "AS IS" BASIS, 11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | // See the License for the specific language governing permissions and 13 | // limitations under the License. 14 | 15 | #include "spdm_lite/common/crypto_types.h" 16 | #include "spdm_lite/crypto_impl/mbedtls_sign.h" 17 | #include "spdm_lite/crypto_impl/tpmt_public_serialize.h" 18 | #include "tss2/tss2_mu.h" 19 | #include "tss2/tss2_tpm2_types.h" 20 | 21 | #include "gtest/gtest.h" 22 | 23 | namespace { 24 | 25 | TEST(TpmtPublicSerializeTest, Serialize) { 26 | SpdmAsymPrivKey priv_key; 27 | SpdmAsymPubKey pub_key; 28 | 29 | ASSERT_EQ(0, spdm_generate_asym_keypair(SPDM_ASYM_ECDSA_ECC_NIST_P256, 30 | &priv_key, &pub_key)); 31 | 32 | std::vector serialized(sizeof(TPMT_PUBLIC)); 33 | uint16_t serialized_size = serialized.size(); 34 | 35 | ASSERT_EQ(0, spdm_serialize_asym_pub_to_tpmt_public( 36 | pub_key.alg, SPDM_HASH_SHA256, pub_key.data, pub_key.size, 37 | serialized.data(), &serialized_size)); 38 | 39 | ASSERT_LT(serialized_size, serialized.size()); 40 | serialized.resize(serialized_size); 41 | 42 | TPMT_PUBLIC tpmt_public; 43 | ASSERT_EQ(TSS2_RC_SUCCESS, 44 | Tss2_MU_TPMT_PUBLIC_Unmarshal(serialized.data(), serialized.size(), 45 | /*offset=*/nullptr, &tpmt_public)); 46 | 47 | EXPECT_EQ(tpmt_public.type, TPM2_ALG_ECC); 48 | EXPECT_EQ(tpmt_public.nameAlg, TPM2_ALG_NULL); 49 | EXPECT_EQ(tpmt_public.objectAttributes, TPMA_OBJECT_SIGN_ENCRYPT); 50 | EXPECT_EQ(tpmt_public.authPolicy.size, 0); 51 | 52 | const TPMS_ECC_PARMS* params = &tpmt_public.parameters.eccDetail; 53 | 54 | EXPECT_EQ(params->symmetric.algorithm, TPM2_ALG_NULL); 55 | EXPECT_EQ(params->scheme.scheme, TPM2_ALG_ECDSA); 56 | EXPECT_EQ(params->scheme.details.ecdsa.hashAlg, TPM2_ALG_SHA256); 57 | EXPECT_EQ(params->kdf.scheme, TPM2_ALG_NULL); 58 | EXPECT_EQ(params->curveID, TPM2_ECC_NIST_P256); 59 | 60 | const TPMS_ECC_POINT* ecc = &tpmt_public.unique.ecc; 61 | 62 | EXPECT_EQ(ecc->x.size, P256_COORD_SIZE); 63 | EXPECT_EQ(ecc->y.size, P256_COORD_SIZE); 64 | } 65 | 66 | TEST(TpmtPublicSerializeTest, Deserialize) { 67 | SpdmAsymPrivKey priv_key; 68 | SpdmAsymPubKey pub_key; 69 | 70 | ASSERT_EQ(0, spdm_generate_asym_keypair(SPDM_ASYM_ECDSA_ECC_NIST_P256, 71 | &priv_key, &pub_key)); 72 | 73 | std::vector serialized(sizeof(TPMT_PUBLIC)); 74 | uint16_t serialized_size = serialized.size(); 75 | 76 | ASSERT_EQ(0, spdm_serialize_asym_pub_to_tpmt_public( 77 | pub_key.alg, SPDM_HASH_SHA256, pub_key.data, pub_key.size, 78 | serialized.data(), &serialized_size)); 79 | 80 | ASSERT_LT(serialized_size, serialized.size()); 81 | serialized.resize(serialized_size); 82 | 83 | std::vector serialized_2(sizeof(TPMT_PUBLIC)); 84 | 85 | SpdmAsymPubKey post_pub_key; 86 | spdm_init_asym_pub_key(&post_pub_key, pub_key.alg); 87 | uint16_t post_pub_key_size = post_pub_key.size; 88 | 89 | // First try with the wrong hash alg. 90 | ASSERT_EQ(-1, spdm_deserialize_asym_pub_from_tpmt_public( 91 | pub_key.alg, SPDM_HASH_SHA384, serialized.data(), 92 | serialized.size(), post_pub_key.data, &post_pub_key_size)); 93 | 94 | ASSERT_EQ(0, spdm_deserialize_asym_pub_from_tpmt_public( 95 | pub_key.alg, SPDM_HASH_SHA256, serialized.data(), 96 | serialized.size(), post_pub_key.data, &post_pub_key_size)); 97 | 98 | ASSERT_EQ(post_pub_key_size, post_pub_key.size); 99 | 100 | ASSERT_EQ(pub_key.alg, post_pub_key.alg); 101 | ASSERT_EQ(pub_key.size, post_pub_key.size); 102 | 103 | ASSERT_EQ(0, memcmp(pub_key.data, post_pub_key.data, post_pub_key.size)); 104 | } 105 | 106 | } // namespace 107 | --------------------------------------------------------------------------------