/** * verify_pefile_signature - Verify the signature on a PE binary image * @pebuf: Buffer containing the PE binary image * @pelen: Length of the binary image * @trust_keyring: Signing certificates to use as starting points * @usage: The use to which the key is being put. * @_trusted: Set to true if trustworth, false otherwise * * Validate that the certificate chain inside the PKCS#7 message inside the PE * binary image intersects keys we already know and trust. * * Returns, in order of descending priority: * * (*) -ELIBBAD if the image cannot be parsed, or: * * (*) -EKEYREJECTED if a signature failed to match for which we have a valid * key, or: * * (*) 0 if at least one signature chain intersects with the keys in the trust * keyring, or: * * (*) -ENOPKG if a suitable crypto module couldn't be found for a check on a * chain. * * (*) -ENOKEY if we couldn't find a match for any of the signature chains in * the message. * * May also return -ENOMEM. */ int verify_pefile_signature(const void *pebuf, unsigned pelen, struct key *trusted_keyring, enum key_being_used_for usage, bool *_trusted) { struct pkcs7_message *pkcs7; struct pefile_context ctx; const void *data; size_t datalen; int ret; kenter(""); memset(&ctx, 0, sizeof(ctx)); ret = pefile_parse_binary(pebuf, pelen, &ctx); if (ret < 0) return ret; ret = pefile_strip_sig_wrapper(pebuf, &ctx); if (ret < 0) return ret; pkcs7 = pkcs7_parse_message(pebuf + ctx.sig_offset, ctx.sig_len); if (IS_ERR(pkcs7)) return PTR_ERR(pkcs7); ctx.pkcs7 = pkcs7; ret = pkcs7_get_content_data(ctx.pkcs7, &data, &datalen, false); if (ret < 0 || datalen == 0) { pr_devel("PKCS#7 message does not contain data\n"); ret = -EBADMSG; goto error; } ret = mscode_parse(&ctx); if (ret < 0) goto error; pr_debug("Digest: %u [%*ph]\n", ctx.digest_len, ctx.digest_len, ctx.digest); /* Generate the digest and check against the PKCS7 certificate * contents. */ ret = pefile_digest_pe(pebuf, pelen, &ctx); if (ret < 0) goto error; ret = pkcs7_verify(pkcs7, usage); if (ret < 0) goto error; ret = pkcs7_validate_trust(pkcs7, trusted_keyring, _trusted); error: pkcs7_free_message(ctx.pkcs7); return ret; }
/* * Instantiate a PKCS#7 wrapped and validated key. */ int pkcs7_instantiate(struct key *key, struct key_preparsed_payload *prep) { struct pkcs7_message *pkcs7; const void *data, *saved_prep_data; size_t datalen, saved_prep_datalen; bool trusted; int ret; kenter(""); saved_prep_data = prep->data; saved_prep_datalen = prep->datalen; pkcs7 = pkcs7_parse_message(saved_prep_data, saved_prep_datalen); if (IS_ERR(pkcs7)) { ret = PTR_ERR(pkcs7); goto error; } ret = pkcs7_verify(pkcs7); if (ret < 0) goto error_free; ret = pkcs7_validate_trust(pkcs7, system_trusted_keyring, &trusted); if (ret < 0) goto error_free; if (!trusted) pr_warn("PKCS#7 message doesn't chain back to a trusted key\n"); ret = pkcs7_get_content_data(pkcs7, &data, &datalen, false); if (ret < 0) goto error_free; prep->data = data; prep->datalen = datalen; ret = user_instantiate(key, prep); prep->data = saved_prep_data; prep->datalen = saved_prep_datalen; error_free: pkcs7_free_message(pkcs7); error: kleave(" = %d", ret); return ret; }
/** * verify_pkcs7_signature - Verify a PKCS#7-based signature on system data. * @data: The data to be verified (NULL if expecting internal data). * @len: Size of @data. * @raw_pkcs7: The PKCS#7 message that is the signature. * @pkcs7_len: The size of @raw_pkcs7. * @trusted_keys: Trusted keys to use (NULL for builtin trusted keys only, * (void *)1UL for all trusted keys). * @usage: The use to which the key is being put. * @view_content: Callback to gain access to content. * @ctx: Context for callback. */ int verify_pkcs7_signature(const void *data, size_t len, const void *raw_pkcs7, size_t pkcs7_len, struct key *trusted_keys, enum key_being_used_for usage, int (*view_content)(void *ctx, const void *data, size_t len, size_t asn1hdrlen), void *ctx) { struct pkcs7_message *pkcs7; int ret; pkcs7 = pkcs7_parse_message(raw_pkcs7, pkcs7_len); if (IS_ERR(pkcs7)) return PTR_ERR(pkcs7); /* The data should be detached - so we need to supply it. */ if (data && pkcs7_supply_detached_data(pkcs7, data, len) < 0) { pr_err("PKCS#7 signature with non-detached data\n"); ret = -EBADMSG; goto error; } ret = pkcs7_verify(pkcs7, usage); if (ret < 0) goto error; if (!trusted_keys) { trusted_keys = builtin_trusted_keys; } else if (trusted_keys == VERIFY_USE_SECONDARY_KEYRING) { #ifdef CONFIG_SECONDARY_TRUSTED_KEYRING trusted_keys = secondary_trusted_keys; #else trusted_keys = builtin_trusted_keys; #endif } ret = pkcs7_validate_trust(pkcs7, trusted_keys); if (ret < 0) { if (ret == -ENOKEY) pr_err("PKCS#7 signature not signed with a trusted key\n"); goto error; } if (view_content) { size_t asn1hdrlen; ret = pkcs7_get_content_data(pkcs7, &data, &len, &asn1hdrlen); if (ret < 0) { if (ret == -ENODATA) pr_devel("PKCS#7 message does not contain data\n"); goto error; } ret = view_content(ctx, data, len, asn1hdrlen); } error: pkcs7_free_message(pkcs7); pr_devel("<==%s() = %d\n", __func__, ret); return ret; }