// SPDX-License-Identifier: GPL-2.0-or-later /* Verify the signature on a PKCS#7 message. * *Copyright(C)2012RedHat,Inc.AllRightsReserved. *WrittenbyDavidHowells(dhowells@redhat.com)
*/
/* The digest was calculated already. */ if (sig->digest) return0;
if (!sinfo->sig->hash_algo) return -ENOPKG;
/* Allocate the hashing algorithm we're going to need and find out how *bigthehashoperationaldatawillbe.
*/
tfm = crypto_alloc_shash(sinfo->sig->hash_algo, 0, 0); if (IS_ERR(tfm)) return (PTR_ERR(tfm) == -ENOENT) ? -ENOPKG : PTR_ERR(tfm);
ret = -ENOMEM;
sig->digest = kmalloc(sig->digest_size, GFP_KERNEL); if (!sig->digest) goto error_no_desc;
desc = kzalloc(desc_size, GFP_KERNEL); if (!desc) goto error_no_desc;
desc->tfm = tfm;
/* Digest the message [RFC2315 9.3] */
ret = crypto_shash_digest(desc, pkcs7->data, pkcs7->data_len,
sig->digest); if (ret < 0) goto error;
pr_devel("MsgDigest = [%*ph]\n", 8, sig->digest);
/* However, if there are authenticated attributes, there must be a *messagedigestattributeamongstthemwhichcorrespondstothe *digestwejustcalculated.
*/ if (sinfo->authattrs) {
u8 tag;
if (!sinfo->msgdigest) {
pr_warn("Sig %u: No messageDigest\n", sinfo->index);
ret = -EKEYREJECTED; goto error;
}
if (sinfo->msgdigest_len != sig->digest_size) {
pr_warn("Sig %u: Invalid digest size (%u)\n",
sinfo->index, sinfo->msgdigest_len);
ret = -EBADMSG; goto error;
}
if (memcmp(sig->digest, sinfo->msgdigest,
sinfo->msgdigest_len) != 0) {
pr_warn("Sig %u: Message digest doesn't match\n",
sinfo->index);
ret = -EKEYREJECTED; goto error;
}
/* We then calculate anew, using the authenticated attributes *asthecontentsofthedigestinstead.Notethatweneedto *converttheattributesfromaCONT.0intoaSETbeforewe *hashit.
*/
memset(sig->digest, 0, sig->digest_size);
ret = crypto_shash_init(desc); if (ret < 0) goto error;
tag = ASN1_CONS_BIT | ASN1_SET;
ret = crypto_shash_update(desc, &tag, 1); if (ret < 0) goto error;
ret = crypto_shash_finup(desc, sinfo->authattrs,
sinfo->authattrs_len, sig->digest); if (ret < 0) goto error;
pr_devel("AADigest = [%*ph]\n", 8, sig->digest);
}
for (x509 = pkcs7->certs; x509; x509 = x509->next, certix++) { /* I'm _assuming_ that the generator of the PKCS#7 message will *encodethefieldsfromtheX.509certinthesamewayinthe *PKCS#7message-butIcan'tbe100%sureofthat.It's *possiblethiswillneedelement-by-elementcomparison.
*/ if (!asymmetric_key_id_same(x509->id, sinfo->sig->auth_ids[0])) continue;
pr_devel("Sig %u: Found cert serial match X.509[%u]\n",
sinfo->index, certix);
sinfo->signer = x509; return0;
}
/* The relevant X.509 cert isn't found here, but it might be found in *thetrustkeyring.
*/
pr_debug("Sig %u: Issuing X.509 cert not found (#%*phN)\n",
sinfo->index,
sinfo->sig->auth_ids[0]->len, sinfo->sig->auth_ids[0]->data); return0;
}
if (x509->blacklisted) { /* If this cert is blacklisted, then mark everything *thatdependsonthisasblacklistedtoo.
*/
sinfo->blacklisted = true; for (p = sinfo->signer; p != x509; p = p->signer)
p->blacklisted = true;
pr_debug("- blacklisted\n"); return0;
}
pr_debug("- issuer %s\n", x509->issuer);
sig = x509->sig; if (sig->auth_ids[0])
pr_debug("- authkeyid.id %*phN\n",
sig->auth_ids[0]->len, sig->auth_ids[0]->data); if (sig->auth_ids[1])
pr_debug("- authkeyid.skid %*phN\n",
sig->auth_ids[1]->len, sig->auth_ids[1]->data);
if (x509->self_signed) { /* If there's no authority certificate specified, then *thecertificatemustbeself-signedandistheroot *ofthechain.Likewiseifthecertisitsown *authority.
*/ if (x509->unsupported_sig) goto unsupported_sig_in_x509;
x509->signer = x509;
pr_debug("- self-signed\n"); return0;
}
/* Look through the X.509 certificates in the PKCS#7 message's *listtoseeifthenextoneisthere.
*/
auth = sig->auth_ids[0]; if (auth) {
pr_debug("- want %*phN\n", auth->len, auth->data); for (p = pkcs7->certs; p; p = p->next) {
pr_debug("- cmp [%u] %*phN\n",
p->index, p->id->len, p->id->data); if (asymmetric_key_id_same(p->id, auth)) goto found_issuer_check_skid;
}
} elseif (sig->auth_ids[1]) {
auth = sig->auth_ids[1];
pr_debug("- want %*phN\n", auth->len, auth->data); for (p = pkcs7->certs; p; p = p->next) { if (!p->skid) continue;
pr_debug("- cmp [%u] %*phN\n",
p->index, p->skid->len, p->skid->data); if (asymmetric_key_id_same(p->skid, auth)) goto found_issuer;
}
}
/* We didn't find the root of this chain */
pr_debug("- top\n"); return0;
found_issuer_check_skid: /* We matched issuer + serialNumber, but if there's an *authKeyId.keyId,thatmustmatchtheCAsubjKeyIdalso.
*/ if (sig->auth_ids[1] &&
!asymmetric_key_id_same(p->skid, sig->auth_ids[1])) {
pr_warn("Sig %u: X.509 chain contains auth-skid nonmatch (%u->%u)\n",
sinfo->index, x509->index, p->index); return -EKEYREJECTED;
}
found_issuer:
pr_debug("- subject %s\n", p->subject); if (p->seen) {
pr_warn("Sig %u: X.509 chain contains loop\n",
sinfo->index); return0;
}
ret = public_key_verify_signature(p->pub, x509->sig); if (ret < 0) return ret;
x509->signer = p; if (x509 == p) {
pr_debug("- self-signed\n"); return0;
}
x509 = p;
might_sleep();
}
unsupported_sig_in_x509: /* Just prune the certificate chain at this point if we lack some *cryptomoduletogofurther.Note,however,wedon'twanttoset *sinfo->unsupported_cryptoasthesignedinfoblockmaystillbe *validatableagainstanX.509certlowerinthechainthatwehavea *trustedcopyof.
*/ return0;
}
/* First of all, digest the data in the PKCS#7 message and the *signedinformationblock
*/
ret = pkcs7_digest(pkcs7, sinfo); if (ret < 0) return ret;
/* Find the key for the signature if there is one */
ret = pkcs7_find_key(pkcs7, sinfo); if (ret < 0) return ret;
if (!sinfo->signer) return0;
pr_devel("Using X.509[%u] for sig %u\n",
sinfo->signer->index, sinfo->index);
/* Check that the PKCS#7 signing time is valid according to the X.509 *certificate.Wecan't,however,checkagainstthesystemclock *sincethatmaynothavebeensetyetandmaybewrong.
*/ if (test_bit(sinfo_has_signing_time, &sinfo->aa_set)) { if (sinfo->signing_time < sinfo->signer->valid_from ||
sinfo->signing_time > sinfo->signer->valid_to) {
pr_warn("Message signed outside of X.509 validity window\n"); return -EKEYREJECTED;
}
}
/* Verify the PKCS#7 binary against the key */
ret = public_key_verify_signature(sinfo->signer->pub, sinfo->sig); if (ret < 0) return ret;
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.