Пример #1
0
/*
 * Load the compiled-in list of X.509 certificates.
 */
static __init int load_system_certificate_list(void)
{
    key_ref_t key;
    const u8 *p, *end;
    size_t plen;

    pr_notice("Loading compiled-in X.509 certificates\n");

    p = system_certificate_list;
    end = p + system_certificate_list_size;
    while (p < end) {
        /* Each cert begins with an ASN.1 SEQUENCE tag and must be more
         * than 256 bytes in size.
         */
        if (end - p < 4)
            goto dodgy_cert;
        if (p[0] != 0x30 &&
                p[1] != 0x82)
            goto dodgy_cert;
        plen = (p[2] << 8) | p[3];
        plen += 4;
        if (plen > end - p)
            goto dodgy_cert;

        key = key_create_or_update(make_key_ref(system_trusted_keyring, 1),
                                   "asymmetric",
                                   NULL,
                                   p,
                                   plen,
                                   ((KEY_POS_ALL & ~KEY_POS_SETATTR) |
                                    KEY_USR_VIEW | KEY_USR_READ),
                                   KEY_ALLOC_NOT_IN_QUOTA |
                                   KEY_ALLOC_TRUSTED);
        if (IS_ERR(key)) {
            pr_err("Problem loading in-kernel X.509 certificate (%ld)\n",
                   PTR_ERR(key));
        } else {
            set_bit(KEY_FLAG_BUILTIN, &key_ref_to_ptr(key)->flags);
            pr_notice("Loaded X.509 cert '%s'\n",
                      key_ref_to_ptr(key)->description);
            key_ref_put(key);
        }
        p += plen;
    }

    return 0;

dodgy_cert:
    pr_err("Problem parsing in-kernel X.509 certificate list\n");
    return 0;
}
Пример #2
0
/*
 * Load the compiled-in keys
 */
static __init int load_module_signing_keys(void)
{
	key_ref_t key;
	const u8 *p, *end;
	size_t plen;

	pr_notice("Loading module verification certificates\n");

	end = modsign_certificate_list_end;
	p = modsign_certificate_list;
	while (p < end) {
		/* Each cert begins with an ASN.1 SEQUENCE tag and must be more
		 * than 256 bytes in size.
		 */
		if (end - p < 4)
			goto dodgy_cert;
		if (p[0] != 0x30 &&
		    p[1] != 0x82)
			goto dodgy_cert;
		plen = (p[2] << 8) | p[3];
		plen += 4;
		if (plen > end - p)
			goto dodgy_cert;

		key = key_create_or_update(make_key_ref(modsign_keyring, 1),
					   "asymmetric",
					   NULL,
					   p,
					   plen,
					   (KEY_POS_ALL & ~KEY_POS_SETATTR) |
					   KEY_USR_VIEW,
					   KEY_ALLOC_NOT_IN_QUOTA);
		if (IS_ERR(key))
			pr_err("MODSIGN: Problem loading in-kernel X.509 certificate (%ld)\n",
			       PTR_ERR(key));
		else
			pr_notice("MODSIGN: Loaded cert '%s'\n",
				  key_ref_to_ptr(key)->description);
		p += plen;
	}

	return 0;

dodgy_cert:
	pr_err("MODSIGN: Problem parsing in-kernel X.509 certificate list\n");
	return 0;
}
Пример #3
0
int __init integrity_add_key(const unsigned int id, const void *data,
			     off_t size, key_perm_t perm)
{
	key_ref_t key;
	int rc = 0;

	if (!keyring[id])
		return -EINVAL;

	key = key_create_or_update(make_key_ref(keyring[id], 1), "asymmetric",
				   NULL, data, size, perm,
				   KEY_ALLOC_NOT_IN_QUOTA);
	if (IS_ERR(key)) {
		rc = PTR_ERR(key);
		pr_err("Problem loading X.509 certificate %d\n", rc);
	} else {
		pr_notice("Loaded X.509 cert '%s'\n",
			  key_ref_to_ptr(key)->description);
		key_ref_put(key);
	}

	return rc;

}
Пример #4
0
/*
 * Extract the description of a new key from userspace and either add it as a
 * new key to the specified keyring or update a matching key in that keyring.
 *
 * If the description is NULL or an empty string, the key type is asked to
 * generate one from the payload.
 *
 * The keyring must be writable so that we can attach the key to it.
 *
 * If successful, the new key's serial number is returned, otherwise an error
 * code is returned.
 */
