コード例 #1
0
/*
 * Check the new certificate against the ones in the trust keyring.  If one of
 * those is the signing key and validates the new certificate, then mark the
 * new certificate as being trusted.
 *
 * Return 0 if the new certificate was successfully validated, 1 if we couldn't
 * find a matching parent certificate in the trusted list and an error if there
 * is a matching certificate but the signature check fails.
 */
static int x509_validate_trust(struct x509_certificate *cert,
			       struct key *trust_keyring)
{
	struct key *key;
	int ret = 1;

	if (!trust_keyring)
		return -EOPNOTSUPP;

	if (ca_keyid && !asymmetric_key_id_partial(cert->akid_skid, ca_keyid))
		return -EPERM;

	key = x509_request_asymmetric_key(trust_keyring, cert->akid_skid,
					  false);
	if (!IS_ERR(key))  {
		if (!use_builtin_keys
		    || test_bit(KEY_FLAG_BUILTIN, &key->flags))
			ret = x509_check_signature(key->payload.data, cert);
		key_put(key);
	}
	return ret;
}
コード例 #2
0
ファイル: pkcs7_trust.c プロジェクト: 0x000000FF/edison-linux
/**
 * Check the trust on one PKCS#7 SignedInfo block.
 */
static int pkcs7_validate_trust_one(struct pkcs7_message *pkcs7,
				    struct pkcs7_signed_info *sinfo,
				    struct key *trust_keyring)
{
	struct public_key_signature *sig = &sinfo->sig;
	struct x509_certificate *x509, *last = NULL, *p;
	struct key *key;
	bool trusted;
	int ret;

	kenter(",%u,", sinfo->index);

	if (sinfo->unsupported_crypto) {
		kleave(" = -ENOPKG [cached]");
		return -ENOPKG;
	}

	for (x509 = sinfo->signer; x509; x509 = x509->signer) {
		if (x509->seen) {
			if (x509->verified) {
				trusted = x509->trusted;
				goto verified;
			}
			kleave(" = -ENOKEY [cached]");
			return -ENOKEY;
		}
		x509->seen = true;

		/* Look to see if this certificate is present in the trusted
		 * keys.
		 */
		key = x509_request_asymmetric_key(trust_keyring, x509->id,
						  false);
		if (!IS_ERR(key)) {
			/* One of the X.509 certificates in the PKCS#7 message
			 * is apparently the same as one we already trust.
			 * Verify that the trusted variant can also validate
			 * the signature on the descendant.
			 */
			pr_devel("sinfo %u: Cert %u as key %x\n",
				 sinfo->index, x509->index, key_serial(key));
			goto matched;
		}
		if (key == ERR_PTR(-ENOMEM))
			return -ENOMEM;

		 /* Self-signed certificates form roots of their own, and if we
		  * don't know them, then we can't accept them.
		  */
		if (x509->next == x509) {
			kleave(" = -ENOKEY [unknown self-signed]");
			return -ENOKEY;
		}

		might_sleep();
		last = x509;
		sig = &last->sig;
	}

	/* No match - see if the root certificate has a signer amongst the
	 * trusted keys.
	 */
	if (last && last->authority) {
		key = x509_request_asymmetric_key(trust_keyring, last->authority,
						  false);
		if (!IS_ERR(key)) {
			x509 = last;
			pr_devel("sinfo %u: Root cert %u signer is key %x\n",
				 sinfo->index, x509->index, key_serial(key));
			goto matched;
		}
		if (PTR_ERR(key) != -ENOKEY)
			return PTR_ERR(key);
	}

	/* As a last resort, see if we have a trusted public key that matches
	 * the signed info directly.
	 */
	key = x509_request_asymmetric_key(trust_keyring,
					  sinfo->signing_cert_id,
					  false);
	if (!IS_ERR(key)) {
		pr_devel("sinfo %u: Direct signer is key %x\n",
			 sinfo->index, key_serial(key));
		x509 = NULL;
		goto matched;
	}
	if (PTR_ERR(key) != -ENOKEY)
		return PTR_ERR(key);

	kleave(" = -ENOKEY [no backref]");
	return -ENOKEY;

matched:
	ret = verify_signature(key, sig);
	trusted = test_bit(KEY_FLAG_TRUSTED, &key->flags);
	key_put(key);
	if (ret < 0) {
		if (ret == -ENOMEM)
			return ret;
		kleave(" = -EKEYREJECTED [verify %d]", ret);
		return -EKEYREJECTED;
	}

verified:
	if (x509) {
		x509->verified = true;
		for (p = sinfo->signer; p != x509; p = p->signer) {
			p->verified = true;
			p->trusted = trusted;
		}
	}
	sinfo->trusted = trusted;
	kleave(" = 0");
	return 0;
}