While reviewing implementation for attesting the X.509v3 Certificate Extension provided in the AMD VCEK against the Attestation Report retrieved from the AMD Secure Processor, I stumbled across a bug in the parsing of the X.509v3 Certificate Extensions. Currently the implementation is using the function checkExtensionUint8(...) (which is defined in attestationreport.go) to parse the values from the certificate.
According to the SNP ABI Specification, the value should be an 8-bits in length, which is correct:
Bits |
Field |
Description |
63:56 |
MICROCODE |
• Lowest current patch level of all cores |
... |
... |
... |
However, according to RFC-5280 - Appendix B. ASN.1 Notes:
CAs MUST force the serialNumber to be a non-negative integer, that
is, the sign bit in the DER encoding of the INTEGER value MUST be
zero. This can be done by adding a leading (leftmost) `00'H octet if
necessary. This removes a potential ambiguity in mapping between a
string of octets and an integer value.
Which we will see when examining the contents of a VCEK certificate where that value is greater than 127:
Extension
Identifier: 1.3.6.1.4.1.3704.1.3.8
Value: 02 02 00 A9
Critical: No
Because this implementation is attempting to validate a specific value of 0x1
for the second octet, it will always return an error. Further, as it is attempting to parse an unsigned 8-bit integer from the wrong octet, if it didn't return an error, it would always fail to match the value present in the attestation report; as it will always be zero.
There are obviously a few ways this could be mitigated. One would be to check the second octet to derive the size from the certificate, and then parse that many bytes, down-casting the value to an unsigned 8-bit integer. Another way would be to check if the value doesn't equal one, and then parse the expected octet, instead.