evm: digital signature verification extension
Subsystems (4)
cover evm: digital signature verification extension
Hello,
Updated before LSS.
Changes to version 1.1:
- GnuPG MPI library has been refactored with lindent and checkpatch errors and warnings has been fixed.
- creation of evm keyring has been remove. It is done now in user space.
- related ksign and evm patches has been squashed.
- patch descriptions has been updated.
As EVM patches were recently merged to security-testing-2.6#next, it is a good time to resend evm signature verification patches for active discussion. Last time I forgot --cc linux-crypto. Here it is.
This patchset introduces digital signature extensions for the IMA/EVM kernel integrity subsystem and is applied on the top of the EVM patches posted to LSM mailing list earlier.
Currently EVM stores the HMAC in security.evm to verify integrity of the file's metadata. This is quite sufficient for individually installed systems, where a system unique HMAC key can be provisioned and the initial filesystem labeling can be done.
Software installation for consumer electronics or embedded devices is usually done via flashing a filesystem image. Initial filesystem image labeling is done during image creation process. It either has to be done (1) using a system unique HMAC key or (2) using an image specific HMAC key. In first case, those keys are either unknown, or a unique image has to be created for thousand or millions of devices, which is not feasible. The second case, using an image specific HMAC key, would require (2.1) provisioning of the key to millions of devices, which is not easily feasible or (2.1) encrypting the key with a shared symmetric key which is not a strong security measure.
Digital signature extension for EVM provides a solution to perform labeling of the image using a single digital private key and use a known public key to verify the signature. For performance reasons, after verification, signature is replaced with local HMAC.
Digital signature verification uses RSA algorithm, implemented using cut-down port of multi-precision integers (MPI) library from GnuPG and has been taken from RedHat Enterprise Linux kernel (MODSIGN patches). Decision to use this library was made, because its performance was 2 times better than other ports such as libtommath library.
The motivation for integrity protection, in general, is to protect against offline modifications. The runtime protection is ensured via access control mechanisms. Of particular importance is protecting users or owners from being sold or given tampered devices, which can do nasty things such as spying or stealing personal data. Integrity protection ensures that modifications of the system will not remain undetected. The EVM digital signature extension makes this feasible for consumerelectronics/embedded devices.
There is also a second patchset which implements digital signature support for IMA-appraisal patchset, which is planned to be reviewed right after the IMA-appaisal review.
All patches on the top of ima-2.6 (3.x.x) kernel are available here:git://git.kernel.org/pub/scm/linux/kernel/git/kasatkin/ima-ksign.git
Supporting utility for key handling and signing is available here:
http://meego.gitorious.org/meego-platform-security/evm-utils
Regards,
Dmitry
Dmitry Kasatkin (3):
crypto: GnuPG based MPI lib
crypto: ksign - digital signature verification support
evm: digital signature verification support
crypto/Kconfig | 19 + crypto/Makefile | 4 + crypto/ksign.c | 269 +++++++ crypto/mpi/Makefile | 30 + crypto/mpi/generic_mpi-asm-defs.h | 4 + crypto/mpi/generic_mpih-add1.c | 61 ++ crypto/mpi/generic_mpih-lshift.c | 63 ++ crypto/mpi/generic_mpih-mul1.c | 57 ++ crypto/mpi/generic_mpih-mul2.c | 60 ++ crypto/mpi/generic_mpih-mul3.c | 61 ++ crypto/mpi/generic_mpih-rshift.c | 63 ++ crypto/mpi/generic_mpih-sub1.c | 60 ++ crypto/mpi/generic_udiv-w-sdiv.c | 106 +++ crypto/mpi/longlong.h | 1478 +++++++++++++++++++++++++++++++++++ crypto/mpi/mpi-add.c | 234 ++++++ crypto/mpi/mpi-bit.c | 235 ++++++ crypto/mpi/mpi-cmp.c | 68 ++ crypto/mpi/mpi-div.c | 333 ++++++++ crypto/mpi/mpi-gcd.c | 59 ++ crypto/mpi/mpi-inline.c | 31 + crypto/mpi/mpi-inline.h | 122 +++ crypto/mpi/mpi-internal.h | 260 ++++++ crypto/mpi/mpi-inv.c | 187 +++++ crypto/mpi/mpi-mpow.c | 133 ++++ crypto/mpi/mpi-mul.c | 194 +++++ crypto/mpi/mpi-pow.c | 322 ++++++++ crypto/mpi/mpi-scan.c | 136 ++++ crypto/mpi/mpicoder.c | 361 +++++++++ crypto/mpi/mpih-cmp.c | 56 ++ crypto/mpi/mpih-div.c | 541 +++++++++++++ crypto/mpi/mpih-mul.c | 527 +++++++++++++ crypto/mpi/mpiutil.c | 206 +++++ include/linux/crypto/ksign.h | 67 ++ include/linux/crypto/mpi.h | 146 ++++ security/integrity/evm/Kconfig | 15 + security/integrity/evm/evm.h | 12 + security/integrity/evm/evm_crypto.c | 66 ++- security/integrity/evm/evm_main.c | 125 +++- 38 files changed, 6741 insertions(+), 30 deletions(-) create mode 100644 crypto/ksign.c create mode 100644 crypto/mpi/Makefile create mode 100644 crypto/mpi/generic_mpi-asm-defs.h create mode 100644 crypto/mpi/generic_mpih-add1.c create mode 100644 crypto/mpi/generic_mpih-lshift.c create mode 100644 crypto/mpi/generic_mpih-mul1.c create mode 100644 crypto/mpi/generic_mpih-mul2.c create mode 100644 crypto/mpi/generic_mpih-mul3.c create mode 100644 crypto/mpi/generic_mpih-rshift.c create mode 100644 crypto/mpi/generic_mpih-sub1.c create mode 100644 crypto/mpi/generic_udiv-w-sdiv.c create mode 100644 crypto/mpi/longlong.h create mode 100644 crypto/mpi/mpi-add.c create mode 100644 crypto/mpi/mpi-bit.c create mode 100644 crypto/mpi/mpi-cmp.c create mode 100644 crypto/mpi/mpi-div.c create mode 100644 crypto/mpi/mpi-gcd.c create mode 100644 crypto/mpi/mpi-inline.c create mode 100644 crypto/mpi/mpi-inline.h create mode 100644 crypto/mpi/mpi-internal.h create mode 100644 crypto/mpi/mpi-inv.c create mode 100644 crypto/mpi/mpi-mpow.c create mode 100644 crypto/mpi/mpi-mul.c create mode 100644 crypto/mpi/mpi-pow.c create mode 100644 crypto/mpi/mpi-scan.c create mode 100644 crypto/mpi/mpicoder.c create mode 100644 crypto/mpi/mpih-cmp.c create mode 100644 crypto/mpi/mpih-div.c create mode 100644 crypto/mpi/mpih-mul.c create mode 100644 crypto/mpi/mpiutil.c create mode 100644 include/linux/crypto/ksign.h create mode 100644 include/linux/crypto/mpi.h
Signature · 1 line
1.7.4.1
RFC 1/3 crypto: GnuPG based MPI lib
Adds the multi-precision-integer maths library which was originally taken from GnuPG and ported to the kernel by (among others) David Howells. This version is taken from Fedora kernel 2.6.32-71.14.1.el6.
The difference is that checkpatch reported errors and warning has been fixed.
This library is used to implemenet RSA digital signature verification used in IMA/EVM integrity protection subsystem.
--- crypto/Kconfig | 6 + crypto/Makefile | 1 + crypto/mpi/Makefile | 30 + crypto/mpi/generic_mpi-asm-defs.h | 4 + crypto/mpi/generic_mpih-add1.c | 61 ++ crypto/mpi/generic_mpih-lshift.c | 63 ++ crypto/mpi/generic_mpih-mul1.c | 57 ++ crypto/mpi/generic_mpih-mul2.c | 60 ++ crypto/mpi/generic_mpih-mul3.c | 61 ++ crypto/mpi/generic_mpih-rshift.c | 63 ++ crypto/mpi/generic_mpih-sub1.c | 60 ++ crypto/mpi/generic_udiv-w-sdiv.c | 106 +++ crypto/mpi/longlong.h | 1478 +++++++++++++++++++++++++++++++++++++ crypto/mpi/mpi-add.c | 234 ++++++ crypto/mpi/mpi-bit.c | 235 ++++++ crypto/mpi/mpi-cmp.c | 68 ++ crypto/mpi/mpi-div.c | 333 +++++++++ crypto/mpi/mpi-gcd.c | 59 ++ crypto/mpi/mpi-inline.c | 31 + crypto/mpi/mpi-inline.h | 122 +++ crypto/mpi/mpi-internal.h | 260 +++++++ crypto/mpi/mpi-inv.c | 187 +++++ crypto/mpi/mpi-mpow.c | 133 ++++ crypto/mpi/mpi-mul.c | 194 +++++ crypto/mpi/mpi-pow.c | 322 ++++++++ crypto/mpi/mpi-scan.c | 136 ++++ crypto/mpi/mpicoder.c | 361 +++++++++ crypto/mpi/mpih-cmp.c | 56 ++ crypto/mpi/mpih-div.c | 541 ++++++++++++++ crypto/mpi/mpih-mul.c | 527 +++++++++++++ crypto/mpi/mpiutil.c | 206 +++++ include/linux/crypto/mpi.h | 146 ++++ 32 files changed, 6201 insertions(+), 0 deletions(-) create mode 100644 crypto/mpi/Makefile create mode 100644 crypto/mpi/generic_mpi-asm-defs.h create mode 100644 crypto/mpi/generic_mpih-add1.c create mode 100644 crypto/mpi/generic_mpih-lshift.c create mode 100644 crypto/mpi/generic_mpih-mul1.c create mode 100644 crypto/mpi/generic_mpih-mul2.c create mode 100644 crypto/mpi/generic_mpih-mul3.c create mode 100644 crypto/mpi/generic_mpih-rshift.c create mode 100644 crypto/mpi/generic_mpih-sub1.c create mode 100644 crypto/mpi/generic_udiv-w-sdiv.c create mode 100644 crypto/mpi/longlong.h create mode 100644 crypto/mpi/mpi-add.c create mode 100644 crypto/mpi/mpi-bit.c create mode 100644 crypto/mpi/mpi-cmp.c create mode 100644 crypto/mpi/mpi-div.c create mode 100644 crypto/mpi/mpi-gcd.c create mode 100644 crypto/mpi/mpi-inline.c create mode 100644 crypto/mpi/mpi-inline.h create mode 100644 crypto/mpi/mpi-internal.h create mode 100644 crypto/mpi/mpi-inv.c create mode 100644 crypto/mpi/mpi-mpow.c create mode 100644 crypto/mpi/mpi-mul.c create mode 100644 crypto/mpi/mpi-pow.c create mode 100644 crypto/mpi/mpi-scan.c create mode 100644 crypto/mpi/mpicoder.c create mode 100644 crypto/mpi/mpih-cmp.c create mode 100644 crypto/mpi/mpih-div.c create mode 100644 crypto/mpi/mpih-mul.c create mode 100644 crypto/mpi/mpiutil.c create mode 100644 include/linux/crypto/mpi.h
crypto/Kconfig +6 -0
@@ -857,6 +857,12 @@ config CRYPTO_USER_API_SKCIPHER This option enables the user-spaces interface for symmetric key cipher algorithms. +config CRYPTO_MPILIB + bool "Multiprecision maths library (EXPERIMENTAL)" + depends on CRYPTO + help + Multiprecision maths library from GnuPG + source "drivers/crypto/Kconfig" endif # if CRYPTO
crypto/Makefile +1 -0
@@ -88,6 +88,7 @@ obj-$(CONFIG_CRYPTO_GHASH) += ghash-generic.o obj-$(CONFIG_CRYPTO_USER_API) += af_alg.o obj-$(CONFIG_CRYPTO_USER_API_HASH) += algif_hash.o obj-$(CONFIG_CRYPTO_USER_API_SKCIPHER) += algif_skcipher.o +obj-$(CONFIG_CRYPTO_MPILIB) += mpi/ # # generic algorithms and the async_tx api
crypto/mpi/Makefile new file +30 -0
@@ -0,0 +1,30 @@ +# +# MPI multiprecision maths library (from gpg) +# + +obj-$(CONFIG_CRYPTO_MPILIB) = \ + generic_mpih-lshift.o \ + generic_mpih-mul1.o \ + generic_mpih-mul2.o \ + generic_mpih-mul3.o \ + generic_mpih-rshift.o \ + generic_mpih-sub1.o \ + generic_mpih-add1.o \ + generic_udiv-w-sdiv.o \ + mpicoder.o \ + mpi-add.o \ + mpi-bit.o \ + mpi-div.o \ + mpi-cmp.o \ + mpi-gcd.o \ + mpih-cmp.o \ + mpih-div.o \ + mpih-mul.o \ + mpi-inline.o \ + mpi-inv.o \ + mpi-mpow.o \ + mpi-mul.o \ + mpi-pow.o \ + mpi-scan.o \ + mpiutil.o +
crypto/mpi/generic_mpi-asm-defs.h new file +4 -0
@@ -0,0 +1,4 @@ +/* This file defines some basic constants for the MPI machinery. We +* need to define the types on a per-CPU basis, so it is done with +* this file here. */ +#define BYTES_PER_MPI_LIMB (SIZEOF_UNSIGNED_LONG)
crypto/mpi/generic_mpih-add1.c new file +61 -0
61 lines not on this page · raw message
crypto/mpi/generic_mpih-lshift.c new file +63 -0
63 lines not on this page · raw message
crypto/mpi/generic_mpih-mul1.c new file +57 -0
57 lines not on this page · raw message
crypto/mpi/generic_mpih-mul2.c new file +60 -0
60 lines not on this page · raw message
crypto/mpi/generic_mpih-mul3.c new file +61 -0
61 lines not on this page · raw message
crypto/mpi/generic_mpih-rshift.c new file +63 -0
63 lines not on this page · raw message
crypto/mpi/generic_mpih-sub1.c new file +60 -0
60 lines not on this page · raw message
crypto/mpi/generic_udiv-w-sdiv.c new file +106 -0
106 lines not on this page · raw message
crypto/mpi/longlong.h new file +1478 -0
1,478 lines not on this page · raw message
crypto/mpi/mpi-add.c new file +234 -0
234 lines not on this page · raw message
crypto/mpi/mpi-bit.c new file +235 -0
235 lines not on this page · raw message
crypto/mpi/mpi-cmp.c new file +68 -0
68 lines not on this page · raw message
crypto/mpi/mpi-div.c new file +333 -0
333 lines not on this page · raw message
crypto/mpi/mpi-gcd.c new file +59 -0
59 lines not on this page · raw message
crypto/mpi/mpi-inline.c new file +31 -0
@@ -0,0 +1,31 @@ +/* mpi-inline.c +* Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc. +* +* This file is part of GnuPG. +* +* GnuPG is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version.
Lines of this file are not shown. View the raw message.
crypto/mpi/mpi-inline.h new file +122 -0
122 lines not on this page · raw message
crypto/mpi/mpi-internal.h new file +260 -0
260 lines not on this page · raw message
crypto/mpi/mpi-inv.c new file +187 -0
187 lines not on this page · raw message
crypto/mpi/mpi-mpow.c new file +133 -0
133 lines not on this page · raw message
crypto/mpi/mpi-mul.c new file +194 -0
194 lines not on this page · raw message
crypto/mpi/mpi-pow.c new file +322 -0
322 lines not on this page · raw message
crypto/mpi/mpi-scan.c new file +136 -0
136 lines not on this page · raw message
crypto/mpi/mpicoder.c new file +361 -0
361 lines not on this page · raw message
crypto/mpi/mpih-cmp.c new file +56 -0
56 lines not on this page · raw message
crypto/mpi/mpih-div.c new file +541 -0
541 lines not on this page · raw message
crypto/mpi/mpih-mul.c new file +527 -0
527 lines not on this page · raw message
crypto/mpi/mpiutil.c new file +206 -0
206 lines not on this page · raw message
include/linux/crypto/mpi.h new file +146 -0
146 lines not on this page · raw message
The rest of this diff is not shown. View the raw message.
Signature · 1 line
1.7.4.1
Part of the diff is not shown here. View the raw message.
RFC 2/3 crypto: ksign - digital signature verification support
In reply to Dmitry KasatkinThis patch implements RSA digital signature verification using GnuPG library.
Signature and public key have a special format and have special headers. Signature header contains keyid, which is used to identify the key, needed for signature verification.
Payload of the signature and the key are multi-precision integers.
Signing and key management utility "evmctl" is available on
http://meego.gitorious.org/meego-platform-security/evm-utils
Key is added to the kernel keyring with the name equal to a keyid. evm-utils provide support to load PEM key into the keyring, to convert PEM key to the kernel format and to load it into the keyring.
--- crypto/Kconfig | 13 ++ crypto/Makefile | 3 + crypto/ksign.c | 269 ++++++++++++++++++++++++++++++++++++++++++ include/linux/crypto/ksign.h | 67 +++++++++++ 4 files changed, 352 insertions(+), 0 deletions(-) create mode 100644 crypto/ksign.c create mode 100644 include/linux/crypto/ksign.h
crypto/Kconfig +13 -0
@@ -863,6 +863,19 @@ config CRYPTO_MPILIB help Multiprecision maths library from GnuPG +config CRYPTO_KSIGN + bool "In-kernel signature checker (EXPERIMENTAL)" + depends on CRYPTO + help + Signature checker (used for module sig checking). + +config CRYPTO_KSIGN_RSA + bool "Handle RSA signatures (EXPERIMENTAL)" + select CRYPTO_KSIGN + select CRYPTO_MPILIB + help + RSA Signature checker. + source "drivers/crypto/Kconfig" endif # if CRYPTO
crypto/Makefile +3 -0
@@ -90,6 +90,9 @@ obj-$(CONFIG_CRYPTO_USER_API_HASH) += algif_hash.o obj-$(CONFIG_CRYPTO_USER_API_SKCIPHER) += algif_skcipher.o obj-$(CONFIG_CRYPTO_MPILIB) += mpi/ +obj-$(CONFIG_CRYPTO_KSIGN) += ksignmod.o +ksignmod-objs := ksign.o + # # generic algorithms and the async_tx api #
crypto/ksign.c new file +269 -0
269 lines not on this page · raw message
include/linux/crypto/ksign.h new file +67 -0
67 lines not on this page · raw message
Signature · 1 line
1.7.4.1
RFC 3/3 evm: digital signature verification support
In reply to Dmitry KasatkinThis option enables digital signature verification support for EVM. With this feature file metadata can be protected using digital signature instead of HMAC. When building an image,
which has to be flashed to different devices, an HMAC cannot be used to sign file metadata, because the HMAC key is different on every device. File metadata can be protected using digital signature.
--- security/integrity/evm/Kconfig | 15 ++++ security/integrity/evm/evm.h | 12 ++++ security/integrity/evm/evm_crypto.c | 66 ++++++++++++++----- security/integrity/evm/evm_main.c | 125 +++++++++++++++++++++++++++++++---- 4 files changed, 188 insertions(+), 30 deletions(-)
security/integrity/evm/Kconfig +15 -0
@@ -12,3 +12,18 @@ config EVM integrity attacks. If you are unsure how to answer this question, answer N. + +config EVM_DIGSIG + boolean "EVM Digital Signature support" + depends on EVM + default n + select CRYPTO_KSIGN_RSA + help + This option enables digital signature verification support for EVM. + With this feature file metadata can be protected using digital + signature instead of HMAC. When building an image, + which has to be flashed to different devices, an HMAC cannot + be used to sign file metadata, because the HMAC key is different on + every device. File metadata can be protected using digital signature. + + If unsure, say N.
security/integrity/evm/evm.h +12 -0
@@ -12,14 +12,21 @@* File: evm.h * */ + +#ifndef __INTEGRITY_EVM_H +#define __INTEGRITY_EVM_H +#include <linux/xattr.h> #include <linux/security.h> +#include "../integrity.h" extern int evm_initialized;extern char *evm_hmac; +extern char *evm_hash;extern struct crypto_shash *hmac_tfm; +extern struct crypto_shash *hash_tfm;/* List of EVM protected security xattrs */ extern char *evm_config_xattrnames[];
@@ -32,7 +39,12 @@ extern int evm_update_evmxattr(struct dentry *dentry,extern int evm_calc_hmac (struct dentry *dentry,const char *req_xattr_name,const char *req_xattr_value,size_t req_xattr_value_len,char *digest); +extern int evm_calc_hash (struct dentry *dentry,const char *req_xattr_name, +const char *req_xattr_value, +size_t req_xattr_value_len,char *digest);extern int evm_init_hmac (struct inode *inode,const struct xattr *xattr,char *hmac_val);extern int evm_init_secfs (void );extern void evm_cleanup_secfs (void ); + +#endif
security/integrity/evm/evm_crypto.c +49 -17
112 lines not on this page · raw message
security/integrity/evm/evm_main.c +112 -13
182 lines not on this page · raw message
Signature · 1 line
1.7.4.1
RFC 3/3 evm: digital signature support
In reply to Dmitry KasatkinWhen building an image, which has to be flashed to different devices, an HMAC cannot be used to sign file metadata, as the HMAC key is different on every device. File metadata can be protected using digital signature. This patch enables RSA signature based integrity verification.
--- security/integrity/evm/Kconfig | 14 ++++ security/integrity/evm/evm.h | 12 ++++ security/integrity/evm/evm_crypto.c | 66 ++++++++++++++----- security/integrity/evm/evm_main.c | 125 +++++++++++++++++++++++++++++++---- 4 files changed, 187 insertions(+), 30 deletions(-)
security/integrity/evm/Kconfig +14 -0
@@ -12,3 +12,17 @@ config EVM integrity attacks. If you are unsure how to answer this question, answer N. + +config EVM_DIGSIG + boolean "EVM Digital Signature support" + depends on EVM + default n + select CRYPTO_KSIGN_RSA + help + When building an image, which has to be flashed to different + devices, an HMAC cannot be used to sign file metadata, as + the HMAC key is different on every device. + File metadata can be protected using digital signature. + This option enables RSA signature based integrity verification. + + If unsure, say N.
security/integrity/evm/evm.h +12 -0
@@ -12,14 +12,21 @@* File: evm.h * */ + +#ifndef __INTEGRITY_EVM_H +#define __INTEGRITY_EVM_H +#include <linux/xattr.h> #include <linux/security.h> +#include "../integrity.h" extern int evm_initialized;extern char *evm_hmac; +extern char *evm_hash;extern struct crypto_shash *hmac_tfm; +extern struct crypto_shash *hash_tfm;/* List of EVM protected security xattrs */ extern char *evm_config_xattrnames[];
@@ -32,7 +39,12 @@ extern int evm_update_evmxattr(struct dentry *dentry,extern int evm_calc_hmac (struct dentry *dentry,const char *req_xattr_name,const char *req_xattr_value,size_t req_xattr_value_len,char *digest); +extern int evm_calc_hash (struct dentry *dentry,const char *req_xattr_name, +const char *req_xattr_value, +size_t req_xattr_value_len,char *digest);extern int evm_init_hmac (struct inode *inode,const struct xattr *xattr,char *hmac_val);extern int evm_init_secfs (void );extern void evm_cleanup_secfs (void ); + +#endif
security/integrity/evm/evm_crypto.c +49 -17
112 lines not on this page · raw message
security/integrity/evm/evm_main.c +112 -13
182 lines not on this page · raw message
Signature · 1 line
1.7.4.1
Re: [RFC v2.0 3/3] evm: digital signature support
Please ignore this patch. It was sent by mistake... Check:
evm: digital signature verification support
- Dmitry
Quoted 393 lines · Dmitry Kasatkin
When building an image, which has to be flashed to different devices, an HMAC cannot be used to sign file metadata, as the HMAC key is different on every device. File metadata can be protected using digital signature. This patch enables RSA signature based integrity verification.
Signed-off-by Dmitry Kasatkin <[email protected]>Acked-by Mimi Zohar <[email protected]>---
security/integrity/evm/Kconfig | 14 ++++security/integrity/evm/evm.h| 12 ++++security/integrity/evm/evm_crypto.c| 66 ++++++++++++++-----security/integrity/evm/evm_main.c| 125 +++++++++++++++++++++++++++++++----4 files changed, 187 insertions(+), 30 deletions(-)security/integrity/evm/Kconfig +0
-0@@ -12,3 +12,17 @@ config EVMintegrity attacks.
If you are unsure how to answer this question, answer N.
security/integrity/evm/Kconfig +14
-0+ +config EVM_DIGSIG + boolean "EVM Digital Signature support" + depends on EVM + default n + select CRYPTO_KSIGN_RSA + help + When building an image, which has to be flashed to different + devices, an HMAC cannot be used to sign file metadata, as + the HMAC key is different on every device. + File metadata can be protected using digital signature. + This option enables RSA signature based integrity verification. + + If unsure, say N.security/integrity/evm/evm.h +12
-0@@ -12,14 +12,21 @@* File: evm.h * */ + +#ifndef __INTEGRITY_EVM_H +#define __INTEGRITY_EVM_H + #include <linux/xattr.h> #include <linux/security.h> + #include "../integrity.h" extern int evm_initialized; extern char *evm_hmac; +extern char *evm_hash; extern struct crypto_shash *hmac_tfm; +extern struct crypto_shash *hash_tfm; /* List of EVM protected security xattrs */ extern char *evm_config_xattrnames[];@@ -32,7 +39,12 @@ extern int evm_update_evmxattr(struct dentry *dentry, extern int evm_calc_hmac(struct dentry *dentry, const char *req_xattr_name, const char *req_xattr_value, size_t req_xattr_value_len, char *digest); +extern int evm_calc_hash (struct dentry *dentry,const char *req_xattr_name, + const char *req_xattr_value, + size_t req_xattr_value_len, char *digest); extern int evm_init_hmac(struct inode *inode, const struct xattr *xattr, char *hmac_val); extern int evm_init_secfs(void); extern void evm_cleanup_secfs(void); + +#endif security/integrity/evm/evm_crypto.c +26
-12@@ -26,34 +26,48 @@ static unsigned char evmkey[MAX_KEY_SIZE]; static int evmkey_len = MAX_KEY_SIZE; struct crypto_shash *hmac_tfm; +struct crypto_shash *hash_tfm; -static struct shash_desc *init_desc (void ) +static struct shash_desc *init_desc (const char type) { int rc; + char *algo; + struct crypto_shash **tfm; struct shash_desc *desc; - if (hmac_tfm == NULL) { - hmac_tfm = crypto_alloc_shash(evm_hmac, 0, CRYPTO_ALG_ASYNC); - if (IS_ERR(hmac_tfm)) { + if (type == EVM_XATTR_HMAC) { + tfm = &hmac_tfm; + algo = evm_hmac; + } else { + tfm = &hash_tfm; + algo = evm_hash; + } + + if (*tfm == NULL) { + *tfm = crypto_alloc_shash(algo, 0, CRYPTO_ALG_ASYNC); + if (IS_ERR(*tfm)) { pr_err("Can not allocate %s (reason: %ld)\n", - evm_hmac, PTR_ERR(hmac_tfm)); - rc = PTR_ERR(hmac_tfm); - hmac_tfm = NULL; + algo, PTR_ERR(*tfm)); + rc = PTR_ERR(*tfm); + *tfm = NULL; return ERR_PTR(rc); } } - desc = kmalloc(sizeof(*desc) + crypto_shash_descsize(hmac_tfm), + desc = kmalloc(sizeof(*desc) + crypto_shash_descsize(*tfm), GFP_KERNEL); if (!desc) return ERR_PTR(-ENOMEM); - desc->tfm = hmac_tfm; + desc->tfm = *tfm; desc->flags = CRYPTO_TFM_REQ_MAY_SLEEP; - rc = crypto_shash_setkey(hmac_tfm, evmkey, evmkey_len); - if (rc) - goto out; + if (type == EVM_XATTR_HMAC) { + rc = crypto_shash_setkey(*tfm, evmkey, evmkey_len); + if (rc) + goto out; + } + rc = crypto_shash_init(desc);out:
if (rc) {security/integrity/evm/evm_crypto.c +23
-5@@ -97,9 +111,11 @@ static void hmac_add_misc(struct shash_desc *desc, struct inode *inode,* the hmac using the requested xattr value. Don't alloc/free memory for * each xattr, but attempt to re-use the previously allocated memory. */ -int evm_calc_hmac (struct dentry *dentry,const char *req_xattr_name, - const char *req_xattr_value, size_t req_xattr_value_len, - char *digest) +static int evm_calc_hmac_or_hash (struct dentry *dentry, + const char *req_xattr_name, + const char *req_xattr_value, + size_t req_xattr_value_len, + char type, char *digest) { struct inode *inode = dentry->d_inode; struct shash_desc *desc;@@ -111,7 +127,7 @@ int evm_calc_hmac(struct dentry *dentry, const char *req_xattr_name, if (!inode->i_op || !inode->i_op->getxattr) return -EOPNOTSUPP; - desc = init_desc(); + desc = init_desc(type); if (IS_ERR(desc)) return PTR_ERR(desc);@@ -145,6 +161,22 @@ out: return error; } +int evm_calc_hmac (struct dentry *dentry,const char *req_xattr_name, + const char *req_xattr_value, size_t req_xattr_value_len, + char *digest) +{ + return evm_calc_hmac_or_hash(dentry, req_xattr_name, req_xattr_value, + req_xattr_value_len, EVM_XATTR_HMAC, digest); +} + +int evm_calc_hash (struct dentry *dentry,const char *req_xattr_name, + const char *req_xattr_value, size_t req_xattr_value_len, + char *digest) +{ + return evm_calc_hmac_or_hash(dentry, req_xattr_name, req_xattr_value, + req_xattr_value_len, IMA_XATTR_DIGEST, digest); +} + /** Calculate the hmac and update security.evm xattr * @@ -175,7 +207,7 @@ int evm_init_hmac(struct inode *inode, const struct xattr *lsm_xattr, { struct shash_desc *desc; - desc = init_desc(); + desc = init_desc(EVM_XATTR_HMAC); if (IS_ERR(desc)) { printk(KERN_INFO "init_desc failed\n"); return PTR_ERR(desc);security/integrity/evm/evm_main.c +3
-0@@ -18,6 +18,8 @@ #include <linux/crypto.h> #include <linux/xattr.h> #include <linux/integrity.h> +#include <linux/key-type.h> +#include <linux/crypto/ksign.h> #include <linux/evm.h> #include <crypto/hash.h> #include "evm.h"@@ -25,6 +27,7 @@ int evm_initialized; char *evm_hmac = "hmac(sha1)"; +char *evm_hash ="sha1" ; char *evm_config_xattrnames[] = { #ifdef CONFIG_SECURITY_SELINUX@@ -40,6 +43,8 @@ char *evm_config_xattrnames[] = {NULL
};security/integrity/evm/evm_main.c +2
-0+static struct key *evm_keyring; +static int
evm_fixmode;
static int__initevm_set_fixmode(char *str)
{security/integrity/evm/evm_main.c +101
-13@@ -49,6 +54,56 @@ static int __init evm_set_fixmode(char *str) } __setup("evm=", evm_set_fixmode); +static int evm_find_protected_xattrs (struct dentry *dentry) +{ + struct inode *inode = dentry->d_inode; + char **xattr; + int error; + int count = 0; + + if (!inode->i_op || !inode->i_op->getxattr) + return -EOPNOTSUPP; + + for (xattr = evm_config_xattrnames; *xattr != NULL; xattr++) { + error = inode->i_op->getxattr(dentry, *xattr, NULL, 0); + if (error < 0) { + if (error == -ENODATA) + continue; + return error; + } + count++; + } + + return count; +} + +#ifdef CONFIG_EVM_DIGSIG + +int evm_sign_verify (const char *sig,int siglen, + const char *digest, int digestlen) +{ + if (!evm_keyring) { + evm_keyring = request_key(&key_type_keyring, "_evm", NULL); + if (IS_ERR(evm_keyring)) { + pr_err("no evm keyring: %ld\n", PTR_ERR(evm_keyring)); + evm_keyring = NULL; + return PTR_ERR(evm_keyring); + } + } + + return ksign_verify(evm_keyring, sig, siglen, digest, digestlen); +} + +#else + +static inline int evm_sign_verify (const char *sig,int siglen, + const char *digest, int digestlen) +{ + return -EOPNOTSUPP; +} + +#endif /* CONFIG_EVM_DIGSIG */ + /** evm_verify_hmac - calculate and compare the HMAC with the EVM xattr * @@ -68,32 +123,71 @@ static enum integrity_status evm_verify_hmac(struct dentry *dentry, size_t xattr_value_len, struct integrity_iint_cache *iint) { - struct evm_ima_xattr_data xattr_data; + struct evm_ima_xattr_data *xattr_data = NULL; + struct evm_ima_xattr_data calc; enum integrity_status evm_status = INTEGRITY_PASS; - int rc; + int rc, xattr_len; if (iint && iint->evm_status == INTEGRITY_PASS) return iint->evm_status; /* if status is not PASS, try to check again - against -ENOMEM */ - rc = evm_calc_hmac(dentry, xattr_name, xattr_value, - xattr_value_len, xattr_data.digest); - if (rc < 0) { - evm_status = (rc == -ENODATA) - ? INTEGRITY_NOXATTRS : INTEGRITY_FAIL; + /* first need to know the sig type */ + rc = vfs_getxattr_alloc(dentry, XATTR_NAME_EVM, (char **)&xattr_data, 0, + GFP_NOFS); + if (rc <= 0) { + if (rc == 0) + evm_status = INTEGRITY_FAIL; /* empty */ + else if (rc == -ENODATA) { + rc = evm_find_protected_xattrs(dentry); + if (rc > 0) + evm_status = INTEGRITY_NOLABEL; + else if (rc == 0) + evm_status = INTEGRITY_NOXATTRS; /* new file */ + } goto out; } - xattr_data.type = EVM_XATTR_HMAC; - rc = vfs_xattr_cmp(dentry, XATTR_NAME_EVM, (u8 *)&xattr_data, - sizeof xattr_data, GFP_NOFS); - if (rc < 0) - evm_status = (rc == -ENODATA) - ? INTEGRITY_NOLABEL : INTEGRITY_FAIL; + xattr_len = rc - 1; + + /* check value type */ + switch (xattr_data->type) { + case EVM_XATTR_HMAC: + rc = evm_calc_hmac(dentry, xattr_name, xattr_value, + xattr_value_len, calc.digest); + if (rc) + break; + rc = memcmp(xattr_data->digest, calc.digest, + sizeof(calc.digest)); + if (rc) + rc = -EINVAL; + break; + case EVM_IMA_XATTR_DIGSIG: + rc = evm_calc_hash(dentry, xattr_name, xattr_value, + xattr_value_len, calc.digest); + if (rc) + break; + rc = evm_sign_verify(xattr_data->digest, xattr_len, + calc.digest, sizeof(calc.digest)); + if (!rc) { + /* we probably want to replace rsa with hmac here */ + evm_update_evmxattr(dentry, xattr_name, xattr_value, + xattr_value_len); + } + break; + default: + rc = -EINVAL; + break; + } + + if (rc) + evm_status = (rc == -ENODATA) ? + INTEGRITY_NOXATTRS : INTEGRITY_FAIL;out:
if (iint)
iint->evm_status =evm_status;
+kfree(xattr_data);
returnevm_status;
}security/integrity/evm/evm_main.c +2
-0@@ -357,6 +451,8 @@ static int __init init_evm(void) printk(KERN_INFO "EVM: Error registering secfs\n"); goto err; } + + return 0;err:
return error;
}security/integrity/evm/evm_main.c +3
-1@@ -364,8 +460,11 @@ err: static void __exit cleanup_evm(void) { evm_cleanup_secfs(); + key_put(evm_keyring); if (hmac_tfm) crypto_free_shash(hmac_tfm); + if (hash_tfm) + crypto_free_shash(hash_tfm); } /* -- 1.7.4.1
Hello Dmitry,
Was there supposed to be part 1/3 for this patch set. At least I didn't see it also it doesn't show in mailing list archives.
I also don't see it in mailing list archives at
http://marc.info/?l=linux-security-module&r=1&b=201109&w=2
Can you resend it?
-Sam