Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

PKCS#7: Provide a key type for testing PKCS#7

Provide a key type for testing the PKCS#7 parser. It is given a non-detached
PKCS#7 message as payload:

keyctl padd pkcs7_test a @s <stuff.pkcs7

The PKCS#7 wrapper is validated against the trusted certificates available and
then stripped off. If successful, the key can be read, which will give the
data content of the PKCS#7 message.

A suitable message can be created by running make on the attached Makefile.
This will produce a file called stuff.pkcs7 for test loading. The key3.x509
file should be put into the kernel source tree before it is built and
converted to DER form:

openssl x509 -in .../pkcs7/key3.x509 -outform DER -out key3.x509

###############################################################################
#
# Create a pkcs7 message and sign it twice
#
# openssl x509 -text -inform PEM -noout -in key2.x509
#
###############################################################################
stuff.pkcs7: stuff.txt key2.priv key2.x509 key4.priv key4.x509 certs
$(RM) $@
openssl smime -sign \
-signer key2.x509 \
-inkey key2.priv \
-signer key4.x509 \
-inkey key4.priv \
-in stuff.txt \
-certfile certs \
-out $@ -binary -outform DER -nodetach
openssl pkcs7 -inform DER -in stuff.pkcs7 -print_certs -noout
openssl asn1parse -inform DER -in stuff.pkcs7 -i >out

stuff.txt:
echo "The quick red fox jumped over the lazy brown dog" >stuff.txt

certs: key1.x509 key2.x509 key3.x509 key4.x509
cat key{1,3}.x509 >$@

###############################################################################
#
# Generate a signed key
#
# openssl x509 -text -inform PEM -noout -in key2.x509
#
###############################################################################
key2.x509: key2.x509_unsigned key1.priv key1.x509
openssl x509 \
-req -in key2.x509_unsigned \
-out key2.x509 \
-extfile key2.genkey -extensions myexts \
-CA key1.x509 \
-CAkey key1.priv \
-CAcreateserial

key2.priv key2.x509_unsigned: key2.genkey
openssl req -new -nodes -utf8 -sha1 -days 36500 \
-batch -outform PEM \
-config key2.genkey \
-keyout key2.priv \
-out key2.x509_unsigned

key2.genkey:
@echo Generating X.509 key generation config
@echo >$@ "[ req ]"
@echo >>$@ "default_bits = 4096"
@echo >>$@ "distinguished_name = req_distinguished_name"
@echo >>$@ "prompt = no"
@echo >>$@ "string_mask = utf8only"
@echo >>$@ "x509_extensions = myexts"
@echo >>$@
@echo >>$@ "[ req_distinguished_name ]"
@echo >>$@ "O = Magrathea"
@echo >>$@ "CN = PKCS7 key 2"
@echo >>$@ "emailAddress = slartibartfast@magrathea.h2g2"
@echo >>$@
@echo >>$@ "[ myexts ]"
@echo >>$@ "basicConstraints=critical,CA:FALSE"
@echo >>$@ "keyUsage=digitalSignature"
@echo >>$@ "subjectKeyIdentifier=hash"
@echo >>$@ "authorityKeyIdentifier=keyid"

###############################################################################
#
# Generate a couple of signing keys
#
# openssl x509 -text -inform PEM -noout -in key1.x509
#
###############################################################################
key1.x509: key1.x509_unsigned key4.priv key4.x509
openssl x509 \
-req -in key1.x509_unsigned \
-out key1.x509 \
-extfile key1.genkey -extensions myexts \
-CA key4.x509 \
-CAkey key4.priv \
-CAcreateserial

key1.priv key1.x509_unsigned: key1.genkey
openssl req -new -nodes -utf8 -sha1 -days 36500 \
-batch -outform PEM \
-config key1.genkey \
-keyout key1.priv \
-out key1.x509_unsigned

