diff --git a/idc.c b/idc.c index 0e49b66..289f9c2 100644 --- a/idc.c +++ b/idc.c @@ -217,20 +217,48 @@ int IDC_set(PKCS7 *p7, PKCS7_SIGNER_INFO *si, struct image *image) return 0; } -int IDC_check_hash(struct image *image, PKCS7 *p7) +struct idc *IDC_get(PKCS7 *p7, BIO *bio) +{ + const unsigned char *buf, *idcbuf; + ASN1_STRING *str; + IDC *idc; + + /* extract the idc from the signed PKCS7 'other' data */ + str = p7->d.sign->contents->d.other->value.asn1_string; + idcbuf = buf = ASN1_STRING_data(str); + idc = d2i_IDC(NULL, &buf, ASN1_STRING_length(str)); + + /* If we were passed a BIO, write the idc data, minus type and length, + * to the BIO. This can be used to PKCS7_verify the idc */ + if (bio) { + uint32_t idclen; + uint8_t tmp; + + tmp = idcbuf[1]; + + if (!(tmp & 0x80)) { + idclen = tmp & 0x7f; + idcbuf += 2; + } else if ((tmp & 0x82) == 0x82) { + idclen = (idcbuf[2] << 8) + + idcbuf[3]; + idcbuf += 4; + } + + BIO_write(bio, idcbuf, idclen); + } + + return idc; +} + +int IDC_check_hash(struct idc *idc, struct image *image) { unsigned char sha[SHA256_DIGEST_LENGTH]; const unsigned char *buf; ASN1_STRING *str; - IDC *idc; image_hash_sha256(image, sha); - /* extract the idc from the signed PKCS7 'other' data */ - str = p7->d.sign->contents->d.other->value.asn1_string; - buf = ASN1_STRING_data(str); - idc = d2i_IDC(NULL, &buf, ASN1_STRING_length(str)); - /* check hash algorithm sanity */ if (OBJ_cmp(idc->digest->alg->algorithm, OBJ_nid2obj(NID_sha256))) { fprintf(stderr, "Invalid algorithm type\n"); diff --git a/idc.h b/idc.h index ecd6b97..9572258 100644 --- a/idc.h +++ b/idc.h @@ -23,8 +23,11 @@ #include +struct idc; + int IDC_set(PKCS7 *p7, PKCS7_SIGNER_INFO *si, struct image *image); -int IDC_check_hash(struct image *image, PKCS7 *p7); +struct idc *IDC_get(PKCS7 *p7, BIO *bio); +int IDC_check_hash(struct idc *idc, struct image *image); #endif /* IDC_H */ diff --git a/sbverify.c b/sbverify.c index 90e18cd..3ea159a 100644 --- a/sbverify.c +++ b/sbverify.c @@ -40,9 +40,9 @@ int main(int argc, char **argv) struct cert_table_header *header; enum verify_status status; struct image *image; - uint8_t *idcbuf, tmp; const uint8_t *buf; - int idclen, rc; + struct idc *idc; + int rc; BIO *idcbio; PKCS7 *p7; @@ -70,29 +70,17 @@ int main(int argc, char **argv) buf = (void *)(header + 1); p7 = d2i_PKCS7(NULL, &buf, header->size); - rc = IDC_check_hash(image, p7); + idcbio = BIO_new(BIO_s_mem()); + idc = IDC_get(p7, idcbio); + if (!idc) + goto out; + + rc = IDC_check_hash(idc, image); if (rc) goto out; - idcbuf = p7->d.sign->contents->d.other->value.asn1_string->data; - - /* we don't include the type and length data in the hash */ - tmp = idcbuf[1]; - if (!(tmp & 0x80)) { - idclen = tmp & 0x7f; - idcbuf += 2; - } else if ((tmp & 0x82) == 0x82) { - idclen = (idcbuf[2] << 8) + - idcbuf[3]; - idcbuf += 4; - } - - idcbio = BIO_new(BIO_s_mem()); - BIO_write(idcbio, idcbuf, idclen); - rc = PKCS7_verify(p7, NULL, NULL, idcbio, NULL, PKCS7_BINARY | PKCS7_NOVERIFY); - if (!rc) { printf("PKCS7 verification failed\n"); ERR_print_errors_fp(stderr);