linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [GIT PULL] Asymmetric keys and module signing
@ 2012-09-25  0:07 David Howells
  2012-09-25  0:11 ` David Howells
                   ` (5 more replies)
  0 siblings, 6 replies; 47+ messages in thread
From: David Howells @ 2012-09-25  0:07 UTC (permalink / raw)
  To: herbert, rusty
  Cc: dhowells, pjones, jwboyer, linux-crypto, linux-security-module,
	linux-kernel, keyrings


Hi Herbert, Rusty,

Here are my latest module signing patches on top of the asymmetric key crypto
patches, which I hope Herbert will consider taking, at least from the
crypto-keys-post-KS branch:

	http://git.kernel.org/?p=linux/kernel/git/dhowells/linux-modsign.git;a=shortlog;h=refs/heads/crypto-keys-post-KS

The module signing patches go on top of those, and the set can be found here:

	http://git.kernel.org/?p=linux/kernel/git/dhowells/linux-modsign.git;a=shortlog;h=refs/heads/modsign-post-KS

Do you want the patches posting to the lists?  I've tried posting the series
as one, but there seems to be a problem posting the merge commit in the middle
because it has two parents:-/

Anyway...


The module signing patches provide:

 - Some fixes to Rusty's patch.  Also an additional patch to extend the policy
   handling for modules signed with an unknown key and to handle FIPS mode.

 - Module signature generation and checking.  The signature format is:

	<signer-id-string>
	<binary-key-id>
	<binary-signature>
	<sig-information-block>

   The fixed-length sig-information-block indicates the crypto algorithm (RSA
   only for the moment), the hash type (SHA512 for example) and the identifier
   scope (X.509 in this case), plus the lengths of the other three parts.

   The binary-key-id could be rendered as hex and pasted onto the end of the
   signer-id-string so that the kernel doesn't have to do the conversion.

   A script is provided in one of the patches to generate the signer name and
   key ID parts from the X.509 cert for later inclusion in module signatures
   during the build.

 - A transient X.509 cert will be automatically generated if one is not given
   and will be used to automatically sign the modules after they've been
   thoroughly stripped.

   Note that this may prove not to be the best way for distributions to do
   things.  We're currently looking at the best way being to do the stripping
   and signing manually from the RPM spec file after the make modules_install
   step and after the debuginfo has been extracted, so automatic signing may
   need to go away, or at least become optional.

   To make this easier, a script is provided to sign a module and this can be
   called either from the Makefile or the spec file.

 - An 'extra_certificates' file can be placed in the root of the kernel build
   containing a number of supplementary X.509 certs just cat'd together.  These
   will get added to the internal keyring and can then be used to check module
   signatures also.


I have also fixed a number of things in the crypto patches:

 - GeneralizedTime and GeneralString were transposed in the ASN.1 compiler
   directive table and enum token_type ('S' comes before 'i' to strcmp()),
   resulting in it not being possible to use either.

 - I had made it a requirement that the X.509 certificate subjectKeyIdentifier
   and authorityKeyIdentifier extensions exist so that we can validate the
   X.509 signature if possible, but I hadn't put in any checks that they'd been
   found before using the values extracted, leading to a crash.

 - I fixed header length computation in ASN.1 decoder resulting making it
   possible to discard one of the x509.asn1 callback actions (we can locate the
   start of the TBS container directly now by subtraction).

 - I got rid of the fingerprint bit at the end of the public_key struct as it's
   superfluous (the asymmetric key type stores the fingerprint attached to
   key->type_data.p[1]).

 - I made the X.509 parser render the key description in a more compact manner:

   The description is split into two parts: "<signer>: <key-id>".

   The <key-id> is a hex rendering of the key identifier - in the case of X.509
   that would be the contents of the subjectKeyIdentifier extension field with
   the ASN.1 OctetString wrapper removed.

   The <signer> is (in order) one of:

	- The O and CN attributes as "<O-attr>: <CN-attr>" if the CN attribute
          isn't prefixed with the O attribute, and, if longer, doesn't share
          the same first seven chars (say a company name such as Red Hat Inc.).
          I admit this is entirely arbitrary and biased towards companies with
          7 chars or more in there name, but it does remove duplication of the
          organisation's name if it's in both the O and the CN.  Can anyone
          suggest a better heuristic?

        - The CN attribute.

	- The O attribute.

	- The email address.

	- Omitted (with ": " omitted too).

   As an example:

	Magrathea: Glacier signing key: 5dd0839552bd6af498253f8af1e65da3472941c6

   which is "<O-attr>: <CN-attr>: <key-id>" in form, or:

	Red Hat Test Certificate: 3580cf35d76b3b667a40df66691cbcf87353b23c

   which is just "<CN-attr>: <key-id>" in form.

 - I no longer extract the bits of the X.509 certificate I don't currently use
   (such as the version number).

Note, this implementation of the X.509 certificate parser uses a couple of
patterns to drive a reusable ASN.1 decoder.  I do, however, have a direct
in-line decoder implementation also that can only decode X.509 certs.  The
stack space usage is greater, but the code size is simpler and slightly smaller
and the code is less capable (it can't handle indefinite-length elements for
example), and it can't be reused for anything else (such as CIFS, netfilter,
PKCS#7, Kerberos tickets), whereas the pattern-based decoder can.  I'll post
this separately to see what people think.

As far as testing goes, I have posted a number of testing scripts that I have
used to punish the crypto keys side of things.  The "keyctl padd" command makes
this straightforward.

Hopefully, later this week the patches will appear in the Fedora 18 kernel.

David
---
The following changes since commit eeea3ac912207dcf759b95b2b4c36f96bce583bf:

  Merge tag 'fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc (2012-09-06 10:23:58 -0700)

are available in the git repository at:


  git://git.kernel.org/pub/scm/linux/kernel/git/dhowells/linux-modsign.git modsign-post-KS

for you to fetch changes up to 8d4f62638e9aae069d1145dfeb7300c58077be49:

  MODSIGN: Extend the policy on signature check failure (2012-09-24 20:51:59 +0100)

----------------------------------------------------------------
(from the branch description for modsign-post-KS local branch)