key1.genkey:
@echo Generating X.509 key generation config
@echo >$@ "[ req ]"
@echo >>$@ "default_bits = 4096"
@echo >>$@ "distinguished_name = req_distinguished_name"
@echo >>$@ "prompt = no"
@echo >>$@ "string_mask = utf8only"
@echo >>$@ "x509_extensions = myexts"
@echo >>$@
@echo >>$@ "[ req_distinguished_name ]"
@echo >>$@ "O = Magrathea"
@echo >>$@ "CN = PKCS7 key 1"
@echo >>$@ "emailAddress = slartibartfast@magrathea.h2g2"
@echo >>$@
@echo >>$@ "[ myexts ]"
@echo >>$@ "basicConstraints=critical,CA:TRUE"
@echo >>$@ "keyUsage=digitalSignature,keyCertSign"
@echo >>$@ "subjectKeyIdentifier=hash"
@echo >>$@ "authorityKeyIdentifier=keyid"

###############################################################################
#
# Generate a signed key
#
# openssl x509 -text -inform PEM -noout -in key4.x509
#
###############################################################################
key4.x509: key4.x509_unsigned key3.priv key3.x509
openssl x509 \
-req -in key4.x509_unsigned \
-out key4.x509 \
-extfile key4.genkey -extensions myexts \
-CA key3.x509 \
-CAkey key3.priv \
-CAcreateserial

key4.priv key4.x509_unsigned: key4.genkey
openssl req -new -nodes -utf8 -sha1 -days 36500 \
-batch -outform PEM \
-config key4.genkey \
-keyout key4.priv \
-out key4.x509_unsigned

key4.genkey:
@echo Generating X.509 key generation config
@echo >$@ "[ req ]"
@echo >>$@ "default_bits = 4096"
@echo >>$@ "distinguished_name = req_distinguished_name"
@echo >>$@ "prompt = no"
@echo >>$@ "string_mask = utf8only"
@echo >>$@ "x509_extensions = myexts"
@echo >>$@
@echo >>$@ "[ req_distinguished_name ]"
@echo >>$@ "O = Magrathea"
@echo >>$@ "CN = PKCS7 key 4"
@echo >>$@ "emailAddress = slartibartfast@magrathea.h2g2"
@echo >>$@
@echo >>$@ "[ myexts ]"
@echo >>$@ "basicConstraints=critical,CA:TRUE"
@echo >>$@ "keyUsage=digitalSignature,keyCertSign"
@echo >>$@ "subjectKeyIdentifier=hash"
@echo >>$@ "authorityKeyIdentifier=keyid"

###############################################################################
#
# Generate a couple of signing keys
#
# openssl x509 -text -inform PEM -noout -in key3.x509
#
###############################################################################
key3.priv key3.x509: key3.genkey
openssl req -new -nodes -utf8 -sha1 -days 36500 \
-batch -x509 -outform PEM \
-config key3.genkey \
-keyout key3.priv \
-out key3.x509

key3.genkey:
@echo Generating X.509 key generation config
@echo >$@ "[ req ]"
@echo >>$@ "default_bits = 4096"
@echo >>$@ "distinguished_name = req_distinguished_name"
@echo >>$@ "prompt = no"
@echo >>$@ "string_mask = utf8only"
@echo >>$@ "x509_extensions = myexts"
@echo >>$@
@echo >>$@ "[ req_distinguished_name ]"
@echo >>$@ "O = Magrathea"
@echo >>$@ "CN = PKCS7 key 3"
@echo >>$@ "emailAddress = slartibartfast@magrathea.h2g2"
@echo >>$@
@echo >>$@ "[ myexts ]"
@echo >>$@ "basicConstraints=critical,CA:TRUE"
@echo >>$@ "keyUsage=digitalSignature,keyCertSign"
@echo >>$@ "subjectKeyIdentifier=hash"
@echo >>$@ "authorityKeyIdentifier=keyid"

clean:
$(RM) *~
$(RM) key1.* key2.* key3.* key4.* stuff.* out certs

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

