diff --git a/src/tpm2_asn.c b/src/tpm2_asn.c index 7b1053e6..4891900c 100644 --- a/src/tpm2_asn.c +++ b/src/tpm2_asn.c @@ -100,6 +100,7 @@ static int TPM2_ASN_GetHeader(const uint8_t* input, byte tag, word32* inOutIdx, word32 idx = *inOutIdx; byte b; int length; + int rc; if ((idx + 1) > maxIdx) return TPM_RC_ASN_INSUFFICIENT; @@ -108,8 +109,9 @@ static int TPM2_ASN_GetHeader(const uint8_t* input, byte tag, word32* inOutIdx, if (b != tag) return TPM_RC_ASN_VALUE; - if (TPM2_ASN_GetLength(input, &idx, &length, maxIdx) < 0) - return TPM_RC_ASN_VALUE; + rc = TPM2_ASN_GetLength(input, &idx, &length, maxIdx); + if (rc < 0) + return rc; *len = length; *inOutIdx = idx; @@ -177,7 +179,7 @@ int TPM2_ASN_DecodeX509Cert(uint8_t* input, int inputSz, DecodedX509* x509) { int rc = 0; - word32 idx = 0, sigAlgEnd = 0; + word32 idx = 0, sigAlgEnd = 0, nameBegin = 0; word32 tbsSigAlgBegin = 0, tbsSigAlgSz = 0; word32 outerSigAlgBegin = 0, outerSigAlgSz = 0; int tot_len, cert_len = 0, len, pubkey_len = 0, sig_len = 0; @@ -244,13 +246,16 @@ int TPM2_ASN_DecodeX509Cert(uint8_t* input, int inputSz, tbsSigAlgSz = idx - tbsSigAlgBegin + (word32)len; idx += len; /* skip signature oid */ - /* Skip issuer */ + /* Issuer */ + x509->issuer = &input[idx]; + nameBegin = idx; rc = TPM2_ASN_GetHeader(input, TPM2_ASN_SEQUENCE | TPM2_ASN_CONSTRUCTED, &idx, &len, inputSz); } if (rc >= 0) { idx += len; /* skip issuer */ + x509->issuerSz = idx - nameBegin; /* Skip validity */ rc = TPM2_ASN_GetHeader(input, TPM2_ASN_SEQUENCE | TPM2_ASN_CONSTRUCTED, @@ -260,13 +265,16 @@ int TPM2_ASN_DecodeX509Cert(uint8_t* input, int inputSz, if (rc >= 0) { idx += len; /* skip validity */ - /* Skip subject */ + /* Subject */ + x509->subject = &input[idx]; + nameBegin = idx; rc = TPM2_ASN_GetHeader(input, TPM2_ASN_SEQUENCE | TPM2_ASN_CONSTRUCTED, &idx, &len, inputSz); } if (rc >= 0) { idx += len; /* skip subject */ + x509->subjectSz = idx - nameBegin; /* subject public key info */ rc = TPM2_ASN_GetHeader(input, TPM2_ASN_SEQUENCE | TPM2_ASN_CONSTRUCTED, &idx, &len, inputSz); @@ -357,6 +365,79 @@ int TPM2_ASN_DecodeX509Cert(uint8_t* input, int inputSz, return rc; } +int TPM2_ASN_GetNameAttr(const uint8_t* name, word32 nameSz, + const uint8_t* oid, word32 oidSz, const uint8_t** value, word32* valueSz) +{ + int rc; + int len, setLen, attrLen, oidLen; + int match; + word32 idx = 0, nameEnd, setEnd, attrEnd; + + if (name == NULL || oid == NULL || oidSz == 0 || value == NULL || + valueSz == NULL) { + return TPM_RC_ASN_VALUE; + } + + /* Name ::= SEQUENCE OF RelativeDistinguishedName */ + rc = TPM2_ASN_GetHeader(name, TPM2_ASN_SEQUENCE | TPM2_ASN_CONSTRUCTED, + &idx, &len, nameSz); + if (rc < 0) { + return rc; + } + nameEnd = idx + (word32)len; + + while (idx < nameEnd) { + /* RelativeDistinguishedName ::= SET OF AttributeTypeAndValue */ + rc = TPM2_ASN_GetHeader(name, TPM2_ASN_SET | TPM2_ASN_CONSTRUCTED, + &idx, &setLen, nameEnd); + if (rc < 0) { + return rc; + } + setEnd = idx + (word32)setLen; + + while (idx < setEnd) { + /* AttributeTypeAndValue ::= SEQUENCE { type OID, value ANY } */ + rc = TPM2_ASN_GetHeader(name, + TPM2_ASN_SEQUENCE | TPM2_ASN_CONSTRUCTED, &idx, &attrLen, + setEnd); + if (rc < 0) { + return rc; + } + attrEnd = idx + (word32)attrLen; + + rc = TPM2_ASN_GetHeader(name, TPM2_ASN_OBJECT_ID, &idx, &oidLen, + attrEnd); + if (rc < 0) { + return rc; + } + match = ((word32)oidLen == oidSz && + XMEMCMP(&name[idx], oid, oidSz) == 0); + idx += (word32)oidLen; + + /* value must be exactly one TLV filling the rest of the SEQUENCE */ + if (idx >= attrEnd) { + return TPM_RC_ASN_VALUE; + } + idx++; /* any string tag */ + rc = TPM2_ASN_GetLength(name, &idx, &len, attrEnd); + if (rc < 0) { + return rc; + } + if (idx + (word32)len != attrEnd) { + return TPM_RC_ASN_VALUE; + } + if (match) { + *value = &name[idx]; + *valueSz = (word32)len; + return 0; + } + idx = attrEnd; + } + } + + return TPM_RC_ASN_VALUE; +} + int TPM2_ASN_DecodeRsaPubKey(uint8_t* input, int inputSz, TPM2B_PUBLIC* pub) { diff --git a/tests/unit_tests.c b/tests/unit_tests.c index 155033ca..31ac6fba 100644 --- a/tests/unit_tests.c +++ b/tests/unit_tests.c @@ -8894,6 +8894,220 @@ static void test_TPM2_ASN_DecodeX509Cert_Valid(void) #endif } +static void test_TPM2_ASN_GetNameAttr(void) +{ +#if !defined(WOLFTPM2_NO_WRAPPER) && !defined(WOLFTPM2_NO_ASN) + /* from wolfSSL ./certs/server-ecc.der */ + static const byte cert[] = { + 0x30, 0x82, 0x02, 0xa4, 0x30, 0x82, 0x02, 0x4a, 0xa0, 0x03, 0x02, 0x01, + 0x02, 0x02, 0x01, 0x03, 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, + 0x3d, 0x04, 0x03, 0x02, 0x30, 0x81, 0x98, 0x31, 0x0b, 0x30, 0x09, 0x06, + 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x13, 0x30, 0x11, + 0x06, 0x03, 0x55, 0x04, 0x08, 0x0c, 0x0a, 0x57, 0x61, 0x73, 0x68, 0x69, + 0x6e, 0x67, 0x74, 0x6f, 0x6e, 0x31, 0x10, 0x30, 0x0e, 0x06, 0x03, 0x55, + 0x04, 0x07, 0x0c, 0x07, 0x53, 0x65, 0x61, 0x74, 0x74, 0x6c, 0x65, 0x31, + 0x10, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x07, 0x77, 0x6f, + 0x6c, 0x66, 0x53, 0x53, 0x4c, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, + 0x04, 0x0b, 0x0c, 0x0b, 0x44, 0x65, 0x76, 0x65, 0x6c, 0x6f, 0x70, 0x6d, + 0x65, 0x6e, 0x74, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x03, + 0x0c, 0x0f, 0x77, 0x77, 0x77, 0x2e, 0x77, 0x6f, 0x6c, 0x66, 0x73, 0x73, + 0x6c, 0x2e, 0x63, 0x6f, 0x6d, 0x31, 0x20, 0x30, 0x1e, 0x06, 0x09, 0x2a, + 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x01, 0x16, 0x11, 0x66, 0x61, + 0x63, 0x74, 0x73, 0x40, 0x77, 0x6f, 0x6c, 0x66, 0x73, 0x73, 0x6c, 0x2e, + 0x63, 0x6f, 0x6d, 0x30, 0x1e, 0x17, 0x0d, 0x32, 0x36, 0x30, 0x36, 0x31, + 0x31, 0x32, 0x31, 0x34, 0x34, 0x32, 0x39, 0x5a, 0x17, 0x0d, 0x32, 0x39, + 0x30, 0x33, 0x30, 0x37, 0x32, 0x31, 0x34, 0x34, 0x32, 0x39, 0x5a, 0x30, + 0x81, 0x91, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, + 0x0c, 0x0a, 0x57, 0x61, 0x73, 0x68, 0x69, 0x6e, 0x67, 0x74, 0x6f, 0x6e, + 0x31, 0x10, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x04, 0x07, 0x0c, 0x07, 0x53, + 0x65, 0x61, 0x74, 0x74, 0x6c, 0x65, 0x31, 0x11, 0x30, 0x0f, 0x06, 0x03, + 0x55, 0x04, 0x0a, 0x0c, 0x08, 0x45, 0x6c, 0x6c, 0x69, 0x70, 0x74, 0x69, + 0x63, 0x31, 0x0c, 0x30, 0x0a, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x0c, 0x03, + 0x45, 0x43, 0x43, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x03, + 0x0c, 0x0f, 0x77, 0x77, 0x77, 0x2e, 0x77, 0x6f, 0x6c, 0x66, 0x73, 0x73, + 0x6c, 0x2e, 0x63, 0x6f, 0x6d, 0x31, 0x20, 0x30, 0x1e, 0x06, 0x09, 0x2a, + 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x01, 0x16, 0x11, 0x66, 0x61, + 0x63, 0x74, 0x73, 0x40, 0x77, 0x6f, 0x6c, 0x66, 0x73, 0x73, 0x6c, 0x2e, + 0x63, 0x6f, 0x6d, 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2a, 0x86, 0x48, + 0xce, 0x3d, 0x02, 0x01, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, + 0x01, 0x07, 0x03, 0x42, 0x00, 0x04, 0xbb, 0x33, 0xac, 0x4c, 0x27, 0x50, + 0x4a, 0xc6, 0x4a, 0xa5, 0x04, 0xc3, 0x3c, 0xde, 0x9f, 0x36, 0xdb, 0x72, + 0x2d, 0xce, 0x94, 0xea, 0x2b, 0xfa, 0xcb, 0x20, 0x09, 0x39, 0x2c, 0x16, + 0xe8, 0x61, 0x02, 0xe9, 0xaf, 0x4d, 0xd3, 0x02, 0x93, 0x9a, 0x31, 0x5b, + 0x97, 0x92, 0x21, 0x7f, 0xf0, 0xcf, 0x18, 0xda, 0x91, 0x11, 0x02, 0x34, + 0x86, 0xe8, 0x20, 0x58, 0x33, 0x0b, 0x80, 0x34, 0x89, 0xd8, 0xa3, 0x81, + 0x89, 0x30, 0x81, 0x86, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, + 0x16, 0x04, 0x14, 0x5d, 0x5d, 0x26, 0xef, 0xac, 0x7e, 0x36, 0xf9, 0x9b, + 0x76, 0x15, 0x2b, 0x4a, 0x25, 0x02, 0x23, 0xef, 0xb2, 0x89, 0x30, 0x30, + 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, + 0x56, 0x8e, 0x9a, 0xc3, 0xf0, 0x42, 0xde, 0x18, 0xb9, 0x45, 0x55, 0x6e, + 0xf9, 0x93, 0xcf, 0xea, 0xc3, 0xf3, 0xa5, 0x21, 0x30, 0x0c, 0x06, 0x03, + 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x02, 0x30, 0x00, 0x30, 0x0e, + 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, 0x03, 0x02, + 0x03, 0xa8, 0x30, 0x13, 0x06, 0x03, 0x55, 0x1d, 0x25, 0x04, 0x0c, 0x30, + 0x0a, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x01, 0x30, + 0x11, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x86, 0xf8, 0x42, 0x01, 0x01, + 0x04, 0x04, 0x03, 0x02, 0x06, 0x40, 0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, + 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x03, 0x48, 0x00, 0x30, 0x45, 0x02, + 0x20, 0x45, 0x9c, 0xf5, 0x02, 0x68, 0xb0, 0x25, 0xcf, 0x84, 0x5b, 0xba, + 0x4c, 0xab, 0x95, 0x3b, 0xf3, 0x19, 0xe0, 0x7d, 0x05, 0x2b, 0x1d, 0xae, + 0x31, 0x6e, 0xb2, 0x08, 0x14, 0x52, 0xe1, 0xed, 0x3d, 0x02, 0x21, 0x00, + 0x98, 0x47, 0x72, 0x4f, 0xae, 0xeb, 0xc4, 0xe8, 0x02, 0x46, 0x51, 0x47, + 0x3c, 0x03, 0x2f, 0x4e, 0x67, 0x3d, 0x00, 0x07, 0x18, 0xa9, 0x66, 0x80, + 0x5f, 0xfe, 0x82, 0xe9, 0x68, 0x92, 0xf5, 0x97 + }; + static const byte oidCN[] = { 0x55, 0x04, 0x03 }; + static const byte oidSerial[] = { 0x55, 0x04, 0x05 }; + static const byte oidOU[] = { 0x55, 0x04, 0x0B }; + static const byte oidO[] = { 0x55, 0x04, 0x0A }; + static const byte multiRdn[] = { + 0x30, 0x1f, 0x31, 0x1d, + 0x30, 0x08, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x01, 'x', + 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x05, 0x13, 0x0a, + 'P', 'I', 'D', ':', 'A', ' ', 'S', 'N', ':', 'B' + }; + /* malformed Names, all looking up commonName */ + static const byte badLen[] = { 0x30, 0x81 }; + static const byte badTag[] = { 0x31, 0x00 }; + static const byte badSet[] = { 0x30, 0x02, 0x31, 0x05 }; + static const byte badAttr[] = { 0x30, 0x04, 0x31, 0x02, 0x30, 0x05 }; + static const byte badOid[] = { + 0x30, 0x06, 0x31, 0x04, 0x30, 0x02, 0x06, 0x05 + }; + static const byte noValue[] = { + 0x30, 0x09, 0x31, 0x07, 0x30, 0x05, 0x06, 0x03, 0x55, 0x04, 0x03 + }; + static const byte noValueOther[] = { + 0x30, 0x15, + 0x31, 0x07, 0x30, 0x05, 0x06, 0x03, 0x55, 0x04, 0x0a, + 0x31, 0x0a, 0x30, 0x08, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x01, 'a' + }; + static const byte extraField[] = { + 0x30, 0x0e, 0x31, 0x0c, 0x30, 0x0a, 0x06, 0x03, 0x55, 0x04, 0x03, + 0x0c, 0x01, 'a', 0x05, 0x00 + }; + static const byte valueTagOnly[] = { + 0x30, 0x0a, 0x31, 0x08, 0x30, 0x06, 0x06, 0x03, 0x55, 0x04, 0x03, + 0x0c + }; + static const byte valueLen[] = { + 0x30, 0x0c, 0x31, 0x0a, 0x30, 0x08, 0x06, 0x03, 0x55, 0x04, 0x03, + 0x0c, 0x05, 'a' + }; + static const struct { + const byte* name; + word32 nameSz; + int rc; + } bad[] = { + { badLen, sizeof(badLen), TPM_RC_ASN_INSUFFICIENT }, + { badTag, sizeof(badTag), TPM_RC_ASN_VALUE }, + { badSet, sizeof(badSet), TPM_RC_ASN_INSUFFICIENT }, + { badAttr, sizeof(badAttr), TPM_RC_ASN_INSUFFICIENT }, + { badOid, sizeof(badOid), TPM_RC_ASN_INSUFFICIENT }, + { noValue, sizeof(noValue), TPM_RC_ASN_VALUE }, + { noValueOther, sizeof(noValueOther), TPM_RC_ASN_VALUE }, + { extraField, sizeof(extraField), TPM_RC_ASN_VALUE }, + { valueTagOnly, sizeof(valueTagOnly), TPM_RC_ASN_INSUFFICIENT }, + { valueLen, sizeof(valueLen), TPM_RC_ASN_INSUFFICIENT }, + { noValue, 0, TPM_RC_ASN_INSUFFICIENT } + }; + byte certBuf[sizeof(cert)]; + DecodedX509 x509; + const byte* val = NULL; + word32 valSz = 0; + word32 i; + int rc; + + XMEMCPY(certBuf, cert, sizeof(cert)); + XMEMSET(&x509, 0, sizeof(x509)); + rc = TPM2_ASN_DecodeX509Cert(certBuf, (int)sizeof(certBuf), &x509); + AssertIntEQ(rc, 0); + AssertNotNull(x509.subject); + AssertNotNull(x509.issuer); + AssertIntGT(x509.subjectSz, 0); + AssertIntGT(x509.issuerSz, 0); + + rc = TPM2_ASN_GetNameAttr(x509.subject, x509.subjectSz, oidCN, + sizeof(oidCN), &val, &valSz); + AssertIntEQ(rc, 0); + AssertIntEQ(valSz, 15); + AssertIntEQ(XMEMCMP(val, "www.wolfssl.com", 15), 0); + + rc = TPM2_ASN_GetNameAttr(x509.subject, x509.subjectSz, oidO, + sizeof(oidO), &val, &valSz); + AssertIntEQ(rc, 0); + AssertIntEQ(valSz, 8); + AssertIntEQ(XMEMCMP(val, "Elliptic", 8), 0); + + rc = TPM2_ASN_GetNameAttr(x509.subject, x509.subjectSz, oidOU, + sizeof(oidOU), &val, &valSz); + AssertIntEQ(rc, 0); + AssertIntEQ(valSz, 3); + AssertIntEQ(XMEMCMP(val, "ECC", 3), 0); + + rc = TPM2_ASN_GetNameAttr(x509.issuer, x509.issuerSz, oidO, + sizeof(oidO), &val, &valSz); + AssertIntEQ(rc, 0); + AssertIntEQ(valSz, 7); + AssertIntEQ(XMEMCMP(val, "wolfSSL", 7), 0); + + rc = TPM2_ASN_GetNameAttr(x509.issuer, x509.issuerSz, oidOU, + sizeof(oidOU), &val, &valSz); + AssertIntEQ(rc, 0); + AssertIntEQ(valSz, 11); + AssertIntEQ(XMEMCMP(val, "Development", 11), 0); + + /* absent attribute */ + rc = TPM2_ASN_GetNameAttr(x509.subject, x509.subjectSz, oidSerial, + sizeof(oidSerial), &val, &valSz); + AssertIntEQ(rc, TPM_RC_ASN_VALUE); + + /* truncated Name must not read past the buffer */ + rc = TPM2_ASN_GetNameAttr(x509.subject, x509.subjectSz - 1, oidCN, + sizeof(oidCN), &val, &valSz); + AssertIntEQ(rc, TPM_RC_ASN_INSUFFICIENT); + + rc = TPM2_ASN_GetNameAttr(NULL, 0, oidCN, sizeof(oidCN), &val, &valSz); + AssertIntEQ(rc, TPM_RC_ASN_VALUE); + rc = TPM2_ASN_GetNameAttr(x509.subject, x509.subjectSz, NULL, + sizeof(oidCN), &val, &valSz); + AssertIntEQ(rc, TPM_RC_ASN_VALUE); + rc = TPM2_ASN_GetNameAttr(x509.subject, x509.subjectSz, oidCN, 0, + &val, &valSz); + AssertIntEQ(rc, TPM_RC_ASN_VALUE); + rc = TPM2_ASN_GetNameAttr(x509.subject, x509.subjectSz, oidCN, + sizeof(oidCN), NULL, &valSz); + AssertIntEQ(rc, TPM_RC_ASN_VALUE); + rc = TPM2_ASN_GetNameAttr(x509.subject, x509.subjectSz, oidCN, + sizeof(oidCN), &val, NULL); + AssertIntEQ(rc, TPM_RC_ASN_VALUE); + + for (i = 0; i < (word32)(sizeof(bad) / sizeof(bad[0])); i++) { + rc = TPM2_ASN_GetNameAttr(bad[i].name, bad[i].nameSz, oidCN, + sizeof(oidCN), &val, &valSz); + if (rc != bad[i].rc) { + printf("GetNameAttr bad case %u\n", (unsigned)i); + } + AssertIntEQ(rc, bad[i].rc); + } + + /* multi-valued RDN: SET { O=x, serialNumber=PID:A SN:B } */ + rc = TPM2_ASN_GetNameAttr(multiRdn, sizeof(multiRdn), oidSerial, + sizeof(oidSerial), &val, &valSz); + AssertIntEQ(rc, 0); + AssertIntEQ(valSz, 10); + AssertIntEQ(XMEMCMP(val, "PID:A SN:B", 10), 0); + rc = TPM2_ASN_GetNameAttr(multiRdn, sizeof(multiRdn), oidO, + sizeof(oidO), &val, &valSz); + AssertIntEQ(rc, 0); + AssertIntEQ(valSz, 1); + AssertIntEQ(val[0], 'x'); + + printf("Test TPM Wrapper: %-40s Passed\n", "ASN GetNameAttr:"); +#endif +} + static void test_TPM2_ASN_DecodeTag_Errors(void) { #if !defined(WOLFTPM2_NO_WRAPPER) && !defined(WOLFTPM2_NO_ASN) @@ -11534,6 +11748,7 @@ int unit_tests(int argc, char *argv[]) test_wolfTPM2_CryptoDevCb_KeyIdRefused(); test_wolfTPM2_CryptoDevCb_MlDsaKeyId(); test_TPM2_ASN_DecodeX509Cert_Errors(); + test_TPM2_ASN_GetNameAttr(); test_TPM2_ASN_RsaUnpadPkcsv15(); test_TPM2_ASN_TrimZeros(); test_TPM2_ASN_DecodeX509Cert_Valid(); diff --git a/wolftpm/tpm2_asn.h b/wolftpm/tpm2_asn.h index 1ff69870..74a421a8 100644 --- a/wolftpm/tpm2_asn.h +++ b/wolftpm/tpm2_asn.h @@ -66,7 +66,8 @@ enum { TPM2_ASN_BIT_STRING = 0x03, TPM2_ASN_OCTET_STRING = 0x04, TPM2_ASN_TAG_NULL = 0x05, - TPM2_ASN_OBJECT_ID = 0x06 + TPM2_ASN_OBJECT_ID = 0x06, + TPM2_ASN_SET = 0x11 }; #if defined(WOLFTPM2_NO_WOLFCRYPT) || defined(NO_RSA) @@ -83,6 +84,10 @@ typedef struct DecodedX509 { word32 pubKeySz; byte* signature; /* pointer to signature */ word32 sigSz; /* length of signature */ + byte* issuer; /* pointer to issuer Name (SEQUENCE TLV) */ + word32 issuerSz; + byte* subject; /* pointer to subject Name (SEQUENCE TLV) */ + word32 subjectSz; } DecodedX509; /* ASN.1 Decoder Functions */ @@ -144,6 +149,25 @@ WOLFTPM_API int TPM2_ASN_RsaDecodeSignature(uint8_t** pInput, int inputSz); WOLFTPM_API int TPM2_ASN_DecodeX509Cert(uint8_t* input, int inputSz, DecodedX509* x509); +/*! + \ingroup ASN + \brief Finds the first attribute with a given OID in an X.509 Name, such as + DecodedX509.subject or DecodedX509.issuer + \param name Buffer containing the DER encoded Name (SEQUENCE TLV) + \param nameSz Size of name buffer + \param oid DER content bytes of the attribute type OID (no tag or length), + for example {0x55, 0x04, 0x03} for commonName + \param oidSz Size of oid + \param value Set to point at the attribute value inside name (not NUL + terminated) + \param valueSz Set to the size of the attribute value + \return 0 on success, TPM_RC_ASN_VALUE if the attribute is not present, + on a bad argument or on malformed DER, TPM_RC_ASN_INSUFFICIENT if a + length runs past the end of name +*/ +WOLFTPM_API int TPM2_ASN_GetNameAttr(const uint8_t* name, word32 nameSz, + const uint8_t* oid, word32 oidSz, const uint8_t** value, word32* valueSz); + /*! \ingroup ASN \brief Decodes RSA public key from ASN.1 format into TPM2B_PUBLIC structure