blob: ca4cfe673b24413789b75f62461dfa624d3a0c7a [file] [log] [blame]
/* Cryptographic key request handling
*
* Copyright (C) 2011 Red Hat, Inc. All Rights Reserved.
* Written by David Howells (dhowells@redhat.com)
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public Licence
* as published by the Free Software Foundation; either version
* 2 of the Licence, or (at your option) any later version.
*
* See Documentation/security/keys-crypto.txt
*/
#include <linux/module.h>
#include <linux/key.h>
#include <linux/pgplib.h>
#include <linux/err.h>
#include <keys/crypto-type.h>
#include "crypto_keys.h"
struct preload_pgp_keys_context {
struct pgp_parse_context pgp;
key_ref_t keyring;
const u8 *key_start;
const u8 *key_end;
bool found_key;
};
/*
* Create a key.
*/
static int __init create_pgp_key(struct preload_pgp_keys_context *ctx)
{
key_ref_t key;
key = key_create_or_update(ctx->keyring, "crypto", NULL,
ctx->key_start,
ctx->key_end - ctx->key_start,
KEY_POS_ALL | KEY_USR_VIEW,
KEY_ALLOC_NOT_IN_QUOTA);
if (IS_ERR(key))
return PTR_ERR(key);
pr_notice("Loaded %s key: %s\n",
key_ref_to_ptr(key)->description,
crypto_key_id(key_ref_to_ptr(key)));
key_ref_put(key);
return 0;
}
/*
* Extract a public key or subkey from the PGP stream.
*/
static int __init found_pgp_key(struct pgp_parse_context *context,
enum pgp_packet_tag type, u8 headerlen,
const u8 *data, size_t datalen)
{
struct preload_pgp_keys_context *ctx =
container_of(context, struct preload_pgp_keys_context, pgp);
int ret;
if (ctx->found_key) {
ctx->key_end = data - headerlen;
ret = create_pgp_key(ctx);
if (ret < 0)
return ret;
}
ctx->key_start = data - headerlen;
ctx->found_key = true;
return 0;
}
/**
* preload_pgp_keys - Load keys from a PGP keyring blob
* @pgpdata: The PGP keyring blob containing the keys.
* @pgpdatalen: The size of the @pgpdata blob.
* @keyring: The keyring to add the new keys to.
*
* Preload a pack of keys from a PGP keyring blob.
*
* The keys have their descriptions generated from the user ID and fingerprint
* in the PGP stream. Since keys can be matched on their key IDs independently
* of the key description, the description is mostly irrelevant apart from the
* fact that keys of the same description displace one another from a keyring.
*
* The caller should override the current creds if they want the keys to be
* owned by someone other than the current process's owner. Keys will not be
* accounted towards the owner's quota.
*
* This function may only be called whilst the kernel is booting.
*/
int __init preload_pgp_keys(const u8 *pgpdata, size_t pgpdatalen,
struct key *keyring)
{
struct preload_pgp_keys_context ctx;
int ret;
ctx.pgp.types_of_interest =
(1 << PGP_PKT_PUBLIC_KEY) | (1 << PGP_PKT_PUBLIC_SUBKEY);
ctx.pgp.process_packet = found_pgp_key;
ctx.keyring = make_key_ref(keyring, 1);
ctx.found_key = false;
ret = pgp_parse_packets(pgpdata, pgpdatalen, &ctx.pgp);
if (ret < 0)
return ret;
if (ctx.found_key) {
ctx.key_end = pgpdata + pgpdatalen;
return create_pgp_key(&ctx);
}
return 0;
}