Software APIs
cert.c
1 // Copyright lowRISC contributors (OpenTitan project).
2 // Licensed under the Apache License, Version 2.0, see LICENSE for details.
3 // SPDX-License-Identifier: Apache-2.0
4 
5 #include "sw/device/silicon_creator/lib/cert/cert.h"
6 
9 #include "sw/device/silicon_creator/lib/error.h"
10 
11 static_assert(kCertX509Asn1SerialNumberSizeInBytes <= kHmacDigestNumBytes,
12  "The ASN.1 encoded X.509 serial number field should be <= the "
13  "size of a SHA256 digest.");
14 
15 uint32_t cert_x509_asn1_decode_size_header(const uint8_t *header) {
16  if (header[0] != 0x30 || header[1] != 0x82) {
17  return 0;
18  }
19  return (((uint32_t)header[2]) << 8) + header[3] + 4 /* size of the header */;
20 }
21 
22 rom_error_t cert_x509_asn1_check_serial_number(const uint8_t *cert, size_t size,
23  cert_key_id_t *expected_sn_bytes,
24  hardened_bool_t *matches) {
25  *matches = kHardenedBoolFalse;
26  if (size < kDiceX509MinSizeBytes) {
27  return kErrorCertInvalidSize;
28  }
29 
30  // We want the initializer for this to be `{0x02, 0x15, 0x00, ...}`, however
31  // that results in 23 bytes of .rodata, 20 of which we immediately overwrite
32  // by the memcpy below. Initialization with code results in 16 bytes of
33  // rv32imc code.
34  char expected_serial[kDiceX509SerialSizeBytes];
35  expected_serial[0] = 0x02;
36  expected_serial[1] = 0x15;
37  expected_serial[2] = 0x00;
38 
39  // Prepare expected serial number.
40  memcpy(&expected_serial[kDiceX509SerialHeaderSizeBytes], expected_sn_bytes,
41  kCertKeyIdSizeInBytes);
42  expected_serial[kDiceX509SerialHeaderSizeBytes] |= 0x80; // Tweak MSb.
43 
44  // Check if serial number matches.
45  const uint8_t *serial = cert + kDiceX509SerialOffsetBytes;
46  if (memcmp(serial, expected_serial, sizeof(expected_serial)) == 0) {
47  *matches = kHardenedBoolTrue;
48  }
49 
50  return kErrorOk;
51 }