// SPDX-License-Identifier: GPL-2.0-or-later /* Parse a signed PE binary * *Copyright(C)2014RedHat,Inc.AllRightsReserved. *WrittenbyDavidHowells(dhowells@redhat.com)
*/
/* sbsign rounds up the length of certificate table (in optional *headerdatadirectories)to8bytealignment.However,thePE *specificationstatesthatwhileentriesare8-bytealigned,thisis *notincludedintheirlength,andasaresult,pesignhasnot *roundedupsince0.110.
*/ if (wrapper.length > ctx->sig_len) {
pr_warn("Signature wrapper bigger than sig len (%x > %x)\n",
ctx->sig_len, wrapper.length); return -ELIBBAD;
} if (wrapper.revision != WIN_CERT_REVISION_2_0) {
pr_warn("Signature is not revision 2.0\n"); return -ENOTSUPP;
} if (wrapper.cert_type != WIN_CERT_TYPE_PKCS_SIGNED_DATA) {
pr_warn("Signature certificate type is not PKCS\n"); return -ENOTSUPP;
}
/* It looks like the pkcs signature length in wrapper->length and the *sizeobtainedfromthedatadirentries,whichliststhetotalsize *ofcertificatetable,arebothalignedtoanoctawordboundary,so *wemayhavetodealwithsomepadding.
*/
ctx->sig_len = wrapper.length;
ctx->sig_offset += sizeof(wrapper);
ctx->sig_len -= sizeof(wrapper); if (ctx->sig_len < 4) {
pr_warn("Signature data missing\n"); return -EKEYREJECTED;
}
/* What's left should be a PKCS#7 cert */
pkcs7 = pebuf + ctx->sig_offset; if (pkcs7[0] != (ASN1_CONS_BIT | ASN1_SEQ)) goto not_pkcs7;
check_len: if (len <= ctx->sig_len) { /* There may be padding */
ctx->sig_len = len; return0;
}
not_pkcs7:
pr_warn("Signature data not PKCS#7\n"); return -ELIBBAD;
}
/* Digest the header and data directory, but leave out the image *checksumandthedatadirentforthesignature.
*/
ret = crypto_shash_update(desc, pebuf, ctx->image_checksum_offset); if (ret < 0) return ret;
tmp = ctx->image_checksum_offset + sizeof(uint32_t);
ret = crypto_shash_update(desc, pebuf + tmp,
ctx->cert_dirent_offset - tmp); if (ret < 0) return ret;
canon = kcalloc(ctx->n_sections, sizeof(unsigned), GFP_KERNEL); if (!canon) return -ENOMEM;
/* We have to canonicalise the section table, so we perform an *insertionsort.
*/
canon[0] = 0; for (loop = 1; loop < ctx->n_sections; loop++) { for (i = 0; i < loop; i++) { if (pefile_compare_shdrs(&ctx->secs[canon[i]],
&ctx->secs[loop]) > 0) {
memmove(&canon[i + 1], &canon[i],
(loop - i) * sizeof(canon[0])); break;
}
}
canon[i] = loop;
}
hashed_bytes = ctx->header_size; for (loop = 0; loop < ctx->n_sections; loop++) {
i = canon[loop]; if (ctx->secs[i].raw_data_size == 0) continue;
ret = crypto_shash_update(desc,
pebuf + ctx->secs[i].data_addr,
ctx->secs[i].raw_data_size); if (ret < 0) {
kfree(canon); return ret;
}
hashed_bytes += ctx->secs[i].raw_data_size;
}
kfree(canon);
if (pelen > hashed_bytes) {
tmp = hashed_bytes + ctx->certs_size;
ret = crypto_shash_update(desc,
pebuf + hashed_bytes,
pelen - tmp); if (ret < 0) return ret;
}
/* Allocate the hashing algorithm we're going to need and find out how *bigthehashoperationaldatawillbe.
*/
tfm = crypto_alloc_shash(ctx->digest_algo, 0, 0); if (IS_ERR(tfm)) return (PTR_ERR(tfm) == -ENOENT) ? -ENOPKG : PTR_ERR(tfm);
/* Check that the PE file digest matches that in the MSCODE part of the *PKCS#7certificate.
*/ if (memcmp(digest, ctx->digest, ctx->digest_len) != 0) {
pr_warn("Digest mismatch\n");
ret = -EKEYREJECTED;
} else {
pr_debug("The digests match!\n");
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.