+117
+13
crypto/asymmetric_keys/Kconfig
··· 46 46 This option provides support for parsing PKCS#7 format messages for 47 47 signature data and provides the ability to verify the signature. 48 48 49 + config PKCS7_TEST_KEY 50 + tristate "PKCS#7 testing key type" 51 + depends on PKCS7_MESSAGE_PARSER 52 + select SYSTEM_TRUSTED_KEYRING 53 + help 54 + This option provides a type of key that can be loaded up from a 55 + PKCS#7 message - provided the message is signed by a trusted key. If 56 + it is, the PKCS#7 wrapper is discarded and reading the key returns 57 + just the payload. If it isn't, adding the key will fail with an 58 + error. 59 + 60 + This is intended for testing the PKCS#7 parser. 61 + 49 62 endif # ASYMMETRIC_KEY_TYPE
+7
crypto/asymmetric_keys/Makefile
··· 40 40 $(obj)/pkcs7-asn1.o: $(obj)/pkcs7-asn1.c $(obj)/pkcs7-asn1.h 41 41 42 42 clean-files += pkcs7-asn1.c pkcs7-asn1.h 43 + 44 + # 45 + # PKCS#7 parser testing key 46 + # 47 + obj-$(CONFIG_PKCS7_TEST_KEY) += pkcs7_test_key.o 48 + pkcs7_test_key-y := \ 49 + pkcs7_key_type.o
+97
crypto/asymmetric_keys/pkcs7_key_type.c
··· 1 + /* Testing module to load key from trusted PKCS#7 message 2 + * 3 + * Copyright (C) 2014 Red Hat, Inc. All Rights Reserved. 4 + * Written by David Howells (dhowells@redhat.com) 5 + * 6 + * This program is free software; you can redistribute it and/or 7 + * modify it under the terms of the GNU General Public Licence 8 + * as published by the Free Software Foundation; either version 9 + * 2 of the Licence, or (at your option) any later version. 10 + */ 11 + 12 + #define pr_fmt(fmt) "PKCS7key: "fmt 13 + #include <linux/key.h> 14 + #include <linux/key-type.h> 15 + #include <crypto/pkcs7.h> 16 + #include <keys/user-type.h> 17 + #include <keys/system_keyring.h> 18 + #include "pkcs7_parser.h" 19 + 20 + /* 21 + * Instantiate a PKCS#7 wrapped and validated key. 22 + */ 23 + int pkcs7_instantiate(struct key *key, struct key_preparsed_payload *prep) 24 + { 25 + struct pkcs7_message *pkcs7; 26 + const void *data, *saved_prep_data; 27 + size_t datalen, saved_prep_datalen; 28 + bool trusted; 29 + int ret; 30 + 31 + kenter(""); 32 + 33 + saved_prep_data = prep->data; 34 + saved_prep_datalen = prep->datalen; 35 + pkcs7 = pkcs7_parse_message(saved_prep_data, saved_prep_datalen); 36 + if (IS_ERR(pkcs7)) { 37 + ret = PTR_ERR(pkcs7); 38 + goto error; 39 + } 40 + 41 + ret = pkcs7_verify(pkcs7); 42 + if (ret < 0) 43 + goto error_free; 44 + 45 + ret = pkcs7_validate_trust(pkcs7, system_trusted_keyring, &trusted); 46 + if (ret < 0) 47 + goto error_free; 48 + if (!trusted) 49 + pr_warn("PKCS#7 message doesn't chain back to a trusted key\n"); 50 + 51 + ret = pkcs7_get_content_data(pkcs7, &data, &datalen, false); 52 + if (ret < 0) 53 + goto error_free; 54 + 55 + prep->data = data; 56 + prep->datalen = datalen; 57 + ret = user_instantiate(key, prep); 58 + prep->data = saved_prep_data; 59 + prep->datalen = saved_prep_datalen; 60 + 61 + error_free: 62 + pkcs7_free_message(pkcs7); 63 + error: 64 + kleave(" = %d", ret); 65 + return ret; 66 + } 67 + 68 + /* 69 + * user defined keys take an arbitrary string as the description and an 70 + * arbitrary blob of data as the payload 71 + */ 72 + struct key_type key_type_pkcs7 = { 73 + .name = "pkcs7_test", 74 + .def_lookup_type = KEYRING_SEARCH_LOOKUP_DIRECT, 75 + .instantiate = pkcs7_instantiate, 76 + .match = user_match, 77 + .revoke = user_revoke, 78 + .destroy = user_destroy, 79 + .describe = user_describe, 80 + .read = user_read, 81 + }; 82 + 83 + /* 84 + * Module stuff 85 + */ 86 + static int __init pkcs7_key_init(void) 87 + { 88 + return register_key_type(&key_type_pkcs7); 89 + } 90 + 91 + static void __exit pkcs7_key_cleanup(void) 92 + { 93 + unregister_key_type(&key_type_pkcs7); 94 + } 95 + 96 + module_init(pkcs7_key_init); 97 + module_exit(pkcs7_key_cleanup);