Merge tag 'keys-next-20160303' of git://git.kernel.org/pub/scm/linux/kernel/git/dhowells/linux-fs into next

This commit is contained in:
James Morris
2016-03-04 11:39:53 +11:00
59 changed files with 1002 additions and 748 deletions

View File

@@ -166,7 +166,6 @@ CONFIG_DEBUG_USER=y
CONFIG_DEBUG_ERRORS=y CONFIG_DEBUG_ERRORS=y
CONFIG_DEBUG_LL=y CONFIG_DEBUG_LL=y
CONFIG_KEYS=y CONFIG_KEYS=y
CONFIG_KEYS_DEBUG_PROC_KEYS=y
CONFIG_SECURITY=y CONFIG_SECURITY=y
CONFIG_CRYPTO_PCBC=m CONFIG_CRYPTO_PCBC=m
CONFIG_CRYPTO_SHA1=m CONFIG_CRYPTO_SHA1=m

View File

@@ -95,7 +95,6 @@ CONFIG_PARTITION_ADVANCED=y
CONFIG_NLS=y CONFIG_NLS=y
CONFIG_DEBUG_USER=y CONFIG_DEBUG_USER=y
CONFIG_KEYS=y CONFIG_KEYS=y
CONFIG_KEYS_DEBUG_PROC_KEYS=y
CONFIG_CRYPTO_NULL=y CONFIG_CRYPTO_NULL=y
CONFIG_CRYPTO_LRW=y CONFIG_CRYPTO_LRW=y
CONFIG_CRYPTO_PCBC=m CONFIG_CRYPTO_PCBC=m

View File

@@ -108,7 +108,6 @@ CONFIG_DEBUG_USER=y
CONFIG_DEBUG_LL=y CONFIG_DEBUG_LL=y
CONFIG_DEBUG_LL_UART_8250=y CONFIG_DEBUG_LL_UART_8250=y
CONFIG_KEYS=y CONFIG_KEYS=y
CONFIG_KEYS_DEBUG_PROC_KEYS=y
CONFIG_CRYPTO_NULL=y CONFIG_CRYPTO_NULL=y
CONFIG_CRYPTO_LRW=y CONFIG_CRYPTO_LRW=y
CONFIG_CRYPTO_PCBC=m CONFIG_CRYPTO_PCBC=m

View File

@@ -214,7 +214,6 @@ CONFIG_MAGIC_SYSRQ=y
CONFIG_DEBUG_FS=y CONFIG_DEBUG_FS=y
CONFIG_DEBUG_USER=y CONFIG_DEBUG_USER=y
CONFIG_KEYS=y CONFIG_KEYS=y
CONFIG_KEYS_DEBUG_PROC_KEYS=y
CONFIG_SECURITY=y CONFIG_SECURITY=y
CONFIG_CRYPTO_PCBC=m CONFIG_CRYPTO_PCBC=m
CONFIG_CRYPTO_SHA256=m CONFIG_CRYPTO_SHA256=m

View File

@@ -87,5 +87,4 @@ CONFIG_KGDB_KDB=y
CONFIG_EARLY_PRINTK=y CONFIG_EARLY_PRINTK=y
CONFIG_KEYS=y CONFIG_KEYS=y
CONFIG_ENCRYPTED_KEYS=y CONFIG_ENCRYPTED_KEYS=y
CONFIG_KEYS_DEBUG_PROC_KEYS=y
# CONFIG_CRYPTO_ANSI_CPRNG is not set # CONFIG_CRYPTO_ANSI_CPRNG is not set

View File

@@ -92,7 +92,6 @@ CONFIG_DEBUG_INFO=y
CONFIG_EARLY_PRINTK=y CONFIG_EARLY_PRINTK=y
CONFIG_KEYS=y CONFIG_KEYS=y
CONFIG_ENCRYPTED_KEYS=y CONFIG_ENCRYPTED_KEYS=y
CONFIG_KEYS_DEBUG_PROC_KEYS=y
CONFIG_CRYPTO_ECB=y CONFIG_CRYPTO_ECB=y
CONFIG_CRYPTO_MD4=y CONFIG_CRYPTO_MD4=y
CONFIG_CRYPTO_MD5=y CONFIG_CRYPTO_MD5=y

View File

@@ -247,7 +247,6 @@ CONFIG_DEBUG_SPINLOCK_SLEEP=y
CONFIG_DEBUG_MEMORY_INIT=y CONFIG_DEBUG_MEMORY_INIT=y
CONFIG_DEBUG_LIST=y CONFIG_DEBUG_LIST=y
CONFIG_KEYS=y CONFIG_KEYS=y
CONFIG_KEYS_DEBUG_PROC_KEYS=y
CONFIG_SECURITY=y CONFIG_SECURITY=y
CONFIG_SECURITY_NETWORK=y CONFIG_SECURITY_NETWORK=y
CONFIG_SECURITY_NETWORK_XFRM=y CONFIG_SECURITY_NETWORK_XFRM=y

View File

@@ -358,7 +358,6 @@ CONFIG_DLM=m
CONFIG_DEBUG_MEMORY_INIT=y CONFIG_DEBUG_MEMORY_INIT=y
# CONFIG_RCU_CPU_STALL_DETECTOR is not set # CONFIG_RCU_CPU_STALL_DETECTOR is not set
CONFIG_KEYS=y CONFIG_KEYS=y
CONFIG_KEYS_DEBUG_PROC_KEYS=y
CONFIG_CRYPTO_FIPS=y CONFIG_CRYPTO_FIPS=y
CONFIG_CRYPTO_NULL=m CONFIG_CRYPTO_NULL=m
CONFIG_CRYPTO_CRYPTD=m CONFIG_CRYPTO_CRYPTD=m

View File

@@ -346,7 +346,6 @@ CONFIG_PARTITION_ADVANCED=y
CONFIG_DLM=m CONFIG_DLM=m
# CONFIG_RCU_CPU_STALL_DETECTOR is not set # CONFIG_RCU_CPU_STALL_DETECTOR is not set
CONFIG_KEYS=y CONFIG_KEYS=y
CONFIG_KEYS_DEBUG_PROC_KEYS=y
CONFIG_SECURITYFS=y CONFIG_SECURITYFS=y
CONFIG_CRYPTO_FIPS=y CONFIG_CRYPTO_FIPS=y
CONFIG_CRYPTO_NULL=m CONFIG_CRYPTO_NULL=m

View File

@@ -181,7 +181,6 @@ CONFIG_MAGIC_SYSRQ=y
# CONFIG_RCU_CPU_STALL_DETECTOR is not set # CONFIG_RCU_CPU_STALL_DETECTOR is not set
CONFIG_SYSCTL_SYSCALL_CHECK=y CONFIG_SYSCTL_SYSCALL_CHECK=y
CONFIG_KEYS=y CONFIG_KEYS=y
CONFIG_KEYS_DEBUG_PROC_KEYS=y
CONFIG_CRYPTO_NULL=y CONFIG_CRYPTO_NULL=y
CONFIG_CRYPTO_CBC=y CONFIG_CRYPTO_CBC=y
CONFIG_CRYPTO_ECB=y CONFIG_CRYPTO_ECB=y

View File

@@ -362,7 +362,6 @@ CONFIG_NLS_KOI8_R=m
CONFIG_NLS_KOI8_U=m CONFIG_NLS_KOI8_U=m
CONFIG_NLS_UTF8=m CONFIG_NLS_UTF8=m
CONFIG_DLM=m CONFIG_DLM=m
CONFIG_KEYS_DEBUG_PROC_KEYS=y
CONFIG_CRYPTO_NULL=m CONFIG_CRYPTO_NULL=m
CONFIG_CRYPTO_ECB=m CONFIG_CRYPTO_ECB=m
CONFIG_CRYPTO_LRW=m CONFIG_CRYPTO_LRW=m

View File

@@ -412,7 +412,6 @@ CONFIG_DEBUG_FS=y
# CONFIG_RCU_CPU_STALL_DETECTOR is not set # CONFIG_RCU_CPU_STALL_DETECTOR is not set
CONFIG_SYSCTL_SYSCALL_CHECK=y CONFIG_SYSCTL_SYSCALL_CHECK=y
CONFIG_KEYS=y CONFIG_KEYS=y
CONFIG_KEYS_DEBUG_PROC_KEYS=y
CONFIG_CRYPTO_FIPS=y CONFIG_CRYPTO_FIPS=y
CONFIG_CRYPTO_NULL=m CONFIG_CRYPTO_NULL=m
CONFIG_CRYPTO_CRYPTD=m CONFIG_CRYPTO_CRYPTD=m

View File

@@ -453,7 +453,6 @@ CONFIG_NLS_KOI8_R=m
CONFIG_NLS_KOI8_U=m CONFIG_NLS_KOI8_U=m
CONFIG_NLS_UTF8=m CONFIG_NLS_UTF8=m
CONFIG_DLM=m CONFIG_DLM=m
CONFIG_KEYS_DEBUG_PROC_KEYS=y
CONFIG_CRYPTO_NULL=m CONFIG_CRYPTO_NULL=m
CONFIG_CRYPTO_ECB=m CONFIG_CRYPTO_ECB=m
CONFIG_CRYPTO_LRW=m CONFIG_CRYPTO_LRW=m

View File

@@ -87,7 +87,6 @@ CONFIG_NFS_V3=y
CONFIG_ROOT_NFS=y CONFIG_ROOT_NFS=y
CONFIG_DLM=m CONFIG_DLM=m
CONFIG_KEYS=y CONFIG_KEYS=y
CONFIG_KEYS_DEBUG_PROC_KEYS=y
CONFIG_CRYPTO_NULL=m CONFIG_CRYPTO_NULL=m
CONFIG_CRYPTO_CRYPTD=m CONFIG_CRYPTO_CRYPTD=m
CONFIG_CRYPTO_AUTHENC=m CONFIG_CRYPTO_AUTHENC=m

View File

@@ -183,7 +183,6 @@ CONFIG_DEBUG_KERNEL=y
CONFIG_DEBUG_MUTEXES=y CONFIG_DEBUG_MUTEXES=y
# CONFIG_RCU_CPU_STALL_DETECTOR is not set # CONFIG_RCU_CPU_STALL_DETECTOR is not set
CONFIG_DEBUG_RODATA=y CONFIG_DEBUG_RODATA=y
CONFIG_KEYS_DEBUG_PROC_KEYS=y
CONFIG_CRYPTO_NULL=m CONFIG_CRYPTO_NULL=m
CONFIG_CRYPTO_TEST=m CONFIG_CRYPTO_TEST=m
CONFIG_CRYPTO_HMAC=y CONFIG_CRYPTO_HMAC=y

View File

@@ -193,7 +193,6 @@ CONFIG_HEADERS_CHECK=y
CONFIG_DEBUG_KERNEL=y CONFIG_DEBUG_KERNEL=y
# CONFIG_DEBUG_BUGVERBOSE is not set # CONFIG_DEBUG_BUGVERBOSE is not set
# CONFIG_RCU_CPU_STALL_DETECTOR is not set # CONFIG_RCU_CPU_STALL_DETECTOR is not set
CONFIG_KEYS_DEBUG_PROC_KEYS=y
CONFIG_CRYPTO_NULL=m CONFIG_CRYPTO_NULL=m
CONFIG_CRYPTO_TEST=m CONFIG_CRYPTO_TEST=m
CONFIG_CRYPTO_HMAC=y CONFIG_CRYPTO_HMAC=y

View File

@@ -211,7 +211,6 @@ CONFIG_DEBUG_KERNEL=y
CONFIG_DEBUG_MUTEXES=y CONFIG_DEBUG_MUTEXES=y
# CONFIG_RCU_CPU_STALL_DETECTOR is not set # CONFIG_RCU_CPU_STALL_DETECTOR is not set
CONFIG_KEYS=y CONFIG_KEYS=y
CONFIG_KEYS_DEBUG_PROC_KEYS=y
CONFIG_CRYPTO_NULL=m CONFIG_CRYPTO_NULL=m
CONFIG_CRYPTO_TEST=m CONFIG_CRYPTO_TEST=m
CONFIG_CRYPTO_MD4=m CONFIG_CRYPTO_MD4=m

View File

@@ -301,7 +301,6 @@ CONFIG_RCU_CPU_STALL_INFO=y
CONFIG_LATENCYTOP=y CONFIG_LATENCYTOP=y
CONFIG_LKDTM=m CONFIG_LKDTM=m
CONFIG_KEYS=y CONFIG_KEYS=y
CONFIG_KEYS_DEBUG_PROC_KEYS=y
CONFIG_CRYPTO_NULL=m CONFIG_CRYPTO_NULL=m
CONFIG_CRYPTO_TEST=m CONFIG_CRYPTO_TEST=m
CONFIG_CRYPTO_HMAC=y CONFIG_CRYPTO_HMAC=y

View File

@@ -387,7 +387,6 @@ CONFIG_DETECT_HUNG_TASK=y
CONFIG_DEBUG_SPINLOCK=y CONFIG_DEBUG_SPINLOCK=y
CONFIG_BOOTX_TEXT=y CONFIG_BOOTX_TEXT=y
CONFIG_PPC_EARLY_DEBUG=y CONFIG_PPC_EARLY_DEBUG=y
CONFIG_KEYS_DEBUG_PROC_KEYS=y
CONFIG_SECURITY=y CONFIG_SECURITY=y
CONFIG_SECURITY_NETWORK=y CONFIG_SECURITY_NETWORK=y
CONFIG_SECURITY_SELINUX=y CONFIG_SECURITY_SELINUX=y

View File

@@ -1175,7 +1175,6 @@ CONFIG_BLK_DEV_IO_TRACE=y
CONFIG_XMON=y CONFIG_XMON=y
CONFIG_BOOTX_TEXT=y CONFIG_BOOTX_TEXT=y
CONFIG_PPC_EARLY_DEBUG=y CONFIG_PPC_EARLY_DEBUG=y
CONFIG_KEYS_DEBUG_PROC_KEYS=y
CONFIG_SECURITY=y CONFIG_SECURITY=y
CONFIG_SECURITY_NETWORK=y CONFIG_SECURITY_NETWORK=y
CONFIG_SECURITY_NETWORK_XFRM=y CONFIG_SECURITY_NETWORK_XFRM=y

View File

@@ -70,7 +70,6 @@ CONFIG_NFSD=y
CONFIG_NFSD_V3_ACL=y CONFIG_NFSD_V3_ACL=y
CONFIG_NFSD_V4=y CONFIG_NFSD_V4=y
# CONFIG_RCU_CPU_STALL_DETECTOR is not set # CONFIG_RCU_CPU_STALL_DETECTOR is not set
CONFIG_KEYS_DEBUG_PROC_KEYS=y
CONFIG_SECURITY=y CONFIG_SECURITY=y
CONFIG_SECURITY_NETWORK=y CONFIG_SECURITY_NETWORK=y
CONFIG_CRYPTO_NULL=y CONFIG_CRYPTO_NULL=y

View File

@@ -374,7 +374,6 @@ CONFIG_DEBUG_CREDENTIALS=y
CONFIG_RCU_CPU_STALL_TIMEOUT=60 CONFIG_RCU_CPU_STALL_TIMEOUT=60
CONFIG_ASYNC_RAID6_TEST=m CONFIG_ASYNC_RAID6_TEST=m
CONFIG_KGDB=y CONFIG_KGDB=y
CONFIG_KEYS_DEBUG_PROC_KEYS=y
CONFIG_SECURITY=y CONFIG_SECURITY=y
CONFIG_SECURITYFS=y CONFIG_SECURITYFS=y
CONFIG_SECURITY_NETWORK=y CONFIG_SECURITY_NETWORK=y

