|
@@ -181,7 +181,7 @@ static int pkcs7_verify_sig_chain(struct pkcs7_message *pkcs7,
|
|
|
x509->seen = true;
|
|
|
ret = x509_get_sig_params(x509);
|
|
|
if (ret < 0)
|
|
|
- return ret;
|
|
|
+ goto maybe_missing_crypto_in_x509;
|
|
|
|
|
|
pr_debug("- issuer %s\n", x509->issuer);
|
|
|
if (x509->authority)
|
|
@@ -203,7 +203,7 @@ static int pkcs7_verify_sig_chain(struct pkcs7_message *pkcs7,
|
|
|
|
|
|
ret = x509_check_signature(x509->pub, x509);
|
|
|
if (ret < 0)
|
|
|
- return ret;
|
|
|
+ goto maybe_missing_crypto_in_x509;
|
|
|
x509->signer = x509;
|
|
|
pr_debug("- self-signed\n");
|
|
|
return 0;
|
|
@@ -245,6 +245,17 @@ static int pkcs7_verify_sig_chain(struct pkcs7_message *pkcs7,
|
|
|
x509 = p;
|
|
|
might_sleep();
|
|
|
}
|
|
|
+
|
|
|
+maybe_missing_crypto_in_x509:
|
|
|
+ /* Just prune the certificate chain at this point if we lack some
|
|
|
+ * crypto module to go further. Note, however, we don't want to set
|
|
|
+ * sinfo->missing_crypto as the signed info block may still be
|
|
|
+ * validatable against an X.509 cert lower in the chain that we have a
|
|
|
+ * trusted copy of.
|
|
|
+ */
|
|
|
+ if (ret == -ENOPKG)
|
|
|
+ return 0;
|
|
|
+ return ret;
|
|
|
}
|
|
|
|
|
|
/*
|
|
@@ -286,11 +297,33 @@ static int pkcs7_verify_one(struct pkcs7_message *pkcs7,
|
|
|
/**
|
|
|
* pkcs7_verify - Verify a PKCS#7 message
|
|
|
* @pkcs7: The PKCS#7 message to be verified
|
|
|
+ *
|
|
|
+ * Verify a PKCS#7 message is internally consistent - that is, the data digest
|
|
|
+ * matches the digest in the AuthAttrs and any signature in the message or one
|
|
|
+ * of the X.509 certificates it carries that matches another X.509 cert in the
|
|
|
+ * message can be verified.
|
|
|
+ *
|
|
|
+ * This does not look to match the contents of the PKCS#7 message against any
|
|
|
+ * external public keys.
|
|
|
+ *
|
|
|
+ * Returns, in order of descending priority:
|
|
|
+ *
|
|
|
+ * (*) -EKEYREJECTED if a signature failed to match for which we found an
|
|
|
+ * appropriate X.509 certificate, or:
|
|
|
+ *
|
|
|
+ * (*) -EBADMSG if some part of the message was invalid, or:
|
|
|
+ *
|
|
|
+ * (*) -ENOPKG if none of the signature chains are verifiable because suitable
|
|
|
+ * crypto modules couldn't be found, or:
|
|
|
+ *
|
|
|
+ * (*) 0 if all the signature chains that don't incur -ENOPKG can be verified
|
|
|
+ * (note that a signature chain may be of zero length), or:
|
|
|
*/
|
|
|
int pkcs7_verify(struct pkcs7_message *pkcs7)
|
|
|
{
|
|
|
struct pkcs7_signed_info *sinfo;
|
|
|
struct x509_certificate *x509;
|
|
|
+ int enopkg = -ENOPKG;
|
|
|
int ret, n;
|
|
|
|
|
|
kenter("");
|
|
@@ -306,12 +339,17 @@ int pkcs7_verify(struct pkcs7_message *pkcs7)
|
|
|
for (sinfo = pkcs7->signed_infos; sinfo; sinfo = sinfo->next) {
|
|
|
ret = pkcs7_verify_one(pkcs7, sinfo);
|
|
|
if (ret < 0) {
|
|
|
+ if (ret == -ENOPKG) {
|
|
|
+ sinfo->unsupported_crypto = true;
|
|
|
+ continue;
|
|
|
+ }
|
|
|
kleave(" = %d", ret);
|
|
|
return ret;
|
|
|
}
|
|
|
+ enopkg = 0;
|
|
|
}
|
|
|
|
|
|
- kleave(" = 0");
|
|
|
- return 0;
|
|
|
+ kleave(" = %d", enopkg);
|
|
|
+ return enopkg;
|
|
|
}
|
|
|
EXPORT_SYMBOL_GPL(pkcs7_verify);
|