|
| 1 | +/** |
| 2 | + * Copyright Notice: |
| 3 | + * Copyright 2024 DMTF. All rights reserved. |
| 4 | + * License: BSD 3-Clause License. For full text see link: https://github.com/DMTF/libspdm/blob/main/LICENSE.md |
| 5 | + **/ |
| 6 | + |
| 7 | +#include <base.h> |
| 8 | +#include "spdm_cert_verify_callback_internal.h" |
| 9 | + |
| 10 | +/** |
| 11 | + * tcg-dice-TcbInfo OID: 2.23.133.5.4.1 |
| 12 | + * https://trustedcomputinggroup.org/wp-content/uploads/DICE-Attestation-Architecture-Version-1.1-Revision-18_pub.pdf |
| 13 | + **/ |
| 14 | +uint8_t m_libspdm_tcg_dice_tcbinfo_oid[] = {0x67, 0x81, 0x05, 0x05, 0x04, 0x01}; |
| 15 | + |
| 16 | +/*the cert chain must have a or more cert with DiceTcbInfo extension*/ |
| 17 | +bool m_libspdm_must_have_dice_tcb_info = true; |
| 18 | + |
| 19 | +/*the reference cert number with DiceTcbinfo in the cert chain*/ |
| 20 | +uint8_t m_libspdm_dice_tcb_info_number = 1; |
| 21 | + |
| 22 | +/*reference DiceTcbinfo*/ |
| 23 | + |
| 24 | +/*vendor: INTC*/ |
| 25 | +uint8_t m_libspdm_dice_tcbinfo_vendor[] = {0x49, 0x4E, 0x54, 0x43}; |
| 26 | +/*model: S3M GNR*/ |
| 27 | +uint8_t m_libspdm_dice_tcbinfo_model[] = {0x53, 0x33, 0x4D, 0x20, 0x47, 0x4E, 0x52}; |
| 28 | +/*version: 000200000000008B*/ |
| 29 | +uint8_t m_libspdm_dice_tcbinfo_version[] = {0x30, 0x30, 0x30, 0x32, 0x30, 0x30, 0x30, 0x30, 0x30, |
| 30 | + 0x30, 0x30, 0x30, 0x30, 0x30, 0x38, 0x42}; |
| 31 | +/*svn*/ |
| 32 | +uint8_t m_libspdm_dice_tcbinfo_svn[] = {0x01}; |
| 33 | +/*layer*/ |
| 34 | +uint8_t m_libspdm_dice_tcbinfo_layer[] = {0x01}; |
| 35 | +/*fwids*/ |
| 36 | +uint8_t m_libspdm_dice_tcbinfo_fwids[] = {0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, |
| 37 | + 0x02, 0x02, 0x04, 0x30, 0x6B, 0x44, 0x7B, 0x5E, 0x99, |
| 38 | + 0x21, 0x0A, 0x58, 0x8A, 0x7B, 0x31, 0x7D, 0xBA, 0x2D, |
| 39 | + 0x4A, 0x7F, 0x75, 0xE6, 0x97, 0xF2, 0x07, 0xE0, 0xC2, |
| 40 | + 0x99, 0x78, 0xF3, 0xF6, 0x2B, 0x53, 0xF5, 0xBE, 0xEB, |
| 41 | + 0x73, 0xF0, 0x37, 0xB8, 0x79, 0xC1, 0xFF, 0x76, 0x2A, |
| 42 | + 0x3A, 0x39, 0xCA, 0xE2, 0x8C, 0xF0, 0x56}; |
| 43 | +/*type*/ |
| 44 | +uint8_t m_libspdm_dice_tcbinfo_type[] = {0x46, 0x69, 0x72, 0x6D, 0x77, 0x61, 0x72, 0x65, 0x20, |
| 45 | + 0x44, 0x69, 0x67, 0x65, 0x73, 0x74}; |
| 46 | + |
| 47 | +/*verify cert DiceTcbInfo extension*/ |
| 48 | +bool libspdm_verify_cert_dicetcbinfo(const void *cert, size_t cert_size, |
| 49 | + size_t *spdm_get_dice_tcb_info_size) { |
| 50 | + bool result; |
| 51 | + uint8_t spdm_dice_tcb_info[256]; |
| 52 | + size_t spdm_dice_tcb_info_size; |
| 53 | + uint8_t *ptr; |
| 54 | + int32_t length; |
| 55 | + size_t obj_len; |
| 56 | + uint8_t *end; |
| 57 | + |
| 58 | + spdm_dice_tcb_info_size = 256; |
| 59 | + *spdm_get_dice_tcb_info_size = 0; |
| 60 | + result = libspdm_x509_get_extension_data(cert, cert_size, |
| 61 | + m_libspdm_tcg_dice_tcbinfo_oid, |
| 62 | + sizeof(m_libspdm_tcg_dice_tcbinfo_oid), |
| 63 | + spdm_dice_tcb_info, &spdm_dice_tcb_info_size); |
| 64 | + if (!result) { |
| 65 | + return false; |
| 66 | + } else if (spdm_dice_tcb_info_size == 0) { |
| 67 | + return true; |
| 68 | + } |
| 69 | + |
| 70 | + *spdm_get_dice_tcb_info_size = spdm_dice_tcb_info_size; |
| 71 | + length = (int32_t)spdm_dice_tcb_info_size; |
| 72 | + ptr = (uint8_t*)(size_t)spdm_dice_tcb_info; |
| 73 | + obj_len = 0; |
| 74 | + end = ptr + length; |
| 75 | + |
| 76 | + /*get DiceTcbInfo*/ |
| 77 | + result = libspdm_asn1_get_tag(&ptr, end, &obj_len, |
| 78 | + LIBSPDM_CRYPTO_ASN1_SEQUENCE | LIBSPDM_CRYPTO_ASN1_CONSTRUCTED); |
| 79 | + if (!result) { |
| 80 | + *spdm_get_dice_tcb_info_size = 0; |
| 81 | + return false; |
| 82 | + } |
| 83 | + result = libspdm_asn1_get_tag(&ptr, end, &obj_len, |
| 84 | + LIBSPDM_CRYPTO_ASN1_SEQUENCE | LIBSPDM_CRYPTO_ASN1_CONSTRUCTED); |
| 85 | + if (!result) { |
| 86 | + *spdm_get_dice_tcb_info_size = 0; |
| 87 | + return false; |
| 88 | + } |
| 89 | + |
| 90 | + /*vendor*/ |
| 91 | + result = libspdm_asn1_get_tag(&ptr, end, &obj_len, |
| 92 | + LIBSPDM_CRYPTO_ASN1_CONTEXT_SPECIFIC); |
| 93 | + if (result) { |
| 94 | + if ((obj_len != sizeof(m_libspdm_dice_tcbinfo_vendor)) || |
| 95 | + (!libspdm_consttime_is_mem_equal(ptr, m_libspdm_dice_tcbinfo_vendor, obj_len))) { |
| 96 | + return false; |
| 97 | + } |
| 98 | + ptr += obj_len; |
| 99 | + } else { |
| 100 | + return false; |
| 101 | + } |
| 102 | + /*model*/ |
| 103 | + result = libspdm_asn1_get_tag(&ptr, end, &obj_len, |
| 104 | + LIBSPDM_CRYPTO_ASN1_CONTEXT_SPECIFIC + 1); |
| 105 | + if (result) { |
| 106 | + if ((obj_len != sizeof(m_libspdm_dice_tcbinfo_model)) || |
| 107 | + (!libspdm_consttime_is_mem_equal(ptr, m_libspdm_dice_tcbinfo_model, obj_len))) { |
| 108 | + return false; |
| 109 | + } |
| 110 | + ptr += obj_len; |
| 111 | + } else { |
| 112 | + return false; |
| 113 | + } |
| 114 | + /*version*/ |
| 115 | + result = libspdm_asn1_get_tag(&ptr, end, &obj_len, |
| 116 | + LIBSPDM_CRYPTO_ASN1_CONTEXT_SPECIFIC + 2); |
| 117 | + if (result) { |
| 118 | + if ((obj_len != sizeof(m_libspdm_dice_tcbinfo_version)) || |
| 119 | + (!libspdm_consttime_is_mem_equal(ptr, m_libspdm_dice_tcbinfo_version, obj_len))) { |
| 120 | + return false; |
| 121 | + } |
| 122 | + ptr += obj_len; |
| 123 | + } else { |
| 124 | + return false; |
| 125 | + } |
| 126 | + /*svn*/ |
| 127 | + result = libspdm_asn1_get_tag(&ptr, end, &obj_len, |
| 128 | + LIBSPDM_CRYPTO_ASN1_CONTEXT_SPECIFIC + 3); |
| 129 | + if (result) { |
| 130 | + if ((obj_len != sizeof(m_libspdm_dice_tcbinfo_svn)) || |
| 131 | + (!libspdm_consttime_is_mem_equal(ptr, m_libspdm_dice_tcbinfo_svn, obj_len))) { |
| 132 | + return false; |
| 133 | + } |
| 134 | + ptr += obj_len; |
| 135 | + } else { |
| 136 | + return false; |
| 137 | + } |
| 138 | + /*layer*/ |
| 139 | + result = libspdm_asn1_get_tag(&ptr, end, &obj_len, |
| 140 | + LIBSPDM_CRYPTO_ASN1_CONTEXT_SPECIFIC + 4); |
| 141 | + if (result) { |
| 142 | + if ((obj_len != sizeof(m_libspdm_dice_tcbinfo_layer)) || |
| 143 | + (!libspdm_consttime_is_mem_equal(ptr, m_libspdm_dice_tcbinfo_layer, obj_len))) { |
| 144 | + return false; |
| 145 | + } |
| 146 | + ptr += obj_len; |
| 147 | + } |
| 148 | + /*index*/ |
| 149 | + result = libspdm_asn1_get_tag(&ptr, end, &obj_len, |
| 150 | + LIBSPDM_CRYPTO_ASN1_CONTEXT_SPECIFIC + 5); |
| 151 | + if (result) { |
| 152 | + ptr += obj_len; |
| 153 | + } |
| 154 | + /*fwids*/ |
| 155 | + result = libspdm_asn1_get_tag(&ptr, end, &obj_len, |
| 156 | + (LIBSPDM_CRYPTO_ASN1_CONTEXT_SPECIFIC | |
| 157 | + LIBSPDM_CRYPTO_ASN1_CONSTRUCTED) + 6); |
| 158 | + if (result) { |
| 159 | + if ((obj_len != sizeof(m_libspdm_dice_tcbinfo_fwids)) || |
| 160 | + (!libspdm_consttime_is_mem_equal(ptr, m_libspdm_dice_tcbinfo_fwids, obj_len))) { |
| 161 | + return false; |
| 162 | + } |
| 163 | + ptr += obj_len; |
| 164 | + } else { |
| 165 | + return false; |
| 166 | + } |
| 167 | + /*flags*/ |
| 168 | + result = libspdm_asn1_get_tag(&ptr, end, &obj_len, |
| 169 | + LIBSPDM_CRYPTO_ASN1_CONTEXT_SPECIFIC + 7); |
| 170 | + if (result) { |
| 171 | + ptr += obj_len; |
| 172 | + } |
| 173 | + /*vendorInfo*/ |
| 174 | + result = libspdm_asn1_get_tag(&ptr, end, &obj_len, |
| 175 | + LIBSPDM_CRYPTO_ASN1_CONTEXT_SPECIFIC + 8); |
| 176 | + if (result) { |
| 177 | + ptr += obj_len; |
| 178 | + } |
| 179 | + /*type*/ |
| 180 | + result = libspdm_asn1_get_tag(&ptr, end, &obj_len, |
| 181 | + LIBSPDM_CRYPTO_ASN1_CONTEXT_SPECIFIC + 9); |
| 182 | + if (result) { |
| 183 | + if ((obj_len != sizeof(m_libspdm_dice_tcbinfo_type)) || |
| 184 | + (!libspdm_consttime_is_mem_equal(ptr, m_libspdm_dice_tcbinfo_type, obj_len))) { |
| 185 | + return false; |
| 186 | + } |
| 187 | + ptr += obj_len; |
| 188 | + } else { |
| 189 | + return false; |
| 190 | + } |
| 191 | + /*flagMask*/ |
| 192 | + result = libspdm_asn1_get_tag(&ptr, end, &obj_len, |
| 193 | + LIBSPDM_CRYPTO_ASN1_CONTEXT_SPECIFIC + 10); |
| 194 | + if (result) { |
| 195 | + ptr += obj_len; |
| 196 | + } |
| 197 | + |
| 198 | + if (ptr == end) { |
| 199 | + return true; |
| 200 | + } else { |
| 201 | + return false; |
| 202 | + } |
| 203 | +} |
| 204 | + |
| 205 | +/*callback function for verifying cert_chain DiceTcbInfo extension*/ |
| 206 | +bool libspdm_verify_spdm_cert_chain_with_dice(void *spdm_context, uint8_t slot_id, |
| 207 | + size_t cert_chain_size, const void *cert_chain, |
| 208 | + const void **trust_anchor, |
| 209 | + size_t *trust_anchor_size) |
| 210 | +{ |
| 211 | + bool result; |
| 212 | + libspdm_context_t *context; |
| 213 | + const uint8_t *cert_chain_data; |
| 214 | + size_t cert_chain_data_size; |
| 215 | + size_t hash_size; |
| 216 | + uint8_t *ptr; |
| 217 | + uint8_t *tem_ptr; |
| 218 | + int32_t length; |
| 219 | + size_t obj_len; |
| 220 | + uint8_t *end; |
| 221 | + size_t cert_dice_tcb_info_size; |
| 222 | + bool cert_chain_have_matched_dice; |
| 223 | + uint8_t number_dice_tcb_info; |
| 224 | + |
| 225 | + /*verify peer cert chain integrity*/ |
| 226 | + result = libspdm_verify_peer_cert_chain_buffer_integrity(spdm_context, cert_chain, |
| 227 | + cert_chain_size); |
| 228 | + if (!result) { |
| 229 | + return false; |
| 230 | + } |
| 231 | + |
| 232 | + /*verify peer cert chain authority*/ |
| 233 | + result = libspdm_verify_peer_cert_chain_buffer_authority(spdm_context, cert_chain, |
| 234 | + cert_chain_size, trust_anchor, |
| 235 | + trust_anchor_size); |
| 236 | + if (!result) { |
| 237 | + return false; |
| 238 | + } |
| 239 | + |
| 240 | + context = spdm_context; |
| 241 | + hash_size = libspdm_get_hash_size(context->connection_info.algorithm.base_hash_algo); |
| 242 | + |
| 243 | + cert_chain_data = (const uint8_t *)cert_chain + sizeof(spdm_cert_chain_t) + hash_size; |
| 244 | + cert_chain_data_size = cert_chain_size - sizeof(spdm_cert_chain_t) - hash_size; |
| 245 | + |
| 246 | + length = (int32_t)cert_chain_data_size; |
| 247 | + ptr = (uint8_t*)(size_t)cert_chain_data; |
| 248 | + obj_len = 0; |
| 249 | + end = ptr + length; |
| 250 | + cert_chain_have_matched_dice = false; |
| 251 | + number_dice_tcb_info = 0; |
| 252 | + |
| 253 | + while (ptr < end) { |
| 254 | + cert_dice_tcb_info_size = 0; |
| 255 | + tem_ptr = ptr; |
| 256 | + result = libspdm_asn1_get_tag(&ptr, end, &obj_len, |
| 257 | + LIBSPDM_CRYPTO_ASN1_SEQUENCE | |
| 258 | + LIBSPDM_CRYPTO_ASN1_CONSTRUCTED); |
| 259 | + if (result) { |
| 260 | + /*verify Dice TCB info*/ |
| 261 | + result = libspdm_verify_cert_dicetcbinfo(tem_ptr, obj_len + (ptr - tem_ptr), |
| 262 | + &cert_dice_tcb_info_size); |
| 263 | + if (!result) { |
| 264 | + if (cert_dice_tcb_info_size == 0) { |
| 265 | + return false; |
| 266 | + } |
| 267 | + number_dice_tcb_info++; |
| 268 | + } else { |
| 269 | + if (cert_dice_tcb_info_size != 0) { |
| 270 | + cert_chain_have_matched_dice = true; |
| 271 | + number_dice_tcb_info++; |
| 272 | + } |
| 273 | + } |
| 274 | + /* Move to next cert*/ |
| 275 | + ptr += obj_len; |
| 276 | + } else { |
| 277 | + return false; |
| 278 | + } |
| 279 | + } |
| 280 | + |
| 281 | + if (m_libspdm_must_have_dice_tcb_info && !cert_chain_have_matched_dice) { |
| 282 | + return false; |
| 283 | + } |
| 284 | + |
| 285 | + /*check the number of cert with DiceTcbinfo in cert chain*/ |
| 286 | + if (number_dice_tcb_info != m_libspdm_dice_tcb_info_number) { |
| 287 | + return false; |
| 288 | + } |
| 289 | + |
| 290 | + if (ptr == end) { |
| 291 | + return true; |
| 292 | + } else { |
| 293 | + return false; |
| 294 | + } |
| 295 | +} |
0 commit comments