View File

@@ -486,7 +486,6 @@ CONFIG_DEBUG_LIST=y
CONFIG_DEBUG_CREDENTIALS=y CONFIG_DEBUG_CREDENTIALS=y
CONFIG_RCU_CPU_STALL_TIMEOUT=60 CONFIG_RCU_CPU_STALL_TIMEOUT=60
CONFIG_ASYNC_RAID6_TEST=m CONFIG_ASYNC_RAID6_TEST=m
CONFIG_KEYS_DEBUG_PROC_KEYS=y
CONFIG_SECURITY=y CONFIG_SECURITY=y
CONFIG_SECURITYFS=y CONFIG_SECURITYFS=y
CONFIG_SECURITY_NETWORK=y CONFIG_SECURITY_NETWORK=y

View File

@@ -303,7 +303,6 @@ CONFIG_DEBUG_STACKOVERFLOW=y
# CONFIG_DEBUG_RODATA_TEST is not set # CONFIG_DEBUG_RODATA_TEST is not set
CONFIG_DEBUG_BOOT_PARAMS=y CONFIG_DEBUG_BOOT_PARAMS=y
CONFIG_OPTIMIZE_INLINING=y CONFIG_OPTIMIZE_INLINING=y
CONFIG_KEYS_DEBUG_PROC_KEYS=y
CONFIG_SECURITY=y CONFIG_SECURITY=y
CONFIG_SECURITY_NETWORK=y CONFIG_SECURITY_NETWORK=y
CONFIG_SECURITY_SELINUX=y CONFIG_SECURITY_SELINUX=y

View File

@@ -300,7 +300,6 @@ CONFIG_DEBUG_STACKOVERFLOW=y
# CONFIG_DEBUG_RODATA_TEST is not set # CONFIG_DEBUG_RODATA_TEST is not set
CONFIG_DEBUG_BOOT_PARAMS=y CONFIG_DEBUG_BOOT_PARAMS=y
CONFIG_OPTIMIZE_INLINING=y CONFIG_OPTIMIZE_INLINING=y
CONFIG_KEYS_DEBUG_PROC_KEYS=y
CONFIG_SECURITY=y CONFIG_SECURITY=y
CONFIG_SECURITY_NETWORK=y CONFIG_SECURITY_NETWORK=y
CONFIG_SECURITY_SELINUX=y CONFIG_SECURITY_SELINUX=y

View File

@@ -39,4 +39,20 @@ config SYSTEM_TRUSTED_KEYS
form of DER-encoded *.x509 files in the top-level build directory, form of DER-encoded *.x509 files in the top-level build directory,
those are no longer used. You will need to set this option instead. those are no longer used. You will need to set this option instead.
config SYSTEM_EXTRA_CERTIFICATE
bool "Reserve area for inserting a certificate without recompiling"
depends on SYSTEM_TRUSTED_KEYRING
help
If set, space for an extra certificate will be reserved in the kernel
image. This allows introducing a trusted certificate to the default
system keyring without recompiling the kernel.
config SYSTEM_EXTRA_CERTIFICATE_SIZE
int "Number of bytes to reserve for the extra certificate"
depends on SYSTEM_EXTRA_CERTIFICATE
default 4096
help
This is the number of bytes reserved in the kernel image for a
certificate to be inserted.
endmenu endmenu

View File

@@ -36,29 +36,34 @@ ifndef CONFIG_MODULE_SIG_HASH
$(error Could not determine digest type to use from kernel config) $(error Could not determine digest type to use from kernel config)
endif endif
redirect_openssl = 2>&1
quiet_redirect_openssl = 2>&1
silent_redirect_openssl = 2>/dev/null
# We do it this way rather than having a boolean option for enabling an # We do it this way rather than having a boolean option for enabling an
# external private key, because 'make randconfig' might enable such a # external private key, because 'make randconfig' might enable such a
# boolean option and we unfortunately can't make it depend on !RANDCONFIG. # boolean option and we unfortunately can't make it depend on !RANDCONFIG.
ifeq ($(CONFIG_MODULE_SIG_KEY),"certs/signing_key.pem") ifeq ($(CONFIG_MODULE_SIG_KEY),"certs/signing_key.pem")
$(obj)/signing_key.pem: $(obj)/x509.genkey $(obj)/signing_key.pem: $(obj)/x509.genkey
@echo "###" @$(kecho) "###"
@echo "### Now generating an X.509 key pair to be used for signing modules." @$(kecho) "### Now generating an X.509 key pair to be used for signing modules."
@echo "###" @$(kecho) "###"
@echo "### If this takes a long time, you might wish to run rngd in the" @$(kecho) "### If this takes a long time, you might wish to run rngd in the"
@echo "### background to keep the supply of entropy topped up. It" @$(kecho) "### background to keep the supply of entropy topped up. It"
@echo "### needs to be run as root, and uses a hardware random" @$(kecho) "### needs to be run as root, and uses a hardware random"
@echo "### number generator if one is available." @$(kecho) "### number generator if one is available."
@echo "###" @$(kecho) "###"
openssl req -new -nodes -utf8 -$(CONFIG_MODULE_SIG_HASH) -days 36500 \ $(Q)openssl req -new -nodes -utf8 -$(CONFIG_MODULE_SIG_HASH) -days 36500 \
-batch -x509 -config $(obj)/x509.genkey \ -batch -x509 -config $(obj)/x509.genkey \
-outform PEM -out $(obj)/signing_key.pem \ -outform PEM -out $(obj)/signing_key.pem \
-keyout $(obj)/signing_key.pem 2>&1 -keyout $(obj)/signing_key.pem \
@echo "###" $($(quiet)redirect_openssl)
@echo "### Key pair generated." @$(kecho) "###"
@echo "###" @$(kecho) "### Key pair generated."
@$(kecho) "###"
$(obj)/x509.genkey: $(obj)/x509.genkey:
@echo Generating X.509 key generation config @$(kecho) Generating X.509 key generation config
@echo >$@ "[ req ]" @echo >$@ "[ req ]"
@echo >>$@ "default_bits = 4096" @echo >>$@ "default_bits = 4096"
@echo >>$@ "distinguished_name = req_distinguished_name" @echo >>$@ "distinguished_name = req_distinguished_name"

View File

@@ -13,6 +13,19 @@ __cert_list_start:
.incbin "certs/x509_certificate_list" .incbin "certs/x509_certificate_list"
__cert_list_end: __cert_list_end:
#ifdef CONFIG_SYSTEM_EXTRA_CERTIFICATE
.globl VMLINUX_SYMBOL(system_extra_cert)
.size system_extra_cert, CONFIG_SYSTEM_EXTRA_CERTIFICATE_SIZE
VMLINUX_SYMBOL(system_extra_cert):
.fill CONFIG_SYSTEM_EXTRA_CERTIFICATE_SIZE, 1, 0
.align 4
.globl VMLINUX_SYMBOL(system_extra_cert_used)
VMLINUX_SYMBOL(system_extra_cert_used):
.int 0
#endif /* CONFIG_SYSTEM_EXTRA_CERTIFICATE */
.align 8 .align 8
.globl VMLINUX_SYMBOL(system_certificate_list_size) .globl VMLINUX_SYMBOL(system_certificate_list_size)
VMLINUX_SYMBOL(system_certificate_list_size): VMLINUX_SYMBOL(system_certificate_list_size):

View File

