├── 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 |
--------------------------------------------------------------------------------