SYSCALL_DEFINE5(add_key, const char __user *, _type,
		const char __user *, _description,
		const void __user *, _payload,
		size_t, plen,
		key_serial_t, ringid)
{
	key_ref_t keyring_ref, key_ref;
	char type[32], *description;
	void *payload;
	long ret;
	bool vm;

	ret = -EINVAL;
	if (plen > 1024 * 1024 - 1)
		goto error;

	/* draw all the data into kernel space */
	ret = key_get_type_from_user(type, _type, sizeof(type));
	if (ret < 0)
		goto error;

	description = NULL;
	if (_description) {
		description = strndup_user(_description, PAGE_SIZE);
		if (IS_ERR(description)) {
			ret = PTR_ERR(description);
			goto error;
		}
		if (!*description) {
			kfree(description);
			description = NULL;
		}
	}

	/* pull the payload in if one was supplied */
	payload = NULL;

	vm = false;
	if (_payload) {
		ret = -ENOMEM;
		payload = kmalloc(plen, GFP_KERNEL | __GFP_NOWARN);
		if (!payload) {
			if (plen <= PAGE_SIZE)
				goto error2;
			vm = true;
			payload = vmalloc(plen);
			if (!payload)
				goto error2;
		}

		ret = -EFAULT;
		if (copy_from_user(payload, _payload, plen) != 0)
			goto error3;
	}

	/* find the target keyring (which must be writable) */
	keyring_ref = lookup_user_key(ringid, KEY_LOOKUP_CREATE, KEY_WRITE);
	if (IS_ERR(keyring_ref)) {
		ret = PTR_ERR(keyring_ref);
		goto error3;
	}

	/* create or update the requested key and add it to the target
	 * keyring */
	key_ref = key_create_or_update(keyring_ref, type, description,
				       payload, plen, KEY_PERM_UNDEF,
				       KEY_ALLOC_IN_QUOTA);
	if (!IS_ERR(key_ref)) {
		ret = key_ref_to_ptr(key_ref)->serial;
		key_ref_put(key_ref);
	}
	else {
		ret = PTR_ERR(key_ref);
	}

	key_ref_put(keyring_ref);
 error3:
	if (!vm)
		kfree(payload);
	else
		vfree(payload);
 error2:
	kfree(description);
 error:
	return ret;
}
Пример #5
0
/*
 * extract the description of a new key from userspace and either add it as a
 * new key to the specified keyring or update a matching key in that keyring
 * - the keyring must be writable
 * - returns the new key's serial number
 * - implements add_key()
 */
asmlinkage long sys_add_key(const char __user *_type,
			    const char __user *_description,
			    const void __user *_payload,
			    size_t plen,
			    key_serial_t ringid)
{
	key_ref_t keyring_ref, key_ref;
	char type[32], *description;
	void *payload;
	long dlen, ret;

	ret = -EINVAL;
	if (plen > 32767)
		goto error;

	/* draw all the data into kernel space */
	ret = strncpy_from_user(type, _type, sizeof(type) - 1);
	if (ret < 0)
		goto error;
	type[31] = '\0';

	ret = -EPERM;
	if (type[0] == '.')
		goto error;

	ret = -EFAULT;
	dlen = strnlen_user(_description, PAGE_SIZE - 1);
	if (dlen <= 0)
		goto error;

	ret = -EINVAL;
	if (dlen > PAGE_SIZE - 1)
		goto error;

	ret = -ENOMEM;
	description = kmalloc(dlen + 1, GFP_KERNEL);
	if (!description)
		goto error;

	ret = -EFAULT;
	if (copy_from_user(description, _description, dlen + 1) != 0)
		goto error2;

	/* pull the payload in if one was supplied */
	payload = NULL;

	if (_payload) {
		ret = -ENOMEM;
		payload = kmalloc(plen, GFP_KERNEL);
		if (!payload)
			goto error2;

		ret = -EFAULT;
		if (copy_from_user(payload, _payload, plen) != 0)
			goto error3;
	}

	/* find the target keyring (which must be writable) */
	keyring_ref = lookup_user_key(NULL, ringid, 1, 0, KEY_WRITE);
	if (IS_ERR(keyring_ref)) {
		ret = PTR_ERR(keyring_ref);
		goto error3;
	}

	/* create or update the requested key and add it to the target
	 * keyring */
	key_ref = key_create_or_update(keyring_ref, type, description,
				       payload, plen, 0);
	if (!IS_ERR(key_ref)) {
		ret = key_ref_to_ptr(key_ref)->serial;
		key_ref_put(key_ref);
	}
	else {
		ret = PTR_ERR(key_ref);
	}

	key_ref_put(keyring_ref);
 error3:
	kfree(payload);
 error2:
	kfree(description);
 error:
	return ret;

} /* end sys_add_key() */