@@ -84,12 +84,12 @@ static __init int load_system_certificate_list(void)
((KEY_POS_ALL & ~KEY_POS_SETATTR) | ((KEY_POS_ALL & ~KEY_POS_SETATTR) |
KEY_USR_VIEW | KEY_USR_READ), KEY_USR_VIEW | KEY_USR_READ),
KEY_ALLOC_NOT_IN_QUOTA | KEY_ALLOC_NOT_IN_QUOTA |
KEY_ALLOC_TRUSTED); KEY_ALLOC_TRUSTED |
KEY_ALLOC_BUILT_IN);
if (IS_ERR(key)) { if (IS_ERR(key)) {
pr_err("Problem loading in-kernel X.509 certificate (%ld)\n", pr_err("Problem loading in-kernel X.509 certificate (%ld)\n",
PTR_ERR(key)); PTR_ERR(key));
} else { } else {
set_bit(KEY_FLAG_BUILTIN, &key_ref_to_ptr(key)->flags);
pr_notice("Loaded X.509 cert '%s'\n", pr_notice("Loaded X.509 cert '%s'\n",
key_ref_to_ptr(key)->description); key_ref_to_ptr(key)->description);
key_ref_put(key); key_ref_put(key);

View File

@@ -12,7 +12,6 @@ if ASYMMETRIC_KEY_TYPE
config ASYMMETRIC_PUBLIC_KEY_SUBTYPE config ASYMMETRIC_PUBLIC_KEY_SUBTYPE
tristate "Asymmetric public-key crypto algorithm subtype" tristate "Asymmetric public-key crypto algorithm subtype"
select MPILIB select MPILIB
select PUBLIC_KEY_ALGO_RSA
select CRYPTO_HASH_INFO select CRYPTO_HASH_INFO
help help
This option provides support for asymmetric public key type handling. This option provides support for asymmetric public key type handling.
@@ -20,12 +19,6 @@ config ASYMMETRIC_PUBLIC_KEY_SUBTYPE
appropriate hash algorithms (such as SHA-1) must be available. appropriate hash algorithms (such as SHA-1) must be available.
ENOPKG will be reported if the requisite algorithm is unavailable. ENOPKG will be reported if the requisite algorithm is unavailable.
config PUBLIC_KEY_ALGO_RSA
tristate "RSA public-key algorithm"
select MPILIB
help
This option enables support for the RSA algorithm (PKCS#1, RFC3447).
config X509_CERTIFICATE_PARSER config X509_CERTIFICATE_PARSER
tristate "X.509 certificate parser" tristate "X.509 certificate parser"
depends on ASYMMETRIC_PUBLIC_KEY_SUBTYPE depends on ASYMMETRIC_PUBLIC_KEY_SUBTYPE

View File

@@ -7,7 +7,6 @@ obj-$(CONFIG_ASYMMETRIC_KEY_TYPE) += asymmetric_keys.o
asymmetric_keys-y := asymmetric_type.o signature.o asymmetric_keys-y := asymmetric_type.o signature.o
obj-$(CONFIG_ASYMMETRIC_PUBLIC_KEY_SUBTYPE) += public_key.o obj-$(CONFIG_ASYMMETRIC_PUBLIC_KEY_SUBTYPE) += public_key.o
obj-$(CONFIG_PUBLIC_KEY_ALGO_RSA) += rsa.o
# #
# X.509 Certificate handling # X.509 Certificate handling
@@ -16,21 +15,18 @@ obj-$(CONFIG_X509_CERTIFICATE_PARSER) += x509_key_parser.o
x509_key_parser-y := \ x509_key_parser-y := \
x509-asn1.o \ x509-asn1.o \
x509_akid-asn1.o \ x509_akid-asn1.o \
x509_rsakey-asn1.o \
x509_cert_parser.o \ x509_cert_parser.o \
x509_public_key.o x509_public_key.o
$(obj)/x509_cert_parser.o: \ $(obj)/x509_cert_parser.o: \
$(obj)/x509-asn1.h \ $(obj)/x509-asn1.h \
$(obj)/x509_akid-asn1.h \ $(obj)/x509_akid-asn1.h
$(obj)/x509_rsakey-asn1.h
$(obj)/x509-asn1.o: $(obj)/x509-asn1.c $(obj)/x509-asn1.h $(obj)/x509-asn1.o: $(obj)/x509-asn1.c $(obj)/x509-asn1.h
$(obj)/x509_akid-asn1.o: $(obj)/x509_akid-asn1.c $(obj)/x509_akid-asn1.h $(obj)/x509_akid-asn1.o: $(obj)/x509_akid-asn1.c $(obj)/x509_akid-asn1.h
$(obj)/x509_rsakey-asn1.o: $(obj)/x509_rsakey-asn1.c $(obj)/x509_rsakey-asn1.h
clean-files += x509-asn1.c x509-asn1.h clean-files += x509-asn1.c x509-asn1.h
clean-files += x509_akid-asn1.c x509_akid-asn1.h clean-files += x509_akid-asn1.c x509_akid-asn1.h
clean-files += x509_rsakey-asn1.c x509_rsakey-asn1.h
# #
# PKCS#7 message handling # PKCS#7 message handling

View File

@@ -86,25 +86,25 @@ int mscode_note_digest_algo(void *context, size_t hdrlen,
oid = look_up_OID(value, vlen); oid = look_up_OID(value, vlen);
switch (oid) { switch (oid) {
case OID_md4: case OID_md4:
ctx->digest_algo = HASH_ALGO_MD4; ctx->digest_algo = "md4";
break; break;
case OID_md5: case OID_md5:
ctx->digest_algo = HASH_ALGO_MD5; ctx->digest_algo = "md5";
break; break;
case OID_sha1: case OID_sha1:
ctx->digest_algo = HASH_ALGO_SHA1; ctx->digest_algo = "sha1";
break; break;
case OID_sha256: case OID_sha256:
ctx->digest_algo = HASH_ALGO_SHA256; ctx->digest_algo = "sha256";
break; break;
case OID_sha384: case OID_sha384:
ctx->digest_algo = HASH_ALGO_SHA384; ctx->digest_algo = "sha384";
break; break;
case OID_sha512: case OID_sha512:
ctx->digest_algo = HASH_ALGO_SHA512; ctx->digest_algo = "sha512";
break; break;
case OID_sha224: case OID_sha224:
ctx->digest_algo = HASH_ALGO_SHA224; ctx->digest_algo = "sha224";
break; break;
case OID__NR: case OID__NR:

View File

@@ -15,7 +15,7 @@
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/err.h> #include <linux/err.h>
#include <linux/oid_registry.h> #include <linux/oid_registry.h>
#include "public_key.h" #include <crypto/public_key.h>
#include "pkcs7_parser.h" #include "pkcs7_parser.h"
#include "pkcs7-asn1.h" #include "pkcs7-asn1.h"
@@ -44,7 +44,7 @@ struct pkcs7_parse_context {
static void pkcs7_free_signed_info(struct pkcs7_signed_info *sinfo) static void pkcs7_free_signed_info(struct pkcs7_signed_info *sinfo)
{ {
if (sinfo) { if (sinfo) {
mpi_free(sinfo->sig.mpi[0]); kfree(sinfo->sig.s);
kfree(sinfo->sig.digest); kfree(sinfo->sig.digest);
kfree(sinfo->signing_cert_id); kfree(sinfo->signing_cert_id);
kfree(sinfo); kfree(sinfo);
@@ -87,7 +87,7 @@ EXPORT_SYMBOL_GPL(pkcs7_free_message);
static int pkcs7_check_authattrs(struct pkcs7_message *msg) static int pkcs7_check_authattrs(struct pkcs7_message *msg)
{ {
struct pkcs7_signed_info *sinfo; struct pkcs7_signed_info *sinfo;
bool want; bool want = false;
sinfo = msg->signed_infos; sinfo = msg->signed_infos;
if (sinfo->authattrs) { if (sinfo->authattrs) {
@@ -218,25 +218,25 @@ int pkcs7_sig_note_digest_algo(void *context, size_t hdrlen,
switch (ctx->last_oid) { switch (ctx->last_oid) {
case OID_md4: case OID_md4:
ctx->sinfo->sig.pkey_hash_algo = HASH_ALGO_MD4; ctx->sinfo->sig.hash_algo = "md4";
break; break;
case OID_md5: case OID_md5:
ctx->sinfo->sig.pkey_hash_algo = HASH_ALGO_MD5; ctx->sinfo->sig.hash_algo = "md5";
break; break;
case OID_sha1: case OID_sha1:
ctx->sinfo->sig.pkey_hash_algo = HASH_ALGO_SHA1; ctx->sinfo->sig.hash_algo = "sha1";
break; break;
case OID_sha256: case OID_sha256:
ctx->sinfo->sig.pkey_hash_algo = HASH_ALGO_SHA256; ctx->sinfo->sig.hash_algo = "sha256";
break; break;
case OID_sha384: case OID_sha384:
ctx->sinfo->sig.pkey_hash_algo = HASH_ALGO_SHA384; ctx->sinfo->sig.hash_algo = "sha384";
break; break;
case OID_sha512: case OID_sha512:
ctx->sinfo->sig.pkey_hash_algo = HASH_ALGO_SHA512; ctx->sinfo->sig.hash_algo = "sha512";
break; break;
case OID_sha224: case OID_sha224:
ctx->sinfo->sig.pkey_hash_algo = HASH_ALGO_SHA224; ctx->sinfo->sig.hash_algo = "sha224";
default: default:
printk("Unsupported digest algo: %u\n", ctx->last_oid); printk("Unsupported digest algo: %u\n", ctx->last_oid);
return -ENOPKG; return -ENOPKG;
@@ -255,7 +255,7 @@ int pkcs7_sig_note_pkey_algo(void *context, size_t hdrlen,
switch (ctx->last_oid) { switch (ctx->last_oid) {
case OID_rsaEncryption: case OID_rsaEncryption:
ctx->sinfo->sig.pkey_algo = PKEY_ALGO_RSA; ctx->sinfo->sig.pkey_algo = "rsa";
break; break;
default: default:
printk("Unsupported pkey algo: %u\n", ctx->last_oid); printk("Unsupported pkey algo: %u\n", ctx->last_oid);
@@ -614,16 +614,12 @@ int pkcs7_sig_note_signature(void *context, size_t hdrlen,
const void *value, size_t vlen) const void *value, size_t vlen)
{ {
struct pkcs7_parse_context *ctx = context; struct pkcs7_parse_context *ctx = context;
MPI mpi;
BUG_ON(ctx->sinfo->sig.pkey_algo != PKEY_ALGO_RSA); ctx->sinfo->sig.s = kmemdup(value, vlen, GFP_KERNEL);
if (!ctx->sinfo->sig.s)
mpi = mpi_read_raw_data(value, vlen);
if (!mpi)
return -ENOMEM; return -ENOMEM;
ctx->sinfo->sig.mpi[0] = mpi; ctx->sinfo->sig.s_size = vlen;
ctx->sinfo->sig.nr_mpi = 1;
return 0; return 0;
} }

View File

@@ -17,7 +17,7 @@
#include <linux/asn1.h> #include <linux/asn1.h>
#include <linux/key.h> #include <linux/key.h>
#include <keys/asymmetric-type.h> #include <keys/asymmetric-type.h>
#include "public_key.h" #include <crypto/public_key.h>
#include "pkcs7_parser.h" #include "pkcs7_parser.h"
/** /**

View File

@@ -16,7 +16,7 @@
#include <linux/err.h> #include <linux/err.h>
#include <linux/asn1.h> #include <linux/asn1.h>
#include <crypto/hash.h> #include <crypto/hash.h>
#include "public_key.h" #include <crypto/public_key.h>
#include "pkcs7_parser.h" #include "pkcs7_parser.h"
/* /*
@@ -31,17 +31,15 @@ static int pkcs7_digest(struct pkcs7_message *pkcs7,
void *digest; void *digest;
int ret; int ret;
kenter(",%u,%u", sinfo->index, sinfo->sig.pkey_hash_algo); kenter(",%u,%s", sinfo->index, sinfo->sig.hash_algo);
if (sinfo->sig.pkey_hash_algo >= PKEY_HASH__LAST || if (!sinfo->sig.hash_algo)
!hash_algo_name[sinfo->sig.pkey_hash_algo])
return -ENOPKG; return -ENOPKG;
/* Allocate the hashing algorithm we're going to need and find out how /* Allocate the hashing algorithm we're going to need and find out how
* big the hash operational data will be. * big the hash operational data will be.
*/ */
tfm = crypto_alloc_shash(hash_algo_name[sinfo->sig.pkey_hash_algo], tfm = crypto_alloc_shash(sinfo->sig.hash_algo, 0, 0);
0, 0);
if (IS_ERR(tfm)) if (IS_ERR(tfm))
return (PTR_ERR(tfm) == -ENOENT) ? -ENOPKG : PTR_ERR(tfm); return (PTR_ERR(tfm) == -ENOENT) ? -ENOPKG : PTR_ERR(tfm);

View File

@@ -17,32 +17,13 @@
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/seq_file.h> #include <linux/seq_file.h>
#include <linux/scatterlist.h>
#include <keys/asymmetric-subtype.h> #include <keys/asymmetric-subtype.h>
#include "public_key.h" #include <crypto/public_key.h>
#include <crypto/akcipher.h>
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
const char *const pkey_algo_name[PKEY_ALGO__LAST] = {
[PKEY_ALGO_DSA] = "DSA",
[PKEY_ALGO_RSA] = "RSA",
};
EXPORT_SYMBOL_GPL(pkey_algo_name);
const struct public_key_algorithm *pkey_algo[PKEY_ALGO__LAST] = {
#if defined(CONFIG_PUBLIC_KEY_ALGO_RSA) || \
defined(CONFIG_PUBLIC_KEY_ALGO_RSA_MODULE)
[PKEY_ALGO_RSA] = &RSA_public_key_algorithm,
#endif
};
EXPORT_SYMBOL_GPL(pkey_algo);
const char *const pkey_id_type_name[PKEY_ID_TYPE__LAST] = {
[PKEY_ID_PGP] = "PGP",
[PKEY_ID_X509] = "X509",
[PKEY_ID_PKCS7] = "PKCS#7",
};
EXPORT_SYMBOL_GPL(pkey_id_type_name);
/* /*
* Provide a part of a description of the key for /proc/keys. * Provide a part of a description of the key for /proc/keys.
*/ */
@@ -52,8 +33,7 @@ static void public_key_describe(const struct key *asymmetric_key,
struct public_key *key = asymmetric_key->payload.data[asym_crypto]; struct public_key *key = asymmetric_key->payload.data[asym_crypto];
if (key) if (key)
seq_printf(m, "%s.%s", seq_printf(m, "%s.%s", key->id_type, key->pkey_algo);
pkey_id_type_name[key->id_type], key->algo->name);
} }
/* /*
@@ -62,50 +42,116 @@ static void public_key_describe(const struct key *asymmetric_key,
void public_key_destroy(void *payload) void public_key_destroy(void *payload)
{ {
struct public_key *key = payload; struct public_key *key = payload;
int i;
if (key) { if (key)
for (i = 0; i < ARRAY_SIZE(key->mpi); i++) kfree(key->key);
mpi_free(key->mpi[i]); kfree(key);
kfree(key);
}
} }
EXPORT_SYMBOL_GPL(public_key_destroy); EXPORT_SYMBOL_GPL(public_key_destroy);
struct public_key_completion {
struct completion completion;
int err;
};
static void public_key_verify_done(struct crypto_async_request *req, int err)
{
struct public_key_completion *compl = req->data;
if (err == -EINPROGRESS)
return;
compl->err = err;
complete(&compl->completion);
}
/* /*
* Verify a signature using a public key. * Verify a signature using a public key.
*/ */
int public_key_verify_signature(const struct public_key *pk, int public_key_verify_signature(const struct public_key *pkey,
const struct public_key_signature *sig) const struct public_key_signature *sig)
{ {
const struct public_key_algorithm *algo; struct public_key_completion compl;
struct crypto_akcipher *tfm;
struct akcipher_request *req;
struct scatterlist sig_sg, digest_sg;
const char *alg_name;
char alg_name_buf[CRYPTO_MAX_ALG_NAME];
void *output;
unsigned int outlen;
int ret = -ENOMEM;
BUG_ON(!pk); pr_devel("==>%s()\n", __func__);
BUG_ON(!pk->mpi[0]);
BUG_ON(!pk->mpi[1]); BUG_ON(!pkey);
BUG_ON(!sig); BUG_ON(!sig);
BUG_ON(!sig->digest); BUG_ON(!sig->digest);
BUG_ON(!sig->mpi[0]); BUG_ON(!sig->s);
algo = pk->algo; alg_name = sig->pkey_algo;
if (!algo) { if (strcmp(sig->pkey_algo, "rsa") == 0) {
if (pk->pkey_algo >= PKEY_ALGO__LAST) /* The data wangled by the RSA algorithm is typically padded
return -ENOPKG; * and encoded in some manner, such as EMSA-PKCS1-1_5 [RFC3447
algo = pkey_algo[pk->pkey_algo]; * sec 8.2].
if (!algo) */
return -ENOPKG; if (snprintf(alg_name_buf, CRYPTO_MAX_ALG_NAME,
"pkcs1pad(rsa,%s)", sig->hash_algo
) >= CRYPTO_MAX_ALG_NAME)
return -EINVAL;
alg_name = alg_name_buf;
} }
if (!algo->verify_signature) tfm = crypto_alloc_akcipher(alg_name, 0, 0);
return -ENOTSUPP; if (IS_ERR(tfm))
return PTR_ERR(tfm);
if (sig->nr_mpi != algo->n_sig_mpi) { req = akcipher_request_alloc(tfm, GFP_KERNEL);
pr_debug("Signature has %u MPI not %u\n", if (!req)
sig->nr_mpi, algo->n_sig_mpi); goto error_free_tfm;
return -EINVAL;
ret = crypto_akcipher_set_pub_key(tfm, pkey->key, pkey->keylen);
if (ret)
goto error_free_req;
outlen = crypto_akcipher_maxsize(tfm);
output = kmalloc(outlen, GFP_KERNEL);
if (!output)
goto error_free_req;
sg_init_one(&sig_sg, sig->s, sig->s_size);
sg_init_one(&digest_sg, output, outlen);
akcipher_request_set_crypt(req, &sig_sg, &digest_sg, sig->s_size,
outlen);
init_completion(&compl.completion);
akcipher_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG |
CRYPTO_TFM_REQ_MAY_SLEEP,
public_key_verify_done, &compl);
/* Perform the verification calculation. This doesn't actually do the
* verification, but rather calculates the hash expected by the
* signature and returns that to us.
*/
ret = crypto_akcipher_verify(req);
if (ret == -EINPROGRESS) {
wait_for_completion(&compl.completion);
ret = compl.err;
} }
if (ret < 0)
goto out_free_output;
return algo->verify_signature(pk, sig); /* Do the actual verification step. */
if (req->dst_len != sig->digest_size ||
memcmp(sig->digest, output, sig->digest_size) != 0)
ret = -EKEYREJECTED;
out_free_output:
kfree(output);
error_free_req:
akcipher_request_free(req);
error_free_tfm:
crypto_free_akcipher(tfm);
pr_devel("<==%s() = %d\n", __func__, ret);
return ret;
} }
EXPORT_SYMBOL_GPL(public_key_verify_signature); EXPORT_SYMBOL_GPL(public_key_verify_signature);

View File

@@ -1,36 +0,0 @@
/* Public key algorithm internals
*
* See Documentation/crypto/asymmetric-keys.txt
*
* 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 <crypto/public_key.h>
extern struct asymmetric_key_subtype public_key_subtype;
/*
* Public key algorithm definition.
*/
struct public_key_algorithm {
const char *name;
u8 n_pub_mpi; /* Number of MPIs in public key */
u8 n_sec_mpi; /* Number of MPIs in secret key */
u8 n_sig_mpi; /* Number of MPIs in a signature */
int (*verify_signature)(const struct public_key *key,
const struct public_key_signature *sig);
};
extern const struct public_key_algorithm RSA_public_key_algorithm;
/*
* public_key.c
*/
extern int public_key_verify_signature(const struct public_key *pk,
const struct public_key_signature *sig);

View File

@@ -1,278 +0,0 @@
/* RSA asymmetric public-key algorithm [RFC3447]
*
* 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) "RSA: "fmt
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/slab.h>
#include <crypto/algapi.h>
#include "public_key.h"
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("RSA Public Key Algorithm");
#define kenter(FMT, ...) \
pr_devel("==> %s("FMT")\n", __func__, ##__VA_ARGS__)
#define kleave(FMT, ...) \
pr_devel("<== %s()"FMT"\n", __func__, ##__VA_ARGS__)
/*
* Hash algorithm OIDs plus ASN.1 DER wrappings [RFC4880 sec 5.2.2].
*/
static const u8 RSA_digest_info_MD5[] = {
0x30, 0x20, 0x30, 0x0C, 0x06, 0x08,
0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x02, 0x05, /* OID */
0x05, 0x00, 0x04, 0x10
};
static const u8 RSA_digest_info_SHA1[] = {
0x30, 0x21, 0x30, 0x09, 0x06, 0x05,
0x2B, 0x0E, 0x03, 0x02, 0x1A,
0x05, 0x00, 0x04, 0x14
};
static const u8 RSA_digest_info_RIPE_MD_160[] = {
0x30, 0x21, 0x30, 0x09, 0x06, 0x05,
0x2B, 0x24, 0x03, 0x02, 0x01,
0x05, 0x00, 0x04, 0x14
};
static const u8 RSA_digest_info_SHA224[] = {
0x30, 0x2d, 0x30, 0x0d, 0x06, 0x09,
0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x04,
0x05, 0x00, 0x04, 0x1C
};
static const u8 RSA_digest_info_SHA256[] = {
0x30, 0x31, 0x30, 0x0d, 0x06, 0x09,
0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01,
0x05, 0x00, 0x04, 0x20
};
static const u8 RSA_digest_info_SHA384[] = {
0x30, 0x41, 0x30, 0x0d, 0x06, 0x09,
0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02,
0x05, 0x00, 0x04, 0x30
};
static const u8 RSA_digest_info_SHA512[] = {
0x30, 0x51, 0x30, 0x0d, 0x06, 0x09,
0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03,
0x05, 0x00, 0x04, 0x40
};
static const struct {
const u8 *data;
size_t size;
} RSA_ASN1_templates[PKEY_HASH__LAST] = {
#define _(X) { RSA_digest_info_##X, sizeof(RSA_digest_info_##X) }
[HASH_ALGO_MD5] = _(MD5),
[HASH_ALGO_SHA1] = _(SHA1),
[HASH_ALGO_RIPE_MD_160] = _(RIPE_MD_160),
[HASH_ALGO_SHA256] = _(SHA256),
[HASH_ALGO_SHA384] = _(SHA384),
[HASH_ALGO_SHA512] = _(SHA512),
[HASH_ALGO_SHA224] = _(SHA224),
#undef _
};
/*
* RSAVP1() function [RFC3447 sec 5.2.2]
*/
static int RSAVP1(const struct public_key *key, MPI s, MPI *_m)
{
MPI m;
int ret;
/* (1) Validate 0 <= s < n */
if (mpi_cmp_ui(s, 0) < 0) {
kleave(" = -EBADMSG [s < 0]");
return -EBADMSG;
}
if (mpi_cmp(s, key->rsa.n) >= 0) {
kleave(" = -EBADMSG [s >= n]");
return -EBADMSG;
}
m = mpi_alloc(0);
if (!m)
return -ENOMEM;
/* (2) m = s^e mod n */
ret = mpi_powm(m, s, key->rsa.e, key->rsa.n);
if (ret < 0) {
mpi_free(m);
return ret;
}
*_m = m;
return 0;
}
/*
* Integer to Octet String conversion [RFC3447 sec 4.1]
*/
static int RSA_I2OSP(MPI x, size_t xLen, u8 **pX)
{
unsigned X_size, x_size;
int X_sign;
u8 *X;
/* Make sure the string is the right length. The number should begin
* with { 0x00, 0x01, ... } so we have to account for 15 leading zero
* bits not being reported by MPI.
*/
x_size = mpi_get_nbits(x);
pr_devel("size(x)=%u xLen*8=%zu\n", x_size, xLen * 8);
if (x_size != xLen * 8 - 15)
return -ERANGE;
X = mpi_get_buffer(x, &X_size, &X_sign);
if (!X)
return -ENOMEM;
if (X_sign < 0) {
kfree(X);
return -EBADMSG;
}
if (X_size != xLen - 1) {
kfree(X);
return -EBADMSG;
}
*pX = X;
return 0;
}
/*
* Perform the RSA signature verification.
* @H: Value of hash of data and metadata
* @EM: The computed signature value
* @k: The size of EM (EM[0] is an invalid location but should hold 0x00)
* @hash_size: The size of H
* @asn1_template: The DigestInfo ASN.1 template
* @asn1_size: Size of asm1_template[]
*/
static int RSA_verify(const u8 *H, const u8 *EM, size_t k, size_t hash_size,
const u8 *asn1_template, size_t asn1_size)
{
unsigned PS_end, T_offset, i;
kenter(",,%zu,%zu,%zu", k, hash_size, asn1_size);
if (k < 2 + 1 + asn1_size + hash_size)
return -EBADMSG;
/* Decode the EMSA-PKCS1-v1_5 */
if (EM[1] != 0x01) {
kleave(" = -EBADMSG [EM[1] == %02u]", EM[1]);
return -EBADMSG;
}
T_offset = k - (asn1_size + hash_size);
PS_end = T_offset - 1;
if (EM[PS_end] != 0x00) {
kleave(" = -EBADMSG [EM[T-1] == %02u]", EM[PS_end]);
return -EBADMSG;
}
for (i = 2; i < PS_end; i++) {
if (EM[i] != 0xff) {
kleave(" = -EBADMSG [EM[PS%x] == %02u]", i - 2, EM[i]);
return -EBADMSG;
}
}
if (crypto_memneq(asn1_template, EM + T_offset, asn1_size) != 0) {
kleave(" = -EBADMSG [EM[T] ASN.1 mismatch]");
return -EBADMSG;
}
if (crypto_memneq(H, EM + T_offset + asn1_size, hash_size) != 0) {
kleave(" = -EKEYREJECTED [EM[T] hash mismatch]");
return -EKEYREJECTED;
}
kleave(" = 0");
return 0;
}
/*
* Perform the verification step [RFC3447 sec 8.2.2].
*/
static int RSA_verify_signature(const struct public_key *key,
const struct public_key_signature *sig)
{
size_t tsize;
int ret;
/* Variables as per RFC3447 sec 8.2.2 */
const u8 *H = sig->digest;
u8 *EM = NULL;
MPI m = NULL;
size_t k;
kenter("");
if (!RSA_ASN1_templates[sig->pkey_hash_algo].data)
return -ENOTSUPP;
/* (1) Check the signature size against the public key modulus size */
k = mpi_get_nbits(key->rsa.n);
tsize = mpi_get_nbits(sig->rsa.s);
/* According to RFC 4880 sec 3.2, length of MPI is computed starting
* from most significant bit. So the RFC 3447 sec 8.2.2 size check
* must be relaxed to conform with shorter signatures - so we fail here
* only if signature length is longer than modulus size.
*/
pr_devel("step 1: k=%zu size(S)=%zu\n", k, tsize);
if (k < tsize) {
ret = -EBADMSG;
goto error;
}
/* Round up and convert to octets */
k = (k + 7) / 8;
/* (2b) Apply the RSAVP1 verification primitive to the public key */
ret = RSAVP1(key, sig->rsa.s, &m);
if (ret < 0)
goto error;
/* (2c) Convert the message representative (m) to an encoded message
* (EM) of length k octets.
*
* NOTE! The leading zero byte is suppressed by MPI, so we pass a
* pointer to the _preceding_ byte to RSA_verify()!
*/
ret = RSA_I2OSP(m, k, &EM);
if (ret < 0)
goto error;
ret = RSA_verify(H, EM - 1, k, sig->digest_size,
RSA_ASN1_templates[sig->pkey_hash_algo].data,
RSA_ASN1_templates[sig->pkey_hash_algo].size);
error:
kfree(EM);
mpi_free(m);
kleave(" = %d", ret);
return ret;
}
const struct public_key_algorithm RSA_public_key_algorithm = {
.name = "RSA",
.n_pub_mpi = 2,
.n_sec_mpi = 3,
.n_sig_mpi = 1,
.verify_signature = RSA_verify_signature,
};
EXPORT_SYMBOL_GPL(RSA_public_key_algorithm);

View File

@@ -328,12 +328,12 @@ static int pefile_digest_pe(const void *pebuf, unsigned int pelen,
void *digest; void *digest;
int ret; int ret;
kenter(",%u", ctx->digest_algo); kenter(",%s", ctx->digest_algo);
/* Allocate the hashing algorithm we're going to need and find out how /* Allocate the hashing algorithm we're going to need and find out how
* big the hash operational data will be. * big the hash operational data will be.
*/ */
tfm = crypto_alloc_shash(hash_algo_name[ctx->digest_algo], 0, 0); tfm = crypto_alloc_shash(ctx->digest_algo, 0, 0);
if (IS_ERR(tfm)) if (IS_ERR(tfm))
return (PTR_ERR(tfm) == -ENOENT) ? -ENOPKG : PTR_ERR(tfm); return (PTR_ERR(tfm) == -ENOENT) ? -ENOPKG : PTR_ERR(tfm);

View File

@@ -28,7 +28,7 @@ struct pefile_context {
/* PKCS#7 MS Individual Code Signing content */ /* PKCS#7 MS Individual Code Signing content */
const void *digest; /* Digest */ const void *digest; /* Digest */
unsigned digest_len; /* Digest length */ unsigned digest_len; /* Digest length */
enum hash_algo digest_algo; /* Digest algorithm */ const char *digest_algo; /* Digest algorithm */
}; };
#define kenter(FMT, ...) \ #define kenter(FMT, ...) \

View File

@@ -15,11 +15,10 @@
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/err.h> #include <linux/err.h>
#include <linux/oid_registry.h> #include <linux/oid_registry.h>
#include "public_key.h" #include <crypto/public_key.h>
#include "x509_parser.h" #include "x509_parser.h"
#include "x509-asn1.h" #include "x509-asn1.h"
#include "x509_akid-asn1.h" #include "x509_akid-asn1.h"
#include "x509_rsakey-asn1.h"
struct x509_parse_context { struct x509_parse_context {
struct x509_certificate *cert; /* Certificate being constructed */ struct x509_certificate *cert; /* Certificate being constructed */
@@ -56,7 +55,7 @@ void x509_free_certificate(struct x509_certificate *cert)
kfree(cert->akid_id); kfree(cert->akid_id);
kfree(cert->akid_skid); kfree(cert->akid_skid);
kfree(cert->sig.digest); kfree(cert->sig.digest);
mpi_free(cert->sig.rsa.s); kfree(cert->sig.s);
kfree(cert); kfree(cert);
} }
} }
@@ -103,12 +102,12 @@ struct x509_certificate *x509_cert_parse(const void *data, size_t datalen)
} }
} }
/* Decode the public key */ cert->pub->key = kmemdup(ctx->key, ctx->key_size, GFP_KERNEL);
ret = asn1_ber_decoder(&x509_rsakey_decoder, ctx, if (!cert->pub->key)
ctx->key, ctx->key_size);
if (ret < 0)
goto error_decode; goto error_decode;
cert->pub->keylen = ctx->key_size;
/* Generate cert issuer + serial number key ID */ /* Generate cert issuer + serial number key ID */
kid = asymmetric_key_generate_id(cert->raw_serial, kid = asymmetric_key_generate_id(cert->raw_serial,
cert->raw_serial_size, cert->raw_serial_size,
@@ -124,6 +123,7 @@ struct x509_certificate *x509_cert_parse(const void *data, size_t datalen)
return cert; return cert;
error_decode: error_decode:
kfree(cert->pub->key);
kfree(ctx); kfree(ctx);
error_no_ctx: error_no_ctx:
x509_free_certificate(cert); x509_free_certificate(cert);
@@ -188,33 +188,33 @@ int x509_note_pkey_algo(void *context, size_t hdrlen,
return -ENOPKG; /* Unsupported combination */ return -ENOPKG; /* Unsupported combination */
case OID_md4WithRSAEncryption: case OID_md4WithRSAEncryption:
ctx->cert->sig.pkey_hash_algo = HASH_ALGO_MD5; ctx->cert->sig.hash_algo = "md4";
ctx->cert->sig.pkey_algo = PKEY_ALGO_RSA; ctx->cert->sig.pkey_algo = "rsa";
break; break;
case OID_sha1WithRSAEncryption: case OID_sha1WithRSAEncryption:
ctx->cert->sig.pkey_hash_algo = HASH_ALGO_SHA1; ctx->cert->sig.hash_algo = "sha1";
ctx->cert->sig.pkey_algo = PKEY_ALGO_RSA; ctx->cert->sig.pkey_algo = "rsa";
break; break;
case OID_sha256WithRSAEncryption: case OID_sha256WithRSAEncryption:
ctx->cert->sig.pkey_hash_algo = HASH_ALGO_SHA256; ctx->cert->sig.hash_algo = "sha256";
ctx->cert->sig.pkey_algo = PKEY_ALGO_RSA; ctx->cert->sig.pkey_algo = "rsa";
break; break;
case OID_sha384WithRSAEncryption: case OID_sha384WithRSAEncryption:
ctx->cert->sig.pkey_hash_algo = HASH_ALGO_SHA384; ctx->cert->sig.hash_algo = "sha384";
ctx->cert->sig.pkey_algo = PKEY_ALGO_RSA; ctx->cert->sig.pkey_algo = "rsa";
break; break;
case OID_sha512WithRSAEncryption: case OID_sha512WithRSAEncryption:
ctx->cert->sig.pkey_hash_algo = HASH_ALGO_SHA512; ctx->cert->sig.hash_algo = "sha512";
ctx->cert->sig.pkey_algo = PKEY_ALGO_RSA; ctx->cert->sig.pkey_algo = "rsa";
break; break;
case OID_sha224WithRSAEncryption: case OID_sha224WithRSAEncryption:
ctx->cert->sig.pkey_hash_algo = HASH_ALGO_SHA224; ctx->cert->sig.hash_algo = "sha224";
ctx->cert->sig.pkey_algo = PKEY_ALGO_RSA; ctx->cert->sig.pkey_algo = "rsa";
break; break;
} }
@@ -396,7 +396,7 @@ int x509_extract_key_data(void *context, size_t hdrlen,
if (ctx->last_oid != OID_rsaEncryption) if (ctx->last_oid != OID_rsaEncryption)
return -ENOPKG; return -ENOPKG;
ctx->cert->pub->pkey_algo = PKEY_ALGO_RSA; ctx->cert->pub->pkey_algo = "rsa";
/* Discard the BIT STRING metadata */ /* Discard the BIT STRING metadata */
ctx->key = value + 1; ctx->key = value + 1;
@@ -404,29 +404,6 @@ int x509_extract_key_data(void *context, size_t hdrlen,
return 0; return 0;
} }
/*
* Extract a RSA public key value
*/
int rsa_extract_mpi(void *context, size_t hdrlen,
unsigned char tag,
const void *value, size_t vlen)
{
struct x509_parse_context *ctx = context;
MPI mpi;
if (ctx->nr_mpi >= ARRAY_SIZE(ctx->cert->pub->mpi)) {
pr_err("Too many public key MPIs in certificate\n");
return -EBADMSG;
}
mpi = mpi_read_raw_data(value, vlen);
if (!mpi)
return -ENOMEM;
ctx->cert->pub->mpi[ctx->nr_mpi++] = mpi;
return 0;
}
/* The keyIdentifier in AuthorityKeyIdentifier SEQUENCE is tag(CONT,PRIM,0) */ /* The keyIdentifier in AuthorityKeyIdentifier SEQUENCE is tag(CONT,PRIM,0) */
#define SEQ_TAG_KEYID (ASN1_CONT << 6) #define SEQ_TAG_KEYID (ASN1_CONT << 6)
@@ -494,7 +471,7 @@ int x509_decode_time(time64_t *_t, size_t hdrlen,
unsigned char tag, unsigned char tag,
const unsigned char *value, size_t vlen) const unsigned char *value, size_t vlen)
{ {
static const unsigned char month_lengths[] = { 31, 29, 31, 30, 31, 30, static const unsigned char month_lengths[] = { 31, 28, 31, 30, 31, 30,
31, 31, 30, 31, 30, 31 }; 31, 31, 30, 31, 30, 31 };
const unsigned char *p = value; const unsigned char *p = value;
unsigned year, mon, day, hour, min, sec, mon_len; unsigned year, mon, day, hour, min, sec, mon_len;
@@ -540,17 +517,17 @@ int x509_decode_time(time64_t *_t, size_t hdrlen,
if (year % 4 == 0) { if (year % 4 == 0) {
mon_len = 29; mon_len = 29;
if (year % 100 == 0) { if (year % 100 == 0) {
year /= 100; mon_len = 28;
if (year % 4 != 0) if (year % 400 == 0)
mon_len = 28; mon_len = 29;
} }
} }
} }
if (day < 1 || day > mon_len || if (day < 1 || day > mon_len ||
hour > 23 || hour > 24 || /* ISO 8601 permits 24:00:00 as midnight tomorrow */
min > 59 || min > 59 ||
sec > 59) sec > 60) /* ISO 8601 permits leap seconds [X.680 46.3] */
goto invalid_time; goto invalid_time;
*_t = mktime64(year, mon, day, hour, min, sec); *_t = mktime64(year, mon, day, hour, min, sec);

View File

@@ -13,15 +13,11 @@
#include <linux/module.h> #include <linux/module.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/err.h>
#include <linux/mpi.h>
#include <linux/asn1_decoder.h>
#include <keys/asymmetric-subtype.h> #include <keys/asymmetric-subtype.h>
#include <keys/asymmetric-parser.h> #include <keys/asymmetric-parser.h>
#include <keys/system_keyring.h> #include <keys/system_keyring.h>
#include <crypto/hash.h> #include <crypto/hash.h>
#include "asymmetric_keys.h" #include "asymmetric_keys.h"
#include "public_key.h"
#include "x509_parser.h" #include "x509_parser.h"
static bool use_builtin_keys; static bool use_builtin_keys;
@@ -167,18 +163,20 @@ int x509_get_sig_params(struct x509_certificate *cert)
if (cert->unsupported_crypto) if (cert->unsupported_crypto)
return -ENOPKG; return -ENOPKG;
if (cert->sig.rsa.s) if (cert->sig.s)
return 0; return 0;
cert->sig.rsa.s = mpi_read_raw_data(cert->raw_sig, cert->raw_sig_size); cert->sig.s = kmemdup(cert->raw_sig, cert->raw_sig_size,
if (!cert->sig.rsa.s) GFP_KERNEL);
if (!cert->sig.s)
return -ENOMEM; return -ENOMEM;
cert->sig.nr_mpi = 1;
cert->sig.s_size = cert->raw_sig_size;
/* Allocate the hashing algorithm we're going to need and find out how /* Allocate the hashing algorithm we're going to need and find out how
* big the hash operational data will be. * big the hash operational data will be.
*/ */
tfm = crypto_alloc_shash(hash_algo_name[cert->sig.pkey_hash_algo], 0, 0); tfm = crypto_alloc_shash(cert->sig.hash_algo, 0, 0);
if (IS_ERR(tfm)) { if (IS_ERR(tfm)) {
if (PTR_ERR(tfm) == -ENOENT) { if (PTR_ERR(tfm) == -ENOENT) {
cert->unsupported_crypto = true; cert->unsupported_crypto = true;
@@ -293,24 +291,20 @@ static int x509_key_preparse(struct key_preparsed_payload *prep)
pr_devel("Cert Issuer: %s\n", cert->issuer); pr_devel("Cert Issuer: %s\n", cert->issuer);
pr_devel("Cert Subject: %s\n", cert->subject); pr_devel("Cert Subject: %s\n", cert->subject);
if (cert->pub->pkey_algo >= PKEY_ALGO__LAST || if (!cert->pub->pkey_algo ||
cert->sig.pkey_algo >= PKEY_ALGO__LAST || !cert->sig.pkey_algo ||
cert->sig.pkey_hash_algo >= PKEY_HASH__LAST || !cert->sig.hash_algo) {
!pkey_algo[cert->pub->pkey_algo] ||
!pkey_algo[cert->sig.pkey_algo] ||
!hash_algo_name[cert->sig.pkey_hash_algo]) {
ret = -ENOPKG; ret = -ENOPKG;
goto error_free_cert; goto error_free_cert;
} }
pr_devel("Cert Key Algo: %s\n", pkey_algo_name[cert->pub->pkey_algo]); pr_devel("Cert Key Algo: %s\n", cert->pub->pkey_algo);
pr_devel("Cert Valid period: %lld-%lld\n", cert->valid_from, cert->valid_to); pr_devel("Cert Valid period: %lld-%lld\n", cert->valid_from, cert->valid_to);
pr_devel("Cert Signature: %s + %s\n", pr_devel("Cert Signature: %s + %s\n",
pkey_algo_name[cert->sig.pkey_algo], cert->sig.pkey_algo,
hash_algo_name[cert->sig.pkey_hash_algo]); cert->sig.hash_algo);
cert->pub->algo = pkey_algo[cert->pub->pkey_algo]; cert->pub->id_type = "X509";
cert->pub->id_type = PKEY_ID_X509;
/* Check the signature on the key if it appears to be self-signed */ /* Check the signature on the key if it appears to be self-signed */
if ((!cert->akid_skid && !cert->akid_id) || if ((!cert->akid_skid && !cert->akid_id) ||

View File

@@ -1,4 +0,0 @@
RSAPublicKey ::= SEQUENCE {
modulus INTEGER ({ rsa_extract_mpi }), -- n
publicExponent INTEGER ({ rsa_extract_mpi }) -- e
}

View File

@@ -18,12 +18,89 @@
#include <linux/module.h> #include <linux/module.h>
#include <linux/random.h> #include <linux/random.h>
/*
* Hash algorithm OIDs plus ASN.1 DER wrappings [RFC4880 sec 5.2.2].
*/
static const u8 rsa_digest_info_md5[] = {
0x30, 0x20, 0x30, 0x0c, 0x06, 0x08,
0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x02, 0x05, /* OID */
0x05, 0x00, 0x04, 0x10
};
static const u8 rsa_digest_info_sha1[] = {
0x30, 0x21, 0x30, 0x09, 0x06, 0x05,
0x2b, 0x0e, 0x03, 0x02, 0x1a,
0x05, 0x00, 0x04, 0x14
};
static const u8 rsa_digest_info_rmd160[] = {
0x30, 0x21, 0x30, 0x09, 0x06, 0x05,
0x2b, 0x24, 0x03, 0x02, 0x01,
0x05, 0x00, 0x04, 0x14
};
static const u8 rsa_digest_info_sha224[] = {
0x30, 0x2d, 0x30, 0x0d, 0x06, 0x09,
0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x04,
0x05, 0x00, 0x04, 0x1c
};
static const u8 rsa_digest_info_sha256[] = {
0x30, 0x31, 0x30, 0x0d, 0x06, 0x09,
0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01,
0x05, 0x00, 0x04, 0x20
};
static const u8 rsa_digest_info_sha384[] = {
0x30, 0x41, 0x30, 0x0d, 0x06, 0x09,
0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02,
0x05, 0x00, 0x04, 0x30
};
static const u8 rsa_digest_info_sha512[] = {
0x30, 0x51, 0x30, 0x0d, 0x06, 0x09,
0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03,
0x05, 0x00, 0x04, 0x40
};
static const struct rsa_asn1_template {
const char *name;
const u8 *data;
size_t size;
} rsa_asn1_templates[] = {
#define _(X) { #X, rsa_digest_info_##X, sizeof(rsa_digest_info_##X) }
_(md5),
_(sha1),
_(rmd160),
_(sha256),
_(sha384),
_(sha512),
_(sha224),
{ NULL }
#undef _
};
static const struct rsa_asn1_template *rsa_lookup_asn1(const char *name)
{
const struct rsa_asn1_template *p;
for (p = rsa_asn1_templates; p->name; p++)
if (strcmp(name, p->name) == 0)
return p;
return NULL;
}
struct pkcs1pad_ctx { struct pkcs1pad_ctx {
struct crypto_akcipher *child; struct crypto_akcipher *child;
const char *hash_name;
unsigned int key_size; unsigned int key_size;
}; };
struct pkcs1pad_inst_ctx {
struct crypto_akcipher_spawn spawn;
const char *hash_name;
};
struct pkcs1pad_request { struct pkcs1pad_request {
struct akcipher_request child_req; struct akcipher_request child_req;
@@ -339,13 +416,22 @@ static int pkcs1pad_sign(struct akcipher_request *req)
struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req); struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req);
struct pkcs1pad_ctx *ctx = akcipher_tfm_ctx(tfm); struct pkcs1pad_ctx *ctx = akcipher_tfm_ctx(tfm);
struct pkcs1pad_request *req_ctx = akcipher_request_ctx(req); struct pkcs1pad_request *req_ctx = akcipher_request_ctx(req);
const struct rsa_asn1_template *digest_info = NULL;
int err; int err;
unsigned int ps_end; unsigned int ps_end, digest_size = 0;
if (!ctx->key_size) if (!ctx->key_size)
return -EINVAL; return -EINVAL;
if (req->src_len > ctx->key_size - 11) if (ctx->hash_name) {
digest_info = rsa_lookup_asn1(ctx->hash_name);
if (!digest_info)
return -EINVAL;
digest_size = digest_info->size;
}
if (req->src_len + digest_size > ctx->key_size - 11)
return -EOVERFLOW; return -EOVERFLOW;
if (req->dst_len < ctx->key_size) { if (req->dst_len < ctx->key_size) {
@@ -371,11 +457,16 @@ static int pkcs1pad_sign(struct akcipher_request *req)
if (!req_ctx->in_buf) if (!req_ctx->in_buf)
return -ENOMEM; return -ENOMEM;
ps_end = ctx->key_size - req->src_len - 2; ps_end = ctx->key_size - digest_size - req->src_len - 2;
req_ctx->in_buf[0] = 0x01; req_ctx->in_buf[0] = 0x01;
memset(req_ctx->in_buf + 1, 0xff, ps_end - 1); memset(req_ctx->in_buf + 1, 0xff, ps_end - 1);
req_ctx->in_buf[ps_end] = 0x00; req_ctx->in_buf[ps_end] = 0x00;
if (digest_info) {
memcpy(req_ctx->in_buf + ps_end + 1, digest_info->data,
digest_info->size);
}
pkcs1pad_sg_set_buf(req_ctx->in_sg, req_ctx->in_buf, pkcs1pad_sg_set_buf(req_ctx->in_sg, req_ctx->in_buf,
ctx->key_size - 1 - req->src_len, req->src); ctx->key_size - 1 - req->src_len, req->src);
@@ -408,6 +499,7 @@ static int pkcs1pad_verify_complete(struct akcipher_request *req, int err)
struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req); struct crypto_akcipher *tfm = crypto_akcipher_reqtfm(req);
struct pkcs1pad_ctx *ctx = akcipher_tfm_ctx(tfm); struct pkcs1pad_ctx *ctx = akcipher_tfm_ctx(tfm);
struct pkcs1pad_request *req_ctx = akcipher_request_ctx(req); struct pkcs1pad_request *req_ctx = akcipher_request_ctx(req);
const struct rsa_asn1_template *digest_info;
unsigned int pos; unsigned int pos;
if (err == -EOVERFLOW) if (err == -EOVERFLOW)
@@ -422,20 +514,33 @@ static int pkcs1pad_verify_complete(struct akcipher_request *req, int err)
goto done; goto done;
} }
if (req_ctx->out_buf[0] != 0x01) { err = -EBADMSG;
err = -EINVAL; if (req_ctx->out_buf[0] != 0x01)
goto done; goto done;
}
for (pos = 1; pos < req_ctx->child_req.dst_len; pos++) for (pos = 1; pos < req_ctx->child_req.dst_len; pos++)
if (req_ctx->out_buf[pos] != 0xff) if (req_ctx->out_buf[pos] != 0xff)
break; break;
if (pos < 9 || pos == req_ctx->child_req.dst_len || if (pos < 9 || pos == req_ctx->child_req.dst_len ||
req_ctx->out_buf[pos] != 0x00) { req_ctx->out_buf[pos] != 0x00)
err = -EINVAL;
goto done; goto done;
}
pos++; pos++;
if (ctx->hash_name) {
digest_info = rsa_lookup_asn1(ctx->hash_name);
if (!digest_info)
goto done;
if (memcmp(req_ctx->out_buf + pos, digest_info->data,
digest_info->size))
goto done;
pos += digest_info->size;
}
err = 0;
if (req->dst_len < req_ctx->child_req.dst_len - pos) if (req->dst_len < req_ctx->child_req.dst_len - pos)
err = -EOVERFLOW; err = -EOVERFLOW;
req->dst_len = req_ctx->child_req.dst_len - pos; req->dst_len = req_ctx->child_req.dst_len - pos;
@@ -444,7 +549,6 @@ static int pkcs1pad_verify_complete(struct akcipher_request *req, int err)
sg_copy_from_buffer(req->dst, sg_copy_from_buffer(req->dst,
sg_nents_for_len(req->dst, req->dst_len), sg_nents_for_len(req->dst, req->dst_len),
req_ctx->out_buf + pos, req->dst_len); req_ctx->out_buf + pos, req->dst_len);
done: done:
kzfree(req_ctx->out_buf); kzfree(req_ctx->out_buf);
@@ -481,7 +585,7 @@ static int pkcs1pad_verify(struct akcipher_request *req)
struct pkcs1pad_request *req_ctx = akcipher_request_ctx(req); struct pkcs1pad_request *req_ctx = akcipher_request_ctx(req);
int err; int err;
if (!ctx->key_size || req->src_len != ctx->key_size) if (!ctx->key_size || req->src_len < ctx->key_size)
return -EINVAL; return -EINVAL;
if (ctx->key_size > PAGE_SIZE) if (ctx->key_size > PAGE_SIZE)
@@ -518,6 +622,7 @@ static int pkcs1pad_verify(struct akcipher_request *req)
static int pkcs1pad_init_tfm(struct crypto_akcipher *tfm) static int pkcs1pad_init_tfm(struct crypto_akcipher *tfm)
{ {
struct akcipher_instance *inst = akcipher_alg_instance(tfm); struct akcipher_instance *inst = akcipher_alg_instance(tfm);
struct pkcs1pad_inst_ctx *ictx = akcipher_instance_ctx(inst);
struct pkcs1pad_ctx *ctx = akcipher_tfm_ctx(tfm); struct pkcs1pad_ctx *ctx = akcipher_tfm_ctx(tfm);
struct crypto_akcipher *child_tfm; struct crypto_akcipher *child_tfm;
@@ -526,7 +631,7 @@ static int pkcs1pad_init_tfm(struct crypto_akcipher *tfm)
return PTR_ERR(child_tfm); return PTR_ERR(child_tfm);
ctx->child = child_tfm; ctx->child = child_tfm;
ctx->hash_name = ictx->hash_name;
return 0; return 0;
} }
@@ -539,10 +644,11 @@ static void pkcs1pad_exit_tfm(struct crypto_akcipher *tfm)
static void pkcs1pad_free(struct akcipher_instance *inst) static void pkcs1pad_free(struct akcipher_instance *inst)
{ {
struct crypto_akcipher_spawn *spawn = akcipher_instance_ctx(inst); struct pkcs1pad_inst_ctx *ctx = akcipher_instance_ctx(inst);
struct crypto_akcipher_spawn *spawn = &ctx->spawn;
crypto_drop_akcipher(spawn); crypto_drop_akcipher(spawn);
kfree(ctx->hash_name);
kfree(inst); kfree(inst);
} }
@@ -550,9 +656,11 @@ static int pkcs1pad_create(struct crypto_template *tmpl, struct rtattr **tb)
{ {
struct crypto_attr_type *algt; struct crypto_attr_type *algt;
struct akcipher_instance *inst; struct akcipher_instance *inst;
struct pkcs1pad_inst_ctx *ctx;
struct crypto_akcipher_spawn *spawn; struct crypto_akcipher_spawn *spawn;
struct akcipher_alg *rsa_alg; struct akcipher_alg *rsa_alg;
const char *rsa_alg_name; const char *rsa_alg_name;
const char *hash_name;
int err; int err;
algt = crypto_get_attr_type(tb); algt = crypto_get_attr_type(tb);
@@ -566,11 +674,18 @@ static int pkcs1pad_create(struct crypto_template *tmpl, struct rtattr **tb)
if (IS_ERR(rsa_alg_name)) if (IS_ERR(rsa_alg_name))
return PTR_ERR(rsa_alg_name); return PTR_ERR(rsa_alg_name);
inst = kzalloc(sizeof(*inst) + sizeof(*spawn), GFP_KERNEL); hash_name = crypto_attr_alg_name(tb[2]);
if (IS_ERR(hash_name))
hash_name = NULL;
inst = kzalloc(sizeof(*inst) + sizeof(*ctx), GFP_KERNEL);
if (!inst) if (!inst)
return -ENOMEM; return -ENOMEM;
spawn = akcipher_instance_ctx(inst); ctx = akcipher_instance_ctx(inst);
spawn = &ctx->spawn;
ctx->hash_name = hash_name ? kstrdup(hash_name, GFP_KERNEL) : NULL;
crypto_set_spawn(&spawn->base, akcipher_crypto_instance(inst)); crypto_set_spawn(&spawn->base, akcipher_crypto_instance(inst));
err = crypto_grab_akcipher(spawn, rsa_alg_name, 0, err = crypto_grab_akcipher(spawn, rsa_alg_name, 0,
crypto_requires_sync(algt->type, algt->mask)); crypto_requires_sync(algt->type, algt->mask));
@@ -580,15 +695,28 @@ static int pkcs1pad_create(struct crypto_template *tmpl, struct rtattr **tb)
rsa_alg = crypto_spawn_akcipher_alg(spawn); rsa_alg = crypto_spawn_akcipher_alg(spawn);
err = -ENAMETOOLONG; err = -ENAMETOOLONG;
if (snprintf(inst->alg.base.cra_name,
CRYPTO_MAX_ALG_NAME, "pkcs1pad(%s)", if (!hash_name) {
rsa_alg->base.cra_name) >= if (snprintf(inst->alg.base.cra_name,
CRYPTO_MAX_ALG_NAME || CRYPTO_MAX_ALG_NAME, "pkcs1pad(%s)",
snprintf(inst->alg.base.cra_driver_name, rsa_alg->base.cra_name) >=
CRYPTO_MAX_ALG_NAME, "pkcs1pad(%s)", CRYPTO_MAX_ALG_NAME ||
rsa_alg->base.cra_driver_name) >= snprintf(inst->alg.base.cra_driver_name,
CRYPTO_MAX_ALG_NAME) CRYPTO_MAX_ALG_NAME, "pkcs1pad(%s)",
rsa_alg->base.cra_driver_name) >=
CRYPTO_MAX_ALG_NAME)
goto out_drop_alg; goto out_drop_alg;
} else {
if (snprintf(inst->alg.base.cra_name,
CRYPTO_MAX_ALG_NAME, "pkcs1pad(%s,%s)",
rsa_alg->base.cra_name, hash_name) >=
CRYPTO_MAX_ALG_NAME ||
snprintf(inst->alg.base.cra_driver_name,
CRYPTO_MAX_ALG_NAME, "pkcs1pad(%s,%s)",
rsa_alg->base.cra_driver_name, hash_name) >=
CRYPTO_MAX_ALG_NAME)
goto out_free_hash;
}
inst->alg.base.cra_flags = rsa_alg->base.cra_flags & CRYPTO_ALG_ASYNC; inst->alg.base.cra_flags = rsa_alg->base.cra_flags & CRYPTO_ALG_ASYNC;
inst->alg.base.cra_priority = rsa_alg->base.cra_priority; inst->alg.base.cra_priority = rsa_alg->base.cra_priority;
@@ -610,10 +738,12 @@ static int pkcs1pad_create(struct crypto_template *tmpl, struct rtattr **tb)
err = akcipher_register_instance(tmpl, inst); err = akcipher_register_instance(tmpl, inst);
if (err) if (err)
goto out_drop_alg; goto out_free_hash;
return 0; return 0;
out_free_hash:
kfree(ctx->hash_name);
out_drop_alg: out_drop_alg:
crypto_drop_akcipher(spawn); crypto_drop_akcipher(spawn);
out_free_inst: out_free_inst:

View File

@@ -14,30 +14,6 @@
#ifndef _LINUX_PUBLIC_KEY_H #ifndef _LINUX_PUBLIC_KEY_H
#define _LINUX_PUBLIC_KEY_H #define _LINUX_PUBLIC_KEY_H
#include <linux/mpi.h>
#include <crypto/hash_info.h>
enum pkey_algo {
PKEY_ALGO_DSA,
PKEY_ALGO_RSA,
PKEY_ALGO__LAST
};
extern const char *const pkey_algo_name[PKEY_ALGO__LAST];
extern const struct public_key_algorithm *pkey_algo[PKEY_ALGO__LAST];
/* asymmetric key implementation supports only up to SHA224 */
#define PKEY_HASH__LAST (HASH_ALGO_SHA224 + 1)
enum pkey_id_type {
PKEY_ID_PGP, /* OpenPGP generated key ID */
PKEY_ID_X509, /* X.509 arbitrary subjectKeyIdentifier */
PKEY_ID_PKCS7, /* Signature in PKCS#7 message */
PKEY_ID_TYPE__LAST
};
extern const char *const pkey_id_type_name[PKEY_ID_TYPE__LAST];
/* /*
* The use to which an asymmetric key is being put. * The use to which an asymmetric key is being put.
*/ */
@@ -59,31 +35,10 @@ extern const char *const key_being_used_for[NR__KEY_BEING_USED_FOR];
* part. * part.
*/ */
struct public_key { struct public_key {
const struct public_key_algorithm *algo; void *key;
u8 capabilities; u32 keylen;
#define PKEY_CAN_ENCRYPT 0x01 const char *id_type;
#define PKEY_CAN_DECRYPT 0x02 const char *pkey_algo;
#define PKEY_CAN_SIGN 0x04
#define PKEY_CAN_VERIFY 0x08
enum pkey_algo pkey_algo : 8;
enum pkey_id_type id_type : 8;
union {
MPI mpi[5];
struct {
MPI p; /* DSA prime */
MPI q; /* DSA group order */
MPI g; /* DSA group generator */
MPI y; /* DSA public-key value = g^x mod p */
MPI x; /* DSA secret exponent (if present) */
} dsa;
struct {
MPI n; /* RSA public modulus */
MPI e; /* RSA public encryption exponent */
MPI d; /* RSA secret encryption exponent (if present) */
MPI p; /* RSA secret prime (if present) */
MPI q; /* RSA secret prime (if present) */
} rsa;
};
}; };
extern void public_key_destroy(void *payload); extern void public_key_destroy(void *payload);
@@ -92,23 +47,15 @@ extern void public_key_destroy(void *payload);
* Public key cryptography signature data * Public key cryptography signature data
*/ */
struct public_key_signature { struct public_key_signature {
u8 *s; /* Signature */
u32 s_size; /* Number of bytes in signature */
u8 *digest; u8 *digest;
u8 digest_size; /* Number of bytes in digest */ u8 digest_size; /* Number of bytes in digest */
u8 nr_mpi; /* Occupancy of mpi[] */ const char *pkey_algo;
enum pkey_algo pkey_algo : 8; const char *hash_algo;
enum hash_algo pkey_hash_algo : 8;
union {
MPI mpi[2];
struct {
MPI s; /* m^d mod n */
} rsa;
struct {
MPI r;
MPI s;
} dsa;
};
}; };
extern struct asymmetric_key_subtype public_key_subtype;
struct key; struct key;
extern int verify_signature(const struct key *key, extern int verify_signature(const struct key *key,
const struct public_key_signature *sig); const struct public_key_signature *sig);
@@ -119,4 +66,7 @@ extern struct key *x509_request_asymmetric_key(struct key *keyring,
const struct asymmetric_key_id *skid, const struct asymmetric_key_id *skid,
bool partial); bool partial);
int public_key_verify_signature(const struct public_key *pkey,
const struct public_key_signature *sig);
#endif /* _LINUX_PUBLIC_KEY_H */ #endif /* _LINUX_PUBLIC_KEY_H */

View File

@@ -219,6 +219,7 @@ extern struct key *key_alloc(struct key_type *type,
#define KEY_ALLOC_QUOTA_OVERRUN 0x0001 /* add to quota, permit even if overrun */ #define KEY_ALLOC_QUOTA_OVERRUN 0x0001 /* add to quota, permit even if overrun */
#define KEY_ALLOC_NOT_IN_QUOTA 0x0002 /* not in quota */ #define KEY_ALLOC_NOT_IN_QUOTA 0x0002 /* not in quota */
#define KEY_ALLOC_TRUSTED 0x0004 /* Key should be flagged as trusted */ #define KEY_ALLOC_TRUSTED 0x0004 /* Key should be flagged as trusted */
#define KEY_ALLOC_BUILT_IN 0x0008 /* Key is built into kernel */
extern void key_revoke(struct key *key); extern void key_revoke(struct key *key);
extern void key_invalidate(struct key *key); extern void key_invalidate(struct key *key);

View File

@@ -1757,9 +1757,9 @@ config SYSTEM_DATA_VERIFICATION
select SYSTEM_TRUSTED_KEYRING select SYSTEM_TRUSTED_KEYRING
select KEYS select KEYS
select CRYPTO select CRYPTO
select CRYPTO_RSA
select ASYMMETRIC_KEY_TYPE select ASYMMETRIC_KEY_TYPE
select ASYMMETRIC_PUBLIC_KEY_SUBTYPE select ASYMMETRIC_PUBLIC_KEY_SUBTYPE
select PUBLIC_KEY_ALGO_RSA
select ASN1 select ASN1
select OID_REGISTRY select OID_REGISTRY
select X509_CERTIFICATE_PARSER select X509_CERTIFICATE_PARSER

View File

@@ -11,10 +11,17 @@
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/errno.h> #include <linux/errno.h>
#include <linux/string.h>
#include <keys/system_keyring.h> #include <keys/system_keyring.h>
#include <crypto/public_key.h> #include <crypto/public_key.h>
#include "module-internal.h" #include "module-internal.h"
enum pkey_id_type {
PKEY_ID_PGP, /* OpenPGP generated key ID */
PKEY_ID_X509, /* X.509 arbitrary subjectKeyIdentifier */
PKEY_ID_PKCS7, /* Signature in PKCS#7 message */
};
/* /*
* Module signature information block. * Module signature information block.
* *

View File

@@ -322,6 +322,13 @@ EXPORT_SYMBOL(timespec_trunc);
* -year/100+year/400 terms, and add 10.] * -year/100+year/400 terms, and add 10.]
* *
* This algorithm was first published by Gauss (I think). * This algorithm was first published by Gauss (I think).
*
* A leap second can be indicated by calling this function with sec as
* 60 (allowable under ISO 8601). The leap second is treated the same
* as the following second since they don't exist in UNIX time.
*
* An encoding of midnight at the end of the day as 24:00:00 - ie. midnight
* tomorrow - (allowable under ISO 8601) is supported.
*/ */
time64_t mktime64(const unsigned int year0, const unsigned int mon0, time64_t mktime64(const unsigned int year0, const unsigned int mon0,
const unsigned int day, const unsigned int hour, const unsigned int day, const unsigned int hour,
@@ -338,7 +345,7 @@ time64_t mktime64(const unsigned int year0, const unsigned int mon0,
return ((((time64_t) return ((((time64_t)
(year/4 - year/100 + year/400 + 367*mon/12 + day) + (year/4 - year/100 + year/400 + 367*mon/12 + day) +
year*365 - 719499 year*365 - 719499
)*24 + hour /* now have hours */ )*24 + hour /* now have hours - midnight tomorrow handled here */
)*60 + min /* now have minutes */ )*60 + min /* now have minutes */
)*60 + sec; /* finally seconds */ )*60 + sec; /* finally seconds */
} }

1
scripts/.gitignore vendored
View File

@@ -13,3 +13,4 @@ sortextable
asn1_compiler asn1_compiler
extract-cert extract-cert
sign-file sign-file
insert-sys-cert

View File

@@ -19,6 +19,7 @@ hostprogs-$(CONFIG_BUILDTIME_EXTABLE_SORT) += sortextable
hostprogs-$(CONFIG_ASN1) += asn1_compiler hostprogs-$(CONFIG_ASN1) += asn1_compiler
hostprogs-$(CONFIG_MODULE_SIG) += sign-file hostprogs-$(CONFIG_MODULE_SIG) += sign-file
hostprogs-$(CONFIG_SYSTEM_TRUSTED_KEYRING) += extract-cert hostprogs-$(CONFIG_SYSTEM_TRUSTED_KEYRING) += extract-cert
hostprogs-$(CONFIG_SYSTEM_EXTRA_CERTIFICATE) += insert-sys-cert
HOSTCFLAGS_sortextable.o = -I$(srctree)/tools/include HOSTCFLAGS_sortextable.o = -I$(srctree)/tools/include
HOSTCFLAGS_asn1_compiler.o = -I$(srctree)/include HOSTCFLAGS_asn1_compiler.o = -I$(srctree)/include

View File

@@ -91,13 +91,15 @@ print "Have $nr_symbols symbols\n";
die "Can't find system certificate list" die "Can't find system certificate list"
unless (exists($symbols{"__cert_list_start"}) && unless (exists($symbols{"__cert_list_start"}) &&
exists($symbols{"__cert_list_end"})); exists($symbols{"system_certificate_list_size"}));
my $start = Math::BigInt->new($symbols{"__cert_list_start"}); my $start = Math::BigInt->new($symbols{"__cert_list_start"});
my $end = Math::BigInt->new($symbols{"__cert_list_end"}); my $end;
my $size = $end - $start; my $size;
my $size_sym = Math::BigInt->new($symbols{"system_certificate_list_size"});
printf "Have %u bytes of certs at VMA 0x%x\n", $size, $start; open FD, "<$vmlinux" || die $vmlinux;
binmode(FD);
my $s = undef; my $s = undef;
foreach my $sec (@sections) { foreach my $sec (@sections) {
@@ -110,11 +112,24 @@ foreach my $sec (@sections) {
next unless ($start >= $s_vma); next unless ($start >= $s_vma);
next if ($start >= $s_vend); next if ($start >= $s_vend);
die "Cert object partially overflows section $s_name\n" die "Certificate list size was not found on the same section\n"
if ($end > $s_vend); if ($size_sym < $s_vma || $size_sym > $s_vend);
die "Cert object in multiple sections: ", $s_name, " and ", $s->{name}, "\n" die "Cert object in multiple sections: ", $s_name, " and ", $s->{name}, "\n"
if ($s); if ($s);
my $size_off = $size_sym -$s_vma + $s_foff;
my $packed;
die $vmlinux if (!defined(sysseek(FD, $size_off, SEEK_SET)));
sysread(FD, $packed, 8);
$size = unpack 'L!', $packed;
$end = $start + $size;
printf "Have %u bytes of certs at VMA 0x%x\n", $size, $start;
die "Cert object partially overflows section $s_name\n"
if ($end > $s_vend);
$s = $sec; $s = $sec;
} }
@@ -127,8 +142,6 @@ my $foff = $start - $s->{vma} + $s->{foff};
printf "Certificate list at file offset 0x%x\n", $foff; printf "Certificate list at file offset 0x%x\n", $foff;
open FD, "<$vmlinux" || die $vmlinux;
binmode(FD);
die $vmlinux if (!defined(sysseek(FD, $foff, SEEK_SET))); die $vmlinux if (!defined(sysseek(FD, $foff, SEEK_SET)));
my $buf = ""; my $buf = "";
my $len = sysread(FD, $buf, $size); my $len = sysread(FD, $buf, $size);

410
scripts/insert-sys-cert.c Normal file
View File

@@ -0,0 +1,410 @@
/* Write the contents of the <certfile> into kernel symbol system_extra_cert
*
* Copyright (C) IBM Corporation, 2015
*
* Author: Mehmet Kayaalp <mkayaalp@linux.vnet.ibm.com>
*
* This software may be used and distributed according to the terms
* of the GNU General Public License, incorporated herein by reference.
*
* Usage: insert-sys-cert [-s <System.map> -b <vmlinux> -c <certfile>
*/
#define _GNU_SOURCE
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <limits.h>
#include <stdbool.h>
#include <errno.h>
#include <stdlib.h>
#include <stdarg.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <unistd.h>
#include <elf.h>
#define CERT_SYM "system_extra_cert"
#define USED_SYM "system_extra_cert_used"
#define LSIZE_SYM "system_certificate_list_size"
#define info(format, args...) fprintf(stderr, "INFO: " format, ## args)
#define warn(format, args...) fprintf(stdout, "WARNING: " format, ## args)
#define err(format, args...) fprintf(stderr, "ERROR: " format, ## args)
#if UINTPTR_MAX == 0xffffffff
#define CURRENT_ELFCLASS ELFCLASS32
#define Elf_Ehdr Elf32_Ehdr
#define Elf_Shdr Elf32_Shdr
#define Elf_Sym Elf32_Sym
#else
#define CURRENT_ELFCLASS ELFCLASS64
#define Elf_Ehdr Elf64_Ehdr
#define Elf_Shdr Elf64_Shdr
#define Elf_Sym Elf64_Sym
#endif
static unsigned char endianness(void)
{
uint16_t two_byte = 0x00FF;
uint8_t low_address = *((uint8_t *)&two_byte);
if (low_address == 0)
return ELFDATA2MSB;
else
return ELFDATA2LSB;
}
struct sym {
char *name;
unsigned long address;
unsigned long offset;
void *content;
int size;
};
static unsigned long get_offset_from_address(Elf_Ehdr *hdr, unsigned long addr)
{
Elf_Shdr *x;
unsigned int i, num_sections;
x = (void *)hdr + hdr->e_shoff;
if (hdr->e_shnum == SHN_UNDEF)
num_sections = x[0].sh_size;
else
num_sections = hdr->e_shnum;
for (i = 1; i < num_sections; i++) {
unsigned long start = x[i].sh_addr;
unsigned long end = start + x[i].sh_size;
unsigned long offset = x[i].sh_offset;
if (addr >= start && addr <= end)
return addr - start + offset;
}
return 0;
}
#define LINE_SIZE 100
static void get_symbol_from_map(Elf_Ehdr *hdr, FILE *f, char *name,
struct sym *s)
{
char l[LINE_SIZE];
char *w, *p, *n;
s->size = 0;
s->address = 0;
s->offset = 0;
if (fseek(f, 0, SEEK_SET) != 0) {
perror("File seek failed");
exit(EXIT_FAILURE);
}
while (fgets(l, LINE_SIZE, f)) {
p = strchr(l, '\n');
if (!p) {
err("Missing line ending.\n");
return;
}
n = strstr(l, name);
if (n)
break;
}
if (!n) {
err("Unable to find symbol: %s\n", name);
return;
}
w = strchr(l, ' ');
if (!w)
return;
*w = '\0';
s->address = strtoul(l, NULL, 16);
if (s->address == 0)
return;
s->offset = get_offset_from_address(hdr, s->address);
s->name = name;
s->content = (void *)hdr + s->offset;
}
static Elf_Sym *find_elf_symbol(Elf_Ehdr *hdr, Elf_Shdr *symtab, char *name)
{
Elf_Sym *sym, *symtab_start;
char *strtab, *symname;
unsigned int link;
Elf_Shdr *x;
int i, n;
x = (void *)hdr + hdr->e_shoff;
link = symtab->sh_link;
symtab_start = (void *)hdr + symtab->sh_offset;
n = symtab->sh_size / symtab->sh_entsize;
strtab = (void *)hdr + x[link].sh_offset;
for (i = 0; i < n; i++) {
sym = &symtab_start[i];
symname = strtab + sym->st_name;
if (strcmp(symname, name) == 0)
return sym;
}
err("Unable to find symbol: %s\n", name);
return NULL;
}
static void get_symbol_from_table(Elf_Ehdr *hdr, Elf_Shdr *symtab,
char *name, struct sym *s)
{
Elf_Shdr *sec;
int secndx;
Elf_Sym *elf_sym;
Elf_Shdr *x;
x = (void *)hdr + hdr->e_shoff;
s->size = 0;
s->address = 0;
s->offset = 0;
elf_sym = find_elf_symbol(hdr, symtab, name);
if (!elf_sym)
return;
secndx = elf_sym->st_shndx;
if (!secndx)
return;
sec = &x[secndx];
s->size = elf_sym->st_size;
s->address = elf_sym->st_value;
s->offset = s->address - sec->sh_addr
+ sec->sh_offset;
s->name = name;
s->content = (void *)hdr + s->offset;
}
static Elf_Shdr *get_symbol_table(Elf_Ehdr *hdr)
{
Elf_Shdr *x;
unsigned int i, num_sections;
x = (void *)hdr + hdr->e_shoff;
if (hdr->e_shnum == SHN_UNDEF)
num_sections = x[0].sh_size;
else
num_sections = hdr->e_shnum;
for (i = 1; i < num_sections; i++)
if (x[i].sh_type == SHT_SYMTAB)
return &x[i];
return NULL;
}
static void *map_file(char *file_name, int *size)
{
struct stat st;
void *map;
int fd;
fd = open(file_name, O_RDWR);
if (fd < 0) {
perror(file_name);
return NULL;
}
if (fstat(fd, &st)) {
perror("Could not determine file size");
close(fd);
return NULL;
}
*size = st.st_size;
map = mmap(NULL, *size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
if (map == MAP_FAILED) {
perror("Mapping to memory failed");
close(fd);
return NULL;
}
close(fd);
return map;
}
static char *read_file(char *file_name, int *size)
{
struct stat st;
char *buf;
int fd;
fd = open(file_name, O_RDONLY);
if (fd < 0) {
perror(file_name);
return NULL;
}
if (fstat(fd, &st)) {
perror("Could not determine file size");
close(fd);
return NULL;
}
*size = st.st_size;
buf = malloc(*size);
if (!buf) {
perror("Allocating memory failed");
close(fd);
return NULL;
}
if (read(fd, buf, *size) != *size) {
perror("File read failed");
close(fd);
return NULL;
}
close(fd);
return buf;
}
static void print_sym(Elf_Ehdr *hdr, struct sym *s)
{
info("sym: %s\n", s->name);
info("addr: 0x%lx\n", s->address);
info("size: %d\n", s->size);
info("offset: 0x%lx\n", (unsigned long)s->offset);
}
static void print_usage(char *e)
{
printf("Usage %s [-s <System.map>] -b <vmlinux> -c <certfile>\n", e);
}
int main(int argc, char **argv)
{
char *system_map_file = NULL;
char *vmlinux_file = NULL;
char *cert_file = NULL;
int vmlinux_size;
int cert_size;
Elf_Ehdr *hdr;
char *cert;
FILE *system_map;
unsigned long *lsize;
int *used;
int opt;
Elf_Shdr *symtab = NULL;
struct sym cert_sym, lsize_sym, used_sym;
while ((opt = getopt(argc, argv, "b:c:s:")) != -1) {
switch (opt) {
case 's':
system_map_file = optarg;
break;
case 'b':
vmlinux_file = optarg;
break;
case 'c':
cert_file = optarg;
break;
default:
break;
}
}
if (!vmlinux_file || !cert_file) {
print_usage(argv[0]);
exit(EXIT_FAILURE);
}
cert = read_file(cert_file, &cert_size);
if (!cert)
exit(EXIT_FAILURE);
hdr = map_file(vmlinux_file, &vmlinux_size);
if (!hdr)
exit(EXIT_FAILURE);
if (vmlinux_size < sizeof(*hdr)) {
err("Invalid ELF file.\n");
exit(EXIT_FAILURE);
}
if ((hdr->e_ident[EI_MAG0] != ELFMAG0) ||
(hdr->e_ident[EI_MAG1] != ELFMAG1) ||
(hdr->e_ident[EI_MAG2] != ELFMAG2) ||
(hdr->e_ident[EI_MAG3] != ELFMAG3)) {
err("Invalid ELF magic.\n");
exit(EXIT_FAILURE);
}
if (hdr->e_ident[EI_CLASS] != CURRENT_ELFCLASS) {
err("ELF class mismatch.\n");
exit(EXIT_FAILURE);
}
if (hdr->e_ident[EI_DATA] != endianness()) {
err("ELF endian mismatch.\n");
exit(EXIT_FAILURE);
}
if (hdr->e_shoff > vmlinux_size) {
err("Could not find section header.\n");
exit(EXIT_FAILURE);
}
symtab = get_symbol_table(hdr);
if (!symtab) {
warn("Could not find the symbol table.\n");
if (!system_map_file) {
err("Please provide a System.map file.\n");
print_usage(argv[0]);
exit(EXIT_FAILURE);
}
system_map = fopen(system_map_file, "r");
if (!system_map) {
perror(system_map_file);
exit(EXIT_FAILURE);
}
get_symbol_from_map(hdr, system_map, CERT_SYM, &cert_sym);
get_symbol_from_map(hdr, system_map, USED_SYM, &used_sym);
get_symbol_from_map(hdr, system_map, LSIZE_SYM, &lsize_sym);
cert_sym.size = used_sym.address - cert_sym.address;
} else {
info("Symbol table found.\n");
if (system_map_file)
warn("System.map is ignored.\n");
get_symbol_from_table(hdr, symtab, CERT_SYM, &cert_sym);
get_symbol_from_table(hdr, symtab, USED_SYM, &used_sym);
get_symbol_from_table(hdr, symtab, LSIZE_SYM, &lsize_sym);
}
if (!cert_sym.offset || !lsize_sym.offset || !used_sym.offset)
exit(EXIT_FAILURE);
print_sym(hdr, &cert_sym);
print_sym(hdr, &used_sym);
print_sym(hdr, &lsize_sym);
lsize = (unsigned long *)lsize_sym.content;
used = (int *)used_sym.content;
if (cert_sym.size < cert_size) {
err("Certificate is larger than the reserved area!\n");
exit(EXIT_FAILURE);
}
/* If the existing cert is the same, don't overwrite */
if (cert_size == *used &&
strncmp(cert_sym.content, cert, cert_size) == 0) {
warn("Certificate was already inserted.\n");
exit(EXIT_SUCCESS);
}
if (*used > 0)
warn("Replacing previously inserted certificate.\n");
memcpy(cert_sym.content, cert, cert_size);
if (cert_size < cert_sym.size)
memset(cert_sym.content + cert_size,
0, cert_sym.size - cert_size);
*lsize = *lsize + cert_size - *used;
*used = cert_size;
info("Inserted the contents of %s into %lx.\n", cert_file,
cert_sym.address);
info("Used %d bytes out of %d bytes reserved.\n", *used,
cert_sym.size);
exit(EXIT_SUCCESS);
}

View File

@@ -2,9 +2,11 @@
* *
* Copyright © 2014-2015 Red Hat, Inc. All Rights Reserved. * Copyright © 2014-2015 Red Hat, Inc. All Rights Reserved.
* Copyright © 2015 Intel Corporation. * Copyright © 2015 Intel Corporation.
* Copyright © 2016 Hewlett Packard Enterprise Development LP
* *
* Authors: David Howells <dhowells@redhat.com> * Authors: David Howells <dhowells@redhat.com>
* David Woodhouse <dwmw2@infradead.org> * David Woodhouse <dwmw2@infradead.org>
* Juerg Haefliger <juerg.haefliger@hpe.com>
* *
* This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License * modify it under the terms of the GNU Lesser General Public License
@@ -39,7 +41,7 @@
* signing with anything other than SHA1 - so we're stuck with that if such is * signing with anything other than SHA1 - so we're stuck with that if such is
* the case. * the case.
*/ */
#if OPENSSL_VERSION_NUMBER < 0x10000000L #if OPENSSL_VERSION_NUMBER < 0x10000000L || defined(OPENSSL_NO_CMS)
#define USE_PKCS7 #define USE_PKCS7
#endif #endif
#ifndef USE_PKCS7 #ifndef USE_PKCS7
@@ -67,6 +69,8 @@ void format(void)
{ {
fprintf(stderr, fprintf(stderr,
"Usage: scripts/sign-file [-dp] <hash algo> <key> <x509> <module> [<dest>]\n"); "Usage: scripts/sign-file [-dp] <hash algo> <key> <x509> <module> [<dest>]\n");
fprintf(stderr,
" scripts/sign-file -s <raw sig> <hash algo> <x509> <module> [<dest>]\n");
exit(2); exit(2);
} }
@@ -126,26 +130,84 @@ static int pem_pw_cb(char *buf, int len, int w, void *v)
return pwlen; return pwlen;
} }
static EVP_PKEY *read_private_key(const char *private_key_name)
{
EVP_PKEY *private_key;
if (!strncmp(private_key_name, "pkcs11:", 7)) {
ENGINE *e;
ENGINE_load_builtin_engines();
drain_openssl_errors();
e = ENGINE_by_id("pkcs11");
ERR(!e, "Load PKCS#11 ENGINE");
if (ENGINE_init(e))
drain_openssl_errors();
else
ERR(1, "ENGINE_init");
if (key_pass)
ERR(!ENGINE_ctrl_cmd_string(e, "PIN", key_pass, 0),
"Set PKCS#11 PIN");
private_key = ENGINE_load_private_key(e, private_key_name,
NULL, NULL);
ERR(!private_key, "%s", private_key_name);
} else {
BIO *b;
b = BIO_new_file(private_key_name, "rb");
ERR(!b, "%s", private_key_name);
private_key = PEM_read_bio_PrivateKey(b, NULL, pem_pw_cb,
NULL);
ERR(!private_key, "%s", private_key_name);
BIO_free(b);
}
return private_key;
}
static X509 *read_x509(const char *x509_name)
{
X509 *x509;
BIO *b;
b = BIO_new_file(x509_name, "rb");
ERR(!b, "%s", x509_name);
x509 = d2i_X509_bio(b, NULL); /* Binary encoded X.509 */
if (!x509) {
ERR(BIO_reset(b) != 1, "%s", x509_name);
x509 = PEM_read_bio_X509(b, NULL, NULL,
NULL); /* PEM encoded X.509 */
if (x509)
drain_openssl_errors();
}
BIO_free(b);
ERR(!x509, "%s", x509_name);
return x509;
}
int main(int argc, char **argv) int main(int argc, char **argv)
{ {
struct module_signature sig_info = { .id_type = PKEY_ID_PKCS7 }; struct module_signature sig_info = { .id_type = PKEY_ID_PKCS7 };
char *hash_algo = NULL; char *hash_algo = NULL;
char *private_key_name, *x509_name, *module_name, *dest_name; char *private_key_name = NULL, *raw_sig_name = NULL;
char *x509_name, *module_name, *dest_name;
bool save_sig = false, replace_orig; bool save_sig = false, replace_orig;
bool sign_only = false; bool sign_only = false;
bool raw_sig = false;
unsigned char buf[4096]; unsigned char buf[4096];
unsigned long module_size, sig_size; unsigned long module_size, sig_size;
unsigned int use_signed_attrs; unsigned int use_signed_attrs;
const EVP_MD *digest_algo; const EVP_MD *digest_algo;
EVP_PKEY *private_key; EVP_PKEY *private_key;
#ifndef USE_PKCS7 #ifndef USE_PKCS7
CMS_ContentInfo *cms; CMS_ContentInfo *cms = NULL;
unsigned int use_keyid = 0; unsigned int use_keyid = 0;
#else #else
PKCS7 *pkcs7; PKCS7 *pkcs7 = NULL;
#endif #endif
X509 *x509; X509 *x509;
BIO *b, *bd = NULL, *bm; BIO *bd, *bm;
int opt, n; int opt, n;
OpenSSL_add_all_algorithms(); OpenSSL_add_all_algorithms();
ERR_load_crypto_strings(); ERR_load_crypto_strings();
@@ -160,8 +222,9 @@ int main(int argc, char **argv)
#endif #endif
do { do {
opt = getopt(argc, argv, "dpk"); opt = getopt(argc, argv, "sdpk");
switch (opt) { switch (opt) {
case 's': raw_sig = true; break;
case 'p': save_sig = true; break; case 'p': save_sig = true; break;
case 'd': sign_only = true; save_sig = true; break; case 'd': sign_only = true; save_sig = true; break;
#ifndef USE_PKCS7 #ifndef USE_PKCS7
@@ -177,8 +240,13 @@ int main(int argc, char **argv)
if (argc < 4 || argc > 5) if (argc < 4 || argc > 5)
format(); format();
hash_algo = argv[0]; if (raw_sig) {
private_key_name = argv[1]; raw_sig_name = argv[0];
hash_algo = argv[1];
} else {
hash_algo = argv[0];
private_key_name = argv[1];
}
x509_name = argv[2]; x509_name = argv[2];
module_name = argv[3]; module_name = argv[3];
if (argc == 5) { if (argc == 5) {
@@ -198,101 +266,74 @@ int main(int argc, char **argv)
} }
#endif #endif
/* Read the private key and the X.509 cert the PKCS#7 message /* Open the module file */
* will point to. bm = BIO_new_file(module_name, "rb");
*/ ERR(!bm, "%s", module_name);
if (!strncmp(private_key_name, "pkcs11:", 7)) {
ENGINE *e;
ENGINE_load_builtin_engines(); if (!raw_sig) {
drain_openssl_errors(); /* Read the private key and the X.509 cert the PKCS#7 message
e = ENGINE_by_id("pkcs11"); * will point to.
ERR(!e, "Load PKCS#11 ENGINE"); */
if (ENGINE_init(e)) private_key = read_private_key(private_key_name);
drain_openssl_errors(); x509 = read_x509(x509_name);
else
ERR(1, "ENGINE_init");
if (key_pass)
ERR(!ENGINE_ctrl_cmd_string(e, "PIN", key_pass, 0), "Set PKCS#11 PIN");
private_key = ENGINE_load_private_key(e, private_key_name, NULL,
NULL);
ERR(!private_key, "%s", private_key_name);
} else {
b = BIO_new_file(private_key_name, "rb");
ERR(!b, "%s", private_key_name);
private_key = PEM_read_bio_PrivateKey(b, NULL, pem_pw_cb, NULL);
ERR(!private_key, "%s", private_key_name);
BIO_free(b);
}
b = BIO_new_file(x509_name, "rb"); /* Digest the module data. */
ERR(!b, "%s", x509_name); OpenSSL_add_all_digests();
x509 = d2i_X509_bio(b, NULL); /* Binary encoded X.509 */ display_openssl_errors(__LINE__);
if (!x509) { digest_algo = EVP_get_digestbyname(hash_algo);
ERR(BIO_reset(b) != 1, "%s", x509_name); ERR(!digest_algo, "EVP_get_digestbyname");
x509 = PEM_read_bio_X509(b, NULL, NULL, NULL); /* PEM encoded X.509 */
if (x509) #ifndef USE_PKCS7
drain_openssl_errors(); /* Load the signature message from the digest buffer. */
cms = CMS_sign(NULL, NULL, NULL, NULL,
CMS_NOCERTS | CMS_PARTIAL | CMS_BINARY |
CMS_DETACHED | CMS_STREAM);
ERR(!cms, "CMS_sign");
ERR(!CMS_add1_signer(cms, x509, private_key, digest_algo,
CMS_NOCERTS | CMS_BINARY |
CMS_NOSMIMECAP | use_keyid |
use_signed_attrs),
"CMS_add1_signer");
ERR(CMS_final(cms, bm, NULL, CMS_NOCERTS | CMS_BINARY) < 0,
"CMS_final");
#else
pkcs7 = PKCS7_sign(x509, private_key, NULL, bm,
PKCS7_NOCERTS | PKCS7_BINARY |
PKCS7_DETACHED | use_signed_attrs);
ERR(!pkcs7, "PKCS7_sign");
#endif
if (save_sig) {
char *sig_file_name;
BIO *b;
ERR(asprintf(&sig_file_name, "%s.p7s", module_name) < 0,
"asprintf");
b = BIO_new_file(sig_file_name, "wb");
ERR(!b, "%s", sig_file_name);
#ifndef USE_PKCS7
ERR(i2d_CMS_bio_stream(b, cms, NULL, 0) < 0,
"%s", sig_file_name);
#else
ERR(i2d_PKCS7_bio(b, pkcs7) < 0,
"%s", sig_file_name);
#endif
BIO_free(b);
}
if (sign_only) {
BIO_free(bm);
return 0;
}
} }
BIO_free(b);
ERR(!x509, "%s", x509_name);
/* Open the destination file now so that we can shovel the module data /* Open the destination file now so that we can shovel the module data
* across as we read it. * across as we read it.
*/ */
if (!sign_only) { bd = BIO_new_file(dest_name, "wb");
bd = BIO_new_file(dest_name, "wb"); ERR(!bd, "%s", dest_name);
ERR(!bd, "%s", dest_name);
}
/* Digest the module data. */
OpenSSL_add_all_digests();
display_openssl_errors(__LINE__);
digest_algo = EVP_get_digestbyname(hash_algo);
ERR(!digest_algo, "EVP_get_digestbyname");
bm = BIO_new_file(module_name, "rb");
ERR(!bm, "%s", module_name);
#ifndef USE_PKCS7
/* Load the signature message from the digest buffer. */
cms = CMS_sign(NULL, NULL, NULL, NULL,
CMS_NOCERTS | CMS_PARTIAL | CMS_BINARY | CMS_DETACHED | CMS_STREAM);
ERR(!cms, "CMS_sign");
ERR(!CMS_add1_signer(cms, x509, private_key, digest_algo,
CMS_NOCERTS | CMS_BINARY | CMS_NOSMIMECAP |
use_keyid | use_signed_attrs),
"CMS_add1_signer");
ERR(CMS_final(cms, bm, NULL, CMS_NOCERTS | CMS_BINARY) < 0,
"CMS_final");
#else
pkcs7 = PKCS7_sign(x509, private_key, NULL, bm,
PKCS7_NOCERTS | PKCS7_BINARY |
PKCS7_DETACHED | use_signed_attrs);
ERR(!pkcs7, "PKCS7_sign");
#endif
if (save_sig) {
char *sig_file_name;
ERR(asprintf(&sig_file_name, "%s.p7s", module_name) < 0,
"asprintf");
b = BIO_new_file(sig_file_name, "wb");
ERR(!b, "%s", sig_file_name);
#ifndef USE_PKCS7
ERR(i2d_CMS_bio_stream(b, cms, NULL, 0) < 0,
"%s", sig_file_name);
#else
ERR(i2d_PKCS7_bio(b, pkcs7) < 0,
"%s", sig_file_name);
#endif
BIO_free(b);
}
if (sign_only)
return 0;
/* Append the marker and the PKCS#7 message to the destination file */ /* Append the marker and the PKCS#7 message to the destination file */
ERR(BIO_reset(bm) < 0, "%s", module_name); ERR(BIO_reset(bm) < 0, "%s", module_name);
@@ -300,14 +341,29 @@ int main(int argc, char **argv)
n > 0) { n > 0) {
ERR(BIO_write(bd, buf, n) < 0, "%s", dest_name); ERR(BIO_write(bd, buf, n) < 0, "%s", dest_name);
} }
BIO_free(bm);
ERR(n < 0, "%s", module_name); ERR(n < 0, "%s", module_name);
module_size = BIO_number_written(bd); module_size = BIO_number_written(bd);
if (!raw_sig) {
#ifndef USE_PKCS7 #ifndef USE_PKCS7
ERR(i2d_CMS_bio_stream(bd, cms, NULL, 0) < 0, "%s", dest_name); ERR(i2d_CMS_bio_stream(bd, cms, NULL, 0) < 0, "%s", dest_name);
#else #else
ERR(i2d_PKCS7_bio(bd, pkcs7) < 0, "%s", dest_name); ERR(i2d_PKCS7_bio(bd, pkcs7) < 0, "%s", dest_name);
#endif #endif
} else {
BIO *b;
/* Read the raw signature file and write the data to the
* destination file
*/
b = BIO_new_file(raw_sig_name, "rb");
ERR(!b, "%s", raw_sig_name);
while ((n = BIO_read(b, buf, sizeof(buf))), n > 0)
ERR(BIO_write(bd, buf, n) < 0, "%s", dest_name);
BIO_free(b);
}
sig_size = BIO_number_written(bd) - module_size; sig_size = BIO_number_written(bd) - module_size;
sig_info.sig_len = htonl(sig_size); sig_info.sig_len = htonl(sig_size);
ERR(BIO_write(bd, &sig_info, sizeof(sig_info)) < 0, "%s", dest_name); ERR(BIO_write(bd, &sig_info, sizeof(sig_info)) < 0, "%s", dest_name);

View File

@@ -36,6 +36,7 @@ config INTEGRITY_ASYMMETRIC_KEYS
select ASYMMETRIC_KEY_TYPE select ASYMMETRIC_KEY_TYPE
select ASYMMETRIC_PUBLIC_KEY_SUBTYPE select ASYMMETRIC_PUBLIC_KEY_SUBTYPE
select PUBLIC_KEY_ALGO_RSA select PUBLIC_KEY_ALGO_RSA
select CRYPTO_RSA
select X509_CERTIFICATE_PARSER select X509_CERTIFICATE_PARSER
help help
This option enables digital signature verification using This option enables digital signature verification using
@@ -45,7 +46,6 @@ config INTEGRITY_TRUSTED_KEYRING
bool "Require all keys on the integrity keyrings be signed" bool "Require all keys on the integrity keyrings be signed"
depends on SYSTEM_TRUSTED_KEYRING depends on SYSTEM_TRUSTED_KEYRING
depends on INTEGRITY_ASYMMETRIC_KEYS depends on INTEGRITY_ASYMMETRIC_KEYS
select KEYS_DEBUG_PROC_KEYS
default y default y
help help
This option requires that all keys added to the .ima and This option requires that all keys added to the .ima and

View File

@@ -16,6 +16,7 @@
#include <linux/ratelimit.h> #include <linux/ratelimit.h>
#include <linux/key-type.h> #include <linux/key-type.h>
#include <crypto/public_key.h> #include <crypto/public_key.h>
#include <crypto/hash_info.h>
#include <keys/asymmetric-type.h> #include <keys/asymmetric-type.h>
#include <keys/system_keyring.h> #include <keys/system_keyring.h>
@@ -94,7 +95,7 @@ int asymmetric_verify(struct key *keyring, const char *sig,
if (siglen != __be16_to_cpu(hdr->sig_size)) if (siglen != __be16_to_cpu(hdr->sig_size))
return -EBADMSG; return -EBADMSG;
if (hdr->hash_algo >= PKEY_HASH__LAST) if (hdr->hash_algo >= HASH_ALGO__LAST)
return -ENOPKG; return -ENOPKG;
key = request_asymmetric_key(keyring, __be32_to_cpu(hdr->keyid)); key = request_asymmetric_key(keyring, __be32_to_cpu(hdr->keyid));
@@ -103,16 +104,13 @@ int asymmetric_verify(struct key *keyring, const char *sig,
memset(&pks, 0, sizeof(pks)); memset(&pks, 0, sizeof(pks));
pks.pkey_hash_algo = hdr->hash_algo; pks.pkey_algo = "rsa";
pks.hash_algo = hash_algo_name[hdr->hash_algo];
pks.digest = (u8 *)data; pks.digest = (u8 *)data;
pks.digest_size = datalen; pks.digest_size = datalen;
pks.nr_mpi = 1; pks.s = hdr->sig;
pks.rsa.s = mpi_read_raw_data(hdr->sig, siglen); pks.s_size = siglen;
ret = verify_signature(key, &pks);
if (pks.rsa.s)
ret = verify_signature(key, &pks);
mpi_free(pks.rsa.s);
key_put(key); key_put(key);
pr_debug("%s() = %d\n", __func__, ret); pr_debug("%s() = %d\n", __func__, ret);
return ret; return ret;

View File

@@ -90,7 +90,7 @@ struct ima_digest_data {
struct signature_v2_hdr { struct signature_v2_hdr {
uint8_t type; /* xattr type */ uint8_t type; /* xattr type */
uint8_t version; /* signature format version */ uint8_t version; /* signature format version */
uint8_t hash_algo; /* Digest algorithm [enum pkey_hash_algo] */ uint8_t hash_algo; /* Digest algorithm [enum hash_algo] */
uint32_t keyid; /* IMA key identifier - not X509/PGP specific */ uint32_t keyid; /* IMA key identifier - not X509/PGP specific */
uint16_t sig_size; /* signature size */ uint16_t sig_size; /* signature size */
uint8_t sig[0]; /* signature payload */ uint8_t sig[0]; /* signature payload */

View File

@@ -9,7 +9,6 @@
* 2 of the Licence, or (at your option) any later version. * 2 of the Licence, or (at your option) any later version.
*/ */
#include <linux/module.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/seq_file.h> #include <linux/seq_file.h>
#include <linux/file.h> #include <linux/file.h>
@@ -18,8 +17,6 @@
#include <keys/user-type.h> #include <keys/user-type.h>
#include <keys/big_key-type.h> #include <keys/big_key-type.h>
MODULE_LICENSE("GPL");
/* /*
* Layout of key payload words. * Layout of key payload words.
*/ */
@@ -212,18 +209,8 @@ long big_key_read(const struct key *key, char __user *buffer, size_t buflen)
return ret; return ret;
} }
/*
* Module stuff
*/
static int __init big_key_init(void) static int __init big_key_init(void)
{ {
return register_key_type(&key_type_big_key); return register_key_type(&key_type_big_key);
} }
device_initcall(big_key_init);
static void __exit big_key_cleanup(void)
{
unregister_key_type(&key_type_big_key);
}
module_init(big_key_init);
module_exit(big_key_cleanup);

View File

@@ -296,6 +296,8 @@ struct key *key_alloc(struct key_type *type, const char *desc,
key->flags |= 1 << KEY_FLAG_IN_QUOTA; key->flags |= 1 << KEY_FLAG_IN_QUOTA;
if (flags & KEY_ALLOC_TRUSTED) if (flags & KEY_ALLOC_TRUSTED)
key->flags |= 1 << KEY_FLAG_TRUSTED; key->flags |= 1 << KEY_FLAG_TRUSTED;
if (flags & KEY_ALLOC_BUILT_IN)
key->flags |= 1 << KEY_FLAG_BUILTIN;
#ifdef KEY_DEBUGGING #ifdef KEY_DEBUGGING
key->magic = KEY_DEBUG_MAGIC; key->magic = KEY_DEBUG_MAGIC;