/*
 * Check for self-signedness in an X.509 cert and if found, check the signature
 * immediately if we can.
 */
int x509_check_for_self_signed(struct x509_certificate *cert)
{
	int ret = 0;

	pr_devel("==>%s()\n", __func__);

	if (cert->raw_subject_size != cert->raw_issuer_size ||
	    memcmp(cert->raw_subject, cert->raw_issuer,
		   cert->raw_issuer_size) != 0)
		goto not_self_signed;

	if (cert->sig->auth_ids[0] || cert->sig->auth_ids[1]) {
		/* If the AKID is present it may have one or two parts.  If
		 * both are supplied, both must match.
		 */
		bool a = asymmetric_key_id_same(cert->skid, cert->sig->auth_ids[1]);
		bool b = asymmetric_key_id_same(cert->id, cert->sig->auth_ids[0]);

		if (!a && !b)
			goto not_self_signed;

		ret = -EKEYREJECTED;
		if (((a && !b) || (b && !a)) &&
		    cert->sig->auth_ids[0] && cert->sig->auth_ids[1])
			goto out;
	}

	ret = -EKEYREJECTED;
	if (strcmp(cert->pub->pkey_algo, cert->sig->pkey_algo) != 0)
		goto out;

	ret = public_key_verify_signature(cert->pub, cert->sig);
	if (ret < 0) {
		if (ret == -ENOPKG) {
			cert->unsupported_sig = true;
			ret = 0;
		}
		goto out;
	}

	pr_devel("Cert Self-signature verified");
	cert->self_signed = true;

out:
	pr_devel("<==%s() = %d\n", __func__, ret);
	return ret;

not_self_signed:
	pr_devel("<==%s() = 0 [not]\n", __func__);
	return 0;
}
Example #2
0
/*
 * Check the signature on a certificate using the provided public key
 */
int x509_check_signature(const struct public_key *pub,
			 struct x509_certificate *cert)
{
	int ret;

	pr_devel("==>%s()\n", __func__);

	ret = x509_get_sig_params(cert);
	if (ret < 0)
		return ret;

	ret = public_key_verify_signature(pub, &cert->sig);
	pr_debug("Cert Verification: %d\n", ret);
	return ret;
}
Example #3
0
/*
 * Verify one signed information block from a PKCS#7 message.
 */
static int pkcs7_verify_one(struct pkcs7_message *pkcs7,
			    struct pkcs7_signed_info *sinfo)
{
	int ret;

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

	/* First of all, digest the data in the PKCS#7 message and the
	 * signed information block
	 */
	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)
		return 0;

	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.  We can't, however, check against the system clock
	 * since that may not have been set yet and may be wrong.
	 */
	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;

	pr_devel("Verified signature %u\n", sinfo->index);

	/* Verify the internal certificate chain */
	return pkcs7_verify_sig_chain(pkcs7, sinfo);
}
Example #4
0
/**
 * 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;
	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)
				goto verified;
			kleave(" = -ENOKEY [cached]");
			return -ENOKEY;
		}
		x509->seen = true;

		/* Look to see if this certificate is present in the trusted
		 * keys.
		 */
		key = find_asymmetric_key(trust_keyring,
					  x509->id, x509->skid, 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->signer == 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->sig->auth_ids[0] || last->sig->auth_ids[1])) {
		key = find_asymmetric_key(trust_keyring,
					  last->sig->auth_ids[0],
					  last->sig->auth_ids[1],
					  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 = find_asymmetric_key(trust_keyring,
				  sinfo->sig->auth_ids[0], NULL, 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 = public_key_verify_signature(key->public_key, sig);
	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;
	}
	kleave(" = 0");
	return 0;
}
Example #5
0
static int public_key_verify_signature_2(const struct key *key,
					 const struct public_key_signature *sig)
{
	const struct public_key *pk = key->payload.data;
	return public_key_verify_signature(pk, sig);
}
Example #6
0
/*
 * Verify the internal certificate chain as best we can.
 */
static int pkcs7_verify_sig_chain(struct pkcs7_message *pkcs7,
                                  struct pkcs7_signed_info *sinfo)
{
    struct public_key_signature *sig;
    struct x509_certificate *x509 = sinfo->signer, *p;
    struct asymmetric_key_id *auth;
    int ret;

    kenter("");

    for (p = pkcs7->certs; p; p = p->next)
        p->seen = false;

    for (;;) {
        pr_debug("verify %s: %*phN\n",
                 x509->subject,
                 x509->raw_serial_size, x509->raw_serial);
        x509->seen = true;
        if (x509->unsupported_key)
            goto unsupported_crypto_in_x509;

        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
             * the certificate must be self-signed and is the root
             * of the chain.  Likewise if the cert is its own
             * authority.
             */
            if (x509->unsupported_sig)
                goto unsupported_crypto_in_x509;
            x509->signer = x509;
            pr_debug("- self-signed\n");
            return 0;
        }

        /* Look through the X.509 certificates in the PKCS#7 message's
         * list to see if the next one is there.
         */
        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;
            }
        } else {
            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");
        return 0;

found_issuer_check_skid:
        /* We matched issuer + serialNumber, but if there's an
         * authKeyId.keyId, that must match the CA subjKeyId also.
         */
        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);
            return 0;
        }
        ret = public_key_verify_signature(p->pub, p->sig);
        if (ret < 0)
            return ret;
        x509->signer = p;
        if (x509 == p) {
            pr_debug("- self-signed\n");
            return 0;
        }
        x509 = p;
        might_sleep();
    }

unsupported_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->unsupported_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.
     */
    return 0;
}