Skip to content

Commit

Permalink
X.509: Move the trust validation code out to its own file
Browse files Browse the repository at this point in the history
Move the X.509 trust validation code out to its own file so that it can be
generalised.

Signed-off-by: David Howells <[email protected]>
  • Loading branch information
dhowells committed Apr 11, 2016
1 parent 5f7f5c8 commit cfb664f
Show file tree
Hide file tree
Showing 4 changed files with 116 additions and 80 deletions.
5 changes: 4 additions & 1 deletion crypto/asymmetric_keys/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,10 @@

obj-$(CONFIG_ASYMMETRIC_KEY_TYPE) += asymmetric_keys.o

asymmetric_keys-y := asymmetric_type.o signature.o
asymmetric_keys-y := \
asymmetric_type.o \
restrict.o \
signature.o

obj-$(CONFIG_ASYMMETRIC_PUBLIC_KEY_SUBTYPE) += public_key.o

Expand Down
106 changes: 106 additions & 0 deletions crypto/asymmetric_keys/restrict.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
/* Instantiate a public key crypto key from an X.509 Certificate
*
* Copyright (C) 2012 Red Hat, Inc. All Rights Reserved.
* Written by David Howells ([email protected])
*
* 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.
*/

#define pr_fmt(fmt) "X.509: "fmt
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/err.h>
#include <linux/mpi.h>
#include <linux/asn1_decoder.h>
#include <keys/asymmetric-subtype.h>
#include <keys/asymmetric-parser.h>
#include <keys/system_keyring.h>
#include <crypto/hash.h>
#include <crypto/public_key.h>
#include "asymmetric_keys.h"
#include "x509_parser.h"

static bool use_builtin_keys;
static struct asymmetric_key_id *ca_keyid;

#ifndef MODULE
static struct {
struct asymmetric_key_id id;
unsigned char data[10];
} cakey;

static int __init ca_keys_setup(char *str)
{
if (!str) /* default system keyring */
return 1;

if (strncmp(str, "id:", 3) == 0) {
struct asymmetric_key_id *p = &cakey.id;
size_t hexlen = (strlen(str) - 3) / 2;
int ret;

if (hexlen == 0 || hexlen > sizeof(cakey.data)) {
pr_err("Missing or invalid ca_keys id\n");
return 1;
}

ret = __asymmetric_key_hex_to_key_id(str + 3, p, hexlen);
if (ret < 0)
pr_err("Unparsable ca_keys id hex string\n");
else
ca_keyid = p; /* owner key 'id:xxxxxx' */
} else if (strcmp(str, "builtin") == 0) {
use_builtin_keys = true;
}

return 1;
}
__setup("ca_keys=", ca_keys_setup);
#endif

/*
* 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.
*/
int x509_validate_trust(struct x509_certificate *cert,
struct key *trust_keyring)
{
struct public_key_signature *sig = cert->sig;
struct key *key;
int ret = 1;

if (!sig->auth_ids[0] && !sig->auth_ids[1])
return 1;

if (!trust_keyring)
return -EOPNOTSUPP;
if (ca_keyid && !asymmetric_key_id_partial(sig->auth_ids[1], ca_keyid))
return -EPERM;
if (cert->unsupported_sig)
return -ENOPKG;

key = find_asymmetric_key(trust_keyring,
sig->auth_ids[0], sig->auth_ids[1],
false);
if (IS_ERR(key))
return PTR_ERR(key);

if (!use_builtin_keys ||
test_bit(KEY_FLAG_BUILTIN, &key->flags)) {
ret = verify_signature(key, cert->sig);
if (ret == -ENOPKG)
cert->unsupported_sig = true;
}
key_put(key);
return ret;
}
EXPORT_SYMBOL_GPL(x509_validate_trust);
6 changes: 6 additions & 0 deletions crypto/asymmetric_keys/x509_parser.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,3 +58,9 @@ extern int x509_decode_time(time64_t *_t, size_t hdrlen,
*/
extern int x509_get_sig_params(struct x509_certificate *cert);
extern int x509_check_for_self_signed(struct x509_certificate *cert);

/*
* public_key_trust.c
*/
extern int x509_validate_trust(struct x509_certificate *cert,
struct key *trust_keyring);
79 changes: 0 additions & 79 deletions crypto/asymmetric_keys/x509_public_key.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,44 +20,6 @@
#include "asymmetric_keys.h"
#include "x509_parser.h"

static bool use_builtin_keys;
static struct asymmetric_key_id *ca_keyid;

#ifndef MODULE
static struct {
struct asymmetric_key_id id;
unsigned char data[10];
} cakey;

static int __init ca_keys_setup(char *str)
{
if (!str) /* default system keyring */
return 1;

if (strncmp(str, "id:", 3) == 0) {
struct asymmetric_key_id *p = &cakey.id;
size_t hexlen = (strlen(str) - 3) / 2;
int ret;

if (hexlen == 0 || hexlen > sizeof(cakey.data)) {
pr_err("Missing or invalid ca_keys id\n");
return 1;
}

ret = __asymmetric_key_hex_to_key_id(str + 3, p, hexlen);
if (ret < 0)
pr_err("Unparsable ca_keys id hex string\n");
else
ca_keyid = p; /* owner key 'id:xxxxxx' */
} else if (strcmp(str, "builtin") == 0) {
use_builtin_keys = true;
}

return 1;
}
__setup("ca_keys=", ca_keys_setup);
#endif

/*
* Set up the signature parameters in an X.509 certificate. This involves
* digesting the signed data and extracting the signature.
Expand Down Expand Up @@ -187,47 +149,6 @@ int x509_check_for_self_signed(struct x509_certificate *cert)
return 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 public_key_signature *sig = cert->sig;
struct key *key;
int ret = 1;

if (!sig->auth_ids[0] && !sig->auth_ids[1])
return 1;

if (!trust_keyring)
return -EOPNOTSUPP;
if (ca_keyid && !asymmetric_key_id_partial(sig->auth_ids[1], ca_keyid))
return -EPERM;
if (cert->unsupported_sig)
return -ENOPKG;

key = find_asymmetric_key(trust_keyring,
sig->auth_ids[0], sig->auth_ids[1], false);
if (IS_ERR(key))
return PTR_ERR(key);

if (!use_builtin_keys ||
test_bit(KEY_FLAG_BUILTIN, &key->flags)) {
ret = verify_signature(key, cert->sig);
if (ret == -ENOPKG)
cert->unsupported_sig = true;
}
key_put(key);
return ret;
}

/*
* Attempt to parse a data blob for a key as an X509 certificate.
*/
Expand Down

0 comments on commit cfb664f

Please sign in to comment.