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:
commit
88a1b564a2
|
@ -166,7 +166,6 @@ CONFIG_DEBUG_USER=y
|
|||
CONFIG_DEBUG_ERRORS=y
|
||||
CONFIG_DEBUG_LL=y
|
||||
CONFIG_KEYS=y
|
||||
CONFIG_KEYS_DEBUG_PROC_KEYS=y
|
||||
CONFIG_SECURITY=y
|
||||
CONFIG_CRYPTO_PCBC=m
|
||||
CONFIG_CRYPTO_SHA1=m
|
||||
|
|
|
@ -95,7 +95,6 @@ CONFIG_PARTITION_ADVANCED=y
|
|||
CONFIG_NLS=y
|
||||
CONFIG_DEBUG_USER=y
|
||||
CONFIG_KEYS=y
|
||||
CONFIG_KEYS_DEBUG_PROC_KEYS=y
|
||||
CONFIG_CRYPTO_NULL=y
|
||||
CONFIG_CRYPTO_LRW=y
|
||||
CONFIG_CRYPTO_PCBC=m
|
||||
|
|
|
@ -108,7 +108,6 @@ CONFIG_DEBUG_USER=y
|
|||
CONFIG_DEBUG_LL=y
|
||||
CONFIG_DEBUG_LL_UART_8250=y
|
||||
CONFIG_KEYS=y
|
||||
CONFIG_KEYS_DEBUG_PROC_KEYS=y
|
||||
CONFIG_CRYPTO_NULL=y
|
||||
CONFIG_CRYPTO_LRW=y
|
||||
CONFIG_CRYPTO_PCBC=m
|
||||
|
|
|
@ -214,7 +214,6 @@ CONFIG_MAGIC_SYSRQ=y
|
|||
CONFIG_DEBUG_FS=y
|
||||
CONFIG_DEBUG_USER=y
|
||||
CONFIG_KEYS=y
|
||||
CONFIG_KEYS_DEBUG_PROC_KEYS=y
|
||||
CONFIG_SECURITY=y
|
||||
CONFIG_CRYPTO_PCBC=m
|
||||
CONFIG_CRYPTO_SHA256=m
|
||||
|
|
|
@ -87,5 +87,4 @@ CONFIG_KGDB_KDB=y
|
|||
CONFIG_EARLY_PRINTK=y
|
||||
CONFIG_KEYS=y
|
||||
CONFIG_ENCRYPTED_KEYS=y
|
||||
CONFIG_KEYS_DEBUG_PROC_KEYS=y
|
||||
# CONFIG_CRYPTO_ANSI_CPRNG is not set
|
||||
|
|
|
@ -92,7 +92,6 @@ CONFIG_DEBUG_INFO=y
|
|||
CONFIG_EARLY_PRINTK=y
|
||||
CONFIG_KEYS=y
|
||||
CONFIG_ENCRYPTED_KEYS=y
|
||||
CONFIG_KEYS_DEBUG_PROC_KEYS=y
|
||||
CONFIG_CRYPTO_ECB=y
|
||||
CONFIG_CRYPTO_MD4=y
|
||||
CONFIG_CRYPTO_MD5=y
|
||||
|
|
|
@ -247,7 +247,6 @@ CONFIG_DEBUG_SPINLOCK_SLEEP=y
|
|||
CONFIG_DEBUG_MEMORY_INIT=y
|
||||
CONFIG_DEBUG_LIST=y
|
||||
CONFIG_KEYS=y
|
||||
CONFIG_KEYS_DEBUG_PROC_KEYS=y
|
||||
CONFIG_SECURITY=y
|
||||
CONFIG_SECURITY_NETWORK=y
|
||||
CONFIG_SECURITY_NETWORK_XFRM=y
|
||||
|
|
|
@ -358,7 +358,6 @@ CONFIG_DLM=m
|
|||
CONFIG_DEBUG_MEMORY_INIT=y
|
||||
# CONFIG_RCU_CPU_STALL_DETECTOR is not set
|
||||
CONFIG_KEYS=y
|
||||
CONFIG_KEYS_DEBUG_PROC_KEYS=y
|
||||
CONFIG_CRYPTO_FIPS=y
|
||||
CONFIG_CRYPTO_NULL=m
|
||||
CONFIG_CRYPTO_CRYPTD=m
|
||||
|
|
|
@ -346,7 +346,6 @@ CONFIG_PARTITION_ADVANCED=y
|
|||
CONFIG_DLM=m
|
||||
# CONFIG_RCU_CPU_STALL_DETECTOR is not set
|
||||
CONFIG_KEYS=y
|
||||
CONFIG_KEYS_DEBUG_PROC_KEYS=y
|
||||
CONFIG_SECURITYFS=y
|
||||
CONFIG_CRYPTO_FIPS=y
|
||||
CONFIG_CRYPTO_NULL=m
|
||||
|
|
|
@ -181,7 +181,6 @@ CONFIG_MAGIC_SYSRQ=y
|
|||
# CONFIG_RCU_CPU_STALL_DETECTOR is not set
|
||||
CONFIG_SYSCTL_SYSCALL_CHECK=y
|
||||
CONFIG_KEYS=y
|
||||
CONFIG_KEYS_DEBUG_PROC_KEYS=y
|
||||
CONFIG_CRYPTO_NULL=y
|
||||
CONFIG_CRYPTO_CBC=y
|
||||
CONFIG_CRYPTO_ECB=y
|
||||
|
|
|
@ -362,7 +362,6 @@ CONFIG_NLS_KOI8_R=m
|
|||
CONFIG_NLS_KOI8_U=m
|
||||
CONFIG_NLS_UTF8=m
|
||||
CONFIG_DLM=m
|
||||
CONFIG_KEYS_DEBUG_PROC_KEYS=y
|
||||
CONFIG_CRYPTO_NULL=m
|
||||
CONFIG_CRYPTO_ECB=m
|
||||
CONFIG_CRYPTO_LRW=m
|
||||
|
|
|
@ -412,7 +412,6 @@ CONFIG_DEBUG_FS=y
|
|||
# CONFIG_RCU_CPU_STALL_DETECTOR is not set
|
||||
CONFIG_SYSCTL_SYSCALL_CHECK=y
|
||||
CONFIG_KEYS=y
|
||||
CONFIG_KEYS_DEBUG_PROC_KEYS=y
|
||||
CONFIG_CRYPTO_FIPS=y
|
||||
CONFIG_CRYPTO_NULL=m
|
||||
CONFIG_CRYPTO_CRYPTD=m
|
||||
|
|
|
@ -453,7 +453,6 @@ CONFIG_NLS_KOI8_R=m
|
|||
CONFIG_NLS_KOI8_U=m
|
||||
CONFIG_NLS_UTF8=m
|
||||
CONFIG_DLM=m
|
||||
CONFIG_KEYS_DEBUG_PROC_KEYS=y
|
||||
CONFIG_CRYPTO_NULL=m
|
||||
CONFIG_CRYPTO_ECB=m
|
||||
CONFIG_CRYPTO_LRW=m
|
||||
|
|
|
@ -87,7 +87,6 @@ CONFIG_NFS_V3=y
|
|||
CONFIG_ROOT_NFS=y
|
||||
CONFIG_DLM=m
|
||||
CONFIG_KEYS=y
|
||||
CONFIG_KEYS_DEBUG_PROC_KEYS=y
|
||||
CONFIG_CRYPTO_NULL=m
|
||||
CONFIG_CRYPTO_CRYPTD=m
|
||||
CONFIG_CRYPTO_AUTHENC=m
|
||||
|
|
|
@ -183,7 +183,6 @@ CONFIG_DEBUG_KERNEL=y
|
|||
CONFIG_DEBUG_MUTEXES=y
|
||||
# CONFIG_RCU_CPU_STALL_DETECTOR is not set
|
||||
CONFIG_DEBUG_RODATA=y
|
||||
CONFIG_KEYS_DEBUG_PROC_KEYS=y
|
||||
CONFIG_CRYPTO_NULL=m
|
||||
CONFIG_CRYPTO_TEST=m
|
||||
CONFIG_CRYPTO_HMAC=y
|
||||
|
|
|
@ -193,7 +193,6 @@ CONFIG_HEADERS_CHECK=y
|
|||
CONFIG_DEBUG_KERNEL=y
|
||||
# CONFIG_DEBUG_BUGVERBOSE is not set
|
||||
# CONFIG_RCU_CPU_STALL_DETECTOR is not set
|
||||
CONFIG_KEYS_DEBUG_PROC_KEYS=y
|
||||
CONFIG_CRYPTO_NULL=m
|
||||
CONFIG_CRYPTO_TEST=m
|
||||
CONFIG_CRYPTO_HMAC=y
|
||||
|
|
|
@ -211,7 +211,6 @@ CONFIG_DEBUG_KERNEL=y
|
|||
CONFIG_DEBUG_MUTEXES=y
|
||||
# CONFIG_RCU_CPU_STALL_DETECTOR is not set
|
||||
CONFIG_KEYS=y
|
||||
CONFIG_KEYS_DEBUG_PROC_KEYS=y
|
||||
CONFIG_CRYPTO_NULL=m
|
||||
CONFIG_CRYPTO_TEST=m
|
||||
CONFIG_CRYPTO_MD4=m
|
||||
|
|
|
@ -301,7 +301,6 @@ CONFIG_RCU_CPU_STALL_INFO=y
|
|||
CONFIG_LATENCYTOP=y
|
||||
CONFIG_LKDTM=m
|
||||
CONFIG_KEYS=y
|
||||
CONFIG_KEYS_DEBUG_PROC_KEYS=y
|
||||
CONFIG_CRYPTO_NULL=m
|
||||
CONFIG_CRYPTO_TEST=m
|
||||
CONFIG_CRYPTO_HMAC=y
|
||||
|
|
|
@ -387,7 +387,6 @@ CONFIG_DETECT_HUNG_TASK=y
|
|||
CONFIG_DEBUG_SPINLOCK=y
|
||||
CONFIG_BOOTX_TEXT=y
|
||||
CONFIG_PPC_EARLY_DEBUG=y
|
||||
CONFIG_KEYS_DEBUG_PROC_KEYS=y
|
||||
CONFIG_SECURITY=y
|
||||
CONFIG_SECURITY_NETWORK=y
|
||||
CONFIG_SECURITY_SELINUX=y
|
||||
|
|
|
@ -1175,7 +1175,6 @@ CONFIG_BLK_DEV_IO_TRACE=y
|
|||
CONFIG_XMON=y
|
||||
CONFIG_BOOTX_TEXT=y
|
||||
CONFIG_PPC_EARLY_DEBUG=y
|
||||
CONFIG_KEYS_DEBUG_PROC_KEYS=y
|
||||
CONFIG_SECURITY=y
|
||||
CONFIG_SECURITY_NETWORK=y
|
||||
CONFIG_SECURITY_NETWORK_XFRM=y
|
||||
|
|
|
@ -70,7 +70,6 @@ CONFIG_NFSD=y
|
|||
CONFIG_NFSD_V3_ACL=y
|
||||
CONFIG_NFSD_V4=y
|
||||
# CONFIG_RCU_CPU_STALL_DETECTOR is not set
|
||||
CONFIG_KEYS_DEBUG_PROC_KEYS=y
|
||||
CONFIG_SECURITY=y
|
||||
CONFIG_SECURITY_NETWORK=y
|
||||
CONFIG_CRYPTO_NULL=y
|
||||
|
|
|
@ -374,7 +374,6 @@ CONFIG_DEBUG_CREDENTIALS=y
|
|||
CONFIG_RCU_CPU_STALL_TIMEOUT=60
|
||||
CONFIG_ASYNC_RAID6_TEST=m
|
||||
CONFIG_KGDB=y
|
||||
CONFIG_KEYS_DEBUG_PROC_KEYS=y
|
||||
CONFIG_SECURITY=y
|
||||
CONFIG_SECURITYFS=y
|
||||
CONFIG_SECURITY_NETWORK=y
|
||||
|
|
|
@ -486,7 +486,6 @@ CONFIG_DEBUG_LIST=y
|
|||
CONFIG_DEBUG_CREDENTIALS=y
|
||||
CONFIG_RCU_CPU_STALL_TIMEOUT=60
|
||||
CONFIG_ASYNC_RAID6_TEST=m
|
||||
CONFIG_KEYS_DEBUG_PROC_KEYS=y
|
||||
CONFIG_SECURITY=y
|
||||
CONFIG_SECURITYFS=y
|
||||
CONFIG_SECURITY_NETWORK=y
|
||||
|
|
|
@ -303,7 +303,6 @@ CONFIG_DEBUG_STACKOVERFLOW=y
|
|||
# CONFIG_DEBUG_RODATA_TEST is not set
|
||||
CONFIG_DEBUG_BOOT_PARAMS=y
|
||||
CONFIG_OPTIMIZE_INLINING=y
|
||||
CONFIG_KEYS_DEBUG_PROC_KEYS=y
|
||||
CONFIG_SECURITY=y
|
||||
CONFIG_SECURITY_NETWORK=y
|
||||
CONFIG_SECURITY_SELINUX=y
|
||||
|
|
|
@ -300,7 +300,6 @@ CONFIG_DEBUG_STACKOVERFLOW=y
|
|||
# CONFIG_DEBUG_RODATA_TEST is not set
|
||||
CONFIG_DEBUG_BOOT_PARAMS=y
|
||||
CONFIG_OPTIMIZE_INLINING=y
|
||||
CONFIG_KEYS_DEBUG_PROC_KEYS=y
|
||||
CONFIG_SECURITY=y
|
||||
CONFIG_SECURITY_NETWORK=y
|
||||
CONFIG_SECURITY_SELINUX=y
|
||||
|
|
|
@ -39,4 +39,20 @@ config SYSTEM_TRUSTED_KEYS
|
|||
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.
|
||||
|
||||
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
|
||||
|
|
|
@ -36,29 +36,34 @@ ifndef CONFIG_MODULE_SIG_HASH
|
|||
$(error Could not determine digest type to use from kernel config)
|
||||
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
|
||||
# external private key, because 'make randconfig' might enable such a
|
||||
# boolean option and we unfortunately can't make it depend on !RANDCONFIG.
|
||||
ifeq ($(CONFIG_MODULE_SIG_KEY),"certs/signing_key.pem")
|
||||
$(obj)/signing_key.pem: $(obj)/x509.genkey
|
||||
@echo "###"
|
||||
@echo "### Now generating an X.509 key pair to be used for signing modules."
|
||||
@echo "###"
|
||||
@echo "### 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"
|
||||
@echo "### needs to be run as root, and uses a hardware random"
|
||||
@echo "### number generator if one is available."
|
||||
@echo "###"
|
||||
openssl req -new -nodes -utf8 -$(CONFIG_MODULE_SIG_HASH) -days 36500 \
|
||||
@$(kecho) "###"
|
||||
@$(kecho) "### Now generating an X.509 key pair to be used for signing modules."
|
||||
@$(kecho) "###"
|
||||
@$(kecho) "### If this takes a long time, you might wish to run rngd in the"
|
||||
@$(kecho) "### background to keep the supply of entropy topped up. It"
|
||||
@$(kecho) "### needs to be run as root, and uses a hardware random"
|
||||
@$(kecho) "### number generator if one is available."
|
||||
@$(kecho) "###"
|
||||
$(Q)openssl req -new -nodes -utf8 -$(CONFIG_MODULE_SIG_HASH) -days 36500 \
|
||||
-batch -x509 -config $(obj)/x509.genkey \
|
||||
-outform PEM -out $(obj)/signing_key.pem \
|
||||
-keyout $(obj)/signing_key.pem 2>&1
|
||||
@echo "###"
|
||||
@echo "### Key pair generated."
|
||||
@echo "###"
|
||||
-keyout $(obj)/signing_key.pem \
|
||||
$($(quiet)redirect_openssl)
|
||||
@$(kecho) "###"
|
||||
@$(kecho) "### Key pair generated."
|
||||
@$(kecho) "###"
|
||||
|
||||
$(obj)/x509.genkey:
|
||||
@echo Generating X.509 key generation config
|
||||
@$(kecho) Generating X.509 key generation config
|
||||
@echo >$@ "[ req ]"
|
||||
@echo >>$@ "default_bits = 4096"
|
||||
@echo >>$@ "distinguished_name = req_distinguished_name"
|
||||
|
|
|
@ -13,6 +13,19 @@ __cert_list_start:
|
|||
.incbin "certs/x509_certificate_list"
|
||||
__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
|
||||
.globl VMLINUX_SYMBOL(system_certificate_list_size)
|
||||
VMLINUX_SYMBOL(system_certificate_list_size):
|
||||
|
|
|
@ -84,12 +84,12 @@ static __init int load_system_certificate_list(void)
|
|||
((KEY_POS_ALL & ~KEY_POS_SETATTR) |
|
||||
KEY_USR_VIEW | KEY_USR_READ),
|
||||
KEY_ALLOC_NOT_IN_QUOTA |
|
||||
KEY_ALLOC_TRUSTED);
|
||||
KEY_ALLOC_TRUSTED |
|
||||
KEY_ALLOC_BUILT_IN);
|
||||
if (IS_ERR(key)) {
|
||||
pr_err("Problem loading in-kernel X.509 certificate (%ld)\n",
|
||||
PTR_ERR(key));
|
||||
} else {
|
||||
set_bit(KEY_FLAG_BUILTIN, &key_ref_to_ptr(key)->flags);
|
||||
pr_notice("Loaded X.509 cert '%s'\n",
|
||||
key_ref_to_ptr(key)->description);
|
||||
key_ref_put(key);
|
||||
|
|
|
@ -12,7 +12,6 @@ if ASYMMETRIC_KEY_TYPE
|
|||
config ASYMMETRIC_PUBLIC_KEY_SUBTYPE
|
||||
tristate "Asymmetric public-key crypto algorithm subtype"
|
||||
select MPILIB
|
||||
select PUBLIC_KEY_ALGO_RSA
|
||||
select CRYPTO_HASH_INFO
|
||||
help
|
||||
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.
|
||||
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
|
||||
tristate "X.509 certificate parser"
|
||||
depends on ASYMMETRIC_PUBLIC_KEY_SUBTYPE
|
||||
|
|
|
@ -7,7 +7,6 @@ obj-$(CONFIG_ASYMMETRIC_KEY_TYPE) += asymmetric_keys.o
|
|||
asymmetric_keys-y := asymmetric_type.o signature.o
|
||||
|
||||
obj-$(CONFIG_ASYMMETRIC_PUBLIC_KEY_SUBTYPE) += public_key.o
|
||||
obj-$(CONFIG_PUBLIC_KEY_ALGO_RSA) += rsa.o
|
||||
|
||||
#
|
||||
# X.509 Certificate handling
|
||||
|
@ -16,21 +15,18 @@ obj-$(CONFIG_X509_CERTIFICATE_PARSER) += x509_key_parser.o
|
|||
x509_key_parser-y := \
|
||||
x509-asn1.o \
|
||||
x509_akid-asn1.o \
|
||||
x509_rsakey-asn1.o \
|
||||
x509_cert_parser.o \
|
||||
x509_public_key.o
|
||||
|
||||
$(obj)/x509_cert_parser.o: \
|
||||
$(obj)/x509-asn1.h \
|
||||
$(obj)/x509_akid-asn1.h \
|
||||
$(obj)/x509_rsakey-asn1.h
|
||||
$(obj)/x509_akid-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_rsakey-asn1.o: $(obj)/x509_rsakey-asn1.c $(obj)/x509_rsakey-asn1.h
|
||||
|
||||
clean-files += x509-asn1.c x509-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
|
||||
|
|
|
@ -86,25 +86,25 @@ int mscode_note_digest_algo(void *context, size_t hdrlen,
|
|||
oid = look_up_OID(value, vlen);
|
||||
switch (oid) {
|
||||
case OID_md4:
|
||||
ctx->digest_algo = HASH_ALGO_MD4;
|
||||
ctx->digest_algo = "md4";
|
||||
break;
|
||||
case OID_md5:
|
||||
ctx->digest_algo = HASH_ALGO_MD5;
|
||||
ctx->digest_algo = "md5";
|
||||
break;
|
||||
case OID_sha1:
|
||||
ctx->digest_algo = HASH_ALGO_SHA1;
|
||||
ctx->digest_algo = "sha1";
|
||||
break;
|
||||
case OID_sha256:
|
||||
ctx->digest_algo = HASH_ALGO_SHA256;
|
||||
ctx->digest_algo = "sha256";
|
||||
break;
|
||||
case OID_sha384:
|
||||
ctx->digest_algo = HASH_ALGO_SHA384;
|
||||
ctx->digest_algo = "sha384";
|
||||
break;
|
||||
case OID_sha512:
|
||||
ctx->digest_algo = HASH_ALGO_SHA512;
|
||||
ctx->digest_algo = "sha512";
|
||||
break;
|
||||
case OID_sha224:
|
||||
ctx->digest_algo = HASH_ALGO_SHA224;
|
||||
ctx->digest_algo = "sha224";
|
||||
break;
|
||||
|
||||
case OID__NR:
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
#include <linux/slab.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/oid_registry.h>
|
||||
#include "public_key.h"
|
||||
#include <crypto/public_key.h>
|
||||
#include "pkcs7_parser.h"
|
||||
#include "pkcs7-asn1.h"
|
||||
|
||||
|
@ -44,7 +44,7 @@ struct pkcs7_parse_context {
|
|||
static void pkcs7_free_signed_info(struct pkcs7_signed_info *sinfo)
|
||||
{
|
||||
if (sinfo) {
|
||||
mpi_free(sinfo->sig.mpi[0]);
|
||||
kfree(sinfo->sig.s);
|
||||
kfree(sinfo->sig.digest);
|
||||
kfree(sinfo->signing_cert_id);
|
||||
kfree(sinfo);
|
||||
|
@ -87,7 +87,7 @@ EXPORT_SYMBOL_GPL(pkcs7_free_message);
|
|||
static int pkcs7_check_authattrs(struct pkcs7_message *msg)
|
||||
{
|
||||
struct pkcs7_signed_info *sinfo;
|
||||
bool want;
|
||||
bool want = false;
|
||||
|
||||
sinfo = msg->signed_infos;
|
||||
if (sinfo->authattrs) {
|
||||
|
@ -218,25 +218,25 @@ int pkcs7_sig_note_digest_algo(void *context, size_t hdrlen,
|
|||
|
||||
switch (ctx->last_oid) {
|
||||
case OID_md4:
|
||||
ctx->sinfo->sig.pkey_hash_algo = HASH_ALGO_MD4;
|
||||
ctx->sinfo->sig.hash_algo = "md4";
|
||||
break;
|
||||
case OID_md5:
|
||||
ctx->sinfo->sig.pkey_hash_algo = HASH_ALGO_MD5;
|
||||
ctx->sinfo->sig.hash_algo = "md5";
|
||||
break;
|
||||
case OID_sha1:
|
||||
ctx->sinfo->sig.pkey_hash_algo = HASH_ALGO_SHA1;
|
||||
ctx->sinfo->sig.hash_algo = "sha1";
|
||||
break;
|
||||
case OID_sha256:
|
||||
ctx->sinfo->sig.pkey_hash_algo = HASH_ALGO_SHA256;
|
||||
ctx->sinfo->sig.hash_algo = "sha256";
|
||||
break;
|
||||
case OID_sha384:
|
||||
ctx->sinfo->sig.pkey_hash_algo = HASH_ALGO_SHA384;
|
||||
ctx->sinfo->sig.hash_algo = "sha384";
|
||||
break;
|
||||
case OID_sha512:
|
||||
ctx->sinfo->sig.pkey_hash_algo = HASH_ALGO_SHA512;
|
||||
ctx->sinfo->sig.hash_algo = "sha512";
|
||||
break;
|
||||
case OID_sha224:
|
||||
ctx->sinfo->sig.pkey_hash_algo = HASH_ALGO_SHA224;
|
||||
ctx->sinfo->sig.hash_algo = "sha224";
|
||||
default:
|
||||
printk("Unsupported digest algo: %u\n", ctx->last_oid);
|
||||
return -ENOPKG;
|
||||
|
@ -255,7 +255,7 @@ int pkcs7_sig_note_pkey_algo(void *context, size_t hdrlen,
|
|||
|
||||
switch (ctx->last_oid) {
|
||||
case OID_rsaEncryption:
|
||||
ctx->sinfo->sig.pkey_algo = PKEY_ALGO_RSA;
|
||||
ctx->sinfo->sig.pkey_algo = "rsa";
|
||||
break;
|
||||
default:
|
||||
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)
|
||||
{
|
||||
struct pkcs7_parse_context *ctx = context;
|
||||
MPI mpi;
|
||||
|
||||
BUG_ON(ctx->sinfo->sig.pkey_algo != PKEY_ALGO_RSA);
|
||||
|
||||
mpi = mpi_read_raw_data(value, vlen);
|
||||
if (!mpi)
|
||||
ctx->sinfo->sig.s = kmemdup(value, vlen, GFP_KERNEL);
|
||||
if (!ctx->sinfo->sig.s)
|
||||
return -ENOMEM;
|
||||
|
||||
ctx->sinfo->sig.mpi[0] = mpi;
|
||||
ctx->sinfo->sig.nr_mpi = 1;
|
||||
ctx->sinfo->sig.s_size = vlen;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
#include <linux/asn1.h>
|
||||
#include <linux/key.h>
|
||||
#include <keys/asymmetric-type.h>
|
||||
#include "public_key.h"
|
||||
#include <crypto/public_key.h>
|
||||
#include "pkcs7_parser.h"
|
||||
|
||||
/**
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
#include <linux/err.h>
|
||||
#include <linux/asn1.h>
|
||||
#include <crypto/hash.h>
|
||||
#include "public_key.h"
|
||||
#include <crypto/public_key.h>
|
||||
#include "pkcs7_parser.h"
|
||||
|
||||
/*
|
||||
|
@ -31,17 +31,15 @@ static int pkcs7_digest(struct pkcs7_message *pkcs7,
|
|||
void *digest;
|
||||
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 ||
|
||||
!hash_algo_name[sinfo->sig.pkey_hash_algo])
|
||||
if (!sinfo->sig.hash_algo)
|
||||
return -ENOPKG;
|
||||
|
||||
/* Allocate the hashing algorithm we're going to need and find out how
|
||||
* big the hash operational data will be.
|
||||
*/
|
||||
tfm = crypto_alloc_shash(hash_algo_name[sinfo->sig.pkey_hash_algo],
|
||||
0, 0);
|
||||
tfm = crypto_alloc_shash(sinfo->sig.hash_algo, 0, 0);
|
||||
if (IS_ERR(tfm))
|
||||
return (PTR_ERR(tfm) == -ENOENT) ? -ENOPKG : PTR_ERR(tfm);
|
||||
|
||||
|
|
|
@ -17,32 +17,13 @@
|
|||
#include <linux/kernel.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/seq_file.h>
|
||||
#include <linux/scatterlist.h>
|
||||
#include <keys/asymmetric-subtype.h>
|
||||
#include "public_key.h"
|
||||
#include <crypto/public_key.h>
|
||||
#include <crypto/akcipher.h>
|
||||
|
||||
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.
|
||||
*/
|
||||
|
@ -52,8 +33,7 @@ static void public_key_describe(const struct key *asymmetric_key,
|
|||
struct public_key *key = asymmetric_key->payload.data[asym_crypto];
|
||||
|
||||
if (key)
|
||||
seq_printf(m, "%s.%s",
|
||||
pkey_id_type_name[key->id_type], key->algo->name);
|
||||
seq_printf(m, "%s.%s", key->id_type, key->pkey_algo);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -62,50 +42,116 @@ static void public_key_describe(const struct key *asymmetric_key,
|
|||
void public_key_destroy(void *payload)
|
||||
{
|
||||
struct public_key *key = payload;
|
||||
int i;
|
||||
|
||||
if (key) {
|
||||
for (i = 0; i < ARRAY_SIZE(key->mpi); i++)
|
||||
mpi_free(key->mpi[i]);
|
||||
kfree(key);
|
||||
}
|
||||
if (key)
|
||||
kfree(key->key);
|
||||
kfree(key);
|
||||
}
|
||||
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.
|
||||
*/
|
||||
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_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);
|
||||
BUG_ON(!pk->mpi[0]);
|
||||
BUG_ON(!pk->mpi[1]);
|
||||
pr_devel("==>%s()\n", __func__);
|
||||
|
||||
BUG_ON(!pkey);
|
||||
BUG_ON(!sig);
|
||||
BUG_ON(!sig->digest);
|
||||
BUG_ON(!sig->mpi[0]);
|
||||
BUG_ON(!sig->s);
|
||||
|
||||
algo = pk->algo;
|
||||
if (!algo) {
|
||||
if (pk->pkey_algo >= PKEY_ALGO__LAST)
|
||||
return -ENOPKG;
|
||||
algo = pkey_algo[pk->pkey_algo];
|
||||
if (!algo)
|
||||
return -ENOPKG;
|
||||
alg_name = sig->pkey_algo;
|
||||
if (strcmp(sig->pkey_algo, "rsa") == 0) {
|
||||
/* The data wangled by the RSA algorithm is typically padded
|
||||
* and encoded in some manner, such as EMSA-PKCS1-1_5 [RFC3447
|
||||
* sec 8.2].
|
||||
*/
|
||||
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)
|
||||
return -ENOTSUPP;
|
||||
tfm = crypto_alloc_akcipher(alg_name, 0, 0);
|
||||
if (IS_ERR(tfm))
|
||||
return PTR_ERR(tfm);
|
||||
|
||||
if (sig->nr_mpi != algo->n_sig_mpi) {
|
||||
pr_debug("Signature has %u MPI not %u\n",
|
||||
sig->nr_mpi, algo->n_sig_mpi);
|
||||
return -EINVAL;
|
||||
req = akcipher_request_alloc(tfm, GFP_KERNEL);
|
||||
if (!req)
|
||||
goto error_free_tfm;
|
||||
|
||||
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);
|
||||
|
||||
|
|
|
@ -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);
|
|
@ -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);
|
|
@ -328,12 +328,12 @@ static int pefile_digest_pe(const void *pebuf, unsigned int pelen,
|
|||
void *digest;
|
||||
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
|
||||
* 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))
|
||||
return (PTR_ERR(tfm) == -ENOENT) ? -ENOPKG : PTR_ERR(tfm);
|
||||
|
||||
|
|
|
@ -28,7 +28,7 @@ struct pefile_context {
|
|||
/* PKCS#7 MS Individual Code Signing content */
|
||||
const void *digest; /* Digest */
|
||||
unsigned digest_len; /* Digest length */
|
||||
enum hash_algo digest_algo; /* Digest algorithm */
|
||||
const char *digest_algo; /* Digest algorithm */
|
||||
};
|
||||
|
||||
#define kenter(FMT, ...) \
|
||||
|
|
|
@ -15,11 +15,10 @@
|
|||
#include <linux/slab.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/oid_registry.h>
|
||||
#include "public_key.h"
|
||||
#include <crypto/public_key.h>
|
||||
#include "x509_parser.h"
|
||||
#include "x509-asn1.h"
|
||||
#include "x509_akid-asn1.h"
|
||||
#include "x509_rsakey-asn1.h"
|
||||
|
||||
struct x509_parse_context {
|
||||
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_skid);
|
||||
kfree(cert->sig.digest);
|
||||
mpi_free(cert->sig.rsa.s);
|
||||
kfree(cert->sig.s);
|
||||
kfree(cert);
|
||||
}
|
||||
}
|
||||
|
@ -103,12 +102,12 @@ struct x509_certificate *x509_cert_parse(const void *data, size_t datalen)
|
|||
}
|
||||
}
|
||||
|
||||
/* Decode the public key */
|
||||
ret = asn1_ber_decoder(&x509_rsakey_decoder, ctx,
|
||||
ctx->key, ctx->key_size);
|
||||
if (ret < 0)
|
||||
cert->pub->key = kmemdup(ctx->key, ctx->key_size, GFP_KERNEL);
|
||||
if (!cert->pub->key)
|
||||
goto error_decode;
|
||||
|
||||
cert->pub->keylen = ctx->key_size;
|
||||
|
||||
/* Generate cert issuer + serial number key ID */
|
||||
kid = asymmetric_key_generate_id(cert->raw_serial,
|
||||
cert->raw_serial_size,
|
||||
|
@ -124,6 +123,7 @@ struct x509_certificate *x509_cert_parse(const void *data, size_t datalen)
|
|||
return cert;
|
||||
|
||||
error_decode:
|
||||
kfree(cert->pub->key);
|
||||
kfree(ctx);
|
||||
error_no_ctx:
|
||||
x509_free_certificate(cert);
|
||||
|
@ -188,33 +188,33 @@ int x509_note_pkey_algo(void *context, size_t hdrlen,
|
|||
return -ENOPKG; /* Unsupported combination */
|
||||
|
||||
case OID_md4WithRSAEncryption:
|
||||
ctx->cert->sig.pkey_hash_algo = HASH_ALGO_MD5;
|
||||
ctx->cert->sig.pkey_algo = PKEY_ALGO_RSA;
|
||||
ctx->cert->sig.hash_algo = "md4";
|
||||
ctx->cert->sig.pkey_algo = "rsa";
|
||||
break;
|
||||
|
||||
case OID_sha1WithRSAEncryption:
|
||||
ctx->cert->sig.pkey_hash_algo = HASH_ALGO_SHA1;
|
||||
ctx->cert->sig.pkey_algo = PKEY_ALGO_RSA;
|
||||
ctx->cert->sig.hash_algo = "sha1";
|
||||
ctx->cert->sig.pkey_algo = "rsa";
|
||||
break;
|
||||
|
||||
case OID_sha256WithRSAEncryption:
|
||||
ctx->cert->sig.pkey_hash_algo = HASH_ALGO_SHA256;
|
||||
ctx->cert->sig.pkey_algo = PKEY_ALGO_RSA;
|
||||
ctx->cert->sig.hash_algo = "sha256";
|
||||
ctx->cert->sig.pkey_algo = "rsa";
|
||||
break;
|
||||
|
||||
case OID_sha384WithRSAEncryption:
|
||||
ctx->cert->sig.pkey_hash_algo = HASH_ALGO_SHA384;
|
||||
ctx->cert->sig.pkey_algo = PKEY_ALGO_RSA;
|
||||
ctx->cert->sig.hash_algo = "sha384";
|
||||
ctx->cert->sig.pkey_algo = "rsa";
|
||||
break;
|
||||
|
||||
case OID_sha512WithRSAEncryption:
|
||||
ctx->cert->sig.pkey_hash_algo = HASH_ALGO_SHA512;
|
||||
ctx->cert->sig.pkey_algo = PKEY_ALGO_RSA;
|
||||
ctx->cert->sig.hash_algo = "sha512";
|
||||
ctx->cert->sig.pkey_algo = "rsa";
|
||||
break;
|
||||
|
||||
case OID_sha224WithRSAEncryption:
|
||||
ctx->cert->sig.pkey_hash_algo = HASH_ALGO_SHA224;
|
||||
ctx->cert->sig.pkey_algo = PKEY_ALGO_RSA;
|
||||
ctx->cert->sig.hash_algo = "sha224";
|
||||
ctx->cert->sig.pkey_algo = "rsa";
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -396,7 +396,7 @@ int x509_extract_key_data(void *context, size_t hdrlen,
|
|||
if (ctx->last_oid != OID_rsaEncryption)
|
||||
return -ENOPKG;
|
||||
|
||||
ctx->cert->pub->pkey_algo = PKEY_ALGO_RSA;
|
||||
ctx->cert->pub->pkey_algo = "rsa";
|
||||
|
||||
/* Discard the BIT STRING metadata */
|
||||
ctx->key = value + 1;
|
||||
|
@ -404,29 +404,6 @@ int x509_extract_key_data(void *context, size_t hdrlen,
|
|||
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) */
|
||||
#define SEQ_TAG_KEYID (ASN1_CONT << 6)
|
||||
|
||||
|
@ -494,7 +471,7 @@ int x509_decode_time(time64_t *_t, size_t hdrlen,
|
|||
unsigned char tag,
|
||||
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 };
|
||||
const unsigned char *p = value;
|
||||
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) {
|
||||
mon_len = 29;
|
||||
if (year % 100 == 0) {
|
||||
year /= 100;
|
||||
if (year % 4 != 0)
|
||||
mon_len = 28;
|
||||
mon_len = 28;
|
||||
if (year % 400 == 0)
|
||||
mon_len = 29;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (day < 1 || day > mon_len ||
|
||||
hour > 23 ||
|
||||
hour > 24 || /* ISO 8601 permits 24:00:00 as midnight tomorrow */
|
||||
min > 59 ||
|
||||
sec > 59)
|
||||
sec > 60) /* ISO 8601 permits leap seconds [X.680 46.3] */
|
||||
goto invalid_time;
|
||||
|
||||
*_t = mktime64(year, mon, day, hour, min, sec);
|
||||
|
|
|
@ -13,15 +13,11 @@
|
|||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/mpi.h>
|
||||
#include <linux/asn1_decoder.h>
|
||||
#include <keys/asymmetric-subtype.h>
|
||||
#include <keys/asymmetric-parser.h>
|
||||
#include <keys/system_keyring.h>
|
||||
#include <crypto/hash.h>
|
||||
#include "asymmetric_keys.h"
|
||||
#include "public_key.h"
|
||||
#include "x509_parser.h"
|
||||
|
||||
static bool use_builtin_keys;
|
||||
|
@ -167,18 +163,20 @@ int x509_get_sig_params(struct x509_certificate *cert)
|
|||
|
||||
if (cert->unsupported_crypto)
|
||||
return -ENOPKG;
|
||||
if (cert->sig.rsa.s)
|
||||
if (cert->sig.s)
|
||||
return 0;
|
||||
|
||||
cert->sig.rsa.s = mpi_read_raw_data(cert->raw_sig, cert->raw_sig_size);
|
||||
if (!cert->sig.rsa.s)
|
||||
cert->sig.s = kmemdup(cert->raw_sig, cert->raw_sig_size,
|
||||
GFP_KERNEL);
|
||||
if (!cert->sig.s)
|
||||
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
|
||||
* 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 (PTR_ERR(tfm) == -ENOENT) {
|
||||
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 Subject: %s\n", cert->subject);
|
||||
|
||||
if (cert->pub->pkey_algo >= PKEY_ALGO__LAST ||
|
||||
cert->sig.pkey_algo >= PKEY_ALGO__LAST ||
|
||||
cert->sig.pkey_hash_algo >= PKEY_HASH__LAST ||
|
||||
!pkey_algo[cert->pub->pkey_algo] ||
|
||||
!pkey_algo[cert->sig.pkey_algo] ||
|
||||
!hash_algo_name[cert->sig.pkey_hash_algo]) {
|
||||
if (!cert->pub->pkey_algo ||
|
||||
!cert->sig.pkey_algo ||
|
||||
!cert->sig.hash_algo) {
|
||||
ret = -ENOPKG;
|
||||
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 Signature: %s + %s\n",
|
||||
pkey_algo_name[cert->sig.pkey_algo],
|
||||
hash_algo_name[cert->sig.pkey_hash_algo]);
|
||||
cert->sig.pkey_algo,
|
||||
cert->sig.hash_algo);
|
||||
|
||||
cert->pub->algo = pkey_algo[cert->pub->pkey_algo];
|
||||
cert->pub->id_type = PKEY_ID_X509;
|
||||
cert->pub->id_type = "X509";
|
||||
|
||||
/* Check the signature on the key if it appears to be self-signed */
|
||||
if ((!cert->akid_skid && !cert->akid_id) ||
|
||||
|
|
|
@ -1,4 +0,0 @@
|
|||
RSAPublicKey ::= SEQUENCE {
|
||||
modulus INTEGER ({ rsa_extract_mpi }), -- n
|
||||
publicExponent INTEGER ({ rsa_extract_mpi }) -- e
|
||||
}
|
|
@ -18,12 +18,89 @@
|
|||
#include <linux/module.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 crypto_akcipher *child;
|
||||
|
||||
const char *hash_name;
|
||||
unsigned int key_size;
|
||||
};
|
||||
|
||||
struct pkcs1pad_inst_ctx {
|
||||
struct crypto_akcipher_spawn spawn;
|
||||
const char *hash_name;
|
||||
};
|
||||
|
||||
struct pkcs1pad_request {
|
||||
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 pkcs1pad_ctx *ctx = akcipher_tfm_ctx(tfm);
|
||||
struct pkcs1pad_request *req_ctx = akcipher_request_ctx(req);
|
||||
const struct rsa_asn1_template *digest_info = NULL;
|
||||
int err;
|
||||
unsigned int ps_end;
|
||||
unsigned int ps_end, digest_size = 0;
|
||||
|
||||
if (!ctx->key_size)
|
||||
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;
|
||||
|
||||
if (req->dst_len < ctx->key_size) {
|
||||
|
@ -371,11 +457,16 @@ static int pkcs1pad_sign(struct akcipher_request *req)
|
|||
if (!req_ctx->in_buf)
|
||||
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;
|
||||
memset(req_ctx->in_buf + 1, 0xff, ps_end - 1);
|
||||
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,
|
||||
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 pkcs1pad_ctx *ctx = akcipher_tfm_ctx(tfm);
|
||||
struct pkcs1pad_request *req_ctx = akcipher_request_ctx(req);
|
||||
const struct rsa_asn1_template *digest_info;
|
||||
unsigned int pos;
|
||||
|
||||
if (err == -EOVERFLOW)
|
||||
|
@ -422,20 +514,33 @@ static int pkcs1pad_verify_complete(struct akcipher_request *req, int err)
|
|||
goto done;
|
||||
}
|
||||
|
||||
if (req_ctx->out_buf[0] != 0x01) {
|
||||
err = -EINVAL;
|
||||
err = -EBADMSG;
|
||||
if (req_ctx->out_buf[0] != 0x01)
|
||||
goto done;
|
||||
}
|
||||
|
||||
for (pos = 1; pos < req_ctx->child_req.dst_len; pos++)
|
||||
if (req_ctx->out_buf[pos] != 0xff)
|
||||
break;
|
||||
|
||||
if (pos < 9 || pos == req_ctx->child_req.dst_len ||
|
||||
req_ctx->out_buf[pos] != 0x00) {
|
||||
err = -EINVAL;
|
||||
req_ctx->out_buf[pos] != 0x00)
|
||||
goto done;
|
||||
}
|
||||
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)
|
||||
err = -EOVERFLOW;
|
||||
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_nents_for_len(req->dst, req->dst_len),
|
||||
req_ctx->out_buf + pos, req->dst_len);
|
||||
|
||||
done:
|
||||
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);
|
||||
int err;
|
||||
|
||||
if (!ctx->key_size || req->src_len != ctx->key_size)
|
||||
if (!ctx->key_size || req->src_len < ctx->key_size)
|
||||
return -EINVAL;
|
||||
|
||||
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)
|
||||
{
|
||||
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 crypto_akcipher *child_tfm;
|
||||
|
||||
|
@ -526,7 +631,7 @@ static int pkcs1pad_init_tfm(struct crypto_akcipher *tfm)
|
|||
return PTR_ERR(child_tfm);
|
||||
|
||||
ctx->child = child_tfm;
|
||||
|
||||
ctx->hash_name = ictx->hash_name;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -539,10 +644,11 @@ static void pkcs1pad_exit_tfm(struct crypto_akcipher *tfm)
|
|||
|
||||
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);
|
||||
|
||||
kfree(ctx->hash_name);
|
||||
kfree(inst);
|
||||
}
|
||||
|
||||
|
@ -550,9 +656,11 @@ static int pkcs1pad_create(struct crypto_template *tmpl, struct rtattr **tb)
|
|||
{
|
||||
struct crypto_attr_type *algt;
|
||||
struct akcipher_instance *inst;
|
||||
struct pkcs1pad_inst_ctx *ctx;
|
||||
struct crypto_akcipher_spawn *spawn;
|
||||
struct akcipher_alg *rsa_alg;
|
||||
const char *rsa_alg_name;
|
||||
const char *hash_name;
|
||||
int err;
|
||||
|
||||
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))
|
||||
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)
|
||||
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));
|
||||
err = crypto_grab_akcipher(spawn, rsa_alg_name, 0,
|
||||
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);
|
||||
|
||||
err = -ENAMETOOLONG;
|
||||
if (snprintf(inst->alg.base.cra_name,
|
||||
CRYPTO_MAX_ALG_NAME, "pkcs1pad(%s)",
|
||||
rsa_alg->base.cra_name) >=
|
||||
CRYPTO_MAX_ALG_NAME ||
|
||||
snprintf(inst->alg.base.cra_driver_name,
|
||||
CRYPTO_MAX_ALG_NAME, "pkcs1pad(%s)",
|
||||
rsa_alg->base.cra_driver_name) >=
|
||||
CRYPTO_MAX_ALG_NAME)
|
||||
|
||||
if (!hash_name) {
|
||||
if (snprintf(inst->alg.base.cra_name,
|
||||
CRYPTO_MAX_ALG_NAME, "pkcs1pad(%s)",
|
||||
rsa_alg->base.cra_name) >=
|
||||
CRYPTO_MAX_ALG_NAME ||
|
||||
snprintf(inst->alg.base.cra_driver_name,
|
||||
CRYPTO_MAX_ALG_NAME, "pkcs1pad(%s)",
|
||||
rsa_alg->base.cra_driver_name) >=
|
||||
CRYPTO_MAX_ALG_NAME)
|
||||
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_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);
|
||||
if (err)
|
||||
goto out_drop_alg;
|
||||
goto out_free_hash;
|
||||
|
||||
return 0;
|
||||
|
||||
out_free_hash:
|
||||
kfree(ctx->hash_name);
|
||||
out_drop_alg:
|
||||
crypto_drop_akcipher(spawn);
|
||||
out_free_inst:
|
||||
|
|
|
@ -14,30 +14,6 @@
|
|||
#ifndef _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.
|
||||
*/
|
||||
|
@ -59,31 +35,10 @@ extern const char *const key_being_used_for[NR__KEY_BEING_USED_FOR];
|
|||
* part.
|
||||
*/
|
||||
struct public_key {
|
||||
const struct public_key_algorithm *algo;
|
||||
u8 capabilities;
|
||||
#define PKEY_CAN_ENCRYPT 0x01
|
||||
#define PKEY_CAN_DECRYPT 0x02
|
||||
#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;
|
||||
};
|
||||
void *key;
|
||||
u32 keylen;
|
||||
const char *id_type;
|
||||
const char *pkey_algo;
|
||||
};
|
||||
|
||||
extern void public_key_destroy(void *payload);
|
||||
|
@ -92,23 +47,15 @@ extern void public_key_destroy(void *payload);
|
|||
* Public key cryptography signature data
|
||||
*/
|
||||
struct public_key_signature {
|
||||
u8 *s; /* Signature */
|
||||
u32 s_size; /* Number of bytes in signature */
|
||||
u8 *digest;
|
||||
u8 digest_size; /* Number of bytes in digest */
|
||||
u8 nr_mpi; /* Occupancy of mpi[] */
|
||||
enum pkey_algo pkey_algo : 8;
|
||||
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;
|
||||
};
|
||||
u8 digest_size; /* Number of bytes in digest */
|
||||
const char *pkey_algo;
|
||||
const char *hash_algo;
|
||||
};
|
||||
|
||||
extern struct asymmetric_key_subtype public_key_subtype;
|
||||
struct key;
|
||||
extern int verify_signature(const struct key *key,
|
||||
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,
|
||||
bool partial);
|
||||
|
||||
int public_key_verify_signature(const struct public_key *pkey,
|
||||
const struct public_key_signature *sig);
|
||||
|
||||
#endif /* _LINUX_PUBLIC_KEY_H */
|
||||
|
|
|
@ -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_NOT_IN_QUOTA 0x0002 /* not in quota */
|
||||
#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_invalidate(struct key *key);
|
||||
|
|
|
@ -1757,9 +1757,9 @@ config SYSTEM_DATA_VERIFICATION
|
|||
select SYSTEM_TRUSTED_KEYRING
|
||||
select KEYS
|
||||
select CRYPTO
|
||||
select CRYPTO_RSA
|
||||
select ASYMMETRIC_KEY_TYPE
|
||||
select ASYMMETRIC_PUBLIC_KEY_SUBTYPE
|
||||
select PUBLIC_KEY_ALGO_RSA
|
||||
select ASN1
|
||||
select OID_REGISTRY
|
||||
select X509_CERTIFICATE_PARSER
|
||||
|
|
|
@ -11,10 +11,17 @@
|
|||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/string.h>
|
||||
#include <keys/system_keyring.h>
|
||||
#include <crypto/public_key.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.
|
||||
*
|
||||
|
|
|
@ -322,6 +322,13 @@ EXPORT_SYMBOL(timespec_trunc);
|
|||
* -year/100+year/400 terms, and add 10.]
|
||||
*
|
||||
* 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,
|
||||
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)
|
||||
(year/4 - year/100 + year/400 + 367*mon/12 + day) +
|
||||
year*365 - 719499
|
||||
)*24 + hour /* now have hours */
|
||||
)*24 + hour /* now have hours - midnight tomorrow handled here */
|
||||
)*60 + min /* now have minutes */
|
||||
)*60 + sec; /* finally seconds */
|
||||
}
|
||||
|
|
|
@ -13,3 +13,4 @@ sortextable
|
|||
asn1_compiler
|
||||
extract-cert
|
||||
sign-file
|
||||
insert-sys-cert
|
||||
|
|
|
@ -19,6 +19,7 @@ hostprogs-$(CONFIG_BUILDTIME_EXTABLE_SORT) += sortextable
|
|||
hostprogs-$(CONFIG_ASN1) += asn1_compiler
|
||||
hostprogs-$(CONFIG_MODULE_SIG) += sign-file
|
||||
hostprogs-$(CONFIG_SYSTEM_TRUSTED_KEYRING) += extract-cert
|
||||
hostprogs-$(CONFIG_SYSTEM_EXTRA_CERTIFICATE) += insert-sys-cert
|
||||
|
||||
HOSTCFLAGS_sortextable.o = -I$(srctree)/tools/include
|
||||
HOSTCFLAGS_asn1_compiler.o = -I$(srctree)/include
|
||||
|
|
|
@ -91,13 +91,15 @@ print "Have $nr_symbols symbols\n";
|
|||
|
||||
die "Can't find system certificate list"
|
||||
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 $end = Math::BigInt->new($symbols{"__cert_list_end"});
|
||||
my $size = $end - $start;
|
||||
my $end;
|
||||
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;
|
||||
foreach my $sec (@sections) {
|
||||
|
@ -110,11 +112,24 @@ foreach my $sec (@sections) {
|
|||
next unless ($start >= $s_vma);
|
||||
next if ($start >= $s_vend);
|
||||
|
||||
die "Cert object partially overflows section $s_name\n"
|
||||
if ($end > $s_vend);
|
||||
die "Certificate list size was not found on the same section\n"
|
||||
if ($size_sym < $s_vma || $size_sym > $s_vend);
|
||||
|
||||
die "Cert object in multiple sections: ", $s_name, " and ", $s->{name}, "\n"
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -127,8 +142,6 @@ my $foff = $start - $s->{vma} + $s->{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)));
|
||||
my $buf = "";
|
||||
my $len = sysread(FD, $buf, $size);
|
||||
|
|
|
@ -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);
|
||||
}
|
|
@ -2,9 +2,11 @@
|
|||
*
|
||||
* Copyright © 2014-2015 Red Hat, Inc. All Rights Reserved.
|
||||
* Copyright © 2015 Intel Corporation.
|
||||
* Copyright © 2016 Hewlett Packard Enterprise Development LP
|
||||
*
|
||||
* Authors: David Howells <dhowells@redhat.com>
|
||||
* David Woodhouse <dwmw2@infradead.org>
|
||||
* Juerg Haefliger <juerg.haefliger@hpe.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* 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
|
||||
* the case.
|
||||
*/
|
||||
#if OPENSSL_VERSION_NUMBER < 0x10000000L
|
||||
#if OPENSSL_VERSION_NUMBER < 0x10000000L || defined(OPENSSL_NO_CMS)
|
||||
#define USE_PKCS7
|
||||
#endif
|
||||
#ifndef USE_PKCS7
|
||||
|
@ -67,6 +69,8 @@ void format(void)
|
|||
{
|
||||
fprintf(stderr,
|
||||
"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);
|
||||
}
|
||||
|
||||
|
@ -126,26 +130,84 @@ static int pem_pw_cb(char *buf, int len, int w, void *v)
|
|||
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)
|
||||
{
|
||||
struct module_signature sig_info = { .id_type = PKEY_ID_PKCS7 };
|
||||
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 sign_only = false;
|
||||
bool raw_sig = false;
|
||||
unsigned char buf[4096];
|
||||
unsigned long module_size, sig_size;
|
||||
unsigned int use_signed_attrs;
|
||||
const EVP_MD *digest_algo;
|
||||
EVP_PKEY *private_key;
|
||||
#ifndef USE_PKCS7
|
||||
CMS_ContentInfo *cms;
|
||||
CMS_ContentInfo *cms = NULL;
|
||||
unsigned int use_keyid = 0;
|
||||
#else
|
||||
PKCS7 *pkcs7;
|
||||
PKCS7 *pkcs7 = NULL;
|
||||
#endif
|
||||
X509 *x509;
|
||||
BIO *b, *bd = NULL, *bm;
|
||||
BIO *bd, *bm;
|
||||
int opt, n;
|
||||
OpenSSL_add_all_algorithms();
|
||||
ERR_load_crypto_strings();
|
||||
|
@ -160,8 +222,9 @@ int main(int argc, char **argv)
|
|||
#endif
|
||||
|
||||
do {
|
||||
opt = getopt(argc, argv, "dpk");
|
||||
opt = getopt(argc, argv, "sdpk");
|
||||
switch (opt) {
|
||||
case 's': raw_sig = true; break;
|
||||
case 'p': save_sig = true; break;
|
||||
case 'd': sign_only = true; save_sig = true; break;
|
||||
#ifndef USE_PKCS7
|
||||
|
@ -177,8 +240,13 @@ int main(int argc, char **argv)
|
|||
if (argc < 4 || argc > 5)
|
||||
format();
|
||||
|
||||
hash_algo = argv[0];
|
||||
private_key_name = argv[1];
|
||||
if (raw_sig) {
|
||||
raw_sig_name = argv[0];
|
||||
hash_algo = argv[1];
|
||||
} else {
|
||||
hash_algo = argv[0];
|
||||
private_key_name = argv[1];
|
||||
}
|
||||
x509_name = argv[2];
|
||||
module_name = argv[3];
|
||||
if (argc == 5) {
|
||||
|
@ -198,101 +266,74 @@ int main(int argc, char **argv)
|
|||
}
|
||||
#endif
|
||||
|
||||
/* Read the private key and the X.509 cert the PKCS#7 message
|
||||
* will point to.
|
||||
*/
|
||||
if (!strncmp(private_key_name, "pkcs11:", 7)) {
|
||||
ENGINE *e;
|
||||
/* Open the module file */
|
||||
bm = BIO_new_file(module_name, "rb");
|
||||
ERR(!bm, "%s", module_name);
|
||||
|
||||
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 {
|
||||
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);
|
||||
}
|
||||
if (!raw_sig) {
|
||||
/* Read the private key and the X.509 cert the PKCS#7 message
|
||||
* will point to.
|
||||
*/
|
||||
private_key = read_private_key(private_key_name);
|
||||
x509 = read_x509(x509_name);
|
||||
|
||||
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();
|
||||
/* 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");
|
||||
|
||||
#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;
|
||||
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
|
||||
* across as we read it.
|
||||
*/
|
||||
if (!sign_only) {
|
||||
bd = BIO_new_file(dest_name, "wb");
|
||||
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;
|
||||
bd = BIO_new_file(dest_name, "wb");
|
||||
ERR(!bd, "%s", dest_name);
|
||||
|
||||
/* Append the marker and the PKCS#7 message to the destination file */
|
||||
ERR(BIO_reset(bm) < 0, "%s", module_name);
|
||||
|
@ -300,14 +341,29 @@ int main(int argc, char **argv)
|
|||
n > 0) {
|
||||
ERR(BIO_write(bd, buf, n) < 0, "%s", dest_name);
|
||||
}
|
||||
BIO_free(bm);
|
||||
ERR(n < 0, "%s", module_name);
|
||||
module_size = BIO_number_written(bd);
|
||||
|
||||
if (!raw_sig) {
|
||||
#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
|
||||
ERR(i2d_PKCS7_bio(bd, pkcs7) < 0, "%s", dest_name);
|
||||
ERR(i2d_PKCS7_bio(bd, pkcs7) < 0, "%s", dest_name);
|
||||
#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_info.sig_len = htonl(sig_size);
|
||||
ERR(BIO_write(bd, &sig_info, sizeof(sig_info)) < 0, "%s", dest_name);
|
||||
|
|
|
@ -36,6 +36,7 @@ config INTEGRITY_ASYMMETRIC_KEYS
|
|||
select ASYMMETRIC_KEY_TYPE
|
||||
select ASYMMETRIC_PUBLIC_KEY_SUBTYPE
|
||||
select PUBLIC_KEY_ALGO_RSA
|
||||
select CRYPTO_RSA
|
||||
select X509_CERTIFICATE_PARSER
|
||||
help
|
||||
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"
|
||||
depends on SYSTEM_TRUSTED_KEYRING
|
||||
depends on INTEGRITY_ASYMMETRIC_KEYS
|
||||
select KEYS_DEBUG_PROC_KEYS
|
||||
default y
|
||||
help
|
||||
This option requires that all keys added to the .ima and
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
#include <linux/ratelimit.h>
|
||||
#include <linux/key-type.h>
|
||||
#include <crypto/public_key.h>
|
||||
#include <crypto/hash_info.h>
|
||||
#include <keys/asymmetric-type.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))
|
||||
return -EBADMSG;
|
||||
|
||||
if (hdr->hash_algo >= PKEY_HASH__LAST)
|
||||
if (hdr->hash_algo >= HASH_ALGO__LAST)
|
||||
return -ENOPKG;
|
||||
|
||||
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));
|
||||
|
||||
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_size = datalen;
|
||||
pks.nr_mpi = 1;
|
||||
pks.rsa.s = mpi_read_raw_data(hdr->sig, siglen);
|
||||
|
||||
if (pks.rsa.s)
|
||||
ret = verify_signature(key, &pks);
|
||||
|
||||
mpi_free(pks.rsa.s);
|
||||
pks.s = hdr->sig;
|
||||
pks.s_size = siglen;
|
||||
ret = verify_signature(key, &pks);
|
||||
key_put(key);
|
||||
pr_debug("%s() = %d\n", __func__, ret);
|
||||
return ret;
|
||||
|
|
|
@ -90,7 +90,7 @@ struct ima_digest_data {
|
|||
struct signature_v2_hdr {
|
||||
uint8_t type; /* xattr type */
|
||||
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 */
|
||||
uint16_t sig_size; /* signature size */
|
||||
uint8_t sig[0]; /* signature payload */
|
||||
|
|
|
@ -9,7 +9,6 @@
|
|||
* 2 of the Licence, or (at your option) any later version.
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/seq_file.h>
|
||||
#include <linux/file.h>
|
||||
|
@ -18,8 +17,6 @@
|
|||
#include <keys/user-type.h>
|
||||
#include <keys/big_key-type.h>
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
/*
|
||||
* 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;
|
||||
}
|
||||
|
||||
/*
|
||||
* Module stuff
|
||||
*/
|
||||
static int __init big_key_init(void)
|
||||
{
|
||||
return register_key_type(&key_type_big_key);
|
||||
}
|
||||
|
||||
static void __exit big_key_cleanup(void)
|
||||
{
|
||||
unregister_key_type(&key_type_big_key);
|
||||
}
|
||||
|
||||
module_init(big_key_init);
|
||||
module_exit(big_key_cleanup);
|
||||
device_initcall(big_key_init);
|
||||
|
|
|
@ -296,6 +296,8 @@ struct key *key_alloc(struct key_type *type, const char *desc,
|
|||
key->flags |= 1 << KEY_FLAG_IN_QUOTA;
|
||||
if (flags & KEY_ALLOC_TRUSTED)
|
||||
key->flags |= 1 << KEY_FLAG_TRUSTED;
|
||||
if (flags & KEY_ALLOC_BUILT_IN)
|
||||
key->flags |= 1 << KEY_FLAG_BUILTIN;
|
||||
|
||||
#ifdef KEY_DEBUGGING
|
||||
key->magic = KEY_DEBUG_MAGIC;
|
||||
|
|
Loading…
Reference in New Issue