forked from torvalds/linux
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge tag 'keys-pkcs7-20140708' into keys-next
Here's a set of changes that implement a PKCS#7 message parser in the kernel. The PKCS#7 message parsing will then be used to limit kexec to authenticated kernels only if so configured. The changes provide the following facilities: (1) Parse an ASN.1 PKCS#7 message and pick out useful bits such as the data content and the X.509 certificates used to sign it and all the data signatures. (2) Verify all the data signatures against the set of X.509 certificates available in the message. (3) Follow the certificate chains and verify that: (a) for every self-signed X.509 certificate, check that it validly signed itself, and: (b) for every non-self-signed certificate, if we have a 'parent' certificate, the former is validly signed by the latter. (4) Look for intersections between the certificate chains and the trusted keyring, if any intersections are found, verify that the trusted certificates signed the intersection point in the chain. (5) For testing purposes, a key type can be made available that will take a PKCS#7 message, check that the message is trustworthy, and if so, add its data content into the key. Note that (5) has to be altered to take account of the preparsing patches already committed to this branch. Signed-off-by: David Howells <[email protected]>
- Loading branch information
Showing
13 changed files
with
1,339 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,127 @@ | ||
PKCS7ContentInfo ::= SEQUENCE { | ||
contentType ContentType, | ||
content [0] EXPLICIT SignedData OPTIONAL | ||
} | ||
|
||
ContentType ::= OBJECT IDENTIFIER ({ pkcs7_note_OID }) | ||
|
||
SignedData ::= SEQUENCE { | ||
version INTEGER, | ||
digestAlgorithms DigestAlgorithmIdentifiers, | ||
contentInfo ContentInfo, | ||
certificates CHOICE { | ||
certSet [0] IMPLICIT ExtendedCertificatesAndCertificates, | ||
certSequence [2] IMPLICIT Certificates | ||
} OPTIONAL ({ pkcs7_note_certificate_list }), | ||
crls CHOICE { | ||
crlSet [1] IMPLICIT CertificateRevocationLists, | ||
crlSequence [3] IMPLICIT CRLSequence | ||
} OPTIONAL, | ||
signerInfos SignerInfos | ||
} | ||
|
||
ContentInfo ::= SEQUENCE { | ||
contentType ContentType, | ||
content [0] EXPLICIT Data OPTIONAL | ||
} | ||
|
||
Data ::= ANY ({ pkcs7_note_data }) | ||
|
||
DigestAlgorithmIdentifiers ::= CHOICE { | ||
daSet SET OF DigestAlgorithmIdentifier, | ||
daSequence SEQUENCE OF DigestAlgorithmIdentifier | ||
} | ||
|
||
DigestAlgorithmIdentifier ::= SEQUENCE { | ||
algorithm OBJECT IDENTIFIER ({ pkcs7_note_OID }), | ||
parameters ANY OPTIONAL | ||
} | ||
|
||
-- | ||
-- Certificates and certificate lists | ||
-- | ||
ExtendedCertificatesAndCertificates ::= SET OF ExtendedCertificateOrCertificate | ||
|
||
ExtendedCertificateOrCertificate ::= CHOICE { | ||
certificate Certificate, -- X.509 | ||
extendedCertificate [0] IMPLICIT ExtendedCertificate -- PKCS#6 | ||
} | ||
|
||
ExtendedCertificate ::= Certificate -- cheating | ||
|
||
Certificates ::= SEQUENCE OF Certificate | ||
|
||
CertificateRevocationLists ::= SET OF CertificateList | ||
|
||
CertificateList ::= SEQUENCE OF Certificate -- This may be defined incorrectly | ||
|
||
CRLSequence ::= SEQUENCE OF CertificateList | ||
|
||
Certificate ::= ANY ({ pkcs7_extract_cert }) -- X.509 | ||
|
||
-- | ||
-- Signer information | ||
-- | ||
SignerInfos ::= CHOICE { | ||
siSet SET OF SignerInfo, | ||
siSequence SEQUENCE OF SignerInfo | ||
} | ||
|
||
SignerInfo ::= SEQUENCE { | ||
version INTEGER, | ||
issuerAndSerialNumber IssuerAndSerialNumber, | ||
digestAlgorithm DigestAlgorithmIdentifier ({ pkcs7_sig_note_digest_algo }), | ||
authenticatedAttributes CHOICE { | ||
aaSet [0] IMPLICIT SetOfAuthenticatedAttribute | ||
({ pkcs7_sig_note_set_of_authattrs }), | ||
aaSequence [2] EXPLICIT SEQUENCE OF AuthenticatedAttribute | ||
-- Explicit because easier to compute digest on | ||
-- sequence of attributes and then reuse encoded | ||
-- sequence in aaSequence. | ||
} OPTIONAL, | ||
digestEncryptionAlgorithm | ||
DigestEncryptionAlgorithmIdentifier ({ pkcs7_sig_note_pkey_algo }), | ||
encryptedDigest EncryptedDigest, | ||
unauthenticatedAttributes CHOICE { | ||
uaSet [1] IMPLICIT SET OF UnauthenticatedAttribute, | ||
uaSequence [3] IMPLICIT SEQUENCE OF UnauthenticatedAttribute | ||
} OPTIONAL | ||
} ({ pkcs7_note_signed_info }) | ||
|
||
IssuerAndSerialNumber ::= SEQUENCE { | ||
issuer Name ({ pkcs7_sig_note_issuer }), | ||
serialNumber CertificateSerialNumber ({ pkcs7_sig_note_serial }) | ||
} | ||
|
||
CertificateSerialNumber ::= INTEGER | ||
|
||
SetOfAuthenticatedAttribute ::= SET OF AuthenticatedAttribute | ||
|
||
AuthenticatedAttribute ::= SEQUENCE { | ||
type OBJECT IDENTIFIER ({ pkcs7_note_OID }), | ||
values SET OF ANY ({ pkcs7_sig_note_authenticated_attr }) | ||
} | ||
|
||
UnauthenticatedAttribute ::= SEQUENCE { | ||
type OBJECT IDENTIFIER ({ pkcs7_note_OID }), | ||
values SET OF ANY | ||
} | ||
|
||
DigestEncryptionAlgorithmIdentifier ::= SEQUENCE { | ||
algorithm OBJECT IDENTIFIER ({ pkcs7_note_OID }), | ||
parameters ANY OPTIONAL | ||
} | ||
|
||
EncryptedDigest ::= OCTET STRING ({ pkcs7_sig_note_signature }) | ||
|
||
--- | ||
--- X.500 Name | ||
--- | ||
Name ::= SEQUENCE OF RelativeDistinguishedName | ||
|
||
RelativeDistinguishedName ::= SET OF AttributeValueAssertion | ||
|
||
AttributeValueAssertion ::= SEQUENCE { | ||
attributeType OBJECT IDENTIFIER ({ pkcs7_note_OID }), | ||
attributeValue ANY | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,99 @@ | ||
/* Testing module to load key from trusted PKCS#7 message | ||
* | ||
* Copyright (C) 2014 Red Hat, Inc. All Rights Reserved. | ||
* Written by David Howells ([email protected]) | ||
* | ||
* This program is free software; you can redistribute it and/or | ||
* modify it under the terms of the GNU General Public Licence | ||
* as published by the Free Software Foundation; either version | ||
* 2 of the Licence, or (at your option) any later version. | ||
*/ | ||
|
||
#define pr_fmt(fmt) "PKCS7key: "fmt | ||
#include <linux/key.h> | ||
#include <linux/key-type.h> | ||
#include <crypto/pkcs7.h> | ||
#include <keys/user-type.h> | ||
#include <keys/system_keyring.h> | ||
#include "pkcs7_parser.h" | ||
|
||
/* | ||
* Preparse a PKCS#7 wrapped and validated data blob. | ||
*/ | ||
static int pkcs7_preparse(struct key_preparsed_payload *prep) | ||
{ | ||
struct pkcs7_message *pkcs7; | ||
const void *data, *saved_prep_data; | ||
size_t datalen, saved_prep_datalen; | ||
bool trusted; | ||
int ret; | ||
|
||
kenter(""); | ||
|
||
saved_prep_data = prep->data; | ||
saved_prep_datalen = prep->datalen; | ||
pkcs7 = pkcs7_parse_message(saved_prep_data, saved_prep_datalen); | ||
if (IS_ERR(pkcs7)) { | ||
ret = PTR_ERR(pkcs7); | ||
goto error; | ||
} | ||
|
||
ret = pkcs7_verify(pkcs7); | ||
if (ret < 0) | ||
goto error_free; | ||
|
||
ret = pkcs7_validate_trust(pkcs7, system_trusted_keyring, &trusted); | ||
if (ret < 0) | ||
goto error_free; | ||
if (!trusted) | ||
pr_warn("PKCS#7 message doesn't chain back to a trusted key\n"); | ||
|
||
ret = pkcs7_get_content_data(pkcs7, &data, &datalen, false); | ||
if (ret < 0) | ||
goto error_free; | ||
|
||
prep->data = data; | ||
prep->datalen = datalen; | ||
ret = user_preparse(prep); | ||
prep->data = saved_prep_data; | ||
prep->datalen = saved_prep_datalen; | ||
|
||
error_free: | ||
pkcs7_free_message(pkcs7); | ||
error: | ||
kleave(" = %d", ret); | ||
return ret; | ||
} | ||
|
||
/* | ||
* user defined keys take an arbitrary string as the description and an | ||
* arbitrary blob of data as the payload | ||
*/ | ||
struct key_type key_type_pkcs7 = { | ||
.name = "pkcs7_test", | ||
.def_lookup_type = KEYRING_SEARCH_LOOKUP_DIRECT, | ||
.preparse = pkcs7_preparse, | ||
.free_preparse = user_free_preparse, | ||
.instantiate = generic_key_instantiate, | ||
.match = user_match, | ||
.revoke = user_revoke, | ||
.destroy = user_destroy, | ||
.describe = user_describe, | ||
.read = user_read, | ||
}; | ||
|
||
/* | ||
* Module stuff | ||
*/ | ||
static int __init pkcs7_key_init(void) | ||
{ | ||
return register_key_type(&key_type_pkcs7); | ||
} | ||
|
||
static void __exit pkcs7_key_cleanup(void) | ||
{ | ||
unregister_key_type(&key_type_pkcs7); | ||
} | ||
|
||
module_init(pkcs7_key_init); | ||
module_exit(pkcs7_key_cleanup); |
Oops, something went wrong.