post Kernel-Summit module signing
----------------------------------------------------------------
David Howells (26):
      KEYS: Add payload preparsing opportunity prior to key instantiate or update
      MPILIB: Provide count_leading/trailing_zeros() based on arch functions
      KEYS: Document asymmetric key type
      KEYS: Implement asymmetric key type
      KEYS: Asymmetric key pluggable data parsers
      KEYS: Asymmetric public-key algorithm crypto key subtype
      KEYS: Provide signature verification with an asymmetric key
      MPILIB: Reinstate mpi_cmp[_ui]() and export for RSA signature verification
      RSA: Implement signature verification algorithm [PKCS#1 / RFC3447]
      RSA: Fix signature verification for shorter signatures
      X.509: Implement simple static OID registry
      X.509: Add utility functions to render OIDs as strings
      X.509: Add simple ASN.1 grammar compiler
      X.509: Add an ASN.1 decoder
      MPILIB: Provide a function to read raw data into an MPI
      X.509: Add a crypto key parser for binary (DER) X.509 certificates
      Merge Rusty's module signature checking hook into modsign-post-KS
      MOD: Fix Rusty's module_sig_check()
      MODSIGN: Provide gitignore and make clean rules for extra files
      MODSIGN: Provide Kconfig options
      MODSIGN: Automatically generate module signing keys if missing
      MODSIGN: Provide module signing public keys to the kernel
      MODSIGN: Implement module signature checking
      MODSIGN: Provide a script for generating a key ID from an X.509 cert
      MODSIGN: Sign modules during the build process
      MODSIGN: Extend the policy on signature check failure

Rusty Russell (1):
      module: signature checking hook

 .gitignore                                |   13 +
 Documentation/crypto/asymmetric-keys.txt  |  312 ++++++
 Documentation/kernel-parameters.txt       |    6 +
 Documentation/security/keys.txt           |   50 +-
 Makefile                                  |    1 +
 crypto/Kconfig                            |    1 +
 crypto/Makefile                           |    1 +
 crypto/asymmetric_keys/.gitignore         |    1 +
 crypto/asymmetric_keys/Kconfig            |   38 +
 crypto/asymmetric_keys/Makefile           |   27 +
 crypto/asymmetric_keys/asymmetric_keys.h  |   15 +
 crypto/asymmetric_keys/asymmetric_type.c  |  274 +++++
 crypto/asymmetric_keys/public_key.c       |  108 ++
 crypto/asymmetric_keys/public_key.h       |   30 +
 crypto/asymmetric_keys/rsa.c              |  277 ++++++
 crypto/asymmetric_keys/signature.c        |   49 +
 crypto/asymmetric_keys/x509.asn1          |   60 ++
 crypto/asymmetric_keys/x509_cert_parser.c |  497 ++++++++++
 crypto/asymmetric_keys/x509_parser.h      |   36 +
 crypto/asymmetric_keys/x509_public_key.c  |  207 ++++
 crypto/asymmetric_keys/x509_rsakey.asn1   |    4 +
 fs/cifs/cifs_spnego.c                     |    6 +-
 fs/cifs/cifsacl.c                         |    8 +-
 include/asm-generic/bitops/count_zeros.h  |   57 ++
 include/crypto/public_key.h               |  108 ++
 include/keys/asymmetric-parser.h          |   37 +
 include/keys/asymmetric-subtype.h         |   55 +
 include/keys/asymmetric-type.h            |   25 +
 include/keys/user-type.h                  |    6 +-
 include/linux/asn1.h                      |   67 ++
 include/linux/asn1_ber_bytecode.h         |   87 ++
 include/linux/asn1_decoder.h              |   24 +
 include/linux/key-type.h                  |   35 +-
 include/linux/module.h                    |    8 +
 include/linux/mpi.h                       |    1 +
 include/linux/oid_registry.h              |   92 ++
 init/Kconfig                              |   68 ++
 kernel/Makefile                           |   57 ++
 kernel/modsign_pubkey.c                   |  112 +++
 kernel/module-internal.h                  |   16 +
 kernel/module.c                           |  100 +-
 kernel/module_signing.c                   |  247 +++++
 lib/.gitignore                            |    2 +-
 lib/Kconfig                               |    5 +
 lib/Makefile                              |   18 +
 lib/asn1_decoder.c                        |  477 +++++++++
 lib/build_OID_registry                    |  209 ++++
 lib/mpi/Makefile                          |    1 +
 lib/mpi/longlong.h                        |  138 +--
 lib/mpi/mpi-bit.c                         |    2 +-
 lib/mpi/mpi-cmp.c                         |   70 ++
 lib/mpi/mpi-pow.c                         |    4 +-
 lib/mpi/mpicoder.c                        |   55 +
 lib/oid_registry.c                        |  170 ++++
 net/ceph/crypto.c                         |    9 +-
 net/dns_resolver/dns_key.c                |    6 +-
 net/rxrpc/ar-key.c                        |   40 +-
 scripts/.gitignore                        |    1 +
 scripts/Makefile                          |    2 +
 scripts/Makefile.build                    |   11 +
 scripts/Makefile.modpost                  |   75 +-
 scripts/asn1_compiler.c                   | 1545 +++++++++++++++++++++++++++++
 scripts/sign-file                         |  115 +++
 scripts/x509keyid                         |  268 +++++
 security/keys/encrypted-keys/encrypted.c  |   16 +-
 security/keys/key.c                       |  114 ++-
 security/keys/keyctl.c                    |   18 +-
 security/keys/keyring.c                   |    6 +-
 security/keys/request_key_auth.c          |    8 +-
 security/keys/trusted.c                   |   16 +-
 security/keys/user_defined.c              |   14 +-
 71 files changed, 6394 insertions(+), 244 deletions(-)
 create mode 100644 Documentation/crypto/asymmetric-keys.txt
 create mode 100644 crypto/asymmetric_keys/.gitignore
 create mode 100644 crypto/asymmetric_keys/Kconfig
 create mode 100644 crypto/asymmetric_keys/Makefile
 create mode 100644 crypto/asymmetric_keys/asymmetric_keys.h
 create mode 100644 crypto/asymmetric_keys/asymmetric_type.c
 create mode 100644 crypto/asymmetric_keys/public_key.c
 create mode 100644 crypto/asymmetric_keys/public_key.h
 create mode 100644 crypto/asymmetric_keys/rsa.c
 create mode 100644 crypto/asymmetric_keys/signature.c
 create mode 100644 crypto/asymmetric_keys/x509.asn1
 create mode 100644 crypto/asymmetric_keys/x509_cert_parser.c
 create mode 100644 crypto/asymmetric_keys/x509_parser.h
 create mode 100644 crypto/asymmetric_keys/x509_public_key.c
 create mode 100644 crypto/asymmetric_keys/x509_rsakey.asn1
 create mode 100644 include/asm-generic/bitops/count_zeros.h
 create mode 100644 include/crypto/public_key.h
 create mode 100644 include/keys/asymmetric-parser.h
 create mode 100644 include/keys/asymmetric-subtype.h
 create mode 100644 include/keys/asymmetric-type.h
 create mode 100644 include/linux/asn1.h
 create mode 100644 include/linux/asn1_ber_bytecode.h
 create mode 100644 include/linux/asn1_decoder.h
 create mode 100644 include/linux/oid_registry.h
 create mode 100644 kernel/modsign_pubkey.c
 create mode 100644 kernel/module-internal.h
 create mode 100644 kernel/module_signing.c
 create mode 100644 lib/asn1_decoder.c
 create mode 100755 lib/build_OID_registry
 create mode 100644 lib/mpi/mpi-cmp.c
 create mode 100644 lib/oid_registry.c
 create mode 100644 scripts/asn1_compiler.c
 create mode 100644 scripts/sign-file
 create mode 100755 scripts/x509keyid

^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: [GIT PULL] Asymmetric keys and module signing
  2012-09-25  0:07 [GIT PULL] Asymmetric keys and module signing David Howells
@ 2012-09-25  0:11 ` David Howells
  2012-09-25 15:09 ` Wrong system clock vs X.509 date specifiers David Howells
                   ` (4 subsequent siblings)
  5 siblings, 0 replies; 47+ messages in thread
From: David Howells @ 2012-09-25  0:11 UTC (permalink / raw)
  To: herbert, rusty
  Cc: dhowells, pjones, jwboyer, linux-crypto, linux-security-module,
	linux-kernel, keyrings

David Howells <dhowells@redhat.com> wrote:

> Note, this implementation of the X.509 certificate parser uses a couple of
> patterns to drive a reusable ASN.1 decoder.  I do, however, have a direct
> in-line decoder implementation also that can only decode X.509 certs.  The
> stack space usage is greater, but the code size is simpler and slightly
> smaller and the code is less capable (it can't handle indefinite-length
> elements for example), and it can't be reused for anything else (such as
> CIFS, netfilter, PKCS#7, Kerberos tickets), whereas the pattern-based
> decoder can.  I'll post this separately to see what people think.

Here's the direct inline X.509 ASN.1 decoder I mentioned.

David
---
/* X.509 certificate parser
 *
 * Copyright (C) 2012 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.
 */

#define pr_fmt(fmt) "X.509: "fmt
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/err.h>
#include <linux/oid_registry.h>
#include "linux/asn1.h"
#include "public_key.h"
#include "x509_parser.h"

struct x509_cursor {
	unsigned	start;			/* Start of this element's content */
	unsigned	len;			/* Remaining length of element's content */
	u8		hdrlen;			/* Length of header */
	u8		tag;			/* Tag found */
	bool		present;		/* Element present */
};

struct x509_parse_context {
	struct x509_certificate	*cert;		/* Certificate being constructed */
	const u8	*data;			/* Start of data */
	const void	*cert_start;		/* Start of cert content */
	const void	*key;			/* Key data */
	size_t		key_size;		/* Size of key data */
	enum OID	algo_oid;		/* Algorithm OID */
	unsigned char	nr_mpi;			/* Number of MPIs stored */
	int		error;
};

/*
 * Free an X.509 certificate
 */
void x509_free_certificate(struct x509_certificate *cert)
{
	if (cert) {
		public_key_destroy(cert->pub);
		kfree(cert->issuer);
		kfree(cert->subject);
		kfree(cert->fingerprint);
		kfree(cert->authority);
		kfree(cert);
	}
}

/*
 * Extract an ASN.1 element.
 */
static bool asn1_extract(struct x509_parse_context *ctx,
			 struct x509_cursor *cursor,
			 int expected_tag, bool optional,
			 struct x509_cursor *_extracted_cursor)
{
	unsigned start, len;
	u8 tag, l;

	pr_devel("==>%s(,{%u,%u},%02x,%u) [%02x%02x]\n",
		 __func__, cursor->start, cursor->len, expected_tag, optional,
		 ctx->data[cursor->start], ctx->data[cursor->start + 1]);

	if (ctx->error)
		return false;

	if (_extracted_cursor)
		_extracted_cursor->present = false;
	if (cursor->len == 0 && optional)
		return false;

	if (cursor->len < 2) {
		pr_debug("ASN.1 elem header underrun @%u+%u\n",
			 cursor->start, cursor->len);
		ctx->error = -EBADMSG;
		return false;
	}

	tag = ctx->data[cursor->start];
	len = ctx->data[cursor->start + 1];

	if (expected_tag != -1 && tag != expected_tag) {
		if (!optional) {
			pr_debug("ASN.1 unexpected tag %02x%02x not %02x @%u+%u\n",
				 tag, len, expected_tag,
				 cursor->start, cursor->len);
			ctx->error = -EBADMSG;
		}
		return false;
	}

	cursor->start += 2;
	cursor->len -= 2;

	if ((tag & 0x1f) == 0x1f) {
		pr_debug("ASN.1 long tag @%u\n", cursor->start);
		ctx->error = -EBADMSG;
		return false;
	}

	if (len == 0x80) {
		pr_debug("ASN.1 indefinite length @%u\n", cursor->start);
		ctx->error = -EBADMSG;
		return false;
	}

	l = 0;
	if (len > 0x80) {
		l = len - 0x80;
		if (cursor->len < l) {
			pr_debug("ASN.1 elem len underrun (%u) @%u+%u\n",
				 l, cursor->start, cursor->len);
			ctx->error = -EBADMSG;
			return false;
		}

		switch (l) {
		case 0x01:
			len = ctx->data[cursor->start];
			break;
		case 0x02:
			len  = ctx->data[cursor->start + 0] << 8;
			len += ctx->data[cursor->start + 1];
			break;
		case 0x03:
			len  = ctx->data[cursor->start + 0] << 16;
			len += ctx->data[cursor->start + 1] << 8;
			len += ctx->data[cursor->start + 2];
			break;
		case 0x04:
			len  = ctx->data[cursor->start + 0] << 24;
			len += ctx->data[cursor->start + 1] << 16;
			len += ctx->data[cursor->start + 2] << 8;
			len += ctx->data[cursor->start + 3];
			break;
		default:
			pr_debug("ASN.1 elem excessive len (%u) @%u\n",
				 l, cursor->start);
			ctx->error = -EBADMSG;
			return false;
		}

		cursor->start += l;
		cursor->len -= l;
	}

	pr_debug("TAG %02x len: %u+%u\n", tag, l + 2, len);

	if (cursor->len < len) {
		pr_debug("ASN.1 data underrun (%u) @%u+%u\n",
			 len, cursor->start, cursor->len);
		ctx->error = -EBADMSG;
		return false;
	}

	start = cursor->start;
	cursor->start += len;
	cursor->len -= len;
	if (_extracted_cursor) {
		_extracted_cursor->start = start;
		_extracted_cursor->len = len;
		_extracted_cursor->hdrlen = 2 + l;
		_extracted_cursor->tag = tag;
		_extracted_cursor->present = true;
	}
	return true;
}

static bool asn1_check_end(struct x509_parse_context *ctx,
			   struct x509_cursor *cursor)
{
	if (ctx->error)
		return false;
	if (cursor->len != 0) {
		pr_debug("ASN.1 excess data @%u+%u\n",
			 cursor->start, cursor->len);
		ctx->error = -EBADMSG;
		return false;
	}
	return true;
}

/*
 * Parse the signature type.
 */
static void x509_parse_signature_type(struct x509_parse_context *ctx,
				      struct x509_cursor *data)
{
	struct x509_cursor type;
	enum OID oid;

	asn1_extract(ctx, data, ASN1_UNIV | ASN1_OID, false, &type);
	asn1_extract(ctx, data, -1, true, NULL);
	if (!asn1_check_end(ctx, data))
		return;

	oid = look_up_OID(ctx->data + type.start, type.len);

	switch (oid) {
	case OID_md2WithRSAEncryption:
	case OID_md3WithRSAEncryption:
	default:
		/* Unsupported combination */
		ctx->error = -ENOPKG;
		return;

	case OID_md4WithRSAEncryption:
		ctx->cert->sig_hash_algo = PKEY_HASH_MD5;
		ctx->cert->sig_pkey_algo = PKEY_ALGO_RSA;
		break;

	case OID_sha1WithRSAEncryption:
		ctx->cert->sig_hash_algo = PKEY_HASH_SHA1;
		ctx->cert->sig_pkey_algo = PKEY_ALGO_RSA;
		break;

	case OID_sha256WithRSAEncryption:
		ctx->cert->sig_hash_algo = PKEY_HASH_SHA256;
		ctx->cert->sig_pkey_algo = PKEY_ALGO_RSA;
		break;

	case OID_sha384WithRSAEncryption:
		ctx->cert->sig_hash_algo = PKEY_HASH_SHA384;
		ctx->cert->sig_pkey_algo = PKEY_ALGO_RSA;
		break;

	case OID_sha512WithRSAEncryption:
		ctx->cert->sig_hash_algo = PKEY_HASH_SHA512;
		ctx->cert->sig_pkey_algo = PKEY_ALGO_RSA;
		break;

	case OID_sha224WithRSAEncryption:
		ctx->cert->sig_hash_algo = PKEY_HASH_SHA224;
		ctx->cert->sig_pkey_algo = PKEY_ALGO_RSA;
		break;
	}

	ctx->algo_oid = oid;
}

/*
 * Parse a name
 */
static void x509_parse_name(struct x509_parse_context *ctx,
			    struct x509_cursor *name, char **_name)
{
	const u8 *data = ctx->data;
	unsigned o_offset = 0, cn_offset = 0, email_offset = 0, offset;
	unsigned namesize;
	u8 o_size = 0, cn_size = 0, email_size = 0;
	char *buffer;

	BUG_ON(*_name);

	while (!ctx->error && name->len > 0) {
		struct x509_cursor rdn, attr, n_oid, n_val;
		enum OID oid;

		asn1_extract(ctx, name, ASN1_UNIV | ASN1_CONS | ASN1_SET,
			     false, &rdn);
		while (!ctx->error && rdn.len > 0) {
			asn1_extract(ctx, &rdn, ASN1_UNIV | ASN1_CONS | ASN1_SEQ,
				     false, &attr);
			asn1_extract(ctx, &attr, ASN1_UNIV | ASN1_OID, false, &n_oid);
			asn1_extract(ctx, &attr, -1, false, &n_val);
			if (!asn1_check_end(ctx, &attr))
				return;

			oid = look_up_OID(data + n_oid.start, n_oid.len);
			switch (oid) {
			case OID_organizationName:
				o_size = n_val.len;
				o_offset = n_val.start;
				break;
			case OID_commonName:
				cn_size = n_val.len;
				cn_offset = n_val.start;
				break;
			case OID_email_address:
				email_size = n_val.len;
				email_offset = n_val.start;
				break;
			default:
				continue;
			}
		}

		if (!asn1_check_end(ctx, &rdn))
			return;
	}

	if (!asn1_check_end(ctx, name))
		return;

	/* Empty name string if no material */
	if (!cn_size && !o_size && !email_size) {
		buffer = kmalloc(1, GFP_KERNEL);
		if (!buffer) {
			ctx->error = -ENOMEM;
			return;
		}
		buffer[0] = 0;
		goto done;
	}

	if (cn_size && o_size) {
		/* Consider combining O and CN, but use only the CN if it is
		 * prefixed by the O, or a significant portion thereof.
		 */
		namesize = cn_size;
		offset = cn_offset;
		if (cn_size >= o_size &&
		    memcmp(data + cn_offset, data + o_offset, o_size) == 0)
			goto single_component;
		if (cn_size >= 7 &&
		    o_size >= 7 &&
		    memcmp(data + cn_offset, data + o_offset, 7) == 0)
			goto single_component;

		buffer = kmalloc(o_size + 2 + cn_size + 1, GFP_KERNEL);
		if (!buffer) {
			ctx->error = -ENOMEM;
			return;
		}

		memcpy(buffer, data + o_offset, o_size);
		buffer[o_size + 0] = ':';
		buffer[o_size + 1] = ' ';
		memcpy(buffer + o_size + 2, data + cn_offset, cn_size);
		buffer[o_size + 2 + cn_size] = 0;
		goto done;

	} else if (cn_size) {
		namesize = cn_size;
		offset = cn_offset;
	} else if (o_size) {
		namesize = o_size;
		offset = o_offset;
	} else {
		namesize = email_size;
		offset = email_offset;
	}

single_component:
	buffer = kmalloc(namesize + 1, GFP_KERNEL);
	if (!buffer) {
		ctx->error = -ENOMEM;
		return;
	}
	memcpy(buffer, data + offset, namesize);
	buffer[namesize] = 0;

done:
	*_name = buffer;
}

/*
 * Record a certificate time.
 */
static bool x509_note_time(struct x509_parse_context *ctx,
			   time_t *_time, u8 tag, const u8 *value, size_t vlen)
{
	unsigned YY, MM, DD, hh, mm, ss;
	const u8 *p = value;

#define dec2bin(X) ((X) - '0')
#define DD2bin(P) ({ unsigned x = dec2bin(P[0]) * 10 + dec2bin(P[1]); P += 2; x; })

	if (tag == ASN1_UNITIM) {
		/* UTCTime: YYMMDDHHMMSSZ */
		if (vlen != 13)
			goto unsupported_time;
		YY = DD2bin(p);
		if (YY > 50)
			YY += 1900;
		else
			YY += 2000;
	} else if (tag == ASN1_GENTIM) {
		/* GenTime: YYYYMMDDHHMMSSZ */
		if (vlen != 15)
			goto unsupported_time;
		YY = DD2bin(p) * 100 + DD2bin(p);
	} else {
		goto unsupported_time;
	}

	MM = DD2bin(p);
	DD = DD2bin(p);
	hh = DD2bin(p);
	mm = DD2bin(p);
	ss = DD2bin(p);

	if (*p != 'Z')
		goto unsupported_time;

	*_time = mktime(YY, MM, DD, hh, mm, ss);
	return true;

unsupported_time:
	pr_debug("Got unsupported time [tag %02x]: '%*.*s'\n",
		 tag, (int)vlen, (int)vlen, value);
	ctx->error = -EBADMSG;
	return false;
}

/*
 * Parse the validity data.
 */
static void x509_parse_validity(struct x509_parse_context *ctx,
				struct x509_cursor *data)
{
	struct x509_cursor not_before, not_after;

	asn1_extract(ctx, data, -1, false, &not_before);
	asn1_extract(ctx, data, -1, false, &not_after);
	if (!asn1_check_end(ctx, data))
		return;

	if (x509_note_time(ctx, &ctx->cert->valid_from, not_before.tag,
			   ctx->data + not_before.start, not_before.len) < 0) {
		ctx->error = -EBADMSG;
		return;
	}
	if (x509_note_time(ctx, &ctx->cert->valid_to, not_after.tag,
			   ctx->data + not_after.start, not_after.len) < 0) {
		ctx->error = -EBADMSG;
		return;
	}
}

/*
 * Extract a RSA public key value
 */
static void x509_parse_rsa_key(struct x509_parse_context *ctx,
			       struct x509_cursor *data)
{
	struct x509_cursor list, integer;
	MPI mpi;

	asn1_extract(ctx, data, ASN1_UNIV | ASN1_CONS | ASN1_SEQ, false, &list);
	if (!asn1_check_end(ctx, data))
		return;

	while (list.len > 0) {
		if (ctx->nr_mpi >= ARRAY_SIZE(ctx->cert->pub->mpi)) {
			pr_debug("Too many public key MPIs in certificate\n");
			ctx->error = -EBADMSG;
			return;
		}

		if (!asn1_extract(ctx, &list, ASN1_UNIV | ASN1_INT,
				  false, &integer))
			return;

		mpi = mpi_read_raw_data(ctx->data + integer.start, integer.len);
		if (!mpi) {
			ctx->error = -ENOMEM;
			return;
		}

		ctx->cert->pub->mpi[ctx->nr_mpi++] = mpi;
	}

	asn1_check_end(ctx, &list);
}

/*
 * Parse the key.
 */
static void x509_parse_key(struct x509_parse_context *ctx,
			   struct x509_cursor *data)
{
	struct x509_cursor algo, type, str;
	enum OID oid;

	asn1_extract(ctx, data, ASN1_UNIV | ASN1_CONS | ASN1_SEQ, false, &algo);
	asn1_extract(ctx, data, ASN1_UNIV | ASN1_BTS, false, &str);
	if (!asn1_check_end(ctx, data))
		return;

	asn1_extract(ctx, &algo, ASN1_UNIV | ASN1_OID, false, &type);
	asn1_extract(ctx, &algo, -1, true, NULL);
	if (!asn1_check_end(ctx, &algo))
		return;

	oid = look_up_OID(ctx->data + type.start, type.len);

	if (oid != OID_rsaEncryption) {
		ctx->error = -ENOPKG;
		return;
	}
	ctx->cert->pkey_algo = PKEY_ALGO_RSA;

	/* Remove the bit string's initial unused bit count */
	if (str.len < 1) {
		pr_debug("ASN.1 short BIT STRING @%u+%u\n", str.start, str.len);
		ctx->error = -EBADMSG;
		return;
	}
	str.start++;
	str.len--;
	x509_parse_rsa_key(ctx, &str);
}

/*
 * Parse the extension list.
 */
static void x509_parse_extensions(struct x509_parse_context *ctx,
				  struct x509_cursor *data)
{
	struct x509_cursor extensions, ext;
	char *f;

	if (!data->present)
		return;

	asn1_extract(ctx, data, ASN1_UNIV | ASN1_CONS | ASN1_SEQ, false, &extensions);
	if (!asn1_check_end(ctx, data))
		return;

	while (extensions.len > 0 &&
	       asn1_extract(ctx, &extensions, ASN1_UNIV | ASN1_CONS | ASN1_SEQ,
			    false, &ext)
	       ) {
		struct x509_cursor type, val, wrapper, part;
		const u8 *v;
		enum OID oid;
		int i;

		asn1_extract(ctx, &ext, ASN1_UNIV | ASN1_OID, false, &type);
		asn1_extract(ctx, &ext, ASN1_UNIV | ASN1_BOOL, true, NULL);
		asn1_extract(ctx, &ext, ASN1_UNIV | ASN1_OTS, false, &val);
		if (!asn1_check_end(ctx, &ext))
			return;

		oid = look_up_OID(ctx->data + type.start, type.len);
		switch (oid) {
		case OID_subjectKeyIdentifier:
			/* Get hold of the key fingerprint */
			asn1_extract(ctx, &val, ASN1_UNIV | ASN1_OTS, false,
				     &part);
			if (!asn1_check_end(ctx, &val))
				return;
			if (part.len == 0) {
				pr_debug("Empty subjectKeyIdentifier\n");
				ctx->error = -EBADMSG;
				return;
			}

			f = kmalloc(part.len * 2 + 1, GFP_KERNEL);
			if (!f) {
				ctx->error = -ENOMEM;
				return;
			}
			v = ctx->data + part.start;
			for (i = 0; i < part.len; i++)
				sprintf(f + i * 2, "%02x", v[i]);
			pr_debug("fingerprint %s\n", f);
			ctx->cert->fingerprint = f;
			break;

		case OID_authorityKeyIdentifier:
			/* Get hold of the CA key fingerprint */
			asn1_extract(ctx, &val, ASN1_UNIV | ASN1_CONS | ASN1_SEQ,
				     false, &wrapper);
			if (!asn1_check_end(ctx, &val))
				return;
			asn1_extract(ctx, &wrapper, ASN1_CONT | 0, false, &part);
			if (!asn1_check_end(ctx, &wrapper))
				return;
			if (part.len == 0) {
				pr_debug("Empty authorityKeyIdentifier\n");
				ctx->error = -EBADMSG;
				return;
			}

			f = kmalloc(part.len * 2 + 1, GFP_KERNEL);
			if (!f) {
				ctx->error = -ENOMEM;
				return;
			}
			v = ctx->data + part.start;
			for (i = 0; i < part.len; i++)
				sprintf(f + i * 2, "%02x", v[i]);
			pr_debug("authority   %s\n", f);
			ctx->cert->authority = f;
			break;

		default:
			continue;
		}
	}

	asn1_check_end(ctx, &extensions);
}

/*
 * Parse the signature algorithm.
 */
static void x509_parse_signature_algo(struct x509_parse_context *ctx,
				      struct x509_cursor *data)
{
	struct x509_cursor type;
	enum OID oid;

	asn1_extract(ctx, data, ASN1_UNIV | ASN1_OID, false, &type);
	asn1_extract(ctx, data, -1, true, NULL);
	if (!asn1_check_end(ctx, data))
		return;

	oid = look_up_OID(ctx->data + type.start, type.len);

	pr_debug("Signature type: %u\n", oid);

	if (oid != ctx->algo_oid) {
		pr_debug("Got cert with pkey (%u) and sig (%u) algorithm OIDs\n",
			 ctx->algo_oid, oid);
		ctx->error = -EINVAL;
	}
}

/*
 * Parse the basic structure of the certificate.
 */
static void x509_parse_basic(struct x509_parse_context *ctx,
			     size_t datalen)
{
	struct x509_cursor cert, tbs;
	struct x509_cursor tmp = {
		.start = 0,
		.len = datalen
	};

	if (!asn1_extract(ctx, &tmp, ASN1_UNIV | ASN1_CONS | ASN1_SEQ,
			  false, &cert) ||
	    !asn1_check_end(ctx, &tmp))
		return;

	if (!asn1_extract(ctx, &cert, ASN1_UNIV | ASN1_CONS | ASN1_SEQ,
			  false, &tbs))
		return;
	pr_debug("x509_note_tbs_certificate(,%02x,%u,%u)!\n",
		 tbs.tag, tbs.start, tbs.len);
	ctx->cert->tbs = ctx->data + (tbs.start - tbs.hdrlen);
	ctx->cert->tbs_size = tbs.hdrlen + tbs.len;

	{
		asn1_extract(ctx, &tbs, ASN1_CONT | ASN1_CONS | 0,
			     true, NULL); /* Version */
		asn1_extract(ctx, &tbs, ASN1_UNIV | ASN1_INT,
			     false, NULL); /* Serial */
		asn1_extract(ctx, &tbs, ASN1_UNIV | ASN1_CONS | ASN1_SEQ,
			     false, &tmp);
		x509_parse_signature_type(ctx, &tmp);
		asn1_extract(ctx, &tbs, ASN1_UNIV | ASN1_CONS | ASN1_SEQ,
			     false, &tmp);
		x509_parse_name(ctx, &tmp, &ctx->cert->issuer);
		asn1_extract(ctx, &tbs, ASN1_UNIV | ASN1_CONS | ASN1_SEQ,
			     false, &tmp);
		x509_parse_validity(ctx, &tmp);
		asn1_extract(ctx, &tbs, ASN1_UNIV | ASN1_CONS | ASN1_SEQ,
			     false, &tmp);
		x509_parse_name(ctx, &tmp, &ctx->cert->subject);
		asn1_extract(ctx, &tbs, ASN1_UNIV | ASN1_CONS | ASN1_SEQ,
			     false, &tmp);
		x509_parse_key(ctx, &tmp);
		asn1_extract(ctx, &tbs, ASN1_CONT | ASN1_CONS | 1,
			     true, NULL); /* Issuer uid */
		asn1_extract(ctx, &tbs, ASN1_CONT | ASN1_CONS | 2,
			     true, NULL); /* Subject uid */
		asn1_extract(ctx, &tbs, ASN1_CONT | ASN1_CONS | 3,
			     true, &tmp);
		x509_parse_extensions(ctx, &tmp);
	}
	if (!asn1_check_end(ctx, &tbs))
		return;

	asn1_extract(ctx, &cert, ASN1_UNIV | ASN1_CONS | ASN1_SEQ,
		     false, &tmp);
	x509_parse_signature_algo(ctx, &tmp);
	asn1_extract(ctx, &cert, ASN1_UNIV | ASN1_BTS, false, &tmp);
	if (!asn1_check_end(ctx, &cert))
		return;

	/* Remove the bit string's initial unused bit count */
	if (tmp.len < 1) {
		pr_debug("ASN.1 short BIT STRING @%u+%u\n", tmp.start, tmp.len);
		ctx->error = -EBADMSG;
		return;
	}
	tmp.start++;
	tmp.len--;

	pr_debug("Signature size %u\n", tmp.len);
	ctx->cert->sig = ctx->data + tmp.start;
	ctx->cert->sig_size = tmp.len;
}

/*
 * Parse an X.509 certificate
 */
struct x509_certificate *x509_cert_parse(const void *data, size_t datalen)
{
	struct x509_certificate *cert;
	struct x509_parse_context *ctx;
	long ret;

	ret = -ENOMEM;
	cert = kzalloc(sizeof(struct x509_certificate), GFP_KERNEL);
	if (!cert)
		goto error_no_cert;
	cert->pub = kzalloc(sizeof(struct public_key), GFP_KERNEL);
	if (!cert->pub)
		goto error_no_ctx;
	ctx = kzalloc(sizeof(struct x509_parse_context), GFP_KERNEL);
	if (!ctx)
		goto error_no_ctx;

	ctx->cert = cert;
	ctx->data = data;

	/* Attempt to decode the certificate */
	x509_parse_basic(ctx, datalen);
	ret = ctx->error;
	if (ret < 0)
		goto error_decode;

	kfree(ctx);
	return cert;

error_decode:
	kfree(ctx);
error_no_ctx:
	x509_free_certificate(cert);
error_no_cert:
	return ERR_PTR(ret);
}

^ permalink raw reply	[flat|nested] 47+ messages in thread

* Wrong system clock vs X.509 date specifiers
  2012-09-25  0:07 [GIT PULL] Asymmetric keys and module signing David Howells
  2012-09-25  0:11 ` David Howells
@ 2012-09-25 15:09 ` David Howells
  2012-09-25 15:30   ` Alan Cox
  2012-09-25 15:35   ` Wrong system clock vs X.509 date specifiers David Howells
  2012-09-25 15:44 ` [GIT PULL] Asymmetric keys and module signing Kasatkin, Dmitry
                   ` (3 subsequent siblings)
  5 siblings, 2 replies; 47+ messages in thread
From: David Howells @ 2012-09-25 15:09 UTC (permalink / raw)
  To: rusty
  Cc: dhowells, herbert, pjones, jwboyer, linux-crypto,
	linux-security-module, linux-kernel, keyrings


The X.509 certificate has a pair of times in it that delineate the valid
period of the cert, and I'm checking that the system clock is within the
bounds they define before permitting you to use the cert.  I've been setting
the expiry date to be 100 years in the future - by which time hopefully I
won't have to worry about it - but occasionally clock skew means a freshly
built kernel won't boot because the machine trying to boot doesn't think that
the start time has been reached yet.

Do we actually want to do this, however?  Or should we just ignore the times?
Or just the start time?

Unfortunately, the ASN.1 says the field are mandatory, and openssl doesn't
seem to give you a way to backdate the start time.

David

^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: Wrong system clock vs X.509 date specifiers
  2012-09-25 15:09 ` Wrong system clock vs X.509 date specifiers David Howells
@ 2012-09-25 15:30   ` Alan Cox
  2013-03-14 10:48     ` David Woodhouse
  2012-09-25 15:35   ` Wrong system clock vs X.509 date specifiers David Howells
  1 sibling, 1 reply; 47+ messages in thread
From: Alan Cox @ 2012-09-25 15:30 UTC (permalink / raw)
  To: David Howells
  Cc: rusty, herbert, pjones, jwboyer, linux-crypto,
	linux-security-module, linux-kernel, keyrings

On Tue, 25 Sep 2012 16:09:54 +0100
David Howells <dhowells@redhat.com> wrote:

> 
> The X.509 certificate has a pair of times in it that delineate the valid
> period of the cert, and I'm checking that the system clock is within the
> bounds they define before permitting you to use the cert.  I've been setting
> the expiry date to be 100 years in the future - by which time hopefully I
> won't have to worry about it - but occasionally clock skew means a freshly
> built kernel won't boot because the machine trying to boot doesn't think that
> the start time has been reached yet.
> 
> Do we actually want to do this, however?  Or should we just ignore the times?
> Or just the start time?

Generate a certificate that is valid from a few minutes before the
wallclock time. It's a certificate policy question not a kernel hackery
one.

Be careful moving your system clock on 100 years and testing - ext4 gets
some timestamps wrong after 2038.

Alan



^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: Wrong system clock vs X.509 date specifiers
  2012-09-25 15:09 ` Wrong system clock vs X.509 date specifiers David Howells
  2012-09-25 15:30   ` Alan Cox
@ 2012-09-25 15:35   ` David Howells
  2012-09-25 15:43     ` Paolo Bonzini
                       ` (4 more replies)
  1 sibling, 5 replies; 47+ messages in thread
From: David Howells @ 2012-09-25 15:35 UTC (permalink / raw)
  To: Alan Cox
  Cc: dhowells, rusty, herbert, pjones, jwboyer, linux-crypto,
	linux-security-module, linux-kernel, keyrings

Alan Cox <alan@lxorguk.ukuu.org.uk> wrote:

> Generate a certificate that is valid from a few minutes before the
> wallclock time. It's a certificate policy question not a kernel hackery
> one.

That doesn't seem to be possible with openssl req.  What would you recommend?

David

^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: Wrong system clock vs X.509 date specifiers
  2012-09-25 15:35   ` Wrong system clock vs X.509 date specifiers David Howells
@ 2012-09-25 15:43     ` Paolo Bonzini
  2012-09-25 16:00     ` Alan Cox
                       ` (3 subsequent siblings)
  4 siblings, 0 replies; 47+ messages in thread
From: Paolo Bonzini @ 2012-09-25 15:43 UTC (permalink / raw)
  To: David Howells
  Cc: Alan Cox, rusty, herbert, pjones, jwboyer, linux-crypto,
	linux-security-module, linux-kernel, keyrings

Il 25/09/2012 17:35, David Howells ha scritto:
> Alan Cox <alan@lxorguk.ukuu.org.uk> wrote:
> 
>> > Generate a certificate that is valid from a few minutes before the
>> > wallclock time. It's a certificate policy question not a kernel hackery
>> > one.
> That doesn't seem to be possible with openssl req.  What would you recommend?

Disgusting, but: add an LD_PRELOAD library that returns a time well in
the past.

Paolo

^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: [GIT PULL] Asymmetric keys and module signing
  2012-09-25  0:07 [GIT PULL] Asymmetric keys and module signing David Howells
  2012-09-25  0:11 ` David Howells
  2012-09-25 15:09 ` Wrong system clock vs X.509 date specifiers David Howells
@ 2012-09-25 15:44 ` Kasatkin, Dmitry
  2012-09-25 16:15 ` David Howells
                   ` (2 subsequent siblings)
  5 siblings, 0 replies; 47+ messages in thread
From: Kasatkin, Dmitry @ 2012-09-25 15:44 UTC (permalink / raw)
  To: David Howells
  Cc: herbert, rusty, pjones, jwboyer, linux-crypto,
	linux-security-module, linux-kernel, keyrings

Hello David,

As I can see API has changed towards our discussion on KS.
Now digest can be supplied to the verify_signature in a
public_key_signature argument.
It looks that in such away we can use this API for IMA/EVM as well.

Just one question about key description...
request_asymmetric_key uses format for key  description: "<signer>: <key-id>".
Preparsing code creates description from those values.
I see that key id is not 8 bytes anymore but full hash size of 20 bytes.

For practical reasons for IMA it might be nice to save some space in
xattrs and use shorter key id/description.
As I understand from implementation, if key name is provided with
"keyctl add", it will not be replaced with
preparsed value.

Right?
And we can actually use any keyid we want?

- Dmitry


On Tue, Sep 25, 2012 at 3:07 AM, David Howells <dhowells@redhat.com> wrote:
>
> Hi Herbert, Rusty,
>
> Here are my latest module signing patches on top of the asymmetric key crypto
> patches, which I hope Herbert will consider taking, at least from the
> crypto-keys-post-KS branch:
>
>         http://git.kernel.org/?p=linux/kernel/git/dhowells/linux-modsign.git;a=shortlog;h=refs/heads/crypto-keys-post-KS
>
> The module signing patches go on top of those, and the set can be found here:
>
>         http://git.kernel.org/?p=linux/kernel/git/dhowells/linux-modsign.git;a=shortlog;h=refs/heads/modsign-post-KS
>
> Do you want the patches posting to the lists?  I've tried posting the series
> as one, but there seems to be a problem posting the merge commit in the middle
> because it has two parents:-/
>
> Anyway...
>
>
> The module signing patches provide:
>
>  - Some fixes to Rusty's patch.  Also an additional patch to extend the policy
>    handling for modules signed with an unknown key and to handle FIPS mode.
>
>  - Module signature generation and checking.  The signature format is:
>
>         <signer-id-string>
>         <binary-key-id>
>         <binary-signature>
>         <sig-information-block>
>
>    The fixed-length sig-information-block indicates the crypto algorithm (RSA
>    only for the moment), the hash type (SHA512 for example) and the identifier
>    scope (X.509 in this case), plus the lengths of the other three parts.
>
>    The binary-key-id could be rendered as hex and pasted onto the end of the
>    signer-id-string so that the kernel doesn't have to do the conversion.
>
>    A script is provided in one of the patches to generate the signer name and
>    key ID parts from the X.509 cert for later inclusion in module signatures
>    during the build.
>
>  - A transient X.509 cert will be automatically generated if one is not given
>    and will be used to automatically sign the modules after they've been
>    thoroughly stripped.
>
>    Note that this may prove not to be the best way for distributions to do
>    things.  We're currently looking at the best way being to do the stripping
>    and signing manually from the RPM spec file after the make modules_install
>    step and after the debuginfo has been extracted, so automatic signing may
>    need to go away, or at least become optional.
>
>    To make this easier, a script is provided to sign a module and this can be
>    called either from the Makefile or the spec file.
>
>  - An 'extra_certificates' file can be placed in the root of the kernel build
>    containing a number of supplementary X.509 certs just cat'd together.  These
>    will get added to the internal keyring and can then be used to check module
>    signatures also.
>
>
> I have also fixed a number of things in the crypto patches:
>
>  - GeneralizedTime and GeneralString were transposed in the ASN.1 compiler
>    directive table and enum token_type ('S' comes before 'i' to strcmp()),
>    resulting in it not being possible to use either.
>
>  - I had made it a requirement that the X.509 certificate subjectKeyIdentifier
>    and authorityKeyIdentifier extensions exist so that we can validate the
>    X.509 signature if possible, but I hadn't put in any checks that they'd been
>    found before using the values extracted, leading to a crash.
>
>  - I fixed header length computation in ASN.1 decoder resulting making it
>    possible to discard one of the x509.asn1 callback actions (we can locate the
>    start of the TBS container directly now by subtraction).
>
>  - I got rid of the fingerprint bit at the end of the public_key struct as it's
>    superfluous (the asymmetric key type stores the fingerprint attached to
>    key->type_data.p[1]).
>
>  - I made the X.509 parser render the key description in a more compact manner:
>
>    The description is split into two parts: "<signer>: <key-id>".
>
>    The <key-id> is a hex rendering of the key identifier - in the case of X.509
>    that would be the contents of the subjectKeyIdentifier extension field with
>    the ASN.1 OctetString wrapper removed.
>
>    The <signer> is (in order) one of:
>
>         - The O and CN attributes as "<O-attr>: <CN-attr>" if the CN attribute
>           isn't prefixed with the O attribute, and, if longer, doesn't share
>           the same first seven chars (say a company name such as Red Hat Inc.).
>           I admit this is entirely arbitrary and biased towards companies with
>           7 chars or more in there name, but it does remove duplication of the
>           organisation's name if it's in both the O and the CN.  Can anyone
>           suggest a better heuristic?
>
>         - The CN attribute.
>
>         - The O attribute.
>
>         - The email address.
>
>         - Omitted (with ": " omitted too).
>
>    As an example:
>
>         Magrathea: Glacier signing key: 5dd0839552bd6af498253f8af1e65da3472941c6
>
>    which is "<O-attr>: <CN-attr>: <key-id>" in form, or:
>
>         Red Hat Test Certificate: 3580cf35d76b3b667a40df66691cbcf87353b23c
>
>    which is just "<CN-attr>: <key-id>" in form.
>
>  - I no longer extract the bits of the X.509 certificate I don't currently use
>    (such as the version number).
>
> Note, this implementation of the X.509 certificate parser uses a couple of
> patterns to drive a reusable ASN.1 decoder.  I do, however, have a direct
> in-line decoder implementation also that can only decode X.509 certs.  The
> stack space usage is greater, but the code size is simpler and slightly smaller
> and the code is less capable (it can't handle indefinite-length elements for
> example), and it can't be reused for anything else (such as CIFS, netfilter,
> PKCS#7, Kerberos tickets), whereas the pattern-based decoder can.  I'll post
> this separately to see what people think.
>
> As far as testing goes, I have posted a number of testing scripts that I have
> used to punish the crypto keys side of things.  The "keyctl padd" command makes
> this straightforward.
>
> Hopefully, later this week the patches will appear in the Fedora 18 kernel.
>
> David
> ---
> The following changes since commit eeea3ac912207dcf759b95b2b4c36f96bce583bf:
>
>   Merge tag 'fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc (2012-09-06 10:23:58 -0700)
>
> are available in the git repository at:
>
>
>   git://git.kernel.org/pub/scm/linux/kernel/git/dhowells/linux-modsign.git modsign-post-KS
>
> for you to fetch changes up to 8d4f62638e9aae069d1145dfeb7300c58077be49:
>
>   MODSIGN: Extend the policy on signature check failure (2012-09-24 20:51:59 +0100)
>
> ----------------------------------------------------------------
> (from the branch description for modsign-post-KS local branch)
>
> post Kernel-Summit module signing
> ----------------------------------------------------------------
> David Howells (26):
>       KEYS: Add payload preparsing opportunity prior to key instantiate or update
>       MPILIB: Provide count_leading/trailing_zeros() based on arch functions
>       KEYS: Document asymmetric key type
>       KEYS: Implement asymmetric key type
>       KEYS: Asymmetric key pluggable data parsers
>       KEYS: Asymmetric public-key algorithm crypto key subtype
>       KEYS: Provide signature verification with an asymmetric key
>       MPILIB: Reinstate mpi_cmp[_ui]() and export for RSA signature verification
>       RSA: Implement signature verification algorithm [PKCS#1 / RFC3447]
>       RSA: Fix signature verification for shorter signatures
>       X.509: Implement simple static OID registry
>       X.509: Add utility functions to render OIDs as strings
>       X.509: Add simple ASN.1 grammar compiler
>       X.509: Add an ASN.1 decoder
>       MPILIB: Provide a function to read raw data into an MPI
>       X.509: Add a crypto key parser for binary (DER) X.509 certificates
>       Merge Rusty's module signature checking hook into modsign-post-KS
>       MOD: Fix Rusty's module_sig_check()
>       MODSIGN: Provide gitignore and make clean rules for extra files
>       MODSIGN: Provide Kconfig options
>       MODSIGN: Automatically generate module signing keys if missing
>       MODSIGN: Provide module signing public keys to the kernel
>       MODSIGN: Implement module signature checking
>       MODSIGN: Provide a script for generating a key ID from an X.509 cert
>       MODSIGN: Sign modules during the build process
>       MODSIGN: Extend the policy on signature check failure
>
> Rusty Russell (1):
>       module: signature checking hook
>
>  .gitignore                                |   13 +
>  Documentation/crypto/asymmetric-keys.txt  |  312 ++++++
>  Documentation/kernel-parameters.txt       |    6 +
>  Documentation/security/keys.txt           |   50 +-
>  Makefile                                  |    1 +
>  crypto/Kconfig                            |    1 +
>  crypto/Makefile                           |    1 +
>  crypto/asymmetric_keys/.gitignore         |    1 +
>  crypto/asymmetric_keys/Kconfig            |   38 +
>  crypto/asymmetric_keys/Makefile           |   27 +
>  crypto/asymmetric_keys/asymmetric_keys.h  |   15 +
>  crypto/asymmetric_keys/asymmetric_type.c  |  274 +++++
>  crypto/asymmetric_keys/public_key.c       |  108 ++
>  crypto/asymmetric_keys/public_key.h       |   30 +
>  crypto/asymmetric_keys/rsa.c              |  277 ++++++
>  crypto/asymmetric_keys/signature.c        |   49 +
>  crypto/asymmetric_keys/x509.asn1          |   60 ++
>  crypto/asymmetric_keys/x509_cert_parser.c |  497 ++++++++++
>  crypto/asymmetric_keys/x509_parser.h      |   36 +
>  crypto/asymmetric_keys/x509_public_key.c  |  207 ++++
>  crypto/asymmetric_keys/x509_rsakey.asn1   |    4 +
>  fs/cifs/cifs_spnego.c                     |    6 +-
>  fs/cifs/cifsacl.c                         |    8 +-
>  include/asm-generic/bitops/count_zeros.h  |   57 ++
>  include/crypto/public_key.h               |  108 ++
>  include/keys/asymmetric-parser.h          |   37 +
>  include/keys/asymmetric-subtype.h         |   55 +
>  include/keys/asymmetric-type.h            |   25 +
>  include/keys/user-type.h                  |    6 +-
>  include/linux/asn1.h                      |   67 ++
>  include/linux/asn1_ber_bytecode.h         |   87 ++
>  include/linux/asn1_decoder.h              |   24 +
>  include/linux/key-type.h                  |   35 +-
>  include/linux/module.h                    |    8 +
>  include/linux/mpi.h                       |    1 +
>  include/linux/oid_registry.h              |   92 ++
>  init/Kconfig                              |   68 ++
>  kernel/Makefile                           |   57 ++
>  kernel/modsign_pubkey.c                   |  112 +++
>  kernel/module-internal.h                  |   16 +
>  kernel/module.c                           |  100 +-
>  kernel/module_signing.c                   |  247 +++++
>  lib/.gitignore                            |    2 +-
>  lib/Kconfig                               |    5 +
>  lib/Makefile                              |   18 +
>  lib/asn1_decoder.c                        |  477 +++++++++
>  lib/build_OID_registry                    |  209 ++++
>  lib/mpi/Makefile                          |    1 +
>  lib/mpi/longlong.h                        |  138 +--
>  lib/mpi/mpi-bit.c                         |    2 +-
>  lib/mpi/mpi-cmp.c                         |   70 ++
>  lib/mpi/mpi-pow.c                         |    4 +-
>  lib/mpi/mpicoder.c                        |   55 +
>  lib/oid_registry.c                        |  170 ++++
>  net/ceph/crypto.c                         |    9 +-
>  net/dns_resolver/dns_key.c                |    6 +-
>  net/rxrpc/ar-key.c                        |   40 +-
>  scripts/.gitignore                        |    1 +
>  scripts/Makefile                          |    2 +
>  scripts/Makefile.build                    |   11 +
>  scripts/Makefile.modpost                  |   75 +-
>  scripts/asn1_compiler.c                   | 1545 +++++++++++++++++++++++++++++
>  scripts/sign-file                         |  115 +++
>  scripts/x509keyid                         |  268 +++++
>  security/keys/encrypted-keys/encrypted.c  |   16 +-
>  security/keys/key.c                       |  114 ++-
>  security/keys/keyctl.c                    |   18 +-
>  security/keys/keyring.c                   |    6 +-
>  security/keys/request_key_auth.c          |    8 +-
>  security/keys/trusted.c                   |   16 +-
>  security/keys/user_defined.c              |   14 +-
>  71 files changed, 6394 insertions(+), 244 deletions(-)
>  create mode 100644 Documentation/crypto/asymmetric-keys.txt
>  create mode 100644 crypto/asymmetric_keys/.gitignore
>  create mode 100644 crypto/asymmetric_keys/Kconfig
>  create mode 100644 crypto/asymmetric_keys/Makefile
>  create mode 100644 crypto/asymmetric_keys/asymmetric_keys.h
>  create mode 100644 crypto/asymmetric_keys/asymmetric_type.c
>  create mode 100644 crypto/asymmetric_keys/public_key.c
>  create mode 100644 crypto/asymmetric_keys/public_key.h
>  create mode 100644 crypto/asymmetric_keys/rsa.c
>  create mode 100644 crypto/asymmetric_keys/signature.c
>  create mode 100644 crypto/asymmetric_keys/x509.asn1
>  create mode 100644 crypto/asymmetric_keys/x509_cert_parser.c
>  create mode 100644 crypto/asymmetric_keys/x509_parser.h
>  create mode 100644 crypto/asymmetric_keys/x509_public_key.c
>  create mode 100644 crypto/asymmetric_keys/x509_rsakey.asn1
>  create mode 100644 include/asm-generic/bitops/count_zeros.h
>  create mode 100644 include/crypto/public_key.h
>  create mode 100644 include/keys/asymmetric-parser.h
>  create mode 100644 include/keys/asymmetric-subtype.h
>  create mode 100644 include/keys/asymmetric-type.h
>  create mode 100644 include/linux/asn1.h
>  create mode 100644 include/linux/asn1_ber_bytecode.h
>  create mode 100644 include/linux/asn1_decoder.h
>  create mode 100644 include/linux/oid_registry.h
>  create mode 100644 kernel/modsign_pubkey.c
>  create mode 100644 kernel/module-internal.h
>  create mode 100644 kernel/module_signing.c
>  create mode 100644 lib/asn1_decoder.c
>  create mode 100755 lib/build_OID_registry
>  create mode 100644 lib/mpi/mpi-cmp.c
>  create mode 100644 lib/oid_registry.c
>  create mode 100644 scripts/asn1_compiler.c
>  create mode 100644 scripts/sign-file
>  create mode 100755 scripts/x509keyid
> --
> To unsubscribe from this list: send the line "unsubscribe linux-crypto" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: Wrong system clock vs X.509 date specifiers
  2012-09-25 15:35   ` Wrong system clock vs X.509 date specifiers David Howells
  2012-09-25 15:43     ` Paolo Bonzini
@ 2012-09-25 16:00     ` Alan Cox
  2012-09-25 16:02     ` Tomas Mraz
                       ` (2 subsequent siblings)
  4 siblings, 0 replies; 47+ messages in thread
From: Alan Cox @ 2012-09-25 16:00 UTC (permalink / raw)
  To: David Howells
  Cc: rusty, herbert, pjones, jwboyer, linux-crypto,
	linux-security-module, linux-kernel, keyrings

On Tue, 25 Sep 2012 16:35:20 +0100
David Howells <dhowells@redhat.com> wrote:

> Alan Cox <alan@lxorguk.ukuu.org.uk> wrote:
> 
> > Generate a certificate that is valid from a few minutes before the
> > wallclock time. It's a certificate policy question not a kernel hackery
> > one.
> 
> That doesn't seem to be possible with openssl req.  What would you recommend?

LD_PRELOAD ? or fixing it if GNUTLS certtool can't do the needed. We
shouldn't botch security checks in kernel code to work around crappy
userspace tools.

Alan



^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: Wrong system clock vs X.509 date specifiers
  2012-09-25 15:35   ` Wrong system clock vs X.509 date specifiers David Howells
  2012-09-25 15:43     ` Paolo Bonzini
  2012-09-25 16:00     ` Alan Cox
@ 2012-09-25 16:02     ` Tomas Mraz
  2012-09-25 17:31     ` David Howells
  2012-09-25 21:57     ` David Howells
  4 siblings, 0 replies; 47+ messages in thread
From: Tomas Mraz @ 2012-09-25 16:02 UTC (permalink / raw)
  To: David Howells
  Cc: Alan Cox, rusty, herbert, pjones, jwboyer, linux-crypto,
	linux-security-module, linux-kernel, keyrings

On Tue, 2012-09-25 at 16:35 +0100, David Howells wrote: 
> Alan Cox <alan@lxorguk.ukuu.org.uk> wrote:
> 
> > Generate a certificate that is valid from a few minutes before the
> > wallclock time. It's a certificate policy question not a kernel hackery
> > one.
> 
> That doesn't seem to be possible with openssl req.  What would you recommend?

You can use openssl ca that allows to set arbitrary start date to
generate selfsigned certs as well (-selfsign option).
-- 
Tomas Mraz
No matter how far down the wrong road you've gone, turn back.
                                              Turkish proverb


^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: [GIT PULL] Asymmetric keys and module signing
  2012-09-25  0:07 [GIT PULL] Asymmetric keys and module signing David Howells
                   ` (2 preceding siblings ...)
  2012-09-25 15:44 ` [GIT PULL] Asymmetric keys and module signing Kasatkin, Dmitry
@ 2012-09-25 16:15 ` David Howells
  2012-09-26  3:46 ` Rusty Russell
  2012-09-26  9:09 ` David Howells
  5 siblings, 0 replies; 47+ messages in thread
From: David Howells @ 2012-09-25 16:15 UTC (permalink / raw)
  To: Kasatkin, Dmitry
  Cc: dhowells, herbert, rusty, pjones, jwboyer, linux-crypto,
	linux-security-module, linux-kernel, keyrings

Kasatkin, Dmitry <dmitry.kasatkin@intel.com> wrote:

> Just one question about key description...
> request_asymmetric_key uses format for key  description: "<signer>: <key-id>".
> Preparsing code creates description from those values.
> I see that key id is not 8 bytes anymore but full hash size of 20 bytes.

Remember:  This is for viewing via /proc/keys and KEYCTL_DESCRIBE as much as
for matching.

> For practical reasons for IMA it might be nice to save some space in
> xattrs and use shorter key id/description.

That's reasonable.

> As I understand from implementation, if key name is provided with "keyctl
> add", it will not be replaced with preparsed value.

Correct.

> And we can actually use any keyid we want?

Yes.

Note: The key type ->match() function is not required to limit itself to a
direct strcmp().  It is at liberty to partially match the description or any
other data attached to the key.

Look at asymmetric_key_match() in crypto/asymmetric/asymmetric_type.c.  If you
do a search for:

	"id:<hex-string>"

this will do a partial tail match on the key fingerprint:

[root@andromeda ~]# keyctl padd asymmetric "" @s </tmp/uefi-x509 
289786205
[root@andromeda ~]# cat /proc/keys
1145c95d I--Q---     1 perm 39390000     0     0 asymmetri Red Hat Test Certificate: 3580cf35d76b3b667a40df66691cbcf87353b23c: X509.RSA 7353b23c []
...
[root@andromeda ~]# keyctl search @s asymmetric "id:53b23c"
289786205


As an optimisation, it might be worth internally calling keyring_search_aux()
with our own match function that takes a binary key ID and storing the
fingerprint as binary rather than hex (attached to key->type_data.p[1]).

The type match function can only take text strings as it has to be invoked
from userspace.

David

^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: Wrong system clock vs X.509 date specifiers
  2012-09-25 15:35   ` Wrong system clock vs X.509 date specifiers David Howells
                       ` (2 preceding siblings ...)
  2012-09-25 16:02     ` Tomas Mraz
@ 2012-09-25 17:31     ` David Howells
  2012-09-25 18:39       ` Tomas Mraz
  2012-09-25 21:57     ` David Howells
  4 siblings, 1 reply; 47+ messages in thread
From: David Howells @ 2012-09-25 17:31 UTC (permalink / raw)
  To: Tomas Mraz
  Cc: dhowells, Alan Cox, rusty, herbert, pjones, jwboyer,
	linux-crypto, linux-security-module, linux-kernel, keyrings

Tomas Mraz <tmraz@redhat.com> wrote:

> You can use openssl ca that allows to set arbitrary start date to
> generate selfsigned certs as well (-selfsign option).

That seems to require some stuff I don't have installed:

warthog>openssl ca -in signing_key.priv -extensions v3_ca -out newcert.pem
Using configuration from /etc/pki/tls/openssl.cnf
Error opening CA private key /etc/pki/CA/private/cakey.pem
140244246955872:error:0200100D:system library:fopen:Permission denied:bss_file.c:398:fopen('/etc/pki/CA/private/cakey.pem','r')
140244246955872:error:20074002:BIO routines:FILE_CTRL:system lib:bss_file.c:400:
unable to load CA private key
unable to write 'random state'

(the /etc/pki/CA/private/ dir is inaccessible if not root and doesn't in any
case contain cakey.pem).

Do I need to start with all the CA stuff in the right places to use it?

David

^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: Wrong system clock vs X.509 date specifiers
  2012-09-25 17:31     ` David Howells
@ 2012-09-25 18:39       ` Tomas Mraz
  0 siblings, 0 replies; 47+ messages in thread
From: Tomas Mraz @ 2012-09-25 18:39 UTC (permalink / raw)
  To: David Howells
  Cc: Alan Cox, rusty, herbert, pjones, jwboyer, linux-crypto,
	linux-security-module, linux-kernel, keyrings

On Tue, 2012-09-25 at 18:31 +0100, David Howells wrote: 
> Tomas Mraz <tmraz@redhat.com> wrote:
> 
> > You can use openssl ca that allows to set arbitrary start date to
> > generate selfsigned certs as well (-selfsign option).
> 
> That seems to require some stuff I don't have installed:
> 
> warthog>openssl ca -in signing_key.priv -extensions v3_ca -out newcert.pem
> Using configuration from /etc/pki/tls/openssl.cnf
> Error opening CA private key /etc/pki/CA/private/cakey.pem
> 140244246955872:error:0200100D:system library:fopen:Permission denied:bss_file.c:398:fopen('/etc/pki/CA/private/cakey.pem','r')
> 140244246955872:error:20074002:BIO routines:FILE_CTRL:system lib:bss_file.c:400:
> unable to load CA private key
> unable to write 'random state'
> 
> (the /etc/pki/CA/private/ dir is inaccessible if not root and doesn't in any
> case contain cakey.pem).
> 
> Do I need to start with all the CA stuff in the right places to use it?

You can configure it to point to a different directories. But yes, you
have to create a CA cert and so on. 
-- 
Tomas Mraz
No matter how far down the wrong road you've gone, turn back.
                                              Turkish proverb


^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: Wrong system clock vs X.509 date specifiers
  2012-09-25 15:35   ` Wrong system clock vs X.509 date specifiers David Howells
                       ` (3 preceding siblings ...)
  2012-09-25 17:31     ` David Howells
@ 2012-09-25 21:57     ` David Howells
  4 siblings, 0 replies; 47+ messages in thread
From: David Howells @ 2012-09-25 21:57 UTC (permalink / raw)
  To: Alan Cox
  Cc: dhowells, rusty, herbert, pjones, jwboyer, linux-crypto,
	linux-security-module, linux-kernel, keyrings


How about the attached?  I knew perl had to be good for something...

David
---
#!/usr/bin/perl -w
#
# Generate an X.509 certificate from a public key.
#
# Format:
#
#	gen-x509-cert <private-key> \
#	   [C=<country>] [O=<org>] [CN=<cn>] [Email=<email>] \
#	   [--from=<secs-before-now>] [--to=<secs-after-now] >output
#
use strict;
use POSIX qw(strftime);

my $UNIV = 0 << 6;
my $APPL = 1 << 6;
my $CONT = 2 << 6;
my $PRIV = 3 << 6;

my $BOOLEAN	= 0x01;
my $INTEGER	= 0x02;
my $BIT_STRING	= 0x03;
my $OCTET_STRING = 0x04;
my $NULL	= 0x05;
my $OBJ_ID	= 0x06;
my $UTF8String	= 0x0c;
my $SEQUENCE	= 0x10;
my $SET		= 0x11;
my $GeneralizedTime = 0x18;

my %OIDs = (
    commonName			=> pack("CCC", 85, 4, 3),
    countryName			=> pack("CCC", 85, 4, 6),
    organizationName		=> pack("CCC", 85, 4, 10),
    organizationUnitName	=> pack("CCC", 85, 4, 11),
    rsaEncryption		=> pack("CCCCCCCCC", 42, 134, 72, 134, 247, 13, 1, 1, 1),
    sha1WithRSAEncryption	=> pack("CCCCCCCCC", 42, 134, 72, 134, 247, 13, 1, 1, 5),
    emailAddress		=> pack("CCCCCCCCC", 42, 134, 72, 134, 247, 13, 1, 9, 1),
    authorityKeyIdentifier	=> pack("CCC", 85, 29, 35),
    subjectKeyIdentifier	=> pack("CCC", 85, 29, 14),
    keyUsage			=> pack("CCC", 85, 29, 15),
    basicConstraints		=> pack("CCC", 85, 29, 19)
);


#
# Set up the X.509 params
#
die "Format: <private-key> [options]"
    if ($#ARGV == -1);

my $privfilename = shift @ARGV;

my %subject_name;

if ($#ARGV == -1) {
    # Make something up if they don't want to admit to it
    $subject_name{"C"}		= 'h2g2',
    $subject_name{"O"}		= 'Magrathea',
    $subject_name{"CN"}		= 'Glacier signing key',
    $subject_name{"Email"}	= 'slartibartfast@magrathea.h2g2'
}

my $from = 7 * 24 * 60 * 60;
my $to = 36500 * 24 * 60 * 60;
foreach my $_ (@ARGV) {
    if (/--from=(.*)/) {
	$from = $1;
    } elsif (/--to=(.*)/) {
	$to = $1;
    } elsif (/([A-Z][A-Za-z]*)=(.*)/) {
	$subject_name{$1} = $2;
    } else {
	last;
    }
}

my $now = time();
my $valid_from = strftime("%Y%m%d%H%M%SZ", gmtime($now - $from));
my $valid_to   = strftime("%Y%m%d%H%M%SZ", gmtime($now + $to));

#
# openssl can be used to give us the public key in exactly the form we need -
# including ASN.1 wrappings - for inclusion in the certificate.
#
open PUBKEYFD, "openssl rsa -in $privfilename -pubout -outform DER 2>/dev/null |" ||
    die "Unable to process $privfilename through openssl rsa: $!\n";
binmode PUBKEYFD;

my $pubkey = "";
my $tmp;
while (read(PUBKEYFD, $tmp, 512)) {
    $pubkey .= $tmp;
}
close PUBKEYFD ||
    die "Unable to close channel to openssl rsa: $!\n";

#
# Generate a serial number
#
my $serial = "";
for (my $i = int(rand(6)) + 6; $i > 0; $i--) {
    $serial .= pack("C", rand(256));
}
$serial = pack("x") . $serial
    if (unpack("C", substr($serial, 0, 1)) >= 0x80);

#
# Generate the SubjectKeyIdentifier.  This is the ASN.1 sum of the contents of
# the bit string element from the public key.
#
die "Can't disassemble RSA public key wrapping\n"
    if (substr($pubkey,  0, 2) ne pack("n", 0x3082) ||
	substr($pubkey,  4, 4) ne pack("N", 0x300d0609) ||
	substr($pubkey,  8, 9) ne $OIDs{"rsaEncryption"} ||
	substr($pubkey, 17, 2) ne pack("n", 0x0500) ||
	substr($pubkey, 19, 2) ne pack("n", 0x0382) ||
	substr($pubkey, 23, 1) ne pack("C", 0x00));

my $key_data = substr($pubkey, 24);

sub sha1sum($)
{
    my ($data) = @_;

    my ($TO_RD, $TO_WR, $FROM_RD, $FROM_WR);
    pipe $TO_RD, $TO_WR;
    pipe $FROM_RD, $FROM_WR;

    my $sha1output;
    my $child = fork();
    if ($child == 0) {
	close $TO_WR;
	close $FROM_RD;
	open(STDIN, ">&", $TO_RD) or die "Can't direct $TO_RD to STDIN: $!";
	open(STDOUT, ">&", $FROM_WR) or die "Can't direct $FROM_WR to STDOUT: $!";
	close $TO_RD;
	close $FROM_WR;
	exec("sha1sum");
    } elsif (!$child) {
	die;
    } else {
	close $TO_RD;
	close $FROM_WR;
	binmode $TO_WR;
	syswrite $TO_WR, $data || die;
	close $TO_WR || die;
	$sha1output = <$FROM_RD> || die;
	close $FROM_RD;
	die "sha1sum failed\n"
	    if (waitpid($child, 0) != $child);
    }

    return pack("H*", substr($sha1output, 0, 40));
}

my $keyid = sha1sum($key_data);

###############################################################################
#
# Generate a header
#
###############################################################################
sub emit_asn1_hdr($$)
{
    my ($tag, $len) = @_;

    if ($len < 0x80) {
	return pack("CC",   $tag, $len);
    } elsif ($len <= 0xff) {
	return pack("CCC",   $tag, 0x81, $len);
    } elsif ($len <= 0xffff) {
	return pack("CCn",  $tag, 0x82, $len);
    } elsif ($len <= 0xffffff) {
	return pack("CCCn", $tag, 0x83, $len >> 16, $len & 0xffff);
    } else {
	return pack("CCN",  $tag, 0x84, $len);
    }
}

###############################################################################
#
# Generate a primitive containing some data
#
###############################################################################
sub emit_asn1_prim(@)
{
    my ($class, $tag, $data) = @_;

    $data = ""
	if ($#_ == 1);

    $tag |= $class;
    return emit_asn1_hdr($tag, length($data)) . $data;
}

###############################################################################
#
# Generate an object identifier
#
###############################################################################
sub emit_asn1_OID($$$)
{
    my ($class, $tag, $oid_name) = @_;
    my $oid;

    if (!exists($OIDs{$oid_name})) {
	print STDERR "Unknown OID: $oid_name\n";
	exit(2);
    }

    $oid = $OIDs{$oid_name};
    return emit_asn1_hdr($class | $tag, length($oid)) . $oid;
}

###############################################################################
#
# Generate a bit string.  This has a leading byte indicating the number of
# trailing bits that should be ignored.
#
###############################################################################
sub emit_asn1_bts($$$)
{
    my ($class, $tag, $content) = @_;
    return emit_asn1_prim($class, $tag, pack("x") . $content);
}

###############################################################################
#
# Generate a construct
#
###############################################################################
sub emit_asn1_cons($$$)
{
    my ($class, $tag, $content) = @_;

    return emit_asn1_hdr($class | 0x20 | $tag, length($content)) . $content;
}

###############################################################################
#
# Generate a name
#
###############################################################################
sub emit_x509_AttributeValueAssertion($$$)
{
    my ($type, $name, $sym) = @_;
    my $output;
    my $data;

    return "" if (!exists($name->{$sym}));

    $data = $name->{$sym};
    $output  = emit_asn1_OID($UNIV, $OBJ_ID, $type);		# attributeType
    $output .= emit_asn1_prim($UNIV, $UTF8String, $data);	# attributeValue
    return emit_asn1_cons($UNIV, $SET,
			  emit_asn1_cons($UNIV, $SEQUENCE, $output));
}

sub emit_x509_RelativeDistinguishedName($)
{
    my ($name) = @_;
    my $output;

    # SET OF AttributeValueAssertion
    $output .= emit_x509_AttributeValueAssertion("countryName", $name, "C");
    $output .= emit_x509_AttributeValueAssertion("organizationName", $name, "O");
    $output .= emit_x509_AttributeValueAssertion("organizationUnitName", $name, "OU");
    $output .= emit_x509_AttributeValueAssertion("commonName", $name, "CN");
    $output .= emit_x509_AttributeValueAssertion("emailAddress", $name, "Email");
    return $output;
}

sub emit_x509_Name($)
{
    my ($name) = @_;
    my $output;

    # SEQUENCE OF RDN
    $output  = emit_x509_RelativeDistinguishedName($name);
    return emit_asn1_cons($UNIV, $SEQUENCE, $output);
}

###############################################################################
#
# Generate some X.509 extensions
#
###############################################################################
sub emit_x509_SubjectKeyIdentifier()
{
    return emit_asn1_prim($UNIV, $OCTET_STRING, $keyid);
}

sub emit_x509_AuthorityKeyIdentifier()
{
    my $content = emit_asn1_prim($CONT, 0, $keyid);
    return emit_asn1_cons($UNIV, $SEQUENCE, $content);
}

sub emit_x509_BasicConstraints()
{
    return pack("CC", 0x30, 0x00);
}

sub emit_x509_KeyUsage()
{
    return emit_asn1_prim($UNIV, $BIT_STRING, pack("CC", 0x07, 0x80));
}

sub emit_x509_Extension($@)
{
    my ($ext, $crit) = @_;
    my $output;
    my $value = "";

    if ($ext eq "authorityKeyIdentifier") {
	$output = emit_asn1_OID($UNIV, $OBJ_ID, $ext);
	$value = emit_x509_AuthorityKeyIdentifier();
    } elsif ($ext eq "subjectKeyIdentifier") {
	$output = emit_asn1_OID($UNIV, $OBJ_ID, $ext);
	$value = emit_x509_SubjectKeyIdentifier();
    } elsif ($ext eq "basicConstraints") {
	$output = emit_asn1_OID($UNIV, $OBJ_ID, $ext);
	$value = emit_x509_BasicConstraints();
    } elsif ($ext eq "keyUsage") {
	$output = emit_asn1_OID($UNIV, $OBJ_ID, $ext);
	$value = emit_x509_KeyUsage();
    } else {
	die;
    }

    $output .= emit_asn1_prim($UNIV, $BOOLEAN, pack("C", 0x01))	# critical
	if ($crit);
    $output .= emit_asn1_hdr($UNIV | $OCTET_STRING, length($value)) . $value;

    return emit_asn1_cons($UNIV, $SEQUENCE, $output);
}

sub emit_x509_Extensions()
{
    my $output = "";

    # Probably do want a sequence of extensions here
    $output .= emit_x509_Extension("basicConstraints", 1);
    $output .= emit_x509_Extension("keyUsage");
    $output .= emit_x509_Extension("authorityKeyIdentifier");
    $output .= emit_x509_Extension("subjectKeyIdentifier");

    return emit_asn1_cons($CONT, 3, emit_asn1_cons($UNIV, $SEQUENCE, $output));
}

###############################################################################
#
# Sign a digest with an RSA key
#
###############################################################################
sub rsa_sign($)
{
    my ($digest) = @_;

    my ($TO_RD, $TO_WR, $FROM_RD, $FROM_WR);
    pipe $TO_RD, $TO_WR;
    pipe $FROM_RD, $FROM_WR;

    my $output;
    my $child = fork();
    if ($child == 0) {
	close $TO_WR;
	close $FROM_RD;
	open(STDIN, ">&", $TO_RD) or die "Can't direct $TO_RD to STDIN: $!";
	open(STDOUT, ">&", $FROM_WR) or die "Can't direct $FROM_WR to STDOUT: $!";
	close $TO_RD;
	close $FROM_WR;
	exec("openssl rsautl -sign -inkey $privfilename");
    } elsif (!$child) {
	die;
    } else {
	close $TO_RD;
	close $FROM_WR;
	binmode $TO_WR;
	syswrite $TO_WR, $digest || die;
	close $TO_WR || die;

	my $tmp;
	while (read($FROM_RD, $tmp, 512)) {
	    $output .= $tmp;
	}
	close $FROM_RD;
	die "openssl rsautl failed\n"
	    if (waitpid($child, 0) != $child);
    }

    return $output;
}

###############################################################################
#
# Generate an X.509 certificate
#
###############################################################################
sub emit_x509_Validity()
{
    my $output;
    $output  = emit_asn1_prim($UNIV, $GeneralizedTime, $valid_from);	# notBefore
    $output .= emit_asn1_prim($UNIV, $GeneralizedTime, $valid_to);	# notAfter
    return emit_asn1_cons($UNIV, $SEQUENCE, $output);
}

sub emit_x509_AlgorithmIdentifier($)
{
    my ($oid) = @_;
    my $output;

    $output  = emit_asn1_OID($UNIV, $OBJ_ID, $oid);	# algorithm
    $output .= emit_asn1_prim($UNIV, $NULL);		# parameters
    return emit_asn1_cons($UNIV, $SEQUENCE, $output);
}

sub emit_x509_Version()
{
    # Version 3
    my $output = emit_asn1_prim($UNIV, $INTEGER, pack("C", 3 - 1));
    return emit_asn1_cons($CONT, 0, $output);
}

sub emit_x509_SubjectPublicKeyInfo()
{
    my $output;
    $output  = emit_x509_AlgorithmIdentifier("rsaEncryption");	# algorithm
    $output .= emit_asn1_prim($UNIV, $BIT_STRING);	# subjectPublicKey
    return emit_asn1_cons($UNIV, $SEQUENCE, $output);
}

sub emit_x509_TBSCertificate()
{
    my $output;

    $output  = emit_x509_Version;			# version
    $output .= emit_asn1_prim($UNIV, $INTEGER, $serial); # serialNumber
    $output .= emit_x509_AlgorithmIdentifier("sha1WithRSAEncryption");	# signature
    $output .= emit_x509_Name(\%subject_name);		# issuer
    $output .= emit_x509_Validity();			# validity
    $output .= emit_x509_Name(\%subject_name);		# subject
    #$output .= emit_x509_SubjectPublicKeyInfo();	# subjectPublicKeyInfo
    $output .= $pubkey;
    $output .= emit_x509_Extensions();			# extensions

    return emit_asn1_cons($UNIV, $SEQUENCE, $output);
}

sub emit_x509_Certificate()
{
    my $output;

    $output  = emit_x509_TBSCertificate();		# tbsCertificate

    # We digest the TBS and sign it.
    my $tbs_digest =
	pack("C*", 0x30, 0x21, 0x30, 0x09, 0x06, 0x05,
	     0x2B, 0x0E, 0x03, 0x02, 0x1A,
	     0x05, 0x00, 0x04, 0x14) .
	     sha1sum($output);

    my $sig = rsa_sign($tbs_digest);

    $output .= emit_x509_AlgorithmIdentifier("sha1WithRSAEncryption");	# signatureAlgorithm
    $output .= emit_asn1_bts($UNIV, $BIT_STRING, $sig);	# signature

    return emit_asn1_cons($UNIV, $SEQUENCE, $output);
}

print emit_x509_Certificate();

^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: [GIT PULL] Asymmetric keys and module signing
  2012-09-25  0:07 [GIT PULL] Asymmetric keys and module signing David Howells
                   ` (3 preceding siblings ...)
  2012-09-25 16:15 ` David Howells
@ 2012-09-26  3:46 ` Rusty Russell
  2012-09-27  2:04   ` Mimi Zohar
                     ` (2 more replies)
  2012-09-26  9:09 ` David Howells
  5 siblings, 3 replies; 47+ messages in thread
From: Rusty Russell @ 2012-09-26  3:46 UTC (permalink / raw)
  To: David Howells, herbert
  Cc: dhowells, pjones, jwboyer, linux-crypto, linux-security-module,
	linux-kernel, keyrings

David Howells <dhowells@redhat.com> writes:
> The module signing patches provide:
>
>  - Some fixes to Rusty's patch.  Also an additional patch to extend the policy
>    handling for modules signed with an unknown key and to handle FIPS mode.

Ok, I merged some of this (after our previous accidentally-off-list
discussion).

You previously wrote:
> You can't compare them that easily.  One has a FIPS-mode panic and the other
> doesn't.  Do we want to panic if we reject an unsigned module in enforcing
> mode when we're in FIPS mode?

It's a line ball, but I think consistency wins.  Not a validly signed
module => panic.

The code becomes pretty straightforward then:

        if (!err) {
                info->sig_ok = true;
                return 0;
        }
        if (fips_enabled)
               panic("Module verification failed with error %d in FIPS mode\n",
                     err);
        if (err == -ENOKEY && !sig_enforce)
                err = 0;
        
        return err;

In preparation, I've changed that below (and also, fixed up the -ENOKEY
which I said I'd do, and didn't).

Thanks,
Rusty.
PS.  Agree with Kconfig options move, but I'll do that in separate patch.

From: Rusty Russell <rusty@rustcorp.com.au>
Subject: module: signature checking hook

We do a very simple search for a particular string appended to the module
(which is cache-hot and about to be SHA'd anyway).  There's both a config
option and a boot parameter which control whether we accept (and taint) or
fail with unsigned modules.

(Useful feedback and tweaks by David Howells <dhowells@redhat.com>)

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>

diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -1582,6 +1582,12 @@ bytes respectively. Such letter suffixes
 			log everything. Information is printed at KERN_DEBUG
 			so loglevel=8 may also need to be specified.
 
+	module.sig_enforce
+			[KNL] When CONFIG_MODULE_SIG is set, this means that
+			modules without (valid) signatures will fail to load.
+			Note that if CONFIG_MODULE_SIG_ENFORCE is set, that
+			is always true, so this option does nothing.
+
 	mousedev.tap_time=
 			[MOUSE] Maximum time between finger touching and
 			leaving touchpad surface for touch to be considered
diff --git a/include/linux/module.h b/include/linux/module.h
--- a/include/linux/module.h
+++ b/include/linux/module.h
@@ -21,6 +21,9 @@
 #include <linux/percpu.h>
 #include <asm/module.h>
 
+/* In stripped ARM and x86-64 modules, ~ is surprisingly rare. */
+#define MODULE_SIG_STRING "~Module signature appended~\n"
+
 /* Not Yet Implemented */
 #define MODULE_SUPPORTED_DEVICE(name)
 
@@ -260,6 +263,11 @@ struct module
 	const unsigned long *unused_gpl_crcs;
 #endif
 
+#ifdef CONFIG_MODULE_SIG
+	/* Signature was verified. */
+	bool sig_ok;
+#endif
+
 	/* symbols that will be GPL-only in the near future. */
 	const struct kernel_symbol *gpl_future_syms;
 	const unsigned long *gpl_future_crcs;
diff --git a/init/Kconfig b/init/Kconfig
--- a/init/Kconfig
+++ b/init/Kconfig
@@ -1585,6 +1585,20 @@ config MODULE_SRCVERSION_ALL
 	  the version).  With this option, such a "srcversion" field
 	  will be created for all modules.  If unsure, say N.
 
+config MODULE_SIG
+	bool "Module signature verification"
+	depends on MODULES
+	help
+	  Check modules for valid signatures upon load: the signature
+	  is simply appended to the module. For more information see
+	  Documentation/module-signing.txt.
+
+config MODULE_SIG_FORCE
+	bool "Require modules to be validly signed"
+	depends on MODULE_SIG
+	help
+	  Reject unsigned modules or signed modules for which we don't have a
+	  key.  Without this, such modules will simply taint the kernel.
 endif # MODULES
 
 config INIT_ALL_POSSIBLE
diff --git a/kernel/Makefile b/kernel/Makefile
--- a/kernel/Makefile
+++ b/kernel/Makefile
@@ -55,6 +55,7 @@ obj-$(CONFIG_DEBUG_SPINLOCK) += spinlock
 obj-$(CONFIG_PROVE_LOCKING) += spinlock.o
 obj-$(CONFIG_UID16) += uid16.o
 obj-$(CONFIG_MODULES) += module.o
+obj-$(CONFIG_MODULE_SIG) += module_signing.o
 obj-$(CONFIG_KALLSYMS) += kallsyms.o
 obj-$(CONFIG_BSD_PROCESS_ACCT) += acct.o
 obj-$(CONFIG_KEXEC) += kexec.o
diff --git a/kernel/module-internal.h b/kernel/module-internal.h
new file mode 100644
--- /dev/null
+++ b/kernel/module-internal.h
@@ -0,0 +1,13 @@
+/* Module internals
+ *
+ * Copyright (C) 2012 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.
+ */
+
+extern int mod_verify_sig(const void *mod, unsigned long modlen,
+			  const void *sig, unsigned long siglen);
diff --git a/kernel/module.c b/kernel/module.c
--- a/kernel/module.c
+++ b/kernel/module.c
@@ -58,6 +58,7 @@
 #include <linux/jump_label.h>
 #include <linux/pfn.h>
 #include <linux/bsearch.h>
+#include "module-internal.h"
 
 #define CREATE_TRACE_POINTS
 #include <trace/events/module.h>
@@ -102,6 +103,43 @@ static LIST_HEAD(modules);
 struct list_head *kdb_modules = &modules; /* kdb needs the list of modules */
 #endif /* CONFIG_KGDB_KDB */
 
+#ifdef CONFIG_MODULE_SIG
+#ifdef CONFIG_MODULE_SIG_FORCE
+static bool sig_enforce = true;
+#else
+static bool sig_enforce = false;
+
+static int param_set_bool_enable_only(const char *val,
+				      const struct kernel_param *kp)
+{
+	int err;
+	bool test;
+	struct kernel_param dummy_kp = *kp;
+
+	dummy_kp.arg = &test;
+
+	err = param_set_bool(val, &dummy_kp);
+	if (err)
+		return err;
+
+	/* Don't let them unset it once it's set! */
+	if (!test && sig_enforce)
+		return -EROFS;
+
+	if (test)
+		sig_enforce = true;
+	return 0;
+}
+
+static const struct kernel_param_ops param_ops_bool_enable_only = {
+	.set = param_set_bool_enable_only,
+	.get = param_get_bool,
+};
+#define param_check_bool_enable_only param_check_bool
+
+module_param(sig_enforce, bool_enable_only, 0644);
+#endif /* !CONFIG_MODULE_SIG_FORCE */
+#endif /* CONFIG_MODULE_SIG */
 
 /* Block module loading/unloading? */
 int modules_disabled = 0;
@@ -136,6 +174,7 @@ struct load_info {
 	unsigned long symoffs, stroffs;
 	struct _ddebug *debug;
 	unsigned int num_debug;
+	bool sig_ok;
 	struct {
 		unsigned int sym, str, mod, vers, info, pcpu;
 	} index;
@@ -2379,7 +2418,49 @@ static inline void kmemleak_load_module(
 }
 #endif
 
-/* Sets info->hdr and info->len. */
+#ifdef CONFIG_MODULE_SIG
+static int module_sig_check(struct load_info *info,
+			    const void *mod, unsigned long *len)
+{
+	int err = -ENOKEY;
+	const unsigned long markerlen = sizeof(MODULE_SIG_STRING) - 1;
+	const void *p = mod, *end = mod + *len;
+
+	/* Poor man's memmem. */
+	while ((p = memchr(p, MODULE_SIG_STRING[0], end - p))) {
+		if (p + markerlen > end)
+			break;
+
+		if (memcmp(p, MODULE_SIG_STRING, markerlen) == 0) {
+			const void *sig = p + markerlen;
+			/* Truncate module up to signature. */
+			*len = p - mod;
+			err = mod_verify_sig(mod, *len, sig, end - sig);
+			break;
+		}
+		p++;
+	}
+
+	if (!err) {
+		info->sig_ok = true;
+		return 0;
+	}
+
+	/* Not having a signature is only an error if we're strict. */
+	if (err == -ENOKEY && !sig_enforce)
+		err = 0;
+
+	return err;
+}
+#else /* !CONFIG_MODULE_SIG */
+static int module_sig_check(struct load_info *info,
+			    void *mod, unsigned long *len)
+{
+	return 0;
+}
+#endif /* !CONFIG_MODULE_SIG */
+
+/* Sets info->hdr, info->len and info->sig_ok. */
 static int copy_and_check(struct load_info *info,
 			  const void __user *umod, unsigned long len,
 			  const char __user *uargs)
@@ -2399,6 +2480,10 @@ static int copy_and_check(struct load_in
 		goto free_hdr;
 	}
 
+	err = module_sig_check(info, hdr, &len);
+	if (err)
+		goto free_hdr;
+
 	/* Sanity checks against insmoding binaries or wrong arch,
 	   weird elf version */
 	if (memcmp(hdr->e_ident, ELFMAG, SELFMAG) != 0
@@ -2884,6 +2969,12 @@ static struct module *load_module(void _
 		goto free_copy;
 	}
 
+#ifdef CONFIG_MODULE_SIG
+	mod->sig_ok = info.sig_ok;
+	if (!mod->sig_ok)
+		add_taint_module(mod, TAINT_FORCED_MODULE);
+#endif
+
 	/* Now module is in final location, initialize linked lists, etc. */
 	err = module_unload_init(mod);
 	if (err)
diff --git a/kernel/module_signing.c b/kernel/module_signing.c
new file mode 100644
--- /dev/null
+++ b/kernel/module_signing.c
@@ -0,0 +1,22 @@
+/* Module signature checker
+ *
+ * Copyright (C) 2012 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.
+ */
+
+#include <linux/kernel.h>
+#include "module-internal.h"
+
+/*
+ * Verify the signature on a module.
+ */
+int mod_verify_sig(const void *mod, unsigned long modlen,
+		   const void *sig, unsigned long siglen)
+{
+	return -ENOKEY;
+}


^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: [GIT PULL] Asymmetric keys and module signing
  2012-09-25  0:07 [GIT PULL] Asymmetric keys and module signing David Howells
                   ` (4 preceding siblings ...)
  2012-09-26  3:46 ` Rusty Russell
@ 2012-09-26  9:09 ` David Howells
  2012-09-27  0:12   ` Rusty Russell
  2012-09-27  9:08   ` David Howells
  5 siblings, 2 replies; 47+ messages in thread
From: David Howells @ 2012-09-26  9:09 UTC (permalink / raw)
  To: Rusty Russell
  Cc: dhowells, herbert, pjones, jwboyer, linux-crypto,
	linux-security-module, linux-kernel, keyrings

Rusty Russell <rusty@rustcorp.com.au> wrote:

> We do a very simple search for a particular string appended to the module
> (which is cache-hot and about to be SHA'd anyway).  There's both a config
> option and a boot parameter which control whether we accept (and taint) or
> fail with unsigned modules.

I've adjusted your patch description to this:

    We do a very simple search for a particular string appended to the module
    (which is cache-hot and about to be SHA'd anyway).  There's both a config
    option and a boot parameter which control whether we accept or fail with
    unsigned modules and modules that are signed with an unknown key.

    If module signing is enabled, the kernel will be tainted if a module is
    accepted that is unsigned or has a signature for which we don't have the
    key.

I think it's worth mentioning the policy for unknown keys and worth making
clear under what circumstances we mean the kernel to be tainted.

David

^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: [GIT PULL] Asymmetric keys and module signing
  2012-09-26  9:09 ` David Howells
@ 2012-09-27  0:12   ` Rusty Russell
  2012-09-27  9:08   ` David Howells
  1 sibling, 0 replies; 47+ messages in thread
From: Rusty Russell @ 2012-09-27  0:12 UTC (permalink / raw)
  To: David Howells
  Cc: dhowells, herbert, pjones, jwboyer, linux-crypto,
	linux-security-module, linux-kernel, keyrings

David Howells <dhowells@redhat.com> writes:

> Rusty Russell <rusty@rustcorp.com.au> wrote:
>
>> We do a very simple search for a particular string appended to the module
>> (which is cache-hot and about to be SHA'd anyway).  There's both a config
>> option and a boot parameter which control whether we accept (and taint) or
>> fail with unsigned modules.
>
> I've adjusted your patch description to this:
>
>     We do a very simple search for a particular string appended to the module
>     (which is cache-hot and about to be SHA'd anyway).  There's both a config
>     option and a boot parameter which control whether we accept or fail with
>     unsigned modules and modules that are signed with an unknown key.
>
>     If module signing is enabled, the kernel will be tainted if a module is
>     accepted that is unsigned or has a signature for which we don't have the
>     key.
>
> I think it's worth mentioning the policy for unknown keys and worth making
> clear under what circumstances we mean the kernel to be tainted.

Great!  I checked your Kconfig help, too, which is states it clearly:

config MODULE_SIG_FORCE
	bool "Require modules to be validly signed"
	depends on MODULE_SIG
	help
	  Reject unsigned modules or signed modules for which we don't have a
	  key.  Without this, such modules will simply taint the kernel.


Which is really nice, since the kernel Kconfig help messages tend to
suck.

Thanks,
Rusty.

^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: [GIT PULL] Asymmetric keys and module signing
  2012-09-26  3:46 ` Rusty Russell
@ 2012-09-27  2:04   ` Mimi Zohar
  2012-09-28  6:54     ` Rusty Russell
  2012-09-28  6:27   ` Geert Uytterhoeven
  2012-09-28  8:00   ` David Howells
  2 siblings, 1 reply; 47+ messages in thread
From: Mimi Zohar @ 2012-09-27  2:04 UTC (permalink / raw)
  To: Rusty Russell
  Cc: David Howells, herbert, pjones, jwboyer, linux-crypto,
	linux-security-module, linux-kernel, keyrings

On Wed, 2012-09-26 at 13:16 +0930, Rusty Russell wrote:
> David Howells <dhowells@redhat.com> writes:
> > The module signing patches provide:
> >
> >  - Some fixes to Rusty's patch.  Also an additional patch to extend the policy
> >    handling for modules signed with an unknown key and to handle FIPS mode.
> 
> Ok, I merged some of this (after our previous accidentally-off-list
> discussion).

Rusty, have you pushed this branch out yet?

thanks,

Mimi


^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: [GIT PULL] Asymmetric keys and module signing
  2012-09-26  9:09 ` David Howells
  2012-09-27  0:12   ` Rusty Russell
@ 2012-09-27  9:08   ` David Howells
  2012-09-28  5:55     ` Rusty Russell
                       ` (10 more replies)
  1 sibling, 11 replies; 47+ messages in thread
From: David Howells @ 2012-09-27  9:08 UTC (permalink / raw)
  To: Rusty Russell
  Cc: dhowells, herbert, pjones, jwboyer, linux-crypto,
	linux-security-module, linux-kernel, keyrings



Hi Rusty,

Could you pull my tree?

David
---

The following changes since commit eeea3ac912207dcf759b95b2b4c36f96bce583bf:

  Merge tag 'fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc (2012-09-06 10:23:58 -0700)

are available in the git repository at:


  git://git.kernel.org/pub/scm/linux/kernel/git/dhowells/linux-modsign.git modsign-post-KS

for you to fetch changes up to 15765081423824e1ccc329264ae13f5ea87f3a85:

  MODSIGN: Sign modules during the build process (2012-09-26 10:11:06 +0100)

----------------------------------------------------------------
(from the branch description for modsign-post-KS local branch)

post Kernel-Summit module signing
----------------------------------------------------------------
David Howells (24):
      KEYS: Add payload preparsing opportunity prior to key instantiate or update
      MPILIB: Provide count_leading/trailing_zeros() based on arch functions
      KEYS: Document asymmetric key type
      KEYS: Implement asymmetric key type
      KEYS: Asymmetric key pluggable data parsers
      KEYS: Asymmetric public-key algorithm crypto key subtype
      KEYS: Provide signature verification with an asymmetric key
      MPILIB: Reinstate mpi_cmp[_ui]() and export for RSA signature verification
      RSA: Implement signature verification algorithm [PKCS#1 / RFC3447]
      RSA: Fix signature verification for shorter signatures
      X.509: Implement simple static OID registry
      X.509: Add utility functions to render OIDs as strings
      X.509: Add simple ASN.1 grammar compiler
      X.509: Add an ASN.1 decoder
      MPILIB: Provide a function to read raw data into an MPI
      X.509: Add a crypto key parser for binary (DER) X.509 certificates
      MODSIGN: Add FIPS policy
      MODSIGN: Provide gitignore and make clean rules for extra files
      MODSIGN: Provide Kconfig options
      MODSIGN: Automatically generate module signing keys if missing
      MODSIGN: Provide module signing public keys to the kernel
      MODSIGN: Implement module signature checking
      MODSIGN: Provide a script for generating a key ID from an X.509 cert
      MODSIGN: Sign modules during the build process

Rusty Russell (1):
      module: signature checking hook

 .gitignore                                |   14 +
 Documentation/crypto/asymmetric-keys.txt  |  312 ++++++
 Documentation/kernel-parameters.txt       |    6 +
 Documentation/security/keys.txt           |   50 +-
 Makefile                                  |    1 +
 crypto/Kconfig                            |    1 +
 crypto/Makefile                           |    1 +
 crypto/asymmetric_keys/.gitignore         |    1 +
 crypto/asymmetric_keys/Kconfig            |   38 +
 crypto/asymmetric_keys/Makefile           |   27 +
 crypto/asymmetric_keys/asymmetric_keys.h  |   15 +
 crypto/asymmetric_keys/asymmetric_type.c  |  274 +++++
 crypto/asymmetric_keys/public_key.c       |  108 ++
 crypto/asymmetric_keys/public_key.h       |   30 +
 crypto/asymmetric_keys/rsa.c              |  277 ++++++
 crypto/asymmetric_keys/signature.c        |   49 +
 crypto/asymmetric_keys/x509.asn1          |   60 ++
 crypto/asymmetric_keys/x509_cert_parser.c |  497 ++++++++++
 crypto/asymmetric_keys/x509_parser.h      |   36 +
 crypto/asymmetric_keys/x509_public_key.c  |  207 ++++
 crypto/asymmetric_keys/x509_rsakey.asn1   |    4 +
 fs/cifs/cifs_spnego.c                     |    6 +-
 fs/cifs/cifsacl.c                         |    8 +-
 include/asm-generic/bitops/count_zeros.h  |   57 ++
 include/crypto/public_key.h               |  108 ++
 include/keys/asymmetric-parser.h          |   37 +
 include/keys/asymmetric-subtype.h         |   55 +
 include/keys/asymmetric-type.h            |   25 +
 include/keys/user-type.h                  |    6 +-
 include/linux/asn1.h                      |   67 ++
 include/linux/asn1_ber_bytecode.h         |   87 ++
 include/linux/asn1_decoder.h              |   24 +
 include/linux/key-type.h                  |   35 +-
 include/linux/module.h                    |    8 +
 include/linux/mpi.h                       |    1 +
 include/linux/oid_registry.h              |   92 ++
 init/Kconfig                              |   68 ++
 kernel/Makefile                           |   57 ++
 kernel/modsign_pubkey.c                   |  112 +++
 kernel/module-internal.h                  |   15 +
 kernel/module.c                           |   97 +-
 kernel/module_signing.c                   |  243 +++++
 lib/.gitignore                            |    2 +-
 lib/Kconfig                               |    5 +
 lib/Makefile                              |   18 +
 lib/asn1_decoder.c                        |  477 +++++++++
 lib/build_OID_registry                    |  209 ++++
 lib/mpi/Makefile                          |    1 +
 lib/mpi/longlong.h                        |  138 +--
 lib/mpi/mpi-bit.c                         |    2 +-
 lib/mpi/mpi-cmp.c                         |   70 ++
 lib/mpi/mpi-pow.c                         |    4 +-
 lib/mpi/mpicoder.c                        |   55 +
 lib/oid_registry.c                        |  170 ++++
 net/ceph/crypto.c                         |    9 +-
 net/dns_resolver/dns_key.c                |    6 +-
 net/rxrpc/ar-key.c                        |   40 +-
 scripts/.gitignore                        |    1 +
 scripts/Makefile                          |    2 +
 scripts/Makefile.build                    |   11 +
 scripts/Makefile.modpost                  |   75 +-
 scripts/asn1_compiler.c                   | 1545 +++++++++++++++++++++++++++++
 scripts/sign-file                         |  115 +++
 scripts/x509keyid                         |  268 +++++
 security/keys/encrypted-keys/encrypted.c  |   16 +-
 security/keys/key.c                       |  114 ++-
 security/keys/keyctl.c                    |   18 +-
 security/keys/keyring.c                   |    6 +-
 security/keys/request_key_auth.c          |    8 +-
 security/keys/trusted.c                   |   16 +-
 security/keys/user_defined.c              |   14 +-
 71 files changed, 6387 insertions(+), 244 deletions(-)
 create mode 100644 Documentation/crypto/asymmetric-keys.txt
 create mode 100644 crypto/asymmetric_keys/.gitignore
 create mode 100644 crypto/asymmetric_keys/Kconfig
 create mode 100644 crypto/asymmetric_keys/Makefile
 create mode 100644 crypto/asymmetric_keys/asymmetric_keys.h
 create mode 100644 crypto/asymmetric_keys/asymmetric_type.c
 create mode 100644 crypto/asymmetric_keys/public_key.c
 create mode 100644 crypto/asymmetric_keys/public_key.h
 create mode 100644 crypto/asymmetric_keys/rsa.c
 create mode 100644 crypto/asymmetric_keys/signature.c
 create mode 100644 crypto/asymmetric_keys/x509.asn1
 create mode 100644 crypto/asymmetric_keys/x509_cert_parser.c
 create mode 100644 crypto/asymmetric_keys/x509_parser.h
 create mode 100644 crypto/asymmetric_keys/x509_public_key.c
 create mode 100644 crypto/asymmetric_keys/x509_rsakey.asn1
 create mode 100644 include/asm-generic/bitops/count_zeros.h
 create mode 100644 include/crypto/public_key.h
 create mode 100644 include/keys/asymmetric-parser.h
 create mode 100644 include/keys/asymmetric-subtype.h
 create mode 100644 include/keys/asymmetric-type.h
 create mode 100644 include/linux/asn1.h
 create mode 100644 include/linux/asn1_ber_bytecode.h
 create mode 100644 include/linux/asn1_decoder.h
 create mode 100644 include/linux/oid_registry.h
 create mode 100644 kernel/modsign_pubkey.c
 create mode 100644 kernel/module-internal.h
 create mode 100644 kernel/module_signing.c
 create mode 100644 lib/asn1_decoder.c
 create mode 100755 lib/build_OID_registry
 create mode 100644 lib/mpi/mpi-cmp.c
 create mode 100644 lib/oid_registry.c
 create mode 100644 scripts/asn1_compiler.c
 create mode 100644 scripts/sign-file
 create mode 100755 scripts/x509keyid

^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: [GIT PULL] Asymmetric keys and module signing
  2012-09-27  9:08   ` David Howells
@ 2012-09-28  5:55     ` Rusty Russell
  2012-09-28  5:58     ` [PATCH 1/2] modsign: don't use bashism in sh scripts Rusty Russell
                       ` (9 subsequent siblings)
  10 siblings, 0 replies; 47+ messages in thread
From: Rusty Russell @ 2012-09-28  5:55 UTC (permalink / raw)
  To: David Howells
  Cc: dhowells, herbert, pjones, jwboyer, linux-crypto,
	linux-security-module, linux-kernel, keyrings

David Howells <dhowells@redhat.com> writes:

> Hi Rusty,
>
> Could you pull my tree?
>
> David
> ---
>
> The following changes since commit eeea3ac912207dcf759b95b2b4c36f96bce583bf:
>
>   Merge tag 'fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc (2012-09-06 10:23:58 -0700)
>
> are available in the git repository at:
>
>
>   git://git.kernel.org/pub/scm/linux/kernel/git/dhowells/linux-modsign.git modsign-post-KS
>
> for you to fetch changes up to 15765081423824e1ccc329264ae13f5ea87f3a85:
>
>   MODSIGN: Sign modules during the build process (2012-09-26 10:11:06 +0100)

warning: (MODULE_SIG) selects ASYMMETRIC_KEY_TYPE which has unmet direct dependencies (CRYPTO && KEYS)

Ah, I see:

+	select CONFIG_KEYS
+	select CONFIG_CRYPTO

I fixed this commit, rather than go around again.

Thanks,
Rusty.

^ permalink raw reply	[flat|nested] 47+ messages in thread

* [PATCH 1/2] modsign: don't use bashism in sh scripts.
  2012-09-27  9:08   ` David Howells
  2012-09-28  5:55     ` Rusty Russell
@ 2012-09-28  5:58     ` Rusty Russell
  2012-09-28  5:59     ` [PATCH 2/2] modules: don't call eu-strip if it doesn't exist Rusty Russell
                       ` (8 subsequent siblings)
  10 siblings, 0 replies; 47+ messages in thread
From: Rusty Russell @ 2012-09-28  5:58 UTC (permalink / raw)
  To: David Howells
  Cc: dhowells, herbert, pjones, jwboyer, linux-crypto,
	linux-security-module, linux-kernel, keyrings

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>

diff --git a/scripts/sign-file b/scripts/sign-file
index 1a472bb..e58e34e 100644
--- a/scripts/sign-file
+++ b/scripts/sign-file
@@ -10,7 +10,7 @@ scripts=`dirname $0`
 CONFIG_MODULE_SIG_SHA512=y
 if [ -r .config ]
 then
-    source ./.config
+    . ./.config
 fi
 
 key="$1"

^ permalink raw reply related	[flat|nested] 47+ messages in thread

* [PATCH 2/2] modules: don't call eu-strip if it doesn't exist.
  2012-09-27  9:08   ` David Howells
  2012-09-28  5:55     ` Rusty Russell
  2012-09-28  5:58     ` [PATCH 1/2] modsign: don't use bashism in sh scripts Rusty Russell
@ 2012-09-28  5:59     ` Rusty Russell
  2012-09-28  6:05     ` [GIT PULL] Asymmetric keys and module signing Rusty Russell
                       ` (7 subsequent siblings)
  10 siblings, 0 replies; 47+ messages in thread
From: Rusty Russell @ 2012-09-28  5:59 UTC (permalink / raw)
  To: David Howells
  Cc: dhowells, herbert, pjones, jwboyer, linux-crypto,
	linux-security-module, linux-kernel, keyrings

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>

diff --git a/scripts/Makefile.modpost b/scripts/Makefile.modpost
index 90b1bb1..2a4d1a1 100644
--- a/scripts/Makefile.modpost
+++ b/scripts/Makefile.modpost
@@ -165,11 +165,13 @@ endif
 
 # We strip the module as best we can - note that using both strip and eu-strip
 # results in a smaller module than using either alone.
+EU_STRIP = $(shell which eu-strip || echo true)
+
 quiet_cmd_sign_ko_stripped_ko_unsigned = STRIP [M] $@
       cmd_sign_ko_stripped_ko_unsigned = \
 		cp $< $@ && \
 		strip -x -g $@ && \
-		eu-strip $@
+		$(EU_STRIP) $@
 
 ifeq ($(SIGN_MODULES),1)
 

^ permalink raw reply related	[flat|nested] 47+ messages in thread

* Re: [GIT PULL] Asymmetric keys and module signing
  2012-09-27  9:08   ` David Howells
                       ` (2 preceding siblings ...)
  2012-09-28  5:59     ` [PATCH 2/2] modules: don't call eu-strip if it doesn't exist Rusty Russell
@ 2012-09-28  6:05     ` Rusty Russell
  2012-09-28  8:09     ` David Howells
                       ` (6 subsequent siblings)
  10 siblings, 0 replies; 47+ messages in thread
From: Rusty Russell @ 2012-09-28  6:05 UTC (permalink / raw)
  To: David Howells
  Cc: dhowells, herbert, pjones, jwboyer, linux-crypto,
	linux-security-module, linux-kernel, keyrings

David Howells <dhowells@redhat.com> writes:

> Hi Rusty,
>
> Could you pull my tree?

And after those three fixes, I still get all fail:

[    3.361036] Request for unknown module key 'Magrathea: Glacier signing key: 6
e03943da0f3b015ba6ed7f5e0cac4fe48680994' err -11

rusty@rusty-x201:~/devel/kernel/linux (tmp-merge)$ grep '^CONFIG.*\(CRYPTO\|KEY\|MODULE\)' .config
CONFIG_MODULES_USE_ELF_REL=y
CONFIG_MODULES=y
CONFIG_MODULE_UNLOAD=y
CONFIG_MODULE_FORCE_UNLOAD=y
CONFIG_MODULE_SIG=y
CONFIG_MODULE_SIG_SHA512=y
CONFIG_NET_KEY=m
CONFIG_INPUT_KEYBOARD=y
CONFIG_KEYBOARD_ATKBD=y
CONFIG_HID_EZKEY=y
CONFIG_THINKPAD_ACPI_HOTKEY_POLL=y
CONFIG_KEYS=y
CONFIG_CRYPTO=y
CONFIG_CRYPTO_ALGAPI=y
CONFIG_CRYPTO_ALGAPI2=y
CONFIG_CRYPTO_AEAD2=y
CONFIG_CRYPTO_BLKCIPHER=m
CONFIG_CRYPTO_BLKCIPHER2=y
CONFIG_CRYPTO_HASH=y
CONFIG_CRYPTO_HASH2=y
CONFIG_CRYPTO_RNG=m
CONFIG_CRYPTO_RNG2=y
CONFIG_CRYPTO_PCOMP2=y
CONFIG_CRYPTO_MANAGER=m
CONFIG_CRYPTO_MANAGER2=y
CONFIG_CRYPTO_MANAGER_DISABLE_TESTS=y
CONFIG_CRYPTO_NULL=m
CONFIG_CRYPTO_WORKQUEUE=y
CONFIG_CRYPTO_CBC=m
CONFIG_CRYPTO_ECB=m
CONFIG_CRYPTO_PCBC=m
CONFIG_CRYPTO_HMAC=m
CONFIG_CRYPTO_CRC32C=y
CONFIG_CRYPTO_CRC32C_INTEL=m
CONFIG_CRYPTO_MD4=m
CONFIG_CRYPTO_MD5=y
CONFIG_CRYPTO_MICHAEL_MIC=m
CONFIG_CRYPTO_SHA1=m
CONFIG_CRYPTO_SHA256=m
CONFIG_CRYPTO_SHA512=y
CONFIG_CRYPTO_TGR192=m
CONFIG_CRYPTO_WP512=m
CONFIG_CRYPTO_AES=m
CONFIG_CRYPTO_ANUBIS=m
CONFIG_CRYPTO_ARC4=m
CONFIG_CRYPTO_BLOWFISH=m
CONFIG_CRYPTO_BLOWFISH_COMMON=m
CONFIG_CRYPTO_CAST5=m
CONFIG_CRYPTO_CAST6=m
CONFIG_CRYPTO_DES=m
CONFIG_CRYPTO_KHAZAD=m
CONFIG_CRYPTO_SERPENT=m
CONFIG_CRYPTO_TEA=m
CONFIG_CRYPTO_TWOFISH=m
CONFIG_CRYPTO_TWOFISH_COMMON=m
CONFIG_CRYPTO_DEFLATE=m
CONFIG_CRYPTO_ANSI_CPRNG=m
CONFIG_ASYMMETRIC_KEY_TYPE=y
CONFIG_ASYMMETRIC_PUBLIC_KEY_SUBTYPE=y
CONFIG_PUBLIC_KEY_ALGO_RSA=y

Clues welcome...
Rusty.

^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: [GIT PULL] Asymmetric keys and module signing
  2012-09-26  3:46 ` Rusty Russell
  2012-09-27  2:04   ` Mimi Zohar
@ 2012-09-28  6:27   ` Geert Uytterhoeven
  2012-09-28  8:00   ` David Howells
  2 siblings, 0 replies; 47+ messages in thread
From: Geert Uytterhoeven @ 2012-09-28  6:27 UTC (permalink / raw)
  To: Rusty Russell
  Cc: David Howells, herbert, pjones, jwboyer, linux-crypto,
	linux-security-module, linux-kernel, keyrings

On Wed, Sep 26, 2012 at 5:46 AM, Rusty Russell <rusty@rustcorp.com.au> wrote:
> You previously wrote:
>> You can't compare them that easily.  One has a FIPS-mode panic and the other
>> doesn't.  Do we want to panic if we reject an unsigned module in enforcing
>> mode when we're in FIPS mode?
>
> It's a line ball, but I think consistency wins.  Not a validly signed
> module => panic.

Just wondering, what's the advantage of doing panic over just
rejecting the module?
Panic is a DoS?

Gr{oetje,eeting}s,

                        Geert

--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
                                -- Linus Torvalds

^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: [GIT PULL] Asymmetric keys and module signing
  2012-09-27  2:04   ` Mimi Zohar
@ 2012-09-28  6:54     ` Rusty Russell
  0 siblings, 0 replies; 47+ messages in thread
From: Rusty Russell @ 2012-09-28  6:54 UTC (permalink / raw)
  To: Mimi Zohar
  Cc: David Howells, herbert, pjones, jwboyer, linux-crypto,
	linux-security-module, linux-kernel, keyrings

Mimi Zohar <zohar@linux.vnet.ibm.com> writes:

> On Wed, 2012-09-26 at 13:16 +0930, Rusty Russell wrote:
>> David Howells <dhowells@redhat.com> writes:
>> > The module signing patches provide:
>> >
>> >  - Some fixes to Rusty's patch.  Also an additional patch to extend the policy
>> >    handling for modules signed with an unknown key and to handle FIPS mode.
>> 
>> Ok, I merged some of this (after our previous accidentally-off-list
>> discussion).
>
> Rusty, have you pushed this branch out yet?
>
> thanks,
>
> Mimi

git://git.kernel.org/pub/scm/linux/kernel/git/rusty/linux.git modules-next

(That's *not* where linux-next currently pulls from)

Cheers,
Rusty.

^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: [GIT PULL] Asymmetric keys and module signing
  2012-09-26  3:46 ` Rusty Russell
  2012-09-27  2:04   ` Mimi Zohar
  2012-09-28  6:27   ` Geert Uytterhoeven
@ 2012-09-28  8:00   ` David Howells
  2 siblings, 0 replies; 47+ messages in thread
From: David Howells @ 2012-09-28  8:00 UTC (permalink / raw)
  To: Geert Uytterhoeven
  Cc: dhowells, Rusty Russell, herbert, pjones, jwboyer, linux-crypto,
	linux-security-module, linux-kernel, keyrings

Geert Uytterhoeven <geert@linux-m68k.org> wrote:

> Just wondering, what's the advantage of doing panic over just
> rejecting the module?
> Panic is a DoS?

FIPS mode is strange like that.

David

^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: [GIT PULL] Asymmetric keys and module signing
  2012-09-27  9:08   ` David Howells
                       ` (3 preceding siblings ...)
  2012-09-28  6:05     ` [GIT PULL] Asymmetric keys and module signing Rusty Russell
@ 2012-09-28  8:09     ` David Howells
  2012-09-29  6:53       ` Rusty Russell
                         ` (2 more replies)
  2012-09-28  8:10     ` [PATCH 1/2] modsign: don't use bashism in sh scripts David Howells
                       ` (5 subsequent siblings)
  10 siblings, 3 replies; 47+ messages in thread
From: David Howells @ 2012-09-28  8:09 UTC (permalink / raw)
  To: Rusty Russell
  Cc: dhowells, herbert, pjones, jwboyer, linux-crypto,
	linux-security-module, linux-kernel, keyrings


Rusty Russell <rusty@rustcorp.com.au> wrote:

> And after those three fixes, I still get all fail:
> 
> [    3.361036] Request for unknown module key 'Magrathea: Glacier signing key: 6
> e03943da0f3b015ba6ed7f5e0cac4fe48680994' err -11

Can you look back further in your kernel output, see if you can spot the bit
where it's trying to load the keys.  Look for things from modsign_pubkey.c:

	pr_notice("Loading module verification certificates\n");
	...
			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);

> CONFIG_CRYPTO_SHA1=m

Hmmm...  I suspect it's that.  We need a hash to verify the key's own
signature too - and if you're using the key my autogen patch created for you,
I think that would be SHA1, so that must be built in too.

If you can see your kernel log (assuming a panic doesn't prevent you), I
suspect you'll see something like:

	MODSIGN: Problem loading in-kernel X.509 certificate (-65)

which is -ENOPKG.

The answer would be to either select SHA1 in Kconfig or, if possible, to tell
openssl to use the same hash algorithm to sign the key as we're going to use
in signing the modules.

David

^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: [PATCH 1/2] modsign: don't use bashism in sh scripts.
  2012-09-27  9:08   ` David Howells
                       ` (4 preceding siblings ...)
  2012-09-28  8:09     ` David Howells
@ 2012-09-28  8:10     ` David Howells
  2012-10-02  2:24       ` Rusty Russell
  2012-09-28  8:11     ` [PATCH 2/2] modules: don't call eu-strip if it doesn't exist David Howells
                       ` (4 subsequent siblings)
  10 siblings, 1 reply; 47+ messages in thread
From: David Howells @ 2012-09-28  8:10 UTC (permalink / raw)
  To: Rusty Russell
  Cc: dhowells, herbert, pjones, jwboyer, linux-crypto,
	linux-security-module, linux-kernel, keyrings

Rusty Russell <rusty@rustcorp.com.au> wrote:

> -    source ./.config
> +    . ./.config

Does that make a difference?

^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: [PATCH 2/2] modules: don't call eu-strip if it doesn't exist.
  2012-09-27  9:08   ` David Howells
                       ` (5 preceding siblings ...)
  2012-09-28  8:10     ` [PATCH 1/2] modsign: don't use bashism in sh scripts David Howells
@ 2012-09-28  8:11     ` David Howells
  2012-09-28  8:13     ` [GIT PULL] Asymmetric keys and module signing David Howells
                       ` (3 subsequent siblings)
  10 siblings, 0 replies; 47+ messages in thread
From: David Howells @ 2012-09-28  8:11 UTC (permalink / raw)
  To: Rusty Russell
  Cc: dhowells, herbert, pjones, jwboyer, linux-crypto,
	linux-security-module, linux-kernel, keyrings

Rusty Russell <rusty@rustcorp.com.au> wrote:

> Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>

Acked-by: David Howells <dhowells@redhat.com>

^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: [GIT PULL] Asymmetric keys and module signing
  2012-09-27  9:08   ` David Howells
                       ` (6 preceding siblings ...)
  2012-09-28  8:11     ` [PATCH 2/2] modules: don't call eu-strip if it doesn't exist David Howells
@ 2012-09-28  8:13     ` David Howells
  2012-09-28  9:23     ` David Howells
                       ` (2 subsequent siblings)
  10 siblings, 0 replies; 47+ messages in thread
From: David Howells @ 2012-09-28  8:13 UTC (permalink / raw)
  To: Rusty Russell
  Cc: dhowells, herbert, pjones, jwboyer, linux-crypto,
	linux-security-module, linux-kernel, keyrings

Rusty Russell <rusty@rustcorp.com.au> wrote:

> warning: (MODULE_SIG) selects ASYMMETRIC_KEY_TYPE which has unmet direct dependencies (CRYPTO && KEYS)
> 
> Ah, I see:
> 
> +	select CONFIG_KEYS
> +	select CONFIG_CRYPTO
> 
> I fixed this commit, rather than go around again.

Thanks.

select is irritatingly broken in that regard.

David

^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: [GIT PULL] Asymmetric keys and module signing
  2012-09-27  9:08   ` David Howells
                       ` (7 preceding siblings ...)
  2012-09-28  8:13     ` [GIT PULL] Asymmetric keys and module signing David Howells
@ 2012-09-28  9:23     ` David Howells
  2012-09-28 10:31     ` David Howells
  2012-10-03 17:50     ` [patch] MODSIGN: Fix build error with strict typechecking David Rientjes
  10 siblings, 0 replies; 47+ messages in thread
From: David Howells @ 2012-09-28  9:23 UTC (permalink / raw)
  To: Rusty Russell
  Cc: dhowells, herbert, pjones, jwboyer, linux-crypto,
	linux-security-module, linux-kernel, keyrings


Rusty Russell <rusty@rustcorp.com.au> wrote:

> [    3.361036] Request for unknown module key 'Magrathea: Glacier signing key: 6
> e03943da0f3b015ba6ed7f5e0cac4fe48680994' err -11

Okay, it turns out that my attempts to remove SHA1 by editing it out of the
.config file were doomed to failure because a couple of IPv6 options I had
turned on selected it back on.

Having turned those off and then turned off SHA1, I see in the kernel log:

MODSIGN: Problem loading in-kernel X.509 certificate (-65)
MODSIGN: Loaded cert 'Red Hat Test Certificate: 3580cf35d76b3b667a40df66691cbcf87353b23c'

My kernel has an extra certificate (in the extra_certificates file) given to
me by Peter Jones in addition to the one it generates itself.

The first line is it failing to load the transient SHA1-hashed cert that was
generated by the kernel build (the Magrathean glacier signing key).

The second line is it managing to load the certificate that Peter gave me for
which it doesn't have the parent CA certificate available.  I've made the
assumption (which isn't necessarily warranted) that the signature in the cert,
if the cert is not self-signed, is generated using the CA private key, not by
the private key corresponding to this cert.

David

^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: [GIT PULL] Asymmetric keys and module signing
  2012-09-27  9:08   ` David Howells
                       ` (8 preceding siblings ...)
  2012-09-28  9:23     ` David Howells
@ 2012-09-28 10:31     ` David Howells
  2012-10-03 17:50     ` [patch] MODSIGN: Fix build error with strict typechecking David Rientjes
  10 siblings, 0 replies; 47+ messages in thread
From: David Howells @ 2012-09-28 10:31 UTC (permalink / raw)
  To: Rusty Russell
  Cc: dhowells, herbert, pjones, jwboyer, linux-crypto,
	linux-security-module, linux-kernel, keyrings


Hi Rusty,

I've pushed two additional patches.  The first makes the X.509 cert signature
use the same hash algorithm as the signatures on the modules - which should
fix the problem you're seeing, I think.  The second makes elements of the
names use UTF8 strings, just in case someone wants to use accented characters.

David
---

The following changes since commit 15765081423824e1ccc329264ae13f5ea87f3a85:

  MODSIGN: Sign modules during the build process (2012-09-26 10:11:06 +0100)

are available in the git repository at:

  git://git.kernel.org/pub/scm/linux/kernel/git/dhowells/linux-modsign.git modsign-post-KS

for you to fetch changes up to 9034de9a2c376229e2309eed7e2c871785b5890f:

  MODSIGN: Use utf8 strings in signer's name in autogenerated X.509 certs (2012-09-28 11:16:57 +0100)

----------------------------------------------------------------
(from the branch description for modsign-post-KS local branch)

post Kernel-Summit module signing
----------------------------------------------------------------
David Howells (2):
      MODSIGN: Use the same digest for the autogen key sig as for the module sig
      MODSIGN: Use utf8 strings in signer's name in autogenerated X.509 certs

 kernel/Makefile | 23 ++++++++++++++++++++++-
 1 file changed, 22 insertions(+), 1 deletion(-)

^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: [GIT PULL] Asymmetric keys and module signing
  2012-09-28  8:09     ` David Howells
@ 2012-09-29  6:53       ` Rusty Russell
  2012-09-29  7:13       ` David Howells
  2012-09-29  7:16       ` David Howells
  2 siblings, 0 replies; 47+ messages in thread
From: Rusty Russell @ 2012-09-29  6:53 UTC (permalink / raw)
  To: David Howells
  Cc: dhowells, herbert, pjones, jwboyer, linux-crypto,
	linux-security-module, linux-kernel, keyrings

David Howells <dhowells@redhat.com> writes:
> Rusty Russell <rusty@rustcorp.com.au> wrote:
>
>> And after those three fixes, I still get all fail:
>> 
>> [    3.361036] Request for unknown module key 'Magrathea: Glacier signing key: 6
>> e03943da0f3b015ba6ed7f5e0cac4fe48680994' err -11
>
> Can you look back further in your kernel output, see if you can spot the bit
> where it's trying to load the keys.  Look for things from modsign_pubkey.c:
>
> 	pr_notice("Loading module verification certificates\n");
> 	...
> 			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);
>
>> CONFIG_CRYPTO_SHA1=m
>
> Hmmm...  I suspect it's that.  We need a hash to verify the key's own
> signature too - and if you're using the key my autogen patch created for you,
> I think that would be SHA1, so that must be built in too.

Right, I chose SHA-512 because everyone knows it's 512 times more secure
than SHA-1.

I cherry-picked those two patches, and now I see:

[    2.808075] Loading module verification certificates
[    2.809331] X.509: Cert 6e03943da0f3b015ba6ed7f5e0cac4fe48680994 has expired
[    2.810500] MODSIGN: Problem loading in-kernel X.509 certificate (-127)

I noticed the Cert number didn't change with rebuilds: "distclean"
didn't remove some files:

$ git clean -f -f -x -d
Removing extra_certificates
Removing signing_key.priv
Removing signing_key.x509
Removing signing_key.x509.keyid
Removing signing_key.x509.signer
Removing x509.genkey

Removing them didn't fix it either, but at least I got a new certificate.

This is x86-32 BTW.  I've put the complete, built tree (minus .git dir)
up at http://ozlabs.org/~rusty/linux-for-dhowells.tar.xz

Here's how I run it:
kvm -nographic -m 256 -net user,restrict=off -net nic,model=virtio -drive file=$QEMUIMAGE,index=0,media=disk,if=virtio -drive file=$QEMUIMAGEB,index=1,media=disk,if=virtio -kernel arch/x86/boot/bzImage -append "ro root=/dev/vda1 console=ttyS0 $*"

Thanks,
Rusty.

^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: [GIT PULL] Asymmetric keys and module signing
  2012-09-28  8:09     ` David Howells
  2012-09-29  6:53       ` Rusty Russell
@ 2012-09-29  7:13       ` David Howells
  2012-10-01 20:41         ` Josh Boyer
  2012-09-29  7:16       ` David Howells
  2 siblings, 1 reply; 47+ messages in thread
From: David Howells @ 2012-09-29  7:13 UTC (permalink / raw)
  To: Rusty Russell
  Cc: dhowells, herbert, pjones, jwboyer, linux-crypto,
	linux-security-module, linux-kernel, keyrings

Rusty Russell <rusty@rustcorp.com.au> wrote:

> [    2.808075] Loading module verification certificates
> [    2.809331] X.509: Cert 6e03943da0f3b015ba6ed7f5e0cac4fe48680994 has expired
> [    2.810500] MODSIGN: Problem loading in-kernel X.509 certificate (-127)

Hmmm...  Other people have seen that.

Ahhhhh!

I wonder if the problem is that the certificate is valid for 100 years....
That might well cause an overflow on a 32-bit system.

Could you try changing the '36500' in kernel/Makefile to something shorter,
like 365?

David

^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: [GIT PULL] Asymmetric keys and module signing
  2012-09-28  8:09     ` David Howells
  2012-09-29  6:53       ` Rusty Russell
  2012-09-29  7:13       ` David Howells
@ 2012-09-29  7:16       ` David Howells
  2012-10-02  6:12         ` Rusty Russell
  2012-10-02 14:07         ` David Howells
  2 siblings, 2 replies; 47+ messages in thread
From: David Howells @ 2012-09-29  7:16 UTC (permalink / raw)
  To: Rusty Russell
  Cc: dhowells, herbert, pjones, jwboyer, linux-crypto,
	linux-security-module, linux-kernel, keyrings

Rusty Russell <rusty@rustcorp.com.au> wrote:

> I noticed the Cert number didn't change with rebuilds: "distclean"
> didn't remove some files:
> 
> $ git clean -f -f -x -d
> Removing extra_certificates
> Removing signing_key.priv
> Removing signing_key.x509
> Removing signing_key.x509.keyid
> Removing signing_key.x509.signer
> Removing x509.genkey

I'm not sure whether distclean should remove those, since they can be
externally supplied, or whether x509.genkey should have a Makefile dependency
on kernel/Makefile.

I lean towards 'yes' when I'm altering kernel/Makefile trying to get things
right, and 'no' when I'm doing a make distclean to change my config or
changing kernel/Makefile for some unrelated reason.

David

^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: [GIT PULL] Asymmetric keys and module signing
  2012-09-29  7:13       ` David Howells
@ 2012-10-01 20:41         ` Josh Boyer
  2012-10-02  3:28           ` Rusty Russell
  0 siblings, 1 reply; 47+ messages in thread
From: Josh Boyer @ 2012-10-01 20:41 UTC (permalink / raw)
  To: David Howells
  Cc: Rusty Russell, herbert, pjones, linux-crypto,
	linux-security-module, linux-kernel, keyrings

On Sat, Sep 29, 2012 at 08:13:25AM +0100, David Howells wrote:
> Rusty Russell <rusty@rustcorp.com.au> wrote:
> 
> > [    2.808075] Loading module verification certificates
> > [    2.809331] X.509: Cert 6e03943da0f3b015ba6ed7f5e0cac4fe48680994 has expired
> > [    2.810500] MODSIGN: Problem loading in-kernel X.509 certificate (-127)
> 
> Hmmm...  Other people have seen that.
> 
> Ahhhhh!
> 
> I wonder if the problem is that the certificate is valid for 100 years....
> That might well cause an overflow on a 32-bit system.

That does seem quite plausible.  The comparisons are done with time_t,
which boils down to 'long' and 100 years in seconds would overflow
LONG_MAX.

> Could you try changing the '36500' in kernel/Makefile to something shorter,
> like 365?

I tried two values today.  One close to LONG_MAX (24800 or ~68 years),
and 10 years (3650).  The former still seemed to overflow, but
specifying a 10yr lifetime appears to have worked.

josh

^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: [PATCH 1/2] modsign: don't use bashism in sh scripts.
  2012-09-28  8:10     ` [PATCH 1/2] modsign: don't use bashism in sh scripts David Howells
@ 2012-10-02  2:24       ` Rusty Russell
  0 siblings, 0 replies; 47+ messages in thread
From: Rusty Russell @ 2012-10-02  2:24 UTC (permalink / raw)
  To: David Howells
  Cc: dhowells, herbert, pjones, jwboyer, linux-crypto,
	linux-security-module, linux-kernel, keyrings

David Howells <dhowells@redhat.com> writes:

> Rusty Russell <rusty@rustcorp.com.au> wrote:
>
>> -    source ./.config
>> +    . ./.config
>
> Does that make a difference?

It does on Ubuntu, where /bin/sh => dash.  "source" is a bashism.

Cheers,
Rusty.

^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: [GIT PULL] Asymmetric keys and module signing
  2012-10-01 20:41         ` Josh Boyer
@ 2012-10-02  3:28           ` Rusty Russell
  2012-10-02 12:17             ` Josh Boyer
  0 siblings, 1 reply; 47+ messages in thread
From: Rusty Russell @ 2012-10-02  3:28 UTC (permalink / raw)
  To: Josh Boyer, David Howells
  Cc: herbert, pjones, linux-crypto, linux-security-module,
	linux-kernel, keyrings

Josh Boyer <jwboyer@redhat.com> writes:

> On Sat, Sep 29, 2012 at 08:13:25AM +0100, David Howells wrote:
>> Rusty Russell <rusty@rustcorp.com.au> wrote:
>> 
>> > [    2.808075] Loading module verification certificates
>> > [    2.809331] X.509: Cert 6e03943da0f3b015ba6ed7f5e0cac4fe48680994 has expired
>> > [    2.810500] MODSIGN: Problem loading in-kernel X.509 certificate (-127)
>> 
>> Hmmm...  Other people have seen that.
>> 
>> Ahhhhh!
>> 
>> I wonder if the problem is that the certificate is valid for 100 years....
>> That might well cause an overflow on a 32-bit system.
>
> That does seem quite plausible.  The comparisons are done with time_t,
> which boils down to 'long' and 100 years in seconds would overflow
> LONG_MAX.
>
>> Could you try changing the '36500' in kernel/Makefile to something shorter,
>> like 365?
>
> I tried two values today.  One close to LONG_MAX (24800 or ~68 years),
> and 10 years (3650).  The former still seemed to overflow, but
> specifying a 10yr lifetime appears to have worked.

That's because the timestamp is absolute, right?  Indeed, that seems to
be the limit here.

Here's my solution (tested, and it breaks if you change 2147300000 to
2147600000 as expected):

>From 2a4b91c2c29739191c6f7db9abee9296ae505c39 Mon Sep 17 00:00:00 2001
From: Rusty Russell <rusty@rustcorp.com.au>
Date: Tue, 2 Oct 2012 12:55:06 +0930
Subject: [PATCH] MODSIGN: fix expiry of auto-generated certificates on 32-bit
 systems

100-year certificates make time_t wrap, resulting in:

[    2.835272] X.509: Cert a94f6776f3f5483b0764011d1fcc6c0298362e63 has expired
[    2.836346] MODSIGN: Problem loading in-kernel X.509 certificate (-127)

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>

diff --git a/kernel/Makefile b/kernel/Makefile
index e951adf..86336c9 100644
--- a/kernel/Makefile
+++ b/kernel/Makefile
@@ -168,6 +168,13 @@ endif
 ifeq ($(sign_key_with_hash),)
 $(error Could not determine digest type to use from kernel config)
 endif
+ifeq ($(CONFIG_64BIT),y)
+# 100 years is beyond my best-before date, anyway.
+end_of_time_days=36500
+else
+# Until 32-bit time_t wraps, with some slack.
+end_of_time_days=$(shell expr \( 2147300000 - `date -u +%s` \) / 86400 )
+endif
 
 signing_key.priv signing_key.x509: x509.genkey
 	@echo "###"
@@ -180,7 +187,8 @@ signing_key.priv signing_key.x509: x509.genkey
 	@echo "###"
 	@echo "###     rngd -r /dev/hwrandom"
 	@echo "###"
-	openssl req -new -nodes -utf8 $(sign_key_with_hash) -days 36500 -batch \
+	openssl req -new -nodes -utf8 $(sign_key_with_hash) \
+		-days $(end_of_time_days) -batch \
 		-x509 -config x509.genkey \
 		-outform DER -out signing_key.x509 \
 		-keyout signing_key.priv

^ permalink raw reply related	[flat|nested] 47+ messages in thread

* Re: [GIT PULL] Asymmetric keys and module signing
  2012-09-29  7:16       ` David Howells
@ 2012-10-02  6:12         ` Rusty Russell
  2012-10-02 14:07         ` David Howells
  1 sibling, 0 replies; 47+ messages in thread
From: Rusty Russell @ 2012-10-02  6:12 UTC (permalink / raw)
  To: David Howells
  Cc: dhowells, herbert, pjones, jwboyer, linux-crypto,
	linux-security-module, linux-kernel, keyrings

David Howells <dhowells@redhat.com> writes:

> Rusty Russell <rusty@rustcorp.com.au> wrote:
>
>> I noticed the Cert number didn't change with rebuilds: "distclean"
>> didn't remove some files:
>> 
>> $ git clean -f -f -x -d
>> Removing extra_certificates
>> Removing signing_key.priv
>> Removing signing_key.x509
>> Removing signing_key.x509.keyid
>> Removing signing_key.x509.signer
>> Removing x509.genkey
>
> I'm not sure whether distclean should remove those, since they can be
> externally supplied, or whether x509.genkey should have a Makefile dependency
> on kernel/Makefile.
>
> I lean towards 'yes' when I'm altering kernel/Makefile trying to get things
> right, and 'no' when I'm doing a make distclean to change my config or
> changing kernel/Makefile for some unrelated reason.

Right.  I think we need to use different names for generated vs supplied
files, then, because 'distclean' really must delete generated files.

But it turns out you do try to clean these files, it just doesn't work.
See below.  I've applied this, as well, to my tree:

        git://git.kernel.org/pub/scm/linux/kernel/git/rusty/linux.git modules-next

BTW, you missed a Signed-off-by: on your "MODSIGN: Use the same digest
for the autogen key sig as for the module sig" patch.  Please update.

Cheers,
Rusty.

>From 8921e2ede91f93dcdbd08fa6613f8458de5f8afe Mon Sep 17 00:00:00 2001
From: Rusty Russell <rusty@rustcorp.com.au>
Date: Tue, 2 Oct 2012 14:35:24 +0930
Subject: [PATCH] MODSIGN: Make mrproper should remove generated files.

It doesn't, because the clean targets don't include kernel/Makefile, and
because two files were missing from the list.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>

diff --git a/Makefile b/Makefile
index 1c88ec3..e70ebfe 100644
--- a/Makefile
+++ b/Makefile
@@ -995,7 +995,10 @@ MRPROPER_DIRS  += include/config usr/include include/generated          \
                   arch/*/include/generated
 MRPROPER_FILES += .config .config.old .version .old_version             \
                   include/linux/version.h                               \
-		  Module.symvers tags TAGS cscope* GPATH GTAGS GRTAGS GSYMS
+		  Module.symvers tags TAGS cscope* GPATH GTAGS GRTAGS GSYMS \
+		  signing_key.priv signing_key.x509 x509.genkey		\
+		  extra_certificates signing_key.x509.keyid		\
+		  signing_key.x509.signer
 
 # clean - Delete most, but leave enough to build external modules
 #
diff --git a/kernel/Makefile b/kernel/Makefile
index 86336c9..bb94783 100644
--- a/kernel/Makefile
+++ b/kernel/Makefile
@@ -216,4 +216,3 @@ x509.genkey:
 	@echo >>x509.genkey "subjectKeyIdentifier=hash"
 	@echo >>x509.genkey "authorityKeyIdentifier=keyid"
 endif
-CLEAN_FILES += signing_key.priv signing_key.x509 x509.genkey extra_certificates



^ permalink raw reply related	[flat|nested] 47+ messages in thread

* Re: [GIT PULL] Asymmetric keys and module signing
  2012-10-02  3:28           ` Rusty Russell
@ 2012-10-02 12:17             ` Josh Boyer
  0 siblings, 0 replies; 47+ messages in thread
From: Josh Boyer @ 2012-10-02 12:17 UTC (permalink / raw)
  To: Rusty Russell
  Cc: David Howells, herbert, pjones, linux-crypto,
	linux-security-module, linux-kernel, keyrings

On Tue, Oct 02, 2012 at 12:58:03PM +0930, Rusty Russell wrote:
> Josh Boyer <jwboyer@redhat.com> writes:
> 
> > On Sat, Sep 29, 2012 at 08:13:25AM +0100, David Howells wrote:
> >> Rusty Russell <rusty@rustcorp.com.au> wrote:
> >> 
> >> > [    2.808075] Loading module verification certificates
> >> > [    2.809331] X.509: Cert 6e03943da0f3b015ba6ed7f5e0cac4fe48680994 has expired
> >> > [    2.810500] MODSIGN: Problem loading in-kernel X.509 certificate (-127)
> >> 
> >> Hmmm...  Other people have seen that.
> >> 
> >> Ahhhhh!
> >> 
> >> I wonder if the problem is that the certificate is valid for 100 years....
> >> That might well cause an overflow on a 32-bit system.
> >
> > That does seem quite plausible.  The comparisons are done with time_t,
> > which boils down to 'long' and 100 years in seconds would overflow
> > LONG_MAX.
> >
> >> Could you try changing the '36500' in kernel/Makefile to something shorter,
> >> like 365?
> >
> > I tried two values today.  One close to LONG_MAX (24800 or ~68 years),
> > and 10 years (3650).  The former still seemed to overflow, but
> > specifying a 10yr lifetime appears to have worked.
> 
> That's because the timestamp is absolute, right?  Indeed, that seems to
> be the limit here.

Yep.

> Here's my solution (tested, and it breaks if you change 2147300000 to
> 2147600000 as expected):
> 
> From 2a4b91c2c29739191c6f7db9abee9296ae505c39 Mon Sep 17 00:00:00 2001
> From: Rusty Russell <rusty@rustcorp.com.au>
> Date: Tue, 2 Oct 2012 12:55:06 +0930
> Subject: [PATCH] MODSIGN: fix expiry of auto-generated certificates on 32-bit
>  systems
> 
> 100-year certificates make time_t wrap, resulting in:
> 
> [    2.835272] X.509: Cert a94f6776f3f5483b0764011d1fcc6c0298362e63 has expired
> [    2.836346] MODSIGN: Problem loading in-kernel X.509 certificate (-127)
> 
> Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
> 
> diff --git a/kernel/Makefile b/kernel/Makefile
> index e951adf..86336c9 100644
> --- a/kernel/Makefile
> +++ b/kernel/Makefile
> @@ -168,6 +168,13 @@ endif
>  ifeq ($(sign_key_with_hash),)
>  $(error Could not determine digest type to use from kernel config)
>  endif
> +ifeq ($(CONFIG_64BIT),y)
> +# 100 years is beyond my best-before date, anyway.
> +end_of_time_days=36500
> +else
> +# Until 32-bit time_t wraps, with some slack.
> +end_of_time_days=$(shell expr \( 2147300000 - `date -u +%s` \) / 86400 )
> +endif
>  
>  signing_key.priv signing_key.x509: x509.genkey
>  	@echo "###"
> @@ -180,7 +187,8 @@ signing_key.priv signing_key.x509: x509.genkey
>  	@echo "###"
>  	@echo "###     rngd -r /dev/hwrandom"
>  	@echo "###"
> -	openssl req -new -nodes -utf8 $(sign_key_with_hash) -days 36500 -batch \
> +	openssl req -new -nodes -utf8 $(sign_key_with_hash) \
> +		-days $(end_of_time_days) -batch \
>  		-x509 -config x509.genkey \
>  		-outform DER -out signing_key.x509 \
>  		-keyout signing_key.priv

That would likely work just fine.  David actually has another patch that
makes 100yrs still work on 32-bit as well that I've tested locally in a
KVM instance.  He was waiting on positive testing confirmation from me
so hopefully he'll send it soon.

josh

^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: [GIT PULL] Asymmetric keys and module signing
  2012-09-29  7:16       ` David Howells
  2012-10-02  6:12         ` Rusty Russell
@ 2012-10-02 14:07         ` David Howells
  2012-10-03 23:22           ` Rusty Russell
  1 sibling, 1 reply; 47+ messages in thread
From: David Howells @ 2012-10-02 14:07 UTC (permalink / raw)
  To: Rusty Russell
  Cc: dhowells, herbert, pjones, jwboyer, linux-crypto,
	linux-security-module, linux-kernel, keyrings

Rusty Russell <rusty@rustcorp.com.au> wrote:

> Right.  I think we need to use different names for generated vs supplied
> files

The problem with supplied files is people who do allyesconfig, allmodconfig
and randconfig just to test things finding that their builds break.  The
kernel build magic is not really set up to handle external files like this.  I
suppose make logic can be used to conditionally include stuff that might not
exist.

> BTW, you missed a Signed-off-by: on your "MODSIGN: Use the same digest
> for the autogen key sig as for the module sig" patch.  Please update.

Done.

I've also added a patch to convert the system clock to a struct tm and to
produce a struct tm within the ASN.1 decode and then compare those rather than
time_t values as a way to deal with the validity time overflow problem.  We
may have to be able to handle certificates that we haven't generated that
stretch beyond 2038 (I wonder if we might find such in the UEFI key database
for example.

Another way of dealing with this could be to make mktime() within the kernel
produce a u64 rather than an unsigned long, and then compare those.

David

^ permalink raw reply	[flat|nested] 47+ messages in thread

* [patch] MODSIGN: Fix build error with strict typechecking
  2012-09-27  9:08   ` David Howells
                       ` (9 preceding siblings ...)
  2012-09-28 10:31     ` David Howells
@ 2012-10-03 17:50     ` David Rientjes
  10 siblings, 0 replies; 47+ messages in thread
From: David Rientjes @ 2012-10-03 17:50 UTC (permalink / raw)
  To: David Howells, Rusty Russell
  Cc: herbert, pjones, jwboyer, linux-crypto, linux-security-module,
	linux-kernel, keyrings

"MODSIGN: Provide module signing public keys to the kernel" causes a build 
error when CONFIG_UIDGID_STRICT_TYPE_CHECKS is enabled:

kernel/modsign_pubkey.c: In function 'module_verify_init':
kernel/modsign_pubkey.c:47: error: incompatible type for argument 3 of 'key_alloc'
include/linux/key.h:195: note: expected 'kuid_t' but argument is of type 'int'
kernel/modsign_pubkey.c:47: error: incompatible type for argument 4 of 'key_alloc'
include/linux/key.h:195: note: expected 'kgid_t' but argument is of type 'int'

Cast the parameters accordingly.

Signed-off-by: David Rientjes <rientjes@google.com>
---
 kernel/modsign_pubkey.c |    3 ++-
 1 files changed, 2 insertions(+), 1 deletions(-)

diff --git a/kernel/modsign_pubkey.c b/kernel/modsign_pubkey.c
--- a/kernel/modsign_pubkey.c
+++ b/kernel/modsign_pubkey.c
@@ -41,7 +41,8 @@ static __init int module_verify_init(void)
 	pr_notice("Initialise module verification\n");
 
 	modsign_keyring = key_alloc(&key_type_keyring, ".module_sign",
-				    0, 0, current_cred(),
+				    KUIDT_INIT(0), KGIDT_INIT(0),
+				    current_cred(),
 				    (KEY_POS_ALL & ~KEY_POS_SETATTR) |
 				    KEY_USR_VIEW | KEY_USR_READ,
 				    KEY_ALLOC_NOT_IN_QUOTA);

^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: [GIT PULL] Asymmetric keys and module signing
  2012-10-02 14:07         ` David Howells
@ 2012-10-03 23:22           ` Rusty Russell
  2012-10-09 10:55             ` Kasatkin, Dmitry
  0 siblings, 1 reply; 47+ messages in thread
From: Rusty Russell @ 2012-10-03 23:22 UTC (permalink / raw)
  To: David Howells
  Cc: dhowells, herbert, pjones, jwboyer, linux-crypto,
	linux-security-module, linux-kernel, keyrings

David Howells <dhowells@redhat.com> writes:

> Rusty Russell <rusty@rustcorp.com.au> wrote:
>
>> Right.  I think we need to use different names for generated vs supplied
>> files
>
> The problem with supplied files is people who do allyesconfig, allmodconfig
> and randconfig just to test things finding that their builds break.  The
> kernel build magic is not really set up to handle external files like this.  I
> suppose make logic can be used to conditionally include stuff that might not
> exist.
>
>> BTW, you missed a Signed-off-by: on your "MODSIGN: Use the same digest
>> for the autogen key sig as for the module sig" patch.  Please update.
>
> Done.
>
> I've also added a patch to convert the system clock to a struct tm and to
> produce a struct tm within the ASN.1 decode and then compare those rather than
> time_t values as a way to deal with the validity time overflow problem.  We
> may have to be able to handle certificates that we haven't generated that
> stretch beyond 2038 (I wonder if we might find such in the UEFI key database
> for example.

OK, cherry-picked to replace my hack.

It's in linux-next, and I will push in the next two days.

Thanks,
Rusty.

^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: [GIT PULL] Asymmetric keys and module signing
  2012-10-03 23:22           ` Rusty Russell
@ 2012-10-09 10:55             ` Kasatkin, Dmitry
  2012-10-10  9:37               ` Rusty Russell
  0 siblings, 1 reply; 47+ messages in thread
From: Kasatkin, Dmitry @ 2012-10-09 10:55 UTC (permalink / raw)
  To: Rusty Russell
  Cc: David Howells, herbert, pjones, jwboyer, linux-crypto,
	linux-security-module, linux-kernel, keyrings

On Thu, Oct 4, 2012 at 2:22 AM, Rusty Russell <rusty@rustcorp.com.au> wrote:
> David Howells <dhowells@redhat.com> writes:
>
>> Rusty Russell <rusty@rustcorp.com.au> wrote:
>>
>>> Right.  I think we need to use different names for generated vs supplied
>>> files
>>
>> The problem with supplied files is people who do allyesconfig, allmodconfig
>> and randconfig just to test things finding that their builds break.  The
>> kernel build magic is not really set up to handle external files like this.  I
>> suppose make logic can be used to conditionally include stuff that might not
>> exist.
>>
>>> BTW, you missed a Signed-off-by: on your "MODSIGN: Use the same digest
>>> for the autogen key sig as for the module sig" patch.  Please update.
>>
>> Done.
>>
>> I've also added a patch to convert the system clock to a struct tm and to
>> produce a struct tm within the ASN.1 decode and then compare those rather than
>> time_t values as a way to deal with the validity time overflow problem.  We
>> may have to be able to handle certificates that we haven't generated that
>> stretch beyond 2038 (I wonder if we might find such in the UEFI key database
>> for example.
>
> OK, cherry-picked to replace my hack.
>
> It's in linux-next, and I will push in the next two days.
>


http://git.kernel.org/?p=linux/kernel/git/rusty/linux.git;a=commit;h=a15e196c5543d1d2d7f0cd70e62351aeb1f8b871

It breaks bisect..

  CC      kernel/module_signing.o
kernel/module_signing.c: In function ‘mod_verify_sig’:
kernel/module_signing.c:21:10: error: ‘ENOKEY’ undeclared (first use
in this function)
kernel/module_signing.c:21:10: note: each undeclared identifier is
reported only once for each function it appears in
kernel/module_signing.c:22:1: warning: control reaches end of non-void
function [-Wreturn-type]
make[1]: *** [kernel/module_signing.o] Error 1
make: *** [kernel] Error 2
make: *** Waiting for unfinished jobs....

> Thanks,
> Rusty.
> --
> To unsubscribe from this list: send the line "unsubscribe linux-crypto" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: [GIT PULL] Asymmetric keys and module signing
  2012-10-09 10:55             ` Kasatkin, Dmitry
@ 2012-10-10  9:37               ` Rusty Russell
  0 siblings, 0 replies; 47+ messages in thread
From: Rusty Russell @ 2012-10-10  9:37 UTC (permalink / raw)
  To: Kasatkin, Dmitry
  Cc: David Howells, herbert, pjones, jwboyer, linux-crypto,
	linux-security-module, linux-kernel, keyrings

"Kasatkin, Dmitry" <dmitry.kasatkin@intel.com> writes:
> http://git.kernel.org/?p=linux/kernel/git/rusty/linux.git;a=commit;h=a15e196c5543d1d2d7f0cd70e62351aeb1f8b871
>
> It breaks bisect..
>
>   CC      kernel/module_signing.o
> kernel/module_signing.c: In function ‘mod_verify_sig’:
> kernel/module_signing.c:21:10: error: ‘ENOKEY’ undeclared (first use
> in this function)
> kernel/module_signing.c:21:10: note: each undeclared identifier is
> reported only once for each function it appears in
> kernel/module_signing.c:22:1: warning: control reaches end of non-void
> function [-Wreturn-type]
> make[1]: *** [kernel/module_signing.o] Error 1
> make: *** [kernel] Error 2
> make: *** Waiting for unfinished jobs....

Ah, my mistake; missing #include.  I've fixed this which unfortunately
meant a rebase.

Thanks,
Rusty.

^ permalink raw reply	[flat|nested] 47+ messages in thread

* Re: Wrong system clock vs X.509 date specifiers
  2012-09-25 15:30   ` Alan Cox
@ 2013-03-14 10:48     ` David Woodhouse
  2013-03-14 12:24       ` [PATCH] Fix x509_key_preparse() not to reject keys outside their validity time range David Woodhouse
  0 siblings, 1 reply; 47+ messages in thread
From: David Woodhouse @ 2013-03-14 10:48 UTC (permalink / raw)
  To: Alan Cox
  Cc: David Howells, rusty, herbert, pjones, jwboyer, linux-crypto,
	linux-security-module, linux-kernel, keyrings

[-- Attachment #1: Type: text/plain, Size: 2323 bytes --]

On Tue, 2012-09-25 at 16:30 +0100, Alan Cox wrote:
> On Tue, 25 Sep 2012 16:09:54 +0100
> David Howells <dhowells@redhat.com> wrote:
> 
> > 
> > The X.509 certificate has a pair of times in it that delineate the valid
> > period of the cert, and I'm checking that the system clock is within the
> > bounds they define before permitting you to use the cert.  I've been setting
> > the expiry date to be 100 years in the future - by which time hopefully I
> > won't have to worry about it - but occasionally clock skew means a freshly
> > built kernel won't boot because the machine trying to boot doesn't think that
> > the start time has been reached yet.
> > 
> > Do we actually want to do this, however?  Or should we just ignore the times?
> > Or just the start time?
> 
> Generate a certificate that is valid from a few minutes before the
> wallclock time. It's a certificate policy question not a kernel hackery
> one.

That's not good enough. I frequently encounter laptops with hardware
clocks which are *way* slower than that. I see lots of machines booting
up thinking it's 1970, 1900 iirc for some Macs, and more recently 2001.

This causes the kernel to refuse to load the certificate:
[    3.116185] Loading module verification certificates
[    3.117414] X.509: Cert e1a74f2317b1f38848278d07926ed16c2675393e is not yet valid
[    3.118639] MODSIGN: Problem loading in-kernel X.509 certificate (-129)

...and then spew error messages every time a module is loaded. 

For the kernel, it makes *absolutely* no sense to be checking the start
date of the certificate. We do not have a usage model where someone says
"hey, here's this kernel module but I don't want you to be able to use
it until tomorrow so I've post-dated its signature".

If we *ever* try to load a signed kernel module when the certificate is
"not yet valid", it's because the clock is wrong. It's as simple as
that.

And even if we *did* want to support that stupid "load this tomorrow"
use case, it's broken. You couldn't boot today, then load the offending
module tomorrow. You'd have to *reboot* tomorrow, because the kernel
refused to load the damn cert into its store at all.

For the specific case of module signing, we should probably just disable
the date checks completely.

-- 
dwmw2

[-- Attachment #2: smime.p7s --]
[-- Type: application/x-pkcs7-signature, Size: 6171 bytes --]

^ permalink raw reply	[flat|nested] 47+ messages in thread

* [PATCH] Fix x509_key_preparse() not to reject keys outside their validity time range
  2013-03-14 10:48     ` David Woodhouse
@ 2013-03-14 12:24       ` David Woodhouse
  2013-03-19 21:06         ` Alexander Holler
  0 siblings, 1 reply; 47+ messages in thread
From: David Woodhouse @ 2013-03-14 12:24 UTC (permalink / raw)
  To: Alan Cox
  Cc: David Howells, rusty, herbert, pjones, jwboyer, linux-crypto,
	linux-security-module, linux-kernel, keyrings

[-- Attachment #1: Type: text/plain, Size: 2543 bytes --]

The x509_key_preparse() function will refuse to even *parse* a
certificate when the system clock happens to be set to a time before the
ValidFrom or after the ValidTo date.

This is wrong. If date checks are to be done, they need to be done at
the time the cert is *used*. It should be perfectly possible to load a
cert which is post-dated, and can only be used for validation at some
point in the future. The key in question should immediately start
working at its ValidFrom date, and stop again at its ValidTo date. It
should be allowed to *exist* in the kernel both before and after those
times.

On systems where the hardware clock is inaccurate (a common occurrence
and one which doesn't even get noticed when you use NTP or something
else to fix it during the boot sequence), this was preventing the module
signing cert from being loaded during boot. When the clock got fixed
later on in he boot sequence, things *should* have started working. But
they didn't...

Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
---

Arguably, for the specific case of module signing we shouldn't bother
checking for a current time before the ValidFrom date *at all*. It's
*always* going to be a screwed up system clock, because we don't have a
usage model of post-dating module signatures. We should simply document
that the date is *not* checked for module signing, and have done with
it. But that's a separate issue.

diff --git a/crypto/asymmetric_keys/x509_public_key.c b/crypto/asymmetric_keys/x509_public_key.c
index 06007f0..326dc80 100644
--- a/crypto/asymmetric_keys/x509_public_key.c
+++ b/crypto/asymmetric_keys/x509_public_key.c
@@ -154,8 +154,6 @@ static int x509_key_preparse(struct key_preparsed_payload *prep)
 		     (now.tm_sec < cert->valid_from.tm_sec
 		      ))))))))))) {
 		pr_warn("Cert %s is not yet valid\n", cert->fingerprint);
-		ret = -EKEYREJECTED;
-		goto error_free_cert;
 	}
 	if (now.tm_year > cert->valid_to.tm_year ||
 	    (now.tm_year == cert->valid_to.tm_year &&
@@ -170,8 +168,6 @@ static int x509_key_preparse(struct key_preparsed_payload *prep)
 		     (now.tm_sec > cert->valid_to.tm_sec
 		      ))))))))))) {
 		pr_warn("Cert %s has expired\n", cert->fingerprint);
-		ret = -EKEYEXPIRED;
-		goto error_free_cert;
 	}
 
 	cert->pub->algo = x509_public_key_algorithms[cert->pkey_algo];




-- 
David Woodhouse                            Open Source Technology Centre
David.Woodhouse@intel.com                              Intel Corporation

[-- Attachment #2: smime.p7s --]
[-- Type: application/x-pkcs7-signature, Size: 6171 bytes --]

^ permalink raw reply related	[flat|nested] 47+ messages in thread

* Re: [PATCH] Fix x509_key_preparse() not to reject keys outside their validity time range
  2013-03-14 12:24       ` [PATCH] Fix x509_key_preparse() not to reject keys outside their validity time range David Woodhouse
@ 2013-03-19 21:06         ` Alexander Holler
  0 siblings, 0 replies; 47+ messages in thread
From: Alexander Holler @ 2013-03-19 21:06 UTC (permalink / raw)
  To: David Woodhouse
  Cc: Alan Cox, David Howells, rusty, herbert, pjones, jwboyer,
	linux-crypto, linux-security-module, linux-kernel, keyrings

Am 14.03.2013 13:24, schrieb David Woodhouse:
> The x509_key_preparse() function will refuse to even *parse* a
> certificate when the system clock happens to be set to a time before the
> ValidFrom or after the ValidTo date.
>
> This is wrong. If date checks are to be done, they need to be done at
> the time the cert is *used*. It should be perfectly possible to load a
> cert which is post-dated, and can only be used for validation at some
> point in the future. The key in question should immediately start
> working at its ValidFrom date, and stop again at its ValidTo date. It
> should be allowed to *exist* in the kernel both before and after those
> times.
>
> On systems where the hardware clock is inaccurate (a common occurrence
> and one which doesn't even get noticed when you use NTP or something
> else to fix it during the boot sequence), this was preventing the module
> signing cert from being loaded during boot. When the clock got fixed
> later on in he boot sequence, things *should* have started working. But
> they didn't...
>
> Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
> ---
>
> Arguably, for the specific case of module signing we shouldn't bother
> checking for a current time before the ValidFrom date *at all*. It's
> *always* going to be a screwed up system clock, because we don't have a
> usage model of post-dating module signatures. We should simply document
> that the date is *not* checked for module signing, and have done with
> it. But that's a separate issue.
>
> diff --git a/crypto/asymmetric_keys/x509_public_key.c b/crypto/asymmetric_keys/x509_public_key.c
> index 06007f0..326dc80 100644
> --- a/crypto/asymmetric_keys/x509_public_key.c
> +++ b/crypto/asymmetric_keys/x509_public_key.c
> @@ -154,8 +154,6 @@ static int x509_key_preparse(struct key_preparsed_payload *prep)
>   		     (now.tm_sec < cert->valid_from.tm_sec
>   		      ))))))))))) {
>   		pr_warn("Cert %s is not yet valid\n", cert->fingerprint);
> -		ret = -EKEYREJECTED;
> -		goto error_free_cert;
>   	}
>   	if (now.tm_year > cert->valid_to.tm_year ||
>   	    (now.tm_year == cert->valid_to.tm_year &&
> @@ -170,8 +168,6 @@ static int x509_key_preparse(struct key_preparsed_payload *prep)
>   		     (now.tm_sec > cert->valid_to.tm_sec
>   		      ))))))))))) {
>   		pr_warn("Cert %s has expired\n", cert->fingerprint);
> -		ret = -EKEYEXPIRED;
> -		goto error_free_cert;
>   	}
>
>   	cert->pub->algo = x509_public_key_algorithms[cert->pkey_algo];

Why not remove the check and warning there too?

Regards,

Alexander


^ permalink raw reply	[flat|nested] 47+ messages in thread

end of thread, other threads:[~2013-03-19 21:07 UTC | newest]

Thread overview: 47+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-09-25  0:07 [GIT PULL] Asymmetric keys and module signing David Howells
2012-09-25  0:11 ` David Howells
2012-09-25 15:09 ` Wrong system clock vs X.509 date specifiers David Howells
2012-09-25 15:30   ` Alan Cox
2013-03-14 10:48     ` David Woodhouse
2013-03-14 12:24       ` [PATCH] Fix x509_key_preparse() not to reject keys outside their validity time range David Woodhouse
2013-03-19 21:06         ` Alexander Holler
2012-09-25 15:35   ` Wrong system clock vs X.509 date specifiers David Howells
2012-09-25 15:43     ` Paolo Bonzini
2012-09-25 16:00     ` Alan Cox
2012-09-25 16:02     ` Tomas Mraz
2012-09-25 17:31     ` David Howells
2012-09-25 18:39       ` Tomas Mraz
2012-09-25 21:57     ` David Howells
2012-09-25 15:44 ` [GIT PULL] Asymmetric keys and module signing Kasatkin, Dmitry
2012-09-25 16:15 ` David Howells
2012-09-26  3:46 ` Rusty Russell
2012-09-27  2:04   ` Mimi Zohar
2012-09-28  6:54     ` Rusty Russell
2012-09-28  6:27   ` Geert Uytterhoeven
2012-09-28  8:00   ` David Howells
2012-09-26  9:09 ` David Howells
2012-09-27  0:12   ` Rusty Russell
2012-09-27  9:08   ` David Howells
2012-09-28  5:55     ` Rusty Russell
2012-09-28  5:58     ` [PATCH 1/2] modsign: don't use bashism in sh scripts Rusty Russell
2012-09-28  5:59     ` [PATCH 2/2] modules: don't call eu-strip if it doesn't exist Rusty Russell
2012-09-28  6:05     ` [GIT PULL] Asymmetric keys and module signing Rusty Russell
2012-09-28  8:09     ` David Howells
2012-09-29  6:53       ` Rusty Russell
2012-09-29  7:13       ` David Howells
2012-10-01 20:41         ` Josh Boyer
2012-10-02  3:28           ` Rusty Russell
2012-10-02 12:17             ` Josh Boyer
2012-09-29  7:16       ` David Howells
2012-10-02  6:12         ` Rusty Russell
2012-10-02 14:07         ` David Howells
2012-10-03 23:22           ` Rusty Russell
2012-10-09 10:55             ` Kasatkin, Dmitry
2012-10-10  9:37               ` Rusty Russell
2012-09-28  8:10     ` [PATCH 1/2] modsign: don't use bashism in sh scripts David Howells
2012-10-02  2:24       ` Rusty Russell
2012-09-28  8:11     ` [PATCH 2/2] modules: don't call eu-strip if it doesn't exist David Howells
2012-09-28  8:13     ` [GIT PULL] Asymmetric keys and module signing David Howells
2012-09-28  9:23     ` David Howells
2012-09-28 10:31     ` David Howells
2012-10-03 17:50     ` [patch] MODSIGN: Fix build error with strict typechecking David Rientjes

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).