Re: [PATCH V3 1/2] evm: Don't deadlock if a crypto algorithm is unavailable

2018-06-13 Thread Mimi Zohar
On Wed, 2018-06-13 at 14:33 +0800, Herbert Xu wrote:
> On Fri, Jun 08, 2018 at 02:57:42PM -0700, Matthew Garrett wrote:
> > When EVM attempts to appraise a file signed with a crypto algorithm the
> > kernel doesn't have support for, it will cause the kernel to trigger a
> > module load. If the EVM policy includes appraisal of kernel modules this
> > will in turn call back into EVM - since EVM is holding a lock until the
> > crypto initialisation is complete, this triggers a deadlock. Add a
> > CRYPTO_NOLOAD flag and skip module loading if it's set, and add that flag
> > in the EVM case in order to fail gracefully with an error message
> > instead of deadlocking.
> > 
> > Signed-off-by: Matthew Garrett 
> 
> Acked-by: Herbert Xu 

Thanks!  This patch and "evm: Allow non-SHA1 digital signatures" are
now queued in the next-integrity-queued branch.

Mimi



Re: CAAM and IMA/EVM : caam_rsa_enc: DECO: desc idx 7: Protocol Size Error

2018-04-09 Thread Mimi Zohar
On Mon, 2018-04-09 at 15:10 +0100, Martin Townsend wrote:
> Hi Mimi,
> 
> On Mon, Apr 9, 2018 at 1:46 PM, Mimi Zohar <zo...@linux.vnet.ibm.com> wrote:
> > On Mon, 2018-04-09 at 09:41 +0100, Martin Townsend wrote:
> >> Hi,
> >>
> >> I'm trying to get to the bottom of an issue I'm seeing when enabling
> >> the CAAM in the kernel with IMA/EVM enabled.  I'm using the official
> >> NXP (imx_4.9.11_1.0.0_ga) vendor Kernel.
> >>
> >> Here's the error message I'm getting.
> >>
> >> caam_jr 2142000.jr1: 4789: DECO: desc idx 7: Protocol Size Error -
> >> A protocol has seen an error in size. When running RSA, pdb size N <
> >> (size of F) when no formatting is used; or pdb size N < (F + 11) when
> >> formatting is used.
> >> integrity: Problem loading X.509 certificate (-129): /etc/keys/ima-x509.der
> >
> > This error message indicates that the kernel is trying to load a key
> > onto the IMA keyring, but any key added to the trusted IMA keyring
> > (.ima) must be signed by a key on the builtin (or secondary) keyring.
> >
> > Please verify that the public key used to sign the ima-x509.der is on
> > the builtin keyring (eg. "keyctl show %keyring:.builtin_trusted_keys)
> > or the secondary keyring.  Depending on how the kernel was configured,
> > loading the public CA onto the builtin (or secondary) keyring might be
> > possible.
> >
> > Some distros are carrying patches which load the UEFI keys onto the
> > secondary keyring.  The other (preferred) method would be to insert
> > the CA certificate into the kernel and resign the kernel.  This
> > requires reserving memory for the key when the kernel is built.
> >
> > CONFIG_SYSTEM_EXTRA_CERTIFICATE=y
> > CONFIG_SYSTEM_EXTRA_CERTIFICATE_SIZE=4096
> >
> > Mimi
> 
> I think the integrity error message is a side effect of the previous
> error, ie we are getting this error message because the CAAM is
> failing to verify the certificates signature and hence IMA fails to
> load the certificate onto the keyring.  If I disable CAAM then
> everything works as expected.

Thanks!

> What I'm trying to get to the bottom of
> is why CAAM is failing to verify the signature.  Further below in the
> email I have determined that the signature is 257 bytes do you think
> this is correct?

Sorry, I'm not going to be of much help here.  Remember everything
that CAAM uses (eg. kernel crypto modules) must be builtin to the
kernel until a key is loaded onto to the IMA keyring.  Perhaps
enabling pr_devel/pr_debug in crypto/asymmetric_keys/ might provide
some additional information.

Mimi


> I've read a post here:
> https://crypto.stackexchange.com/questions/3505/what-is-the-length-of-an-rsa-signature

> That says that for PKCS#1 the signature should always be of the size
> of the modulus, then it goes on to say: "In some protocols, there can
> be some wrapping around the signature, e.g. to indicate which
> algorithm was used,"  I'm wondering if that's what I'm seeing, an
> extra byte in the signature that is the type of algorithm used but
> this extra byte is also passed to the CAAM and causes it to fail as
> then the signature is now larger than the modulus.  But I don't know
> what I can do about this, I'm not even sure what protocol is being
> used to generate this extra byte, any suggestions on how to find this
> out would be appreciated.
> 
> >
> >
> >> I put a dump_stack in the error handling routine in CAAM and in the
> >> caam_jr_enqueue to get (I removed some of the caam_jr_enqueue
> >> dump_stacks during initialisation to highlight the one of interest)
> >>
> >> caam 214.caam: ERA source: CCBVID.
> >> caam 214.caam: Entropy delay = 3200
> >> caam 214.caam: Instantiated RNG4 SH0
> >> caam 214.caam: Instantiated RNG4 SH1
> >> caam 214.caam: device ID = 0x0a160300 (Era 8)
> >> caam 214.caam: job rings = 3, qi = 0
> >> caam algorithms registered in /proc/crypto
> >> caam_jr_enqueue
> >> CPU: 0 PID: 1 Comm: swapper Not tainted 4.9.11-1.0.0+gc27010d #4
> >> Hardware name: Freescale i.MX6 UltraLite (Device Tree)
> >> caam_jr_enqueue
> >> CPU: 0 PID: 1 Comm: swapper Not tainted 4.9.11-1.0.0+gc27010d #4
> >> Hardware name: Freescale i.MX6 UltraLite (Device Tree)
> >> caam_jr 2141000.jr0: registering rng-caam
> >> caam 214.caam: caam pkc algorithms registered in /proc/crypto
> >> caam_jr_enqueue
> >> CPU: 0 PID: 1 Comm: swapper Not tainted 4.9.11-1.0.0+gc27010d #4
> >> Hardware name: Freescale i.MX

Re: CAAM and IMA/EVM : caam_rsa_enc: DECO: desc idx 7: Protocol Size Error

2018-04-09 Thread Mimi Zohar
On Mon, 2018-04-09 at 09:41 +0100, Martin Townsend wrote:
> Hi,
> 
> I'm trying to get to the bottom of an issue I'm seeing when enabling
> the CAAM in the kernel with IMA/EVM enabled.  I'm using the official
> NXP (imx_4.9.11_1.0.0_ga) vendor Kernel.
> 
> Here's the error message I'm getting.
> 
> caam_jr 2142000.jr1: 4789: DECO: desc idx 7: Protocol Size Error -
> A protocol has seen an error in size. When running RSA, pdb size N <
> (size of F) when no formatting is used; or pdb size N < (F + 11) when
> formatting is used.
> integrity: Problem loading X.509 certificate (-129): /etc/keys/ima-x509.der

This error message indicates that the kernel is trying to load a key
onto the IMA keyring, but any key added to the trusted IMA keyring
(.ima) must be signed by a key on the builtin (or secondary) keyring.

Please verify that the public key used to sign the ima-x509.der is on
the builtin keyring (eg. "keyctl show %keyring:.builtin_trusted_keys)
or the secondary keyring.  Depending on how the kernel was configured,
loading the public CA onto the builtin (or secondary) keyring might be
possible.

Some distros are carrying patches which load the UEFI keys onto the
secondary keyring.  The other (preferred) method would be to insert
the CA certificate into the kernel and resign the kernel.  This
requires reserving memory for the key when the kernel is built.

CONFIG_SYSTEM_EXTRA_CERTIFICATE=y
CONFIG_SYSTEM_EXTRA_CERTIFICATE_SIZE=4096

Mimi


> I put a dump_stack in the error handling routine in CAAM and in the
> caam_jr_enqueue to get (I removed some of the caam_jr_enqueue
> dump_stacks during initialisation to highlight the one of interest)
> 
> caam 214.caam: ERA source: CCBVID.
> caam 214.caam: Entropy delay = 3200
> caam 214.caam: Instantiated RNG4 SH0
> caam 214.caam: Instantiated RNG4 SH1
> caam 214.caam: device ID = 0x0a160300 (Era 8)
> caam 214.caam: job rings = 3, qi = 0
> caam algorithms registered in /proc/crypto
> caam_jr_enqueue
> CPU: 0 PID: 1 Comm: swapper Not tainted 4.9.11-1.0.0+gc27010d #4
> Hardware name: Freescale i.MX6 UltraLite (Device Tree)
> caam_jr_enqueue
> CPU: 0 PID: 1 Comm: swapper Not tainted 4.9.11-1.0.0+gc27010d #4
> Hardware name: Freescale i.MX6 UltraLite (Device Tree)
> caam_jr 2141000.jr0: registering rng-caam
> caam 214.caam: caam pkc algorithms registered in /proc/crypto
> caam_jr_enqueue
> CPU: 0 PID: 1 Comm: swapper Not tainted 4.9.11-1.0.0+gc27010d #4
> Hardware name: Freescale i.MX6 UltraLite (Device Tree)
> caam_rsa_set_pub_key
> caam_rsa_max_size
> caam_rsa_enc
> caam_jr_enqueue
> CPU: 0 PID: 1 Comm: swapper Not tainted 4.9.11-1.0.0+gc27010d #4
> Hardware name: Freescale i.MX6 UltraLite (Device Tree)
> [<8010dd8c>] (unwind_backtrace) from [<8010b8cc>] (show_stack+0x10/0x14)
> [<8010b8cc>] (show_stack) from [<80608f74>] (caam_jr_enqueue+0x3c/0x2bc)
> [<80608f74>] (caam_jr_enqueue) from [<8061fb84>] (caam_rsa_enc+0x210/0x3ac)
> [<8061fb84>] (caam_rsa_enc) from [<803ed910>] (pkcs1pad_verify+0xa8/0xe4)
> [<803ed910>] (pkcs1pad_verify) from [<804134e4>]
> (public_key_verify_signature+0x17c/0x248)
> [<804134e4>] (public_key_verify_signature) from [<804132a0>]
> (restrict_link_by_signature+0xa8/0xd4)
> [<804132a0>] (restrict_link_by_signature) from [<803cadd4>]
> (key_create_or_update+0x12c/0x370)
> [<803cadd4>] (key_create_or_update) from [<80c253a0>]
> (integrity_load_x509+0x70/0xc4)
> [<80c253a0>] (integrity_load_x509) from [<80c256bc>] (ima_load_x509+0x28/0x3c)
> [<80c256bc>] (ima_load_x509) from [<80c2510c>] (integrity_load_keys+0x8/0x10)
> [<80c2510c>] (integrity_load_keys) from [<80c00de0>]
> (kernel_init_freeable+0x1bc/0x1cc)
> [<80c00de0>] (kernel_init_freeable) from [<80844ccc>] (kernel_init+0x8/0x114)
> [<80844ccc>] (kernel_init) from [<801078d8>] (ret_from_fork+0x14/0x3c)
> CPU: 0 PID: 112 Comm: irq/214-2142000 Not tainted 4.9.11-1.0.0+gc27010d #4
> Hardware name: Freescale i.MX6 UltraLite (Device Tree)
> [<8010dd8c>] (unwind_backtrace) from [<8010b8cc>] (show_stack+0x10/0x14)
> [<8010b8cc>] (show_stack) from [<8060a0e8>] (report_deco_status+0x30/0xf8)
> [<8060a0e8>] (report_deco_status) from [<8061f3c8>] (rsa_pub_done+0x20/0x60)
> [<8061f3c8>] (rsa_pub_done) from [<80608d94>] (caam_jr_threadirq+0x1dc/0x29c)
> [<80608d94>] (caam_jr_threadirq) from [<80165dcc>] (irq_thread_fn+0x1c/0x54)
> [<80165dcc>] (irq_thread_fn) from [<80166024>] (irq_thread+0x114/0x1d4)
> [<80166024>] (irq_thread) from [<801415b4>] (kthread+0xe4/0xec)
> [<801415b4>] (kthread) from [<801078d8>] (ret_from_fork+0x14/0x3c)
> caam_jr 2142000.jr1: 4789: DECO: desc idx 7: Protocol Size Error -
> A protocol has seen an error in size. When running RSA, pdb size N <
> (size of F) when no formatting is used; or pdb size N < (F + 11) when
> formatting is used.
> integrity: Problem loading X.509 certificate (-129): /etc/keys/ima-x509.der
> [<8010dd8c>] (unwind_backtrace) from [<8010b8cc>] (show_stack+0x10/0x14)
> [<8010b8cc>] (show_stack) from [<8060a0d0>] 

Re: [PATCH v6 04/12] ima: Introduce is_ima_sig()

2018-03-26 Thread Mimi Zohar
On Fri, 2018-03-16 at 17:38 -0300, Thiago Jung Bauermann wrote:
> With the introduction of another IMA signature type (modsig), some places
> will need to check for both of them. It is cleaner to do that if there's a
> helper function to tell whether an xattr_value represents an IMA
> signature.

Initially the function name "is_ima_sig" is fine, since it reflects
the 'imasig' type.  Having a more generic function name would be
better when adding 'modsig' support.  As long as the function is
locally define, we can drop 'ima' from the name.  Perhaps something
like has_signature or is_signed() would be preferable.

Mimi


> 
> Suggested-by: Mimi Zohar <zo...@linux.vnet.ibm.com>
> Signed-off-by: Thiago Jung Bauermann <bauer...@linux.vnet.ibm.com>
> ---
>  security/integrity/ima/ima.h  | 5 +
>  security/integrity/ima/ima_appraise.c | 7 +++
>  security/integrity/ima/ima_template_lib.c | 2 +-
>  3 files changed, 9 insertions(+), 5 deletions(-)
> 
> diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h
> index 35fe91aa1fc9..4bafa6a97967 100644
> --- a/security/integrity/ima/ima.h
> +++ b/security/integrity/ima/ima.h
> @@ -155,6 +155,11 @@ unsigned long ima_get_binary_runtime_size(void);
>  int ima_init_template(void);
>  void ima_init_template_list(void);
> 
> +static inline bool is_ima_sig(const struct evm_ima_xattr_data *xattr_value)
> +{
> + return xattr_value && xattr_value->type == EVM_IMA_XATTR_DIGSIG;
> +}
> +
>  /*
>   * used to protect h_table and sha_table
>   */
> diff --git a/security/integrity/ima/ima_appraise.c 
> b/security/integrity/ima/ima_appraise.c
> index a6b2995b7d0b..01172eab297b 100644
> --- a/security/integrity/ima/ima_appraise.c
> +++ b/security/integrity/ima/ima_appraise.c
> @@ -325,15 +325,14 @@ int ima_appraise_measurement(enum ima_hooks func,
>   } else if (status != INTEGRITY_PASS) {
>   /* Fix mode, but don't replace file signatures. */
>   if ((ima_appraise & IMA_APPRAISE_FIX) &&
> - (!xattr_value ||
> -  xattr_value->type != EVM_IMA_XATTR_DIGSIG)) {
> + !is_ima_sig(xattr_value)) {
>   if (!ima_fix_xattr(dentry, iint))
>   status = INTEGRITY_PASS;
>   }
> 
>   /* Permit new files with file signatures, but without data. */
>   if (inode->i_size == 0 && iint->flags & IMA_NEW_FILE &&
> - xattr_value && xattr_value->type == EVM_IMA_XATTR_DIGSIG) {
> + is_ima_sig(xattr_value)) {
>   status = INTEGRITY_PASS;
>   }
> 
> @@ -448,7 +447,7 @@ int ima_inode_setxattr(struct dentry *dentry, const char 
> *xattr_name,
>   if (!xattr_value_len || (xvalue->type >= IMA_XATTR_LAST))
>   return -EINVAL;
>   ima_reset_appraise_flags(d_backing_inode(dentry),
> - xvalue->type == EVM_IMA_XATTR_DIGSIG);
> +  is_ima_sig(xvalue));
>   result = 0;
>   }
>   return result;
> diff --git a/security/integrity/ima/ima_template_lib.c 
> b/security/integrity/ima/ima_template_lib.c
> index 5afaa53decc5..afb52a90e532 100644
> --- a/security/integrity/ima/ima_template_lib.c
> +++ b/security/integrity/ima/ima_template_lib.c
> @@ -380,7 +380,7 @@ int ima_eventsig_init(struct ima_event_data *event_data,
>  {
>   struct evm_ima_xattr_data *xattr_value = event_data->xattr_value;
> 
> - if ((!xattr_value) || (xattr_value->type != EVM_IMA_XATTR_DIGSIG))
> + if (!is_ima_sig(xattr_value))
>   return 0;
> 
>   return ima_write_template_field_data(xattr_value, event_data->xattr_len,
> 



Re: [PATCH v6 11/12] ima: Implement support for module-style appended signatures

2018-03-26 Thread Mimi Zohar
On Fri, 2018-03-16 at 17:38 -0300, Thiago Jung Bauermann wrote:
> This patch actually implements the appraise_type=imasig|modsig option,
> allowing IMA to read and verify modsig signatures.
> 
> In case both are present in the same file, IMA will first check whether the
> key used by the xattr signature is present in the kernel keyring. If not,
> it will try the appended signature.

Yes, this sounds right.

> 
> Signed-off-by: Thiago Jung Bauermann 
> ---
>  security/integrity/ima/ima.h  | 11 +++-
>  security/integrity/ima/ima_appraise.c | 53 
> +++
>  security/integrity/ima/ima_main.c | 21 +++---
>  3 files changed, 74 insertions(+), 11 deletions(-)
> 
> diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h
> index 49aef56dc96d..c11ccb7c5bfb 100644
> --- a/security/integrity/ima/ima.h
> +++ b/security/integrity/ima/ima.h
> @@ -157,7 +157,8 @@ void ima_init_template_list(void);
> 
>  static inline bool is_ima_sig(const struct evm_ima_xattr_data *xattr_value)
>  {
> - return xattr_value && xattr_value->type == EVM_IMA_XATTR_DIGSIG;
> + return xattr_value && (xattr_value->type == EVM_IMA_XATTR_DIGSIG ||
> +xattr_value->type == IMA_MODSIG);
>  }
> 
>  /*
> @@ -253,6 +254,8 @@ enum integrity_status ima_get_cache_status(struct 
> integrity_iint_cache *iint,
>  enum ima_hooks func);
>  enum hash_algo ima_get_hash_algo(struct evm_ima_xattr_data *xattr_value,
>int xattr_len);
> +bool ima_xattr_sig_known_key(const struct evm_ima_xattr_data *xattr_value,
> +  int xattr_len);
>  int ima_read_xattr(struct dentry *dentry,
>  struct evm_ima_xattr_data **xattr_value);
> 
> @@ -291,6 +294,12 @@ ima_get_hash_algo(struct evm_ima_xattr_data 
> *xattr_value, int xattr_len)
>   return ima_hash_algo;
>  }
> 
> +static inline bool ima_xattr_sig_known_key(const struct evm_ima_xattr_data
> +*xattr_value, int xattr_len)
> +{
> + return false;
> +}
> +
>  static inline int ima_read_xattr(struct dentry *dentry,
>struct evm_ima_xattr_data **xattr_value)
>  {
> diff --git a/security/integrity/ima/ima_appraise.c 
> b/security/integrity/ima/ima_appraise.c
> index 01172eab297b..84e0fd5a19c8 100644
> --- a/security/integrity/ima/ima_appraise.c
> +++ b/security/integrity/ima/ima_appraise.c
> @@ -189,6 +189,22 @@ enum hash_algo ima_get_hash_algo(struct 
> evm_ima_xattr_data *xattr_value,
>   return ima_hash_algo;
>  }
> 
> +bool ima_xattr_sig_known_key(const struct evm_ima_xattr_data *xattr_value,
> +  int xattr_len)
> +{
> + struct key *keyring;
> +
> + if (xattr_value->type != EVM_IMA_XATTR_DIGSIG)
> + return false;
> +
> + keyring = integrity_keyring_from_id(INTEGRITY_KEYRING_IMA);
> + if (IS_ERR(keyring))
> + return false;
> +
> + return asymmetric_sig_has_known_key(keyring, (const char *) xattr_value,
> + xattr_len);
> +}
> +
>  int ima_read_xattr(struct dentry *dentry,
>  struct evm_ima_xattr_data **xattr_value)
>  {
> @@ -221,8 +237,12 @@ int ima_appraise_measurement(enum ima_hooks func,
>   struct inode *inode = d_backing_inode(dentry);
>   enum integrity_status status = INTEGRITY_UNKNOWN;
>   int rc = xattr_len, hash_start = 0;
> + size_t xattr_contents_len;
> + void *xattr_contents;
> 
> - if (!(inode->i_opflags & IOP_XATTR))
> + /* If not appraising a modsig, we need an xattr. */
> + if ((xattr_value == NULL || xattr_value->type != IMA_MODSIG) &&
> + !(inode->i_opflags & IOP_XATTR))
>   return INTEGRITY_UNKNOWN;
> 
>   if (rc <= 0) {
> @@ -241,13 +261,29 @@ int ima_appraise_measurement(enum ima_hooks func,
>   goto out;
>   }
> 
> - status = evm_verifyxattr(dentry, XATTR_NAME_IMA, xattr_value, rc, iint);
> + /*
> +  * If it's a modsig, we don't have the xattr contents to pass to
> +  * evm_verifyxattr().
> +  */
> + if (xattr_value->type == IMA_MODSIG) {
> + xattr_contents = NULL;
> + xattr_contents_len = 0;
> + } else {
> + xattr_contents = xattr_value;
> + xattr_contents_len = xattr_len;
> + }
> +
> + status = evm_verifyxattr(dentry, XATTR_NAME_IMA, xattr_contents,
> +  xattr_contents_len, iint);
>   switch (status) {
>   case INTEGRITY_PASS:
>   case INTEGRITY_PASS_IMMUTABLE:
>   case INTEGRITY_UNKNOWN:
>   break;
>   case INTEGRITY_NOXATTRS:/* No EVM protected xattrs. */
> + /* It's fine not to have xattrs when using a modsig. */
> + if (xattr_value->type == IMA_MODSIG)
> + break;
>   case INTEGRITY_NOLABEL: 

Re: [PATCH v6 12/12] ima: Write modsig to the measurement list

2018-03-26 Thread Mimi Zohar
On Fri, 2018-03-16 at 17:38 -0300, Thiago Jung Bauermann wrote:
> Define new "d-sig" template field which holds the digest that is expected
> to match the one contained in the modsig.
> 
> Also add modsig support to the "sig" template field, allowing the the
> contents of the modsig to be included in the measurement list.

Although including the appended signature in the template data doesn't
make sense on its own, as the file digest (without the appended
signature) is needed to validate the appended signature, defining a
new template field and its usage should be independent of other
changes.

Mimi

> 
> Suggested-by: Mimi Zohar <zo...@linux.vnet.ibm.com>
> Signed-off-by: Thiago Jung Bauermann <bauer...@linux.vnet.ibm.com>
> ---
>  Documentation/security/IMA-templates.rst  |  5 
>  security/integrity/ima/ima_template.c |  4 ++-
>  security/integrity/ima/ima_template_lib.c | 47 
> +--
>  security/integrity/ima/ima_template_lib.h |  2 ++
>  4 files changed, 55 insertions(+), 3 deletions(-)
> 
> diff --git a/Documentation/security/IMA-templates.rst 
> b/Documentation/security/IMA-templates.rst
> index 2cd0e273cc9a..f2a0f4225857 100644
> --- a/Documentation/security/IMA-templates.rst
> +++ b/Documentation/security/IMA-templates.rst
> @@ -68,6 +68,11 @@ descriptors by adding their identifier to the format string
>   - 'd-ng': the digest of the event, calculated with an arbitrary hash
> algorithm (field format: [:]digest, where the digest
> prefix is shown only if the hash algorithm is not SHA1 or MD5);
> + - 'd-sig': the digest of the event for files that have an appended modsig. 
> This
> +   field is calculated without including the modsig and thus will differ from
> +   the total digest of the file, but it is what should match the digest
> +   contained in the modsig (if it doesn't, the signature is invalid). It is
> +   shown in the same format as 'd-ng';
>   - 'n-ng': the name of the event, without size limitations;
>   - 'sig': the file signature.
> 
> diff --git a/security/integrity/ima/ima_template.c 
> b/security/integrity/ima/ima_template.c
> index 30db39b23804..36fc32f538b5 100644
> --- a/security/integrity/ima/ima_template.c
> +++ b/security/integrity/ima/ima_template.c
> @@ -43,8 +43,10 @@ static struct ima_template_field supported_fields[] = {
>.field_show = ima_show_template_string},
>   {.field_id = "sig", .field_init = ima_eventsig_init,
>.field_show = ima_show_template_sig},
> + {.field_id = "d-sig", .field_init = ima_eventdigest_sig_init,
> +  .field_show = ima_show_template_digest_ng},
>  };
> -#define MAX_TEMPLATE_NAME_LEN 15
> +#define MAX_TEMPLATE_NAME_LEN 24
> 
>  static struct ima_template_desc *ima_template;
>  static struct ima_template_desc *lookup_template_desc(const char *name);
> diff --git a/security/integrity/ima/ima_template_lib.c 
> b/security/integrity/ima/ima_template_lib.c
> index afb52a90e532..1dca082cce43 100644
> --- a/security/integrity/ima/ima_template_lib.c
> +++ b/security/integrity/ima/ima_template_lib.c
> @@ -220,7 +220,8 @@ int ima_parse_buf(void *bufstartp, void *bufendp, void 
> **bufcurp,
>   return 0;
>  }
> 
> -static int ima_eventdigest_init_common(u8 *digest, u32 digestsize, u8 
> hash_algo,
> +static int ima_eventdigest_init_common(const u8 *digest, u32 digestsize,
> +u8 hash_algo,
>  struct ima_field_data *field_data)
>  {
>   /*
> @@ -323,6 +324,35 @@ int ima_eventdigest_ng_init(struct ima_event_data 
> *event_data,
>  hash_algo, field_data);
>  }
> 
> +/*
> + * This function writes the digest of the file which is expected to match the
> + * digest contained in the file's embedded signature.
> + */
> +int ima_eventdigest_sig_init(struct ima_event_data *event_data,
> +  struct ima_field_data *field_data)
> +{
> + struct evm_ima_xattr_data *xattr_value = event_data->xattr_value;
> + enum hash_algo hash_algo = HASH_ALGO_SHA1;
> + const u8 *cur_digest = NULL;
> + u8 cur_digestsize = 0;
> + int ret;
> +
> + if (!xattr_value || xattr_value->type != IMA_MODSIG)
> + return 0;
> +
> + if (event_data->violation)  /* recording a violation. */
> + goto out;
> +
> + ret = ima_get_modsig_hash(xattr_value, _algo, _digest,
> +   _digestsize);
> + if (ret)
> + return ret;
> +
> + out:
> + return ima_eventdigest_init_common(cur_digest, cur_digestsize,
> + 

Re: [PATCH v6 03/12] PKCS#7: Introduce pkcs7_get_digest()

2018-03-22 Thread Mimi Zohar
On Fri, 2018-03-16 at 17:38 -0300, Thiago Jung Bauermann wrote:
> IMA will need to access the digest of the PKCS7 message (as calculated by
> the kernel) before the signature is verified, so introduce
> pkcs7_get_digest() for that purpose.
> 
> Also, modify pkcs7_digest() to detect when the digest was already
> calculated so that it doesn't have to do redundant work. Verifying that
> sinfo->sig->digest isn't NULL is sufficient because both places which
> allocate sinfo->sig (pkcs7_parse_message() and pkcs7_note_signed_info())
> use kzalloc() so sig->digest is always initialized to zero.
> 
> Signed-off-by: Thiago Jung Bauermann <bauer...@linux.vnet.ibm.com>
> Cc: David Howells <dhowe...@redhat.com>
> Cc: Herbert Xu <herb...@gondor.apana.org.au>
> Cc: "David S. Miller" <da...@davemloft.net>

Reviewed-by: Mimi Zohar <zo...@linux.vnet.ibm.com>

> ---
>  crypto/asymmetric_keys/pkcs7_verify.c | 25 +
>  include/crypto/pkcs7.h|  3 +++
>  2 files changed, 28 insertions(+)
> 
> diff --git a/crypto/asymmetric_keys/pkcs7_verify.c 
> b/crypto/asymmetric_keys/pkcs7_verify.c
> index 39e6de0c2761..bd02360f8be5 100644
> --- a/crypto/asymmetric_keys/pkcs7_verify.c
> +++ b/crypto/asymmetric_keys/pkcs7_verify.c
> @@ -33,6 +33,10 @@ static int pkcs7_digest(struct pkcs7_message *pkcs7,
> 
>   kenter(",%u,%s", sinfo->index, sinfo->sig->hash_algo);
> 
> + /* The digest was calculated already. */
> + if (sig->digest)
> + return 0;
> +
>   if (!sinfo->sig->hash_algo)
>   return -ENOPKG;
> 
> @@ -122,6 +126,27 @@ static int pkcs7_digest(struct pkcs7_message *pkcs7,
>   return ret;
>  }
> 
> +int pkcs7_get_digest(struct pkcs7_message *pkcs7, const u8 **buf, u8 *len)
> +{
> + struct pkcs7_signed_info *sinfo = pkcs7->signed_infos;
> + int ret;
> +
> + /*
> +  * This function doesn't support messages with more than one signature.
> +  */
> + if (sinfo == NULL || sinfo->next != NULL)
> + return -EBADMSG;
> +
> + ret = pkcs7_digest(pkcs7, sinfo);
> + if (ret)
> + return ret;
> +
> + *buf = sinfo->sig->digest;
> + *len = sinfo->sig->digest_size;
> +
> + return 0;
> +}
> +
>  /*
>   * Find the key (X.509 certificate) to use to verify a PKCS#7 message.  
> PKCS#7
>   * uses the issuer's name and the issuing certificate serial number for
> diff --git a/include/crypto/pkcs7.h b/include/crypto/pkcs7.h
> index 6f51d0cb6d12..cfaea9c37f4a 100644
> --- a/include/crypto/pkcs7.h
> +++ b/include/crypto/pkcs7.h
> @@ -46,4 +46,7 @@ extern int pkcs7_verify(struct pkcs7_message *pkcs7,
>  extern int pkcs7_supply_detached_data(struct pkcs7_message *pkcs7,
> const void *data, size_t datalen);
> 
> +extern int pkcs7_get_digest(struct pkcs7_message *pkcs7, const u8 **buf,
> + u8 *len);
> +
>  #endif /* _CRYPTO_PKCS7_H */
> 



Re: [PATCH v6 02/12] PKCS#7: Introduce pkcs7_get_message_sig() and verify_pkcs7_message_sig()

2018-03-22 Thread Mimi Zohar
Hi Thiago,

On Fri, 2018-03-16 at 17:38 -0300, Thiago Jung Bauermann wrote:
> IMA will need to know the key that signed a given PKCS#7 message, so add
> pkcs7_get_message_sig().
> 
> It will also need to verify an already parsed PKCS#7 message. For this
> purpose, add verify_pkcs7_message_sig() which takes a struct pkcs7_message
> for verification instead of the raw bytes that verify_pkcs7_signature()
> takes.

The title "PKCS#7: refactor verify_pkcs7_signature()" might be more
appropriate.  The patch description would then explain why it needs to
be refactored.  In this case, verify_pkcs7_signature() verifies the
signature using keys on the builtin and secondary keyrings.  IMA-
appraisal needs to verify the signature using keys on its keyring.

The patch itself looks good!

Reviewed-by: Mimi Zohar <zo...@linux.vnet.ibm.com>


> Signed-off-by: Thiago Jung Bauermann <bauer...@linux.vnet.ibm.com>
> Cc: David Howells <dhowe...@redhat.com>
> Cc: David Woodhouse <dw...@infradead.org>
> Cc: Herbert Xu <herb...@gondor.apana.org.au>
> Cc: "David S. Miller" <da...@davemloft.net>
> ---
>  certs/system_keyring.c| 61 
> ++-
>  crypto/asymmetric_keys/pkcs7_parser.c | 16 +
>  include/crypto/pkcs7.h|  2 ++
>  include/linux/verification.h  | 10 ++
>  4 files changed, 73 insertions(+), 16 deletions(-)
> 
> diff --git a/certs/system_keyring.c b/certs/system_keyring.c
> index 6251d1b27f0c..7ddc8b7a3062 100644
> --- a/certs/system_keyring.c
> +++ b/certs/system_keyring.c
> @@ -190,33 +190,27 @@ late_initcall(load_system_certificate_list);
>  #ifdef CONFIG_SYSTEM_DATA_VERIFICATION
> 
>  /**
> - * verify_pkcs7_signature - Verify a PKCS#7-based signature on system data.
> + * verify_pkcs7_message_sig - Verify a PKCS#7-based signature on system data.
>   * @data: The data to be verified (NULL if expecting internal data).
>   * @len: Size of @data.
> - * @raw_pkcs7: The PKCS#7 message that is the signature.
> - * @pkcs7_len: The size of @raw_pkcs7.
> + * @pkcs7: The PKCS#7 message that is the signature.
>   * @trusted_keys: Trusted keys to use (NULL for builtin trusted keys only,
>   *   (void *)1UL for all trusted keys).
>   * @usage: The use to which the key is being put.
>   * @view_content: Callback to gain access to content.
>   * @ctx: Context for callback.
>   */
> -int verify_pkcs7_signature(const void *data, size_t len,
> -const void *raw_pkcs7, size_t pkcs7_len,
> -struct key *trusted_keys,
> -enum key_being_used_for usage,
> -int (*view_content)(void *ctx,
> -const void *data, size_t len,
> -size_t asn1hdrlen),
> -void *ctx)
> +int verify_pkcs7_message_sig(const void *data, size_t len,
> +  struct pkcs7_message *pkcs7,
> +  struct key *trusted_keys,
> +  enum key_being_used_for usage,
> +  int (*view_content)(void *ctx,
> +  const void *data, size_t len,
> +  size_t asn1hdrlen),
> +  void *ctx)
>  {
> - struct pkcs7_message *pkcs7;
>   int ret;
> 
> - pkcs7 = pkcs7_parse_message(raw_pkcs7, pkcs7_len);
> - if (IS_ERR(pkcs7))
> - return PTR_ERR(pkcs7);
> -
>   /* The data should be detached - so we need to supply it. */
>   if (data && pkcs7_supply_detached_data(pkcs7, data, len) < 0) {
>   pr_err("PKCS#7 signature with non-detached data\n");
> @@ -258,6 +252,41 @@ int verify_pkcs7_signature(const void *data, size_t len,
>   }
> 
>  error:
> + pr_devel("<==%s() = %d\n", __func__, ret);
> + return ret;
> +}
> +
> +/**
> + * verify_pkcs7_signature - Verify a PKCS#7-based signature on system data.
> + * @data: The data to be verified (NULL if expecting internal data).
> + * @len: Size of @data.
> + * @raw_pkcs7: The PKCS#7 message that is the signature.
> + * @pkcs7_len: The size of @raw_pkcs7.
> + * @trusted_keys: Trusted keys to use (NULL for builtin trusted keys only,
> + *   (void *)1UL for all trusted keys).
> + * @usage: The use to which the key is being put.
> + * @view_content: Callback to gain access to content.
> + * @ctx: Context for callback.
> + */
> +int verify_pkcs7_signature(const void *data, size_t len,
> +   

Re: [PATCH v6 07/12] integrity: Select CONFIG_KEYS instead of depending on it

2018-03-21 Thread Mimi Zohar
On Fri, 2018-03-16 at 17:38 -0300, Thiago Jung Bauermann wrote:
> This avoids a dependency cycle in CONFIG_IMA_APPRAISE_MODSIG (introduced by
> a later patch in this series): it will select CONFIG_MODULE_SIG_FORMAT
> which in turn selects CONFIG_KEYS. Kconfig then complains that
> CONFIG_INTEGRITY_SIGNATURE depends on CONFIG_KEYS.
> 
> Signed-off-by: Thiago Jung Bauermann <bauer...@linux.vnet.ibm.com>

Signed-off-by: Mimi Zohar <zo...@linux.vnet.ibm.com>

> ---
>  security/integrity/Kconfig | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/security/integrity/Kconfig b/security/integrity/Kconfig
> index da9565891738..0d642e0317c7 100644
> --- a/security/integrity/Kconfig
> +++ b/security/integrity/Kconfig
> @@ -17,8 +17,8 @@ if INTEGRITY
> 
>  config INTEGRITY_SIGNATURE
>   bool "Digital signature verification using multiple keyrings"
> - depends on KEYS
>   default n
> + select KEYS
>   select SIGNATURE
>   help
> This option enables digital signature verification support
> 



Re: [PATCH v6 06/12] integrity: Introduce asymmetric_sig_has_known_key()

2018-03-21 Thread Mimi Zohar
On Fri, 2018-03-16 at 17:38 -0300, Thiago Jung Bauermann wrote:
> IMA will only look for a modsig if the xattr sig references a key which is
> not in the expected kernel keyring. To that end, introduce
> asymmetric_sig_has_known_key().
> 
> The logic of extracting the key used in the xattr sig is factored out from
> asymmetric_verify() so that it can be used by the new function.
> 
> Signed-off-by: Thiago Jung Bauermann <bauer...@linux.vnet.ibm.com>

Signed-off-by: Mimi Zohar <zo...@linux.vnet.ibm.com>

> ---
>  security/integrity/digsig_asymmetric.c | 44 
> +-
>  security/integrity/integrity.h |  8 +++
>  2 files changed, 41 insertions(+), 11 deletions(-)
> 
> diff --git a/security/integrity/digsig_asymmetric.c 
> b/security/integrity/digsig_asymmetric.c
> index ab6a029062a1..241647970c19 100644
> --- a/security/integrity/digsig_asymmetric.c
> +++ b/security/integrity/digsig_asymmetric.c
> @@ -79,26 +79,48 @@ static struct key *request_asymmetric_key(struct key 
> *keyring, uint32_t keyid)
>   return key;
>  }
> 
> -int asymmetric_verify(struct key *keyring, const char *sig,
> -   int siglen, const char *data, int datalen)
> +static struct key *asymmetric_key_from_sig(struct key *keyring, const char 
> *sig,
> +int siglen)
>  {
> - struct public_key_signature pks;
> - struct signature_v2_hdr *hdr = (struct signature_v2_hdr *)sig;
> - struct key *key;
> - int ret = -ENOMEM;
> + const struct signature_v2_hdr *hdr = (struct signature_v2_hdr *) sig;
> 
>   if (siglen <= sizeof(*hdr))
> - return -EBADMSG;
> + return ERR_PTR(-EBADMSG);
> 
>   siglen -= sizeof(*hdr);
> 
>   if (siglen != be16_to_cpu(hdr->sig_size))
> - return -EBADMSG;
> + return ERR_PTR(-EBADMSG);
> 
>   if (hdr->hash_algo >= HASH_ALGO__LAST)
> - return -ENOPKG;
> + return ERR_PTR(-ENOPKG);
> +
> + return request_asymmetric_key(keyring, be32_to_cpu(hdr->keyid));
> +}
> +
> +bool asymmetric_sig_has_known_key(struct key *keyring, const char *sig,
> +   int siglen)
> +{
> + struct key *key;
> +
> + key = asymmetric_key_from_sig(keyring, sig, siglen);
> + if (IS_ERR_OR_NULL(key))
> + return false;
> +
> + key_put(key);
> +
> + return true;
> +}
> +
> +int asymmetric_verify(struct key *keyring, const char *sig,
> +   int siglen, const char *data, int datalen)
> +{
> + struct public_key_signature pks;
> + struct signature_v2_hdr *hdr = (struct signature_v2_hdr *)sig;
> + struct key *key;
> + int ret = -ENOMEM;
> 
> - key = request_asymmetric_key(keyring, be32_to_cpu(hdr->keyid));
> + key = asymmetric_key_from_sig(keyring, sig, siglen);
>   if (IS_ERR(key))
>   return PTR_ERR(key);
> 
> @@ -109,7 +131,7 @@ int asymmetric_verify(struct key *keyring, const char 
> *sig,
>   pks.digest = (u8 *)data;
>   pks.digest_size = datalen;
>   pks.s = hdr->sig;
> - pks.s_size = siglen;
> + pks.s_size = siglen - sizeof(*hdr);
>   ret = verify_signature(key, );
>   key_put(key);
>   pr_debug("%s() = %d\n", __func__, ret);
> diff --git a/security/integrity/integrity.h b/security/integrity/integrity.h
> index 2d245f44ca26..4c381b992e11 100644
> --- a/security/integrity/integrity.h
> +++ b/security/integrity/integrity.h
> @@ -179,12 +179,20 @@ static inline int integrity_init_keyring(const unsigned 
> int id)
>  #ifdef CONFIG_INTEGRITY_ASYMMETRIC_KEYS
>  int asymmetric_verify(struct key *keyring, const char *sig,
> int siglen, const char *data, int datalen);
> +bool asymmetric_sig_has_known_key(struct key *keyring, const char *sig,
> +   int siglen);
>  #else
>  static inline int asymmetric_verify(struct key *keyring, const char *sig,
>   int siglen, const char *data, int datalen)
>  {
>   return -EOPNOTSUPP;
>  }
> +
> +static inline bool asymmetric_sig_has_known_key(struct key *keyring,
> + const char *sig, int siglen)
> +{
> + return false;
> +}
>  #endif
> 
>  #ifdef CONFIG_IMA_LOAD_X509
> 



Re: [PATCH v6 05/12] integrity: Introduce integrity_keyring_from_id()

2018-03-21 Thread Mimi Zohar
On Fri, 2018-03-16 at 17:38 -0300, Thiago Jung Bauermann wrote:
> IMA will need to obtain the keyring used to verify file signatures so that
> it can verify the module-style signature appended to files.
> 
> Signed-off-by: Thiago Jung Bauermann <bauer...@linux.vnet.ibm.com>

Signed-off-by: Mimi Zohar <zo...@linux.vnet.ibm.com>

> ---
>  security/integrity/digsig.c| 28 +---
>  security/integrity/integrity.h |  6 ++
>  2 files changed, 27 insertions(+), 7 deletions(-)
> 
> diff --git a/security/integrity/digsig.c b/security/integrity/digsig.c
> index 6f9e4ce568cd..e641a67b9fc7 100644
> --- a/security/integrity/digsig.c
> +++ b/security/integrity/digsig.c
> @@ -48,11 +48,10 @@ static bool init_keyring __initdata;
>  #define restrict_link_to_ima restrict_link_by_builtin_trusted
>  #endif
> 
> -int integrity_digsig_verify(const unsigned int id, const char *sig, int 
> siglen,
> - const char *digest, int digestlen)
> +struct key *integrity_keyring_from_id(const unsigned int id)
>  {
> - if (id >= INTEGRITY_KEYRING_MAX || siglen < 2)
> - return -EINVAL;
> + if (id >= INTEGRITY_KEYRING_MAX)
> + return ERR_PTR(-EINVAL);
> 
>   if (!keyring[id]) {
>   keyring[id] =
> @@ -61,17 +60,32 @@ int integrity_digsig_verify(const unsigned int id, const 
> char *sig, int siglen,
>   int err = PTR_ERR(keyring[id]);
>   pr_err("no %s keyring: %d\n", keyring_name[id], err);
>   keyring[id] = NULL;
> - return err;
> + return ERR_PTR(err);
>   }
>   }
> 
> + return keyring[id];
> +}
> +
> +int integrity_digsig_verify(const unsigned int id, const char *sig, int 
> siglen,
> + const char *digest, int digestlen)
> +{
> + struct key *keyring;
> +
> + if (siglen < 2)
> + return -EINVAL;
> +
> + keyring = integrity_keyring_from_id(id);
> + if (IS_ERR(keyring))
> + return PTR_ERR(keyring);
> +
>   switch (sig[1]) {
>   case 1:
>   /* v1 API expect signature without xattr type */
> - return digsig_verify(keyring[id], sig + 1, siglen - 1,
> + return digsig_verify(keyring, sig + 1, siglen - 1,
>digest, digestlen);
>   case 2:
> - return asymmetric_verify(keyring[id], sig, siglen,
> + return asymmetric_verify(keyring, sig, siglen,
>digest, digestlen);
>   }
> 
> diff --git a/security/integrity/integrity.h b/security/integrity/integrity.h
> index 79799a0d9195..2d245f44ca26 100644
> --- a/security/integrity/integrity.h
> +++ b/security/integrity/integrity.h
> @@ -150,6 +150,7 @@ int integrity_kernel_read(struct file *file, loff_t 
> offset,
> 
>  #ifdef CONFIG_INTEGRITY_SIGNATURE
> 
> +struct key *integrity_keyring_from_id(const unsigned int id);
>  int integrity_digsig_verify(const unsigned int id, const char *sig, int 
> siglen,
>   const char *digest, int digestlen);
> 
> @@ -157,6 +158,11 @@ int __init integrity_init_keyring(const unsigned int id);
>  int __init integrity_load_x509(const unsigned int id, const char *path);
>  #else
> 
> +static inline struct key *integrity_keyring_from_id(const unsigned int id)
> +{
> + return ERR_PTR(-EINVAL);
> +}
> +
>  static inline int integrity_digsig_verify(const unsigned int id,
> const char *sig, int siglen,
> const char *digest, int digestlen)
> 



Re: [PATCH v5 17/18] ima: Implement support for module-style appended signatures

2017-10-31 Thread Mimi Zohar
On Tue, 2017-10-17 at 22:53 -0200, Thiago Jung Bauermann wrote:

Below are a few additional comments.

> @@ -200,18 +239,28 @@ int ima_read_xattr(struct dentry *dentry,
>   */
>  int ima_appraise_measurement(enum ima_hooks func,
>struct integrity_iint_cache *iint,
> -  struct file *file, const unsigned char *filename,
> -  struct evm_ima_xattr_data *xattr_value,
> -  int xattr_len, int opened)
> +  struct file *file, const void *buf, loff_t size,
> +  const unsigned char *filename,
> +  struct evm_ima_xattr_data **xattr_value_,
> +  int *xattr_len_, int opened)
>  {
>   static const char op[] = "appraise_data";
>   const char *cause = "unknown";
>   struct dentry *dentry = file_dentry(file);
>   struct inode *inode = d_backing_inode(dentry);
>   enum integrity_status status = INTEGRITY_UNKNOWN;
> - int rc = xattr_len, hash_start = 0;
> + struct evm_ima_xattr_data *xattr_value = *xattr_value_;
> + int xattr_len = *xattr_len_, rc = xattr_len, hash_start = 0;
> + bool appraising_modsig = false;
> +
> + if (iint->flags & IMA_MODSIG_ALLOWED &&
> + !ima_read_modsig(func, buf, size, _value, _len)) {
> + appraising_modsig = true;
> + rc = xattr_len;
> + }
> 
> - if (!(inode->i_opflags & IOP_XATTR))
> + /* If not appraising a modsig, we need an xattr. */
> + if (!appraising_modsig && !(inode->i_opflags & IOP_XATTR))
>   return INTEGRITY_UNKNOWN;
> 
>   if (rc <= 0) {
> @@ -235,6 +284,9 @@ int ima_appraise_measurement(enum ima_hooks func,
>   case INTEGRITY_UNKNOWN:
>   break;
>   case INTEGRITY_NOXATTRS:/* No EVM protected xattrs. */
> + /* It's fine not to have xattrs when using a modsig. */
> + if (appraising_modsig)
> + break;
>   case INTEGRITY_NOLABEL: /* No security.evm xattr. */
>   cause = "missing-HMAC";
>   goto out;
> @@ -242,6 +294,8 @@ int ima_appraise_measurement(enum ima_hooks func,
>   cause = "invalid-HMAC";
>   goto out;
>   }
> +
> + retry:
>   switch (xattr_value->type) {
>   case IMA_XATTR_DIGEST_NG:
>   /* first byte contains algorithm id */
> @@ -285,6 +339,61 @@ int ima_appraise_measurement(enum ima_hooks func,
>   status = INTEGRITY_PASS;
>   }
>   break;
> + case IMA_MODSIG:
> + /*
> +  * To avoid being tricked into an infinite loop, we don't allow
> +  * a modsig stored in the xattr.
> +  */
> + if (!appraising_modsig) {
> + status = INTEGRITY_UNKNOWN;
> + cause = "unknown-ima-data";
> + break;
> + }
> + rc = appraise_modsig(iint, xattr_value, xattr_len);
> + if (!rc) {
> + kfree(*xattr_value_);
> + *xattr_value_ = xattr_value;
> + *xattr_len_ = xattr_len;
> +
> + status = INTEGRITY_PASS;
> + break;
> + }
> +
> + ima_free_xattr_data(xattr_value);
> +
> + /*
> +  * The appended signature failed verification. If there's a
> +  * signature in the extended attribute, let's fall back to it.
> +  */
> + if (inode->i_opflags & IOP_XATTR && *xattr_len_ != 0 &&
> + *xattr_len_ != -ENODATA) {

At this point, there was an appended signature verification failure.
 If there isn't an xattr, for whatever reason, shouldn't we be
returning "invalid_signature" and "INTEGRITY_FAIL".  If so, then the
above test could be simplified to check whether there is any data,
like this:

if ((inode->i_opflags & IOP_XATTR) && (*xattr_len_ > 0)) {

> + const char *modsig_cause = rc == -EOPNOTSUPP ?
> + "unknown" : "invalid-signature";

This can then be cleaned up as well.

> +
> + /* First, log that the modsig verification failed. */
> + integrity_audit_msg(AUDIT_INTEGRITY_DATA, inode,
> + filename, op, modsig_cause, rc, 0);

I'm not sure that we want to audit intermediary signature verification
failures.  Perhaps this audit message should be considered
"additional", meaning it is only emitted if the "integrity_audit" boot
command line option is enabled.  Change the last field to 1 to
indicate it is an "additional" audit message.

> +
> + xattr_len = rc = *xattr_len_;
> + xattr_value = *xattr_value_;
> + appraising_modsig = false;
> +
> + if (rc > 0)

This test 

Re: [PATCH v5 12/18] MODSIGN: Export module signature definitions

2017-10-26 Thread Mimi Zohar
On Thu, 2017-10-26 at 20:47 -0200, Thiago Jung Bauermann wrote:
> Mimi Zohar <zo...@linux.vnet.ibm.com> writes:
> 
> > On Tue, 2017-10-17 at 22:53 -0200, Thiago Jung Bauermann wrote:
> >> IMA will use the module_signature format for append signatures, so export
> >> the relevant definitions and factor out the code which verifies that the
> >> appended signature trailer is valid.
> >> 
> >> Also, create a CONFIG_MODULE_SIG_FORMAT option so that IMA can select it
> >> and be able to use validate_module_signature without having to depend on
> >> CONFIG_MODULE_SIG.
> >> 
> >> Signed-off-by: Thiago Jung Bauermann <bauer...@linux.vnet.ibm.com>
> >
> > Reviewed-by: Mimi Zohar <zo...@linux.vnet.ibm.com>
> >
> > One minor comment below...
> 
> Thanks!
> 
> >> diff --git a/kernel/module_signing.c b/kernel/module_signing.c
> >> index 937c844bee4a..204c60d4cc9f 100644
> >> --- a/kernel/module_signing.c
> >> +++ b/kernel/module_signing.c
> >> @@ -11,36 +11,38 @@
> >> 
> >>  #include 
> >>  #include 
> >> +#include 
> >>  #include 
> >>  #include 
> >>  #include 
> >>  #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.
> >> - *
> >> - * The constituents of the signature section are, in order:
> >> +/**
> >> + * validate_module_sig - validate that the given signature is sane
> >>   *
> >> - *- Signer's name
> >> - *- Key identifier
> >> - *- Signature data
> >> - *- Information block
> >> + * @ms:   Signature to validate.
> >> + * @file_len: Size of the file to which @ms is appended.
> >>   */
> >> -struct module_signature {
> >> -  u8  algo;   /* Public-key crypto algorithm [0] */
> >> -  u8  hash;   /* Digest algorithm [0] */
> >> -  u8  id_type;/* Key identifier type [PKEY_ID_PKCS7] */
> >> -  u8  signer_len; /* Length of signer's name [0] */
> >> -  u8  key_id_len; /* Length of key identifier [0] */
> >> -  u8  __pad[3];
> >> -  __be32  sig_len;/* Length of signature data */
> >> -};
> >> +int validate_module_sig(const struct module_signature *ms, size_t 
> >> file_len)
> >> +{
> >> +  if (be32_to_cpu(ms->sig_len) >= file_len - sizeof(*ms))
> >> +  return -EBADMSG;
> >> +  else if (ms->id_type != PKEY_ID_PKCS7) {
> >> +  pr_err("Module is not signed with expected PKCS#7 message\n");
> >> +  return -ENOPKG;
> >> +  } else if (ms->algo != 0 ||
> >> + ms->hash != 0 ||
> >> + ms->signer_len != 0 ||
> >> + ms->key_id_len != 0 ||
> >> + ms->__pad[0] != 0 ||
> >> + ms->__pad[1] != 0 ||
> >> + ms->__pad[2] != 0) {
> >> +  pr_err("PKCS#7 signature info has unexpected non-zero 
> >> params\n");
> >> +  return -EBADMSG;
> >> +  }
> >> +
> >
> > When moving code from one place to another, it's easier to review when
> > there aren't code changes as well. In this case, the original code
> > doesn't have "else clauses".
> 
> Indeed. I changed the code back to using separate if clauses, making
> only the changes that are required for the refactoring.
> 
> > Here some of the if/then/else clauses
> > have braces others don't. There shouldn't be a mixture.
> 
> Does this still apply when the if clauses are separate as in the
> original code? Should the first if still have braces?

No, the original code was fine. 



Re: [PATCH v5 00/18] Appended signatures support for IMA appraisal

2017-10-26 Thread Mimi Zohar
On Tue, 2017-10-17 at 22:53 -0200, Thiago Jung Bauermann wrote:
> Hello,
> 
> The main highlight in this version is that it fixes a bug where the modsig
> wasn't being included in the measurement list if the appraised file was
> already measured by another rule. The fix is in the last patch.
> 
> Another change is that the last patch in the v4 series ("ima: Support
> module-style appended signatures for appraisal") has been broken up into
> smaller patches. I may have overdone it...
> 
> Finally, I have added some patches removing superfluous parentheses from
> expressions. IMO these patches make it easier (and more pleasant) to read
> the code, and thus easier to understand it. Since I'm not sure how welcome
> the changes are, I split them in 3 "levels" in increasing potential for
> conflict with patches from other people (they can be squashed together when
> applied):
> 
> 1. patch 2 contains the bare minimum, changing only lines that are also
>touched by other patches in the series;
> 
> 2. patch 3 cleans up all the files that are touched by this patch series;
> 
> 3. patch 4 cleans up all other EVM and IMA files that weren't already fixed
>by the previous patches.
> 
> If unwanted, patches 3 and 4 can be simply skipped without affecting the
> rest of the patches. I have already rebased them from v4.13-rc2 to
> v4.14-rc3 and now to linux-integrity/next with very few easy to resolve
> conflicts, so I think they are worth keeping.
> 
> These patches apply on top of today's linux-integrity/next.

This cover letter and the patch descriptions are well written,
explaining what and why you're making this change.  The problem is
that I don't agree that fewer parentheses makes the code more
readable.  When you repost the patches (for other reasons), please
don't include these changes.

thanks,

Mimi



Re: [PATCH v5 13/18] PKCS#7: Introduce pkcs7_get_message_sig and verify_pkcs7_message_sig

2017-10-26 Thread Mimi Zohar
On Tue, 2017-10-17 at 22:53 -0200, Thiago Jung Bauermann wrote:
> IMA will need to access the digest used in the signature so that it can
> verify files containing module-style appended signatures. For this purpose,
> add function pkcs7_get_message_sig.
> 
> It will also need to verify an already parsed PKCS#7 message. For this
> purpose, add function verify_pkcs7_message_signature which takes a struct
> pkcs7_message for verification instead of the raw bytes that
> verify_pkcs7_signature takes.
> 
> Signed-off-by: Thiago Jung Bauermann <bauer...@linux.vnet.ibm.com>

Reviewed-by: Mimi Zohar <zo...@linux.vnet.ibm.com>

> ---
>  certs/system_keyring.c| 60 
> +--
>  crypto/asymmetric_keys/pkcs7_parser.c | 12 +++
>  include/crypto/pkcs7.h|  2 ++
>  include/linux/verification.h  | 10 ++
>  4 files changed, 68 insertions(+), 16 deletions(-)
> 
> diff --git a/certs/system_keyring.c b/certs/system_keyring.c
> index 6251d1b27f0c..6a8684959780 100644
> --- a/certs/system_keyring.c
> +++ b/certs/system_keyring.c
> @@ -190,33 +190,26 @@ late_initcall(load_system_certificate_list);
>  #ifdef CONFIG_SYSTEM_DATA_VERIFICATION
> 
>  /**
> - * verify_pkcs7_signature - Verify a PKCS#7-based signature on system data.
> + * verify_pkcs7_message_sig - Verify a PKCS#7-based signature on system data.
>   * @data: The data to be verified (NULL if expecting internal data).
>   * @len: Size of @data.
> - * @raw_pkcs7: The PKCS#7 message that is the signature.
> - * @pkcs7_len: The size of @raw_pkcs7.
> + * @pkcs7: The PKCS#7 message that is the signature.
>   * @trusted_keys: Trusted keys to use (NULL for builtin trusted keys only,
>   *   (void *)1UL for all trusted keys).
>   * @usage: The use to which the key is being put.
>   * @view_content: Callback to gain access to content.
>   * @ctx: Context for callback.
>   */
> -int verify_pkcs7_signature(const void *data, size_t len,
> -const void *raw_pkcs7, size_t pkcs7_len,
> -struct key *trusted_keys,
> -enum key_being_used_for usage,
> -int (*view_content)(void *ctx,
> -const void *data, size_t len,
> -size_t asn1hdrlen),
> -void *ctx)
> +int verify_pkcs7_message_sig(const void *data, size_t len,
> +  struct pkcs7_message *pkcs7,
> +  struct key *trusted_keys,
> +  enum key_being_used_for usage,
> +  int (*view_content)(void *ctx, const void *data,
> +  size_t len, size_t asn1hdrlen),
> +  void *ctx)
>  {
> - struct pkcs7_message *pkcs7;
>   int ret;
> 
> - pkcs7 = pkcs7_parse_message(raw_pkcs7, pkcs7_len);
> - if (IS_ERR(pkcs7))
> - return PTR_ERR(pkcs7);
> -
>   /* The data should be detached - so we need to supply it. */
>   if (data && pkcs7_supply_detached_data(pkcs7, data, len) < 0) {
>   pr_err("PKCS#7 signature with non-detached data\n");
> @@ -258,6 +251,41 @@ int verify_pkcs7_signature(const void *data, size_t len,
>   }
> 
>  error:
> + pr_devel("<==%s() = %d\n", __func__, ret);
> + return ret;
> +}
> +
> +/**
> + * verify_pkcs7_signature - Verify a PKCS#7-based signature on system data.
> + * @data: The data to be verified (NULL if expecting internal data).
> + * @len: Size of @data.
> + * @raw_pkcs7: The PKCS#7 message that is the signature.
> + * @pkcs7_len: The size of @raw_pkcs7.
> + * @trusted_keys: Trusted keys to use (NULL for builtin trusted keys only,
> + *   (void *)1UL for all trusted keys).
> + * @usage: The use to which the key is being put.
> + * @view_content: Callback to gain access to content.
> + * @ctx: Context for callback.
> + */
> +int verify_pkcs7_signature(const void *data, size_t len,
> +const void *raw_pkcs7, size_t pkcs7_len,
> +struct key *trusted_keys,
> +enum key_being_used_for usage,
> +int (*view_content)(void *ctx,
> +const void *data, size_t len,
> +size_t asn1hdrlen),
> +void *ctx)
> +{
> + struct pkcs7_message *pkcs7;
> + int ret;
> +
> + pkcs7 = pkcs7_parse_message(raw_pkcs7, pkcs7_len);
> + if (IS_ERR(pkcs7))

Re: [PATCH v5 12/18] MODSIGN: Export module signature definitions

2017-10-26 Thread Mimi Zohar
On Tue, 2017-10-17 at 22:53 -0200, Thiago Jung Bauermann wrote:
> IMA will use the module_signature format for append signatures, so export
> the relevant definitions and factor out the code which verifies that the
> appended signature trailer is valid.
> 
> Also, create a CONFIG_MODULE_SIG_FORMAT option so that IMA can select it
> and be able to use validate_module_signature without having to depend on
> CONFIG_MODULE_SIG.
> 
> Signed-off-by: Thiago Jung Bauermann <bauer...@linux.vnet.ibm.com>

Reviewed-by: Mimi Zohar <zo...@linux.vnet.ibm.com>

One minor comment below...

> ---
>  include/linux/module.h   |  3 --
>  include/linux/module_signature.h | 47 +
>  init/Kconfig |  6 +++-
>  kernel/Makefile  |  2 +-
>  kernel/module.c  |  1 +
>  kernel/module_signing.c  | 74 
> +---
>  6 files changed, 85 insertions(+), 48 deletions(-)
> 
> diff --git a/include/linux/module.h b/include/linux/module.h
> index fe5aa3736707..108874af9838 100644
> --- a/include/linux/module.h
> +++ b/include/linux/module.h
> @@ -23,9 +23,6 @@
>  #include 
>  #include 
> 
> -/* In stripped ARM and x86-64 modules, ~ is surprisingly rare. */
> -#define MODULE_SIG_STRING "~Module signature appended~\n"
> -
>  /* Not Yet Implemented */
>  #define MODULE_SUPPORTED_DEVICE(name)
> 
> diff --git a/include/linux/module_signature.h 
> b/include/linux/module_signature.h
> new file mode 100644
> index ..e80728e5b86c
> --- /dev/null
> +++ b/include/linux/module_signature.h
> @@ -0,0 +1,47 @@
> +/* Module signature handling.
> + *
> + * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved.
> + * Written by David Howells (dhowe...@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.
> + */
> +
> +#ifndef _LINUX_MODULE_SIGNATURE_H
> +#define _LINUX_MODULE_SIGNATURE_H
> +
> +/* In stripped ARM and x86-64 modules, ~ is surprisingly rare. */
> +#define MODULE_SIG_STRING "~Module signature appended~\n"
> +
> +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.
> + *
> + * The constituents of the signature section are, in order:
> + *
> + *   - Signer's name
> + *   - Key identifier
> + *   - Signature data
> + *   - Information block
> + */
> +struct module_signature {
> + u8  algo;   /* Public-key crypto algorithm [0] */
> + u8  hash;   /* Digest algorithm [0] */
> + u8  id_type;/* Key identifier type [PKEY_ID_PKCS7] */
> + u8  signer_len; /* Length of signer's name [0] */
> + u8  key_id_len; /* Length of key identifier [0] */
> + u8  __pad[3];
> + __be32  sig_len;/* Length of signature data */
> +};
> +
> +int validate_module_sig(const struct module_signature *ms, size_t file_len);
> +int mod_verify_sig(const void *mod, unsigned long *_modlen);
> +
> +#endif /* _LINUX_MODULE_SIGNATURE_H */
> diff --git a/init/Kconfig b/init/Kconfig
> index 78cb2461012e..230e9f3aedaf 100644
> --- a/init/Kconfig
> +++ b/init/Kconfig
> @@ -1748,7 +1748,7 @@ config MODULE_SRCVERSION_ALL
>  config MODULE_SIG
>   bool "Module signature verification"
>   depends on MODULES
> - select SYSTEM_DATA_VERIFICATION
> + select MODULE_SIG_FORMAT
>   help
> Check modules for valid signatures upon load: the signature
> is simply appended to the module. For more information see
> @@ -1763,6 +1763,10 @@ config MODULE_SIG
> debuginfo strip done by some packagers (such as rpmbuild) and
> inclusion into an initramfs that wants the module size reduced.
> 
> +config MODULE_SIG_FORMAT
> + def_bool n
> + select SYSTEM_DATA_VERIFICATION
> +
>  config MODULE_SIG_FORCE
>   bool "Require modules to be validly signed"
>   depends on MODULE_SIG
> diff --git a/kernel/Makefile b/kernel/Makefile
> index ed470aac53da..20fd6d76232e 100644
> --- a/kernel/Makefile
> +++ b/kernel/Makefile
> @@ -57,7 +57,7 @@ obj-y += up.o
>  endif
>  obj-$(CONFIG_UID16) += uid16.o
>  obj-$(CONFIG_MODULES) += module.o
> -obj-$(CONFIG_MODULE_SIG) += module_signing.o
> +

Re: [PATCH v5 18/18] ima: Write modsig to the measurement list

2017-10-26 Thread Mimi Zohar
On Tue, 2017-10-17 at 22:53 -0200, Thiago Jung Bauermann wrote:

> diff --git a/security/integrity/ima/ima_main.c 
> b/security/integrity/ima/ima_main.c
> index 6a2d960fbd92..0d3390de7432 100644
> --- a/security/integrity/ima/ima_main.c
> +++ b/security/integrity/ima/ima_main.c
> @@ -246,7 +246,35 @@ static int process_measurement(struct file *file, char 
> *buf, loff_t size,
>   rc = ima_appraise_measurement(func, iint, file, buf, size,
> pathname, _value,
> _len, opened);
> - if (action & IMA_MEASURE)
> +
> + /*
> +  * MODSIG has one corner case we need to deal with here:
> +  *
> +  * Suppose the policy has one measure rule for one hook and an appraise
> +  * rule for a different hook. Suppose also that the template requires
> +  * the signature to be stored in the measurement list.
> +  *
> +  * If a file containing a MODSIG is measured by the first hook before
> +  * being appraised by the second one, the corresponding entry in the
> +  * measurement list will not contain the MODSIG because we only fetch it
> +  * for IMA_APPRAISAL. We don't fetch it earlier because if the file has
> +  * both a DIGSIG and a MODSIG it's not possible to know which one will
> +  * be valid without actually doing the appraisal.
> +  *
> +  * Therefore, after appraisal of a MODSIG signature we need to store the
> +  * measurement again if the current template requires storing the
> +  * signature.

Yes, all true, but this long comment doesn't belong here in the middle
of process_measurement(). 

> +  * With the opposite ordering (the appraise rule triggering before the
> +  * measurement rule) there is the same problem but it's not possible to
> +  * do anything about it because at the time we are appraising the
> +  * signature it's impossible to know whether a measurement will ever
> +  * need to be stored for this file.
> +  */

With the template format "ima-sig", the verified file signature needs
to be included in the measurement list.  Based on this file signature,
the attestation server can validate the signature.

In this case, where the appraisal comes first followed by the
measurement, the appraised file signature is included in the
measurement list.  I don't see the problem here.

> + if ((action & IMA_MEASURE) || ((iint->flags & IMA_MEASURE) &&
> +xattr_value &&
> +xattr_value->type == IMA_MODSIG &&
> +ima_current_template_has_sig()))

Like the clean up you did elsewhere, this new set of tests should be
made into a function.  The comment could placed along with the new
function.

Mimi

>   ima_store_measurement(iint, file, pathname,
> xattr_value, xattr_len, pcr);
>   if (action & IMA_AUDIT)
> 



Re: [PATCH v4 7/7] ima: Support module-style appended signatures for appraisal

2017-08-17 Thread Mimi Zohar
On Fri, 2017-08-04 at 19:03 -0300, Thiago Jung Bauermann wrote:
> This patch introduces the modsig keyword to the IMA policy syntax to
> specify that a given hook should expect the file to have the IMA signature
> appended to it. Here is how it can be used in a rule:
> 
> appraise func=KEXEC_KERNEL_CHECK appraise_type=modsig|imasig
> 
> With this rule, IMA will accept either an appended signature or a signature
> stored in the extended attribute. In that case, it will first check whether
> there is an appended signature, and if not it will read it from the
> extended attribute.
> 
> The format of the appended signature is the same used for signed kernel
> modules. This means that the file can be signed with the scripts/sign-file
> tool, with a command line such as this:
> 
> $ sign-file sha256 privkey_ima.pem x509_ima.der vmlinux
> 
> This code only works for files that are hashed from a memory buffer, not
> for files that are read from disk at the time of hash calculation. In other
> words, only hooks that use kernel_read_file can support appended
> signatures. This means that only FIRMWARE_CHECK, KEXEC_KERNEL_CHECK,
> KEXEC_INITRAMFS_CHECK and POLICY_CHECK can be supported.
> 
> This feature warrants a separate config option because enabling it brings
> in many other config options.
> 
> Signed-off-by: Thiago Jung Bauermann 

Other than the appended signature not being properly included in the
measurement list, the patch seems to be working.  This patch is on the
rather large size. Could you go back and break this patch up into
smaller, more concise patches, with clear patch descriptions (eg.
separate code cleanup from changes, new policy option, code for
appraising an attached signature, storing the appended signature in
the measurement list, etc)?

thanks!

Mimi

> ---
>  security/integrity/ima/Kconfig|  13 +++
>  security/integrity/ima/Makefile   |   1 +
>  security/integrity/ima/ima.h  |  70 +++-
>  security/integrity/ima/ima_appraise.c | 178 
> +-
>  security/integrity/ima/ima_main.c |   7 +-
>  security/integrity/ima/ima_modsig.c   | 178 
> ++
>  security/integrity/ima/ima_policy.c   |  26 +++--
>  security/integrity/ima/ima_template_lib.c |  14 ++-
>  security/integrity/integrity.h|   4 +-
>  9 files changed, 443 insertions(+), 48 deletions(-)
> 
> diff --git a/security/integrity/ima/Kconfig b/security/integrity/ima/Kconfig
> index 35ef69312811..55f734a6124b 100644
> --- a/security/integrity/ima/Kconfig
> +++ b/security/integrity/ima/Kconfig
> @@ -163,6 +163,19 @@ config IMA_APPRAISE_BOOTPARAM
> This option enables the different "ima_appraise=" modes
> (eg. fix, log) from the boot command line.
> 
> +config IMA_APPRAISE_MODSIG
> + bool "Support module-style signatures for appraisal"
> + depends on IMA_APPRAISE
> + depends on INTEGRITY_ASYMMETRIC_KEYS
> + select PKCS7_MESSAGE_PARSER
> + select MODULE_SIG_FORMAT
> + default n
> + help
> +Adds support for signatures appended to files. The format of the
> +appended signature is the same used for signed kernel modules.
> +The modsig keyword can be used in the IMA policy to allow a hook
> +to accept such signatures.
> +
>  config IMA_TRUSTED_KEYRING
>   bool "Require all keys on the .ima keyring be signed (deprecated)"
>   depends on IMA_APPRAISE && SYSTEM_TRUSTED_KEYRING
> diff --git a/security/integrity/ima/Makefile b/security/integrity/ima/Makefile
> index 29f198bde02b..c72026acecc3 100644
> --- a/security/integrity/ima/Makefile
> +++ b/security/integrity/ima/Makefile
> @@ -8,5 +8,6 @@ obj-$(CONFIG_IMA) += ima.o
>  ima-y := ima_fs.o ima_queue.o ima_init.o ima_main.o ima_crypto.o ima_api.o \
>ima_policy.o ima_template.o ima_template_lib.o
>  ima-$(CONFIG_IMA_APPRAISE) += ima_appraise.o
> +ima-$(CONFIG_IMA_APPRAISE_MODSIG) += ima_modsig.o
>  ima-$(CONFIG_HAVE_IMA_KEXEC) += ima_kexec.o
>  obj-$(CONFIG_IMA_BLACKLIST_KEYRING) += ima_mok.o
> diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h
> index d52b487ad259..5492af2cd7c7 100644
> --- a/security/integrity/ima/ima.h
> +++ b/security/integrity/ima/ima.h
> @@ -190,6 +190,8 @@ enum ima_hooks {
>   __ima_hooks(__ima_hook_enumify)
>  };
> 
> +extern const char *const func_tokens[];
> +
>  /* LIM API function definitions */
>  int ima_get_action(struct inode *inode, int mask,
>  enum ima_hooks func, int *pcr);
> @@ -236,9 +238,10 @@ int ima_policy_show(struct seq_file *m, void *v);
>  #ifdef CONFIG_IMA_APPRAISE
>  int ima_appraise_measurement(enum ima_hooks func,
>struct integrity_iint_cache *iint,
> -  struct file *file, const unsigned char *filename,
> -  struct evm_ima_xattr_data *xattr_value,
> -  int xattr_len, int 

Re: [PATCH v3 7/7] ima: Support module-style appended signatures for appraisal

2017-08-03 Thread Mimi Zohar
On Wed, 2017-08-02 at 18:52 -0400, Mimi Zohar wrote:
> On Wed, 2017-08-02 at 14:42 -0300, Thiago Jung Bauermann wrote:
> > Mimi Zohar <zo...@linux.vnet.ibm.com> writes:

> > >> @@ -229,8 +251,24 @@ int ima_appraise_measurement(enum ima_hooks func,
> > >>  goto out;
> > >>  }
> > >> 
> > >> -status = evm_verifyxattr(dentry, XATTR_NAME_IMA, xattr_value, 
> > >> rc, iint);
> > >> -if ((status != INTEGRITY_PASS) && (status != 
> > >> INTEGRITY_UNKNOWN)) {
> > >> +/*
> > >> + * Appended signatures aren't protected by EVM but we still call
> > >> + * evm_verifyxattr to check other security xattrs, if they 
> > >> exist.
> > >> + */
> > >> +if (appraising_modsig) {
> > >> +xattr_value_evm = NULL;
> > >> +xattr_len_evm = 0;
> > >> +} else {
> > >> +xattr_value_evm = xattr_value;
> > >> +xattr_len_evm = xattr_len;
> > >> +}
> > >> +
> > >> +status = evm_verifyxattr(dentry, XATTR_NAME_IMA, 
> > >> xattr_value_evm,
> > >> + xattr_len_evm, iint);
> > >> +if (appraising_modsig && status == INTEGRITY_FAIL) {
> > >> +cause = "invalid-HMAC";
> > >> +goto out;
> > >
> > > "modsig" is special, because having any security xattrs is not
> > > required. This test doesn't prevent status from being set to
> > > "missing-HMAC". This test is redundant with the original tests below.
> > 
> > Indeed, that is wrong. I'm still a bit fuzzy about how EVM works and how
> > it interacts with IMA. The only way I can think of singling out modsig
> > without reintroduced the complex expression you didn't like in v2 is as
> > below. What do you think?
> 
> The original code, without any extra tests, should be fine.

There is one major difference.

EVM verifies a file's metadata has not been modified based on either
an HMAC or signature stored as security.evm.  Prior to the appended
signatures patch set, all files in policy required a security.evm
xattr. With IMA enabled we could guarantee that at least one security
xattr existed.  The only exception were new files, which hadn't yet
been labeled. 

With appended signatures, there is now no guarantee that at least one
security xattr exists.

Perhaps the code snippet below will help clarify the meaning of the
integrity_status results. 

        switch (status) {
case INTEGRITY_PASS:
case INTEGRITY_UNKNOWN:      
              break;
        case INTEGRITY_NOXATTRS:/* no EVM protected xattrs */
if (appraising_modsig)
break;
case INTEGRITY_NOLABEL: /* no security.evm xattr */
cause = "missing-HMAC";
fail = 1;
break;
case INTEGRITY_FAIL:/* invalid HMAC/signature */
default:
cause = "invalid-HMAC";
fail = 1;
break;
}

Mimi



Re: [PATCH v3 7/7] ima: Support module-style appended signatures for appraisal

2017-08-02 Thread Mimi Zohar
On Wed, 2017-08-02 at 14:42 -0300, Thiago Jung Bauermann wrote:
> Mimi Zohar <zo...@linux.vnet.ibm.com> writes:
> 
> > On Thu, 2017-07-06 at 19:17 -0300, Thiago Jung Bauermann wrote:
> >> --- a/security/integrity/ima/ima_appraise.c
> >> +++ b/security/integrity/ima/ima_appraise.c
> >> @@ -200,18 +200,40 @@ int ima_read_xattr(struct dentry *dentry,
> >>   */
> >>  int ima_appraise_measurement(enum ima_hooks func,
> >> struct integrity_iint_cache *iint,
> >> -   struct file *file, const unsigned char *filename,
> >> -   struct evm_ima_xattr_data *xattr_value,
> >> -   int xattr_len, int opened)
> >> +   struct file *file, const void *buf, loff_t size,
> >> +   const unsigned char *filename,
> >> +   struct evm_ima_xattr_data **xattr_value_,
> >> +   int *xattr_len_, int opened)
> >>  {
> >>static const char op[] = "appraise_data";
> >>char *cause = "unknown";
> >>struct dentry *dentry = file_dentry(file);
> >>struct inode *inode = d_backing_inode(dentry);
> >>enum integrity_status status = INTEGRITY_UNKNOWN;
> >> -  int rc = xattr_len, hash_start = 0;
> >> +  struct evm_ima_xattr_data *xattr_value = *xattr_value_;
> >> +  int xattr_len = *xattr_len_, rc = xattr_len, hash_start = 0;
> >> +  bool appraising_modsig = false;
> >> +  void *xattr_value_evm;
> >> +  size_t xattr_len_evm;
> >> +
> >> +  if (iint->flags & IMA_MODSIG_ALLOWED) {
> >> +  /*
> >> +   * Not supposed to happen. Hooks that support modsig are
> >> +   * whitelisted when parsing the policy using
> >> +   * ima_hooks_supports_modsig.
> >> +   */
> >> +  if (!buf || !size)
> >> +  WARN_ONCE(true, "%s doesn't support modsig\n",
> >> +func_tokens[func]);
> >
> > ima _appraise_measurement() is getting kind of long. Is there any
> > reason we can't move this comment and test to ima_read_modsig()?
> 
> I didn't do that because then I would need to pass func as an argument
> to ima_read_modsig just to print the warning above. But it does simplify
> the code so it may be worth it. I'll make that change in v4.

Makes sense.

> >> @@ -229,8 +251,24 @@ int ima_appraise_measurement(enum ima_hooks func,
> >>goto out;
> >>}
> >> 
> >> -  status = evm_verifyxattr(dentry, XATTR_NAME_IMA, xattr_value, rc, iint);
> >> -  if ((status != INTEGRITY_PASS) && (status != INTEGRITY_UNKNOWN)) {
> >> +  /*
> >> +   * Appended signatures aren't protected by EVM but we still call
> >> +   * evm_verifyxattr to check other security xattrs, if they exist.
> >> +   */
> >> +  if (appraising_modsig) {
> >> +  xattr_value_evm = NULL;
> >> +  xattr_len_evm = 0;
> >> +  } else {
> >> +  xattr_value_evm = xattr_value;
> >> +  xattr_len_evm = xattr_len;
> >> +  }
> >> +
> >> +  status = evm_verifyxattr(dentry, XATTR_NAME_IMA, xattr_value_evm,
> >> +   xattr_len_evm, iint);
> >> +  if (appraising_modsig && status == INTEGRITY_FAIL) {
> >> +  cause = "invalid-HMAC";
> >> +  goto out;
> >
> > "modsig" is special, because having any security xattrs is not
> > required. This test doesn't prevent status from being set to
> > "missing-HMAC". This test is redundant with the original tests below.
> 
> Indeed, that is wrong. I'm still a bit fuzzy about how EVM works and how
> it interacts with IMA. The only way I can think of singling out modsig
> without reintroduced the complex expression you didn't like in v2 is as
> below. What do you think?

The original code, without any extra tests, should be fine.

> 
> @@ -229,8 +241,25 @@ int ima_appraise_measurement(enum ima_hooks func,
>   goto out;
>   }
> 
> - status = evm_verifyxattr(dentry, XATTR_NAME_IMA, xattr_value, rc, iint);
> - if ((status != INTEGRITY_PASS) && (status != INTEGRITY_UNKNOWN)) {
> + /*
> +  * Appended signatures aren't protected by EVM but we still call
> +  * evm_verifyxattr to check other security xattrs, if they exist.
> +  */
> + if (appraising_modsig) {
> + xattr_value_evm =

Re: [PATCH v3 7/7] ima: Support module-style appended signatures for appraisal

2017-07-30 Thread Mimi Zohar
On Thu, 2017-07-06 at 19:17 -0300, Thiago Jung Bauermann wrote:
> This patch introduces the modsig keyword to the IMA policy syntax to
> specify that a given hook should expect the file to have the IMA signature
> appended to it. Here is how it can be used in a rule:
> 
> appraise func=KEXEC_KERNEL_CHECK appraise_type=modsig|imasig
> 
> With this rule, IMA will accept either an appended signature or a signature
> stored in the extended attribute. In that case, it will first check whether
> there is an appended signature, and if not it will read it from the
> extended attribute.
> 
> The format of the appended signature is the same used for signed kernel
> modules. This means that the file can be signed with the scripts/sign-file
> tool, with a command line such as this:
> 
> $ sign-file sha256 privkey_ima.pem x509_ima.der vmlinux
> 
> This code only works for files that are hashed from a memory buffer, not
> for files that are read from disk at the time of hash calculation. In other
> words, only hooks that use kernel_read_file can support appended
> signatures. This means that only FIRMWARE_CHECK, KEXEC_KERNEL_CHECK,
> KEXEC_INITRAMFS_CHECK and POLICY_CHECK can be supported.
> 
> This feature warrants a separate config option because enabling it brings
> in many other config options.
> 
> Signed-off-by: Thiago Jung Bauermann 
> ---
>  security/integrity/ima/Kconfig|  13 +++
>  security/integrity/ima/Makefile   |   1 +
>  security/integrity/ima/ima.h  |  60 ++--
>  security/integrity/ima/ima_appraise.c | 102 ++---
>  security/integrity/ima/ima_main.c |   7 +-
>  security/integrity/ima/ima_modsig.c   | 147 
> ++
>  security/integrity/ima/ima_policy.c   |  26 --
>  security/integrity/ima/ima_template_lib.c |  14 ++-
>  security/integrity/integrity.h|   4 +-
>  9 files changed, 343 insertions(+), 31 deletions(-)
> 
> diff --git a/security/integrity/ima/Kconfig b/security/integrity/ima/Kconfig
> index 35ef69312811..55f734a6124b 100644
> --- a/security/integrity/ima/Kconfig
> +++ b/security/integrity/ima/Kconfig
> @@ -163,6 +163,19 @@ config IMA_APPRAISE_BOOTPARAM
> This option enables the different "ima_appraise=" modes
> (eg. fix, log) from the boot command line.
> 
> +config IMA_APPRAISE_MODSIG
> + bool "Support module-style signatures for appraisal"
> + depends on IMA_APPRAISE
> + depends on INTEGRITY_ASYMMETRIC_KEYS
> + select PKCS7_MESSAGE_PARSER
> + select MODULE_SIG_FORMAT
> + default n
> + help
> +Adds support for signatures appended to files. The format of the
> +appended signature is the same used for signed kernel modules.
> +The modsig keyword can be used in the IMA policy to allow a hook
> +to accept such signatures.
> +
>  config IMA_TRUSTED_KEYRING
>   bool "Require all keys on the .ima keyring be signed (deprecated)"
>   depends on IMA_APPRAISE && SYSTEM_TRUSTED_KEYRING
> diff --git a/security/integrity/ima/Makefile b/security/integrity/ima/Makefile
> index 29f198bde02b..c72026acecc3 100644
> --- a/security/integrity/ima/Makefile
> +++ b/security/integrity/ima/Makefile
> @@ -8,5 +8,6 @@ obj-$(CONFIG_IMA) += ima.o
>  ima-y := ima_fs.o ima_queue.o ima_init.o ima_main.o ima_crypto.o ima_api.o \
>ima_policy.o ima_template.o ima_template_lib.o
>  ima-$(CONFIG_IMA_APPRAISE) += ima_appraise.o
> +ima-$(CONFIG_IMA_APPRAISE_MODSIG) += ima_modsig.o
>  ima-$(CONFIG_HAVE_IMA_KEXEC) += ima_kexec.o
>  obj-$(CONFIG_IMA_BLACKLIST_KEYRING) += ima_mok.o
> diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h
> index d52b487ad259..1e1e7c41ca19 100644
> --- a/security/integrity/ima/ima.h
> +++ b/security/integrity/ima/ima.h
> @@ -190,6 +190,8 @@ enum ima_hooks {
>   __ima_hooks(__ima_hook_enumify)
>  };
> 
> +extern const char *const func_tokens[];
> +
>  /* LIM API function definitions */
>  int ima_get_action(struct inode *inode, int mask,
>  enum ima_hooks func, int *pcr);
> @@ -236,9 +238,10 @@ int ima_policy_show(struct seq_file *m, void *v);
>  #ifdef CONFIG_IMA_APPRAISE
>  int ima_appraise_measurement(enum ima_hooks func,
>struct integrity_iint_cache *iint,
> -  struct file *file, const unsigned char *filename,
> -  struct evm_ima_xattr_data *xattr_value,
> -  int xattr_len, int opened);
> +  struct file *file, const void *buf, loff_t size,
> +  const unsigned char *filename,
> +  struct evm_ima_xattr_data **xattr_value,
> +  int *xattr_len, int opened);
>  int ima_must_appraise(struct inode *inode, int mask, enum ima_hooks func);
>  void ima_update_xattr(struct integrity_iint_cache *iint, struct file *file);
>  enum integrity_status 

Re: [PATCH v3 1/7] integrity: Introduce struct evm_hmac_xattr

2017-07-28 Thread Mimi Zohar
Hi Thiago,

On Thu, 2017-07-06 at 19:17 -0300, Thiago Jung Bauermann wrote:
> Even though struct evm_ima_xattr_data includes a fixed-size array to hold a
> SHA1 digest, most of the code ignores the array and uses the struct to mean
> "type indicator followed by data of unspecified size" and tracks the real
> size of what the struct represents in a separate length variable.
> 
> The only exception to that is the EVM code, which correctly uses the
> definition of struct evm_ima_xattr_data.

Right, the current EVM code converts the EVM signature to an HMAC the
first time the file is accessed.  So most of the code is based on the
HMAC.

> 
> This patch makes this explicit in the code by removing the length
> specification from the array in struct evm_ima_xattr_data. It also changes
> the name of the element from digest to data, since in most places the array
> doesn't hold a digest.
> 
> A separate struct evm_hmac_xattr is introduced, with the original
> definition of evm_ima_xattr_data to be used in the places that actually
> expect that definition.

The new structure name implies that the xattr can only be an HMAC.  By
moving the new structure to evm.h we also loose the connection that it
has to the evm_ima_xattr_type enumeration.

Instead, how about defining the new struct in terms of the modified
evm_ima_xattr_data struct?  Please leave the new structure in
integrity.h.

Mimi

> 
> Signed-off-by: Thiago Jung Bauermann 

> ---
>  security/integrity/evm/evm.h  | 5 +
>  security/integrity/evm/evm_crypto.c   | 2 +-
>  security/integrity/evm/evm_main.c | 8 
>  security/integrity/ima/ima_appraise.c | 7 ---
>  security/integrity/integrity.h| 2 +-
>  5 files changed, 15 insertions(+), 9 deletions(-)
> 
> diff --git a/security/integrity/evm/evm.h b/security/integrity/evm/evm.h
> index f5f12727771a..e1081cf2f9c5 100644
> --- a/security/integrity/evm/evm.h
> +++ b/security/integrity/evm/evm.h
> @@ -24,6 +24,11 @@
>  #define EVM_INIT_HMAC0x0001
>  #define EVM_INIT_X5090x0002
> 
> +struct evm_hmac_xattr {
> + u8 type;/* Should be EVM_XATTR_HMAC. */
> + u8 digest[SHA1_DIGEST_SIZE];
> +} __packed;
> +
>  extern int evm_initialized;
>  extern char *evm_hmac;
>  extern char *evm_hash;
> diff --git a/security/integrity/evm/evm_crypto.c 
> b/security/integrity/evm/evm_crypto.c
> index d7f282d75cc1..08dde59f3128 100644
> --- a/security/integrity/evm/evm_crypto.c
> +++ b/security/integrity/evm/evm_crypto.c
> @@ -252,7 +252,7 @@ int evm_update_evmxattr(struct dentry *dentry, const char 
> *xattr_name,
>   const char *xattr_value, size_t xattr_value_len)
>  {
>   struct inode *inode = d_backing_inode(dentry);
> - struct evm_ima_xattr_data xattr_data;
> + struct evm_hmac_xattr xattr_data;
>   int rc = 0;
> 
>   rc = evm_calc_hmac(dentry, xattr_name, xattr_value,
> diff --git a/security/integrity/evm/evm_main.c 
> b/security/integrity/evm/evm_main.c
> index 063d38aef64e..b7c1e11a915e 100644
> --- a/security/integrity/evm/evm_main.c
> +++ b/security/integrity/evm/evm_main.c
> @@ -116,7 +116,7 @@ static enum integrity_status evm_verify_hmac(struct 
> dentry *dentry,
>struct integrity_iint_cache *iint)
>  {
>   struct evm_ima_xattr_data *xattr_data = NULL;
> - struct evm_ima_xattr_data calc;
> + struct evm_hmac_xattr calc;
>   enum integrity_status evm_status = INTEGRITY_PASS;
>   int rc, xattr_len;
> 
> @@ -147,7 +147,7 @@ static enum integrity_status evm_verify_hmac(struct 
> dentry *dentry,
>   /* check value type */
>   switch (xattr_data->type) {
>   case EVM_XATTR_HMAC:
> - if (xattr_len != sizeof(struct evm_ima_xattr_data)) {
> + if (xattr_len != sizeof(struct evm_hmac_xattr)) {
>   evm_status = INTEGRITY_FAIL;
>   goto out;
>   }
> @@ -155,7 +155,7 @@ static enum integrity_status evm_verify_hmac(struct 
> dentry *dentry,
>  xattr_value_len, calc.digest);
>   if (rc)
>   break;
> - rc = crypto_memneq(xattr_data->digest, calc.digest,
> + rc = crypto_memneq(xattr_data->data, calc.digest,
>   sizeof(calc.digest));
>   if (rc)
>   rc = -EINVAL;
> @@ -467,7 +467,7 @@ int evm_inode_init_security(struct inode *inode,
>const struct xattr *lsm_xattr,
>struct xattr *evm_xattr)
>  {
> - struct evm_ima_xattr_data *xattr_data;
> + struct evm_hmac_xattr *xattr_data;
>   int rc;
> 
>   if (!evm_initialized || !evm_protected_xattr(lsm_xattr->name))
> diff --git a/security/integrity/ima/ima_appraise.c 
> b/security/integrity/ima/ima_appraise.c
> index 809ba70fbbbf..87d2b601cf8e 100644
> --- a/security/integrity/ima/ima_appraise.c
> +++ 

Re: [PATCH v2 6/6] ima: Support module-style appended signatures for appraisal

2017-07-05 Thread Mimi Zohar
On Tue, 2017-07-04 at 23:22 -0300, Thiago Jung Bauermann wrote:
> Mimi Zohar <zo...@linux.vnet.ibm.com> writes:
> 
> > On Wed, 2017-06-21 at 14:45 -0300, Thiago Jung Bauermann wrote:
> >> Mimi Zohar <zo...@linux.vnet.ibm.com> writes:
> >> > On Wed, 2017-06-07 at 22:49 -0300, Thiago Jung Bauermann wrote:
> >> >> @@ -267,11 +276,18 @@ int ima_appraise_measurement(enum ima_hooks func,
> >> >> status = INTEGRITY_PASS;
> >> >> break;
> >> >> case EVM_IMA_XATTR_DIGSIG:
> >> >> +   case IMA_MODSIG:
> >> >> iint->flags |= IMA_DIGSIG;
> >> >> -   rc = integrity_digsig_verify(INTEGRITY_KEYRING_IMA,
> >> >> -(const char *)xattr_value, 
> >> >> rc,
> >> >> -iint->ima_hash->digest,
> >> >> -iint->ima_hash->length);
> >> >> +
> >> >> +   if (xattr_value->type == EVM_IMA_XATTR_DIGSIG)
> >> >> +   rc = 
> >> >> integrity_digsig_verify(INTEGRITY_KEYRING_IMA,
> >> >> +(const char 
> >> >> *)xattr_value,
> >> >> +rc, 
> >> >> iint->ima_hash->digest,
> >> >> +
> >> >> iint->ima_hash->length);
> >> >> +   else
> >> >> +   rc = ima_modsig_verify(INTEGRITY_KEYRING_IMA,
> >> >> +  xattr_value);
> >> >> +
> >> >
> >> > Perhaps allowing IMA_MODSIG to flow into EVM_IMA_XATTR_DIGSIG on
> >> > failure, would help restore process_measurements() to the way it was.
> >> > Further explanation below.
> >> 
> >> It's not possible to simply flow into EVM_IMA_XATTR_DIGSIG on failure
> >> because after calling ima_read_xattr we need to run again all the logic
> >> before the switch statement. Instead, I'm currently testing the
> >> following change for v3, what do you think?
> >
> > I don't think we can assume that the same algorithm will be used for
> > signing the kernel image. Different entities would be signing the
> > kernel image with different requirements.
> >
> > Suppose for example a stock distro image comes signed using one
> > algorithm (appended signature), but the same kernel image is locally
> > signed using a different algorithm (xattr). Signature verification is
> > dependent on either the distro or local public key being loaded onto
> > the IMA keyring.
> 
> This example is good, but it raises one question: should the xattr
> signature cover the entire contents of the stock distro image (i.e.,
> also cover the appended signature), or should it ignore the appended
> signature and thus cover the same contents that the appended signature
> covers?
> 
> If the former, then we can't reuse the iint->ima_hash that was collected
> when trying to verify the appended signature because it doesn't cover
> the appended signature itself and won't match the hash expected by the
> xattr signature.
> 
> If the latter, then evmctl ima_sign needs to be modified to check
> whether there's an appended signature in the given file and ignore it
> when calculating the xattr signature.
> 
> Which is better?

I realize that having the same file hash for both the appended
signature and extended attribute would make things a lot easier, but
security.ima is a signature of the file as written to disk, meaning it
would include any appended signature

> 
> >> >> @@ -226,30 +282,23 @@ static int process_measurement(struct file *file, 
> >> >> char *buf, loff_t size,
> >> >> goto out_digsig;
> >> >> }
> >> >> 
> >> >> -   template_desc = ima_template_desc_current();
> >> >> -   if ((action & IMA_APPRAISE_SUBMASK) ||
> >> >> -   strcmp(template_desc->name, IMA_TEMPLATE_IMA_NAME) 
> >> >> != 0)
> >> >> -   /* read 'security.ima' */
> >> >> -   xattr_len = ima_read_xattr(file_dentry(file), 
> >> >> _value);
> >> >> -
> >> >> -   hash_algo = ima_get_hash_algo(xattr_

Re: [PATCH v2 6/6] ima: Support module-style appended signatures for appraisal

2017-06-21 Thread Mimi Zohar
On Wed, 2017-06-21 at 14:45 -0300, Thiago Jung Bauermann wrote:
> Hello Mimi,
> 
> Thanks for your review, and for queuing the other patches in this series.
> 
> Mimi Zohar <zo...@linux.vnet.ibm.com> writes:
> > On Wed, 2017-06-07 at 22:49 -0300, Thiago Jung Bauermann wrote:
> >> This patch introduces the modsig keyword to the IMA policy syntax to
> >> specify that a given hook should expect the file to have the IMA signature
> >> appended to it.
> >
> > Thank you, Thiago. Appended signatures seem to be working proper now
> > with multiple keys on the IMA keyring.
> 
> Great news!
> 
> > The length of this patch description is a good indication that this
> > patch needs to be broken up for easier review. A few
> > comments/suggestions inline below.
> 
> Ok, I will try to break it up, and also patch 5 as you suggested.
> 
> >> diff --git a/security/integrity/digsig.c b/security/integrity/digsig.c
> >> index 06554c448dce..9190c9058f4f 100644
> >> --- a/security/integrity/digsig.c
> >> +++ b/security/integrity/digsig.c
> >> @@ -48,11 +48,10 @@ static bool init_keyring __initdata;
> >>  #define restrict_link_to_ima restrict_link_by_builtin_trusted
> >>  #endif
> >> 
> >> -int integrity_digsig_verify(const unsigned int id, const char *sig, int 
> >> siglen,
> >> -  const char *digest, int digestlen)
> >> +struct key *integrity_keyring_from_id(const unsigned int id)
> >>  {
> >> -  if (id >= INTEGRITY_KEYRING_MAX || siglen < 2)
> >> -  return -EINVAL;
> >> +  if (id >= INTEGRITY_KEYRING_MAX)
> >> +  return ERR_PTR(-EINVAL);
> >> 
> >
> > When splitting up this patch, the addition of this new function could
> > be a separate patch. The patch description would explain the need for
> > a new function.
> 
> Ok, will do for v3.
> 
> >> @@ -229,10 +234,14 @@ int ima_appraise_measurement(enum ima_hooks func,
> >>goto out;
> >>}
> >> 
> >> -  status = evm_verifyxattr(dentry, XATTR_NAME_IMA, xattr_value, rc, iint);
> >> -  if ((status != INTEGRITY_PASS) && (status != INTEGRITY_UNKNOWN)) {
> >> -  if ((status == INTEGRITY_NOLABEL)
> >> -  || (status == INTEGRITY_NOXATTRS))
> >> +  /* Appended signatures aren't protected by EVM. */
> >> +  status = evm_verifyxattr(dentry, XATTR_NAME_IMA,
> >> +   xattr_value->type == IMA_MODSIG ?
> >> +   NULL : xattr_value, rc, iint);
> >> +  if (status != INTEGRITY_PASS && status != INTEGRITY_UNKNOWN &&
> >> +  !(xattr_value->type == IMA_MODSIG &&
> >> +(status == INTEGRITY_NOLABEL || status == INTEGRITY_NOXATTRS))) {
> >
> > This was messy to begin with, and now it is even more messy. For
> > appended signatures, we're only interested in INTEGRITY_FAIL. Maybe
> > leave the existing "if" clause alone and define a new "if" clause.
> 
> Ok, is this what you had in mind?
> 
> @@ -229,8 +237,14 @@ int ima_appraise_measurement(enum ima_hooks func,
>   goto out;
>   }
> 
> - status = evm_verifyxattr(dentry, XATTR_NAME_IMA, xattr_value, rc, iint);
> - if ((status != INTEGRITY_PASS) && (status != INTEGRITY_UNKNOWN)) {
> + /* Appended signatures aren't protected by EVM. */
> + status = evm_verifyxattr(dentry, XATTR_NAME_IMA,
> +  xattr_value->type == IMA_MODSIG ?
> +  NULL : xattr_value, rc, iint);

Yes, maybe add a comment here indicating only verifying other security
xattrs, if they exist.

> + if (xattr_value->type == IMA_MODSIG && status == INTEGRITY_FAIL) {
> + cause = "invalid-HMAC";
> + goto out;
> + } else if (status != INTEGRITY_PASS && status != INTEGRITY_UNKNOWN) {
>   if ((status == INTEGRITY_NOLABEL)
>   || (status == INTEGRITY_NOXATTRS))
>   cause = "missing-HMAC";

> 
> >> @@ -267,11 +276,18 @@ int ima_appraise_measurement(enum ima_hooks func,
> >>status = INTEGRITY_PASS;
> >>break;
> >>case EVM_IMA_XATTR_DIGSIG:
> >> +  case IMA_MODSIG:
> >>iint->flags |= IMA_DIGSIG;
> >> -  rc = integrity_digsig_verify(INTEGRITY_KEYRING_IMA,
> >> -   (const char *)xattr_value, rc,
> >> -

Re: [PATCH v2 1/6] integrity: Small code improvements

2017-06-15 Thread Mimi Zohar
On Wed, 2017-06-07 at 22:49 -0300, Thiago Jung Bauermann wrote:
> These changes are too small to warrant their own patches:
> 
> The keyid and sig_size members of struct signature_v2_hdr are in BE format,
> so use a type that makes this assumption explicit. Also, use beXX_to_cpu
> instead of __beXX_to_cpu to read them.
> 
> Change integrity_kernel_read to take a void * buffer instead of char *
> buffer, so that callers don't have to use a cast if they provide a buffer
> that isn't a char *.
> 
> Add missing #endif comment in ima.h pointing out which macro it refers to.
> 
> Add missing fall through comment in ima_appraise.c.
> 
> Constify mask_tokens and func_tokens arrays.
> 
> Signed-off-by: Thiago Jung Bauermann 

Thank you.  Queued to be upstreamed.

Mimi


> ---
>  security/integrity/digsig_asymmetric.c | 4 ++--
>  security/integrity/iint.c  | 2 +-
>  security/integrity/ima/ima.h   | 2 +-
>  security/integrity/ima/ima_appraise.c  | 1 +
>  security/integrity/ima/ima_policy.c| 4 ++--
>  security/integrity/integrity.h | 7 ---
>  6 files changed, 11 insertions(+), 9 deletions(-)
> 
> diff --git a/security/integrity/digsig_asymmetric.c 
> b/security/integrity/digsig_asymmetric.c
> index 80052ed8d467..ab6a029062a1 100644
> --- a/security/integrity/digsig_asymmetric.c
> +++ b/security/integrity/digsig_asymmetric.c
> @@ -92,13 +92,13 @@ int asymmetric_verify(struct key *keyring, const char 
> *sig,
> 
>   siglen -= sizeof(*hdr);
> 
> - if (siglen != __be16_to_cpu(hdr->sig_size))
> + if (siglen != be16_to_cpu(hdr->sig_size))
>   return -EBADMSG;
> 
>   if (hdr->hash_algo >= HASH_ALGO__LAST)
>   return -ENOPKG;
> 
> - key = request_asymmetric_key(keyring, __be32_to_cpu(hdr->keyid));
> + key = request_asymmetric_key(keyring, be32_to_cpu(hdr->keyid));
>   if (IS_ERR(key))
>   return PTR_ERR(key);
> 
> diff --git a/security/integrity/iint.c b/security/integrity/iint.c
> index c710d22042f9..6fc888ca468e 100644
> --- a/security/integrity/iint.c
> +++ b/security/integrity/iint.c
> @@ -182,7 +182,7 @@ security_initcall(integrity_iintcache_init);
>   *
>   */
>  int integrity_kernel_read(struct file *file, loff_t offset,
> -   char *addr, unsigned long count)
> +   void *addr, unsigned long count)
>  {
>   mm_segment_t old_fs;
>   char __user *buf = (char __user *)addr;
> diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h
> index d26a30e37d13..215a93c41b51 100644
> --- a/security/integrity/ima/ima.h
> +++ b/security/integrity/ima/ima.h
> @@ -284,7 +284,7 @@ static inline int ima_read_xattr(struct dentry *dentry,
>   return 0;
>  }
> 
> -#endif
> +#endif /* CONFIG_IMA_APPRAISE */
> 
>  /* LSM based policy rules require audit */
>  #ifdef CONFIG_IMA_LSM_RULES
> diff --git a/security/integrity/ima/ima_appraise.c 
> b/security/integrity/ima/ima_appraise.c
> index 7fe0566142d8..ea36a4f134f4 100644
> --- a/security/integrity/ima/ima_appraise.c
> +++ b/security/integrity/ima/ima_appraise.c
> @@ -240,6 +240,7 @@ int ima_appraise_measurement(enum ima_hooks func,
>   case IMA_XATTR_DIGEST_NG:
>   /* first byte contains algorithm id */
>   hash_start = 1;
> + /* fall through */
>   case IMA_XATTR_DIGEST:
>   if (iint->flags & IMA_DIGSIG_REQUIRED) {
>   cause = "IMA-signature-required";
> diff --git a/security/integrity/ima/ima_policy.c 
> b/security/integrity/ima/ima_policy.c
> index 0acd68decb17..949ad3858327 100644
> --- a/security/integrity/ima/ima_policy.c
> +++ b/security/integrity/ima/ima_policy.c
> @@ -965,7 +965,7 @@ enum {
>   mask_exec = 0, mask_write, mask_read, mask_append
>  };
> 
> -static char *mask_tokens[] = {
> +static const char *const mask_tokens[] = {
>   "MAY_EXEC",
>   "MAY_WRITE",
>   "MAY_READ",
> @@ -979,7 +979,7 @@ enum {
>   func_policy
>  };
> 
> -static char *func_tokens[] = {
> +static const char *const func_tokens[] = {
>   "FILE_CHECK",
>   "MMAP_CHECK",
>   "BPRM_CHECK",
> diff --git a/security/integrity/integrity.h b/security/integrity/integrity.h
> index 24520b4ef3b0..a53e7e4ab06c 100644
> --- a/security/integrity/integrity.h
> +++ b/security/integrity/integrity.h
> @@ -92,8 +92,8 @@ struct signature_v2_hdr {
>   uint8_t type;   /* xattr type */
>   uint8_t version;/* signature format version */
>   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 */
> + __be32 keyid;   /* IMA key identifier - not X509/PGP specific */
> + __be16 sig_size;/* signature size */
>   uint8_t sig[0]; /* signature payload */
>  } __packed;
> 
> @@ -118,7 +118,8 @@ struct integrity_iint_cache {
>  struct 

Re: [PATCH v2 3/6] ima: Log the same audit cause whenever a file has no signature

2017-06-15 Thread Mimi Zohar
On Wed, 2017-06-07 at 22:49 -0300, Thiago Jung Bauermann wrote:
> If the file doesn't have an xattr, ima_appraise_measurement sets cause to
> "missing-hash" while if there's an xattr but it's a digest instead of a
> signature it sets cause to "IMA-signature-required".
> 
> Fix it by setting cause to "IMA-signature-required" in both cases.
> 
> Signed-off-by: Thiago Jung Bauermann 

Thank you.  Queued to be upstreamed.

Mimi
> ---
>  security/integrity/ima/ima_appraise.c | 3 ++-
>  1 file changed, 2 insertions(+), 1 deletion(-)
> 
> diff --git a/security/integrity/ima/ima_appraise.c 
> b/security/integrity/ima/ima_appraise.c
> index ea36a4f134f4..809ba70fbbbf 100644
> --- a/security/integrity/ima/ima_appraise.c
> +++ b/security/integrity/ima/ima_appraise.c
> @@ -217,7 +217,8 @@ int ima_appraise_measurement(enum ima_hooks func,
>   if (rc && rc != -ENODATA)
>   goto out;
> 
> - cause = "missing-hash";
> + cause = iint->flags & IMA_DIGSIG_REQUIRED ?
> + "IMA-signature-required" : "missing-hash";
>   status = INTEGRITY_NOLABEL;
>   if (opened & FILE_CREATED)
>   iint->flags |= IMA_NEW_FILE;



Re: [PATCH v2 2/6] ima: Simplify policy_func_show.

2017-06-15 Thread Mimi Zohar
On Wed, 2017-06-07 at 22:49 -0300, Thiago Jung Bauermann wrote:
> If the func_tokens array uses the same indices as enum ima_hooks,
> policy_func_show can be a lot simpler, and the func_* enum becomes
> unnecessary.
> 
> Also, if we use the same macro trick used by kernel_read_file_id_str we can
> use one hooks list for both the enum and the string array, making sure they
> are always in sync (suggested by Mimi Zohar).
> 
> Finally, by using the printf pattern for the function token directly
> instead of using the pt macro we can simplify policy_func_show even further
> and avoid needing a temporary buffer.
> 
> Signed-off-by: Thiago Jung Bauermann <bauer...@linux.vnet.ibm.com>

Thank you.  Queued to be upstreamed.

Mimi
> ---
>  security/integrity/ima/ima.h| 25 +---
>  security/integrity/ima/ima_policy.c | 58 
> -
>  2 files changed, 21 insertions(+), 62 deletions(-)
> 
> diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h
> index 215a93c41b51..d52b487ad259 100644
> --- a/security/integrity/ima/ima.h
> +++ b/security/integrity/ima/ima.h
> @@ -172,17 +172,22 @@ static inline unsigned long ima_hash_key(u8 *digest)
>   return hash_long(*digest, IMA_HASH_BITS);
>  }
> 
> +#define __ima_hooks(hook)\
> + hook(NONE)  \
> + hook(FILE_CHECK)\
> + hook(MMAP_CHECK)\
> + hook(BPRM_CHECK)\
> + hook(POST_SETATTR)  \
> + hook(MODULE_CHECK)  \
> + hook(FIRMWARE_CHECK)\
> + hook(KEXEC_KERNEL_CHECK)\
> + hook(KEXEC_INITRAMFS_CHECK) \
> + hook(POLICY_CHECK)  \
> + hook(MAX_CHECK)
> +#define __ima_hook_enumify(ENUM) ENUM,
> +
>  enum ima_hooks {
> - FILE_CHECK = 1,
> - MMAP_CHECK,
> - BPRM_CHECK,
> - POST_SETATTR,
> - MODULE_CHECK,
> - FIRMWARE_CHECK,
> - KEXEC_KERNEL_CHECK,
> - KEXEC_INITRAMFS_CHECK,
> - POLICY_CHECK,
> - MAX_CHECK
> + __ima_hooks(__ima_hook_enumify)
>  };
> 
>  /* LIM API function definitions */
> diff --git a/security/integrity/ima/ima_policy.c 
> b/security/integrity/ima/ima_policy.c
> index 949ad3858327..f4436626ccb7 100644
> --- a/security/integrity/ima/ima_policy.c
> +++ b/security/integrity/ima/ima_policy.c
> @@ -972,23 +972,10 @@ static const char *const mask_tokens[] = {
>   "MAY_APPEND"
>  };
> 
> -enum {
> - func_file = 0, func_mmap, func_bprm,
> - func_module, func_firmware, func_post,
> - func_kexec_kernel, func_kexec_initramfs,
> - func_policy
> -};
> +#define __ima_hook_stringify(str)(#str),
> 
>  static const char *const func_tokens[] = {
> - "FILE_CHECK",
> - "MMAP_CHECK",
> - "BPRM_CHECK",
> - "MODULE_CHECK",
> - "FIRMWARE_CHECK",
> - "POST_SETATTR",
> - "KEXEC_KERNEL_CHECK",
> - "KEXEC_INITRAMFS_CHECK",
> - "POLICY_CHECK"
> + __ima_hooks(__ima_hook_stringify)
>  };
> 
>  void *ima_policy_start(struct seq_file *m, loff_t *pos)
> @@ -1025,49 +1012,16 @@ void ima_policy_stop(struct seq_file *m, void *v)
> 
>  #define pt(token)policy_tokens[token + Opt_err].pattern
>  #define mt(token)mask_tokens[token]
> -#define ft(token)func_tokens[token]
> 
>  /*
>   * policy_func_show - display the ima_hooks policy rule
>   */
>  static void policy_func_show(struct seq_file *m, enum ima_hooks func)
>  {
> - char tbuf[64] = {0,};
> -
> - switch (func) {
> - case FILE_CHECK:
> - seq_printf(m, pt(Opt_func), ft(func_file));
> - break;
> - case MMAP_CHECK:
> - seq_printf(m, pt(Opt_func), ft(func_mmap));
> - break;
> - case BPRM_CHECK:
> - seq_printf(m, pt(Opt_func), ft(func_bprm));
> - break;
> - case MODULE_CHECK:
> - seq_printf(m, pt(Opt_func), ft(func_module));
> - break;
> - case FIRMWARE_CHECK:
> - seq_printf(m, pt(Opt_func), ft(func_firmware));
> - break;
> - case POST_SETATTR:
> - seq_printf(m, pt(Opt_func), ft(func_post));
> - break;
> - case KEXEC_KERNEL_CHECK:
> - seq_printf(m, pt(Opt_func), ft(func_kexec_kernel));
> - break;
> - case KEXEC_INITRAMFS_CHECK:
> - seq_printf(m, pt(Opt_func), ft(func_kexec_initramfs));
> - break;
> - case POLICY_CHECK:
> - seq_printf(m, pt(Opt_func), ft(func_policy));
> - break;
> - default:
> - snprintf(tbuf, sizeof(tbuf), "%d", func);
> - seq_printf(m, pt(Opt_func), tbuf);
> - break;
> - }
> - seq_puts(m, " ");
> + if (func > 0 && func < MAX_CHECK)
> + seq_printf(m, "func=%s ", func_tokens[func]);
> + else
> + seq_printf(m, "func=%d ", func);
>  }
> 
>  int ima_policy_show(struct seq_file *m, void *v)



Re: [PATCH v2 6/6] ima: Support module-style appended signatures for appraisal

2017-06-14 Thread Mimi Zohar
Hi Thiago,

On Wed, 2017-06-07 at 22:49 -0300, Thiago Jung Bauermann wrote:
> This patch introduces the modsig keyword to the IMA policy syntax to
> specify that a given hook should expect the file to have the IMA signature
> appended to it. Here is how it can be used in a rule:
> 
> appraise func=KEXEC_KERNEL_CHECK appraise_type=modsig|imasig
> 
> With this rule, IMA will accept either an appended signature or a signature
> stored in the extended attribute. In that case, it will first check whether
> there is an appended signature, and if not it will read it from the
> extended attribute.
> 
> The format of the appended signature is the same used for signed kernel
> modules. This means that the file can be signed with the scripts/sign-file
> tool, with a command line such as this:
> 
> $ sign-file sha256 privkey_ima.pem x509_ima.der vmlinux
> 
> This code only works for files that are hashed from a memory buffer, not
> for files that are read from disk at the time of hash calculation. In other
> words, only hooks that use kernel_read_file can support appended
> signatures. This means that only FIRMWARE_CHECK, KEXEC_KERNEL_CHECK,
> KEXEC_INITRAMFS_CHECK and POLICY_CHECK can be supported.
> 
> This feature warrants a separate config option because it depends on many
> other config options:
> 
>  ASYMMETRIC_KEY_TYPE n -> y
>  CRYPTO_RSA n -> y
>  INTEGRITY_SIGNATURE n -> y
>  MODULE_SIG_FORMAT n -> y
>  SYSTEM_DATA_VERIFICATION n -> y
> +ASN1 y
> +ASYMMETRIC_PUBLIC_KEY_SUBTYPE y
> +CLZ_TAB y
> +CRYPTO_AKCIPHER y
> +IMA_APPRAISE_MODSIG y
> +IMA_TRUSTED_KEYRING n
> +INTEGRITY_ASYMMETRIC_KEYS y
> +INTEGRITY_TRUSTED_KEYRING n
> +MPILIB y
> +OID_REGISTRY y
> +PKCS7_MESSAGE_PARSER y
> +PKCS7_TEST_KEY n
> +SECONDARY_TRUSTED_KEYRING n
> +SIGNATURE y
> +SIGNED_PE_FILE_VERIFICATION n
> +SYSTEM_EXTRA_CERTIFICATE n
> +SYSTEM_TRUSTED_KEYRING y
> +SYSTEM_TRUSTED_KEYS ""
> +X509_CERTIFICATE_PARSER y
> 
> The change in CONFIG_INTEGRITY_SIGNATURE to select CONFIG_KEYS instead of
> depending on it is to avoid a dependency recursion in
> CONFIG_IMA_APPRAISE_MODSIG, because CONFIG_MODULE_SIG_FORMAT selects
> CONFIG_KEYS and Kconfig complains that CONFIG_INTEGRITY_SIGNATURE depends
> on it.
> 
> Signed-off-by: Thiago Jung Bauermann 

Thank you, Thiago.  Appended signatures seem to be working proper now
with multiple keys on the IMA keyring.

The length of this patch description is a good indication that this
patch needs to be broken up for easier review.  A few
comments/suggestions inline below.

> ---
>  crypto/asymmetric_keys/pkcs7_parser.c |  12 +++
>  include/crypto/pkcs7.h|   3 +
>  security/integrity/Kconfig|   2 +-
>  security/integrity/digsig.c   |  28 +++--
>  security/integrity/ima/Kconfig|  13 +++
>  security/integrity/ima/Makefile   |   1 +
>  security/integrity/ima/ima.h  |  53 ++
>  security/integrity/ima/ima_api.c  |   2 +-
>  security/integrity/ima/ima_appraise.c |  41 ++--
>  security/integrity/ima/ima_main.c |  91 
>  security/integrity/ima/ima_modsig.c   | 167 
> ++
>  security/integrity/ima/ima_policy.c   |  26 +++--
>  security/integrity/ima/ima_template_lib.c |  14 ++-
>  security/integrity/integrity.h|   5 +-
>  14 files changed, 404 insertions(+), 54 deletions(-)
> 
> diff --git a/crypto/asymmetric_keys/pkcs7_parser.c 
> b/crypto/asymmetric_keys/pkcs7_parser.c
> index af4cd8649117..e41beda297a8 100644
> --- a/crypto/asymmetric_keys/pkcs7_parser.c
> +++ b/crypto/asymmetric_keys/pkcs7_parser.c
> @@ -673,3 +673,15 @@ int pkcs7_note_signed_info(void *context, size_t hdrlen,
>   return -ENOMEM;
>   return 0;
>  }
> +
> +/**
> + * pkcs7_get_message_sig - get signature in @pkcs7
> + *
> + * This function doesn't meaningfully support messages with more than one
> + * signature. It will always return the first signature.
> + */
> +const struct public_key_signature *pkcs7_get_message_sig(
> + const struct pkcs7_message *pkcs7)
> +{
> + return pkcs7->signed_infos ? pkcs7->signed_infos->sig : NULL;
> +}
> diff --git a/include/crypto/pkcs7.h b/include/crypto/pkcs7.h
> index 583f199400a3..a05a0d7214e6 100644
> --- a/include/crypto/pkcs7.h
> +++ b/include/crypto/pkcs7.h
> @@ -29,6 +29,9 @@ extern int pkcs7_get_content_data(const struct 
> pkcs7_message *pkcs7,
> const void **_data, size_t *_datalen,
> size_t *_headerlen);
> 
> +extern const struct public_key_signature *pkcs7_get_message_sig(
> + const struct pkcs7_message *pkcs7);
> +
>  /*
>   * pkcs7_trust.c
>   */
> diff --git a/security/integrity/Kconfig b/security/integrity/Kconfig
> index da9565891738..0d642e0317c7 100644
> --- a/security/integrity/Kconfig
> +++ b/security/integrity/Kconfig
> @@ -17,8 

Re: [RFC 09/10] ima: move to generic async completion

2017-05-10 Thread Mimi Zohar
On Sat, 2017-05-06 at 15:59 +0300, Gilad Ben-Yossef wrote:
> ima starts several async. crypto ops and  waits for their completions.
> Move it over to generic code doing the same.
> 
> Signed-off-by: Gilad Ben-Yossef <gi...@benyossef.com>

Acked-by: Mimi Zohar <zo...@linux.vnet.ibm.com>

> ---
>  security/integrity/ima/ima_crypto.c | 56 
> +++--
>  1 file changed, 17 insertions(+), 39 deletions(-)
> 
> diff --git a/security/integrity/ima/ima_crypto.c 
> b/security/integrity/ima/ima_crypto.c
> index 802d5d2..0e4db1fe 100644
> --- a/security/integrity/ima/ima_crypto.c
> +++ b/security/integrity/ima/ima_crypto.c
> @@ -27,11 +27,6 @@
> 
>  #include "ima.h"
> 
> -struct ahash_completion {
> - struct completion completion;
> - int err;
> -};
> -
>  /* minimum file size for ahash use */
>  static unsigned long ima_ahash_minsize;
>  module_param_named(ahash_minsize, ima_ahash_minsize, ulong, 0644);
> @@ -196,30 +191,13 @@ static void ima_free_atfm(struct crypto_ahash *tfm)
>   crypto_free_ahash(tfm);
>  }
> 
> -static void ahash_complete(struct crypto_async_request *req, int err)
> +static inline int ahash_wait(int err, struct crypto_wait *wait)
>  {
> - struct ahash_completion *res = req->data;
> 
> - if (err == -EINPROGRESS)
> - return;
> - res->err = err;
> - complete(>completion);
> -}
> + err = crypto_wait_req(err, wait);
> 
> -static int ahash_wait(int err, struct ahash_completion *res)
> -{
> - switch (err) {
> - case 0:
> - break;
> - case -EINPROGRESS:
> - case -EBUSY:
> - wait_for_completion(>completion);
> - reinit_completion(>completion);
> - err = res->err;
> - /* fall through */
> - default:
> + if (err)
>   pr_crit_ratelimited("ahash calculation failed: err: %d\n", err);
> - }
> 
>   return err;
>  }
> @@ -233,7 +211,7 @@ static int ima_calc_file_hash_atfm(struct file *file,
>   int rc, read = 0, rbuf_len, active = 0, ahash_rc = 0;
>   struct ahash_request *req;
>   struct scatterlist sg[1];
> - struct ahash_completion res;
> + struct crypto_wait wait;
>   size_t rbuf_size[2];
> 
>   hash->length = crypto_ahash_digestsize(tfm);
> @@ -242,12 +220,12 @@ static int ima_calc_file_hash_atfm(struct file *file,
>   if (!req)
>   return -ENOMEM;
> 
> - init_completion();
> + crypto_init_wait();
>   ahash_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG |
>  CRYPTO_TFM_REQ_MAY_SLEEP,
> -ahash_complete, );
> +crypto_req_done, );
> 
> - rc = ahash_wait(crypto_ahash_init(req), );
> + rc = ahash_wait(crypto_ahash_init(req), );
>   if (rc)
>   goto out1;
> 
> @@ -288,7 +266,7 @@ static int ima_calc_file_hash_atfm(struct file *file,
>* read/request, wait for the completion of the
>* previous ahash_update() request.
>*/
> - rc = ahash_wait(ahash_rc, );
> + rc = ahash_wait(ahash_rc, );
>   if (rc)
>   goto out3;
>   }
> @@ -304,7 +282,7 @@ static int ima_calc_file_hash_atfm(struct file *file,
>* read/request, wait for the completion of the
>* previous ahash_update() request.
>*/
> - rc = ahash_wait(ahash_rc, );
> + rc = ahash_wait(ahash_rc, );
>   if (rc)
>   goto out3;
>   }
> @@ -318,7 +296,7 @@ static int ima_calc_file_hash_atfm(struct file *file,
>   active = !active; /* swap buffers, if we use two */
>   }
>   /* wait for the last update request to complete */
> - rc = ahash_wait(ahash_rc, );
> + rc = ahash_wait(ahash_rc, );
>  out3:
>   if (read)
>   file->f_mode &= ~FMODE_READ;
> @@ -327,7 +305,7 @@ static int ima_calc_file_hash_atfm(struct file *file,
>  out2:
>   if (!rc) {
>   ahash_request_set_crypt(req, NULL, hash->digest, 0);
> - rc = ahash_wait(crypto_ahash_final(req), );
> + rc = ahash_wait(crypto_ahash_final(req), );
>   }
>  out1:
>   ahash_request_free(req);
> @@ -527,7 +505,7 @@ static int calc_buffer_ahash_atfm(const void *buf, loff_t 
> len,
>  {
>   struct ahash

Re: [PATCH 6/6] ima: Support appended signatures for appraisal

2017-04-26 Thread Mimi Zohar
Hi Thiago,

On Tue, 2017-04-18 at 17:17 -0300, Thiago Jung Bauermann wrote:
> This patch introduces the appended_imasig keyword to the IMA policy syntax
> to specify that a given hook should expect the file to have the IMA
> signature appended to it.  Here is how it can be used in a rule:
> 
> appraise func=KEXEC_KERNEL_CHECK appraise_type=appended_imasig
> appraise func=KEXEC_KERNEL_CHECK appraise_type=appended_imasig|imasig

> In the second form, IMA will accept either an appended signature or a
> signature stored in the extended attribute. In that case, it will first
> check whether there is an appended signature, and if not it will read it
> from the extended attribute.

An appended signature should be another place to look for a signature,
when a signature is required, but it shouldn't make a difference where
the signature is located.  "imasig" could have implied to look for the
signature in both places - xattr or appended.  So the new option is
just a hint - a performance improvement.

This might seem picayune, but the difference between "expect" vs.
"hint" impacts the code. (Further explanation inline.)

> The format of the appended signature is the same used for signed kernel
> modules. This means that the file can be signed with the scripts/sign-file
> tool, with a command line such as this:
> 
> $ sign-file sha256 privkey_ima.pem x509_ima.der vmlinux
> 
> This code only works for files that are hashed from a memory buffer, not
> for files that are read from disk at the time of hash calculation. In other
> words, only hooks that use kernel_read_file can support appended
> signatures.
> 
> The change in CONFIG_INTEGRITY_SIGNATURE to select CONFIG_KEYS instead of
> depending on it is to avoid a dependency recursion in
> CONFIG_IMA_APPRAISE_APPENDED_SIG, because CONFIG_MODULE_SIG_FORMAT selects
> CONFIG_KEYS and Kconfig complains that CONFIG_INTEGRITY_SIGNATURE depends
> on it.
> 
> Signed-off-by: Thiago Jung Bauermann 
> ---

snip

> diff --git a/security/integrity/ima/ima_main.c 
> b/security/integrity/ima/ima_main.c
> index 2aebb7984437..994ee420b2ec 100644
> --- a/security/integrity/ima/ima_main.c
> +++ b/security/integrity/ima/ima_main.c
> @@ -16,6 +16,9 @@
>   *   implements the IMA hooks: ima_bprm_check, ima_file_mmap,
>   *   and ima_file_check.
>   */
> +
> +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
> +
>  #include 
>  #include 
>  #include 
> @@ -228,9 +231,30 @@ static int process_measurement(struct file *file, char 
> *buf, loff_t size,
> 
>   template_desc = ima_template_desc_current();
>   if ((action & IMA_APPRAISE_SUBMASK) ||
> - strcmp(template_desc->name, IMA_TEMPLATE_IMA_NAME) != 0)
> - /* read 'security.ima' */
> - xattr_len = ima_read_xattr(file_dentry(file), _value);
> + strcmp(template_desc->name, IMA_TEMPLATE_IMA_NAME) != 0) {
> +#ifdef CONFIG_IMA_APPRAISE_APPENDED_SIG

Using "ifdef" in C code is really discouraged. Normally, it is an
indication that the code needs to be re-factored.  Assuming we really
need a new CONFIG option, which I'm not sure that we do, I would move
the appended signature code to its own file, define stub functions in
ima.h, and update the Makefile.

> + unsigned long digsig_req;
> +
> + if (iint->flags & IMA_APPENDED_DIGSIG_REQUIRED) {
> + if (!buf || !size)
> + pr_err("%s doesn't support appended_imasig\n",
> +func_tokens[func]);

The policy parsing should prevent defining appended_imasig on
inappropriate hooks.  Since the iint->flags might be shared between
hooks, we might still need to test buf, but it could be simplified to:

if (!buf && iint->flags & IMA_APPENDED_DIGSIG_REQUIRED) {

> + else
> + ima_read_appended_sig(buf, , _value,
> +   _len);
> + }
> +
> + /*
> +  * Don't try to read the xattr if we require an appended
> +  * signature but failed to get one.
> +  */

If the appended_sig is just a hint as to where the signature is
located, then we should read the xattr, even if IMA_DIGSIG_REQUIRED is
not specified.  ima_appraise_measurement() should be updated to
require a signature if either IMA_DIGSIG_REQUIRED or
IMA_APPENDED_SIGNATURE_REQUIRED are specified.  

Part of the confusion might be due to the naming
-"IMA_APPENEDED_SIGNATURE_REQUIRED".


> + digsig_req = iint->flags & IMA_DIGSIG_REQUIRED_MASK;
> + if (!xattr_len && digsig_req != IMA_APPENDED_DIGSIG_REQUIRED)
> +#endif /* CONFIG_IMA_APPRAISE_APPENDED_SIG */

Is limiting the "if" to the ifdef really necessary? 

> + /* read 'security.ima' */
> + xattr_len = ima_read_xattr(file_dentry(file),
> +_value);
> + }
> 

Suppose 

Re: [PATCH 3/6] ima: Simplify policy_func_show.

2017-04-21 Thread Mimi Zohar
On Thu, 2017-04-20 at 17:40 -0300, Thiago Jung Bauermann wrote:
> Am Donnerstag, 20. April 2017, 08:13:23 BRT schrieb Mimi Zohar:
> > On Tue, 2017-04-18 at 17:17 -0300, Thiago Jung Bauermann wrote:
> > > If the func_tokens array uses the same indices as enum ima_hooks,
> > > policy_func_show can be a lot simpler, and the func_* enum becomes
> > > unnecessary.
> > 
> > My main concern with separating the enumeration from the string
> > definition is that they might become out of sync.  Perhaps using
> > macros, similar to those used for kernel_read_file_id_str(), would be
> > better?
> 
> I agree that it would be better. Is the patch below what you had in mind?

Yes, I haven't tested it yet, but it looks right.
> 
> I also noticed that policy_func_show can be even simpler if we stop using the 
> printf format string from the policy_tokens table. What do you think?
> 
> -- 
> Thiago Jung Bauermann
> IBM Linux Technology Center
> 
> 
> From 594628c94f5dd7c6d2624944a76b6a01f9668128 Mon Sep 17 00:00:00 2001
> From: Thiago Jung Bauermann <bauer...@linux.vnet.ibm.com>
> Date: Mon, 10 Apr 2017 14:59:44 -0300
> Subject: [PATCH 3/6] ima: Simplify policy_func_show.
> 
> If the func_tokens array uses the same indices as enum ima_hooks,
> policy_func_show can be a lot simpler, and the func_* enum becomes
> unnecessary.
> 
> Also, if we use the same macro trick used by kernel_read_file_id_str we can
> use one hooks list for both the enum and the string array, making sure they
> are always in sync (suggested by Mimi Zohar).

> Finally, by using the printf pattern for the function token directly
> instead of using the pt macro we can simplify policy_func_show even further
> and avoid the need of having a temporary buffer. Since the only use of
> Opt_func's printf pattern in policy_tokens was in policy_func_show, we
> don't need it at all anymore so remove it.
> 
> Signed-off-by: Thiago Jung Bauermann <bauer...@linux.vnet.ibm.com>
> ---
>  security/integrity/ima/ima.h| 25 +---
>  security/integrity/ima/ima_policy.c | 60 
> +
>  2 files changed, 22 insertions(+), 63 deletions(-)
> 
> diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h
> index b563fbd4d122..51ef805cf7f3 100644
> --- a/security/integrity/ima/ima.h
> +++ b/security/integrity/ima/ima.h
> @@ -172,17 +172,22 @@ static inline unsigned long ima_hash_key(u8 *digest)
>   return hash_long(*digest, IMA_HASH_BITS);
>  }
> 
> +#define __ima_hooks(hook)\
> + hook(NONE)  \
> + hook(FILE_CHECK)\
> + hook(MMAP_CHECK)\
> + hook(BPRM_CHECK)\
> + hook(POST_SETATTR)  \
> + hook(MODULE_CHECK)  \
> + hook(FIRMWARE_CHECK)\
> + hook(KEXEC_KERNEL_CHECK)\
> + hook(KEXEC_INITRAMFS_CHECK) \
> + hook(POLICY_CHECK)  \
> + hook(MAX_CHECK)
> +#define __ima_hook_enumify(ENUM) ENUM,
> +
>  enum ima_hooks {
> - FILE_CHECK = 1,
> - MMAP_CHECK,
> - BPRM_CHECK,
> - POST_SETATTR,
> - MODULE_CHECK,
> - FIRMWARE_CHECK,
> - KEXEC_KERNEL_CHECK,
> - KEXEC_INITRAMFS_CHECK,
> - POLICY_CHECK,
> - MAX_CHECK
> + __ima_hooks(__ima_hook_enumify)
>  };
> 
>  /* LIM API function definitions */
> diff --git a/security/integrity/ima/ima_policy.c 
> b/security/integrity/ima/ima_policy.c
> index cfda5d7b17ec..39d43a5beb5a 100644
> --- a/security/integrity/ima/ima_policy.c
> +++ b/security/integrity/ima/ima_policy.c
> @@ -503,7 +503,7 @@ static match_table_t policy_tokens = {
>   {Opt_subj_user, "subj_user=%s"},
>   {Opt_subj_role, "subj_role=%s"},
>   {Opt_subj_type, "subj_type=%s"},
> - {Opt_func, "func=%s"},
> + {Opt_func, NULL},
>   {Opt_mask, "mask=%s"},
>   {Opt_fsmagic, "fsmagic=%s"},
>   {Opt_fsuuid, "fsuuid=%s"},
> @@ -896,23 +896,10 @@ static const char *const mask_tokens[] = {
>   "MAY_APPEND"
>  };
> 
> -enum {
> - func_file = 0, func_mmap, func_bprm,
> - func_module, func_firmware, func_post,
> - func_kexec_kernel, func_kexec_initramfs,
> - func_policy
> -};
> +#define __ima_hook_stringify(str)#str,
> 
>  static const char *const func_tokens[] = {
> - "FILE_CHECK",
> - "MMAP_CHECK",
> - "BPRM_CHECK",
> - "MODULE_CHECK",
> - "FIRMWARE_CHECK",
> - "POST_SETATTR",
> - "KEXEC_KERN

Re: [PATCH 5/6] MODSIGN: Export module signature definitions.

2017-04-20 Thread Mimi Zohar
On Tue, 2017-04-18 at 17:17 -0300, Thiago Jung Bauermann wrote:
> IMA will use the module_signature format for append signatures, so export
> the relevant definitions and factor out the code which verifies that the
> appended signature trailer is valid.
> 
> Also, create a CONFIG_MODULE_SIG_FORMAT option so that IMA can select it
> and be able to use validate_module_signature without having to depend on
> CONFIG_MODULE_SIG.

Basically we want to generalize the concept of an appended signature.
 Referring to it as a "module signature format" seems a bit confusing.

David, would you have a problem with changing the appended string from
"~Module signature appended~\n" to something more generic?  The
appended signature format could be used by anything calling
kernel_read_file() (eg. kexec kernel image/initramfs).

Mimi

> Signed-off-by: Thiago Jung Bauermann 
> ---
>  include/linux/module_signature.h | 45 
>  init/Kconfig |  6 +++-
>  kernel/Makefile  |  2 +-
>  kernel/module_signing.c  | 74 
> +---
>  4 files changed, 82 insertions(+), 45 deletions(-)
> 
> diff --git a/include/linux/module_signature.h 
> b/include/linux/module_signature.h
> new file mode 100644
> index ..b04f16559b47
> --- /dev/null
> +++ b/include/linux/module_signature.h
> @@ -0,0 +1,45 @@
> +/* Module signature handling.
> + *
> + * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved.
> + * Written by David Howells (dhowe...@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.
> + */
> +
> +#ifndef _LINUX_MODULE_SIGNATURE_H
> +#define _LINUX_MODULE_SIGNATURE_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.
> + *
> + * The constituents of the signature section are, in order:
> + *
> + *   - Signer's name
> + *   - Key identifier
> + *   - Signature data
> + *   - Information block
> + */
> +struct module_signature {
> + u8  algo;   /* Public-key crypto algorithm [0] */
> + u8  hash;   /* Digest algorithm [0] */
> + u8  id_type;/* Key identifier type [PKEY_ID_PKCS7] */
> + u8  signer_len; /* Length of signer's name [0] */
> + u8  key_id_len; /* Length of key identifier [0] */
> + u8  __pad[3];
> + __be32  sig_len;/* Length of signature data */
> +};
> +
> +int validate_module_signature(const struct module_signature *ms,
> +   size_t file_len);
> +int mod_verify_sig(const void *mod, unsigned long *_modlen);
> +
> +#endif /* _LINUX_MODULE_SIGNATURE_H */
> diff --git a/init/Kconfig b/init/Kconfig
> index a92f27da4a27..891325e5aeff 100644
> --- a/init/Kconfig
> +++ b/init/Kconfig
> @@ -2024,7 +2024,7 @@ config MODULE_SRCVERSION_ALL
>  config MODULE_SIG
>   bool "Module signature verification"
>   depends on MODULES
> - select SYSTEM_DATA_VERIFICATION
> + select MODULE_SIG_FORMAT
>   help
> Check modules for valid signatures upon load: the signature
> is simply appended to the module. For more information see
> @@ -2039,6 +2039,10 @@ config MODULE_SIG
> debuginfo strip done by some packagers (such as rpmbuild) and
> inclusion into an initramfs that wants the module size reduced.
> 
> +config MODULE_SIG_FORMAT
> + def_bool n
> + select SYSTEM_DATA_VERIFICATION
> +
>  config MODULE_SIG_FORCE
>   bool "Require modules to be validly signed"
>   depends on MODULE_SIG
> diff --git a/kernel/Makefile b/kernel/Makefile
> index b302b4731d16..4451bbc70a08 100644
> --- a/kernel/Makefile
> +++ b/kernel/Makefile
> @@ -56,7 +56,7 @@ obj-y += up.o
>  endif
>  obj-$(CONFIG_UID16) += uid16.o
>  obj-$(CONFIG_MODULES) += module.o
> -obj-$(CONFIG_MODULE_SIG) += module_signing.o
> +obj-$(CONFIG_MODULE_SIG_FORMAT) += module_signing.o
>  obj-$(CONFIG_KALLSYMS) += kallsyms.o
>  obj-$(CONFIG_BSD_PROCESS_ACCT) += acct.o
>  obj-$(CONFIG_KEXEC_CORE) += kexec_core.o
> diff --git a/kernel/module_signing.c b/kernel/module_signing.c
> index 937c844bee4a..421e3e668714 100644
> --- a/kernel/module_signing.c
> +++ b/kernel/module_signing.c
> @@ -11,36 +11,38 @@
> 
>  #include 
>  #include 
> +#include 
>  #include 
>  #include 
>  #include 
>  #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 

Re: [PATCH 3/6] ima: Simplify policy_func_show.

2017-04-20 Thread Mimi Zohar
On Tue, 2017-04-18 at 17:17 -0300, Thiago Jung Bauermann wrote:
> If the func_tokens array uses the same indices as enum ima_hooks,
> policy_func_show can be a lot simpler, and the func_* enum becomes
> unnecessary.

My main concern with separating the enumeration from the string
definition is that they might become out of sync.  Perhaps using
macros, similar to those used for kernel_read_file_id_str(), would be
better?

> Signed-off-by: Thiago Jung Bauermann 
> ---
>  security/integrity/ima/ima_policy.c | 47 
> ++---
>  1 file changed, 7 insertions(+), 40 deletions(-)
> 
> diff --git a/security/integrity/ima/ima_policy.c 
> b/security/integrity/ima/ima_policy.c
> index cfda5d7b17ec..158eafef64e8 100644
> --- a/security/integrity/ima/ima_policy.c
> +++ b/security/integrity/ima/ima_policy.c
> @@ -896,20 +896,14 @@ static const char *const mask_tokens[] = {
>   "MAY_APPEND"
>  };
> 
> -enum {
> - func_file = 0, func_mmap, func_bprm,
> - func_module, func_firmware, func_post,
> - func_kexec_kernel, func_kexec_initramfs,
> - func_policy
> -};
> -

At least, add a comment here and near the ima_hooks enumeration to
prevent them from becoming out of sync.

Mimi

>  static const char *const func_tokens[] = {
> + NULL,
>   "FILE_CHECK",
>   "MMAP_CHECK",
>   "BPRM_CHECK",
> + "POST_SETATTR",
>   "MODULE_CHECK",
>   "FIRMWARE_CHECK",
> - "POST_SETATTR",
>   "KEXEC_KERNEL_CHECK",
>   "KEXEC_INITRAMFS_CHECK",
>   "POLICY_CHECK"
> @@ -949,48 +943,21 @@ void ima_policy_stop(struct seq_file *m, void *v)
> 
>  #define pt(token)policy_tokens[token + Opt_err].pattern
>  #define mt(token)mask_tokens[token]
> -#define ft(token)func_tokens[token]
> 
>  /*
>   * policy_func_show - display the ima_hooks policy rule
>   */
>  static void policy_func_show(struct seq_file *m, enum ima_hooks func)
>  {
> - char tbuf[64] = {0,};
> + if (func > 0 && func < MAX_CHECK)
> + seq_printf(m, pt(Opt_func), func_tokens[func]);
> + else {
> + char tbuf[64] = {0,};
> 
> - switch (func) {
> - case FILE_CHECK:
> - seq_printf(m, pt(Opt_func), ft(func_file));
> - break;
> - case MMAP_CHECK:
> - seq_printf(m, pt(Opt_func), ft(func_mmap));
> - break;
> - case BPRM_CHECK:
> - seq_printf(m, pt(Opt_func), ft(func_bprm));
> - break;
> - case MODULE_CHECK:
> - seq_printf(m, pt(Opt_func), ft(func_module));
> - break;
> - case FIRMWARE_CHECK:
> - seq_printf(m, pt(Opt_func), ft(func_firmware));
> - break;
> - case POST_SETATTR:
> - seq_printf(m, pt(Opt_func), ft(func_post));
> - break;
> - case KEXEC_KERNEL_CHECK:
> - seq_printf(m, pt(Opt_func), ft(func_kexec_kernel));
> - break;
> - case KEXEC_INITRAMFS_CHECK:
> - seq_printf(m, pt(Opt_func), ft(func_kexec_initramfs));
> - break;
> - case POLICY_CHECK:
> - seq_printf(m, pt(Opt_func), ft(func_policy));
> - break;
> - default:
>   snprintf(tbuf, sizeof(tbuf), "%d", func);
>   seq_printf(m, pt(Opt_func), tbuf);
> - break;
>   }
> +
>   seq_puts(m, " ");
>  }
> 



Re: [PATCH] trusted-keys: skcipher bug info

2016-09-20 Thread Mimi Zohar
On Tue, 2016-09-20 at 20:35 +0800, Herbert Xu wrote:
> On Tue, Sep 20, 2016 at 08:11:51AM -0400, Mimi Zohar wrote:
> > Hi Herbert,
> > 
> > The initial random iv value, initialized in encrypted_init(), should
> > not be modified.  Commit c3917fd "KEYS: Use skcipher", which replaced
> > the blkcipher with skcipher, modifies the iv in
> > crypto_skcipher_encrypt()/decrypt().
> > 
> > The following example creates an encrypted key, writes the key to a
> > file, and then loads the key from the file.  To illustrate the problem,
> > this patch provides crypto_skcipher_encrypt()/decrypt() with a copy of
> > the iv.  With this change, the resulting test-key and test-key1 keys
> > are the same.
> 
> Sorry, I missed the subtlety.  This patch should fix the problem.

Thanks!

Mimi
> 
> ---8<---
> Subject: KEYS: Fix skcipher IV clobbering
> 
> The IV must not be modified by the skcipher operation so we need
> to duplicate it.
> 
> Fixes: c3917fd9dfbc ("KEYS: Use skcipher")
> Cc: sta...@vger.kernel.org
> Reported-by: Mimi Zohar <zo...@linux.vnet.ibm.com>
> Signed-off-by: Herbert Xu <herb...@gondor.apana.org.au>
> 
> diff --git a/security/keys/encrypted-keys/encrypted.c 
> b/security/keys/encrypted-keys/encrypted.c
> index 5adbfc3..17a0610 100644
> --- a/security/keys/encrypted-keys/encrypted.c
> +++ b/security/keys/encrypted-keys/encrypted.c
> @@ -29,6 +29,7 @@
>  #include 
>  #include 
>  #include 
> +#include 
>  #include 
>  #include 
>  #include 
> @@ -478,6 +479,7 @@ static int derived_key_encrypt(struct 
> encrypted_key_payload *epayload,
>   struct crypto_skcipher *tfm;
>   struct skcipher_request *req;
>   unsigned int encrypted_datalen;
> + u8 iv[AES_BLOCK_SIZE];
>   unsigned int padlen;
>   char pad[16];
>   int ret;
> @@ -500,8 +502,8 @@ static int derived_key_encrypt(struct 
> encrypted_key_payload *epayload,
>   sg_init_table(sg_out, 1);
>   sg_set_buf(sg_out, epayload->encrypted_data, encrypted_datalen);
> 
> - skcipher_request_set_crypt(req, sg_in, sg_out, encrypted_datalen,
> -epayload->iv);
> + memcpy(iv, epayload->iv, sizeof(iv));
> + skcipher_request_set_crypt(req, sg_in, sg_out, encrypted_datalen, iv);
>   ret = crypto_skcipher_encrypt(req);
>   tfm = crypto_skcipher_reqtfm(req);
>   skcipher_request_free(req);
> @@ -581,6 +583,7 @@ static int derived_key_decrypt(struct 
> encrypted_key_payload *epayload,
>   struct crypto_skcipher *tfm;
>   struct skcipher_request *req;
>   unsigned int encrypted_datalen;
> + u8 iv[AES_BLOCK_SIZE];
>   char pad[16];
>   int ret;
> 
> @@ -599,8 +602,8 @@ static int derived_key_decrypt(struct 
> encrypted_key_payload *epayload,
>  epayload->decrypted_datalen);
>   sg_set_buf(_out[1], pad, sizeof pad);
> 
> - skcipher_request_set_crypt(req, sg_in, sg_out, encrypted_datalen,
> -epayload->iv);
> + memcpy(iv, epayload->iv, sizeof(iv));
> + skcipher_request_set_crypt(req, sg_in, sg_out, encrypted_datalen, iv);
>   ret = crypto_skcipher_decrypt(req);
>   tfm = crypto_skcipher_reqtfm(req);
>   skcipher_request_free(req);
> 


--
To unsubscribe from this list: send the line "unsubscribe linux-crypto" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH] trusted-keys: skcipher bug info

2016-09-20 Thread Mimi Zohar
Hi Herbert,

The initial random iv value, initialized in encrypted_init(), should
not be modified.  Commit c3917fd "KEYS: Use skcipher", which replaced
the blkcipher with skcipher, modifies the iv in
crypto_skcipher_encrypt()/decrypt().

The following example creates an encrypted key, writes the key to a
file, and then loads the key from the file.  To illustrate the problem,
this patch provides crypto_skcipher_encrypt()/decrypt() with a copy of
the iv.  With this change, the resulting test-key and test-key1 keys
are the same.

keyctl add user kmk "`dd if=/dev/urandom bs=1 count=32 2>/dev/null`" @u
keyctl pipe `keyctl search @u user kmk` > ~/tmp/kmk
keyctl add encrypted test-key "new user:kmk 64" @u
keyctl pipe `keyctl search @u encrypted test-key` > /tmp/test-key1
keyctl add encrypted test-key1 "load `cat /tmp/test-key1`" @u

keyctl print `keyctl search @u encrypted test-key`
keyctl print `keyctl search @u encrypted test-key1`

Either the underlying problem should be fixed or commit c3917fd 
"KEYS: Use skcipher" should be reverted.

thanks,

Mimi

---
 security/keys/encrypted-keys/encrypted.c | 22 +++---
 1 file changed, 19 insertions(+), 3 deletions(-)

diff --git a/security/keys/encrypted-keys/encrypted.c 
b/security/keys/encrypted-keys/encrypted.c
index 5adbfc3..e94f586 100644
--- a/security/keys/encrypted-keys/encrypted.c
+++ b/security/keys/encrypted-keys/encrypted.c
@@ -480,6 +480,7 @@ static int derived_key_encrypt(struct encrypted_key_payload 
*epayload,
unsigned int encrypted_datalen;
unsigned int padlen;
char pad[16];
+   u8 iv[16];
int ret;
 
encrypted_datalen = roundup(epayload->decrypted_datalen, blksize);
@@ -500,9 +501,19 @@ static int derived_key_encrypt(struct 
encrypted_key_payload *epayload,
sg_init_table(sg_out, 1);
sg_set_buf(sg_out, epayload->encrypted_data, encrypted_datalen);
 
+   memcpy(iv, epayload->iv, 16);   /* iv is modified */
skcipher_request_set_crypt(req, sg_in, sg_out, encrypted_datalen,
-  epayload->iv);
+  iv);
+print_hex_dump(KERN_INFO, "original iv: ", DUMP_PREFIX_NONE, 32, 1,
+  epayload->iv, ivsize, 0);
+print_hex_dump(KERN_INFO, "copied iv: ", DUMP_PREFIX_NONE, 32, 1,
+  iv, ivsize, 0);
ret = crypto_skcipher_encrypt(req);
+print_hex_dump(KERN_INFO, "original iv: ", DUMP_PREFIX_NONE, 32, 1,
+  epayload->iv, ivsize, 0);
+print_hex_dump(KERN_INFO, "modified iv: ", DUMP_PREFIX_NONE, 32, 1,
+  iv, ivsize, 0);
+
tfm = crypto_skcipher_reqtfm(req);
skcipher_request_free(req);
crypto_free_skcipher(tfm);
@@ -582,6 +593,7 @@ static int derived_key_decrypt(struct encrypted_key_payload 
*epayload,
struct skcipher_request *req;
unsigned int encrypted_datalen;
char pad[16];
+   u8 iv[16];
int ret;
 
encrypted_datalen = roundup(epayload->decrypted_datalen, blksize);
@@ -599,8 +611,9 @@ static int derived_key_decrypt(struct encrypted_key_payload 
*epayload,
   epayload->decrypted_datalen);
sg_set_buf(_out[1], pad, sizeof pad);
 
+   memcpy(iv, epayload->iv, 16);   /* iv is modified */
skcipher_request_set_crypt(req, sg_in, sg_out, encrypted_datalen,
-  epayload->iv);
+  iv);
ret = crypto_skcipher_decrypt(req);
tfm = crypto_skcipher_reqtfm(req);
skcipher_request_free(req);
@@ -778,8 +791,11 @@ static int encrypted_init(struct encrypted_key_payload 
*epayload,
 
get_random_bytes(epayload->decrypted_data,
 epayload->decrypted_datalen);
-   } else
+   } else {
ret = encrypted_key_decrypt(epayload, format, hex_encoded_iv);
+print_hex_dump(KERN_INFO, "init iv: ", DUMP_PREFIX_NONE, 32, 1,
+  epayload->iv, ivsize, 0);
+   }
return ret;
 }
 
-- 
2.7.4



--
To unsubscribe from this list: send the line "unsubscribe linux-crypto" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: Transferring applied X.509 patches from crypto/next to security/next

2016-02-08 Thread Mimi Zohar
Hi Herbert,

On Mon, 2016-02-08 at 13:58 +, David Howells wrote:
> Herbert Xu  wrote:
> 
> > > Hmmm...  That means that the crypto branch and the security branch are 
> > > going
> > > to conflict.
> > 
> > I thought you were OK with it going in now as you said that you'll
> > fix it up later.  Sorry for the misunderstanding.  Do you want me to
> > revert?
> 
> If you can back them out, I'll apply them to my keys-next branch.  Unless
> James is willing to rebase security/next on top of your crypto branch?

Could we upstream these patches via James' tree?  If you re-base these
patches on top of the James' security-next branch and send him a pull
request, we can then base on our patches on top of them.

Mimi

--
To unsubscribe from this list: send the line "unsubscribe linux-crypto" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [Linux-ima-user] [RFC] i.MX6 CAAM blob generator for IMA/EVM initialization

2016-01-28 Thread Mimi Zohar
On Wed, 2016-01-27 at 11:04 +0100, Steffen Trumtrar wrote:
> Hi!
> 
> Mimi Zohar writes:
> 
> > On Mon, 2015-11-09 at 16:18 +0100, Steffen Trumtrar wrote:
> >> Hi!
> >> 
> >> The RFC Patch attached after this cover letter is mostly for illustration
> >> purposes, so please don't waste too much time reviewing the code ;-)
> >> 
> >> For context I'll try to describe the problem that this patch tries to 
> >> solve.
> >> 
> >> I need to be able to boot an EVM signed (and dongled) rootfs. The CAAM on
> >> the i.MX6 has support for an OTP key and can en/decrypt data.
> >> It also has a feature for generating red blobs: basically a chunk of data,
> >> that is encrypted with the OTP key, which can be saved on some medium as a
> >> secret to decrypt the EVM HMAC secret for one specific device.
> >> 
> >> To open the rootfs, the secret is handed from the bootloader to the kernel
> >> as a base64 encoded string via the cmdline to an initramfs.
> >> In the initramfs the sysfs file "modifier" is set to something starting 
> >> with
> >> "kernel:evm" and the base64 string is written to the sysfs file "blob".
> >> The CAAM than decodes the red blob and, in case of "kernel:evm", 
> >> initializes
> >> the EVM or otherwise writes the result to "payload" if the modifier starts
> >> with "user:". Therefore a blob that was generated for EVM never leaves the
> >> kernel on decryption.
> >> Generation of blobs goes like: echoing "modifier" to something and echoing
> >> the payload to "payload". The red blob can than be read from "blob".
> >> 
> >> 
> >> So, the sysfs interface is not the best option, I guess. The question is:
> >> What is the right approach for a setup like this?
> >> I need to:
> >>   - be able to encrypt the secret and store it somewhere
> >>   - to load the stored secret and decrypt it later
> >>   - initialize IMA/EVM with the secret
> >> 
> >> Would something like
> >>   - security/keys/encrypted-keys/encrypted.c
> >> be the correct approach?
> >
> > Instead of using the CAAM for OTP encrypting/decrypting, can it be used
> > to load the EVM key directly?  Dmitry's patches, which will be
> > upstreamed in 4.5
> >
> https://git.kernel.org/cgit/linux/kernel/git/zohar/linux-integrity.git/log/?h=for-next-4.5?
>adds support for a crypto device to directly load the EVM key.
> >
> 
> The patches look good and I use them for loading the EVM key from the
> CAAM driver. But I still need the OTP decryption functionality.

> The key data that I hand to evm_set_key must be device specific but I
> don't want to use the fused OTP in the CAAM directly.
> The OTP is used to protect multiple random keys. Therefore I need to
> generate encrypted blobs that I can store on some unsecure memory
> (EEPROM, NAND,...) and be able to hand that later back to the CAAM
> module, to then get back an IMA/EVM, ecryptfs, $something key.
> 
> > FYI, the EVM key is an encrypted key, which encrypts/decrypts either a
> > trusted or user type key.
> >
> So the normal approach would be to have a key in the kernel keyring
> and decrypt it with the key loaded with evm_set_key?

Sorry, I should have said the encrypted key is encrypted/decrypted using
the trusted or user type key.

> Can I somehow use the keyring framework as an abstraction around my
> blobbing/deblobbing functionality?
> So that the "keyring" calls into the crypto driver to decrypt the data
> and uses the crypto driver to encrypt the keys when I want to "dump"
> them?

Definitely.   It sounds like you want the equivalent functionality as
the TPM based trusted keys using OTP on the CAAM.

>From Documentation/security/keys-trusted-encrypted.txt:

"Trusted Keys use a TPM both to generate and to seal the keys.  Keys are
sealed
under a 2048 bit RSA key in the TPM, and optionally sealed to specified
PCR
(integrity measurement) values, and only unsealed by the TPM, if PCRs
and blob
integrity verifications match."

Mimi

--
To unsubscribe from this list: send the line "unsubscribe linux-crypto" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v2 2/2] integrity: convert digsig to akcipher api

2015-12-14 Thread Mimi Zohar
On Sat, 2015-12-12 at 18:26 -0800, Tadeusz Struk wrote:
> Convert asymmetric_verify to akcipher api.
> 
> Signed-off-by: Tadeusz Struk 
> ---
>  security/integrity/Kconfig |1 +
>  security/integrity/digsig_asymmetric.c |   10 +++---
>  2 files changed, 4 insertions(+), 7 deletions(-)
> 
> diff --git a/security/integrity/Kconfig b/security/integrity/Kconfig
> index 73c457b..f0b2463 100644
> --- a/security/integrity/Kconfig
> +++ b/security/integrity/Kconfig
> @@ -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
> diff --git a/security/integrity/digsig_asymmetric.c 
> b/security/integrity/digsig_asymmetric.c
> index 4fec181..5629372 100644
> --- a/security/integrity/digsig_asymmetric.c
> +++ b/security/integrity/digsig_asymmetric.c
> @@ -92,13 +92,9 @@ int asymmetric_verify(struct key *keyring, const char *sig,
>   pks.pkey_hash_algo = 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, );
> -
> - mpi_free(pks.rsa.s);
> + pks.s = hdr->sig;

Thanks!  With this change, my system is now able to boot.

Mimi 

> + pks.s_size = siglen;
> + ret = verify_signature(key, );
>   key_put(key);
>   pr_debug("%s() = %d\n", __func__, ret);
>   return ret;

--
To unsubscribe from this list: send the line "unsubscribe linux-crypto" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH 0/2] crypto: KEYS: convert public key to akcipher api

2015-12-10 Thread Mimi Zohar
On Thu, 2015-12-10 at 10:39 -0800, Tadeusz Struk wrote:
> Hi Mimi,
> On 12/10/2015 10:25 AM, Mimi Zohar wrote:
> >> This patch set converts the module verification and digital signature
> >> > code to the new akcipher API.
> >> > RSA implementation has been removed from crypto/asymmetric_keys and the
> >> > new API is used for cryptographic primitives.
> >> > There is no need for MPI above the akcipher API anymore.
> >> > Modules can be verified with software as well as HW RSA implementations.
> > With these two patches my system doesn't even boot.  Digging deeper...
> > 
> 
> It needs RSA implementation built-in.
> Could you check if you have CONFIG_CRYPTO_RSA=y

The diff between this config and the previous one:
< CONFIG_CRYPTO_AKCIPHER=y
< CONFIG_CRYPTO_RSA=y
---
> # CONFIG_CRYPTO_RSA is not set

Mimi



--
To unsubscribe from this list: send the line "unsubscribe linux-crypto" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH 0/2] crypto: KEYS: convert public key to akcipher api

2015-12-10 Thread Mimi Zohar
On Thu, 2015-12-10 at 14:37 -0500, Mimi Zohar wrote:
> On Thu, 2015-12-10 at 10:39 -0800, Tadeusz Struk wrote:
> > Hi Mimi,
> > On 12/10/2015 10:25 AM, Mimi Zohar wrote:
> > >> This patch set converts the module verification and digital signature
> > >> > code to the new akcipher API.
> > >> > RSA implementation has been removed from crypto/asymmetric_keys and the
> > >> > new API is used for cryptographic primitives.
> > >> > There is no need for MPI above the akcipher API anymore.
> > >> > Modules can be verified with software as well as HW RSA 
> > >> > implementations.
> > > With these two patches my system doesn't even boot.  Digging deeper...
> > > 
> > 
> > It needs RSA implementation built-in.
> > Could you check if you have CONFIG_CRYPTO_RSA=y
> 
> The diff between this config and the previous one:
> < CONFIG_CRYPTO_AKCIPHER=y
> < CONFIG_CRYPTO_RSA=y
> ---
> > # CONFIG_CRYPTO_RSA is not set

FYI, dracut loaded the keys on the IMA keyring properly.  When we try to
pivot root, real root /sbin/init fails appraisal.  The audit subsystem
is showing "invalid-signature".

There's no additional debugging information with the boot command line
options rd.debug or systemd.log_level=debug.

Mimi


--
To unsubscribe from this list: send the line "unsubscribe linux-crypto" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH 0/2] crypto: KEYS: convert public key to akcipher api

2015-12-10 Thread Mimi Zohar
On Wed, 2015-12-09 at 15:52 -0800, Tadeusz Struk wrote:
> This patch set converts the module verification and digital signature
> code to the new akcipher API.
> RSA implementation has been removed from crypto/asymmetric_keys and the
> new API is used for cryptographic primitives.
> There is no need for MPI above the akcipher API anymore.
> Modules can be verified with software as well as HW RSA implementations.

With these two patches my system doesn't even boot.  Digging deeper...

Mimi

> Patches generated against cryptodev-2.6
> ---
> 
> Tadeusz Struk (2):
>   crypto: KEYS: convert public key to the akcipher api
>   integrity: convert digsig to akcipher api
> 
> 
>  crypto/asymmetric_keys/Kconfig|2 
>  crypto/asymmetric_keys/Makefile   |7 -
>  crypto/asymmetric_keys/pkcs7_parser.c |   12 +-
>  crypto/asymmetric_keys/pkcs7_trust.c  |2 
>  crypto/asymmetric_keys/pkcs7_verify.c |2 
>  crypto/asymmetric_keys/public_key.c   |   64 +++--
>  crypto/asymmetric_keys/public_key.h   |   36 -
>  crypto/asymmetric_keys/rsa.c  |  211 
> +++--
>  crypto/asymmetric_keys/x509_cert_parser.c |   37 +
>  crypto/asymmetric_keys/x509_public_key.c  |   17 +-
>  crypto/asymmetric_keys/x509_rsakey.asn1   |4 -
>  include/crypto/public_key.h   |   49 ++-
>  security/integrity/digsig_asymmetric.c|   10 -
>  13 files changed, 138 insertions(+), 315 deletions(-)
>  delete mode 100644 crypto/asymmetric_keys/public_key.h
>  delete mode 100644 crypto/asymmetric_keys/x509_rsakey.asn1
> 
> --
> TS
> --
> To unsubscribe from this list: send the line "unsubscribe 
> linux-security-module" in
> the body of a message to majord...@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 


--
To unsubscribe from this list: send the line "unsubscribe linux-crypto" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [RFC] KEYS: Exposing {a,}symmetric key ops to userspace and other bits

2015-12-02 Thread Mimi Zohar
On Sun, 2015-11-22 at 09:41 -0500, Mimi Zohar wrote:
> On Fri, 2015-11-20 at 11:07 +, David Howells wrote:
> > 
> >  (*) Add Mimi's patches to allow keys/keyrings to be marked undeletable.  
> > This
> >  is for the purpose of creating blacklists and to prevent people from
> >  removing entries in the blacklist.  Note that only the kernel can 
> > create
> >  a blacklist - we don't want userspace generating them as a way to take 
> > up
> >  kernel space.
> > 
> >  I think the right way to do this is to not allow marked keys to be
> >  unlinked from marked keyrings, but to allow marked keys to be unlinked
> >  from ordinary keyrings.
> > 
> >  The reason the 'keep' mark is required on individual keys is to prevent
> >  the keys from being directly revoked, expired or invalidated by keyctl
> >  without reference to the keyring.  Marked keys that are set expirable
> >  when they're created will still expire and be subsequently removed and 
> > if
> >  a marked key or marked keyring loses all its references it still gets
> >  gc'd.
> 
> Agreed.  I'll fix and re-post soon.

In addition to Petko's 3 patches, the ima-keyrings branch
(git://git.kernel.org/pub/scm/linux/kernel/git/zohar/linux-integrity.git) 
contains these two patches.

d939a88 IMA: prevent keys on the .ima_blacklist from being removed
77f33b5 KEYS: prevent keys from being removed from specified keyrings

As the IMA patch is dependent on the KEYS patch, do you mind if the KEYS
patch would be upstreamed together with this patch set?

Mimi

--
To unsubscribe from this list: send the line "unsubscribe linux-crypto" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [RFC] KEYS: Exposing {a,}symmetric key ops to userspace and other bits

2015-11-22 Thread Mimi Zohar
On Fri, 2015-11-20 at 11:07 +, David Howells wrote:
> Hi Marcel, Mimi, Tadeus,
> 
> I want to consider adding or doing the following bits to the keyrings
> facility, aiming for the next merge window:
> 
>  (*) Bring in the patches that I posted to change how the trust model on a
>  keyring works.
> 
>  The model will then be that keys aren't automatically marked trusted, but
>  linking a key into a keyring that is marked trusted-only will validate
>  the key against the contents of the keyring before permitting its
>  addition.

This trust model is flawed.   We've already discussed this trust model
back when first introducing the concept of a trusted keyring.   Refer to
the v3 "ima: extending secure boot certificate chain of trust" patch set
https://lwn.net/Articles/576563/, which describes two methods of
verifying a certificate before adding the key to the trusted keyring.  

The first method  "4/5 KEYS: verify certificate is signed by a trusted
key on the target keyriing" is similar to the method being proposed
here.  The subsequent patch "5/5 KEYS: verify certificate is signed by a
trusted key on a particular keyring" rejected using the same keyring for
validating the new key being added.  It defined a new separate keyring
for validating the keys.  (Neither of these patches were upstreamed.)

Dmitry Kasatkin proposed a third method, which identified the "trusted"
key(s) on the system keyring, instead of maintaining a separate keyring.
As there wasn't a usecase requiring a separate keyring at the time, his
approach was upstreamed.  Now Petko Manoliv and Mark Bausche  have a
valid use case scenario for having a separate keyring.  (For the details
refer to:
https://www.mail-archive.com/linux-security-module@vger.kernel.org/msg03503.html)

With the proposed trust model change, the keys trusted to verify file
signatures would be allowed to also verify certificate signatures.  For
example, a system owner trusts company A to verify file signatures, yet
they want to retain control over which certificates may be added to the
keyring.  Just because company A trusts company/government X, doesn't
mean the system owner also trusts company/government X.   By having one
keyring, other certificates signed by company A could be added to the
keyring.

>  Note that we can then vary the policy on a per-keyring basis.
> 
>  (*) Add Mimi's patches to allow keys/keyrings to be marked undeletable.  This
>  is for the purpose of creating blacklists and to prevent people from
>  removing entries in the blacklist.  Note that only the kernel can create
>  a blacklist - we don't want userspace generating them as a way to take up
>  kernel space.
> 
>  I think the right way to do this is to not allow marked keys to be
>  unlinked from marked keyrings, but to allow marked keys to be unlinked
>  from ordinary keyrings.
> 
>  The reason the 'keep' mark is required on individual keys is to prevent
>  the keys from being directly revoked, expired or invalidated by keyctl
>  without reference to the keyring.  Marked keys that are set expirable
>  when they're created will still expire and be subsequently removed and if
>  a marked key or marked keyring loses all its references it still gets
>  gc'd.

Agreed.  I'll fix and re-post soon.

Mimi

--
To unsubscribe from this list: send the line "unsubscribe linux-crypto" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [Linux-ima-user] [RFC] i.MX6 CAAM blob generator for IMA/EVM initialization

2015-11-09 Thread Mimi Zohar
On Mon, 2015-11-09 at 16:18 +0100, Steffen Trumtrar wrote:
> Hi!
> 
> The RFC Patch attached after this cover letter is mostly for illustration
> purposes, so please don't waste too much time reviewing the code ;-)
> 
> For context I'll try to describe the problem that this patch tries to solve.
> 
> I need to be able to boot an EVM signed (and dongled) rootfs. The CAAM on
> the i.MX6 has support for an OTP key and can en/decrypt data.
> It also has a feature for generating red blobs: basically a chunk of data,
> that is encrypted with the OTP key, which can be saved on some medium as a
> secret to decrypt the EVM HMAC secret for one specific device.
> 
> To open the rootfs, the secret is handed from the bootloader to the kernel
> as a base64 encoded string via the cmdline to an initramfs.
> In the initramfs the sysfs file "modifier" is set to something starting with
> "kernel:evm" and the base64 string is written to the sysfs file "blob".
> The CAAM than decodes the red blob and, in case of "kernel:evm", initializes
> the EVM or otherwise writes the result to "payload" if the modifier starts
> with "user:". Therefore a blob that was generated for EVM never leaves the
> kernel on decryption.
> Generation of blobs goes like: echoing "modifier" to something and echoing
> the payload to "payload". The red blob can than be read from "blob".
> 
> 
> So, the sysfs interface is not the best option, I guess. The question is:
> What is the right approach for a setup like this?
> I need to:
>   - be able to encrypt the secret and store it somewhere
>   - to load the stored secret and decrypt it later
>   - initialize IMA/EVM with the secret
> 
> Would something like
>   - security/keys/encrypted-keys/encrypted.c
> be the correct approach?

Instead of using the CAAM for OTP encrypting/decrypting, can it be used
to load the EVM key directly?  Dmitry's patches, which will be
upstreamed in 4.5
https://git.kernel.org/cgit/linux/kernel/git/zohar/linux-integrity.git/log/?h=for-next-4.5?
   adds support for a crypto device to directly load the EVM key.

FYI, the EVM key is an encrypted key, which encrypts/decrypts either a
trusted or user type key.

Mimi

--
To unsubscribe from this list: send the line "unsubscribe linux-crypto" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH 00/10] KEYS: Change how keys are determined to be trusted

2015-10-21 Thread Mimi Zohar
On Wed, 2015-10-21 at 16:13 +0100, David Howells wrote:
> Here's a set of patches that changes how keys are determined to be trusted
> - currently, that's a case of whether a key has KEY_FLAG_TRUSTED set upon
> it.  A keyring can then have a flag set (KEY_FLAG_TRUSTED ONLY) that
> indicates that only keys with this flag set may be added to that keyring.
> 
> Further, any time an X.509 certificate is instantiated without this flag
> set, the certificate is judged against the contents of the system trusted
> keyring to determine whether KEY_FLAG_TRUSTED should be set upon it.
> 
> With these patches, KEY_FLAG_TRUSTED is removed.  The kernel may add
> implicitly trusted keys to a trusted-only keyring by asserting
> KEY_ALLOC_TRUSTED when the key is created, 

Ok, but only the x509 certificates built into the kernel image should be
automatically trusted and can be added to a trusted keyring, because the
kernel itself was signed (and verified).  These certificates extend the
(UEFI) certificate chain of trust that is rooted in hardware to the OS.

Other keys that the kernel reads and loads should not automatically be
trusted (eg. ima_load_x509).  They need to be validated against a
trusted key.

> but otherwise the key will only
> be allowed to be added to the keyring if it can be verified by a key
> already in that keyring.  The system trusted keyring is not then special in
> this sense and other trusted keyrings can be set up that are wholly
> independent of it.

We already went down this path of "transitive trust" back when we first
introduced the concept of trusted keys and keyrings.   Just because a
key is on a trusted keyring, doesn't imply that it should be permitted
to load other keys on the same trusted keyring.  In the case of
IMA-appraisal, the key should only be used to verify the file data
signature, not other keys.

The trusted keys used for verifying other certificates should be stored
on a separate keyring, not the target keyring.   Petko's patches define
a new IMA keyring named .ima_mok for this purpose.

Mimi

> To make this work, we have to retain sufficient data from the X.509
> certificate that we can then verify the signature at need.
> 
> The patches can be found here also:
> 
>   
> http://git.kernel.org/cgit/linux/kernel/git/dhowells/linux-fs.git/log/?h=keys-trust
> 
> and are tagged with:
> 
>   keys-trust-20151021
> 


--
To unsubscribe from this list: send the line "unsubscribe linux-crypto" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH 00/10] KEYS: Change how keys are determined to be trusted

2015-10-21 Thread Mimi Zohar
On Wed, 2015-10-21 at 13:21 -0400, Josh Boyer wrote:
> On Wed, Oct 21, 2015 at 1:02 PM, Mimi Zohar <zo...@linux.vnet.ibm.com> wrote:
> > On Wed, 2015-10-21 at 16:13 +0100, David Howells wrote:
> >> Here's a set of patches that changes how keys are determined to be trusted
> >> - currently, that's a case of whether a key has KEY_FLAG_TRUSTED set upon
> >> it.  A keyring can then have a flag set (KEY_FLAG_TRUSTED ONLY) that
> >> indicates that only keys with this flag set may be added to that keyring.
> >>
> >> Further, any time an X.509 certificate is instantiated without this flag
> >> set, the certificate is judged against the contents of the system trusted
> >> keyring to determine whether KEY_FLAG_TRUSTED should be set upon it.
> >>
> >> With these patches, KEY_FLAG_TRUSTED is removed.  The kernel may add
> >> implicitly trusted keys to a trusted-only keyring by asserting
> >> KEY_ALLOC_TRUSTED when the key is created,
> >
> > Ok, but only the x509 certificates built into the kernel image should be
> > automatically trusted and can be added to a trusted keyring, because the
> > kernel itself was signed (and verified).  These certificates extend the
> > (UEFI) certificate chain of trust that is rooted in hardware to the OS.
> 
> That doesn't sound accurate to me.  The cert built into the kernel
> image doesn't extend the UEFI certificates.  In most cases, it is a
> ephemeral cert that is automatically generated at kernel build time
> and then discarded.  It is not chained to or derived from any of the
> UEFI certs stored in the db (or mok) variables.  The built-in cert is
> used for module loading verification.  I agree that it should be
> trusted, but not really for the reason you list.  Perhaps you meant
> the key that the PE image of the kernel is signed with?  If so, the
> kernel doesn't load that.  Only shim (and grub2 via shim) read that
> key.

This is similar to the concept of the MoK DB.  Keys added to the MoK
aren't signed by a UEFI key, yet they extend the UEFI secure boot
certificate chain of trust.  Similarly, the certificates built into the
kernel image don't need to be signed by a UEFI/MoK key for it to extend
the certificate chain of trust.

> However, that does bring up the UEFI db/mok certs and how to deal with
> those.  The out-of-tree patches we have add them to the system keyring
> as trusted keys.  We can modify the patches to use KEY_ALLOC_TRUSTED
> to preserve that functionality I suppose.

Certificates are use case specific.  Just because a key was trusted at
the UEFI layer doesn't mean it should be trusted by the kernel (eg.
Microsoft key).  To illustrate this point, David Howells/David Woodhouse
recently posted/upstreamed patches to differentiate how keys loaded onto
the system keyring may be used. (Reference needed.)

Mimi

--
To unsubscribe from this list: send the line "unsubscribe linux-crypto" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH 00/10] KEYS: Change how keys are determined to be trusted

2015-10-21 Thread Mimi Zohar
On Wed, 2015-10-21 at 14:21 -0400, Josh Boyer wrote:
> On Wed, Oct 21, 2015 at 2:11 PM, Mimi Zohar <zo...@linux.vnet.ibm.com> wrote:
> > On Wed, 2015-10-21 at 13:21 -0400, Josh Boyer wrote:
> >> On Wed, Oct 21, 2015 at 1:02 PM, Mimi Zohar <zo...@linux.vnet.ibm.com> 
> >> wrote:
> >> > On Wed, 2015-10-21 at 16:13 +0100, David Howells wrote:
> >> >> Here's a set of patches that changes how keys are determined to be 
> >> >> trusted
> >> >> - currently, that's a case of whether a key has KEY_FLAG_TRUSTED set 
> >> >> upon
> >> >> it.  A keyring can then have a flag set (KEY_FLAG_TRUSTED ONLY) that
> >> >> indicates that only keys with this flag set may be added to that 
> >> >> keyring.
> >> >>
> >> >> Further, any time an X.509 certificate is instantiated without this flag
> >> >> set, the certificate is judged against the contents of the system 
> >> >> trusted
> >> >> keyring to determine whether KEY_FLAG_TRUSTED should be set upon it.
> >> >>
> >> >> With these patches, KEY_FLAG_TRUSTED is removed.  The kernel may add
> >> >> implicitly trusted keys to a trusted-only keyring by asserting
> >> >> KEY_ALLOC_TRUSTED when the key is created,
> >> >
> >> > Ok, but only the x509 certificates built into the kernel image should be
> >> > automatically trusted and can be added to a trusted keyring, because the
> >> > kernel itself was signed (and verified).  These certificates extend the
> >> > (UEFI) certificate chain of trust that is rooted in hardware to the OS.
> >>
> >> That doesn't sound accurate to me.  The cert built into the kernel
> >> image doesn't extend the UEFI certificates.  In most cases, it is a
> >> ephemeral cert that is automatically generated at kernel build time
> >> and then discarded.  It is not chained to or derived from any of the
> >> UEFI certs stored in the db (or mok) variables.  The built-in cert is
> >> used for module loading verification.  I agree that it should be
> >> trusted, but not really for the reason you list.  Perhaps you meant
> >> the key that the PE image of the kernel is signed with?  If so, the
> >> kernel doesn't load that.  Only shim (and grub2 via shim) read that
> >> key.
> >
> > This is similar to the concept of the MoK DB.  Keys added to the MoK
> > aren't signed by a UEFI key, yet they extend the UEFI secure boot
> > certificate chain of trust.  Similarly, the certificates built into the
> 
> Right, because UEFI is verifying shim, which verifies grub2, which
> verifies the kernel.  I get that.  However, it's irrelevant.
> 
> > kernel image don't need to be signed by a UEFI/MoK key for it to extend
> > the certificate chain of trust.
> 
> The certificates built _into_ the kernel need to be trusted in all
> cases.  It is how module signing is done.  So a user not using Secure
> Boot, or even not using UEFI, still needs those embedded certs trusted
> so that they can load modules.  It has nothing to do with UEFI or some
> single-root-of-trust.
> 
> At any rate, I believe we are both saying the embedded cert needs to
> be trusted so there's little point in debating further.  I just wanted
> to point out that this need has nothing to do with UEFI.

Right, the embedded certs need to trusted.  But that trust needs to be
based on something.  One method of establishing that trust is (UEFI)
secure boot, which verifies the kernel image signature, including the
embedded certs.

Mimi

--
To unsubscribe from this list: send the line "unsubscribe linux-crypto" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v3 1/3] ima: use ahash API for file hash calculation

2014-07-07 Thread Mimi Zohar
On Fri, 2014-07-04 at 15:05 +0300, Dmitry Kasatkin wrote: 
 Async hash API allows to use HW acceleration for hash calculation.
 It may give significant performance gain or/and reduce power consumption,
 which might be very beneficial for battery powered devices.
 
 This patch introduces hash calculation using ahash API.
 
 ahash performance depends on data size and particular HW. Under certain
 limit, depending on the system, shash performance may be better.
 
 This patch defines 'ahash_minsize' module parameter which can be used to
 define minimal file size to use with ahash. When file size is not set
 or smaller than defined by the parameter, shash will be used.
 
 Changes in v3:
 - kernel parameter replaced with module parameter
 - pr_crit replaced with pr_crit_ratelimited
 
 Changes in v2:
 - ima_ahash_size became as ima_ahash
 - ahash pre-allocation moved out from __init code to be able to use
   ahash crypto modules. Ahash allocated once on the first use.
 - hash calculation falls back to shash if ahash allocation/calculation fails
 - complex initialization separated from variable declaration
 - improved comments
 
 Signed-off-by: Dmitry Kasatkin d.kasat...@samsung.com
 ---
  Documentation/kernel-parameters.txt |   9 ++
  security/integrity/ima/ima_crypto.c | 185 
 +++-
  2 files changed, 190 insertions(+), 4 deletions(-)
 
 diff --git a/Documentation/kernel-parameters.txt 
 b/Documentation/kernel-parameters.txt
 index 5a214a3..03c8452 100644
 --- a/Documentation/kernel-parameters.txt
 +++ b/Documentation/kernel-parameters.txt
 @@ -1318,6 +1318,15 @@ bytes respectively. Such letter suffixes can also be 
 entirely omitted.
   Formats: { ima | ima-ng }
   Default: ima-ng
 
 + ima.ahash_minsize= [IMA] Minimum file size for asynchronous hash usage
 + Format: min_file_size
 + Set the minimal file size for using asynchronous hash.
 + If left unspecified, ahash usage is disabled.
 +
 + ahash performance varies for different data sizes on
 + different crypto accelerators. This option can be used
 + to achieve best performance for particular HW.
 +
   init=   [KNL]
   Format: full_path
   Run specified binary instead of /sbin/init as init
 diff --git a/security/integrity/ima/ima_crypto.c 
 b/security/integrity/ima/ima_crypto.c
 index f82d1d7..bc38160 100644
 --- a/security/integrity/ima/ima_crypto.c
 +++ b/security/integrity/ima/ima_crypto.c
 @@ -16,6 +16,8 @@
  #define pr_fmt(fmt) KBUILD_MODNAME :  fmt
 
  #include linux/kernel.h
 +#include linux/moduleparam.h
 +#include linux/ratelimit.h
  #include linux/file.h
  #include linux/crypto.h
  #include linux/scatterlist.h
 @@ -25,7 +27,18 @@
  #include crypto/hash_info.h
  #include ima.h
 
 +struct ahash_completion {
 + struct completion completion;
 + int err;
 +};
 +
 +/* minimum file size for ahash use */
 +static unsigned long ima_ahash_minsize;
 +module_param_named(ahash_minsize, ima_ahash_minsize, ulong, 0644);
 +MODULE_PARM_DESC(ahash_minsize, Minimum file size for ahash use);
 +
  static struct crypto_shash *ima_shash_tfm;
 +static struct crypto_ahash *ima_ahash_tfm;
 
  /**
   * ima_kernel_read - read file content
 @@ -93,9 +106,146 @@ static void ima_free_tfm(struct crypto_shash *tfm)
   crypto_free_shash(tfm);
  }
 
 -/*
 - * Calculate the MD5/SHA1 file digest
 - */
 +static struct crypto_ahash *ima_alloc_atfm(enum hash_algo algo)
 +{
 + struct crypto_ahash *tfm = ima_ahash_tfm;
 + int rc;
 +
 + if ((algo != ima_hash_algo  algo  HASH_ALGO__LAST) || !tfm) {
 + tfm = crypto_alloc_ahash(hash_algo_name[algo], 0, 0);
 + if (!IS_ERR(tfm)) {
 + if (algo == ima_hash_algo)
 + ima_ahash_tfm = tfm;
 + } else {
 + rc = PTR_ERR(tfm);
 + pr_err(Can not allocate %s (reason: %d)\n,
 +hash_algo_name[algo], rc);
 + }
 + }
 + return tfm;
 +}
 +
 +static void ima_free_atfm(struct crypto_ahash *tfm)
 +{
 + if (tfm != ima_ahash_tfm)
 + crypto_free_ahash(tfm);
 +}
 +
 +static void ahash_complete(struct crypto_async_request *req, int err)
 +{
 + struct ahash_completion *res = req-data;
 +
 + if (err == -EINPROGRESS)
 + return;
 + res-err = err;
 + complete(res-completion);
 +}
 +
 +static int ahash_wait(int err, struct ahash_completion *res)
 +{
 + switch (err) {
 + case 0:
 + break;
 + case -EINPROGRESS:
 + case -EBUSY:
 + wait_for_completion(res-completion);
 + reinit_completion(res-completion);
 + err = res-err;
 + /* fall through */
 + default:
 + pr_crit_ratelimited(ahash calculation failed: 

Re: [PATCH v3 1/3] ima: use ahash API for file hash calculation

2014-07-07 Thread Mimi Zohar
On Mon, 2014-07-07 at 16:37 +0300, Dmitry Kasatkin wrote: 
 On 07/07/14 14:56, Mimi Zohar wrote:
  On Fri, 2014-07-04 at 15:05 +0300, Dmitry Kasatkin wrote: 

 
  +/**
  This is the kernel-doc delimiter.
 
  + * ima_calc_file_hash - calculae file hash
  + *
  Missing kernel-doc argument descriptions.  Refer to
  Documentation/kernel-doc-nano-HOWTO.txt.

Not defining the arguments results in a kernel-doc warning.  Providing
kernel-doc is nice, but is unnecessary in this case, as it isn't an
exported loadable module, nor an externally visible function to other
kernel files.  Either remove the extra asterisk, making it a regular
comment, or add the arguments.

 
 There is no need to explain arguments as they self-evident.
 
  + * if ima_ahash_minsize parameter is non-zero, this function uses
  + * ahash for hash caclulation. ahash performance varies for different
  + * data sizes on different crypto accelerators. shash performance might
  + * be better for small file. 'ima.ahash_minsize' module parameter allows
  + * to specify the best value for the system.
  + *
  + * If ahash fails, it fallbacks to shash.
  + */
  +int ima_calc_file_hash(struct file *file, struct ima_digest_data *hash)
  +{
  +  loff_t i_size;
  +  int rc;
  +
  +  i_size = i_size_read(file_inode(file));
  +
  +  if (ima_ahash_minsize  i_size = ima_ahash_minsize) {
  +  rc = ima_calc_file_ahash(file, hash);
  +  if (!rc)
  +  return 0;
  +  }
  +
  +  return ima_calc_file_shash(file, hash);
  +}
  If the crypto accelerator fails, it falls back to using shash.  Is their
  any indication that the HW error is intermittent or persistent?  Should
  ima_ahash_minsize be reset?
 
 If hw constantly does not work then it is simply broken.

True

 You want to be protected from random failures.

 For me it is not the case either... If it works then it works...

This discussion isn't about your particular HW environment, but a
general question.  For example, suppose we were discussing a laptop with
a HW crypto accelerator.  If the HW crypto broke, I would at least want
to be able to quiesce the system properly.  I'd most likely want to be
able to continue using my laptop with software crypto.

  If the crypto accelerator, built as a kernel module, is removed,
  ima_ahash_minsize would still be set.  It would continue to use ahash.
  Is this the correct behavior? Or should ima_ahash_minsize be reset?
 
 
 It cannot be removed, because it is used and module usage counter
 protects from removing...

Ok

Mimi

--
To unsubscribe from this list: send the line unsubscribe linux-crypto in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v3 1/3] ima: use ahash API for file hash calculation

2014-07-07 Thread Mimi Zohar
On Mon, 2014-07-07 at 19:11 +0300, Dmitry Kasatkin wrote: 
 On 07/07/14 18:44, Mimi Zohar wrote:
  On Mon, 2014-07-07 at 16:37 +0300, Dmitry Kasatkin wrote: 
  On 07/07/14 14:56, Mimi Zohar wrote:
  On Fri, 2014-07-04 at 15:05 +0300, Dmitry Kasatkin wrote: 
  +/**
  This is the kernel-doc delimiter.
 
  + * ima_calc_file_hash - calculae file hash
  + *
  Missing kernel-doc argument descriptions.  Refer to
  Documentation/kernel-doc-nano-HOWTO.txt.
  Not defining the arguments results in a kernel-doc warning.  Providing
  kernel-doc is nice, but is unnecessary in this case, as it isn't an
  exported loadable module, nor an externally visible function to other
  kernel files.  Either remove the extra asterisk, making it a regular
  comment, or add the arguments.
 
  There is no need to explain arguments as they self-evident.
 
  + * if ima_ahash_minsize parameter is non-zero, this function uses
  + * ahash for hash caclulation. ahash performance varies for different
  + * data sizes on different crypto accelerators. shash performance might
  + * be better for small file. 'ima.ahash_minsize' module parameter allows
  + * to specify the best value for the system.
  + *
  + * If ahash fails, it fallbacks to shash.
  + */
  +int ima_calc_file_hash(struct file *file, struct ima_digest_data *hash)
  +{
  +loff_t i_size;
  +int rc;
  +
  +i_size = i_size_read(file_inode(file));
  +
  +if (ima_ahash_minsize  i_size = ima_ahash_minsize) {
  +rc = ima_calc_file_ahash(file, hash);
  +if (!rc)
  +return 0;
  +}
  +
  +return ima_calc_file_shash(file, hash);
  +}
  If the crypto accelerator fails, it falls back to using shash.  Is their
  any indication that the HW error is intermittent or persistent?  Should
  ima_ahash_minsize be reset?
  If hw constantly does not work then it is simply broken.
  True
 
  You want to be protected from random failures.
  For me it is not the case either... If it works then it works...
  This discussion isn't about your particular HW environment, but a
  general question.  For example, suppose we were discussing a laptop with
  a HW crypto accelerator.  If the HW crypto broke, I would at least want
  to be able to quiesce the system properly.  I'd most likely want to be
  able to continue using my laptop with software crypto.
 
 Driver probing code will detect that HW is not responding and driver
 will not be enabled...
 
 IMA will not be able to use it...
 
 It is the same story as with any other HW and driver in the system.

Right, but my concern is not about unloading the kernel module, but
about the IMA module parameters left initialized.  The existing code
will continue using ahash (software version), even though the kernel
module was unloaded, not shash.  My question is about the software
implementations of ahash vs. shash performance.

Mimi

--
To unsubscribe from this list: send the line unsubscribe linux-crypto in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v2 1/3] ima: use ahash API for file hash calculation

2014-07-02 Thread Mimi Zohar
On Tue, 2014-07-01 at 23:12 +0300, Dmitry Kasatkin wrote: 
 Async hash API allows to use HW acceleration for hash calculation.
 It may give significant performance gain or/and reduce power consumption,
 which might be very beneficial for battery powered devices.
 
 This patch introduces hash calculation using ahash API.
 
 ahash performance depends on data size and particular HW. Under certain
 limit, depending on the system, shash performance may be better.
 
 This patch defines 'ima_ahash' kernel parameter which can be used to
 define minimal file size to use with ahash. When file size is not set
 or smaller than defined by the parameter, shash will be used.

Thank you for the updated patches. The changes should be listed here in
the patch description.

I keep going back and forth as to whether the ahash routines should be
totally separate, as posted, from the shash routines.  Having separate
functions is very clear/clean, but there is quite a bit of code
duplication (eg. ima_calc_file_hash()/ima_calc_file_ahash(),
ima_free_tfm()/ima_free_atfm(), ima_alloc_tfm()/ima_alloc_atfm()).

Soliciting comments ...

 Signed-off-by: Dmitry Kasatkin d.kasat...@samsung.com

 ---
  Documentation/kernel-parameters.txt |   5 +
  security/integrity/ima/ima_crypto.c | 185 
 +++-
  2 files changed, 186 insertions(+), 4 deletions(-)
 
 diff --git a/Documentation/kernel-parameters.txt 
 b/Documentation/kernel-parameters.txt
 index 5a214a3..b406f5c 100644
 --- a/Documentation/kernel-parameters.txt
 +++ b/Documentation/kernel-parameters.txt
 @@ -1291,6 +1291,11 @@ bytes respectively. Such letter suffixes can also be 
 entirely omitted.
   ihash_entries=  [KNL]
   Set number of hash buckets for inode cache.
 
 + ima_ahash=  [IMA] Asynchronous hash usage parameters
 + Format: min_file_size
 + Set the minimal file size when use asynchronous hash.
 + If ima_ahash is not provided, ahash usage is disabled.
 +
   ima_appraise=   [IMA] appraise integrity measurements
   Format: { off | enforce | fix }
   default: enforce
 diff --git a/security/integrity/ima/ima_crypto.c 
 b/security/integrity/ima/ima_crypto.c
 index f82d1d7..5eb19b4 100644
 --- a/security/integrity/ima/ima_crypto.c
 +++ b/security/integrity/ima/ima_crypto.c
 @@ -25,7 +25,27 @@
  #include crypto/hash_info.h
  #include ima.h
 
 +

Extra blank line not needed.

 +struct ahash_completion {
 + struct completion completion;
 + int err;
 +};
 +
  static struct crypto_shash *ima_shash_tfm;
 +static struct crypto_ahash *ima_ahash_tfm;
 +
 +/* minimal file size for ahash use */
 +static loff_t ima_ahash_size;
 +
 +static int __init ima_ahash_setup(char *str)
 +{
 + int rc;
 +
 + rc = kstrtoll(str, 10, ima_ahash_size);
 +
 + return !rc;
 +}
 +__setup(ima_ahash=, ima_ahash_setup);
 
  /**
   * ima_kernel_read - read file content
 @@ -93,9 +113,146 @@ static void ima_free_tfm(struct crypto_shash *tfm)
   crypto_free_shash(tfm);
  }
 
 -/*
 - * Calculate the MD5/SHA1 file digest
 - */
 +static struct crypto_ahash *ima_alloc_atfm(enum hash_algo algo)
 +{
 + struct crypto_ahash *tfm = ima_ahash_tfm;
 + int rc;
 +
 + if ((algo != ima_hash_algo  algo  HASH_ALGO__LAST) || !tfm) {
 + tfm = crypto_alloc_ahash(hash_algo_name[algo], 0, 0);
 + if (!IS_ERR(tfm)) {
 + if (algo == ima_hash_algo)
 + ima_ahash_tfm = tfm;
 + } else {
 + rc = PTR_ERR(tfm);
 + pr_err(Can not allocate %s (reason: %d)\n,
 +hash_algo_name[algo], rc);
 + }
 + }
 + return tfm;
 +}
 +
 +static void ima_free_atfm(struct crypto_ahash *tfm)
 +{
 + if (tfm != ima_ahash_tfm)
 + crypto_free_ahash(tfm);
 +}
 +
 +static void ahash_complete(struct crypto_async_request *req, int err)
 +{
 + struct ahash_completion *res = req-data;
 +
 + if (err == -EINPROGRESS)
 + return;
 + res-err = err;
 + complete(res-completion);
 +}
 +
 +static int ahash_wait(int err, struct ahash_completion *res)
 +{
 + switch (err) {
 + case 0:
 + break;
 + case -EINPROGRESS:
 + case -EBUSY:
 + wait_for_completion(res-completion);
 + reinit_completion(res-completion);
 + err = res-err;
 + /* fall through */
 + default:
 + pr_crit(ahash calculation failed: err: %d\n, err);
 + }
 +
 + return err;
 +}
 +
 +static int ima_calc_file_hash_atfm(struct file *file,
 +struct ima_digest_data *hash,
 +struct crypto_ahash *tfm)
 +{
 + loff_t i_size, offset;
 + char *rbuf;
 + int rc, read = 0, rbuf_len;
 + struct ahash_request *req;
 + struct scatterlist sg[1];
 + 

Re: [PATCH v2 1/3] ima: use ahash API for file hash calculation

2014-07-02 Thread Mimi Zohar
On Tue, 2014-07-01 at 23:12 +0300, Dmitry Kasatkin wrote:

 -/*
 - * Calculate the MD5/SHA1 file digest
 - */
 +static struct crypto_ahash *ima_alloc_atfm(enum hash_algo algo)
 +{
 + struct crypto_ahash *tfm = ima_ahash_tfm;
 + int rc;
 +
 + if ((algo != ima_hash_algo  algo  HASH_ALGO__LAST) || !tfm) {
 + tfm = crypto_alloc_ahash(hash_algo_name[algo], 0, 0);

In the case where algo isn't the same as ima_hash_algo, won't this
replace the existing ima_ahash_tfm without freeing it?

Mimi

 + if (!IS_ERR(tfm)) {
 + if (algo == ima_hash_algo)
 + ima_ahash_tfm = tfm;
 + } else {
 + rc = PTR_ERR(tfm);
 + pr_err(Can not allocate %s (reason: %d)\n,
 +hash_algo_name[algo], rc);
 + }
 + }
 + return tfm;
 +}
 +
 +static void ima_free_atfm(struct crypto_ahash *tfm)
 +{
 + if (tfm != ima_ahash_tfm)
 + crypto_free_ahash(tfm);
 +}



--
To unsubscribe from this list: send the line unsubscribe linux-crypto in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v2 1/3] ima: use ahash API for file hash calculation

2014-07-02 Thread Mimi Zohar
On Wed, 2014-07-02 at 21:20 +0300, Dmitry Kasatkin wrote: 
 On 2 July 2014 19:40, Mimi Zohar zo...@linux.vnet.ibm.com wrote:
  On Tue, 2014-07-01 at 23:12 +0300, Dmitry Kasatkin wrote:
  Async hash API allows to use HW acceleration for hash calculation.
  It may give significant performance gain or/and reduce power consumption,
  which might be very beneficial for battery powered devices.
 
  This patch introduces hash calculation using ahash API.
 
  ahash performance depends on data size and particular HW. Under certain
  limit, depending on the system, shash performance may be better.
 
  This patch defines 'ima_ahash' kernel parameter which can be used to
  define minimal file size to use with ahash. When file size is not set
  or smaller than defined by the parameter, shash will be used.
 
  Thank you for the updated patches. The changes should be listed here in
  the patch description.
 
  I keep going back and forth as to whether the ahash routines should be
  totally separate, as posted, from the shash routines.  Having separate
  functions is very clear/clean, but there is quite a bit of code
  duplication (eg. ima_calc_file_hash()/ima_calc_file_ahash(),
  ima_free_tfm()/ima_free_atfm(), ima_alloc_tfm()/ima_alloc_atfm()).
 
  Soliciting comments ...
 
 
 I think what you say is a pattern: alloc/calc/free.
 But the code uses different API mostly and there very small duplication...
 
 In fact with this 'clean' separation we can have CONFIG_ option to
 ifdef the code ot have it in separate file for those who really want
 to make smallest kernel possible...

Ok, this is an acceptable reason.

thanks,

Mimi

 
  Signed-off-by: Dmitry Kasatkin d.kasat...@samsung.com
 
  ---
   Documentation/kernel-parameters.txt |   5 +
   security/integrity/ima/ima_crypto.c | 185 
  +++-
   2 files changed, 186 insertions(+), 4 deletions(-)
 
  diff --git a/Documentation/kernel-parameters.txt 
  b/Documentation/kernel-parameters.txt
  index 5a214a3..b406f5c 100644
  --- a/Documentation/kernel-parameters.txt
  +++ b/Documentation/kernel-parameters.txt
  @@ -1291,6 +1291,11 @@ bytes respectively. Such letter suffixes can also 
  be entirely omitted.
ihash_entries=  [KNL]
Set number of hash buckets for inode cache.
 
  + ima_ahash=  [IMA] Asynchronous hash usage parameters
  + Format: min_file_size
  + Set the minimal file size when use asynchronous hash.
  + If ima_ahash is not provided, ahash usage is 
  disabled.
  +
ima_appraise=   [IMA] appraise integrity measurements
Format: { off | enforce | fix }
default: enforce
  diff --git a/security/integrity/ima/ima_crypto.c 
  b/security/integrity/ima/ima_crypto.c
  index f82d1d7..5eb19b4 100644
  --- a/security/integrity/ima/ima_crypto.c
  +++ b/security/integrity/ima/ima_crypto.c
  @@ -25,7 +25,27 @@
   #include crypto/hash_info.h
   #include ima.h
 
  +
 
  Extra blank line not needed.
 
  +struct ahash_completion {
  + struct completion completion;
  + int err;
  +};
  +
   static struct crypto_shash *ima_shash_tfm;
  +static struct crypto_ahash *ima_ahash_tfm;
  +
  +/* minimal file size for ahash use */
  +static loff_t ima_ahash_size;
  +
  +static int __init ima_ahash_setup(char *str)
  +{
  + int rc;
  +
  + rc = kstrtoll(str, 10, ima_ahash_size);
  +
  + return !rc;
  +}
  +__setup(ima_ahash=, ima_ahash_setup);
 
   /**
* ima_kernel_read - read file content
  @@ -93,9 +113,146 @@ static void ima_free_tfm(struct crypto_shash *tfm)
crypto_free_shash(tfm);
   }
 
  -/*
  - * Calculate the MD5/SHA1 file digest
  - */
  +static struct crypto_ahash *ima_alloc_atfm(enum hash_algo algo)
  +{
  + struct crypto_ahash *tfm = ima_ahash_tfm;
  + int rc;
  +
  + if ((algo != ima_hash_algo  algo  HASH_ALGO__LAST) || !tfm) {
  + tfm = crypto_alloc_ahash(hash_algo_name[algo], 0, 0);
  + if (!IS_ERR(tfm)) {
  + if (algo == ima_hash_algo)
  + ima_ahash_tfm = tfm;
  + } else {
  + rc = PTR_ERR(tfm);
  + pr_err(Can not allocate %s (reason: %d)\n,
  +hash_algo_name[algo], rc);
  + }
  + }
  + return tfm;
  +}
  +
  +static void ima_free_atfm(struct crypto_ahash *tfm)
  +{
  + if (tfm != ima_ahash_tfm)
  + crypto_free_ahash(tfm);
  +}
  +
  +static void ahash_complete(struct crypto_async_request *req, int err)
  +{
  + struct ahash_completion *res = req-data;
  +
  + if (err == -EINPROGRESS)
  + return;
  + res-err = err;
  + complete(res-completion);
  +}
  +
  +static int ahash_wait(int err, struct ahash_completion *res)
  +{
  + switch (err) {
  + case 0:
  + break;
  + case -EINPROGRESS:
  + case -EBUSY

Re: [PATCH v2 1/3] ima: use ahash API for file hash calculation

2014-07-02 Thread Mimi Zohar
On Wed, 2014-07-02 at 21:21 +0300, Dmitry Kasatkin wrote: 
 On 2 July 2014 20:44, Mimi Zohar zo...@linux.vnet.ibm.com wrote:
  On Tue, 2014-07-01 at 23:12 +0300, Dmitry Kasatkin wrote:
 
  -/*
  - * Calculate the MD5/SHA1 file digest
  - */
  +static struct crypto_ahash *ima_alloc_atfm(enum hash_algo algo)
  +{
  + struct crypto_ahash *tfm = ima_ahash_tfm;
  + int rc;
  +
  + if ((algo != ima_hash_algo  algo  HASH_ALGO__LAST) || !tfm) {
  + tfm = crypto_alloc_ahash(hash_algo_name[algo], 0, 0);
 
  In the case where algo isn't the same as ima_hash_algo, won't this
  replace the existing ima_ahash_tfm without freeing it?
 
 
 Look to next comment...

Yep, my mistake in reading the code.

Mimi

--
To unsubscribe from this list: send the line unsubscribe linux-crypto in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v2 2/3] ima: introduce multi-page collect buffers

2014-07-02 Thread Mimi Zohar
On Tue, 2014-07-01 at 23:12 +0300, Dmitry Kasatkin wrote: 
 Use of multiple-page collect buffers reduces:
 1) the number of block IO requests
 2) the number of asynchronous hash update requests
 
 Second is important for HW accelerated hashing, because significant
 amount of time is spent for preparation of hash update operation,
 which includes configuring acceleration HW, DMA engine, etc...
 Thus, HW accelerators are more efficient when working on large
 chunks of data.
 
 This patch introduces usage of multi-page collect buffers. Buffer size
 can be specified by providing additional option to the 'ima_ahash='
 kernel parameter. 'ima_ahash=2048,16384' specifies that minimal file
 size to use ahash is 2048 byes and buffer size is 16384 bytes.
 Default buffer size is 4096 bytes.
 
 Signed-off-by: Dmitry Kasatkin d.kasat...@samsung.com
 ---
  Documentation/kernel-parameters.txt |  3 +-
  security/integrity/ima/ima_crypto.c | 85 
 ++---
  2 files changed, 81 insertions(+), 7 deletions(-)
 
 diff --git a/Documentation/kernel-parameters.txt 
 b/Documentation/kernel-parameters.txt
 index b406f5c..529ba58 100644
 --- a/Documentation/kernel-parameters.txt
 +++ b/Documentation/kernel-parameters.txt
 @@ -1292,9 +1292,10 @@ bytes respectively. Such letter suffixes can also be 
 entirely omitted.
   Set number of hash buckets for inode cache.
 
   ima_ahash=  [IMA] Asynchronous hash usage parameters
 - Format: min_file_size
 + Format: min_file_size[,bufsize]
   Set the minimal file size when use asynchronous hash.
   If ima_ahash is not provided, ahash usage is disabled.
 + bufsize - hashing buffer size. 4k if not specified.
 
   ima_appraise=   [IMA] appraise integrity measurements
   Format: { off | enforce | fix }
 diff --git a/security/integrity/ima/ima_crypto.c 
 b/security/integrity/ima/ima_crypto.c
 index 5eb19b4..41f2695 100644
 --- a/security/integrity/ima/ima_crypto.c
 +++ b/security/integrity/ima/ima_crypto.c
 @@ -25,7 +25,6 @@
  #include crypto/hash_info.h
  #include ima.h
 
 -
  struct ahash_completion {
   struct completion completion;
   int err;
 @@ -36,14 +35,24 @@ static struct crypto_ahash *ima_ahash_tfm;
 
  /* minimal file size for ahash use */
  static loff_t ima_ahash_size;
 +/* default is 0 - 1 page. */
 +static int ima_max_order;
 
  static int __init ima_ahash_setup(char *str)
  {
 - int rc;
 + int ints[3] = { 0, };
 +
 + str = get_options(str, ARRAY_SIZE(ints), ints);
 + if (!ints[0])
 + return 0;
 +
 + ima_ahash_size = ints[1];
 + ima_max_order = get_order(ints[2]);

get_options() returns the number of options processed in ints[0].
Before assigning ima_max_order, we normally check to see if it exists.
I guess in this case it doesn't matter since it would return 0 anyway.

Should there be any value checking here?  Should the values be some
multiple of 1024?

 
 - rc = kstrtoll(str, 10, ima_ahash_size);
 + pr_info(ima_ahash: minsize=%lld, bufsize=%lu\n,
 + ima_ahash_size, (PAGE_SIZE  ima_max_order));
 
 - return !rc;
 + return 1;
  }
  __setup(ima_ahash=, ima_ahash_setup);
 
 @@ -166,6 +175,65 @@ static int ahash_wait(int err, struct ahash_completion 
 *res)
   return err;
  }
 
 +/**
 + * ima_alloc_pages() - Allocated contiguous pages.
 + * @max_size:   Maximum amount of memory to allocate.
 + * @allocated_size: Returned size of actual allocation.
 + * @last_warn:  Should the min_size allocation warn or not.
 + *
 + * Tries to do opportunistic allocation for memory first trying to allocate
 + * max_size amount of memory and then splitting that until zero order is
 + * reached. Allocation is tried without generating allocation warnings unless
 + * last_warn is set. Last_warn set affects only last allocation of zero 
 order.
 + *
 + * Return pointer to allocated memory, or NULL on failure.
 + */
 +static void *ima_alloc_pages(loff_t max_size, size_t *allocated_size,
 +  int last_warn)
 +{
 + void *ptr;
 + unsigned int order;
 + gfp_t gfp_mask = __GFP_NOWARN | __GFP_WAIT | __GFP_NORETRY;
 +
 + order = min(get_order(max_size), ima_max_order);
 +
 + for (; order; order--) {
 + ptr = (void *)__get_free_pages(gfp_mask, order);
 + if (ptr) {
 + *allocated_size = PAGE_SIZE  order;
 + return ptr;
 + }
 + }
 +
 + /* order is zero - one page */
 +
 + gfp_mask = GFP_KERNEL;
 +
 + if (!last_warn)
 + gfp_mask |= __GFP_NOWARN;
 +
 + ptr = (void *)__get_free_pages(gfp_mask, 0);
 + if (ptr) {
 + *allocated_size = PAGE_SIZE;
 + return ptr;
 + }
 +
 + *allocated_size = 0;
 + return NULL;
 +}
 +
 +/**
 + * ima_free_pages() - Free pages allocated by 

Re: [PATCH v1 1/3] ima: use ahash API for file hash calculation

2014-06-30 Thread Mimi Zohar
On Mon, 2014-06-30 at 17:58 +0300, Dmitry Kasatkin wrote: 
 On 26/06/14 14:54, Mimi Zohar wrote:
  On Thu, 2014-06-19 at 18:20 +0300, Dmitry Kasatkin wrote:

  @@ -156,7 +316,7 @@ out:
 return rc;
   }
 
  -int ima_calc_file_hash(struct file *file, struct ima_digest_data *hash)
  +static int ima_calc_file_shash(struct file *file, struct ima_digest_data 
  *hash)
   {
 struct crypto_shash *tfm;
 int rc;
  @@ -172,6 +332,20 @@ int ima_calc_file_hash(struct file *file, struct 
  ima_digest_data *hash)
 return rc;
   }
 
  +int ima_calc_file_hash(struct file *file, struct ima_digest_data *hash)
  +{
  +  loff_t i_size = i_size_read(file_inode(file));
  +
  +  /* shash is more efficient small data
  +   * ahash performance depends on data size and particular HW
  +   * ima_ahash_size allows to specify the best value for the system
  +   */
  +  if (ima_ahash_size  i_size = ima_ahash_size)
  +  return ima_calc_file_ahash(file, hash);
  +  else
  +  return ima_calc_file_shash(file, hash);
  +}
  If calculating the file hash using ahash fails, should it fall back to
  using shash?
 
 If ahash fails, then it could be a HW error, which should not happen.
 IF HW fails device is broken.

I would assume it depends on the HW, if the entire device/system is
broken.

 Do you really want to fallback to shash?

Yes, in this case, there is no downside to letting it to continue
working, just slower, using the software crypto implementation.  In any
case, it shouldn't be hard coded.

Mimi

--
To unsubscribe from this list: send the line unsubscribe linux-crypto in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v1 1/3] ima: use ahash API for file hash calculation

2014-06-26 Thread Mimi Zohar
On Thu, 2014-06-19 at 18:20 +0300, Dmitry Kasatkin wrote:
 Async hash API allows to use HW acceleration for hash calculation.
 It may give significant performance gain or/and reduce power consumption,
 which might be very beneficial for battery powered devices.
 
 This patch introduces hash calculation using ahash API.
 
 ahash peformance depends on data size and particular HW. Under certain
 limit, depending on the system, shash performance may be better.
 
 This patch also introduces 'ima_ahash_size' kernel parameter which can
 be used to defines minimal data size to use with ahash. When this
 parameter is not set or file size is smaller than defined by this
 parameter, shash will be used. Thus, by defult, original shash
 implementation is used.
 
 Signed-off-by: Dmitry Kasatkin d.kasat...@samsung.com
 ---
  Documentation/kernel-parameters.txt |   3 +
  security/integrity/ima/ima_crypto.c | 182 
 +++-
  2 files changed, 181 insertions(+), 4 deletions(-)
 
 diff --git a/Documentation/kernel-parameters.txt 
 b/Documentation/kernel-parameters.txt
 index a0c155c..f8efb01 100644
 --- a/Documentation/kernel-parameters.txt
 +++ b/Documentation/kernel-parameters.txt
 @@ -1286,6 +1286,9 @@ bytes respectively. Such letter suffixes can also be 
 entirely omitted.
   ihash_entries=  [KNL]
   Set number of hash buckets for inode cache.
 
 + ima_ahash_size=size [IMA]
 + Set the minimal file size when use ahash API.
 +
   ima_appraise=   [IMA] appraise integrity measurements
   Format: { off | enforce | fix }
   default: enforce
 diff --git a/security/integrity/ima/ima_crypto.c 
 b/security/integrity/ima/ima_crypto.c
 index ccd0ac8..b7a8650 100644
 --- a/security/integrity/ima/ima_crypto.c
 +++ b/security/integrity/ima/ima_crypto.c
 @@ -25,7 +25,25 @@
  #include crypto/hash_info.h
  #include ima.h
 
 +
 +struct ahash_completion {
 + struct completion completion;
 + int err;
 +};
 +
  static struct crypto_shash *ima_shash_tfm;
 +static struct crypto_ahash *ima_ahash_tfm;
 +
 +/* data size for ahash use */
 +static loff_t ima_ahash_size;
 +
 +static int __init ima_ahash_setup(char *str)
 +{
 + int rc = kstrtoll(str, 10, ima_ahash_size);

In general, variable definitions should be separated from code.  A
simple initialization is fine.  Please separate variable definitions
from code with a blank line. 

 + pr_info(ima_ahash_size = %lld\n, ima_ahash_size);
 + return !rc;
 +}
 +__setup(ima_ahash_size=, ima_ahash_setup);

This boot parameter name doesn't reflect its purpose, defining the
minimum file size for using ahash. The next patch defines an additional
boot parameter ima_ahash_bufsize. Perhaps defining a single boot
parameter (eg. ima_ahash=) with multiple fields would be better. 

  /**
   * ima_kernel_read - read file content
 @@ -68,6 +86,14 @@ int ima_init_crypto(void)
  hash_algo_name[ima_hash_algo], rc);
   return rc;
   }
 + ima_ahash_tfm = crypto_alloc_ahash(hash_algo_name[ima_hash_algo], 0, 0);
 + if (IS_ERR(ima_ahash_tfm)) {
 + rc = PTR_ERR(ima_ahash_tfm);
 + crypto_free_shash(ima_shash_tfm);

Only crypto_alloc_ahash() failed, not crypto_alloc_shash(). shash has
worked fine up to now. Why require both shash and ahash to succeed? 

 + pr_err(Can not allocate %s (reason: %ld)\n,
 +hash_algo_name[ima_hash_algo], rc);
 + return rc;
 + }
   return 0;
  }
 

 @@ -93,9 +119,143 @@ static void ima_free_tfm(struct crypto_shash *tfm)
   crypto_free_shash(tfm);
  }
 
 -/*
 - * Calculate the MD5/SHA1 file digest
 - */
 +static struct crypto_ahash *ima_alloc_atfm(enum hash_algo algo)
 +{
 + struct crypto_ahash *tfm = ima_ahash_tfm;
 + int rc;
 +
 + if (algo != ima_hash_algo  algo  HASH_ALGO__LAST) {
 + tfm = crypto_alloc_ahash(hash_algo_name[algo], 0, 0);
 + if (IS_ERR(tfm)) {
 + rc = PTR_ERR(tfm);
 + pr_err(Can not allocate %s (reason: %d)\n,
 +hash_algo_name[algo], rc);
 + }
 + }
 + return tfm;
 +}
 +
 +static void ima_free_atfm(struct crypto_ahash *tfm)
 +{
 + if (tfm != ima_ahash_tfm)
 + crypto_free_ahash(tfm);
 +}
 +
 +static void ahash_complete(struct crypto_async_request *req, int err)
 +{
 + struct ahash_completion *res = req-data;
 +
 + if (err == -EINPROGRESS)
 + return;
 + res-err = err;
 + complete(res-completion);
 +}
 +
 +static int ahash_wait(int err, struct ahash_completion *res)
 +{
 + switch (err) {
 + case 0:
 + break;
 + case -EINPROGRESS:
 + case -EBUSY:
 + wait_for_completion(res-completion);
 + reinit_completion(res-completion);
 + err = res-err;
 + /* fall through */
 + default:
 +

Re: [PATCH v1 3/3] ima: provide double buffering for hash calculation

2014-06-26 Thread Mimi Zohar

On Thu, 2014-06-19 at 18:20 +0300, Dmitry Kasatkin wrote:
 Asynchronous hash API allows initiate hash calculation and perform
 other tasks while hash is calculated.
 
 This patch introduces usage of double buffering for simultenous
^simultaneous
 hashing and reading of the next chunk of data from the storage.
 
 Signed-off-by: Dmitry Kasatkin d.kasat...@samsung.com
 ---
  security/integrity/ima/ima_crypto.c | 59 
 +++--
  1 file changed, 43 insertions(+), 16 deletions(-)
 
 diff --git a/security/integrity/ima/ima_crypto.c 
 b/security/integrity/ima/ima_crypto.c
 index 9e9414e..e6bef4b 100644
 --- a/security/integrity/ima/ima_crypto.c
 +++ b/security/integrity/ima/ima_crypto.c
 @@ -244,12 +244,12 @@ static int ima_calc_file_hash_atfm(struct file *file,
  struct crypto_ahash *tfm)
  {
   loff_t i_size, offset;
 - char *rbuf;
 - int rc, read = 0, rbuf_len;
 + char *rbuf[2] = { NULL, };
 + int rc, read = 0, rbuf_len, active = 0, ahash_rc = 0;
   struct ahash_request *req;
   struct scatterlist sg[1];
   struct ahash_completion res;
 - size_t rbuf_size;
 + size_t rbuf_size[2];
 
   hash-length = crypto_ahash_digestsize(tfm);
 
 @@ -275,36 +275,63 @@ static int ima_calc_file_hash_atfm(struct file *file,
* Try to allocate maximum size of memory, fail if not even single
* page cannot be allocated.
*/
 - rbuf = ima_alloc_pages(i_size, rbuf_size, 1);
 - if (!rbuf) {
 + rbuf[0] = ima_alloc_pages(i_size, rbuf_size[0], 1);
 + if (!rbuf[0]) {
   rc = -ENOMEM;
   goto out1;
   }
 
 + /* Only allocate one buffer if that is enough. */
 + if (i_size  rbuf_size[0]) {
 + /*
 +  * Try to allocate secondary buffer if that fails fallback to
 +  * using single buffering. Use previous memory allocation size
 +  * as baseline for possible allocation size.
 +  */
 + rbuf[1] = ima_alloc_pages(i_size - rbuf_size[0],
 +   rbuf_size[1], 0);
 + }
 +
   if (!(file-f_mode  FMODE_READ)) {
   file-f_mode |= FMODE_READ;
   read = 1;
   }
 
   for (offset = 0; offset  i_size; offset += rbuf_len) {
 - rbuf_len = ima_kernel_read(file, offset, rbuf, PAGE_SIZE);
 - if (rbuf_len  0) {
 - rc = rbuf_len;
 - break;
 + if (offset  !rbuf[1]) {
 + /* wait for completion of previous request */

This comment and the same ones below don't help clarify the code.  Here,
only one buffer is available, so we're waiting for the hash calculation
to complete before reading more data.

 + rc = ahash_wait(ahash_rc, res);
 + if (rc)
 + goto out3;
 + }
 + /* read buffer */
 + rbuf_len = min_t(loff_t, i_size - offset, rbuf_size[active]);
 + rc = ima_kernel_read(file, offset, rbuf[active], rbuf_len);
 + if (rc != rbuf_len)
 + goto out3;
 +
 + if (offset  rbuf[1]) {
 + /* wait for completion of previous request */

Where as here, we finished reading more data and are waiting for the
hash calculation for the prior buffer to complete. 

Mimi

 + rc = ahash_wait(ahash_rc, res);
 + if (rc)
 + goto out3;
   }
 - if (rbuf_len == 0)
 - break;
 
 - sg_init_one(sg[0], rbuf, rbuf_len);
 + sg_init_one(sg[0], rbuf[active], rbuf_len);
   ahash_request_set_crypt(req, sg, NULL, rbuf_len);
 
 - rc = ahash_wait(crypto_ahash_update(req), res);
 - if (rc)
 - break;
 + ahash_rc = crypto_ahash_update(req);
 +
 + if (rbuf[1])
 + active = !active; /* swap buffers. */
   }
 + /* wait for the last request to complete */
 + rc = ahash_wait(ahash_rc, res);
 +out3:
   if (read)
   file-f_mode = ~FMODE_READ;
 - ima_free_pages(rbuf, rbuf_size);
 + ima_free_pages(rbuf[0], rbuf_size[0]);
 + ima_free_pages(rbuf[1], rbuf_size[1]);
  out2:
   if (!rc) {
   ahash_request_set_crypt(req, NULL, hash-digest, 0);



--
To unsubscribe from this list: send the line unsubscribe linux-crypto in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[RFC][PATCH 02/20] keys: change asymmetric keys to use common hash definitions

2013-07-17 Thread Mimi Zohar
From: Dmitry Kasatkin dmitry.kasat...@gmail.com

This patch makes use of the newly defined common hash algorithm info,
replacing, for example, PKEY_HASH with HASH_ALGO.

Changelog:
- Lindent fixes - Mimi

Signed-off-by: Dmitry Kasatkin d.kasat...@samsung.com
Signed-off-by: Mimi Zohar zo...@linux.vnet.ibm.com
---
 crypto/asymmetric_keys/Kconfig|  1 +
 crypto/asymmetric_keys/public_key.c   | 12 
 crypto/asymmetric_keys/rsa.c  | 14 +++---
 crypto/asymmetric_keys/x509_cert_parser.c | 12 ++--
 crypto/asymmetric_keys/x509_parser.h  |  2 +-
 crypto/asymmetric_keys/x509_public_key.c  |  4 ++--
 include/crypto/public_key.h   | 18 --
 kernel/module_signing.c   |  8 
 8 files changed, 25 insertions(+), 46 deletions(-)

diff --git a/crypto/asymmetric_keys/Kconfig b/crypto/asymmetric_keys/Kconfig
index 6d2c2ea..52a7f2c 100644
--- a/crypto/asymmetric_keys/Kconfig
+++ b/crypto/asymmetric_keys/Kconfig
@@ -12,6 +12,7 @@ if ASYMMETRIC_KEY_TYPE
 config ASYMMETRIC_PUBLIC_KEY_SUBTYPE
tristate Asymmetric public-key crypto algorithm subtype
select MPILIB
+   select CRYPTO_HASH_INFO
help
  This option provides support for asymmetric public key type handling.
  If signature generation and/or verification are to be used,
diff --git a/crypto/asymmetric_keys/public_key.c 
b/crypto/asymmetric_keys/public_key.c
index cb2e291..007396f 100644
--- a/crypto/asymmetric_keys/public_key.c
+++ b/crypto/asymmetric_keys/public_key.c
@@ -28,18 +28,6 @@ const char *const pkey_algo[PKEY_ALGO__LAST] = {
 };
 EXPORT_SYMBOL_GPL(pkey_algo);
 
-const char *const pkey_hash_algo[PKEY_HASH__LAST] = {
-   [PKEY_HASH_MD4] = md4,
-   [PKEY_HASH_MD5] = md5,
-   [PKEY_HASH_SHA1]= sha1,
-   [PKEY_HASH_RIPE_MD_160] = rmd160,
-   [PKEY_HASH_SHA256]  = sha256,
-   [PKEY_HASH_SHA384]  = sha384,
-   [PKEY_HASH_SHA512]  = sha512,
-   [PKEY_HASH_SHA224]  = sha224,
-};
-EXPORT_SYMBOL_GPL(pkey_hash_algo);
-
 const char *const pkey_id_type[PKEY_ID_TYPE__LAST] = {
[PKEY_ID_PGP]   = PGP,
[PKEY_ID_X509]  = X509,
diff --git a/crypto/asymmetric_keys/rsa.c b/crypto/asymmetric_keys/rsa.c
index 4a6a069..90a17f5 100644
--- a/crypto/asymmetric_keys/rsa.c
+++ b/crypto/asymmetric_keys/rsa.c
@@ -73,13 +73,13 @@ static const struct {
size_t size;
 } RSA_ASN1_templates[PKEY_HASH__LAST] = {
 #define _(X) { RSA_digest_info_##X, sizeof(RSA_digest_info_##X) }
-   [PKEY_HASH_MD5] = _(MD5),
-   [PKEY_HASH_SHA1]= _(SHA1),
-   [PKEY_HASH_RIPE_MD_160] = _(RIPE_MD_160),
-   [PKEY_HASH_SHA256]  = _(SHA256),
-   [PKEY_HASH_SHA384]  = _(SHA384),
-   [PKEY_HASH_SHA512]  = _(SHA512),
-   [PKEY_HASH_SHA224]  = _(SHA224),
+   [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 _
 };
 
diff --git a/crypto/asymmetric_keys/x509_cert_parser.c 
b/crypto/asymmetric_keys/x509_cert_parser.c
index facbf26..0cefbe2 100644
--- a/crypto/asymmetric_keys/x509_cert_parser.c
+++ b/crypto/asymmetric_keys/x509_cert_parser.c
@@ -152,32 +152,32 @@ int x509_note_pkey_algo(void *context, size_t hdrlen,
return -ENOPKG; /* Unsupported combination */
 
case OID_md4WithRSAEncryption:
-   ctx-cert-sig_hash_algo = PKEY_HASH_MD5;
+   ctx-cert-sig_hash_algo = HASH_ALGO_MD5;
ctx-cert-sig_pkey_algo = PKEY_ALGO_RSA;
break;
 
case OID_sha1WithRSAEncryption:
-   ctx-cert-sig_hash_algo = PKEY_HASH_SHA1;
+   ctx-cert-sig_hash_algo = HASH_ALGO_SHA1;
ctx-cert-sig_pkey_algo = PKEY_ALGO_RSA;
break;
 
case OID_sha256WithRSAEncryption:
-   ctx-cert-sig_hash_algo = PKEY_HASH_SHA256;
+   ctx-cert-sig_hash_algo = HASH_ALGO_SHA256;
ctx-cert-sig_pkey_algo = PKEY_ALGO_RSA;
break;
 
case OID_sha384WithRSAEncryption:
-   ctx-cert-sig_hash_algo = PKEY_HASH_SHA384;
+   ctx-cert-sig_hash_algo = HASH_ALGO_SHA384;
ctx-cert-sig_pkey_algo = PKEY_ALGO_RSA;
break;
 
case OID_sha512WithRSAEncryption:
-   ctx-cert-sig_hash_algo = PKEY_HASH_SHA512;
+   ctx-cert-sig_hash_algo = HASH_ALGO_SHA512;
ctx-cert-sig_pkey_algo = PKEY_ALGO_RSA;
break;
 
case OID_sha224WithRSAEncryption:
-   ctx-cert-sig_hash_algo = PKEY_HASH_SHA224;
+   ctx-cert-sig_hash_algo = HASH_ALGO_SHA224;
ctx-cert-sig_pkey_algo

[RFC][PATCH 03/20] ima: provide support for arbitrary hash algorithms

2013-07-17 Thread Mimi Zohar
From: Dmitry Kasatkin dmitry.kasat...@gmail.com

In preparation of supporting more hash algorithms with larger hash sizes
needed for signature verification, this patch replaces the 20 byte sized
digest, with a more flexible structure.  The new structure includes the
hash algorithm, digest size, and digest.

Changelog:
- recalculate filedata hash for the measurement list, if the signature
  hash digest size is greater than 20 bytes.
- use generic HASH_ALGO_
- make ima_calc_file_hash static
- scripts lindent and checkpatch fixes

Signed-off-by: Dmitry Kasatkin d.kasat...@samsung.com
Signed-off-by: Mimi Zohar zo...@linux.vnet.ibm.com
---
 security/integrity/ima/Kconfig|  1 +
 security/integrity/ima/ima.h  |  7 ++---
 security/integrity/ima/ima_api.c  | 32 +--
 security/integrity/ima/ima_appraise.c | 20 --
 security/integrity/ima/ima_crypto.c   | 49 +--
 security/integrity/ima/ima_main.c |  6 +++--
 security/integrity/integrity.h| 15 ---
 7 files changed, 98 insertions(+), 32 deletions(-)

diff --git a/security/integrity/ima/Kconfig b/security/integrity/ima/Kconfig
index 39196ab..e6628e7 100644
--- a/security/integrity/ima/Kconfig
+++ b/security/integrity/ima/Kconfig
@@ -9,6 +9,7 @@ config IMA
select CRYPTO_HMAC
select CRYPTO_MD5
select CRYPTO_SHA1
+   select CRYPTO_HASH_INFO
select TCG_TPM if HAS_IOMEM  !UML
select TCG_TIS if TCG_TPM  X86
select TCG_IBMVTPM if TCG_TPM  PPC64
diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h
index b3dd616..eb86032 100644
--- a/security/integrity/ima/ima.h
+++ b/security/integrity/ima/ima.h
@@ -39,7 +39,7 @@ enum tpm_pcrs { TPM_PCR0 = 0, TPM_PCR8 = 8 };
 /* set during initialization */
 extern int ima_initialized;
 extern int ima_used_chip;
-extern char *ima_hash;
+extern int ima_hash_algo;
 extern int ima_appraise;
 
 /* IMA inode template definition */
@@ -70,8 +70,9 @@ void ima_fs_cleanup(void);
 int ima_inode_alloc(struct inode *inode);
 int ima_add_template_entry(struct ima_template_entry *entry, int violation,
   const char *op, struct inode *inode);
-int ima_calc_file_hash(struct file *file, char *digest);
-int ima_calc_buffer_hash(const void *data, int len, char *digest);
+int ima_calc_file_hash(struct file *file, struct ima_digest_data *hash);
+int ima_calc_buffer_hash(const void *data, int len,
+struct ima_digest_data *hash);
 int ima_calc_boot_aggregate(char *digest);
 void ima_add_violation(struct inode *inode, const unsigned char *filename,
   const char *op, const char *cause);
diff --git a/security/integrity/ima/ima_api.c b/security/integrity/ima/ima_api.c
index 1c03e8f1..e531fe2 100644
--- a/security/integrity/ima/ima_api.c
+++ b/security/integrity/ima/ima_api.c
@@ -44,6 +44,7 @@ int ima_store_template(struct ima_template_entry *entry,
const char *op = add_template_measure;
const char *audit_cause = hashing_error;
int result;
+   struct ima_digest_data hash;
 
memset(entry-digest, 0, sizeof(entry-digest));
entry-template_name = IMA_TEMPLATE_NAME;
@@ -51,14 +52,14 @@ int ima_store_template(struct ima_template_entry *entry,
 
if (!violation) {
result = ima_calc_buffer_hash(entry-template,
-   entry-template_len,
-   entry-digest);
+ entry-template_len, hash);
if (result  0) {
integrity_audit_msg(AUDIT_INTEGRITY_PCR, inode,
entry-template_name, op,
audit_cause, result, 0);
return result;
}
+   memcpy(entry-digest, hash.digest, hash.length);
}
result = ima_add_template_entry(entry, violation, op, inode);
return result;
@@ -147,8 +148,9 @@ int ima_collect_measurement(struct integrity_iint_cache 
*iint,
if (!(iint-flags  IMA_COLLECTED)) {
u64 i_version = file_inode(file)-i_version;
 
-   iint-ima_xattr.type = IMA_XATTR_DIGEST;
-   result = ima_calc_file_hash(file, iint-ima_xattr.digest);
+   /* use default hash algorithm */
+   iint-ima_hash.algo = ima_hash_algo;
+   result = ima_calc_file_hash(file, iint-ima_hash);
if (!result) {
iint-version = i_version;
iint-flags |= IMA_COLLECTED;
@@ -196,7 +198,21 @@ void ima_store_measurement(struct integrity_iint_cache 
*iint,
return;
}
memset(entry-template, 0, sizeof(entry-template));
-   memcpy(entry-template.digest, iint-ima_xattr.digest, IMA_DIGEST_SIZE);
+   if (iint-ima_hash.algo != ima_hash_algo

[RFC][PATCH 01/20] crypto: provide single place for hash algo information

2013-07-17 Thread Mimi Zohar
From: Dmitry Kasatkin dmitry.kasat...@gmail.com

This patch provides single place for information about hash algorithms,
such as hash sizes, and kernel driver names. Will be used by IMA and
public key code.

Changelog:
- Fix sparse and checkpatch warnings
- Move hash algo enums to uapi for userspace signing functions.

Signed-off-by: Dmitry Kasatkin d.kasat...@samsung.com
Signed-off-by: Mimi Zohar zo...@linux.vnet.ibm.com
---
 crypto/Kconfig |  3 +++
 crypto/Makefile|  1 +
 crypto/hash_info.c | 56 ++
 include/crypto/hash_info.h | 40 ++
 include/uapi/linux/hash_info.h | 37 
 5 files changed, 137 insertions(+)
 create mode 100644 crypto/hash_info.c
 create mode 100644 include/crypto/hash_info.h
 create mode 100644 include/uapi/linux/hash_info.h

diff --git a/crypto/Kconfig b/crypto/Kconfig
index 622d8a4..6f2b632 100644
--- a/crypto/Kconfig
+++ b/crypto/Kconfig
@@ -1393,6 +1393,9 @@ config CRYPTO_USER_API_SKCIPHER
  This option enables the user-spaces interface for symmetric
  key cipher algorithms.
 
+config CRYPTO_HASH_INFO
+   bool
+
 source drivers/crypto/Kconfig
 source crypto/asymmetric_keys/Kconfig
 
diff --git a/crypto/Makefile b/crypto/Makefile
index a8e9b0f..c179df9 100644
--- a/crypto/Makefile
+++ b/crypto/Makefile
@@ -101,3 +101,4 @@ obj-$(CONFIG_CRYPTO_USER_API_SKCIPHER) += algif_skcipher.o
 obj-$(CONFIG_XOR_BLOCKS) += xor.o
 obj-$(CONFIG_ASYNC_CORE) += async_tx/
 obj-$(CONFIG_ASYMMETRIC_KEY_TYPE) += asymmetric_keys/
+obj-$(CONFIG_CRYPTO_HASH_INFO) += hash_info.o
diff --git a/crypto/hash_info.c b/crypto/hash_info.c
new file mode 100644
index 000..3e7ff46
--- /dev/null
+++ b/crypto/hash_info.c
@@ -0,0 +1,56 @@
+/*
+ * Hash Info: Hash algorithms information
+ *
+ * Copyright (c) 2013 Dmitry Kasatkin d.kasat...@samsung.com
+ *
+ * This program 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.
+ *
+ */
+
+#include linux/export.h
+#include crypto/hash_info.h
+
+const char *const hash_algo_name[HASH_ALGO__LAST] = {
+   [HASH_ALGO_MD4] = md4,
+   [HASH_ALGO_MD5] = md5,
+   [HASH_ALGO_SHA1]= sha1,
+   [HASH_ALGO_RIPE_MD_160] = rmd160,
+   [HASH_ALGO_SHA256]  = sha256,
+   [HASH_ALGO_SHA384]  = sha384,
+   [HASH_ALGO_SHA512]  = sha512,
+   [HASH_ALGO_SHA224]  = sha224,
+   [HASH_ALGO_RIPE_MD_128] = rmd128,
+   [HASH_ALGO_RIPE_MD_256] = rmd256,
+   [HASH_ALGO_RIPE_MD_320] = rmd320,
+   [HASH_ALGO_WP_256]  = wp256,
+   [HASH_ALGO_WP_384]  = wp384,
+   [HASH_ALGO_WP_512]  = wp512,
+   [HASH_ALGO_TGR_128] = tgr128,
+   [HASH_ALGO_TGR_160] = tgr160,
+   [HASH_ALGO_TGR_192] = tgr192,
+};
+EXPORT_SYMBOL_GPL(hash_algo_name);
+
+const int hash_digest_size[HASH_ALGO__LAST] = {
+   [HASH_ALGO_MD4] = MD5_DIGEST_SIZE,
+   [HASH_ALGO_MD5] = MD5_DIGEST_SIZE,
+   [HASH_ALGO_SHA1]= SHA1_DIGEST_SIZE,
+   [HASH_ALGO_RIPE_MD_160] = RMD160_DIGEST_SIZE,
+   [HASH_ALGO_SHA256]  = SHA256_DIGEST_SIZE,
+   [HASH_ALGO_SHA384]  = SHA384_DIGEST_SIZE,
+   [HASH_ALGO_SHA512]  = SHA512_DIGEST_SIZE,
+   [HASH_ALGO_SHA224]  = SHA224_DIGEST_SIZE,
+   [HASH_ALGO_RIPE_MD_128] = RMD128_DIGEST_SIZE,
+   [HASH_ALGO_RIPE_MD_256] = RMD256_DIGEST_SIZE,
+   [HASH_ALGO_RIPE_MD_320] = RMD320_DIGEST_SIZE,
+   [HASH_ALGO_WP_256]  = WP256_DIGEST_SIZE,
+   [HASH_ALGO_WP_384]  = WP384_DIGEST_SIZE,
+   [HASH_ALGO_WP_512]  = WP512_DIGEST_SIZE,
+   [HASH_ALGO_TGR_128] = TGR128_DIGEST_SIZE,
+   [HASH_ALGO_TGR_160] = TGR160_DIGEST_SIZE,
+   [HASH_ALGO_TGR_192] = TGR192_DIGEST_SIZE,
+};
+EXPORT_SYMBOL_GPL(hash_digest_size);
diff --git a/include/crypto/hash_info.h b/include/crypto/hash_info.h
new file mode 100644
index 000..e1e5a3e
--- /dev/null
+++ b/include/crypto/hash_info.h
@@ -0,0 +1,40 @@
+/*
+ * Hash Info: Hash algorithms information
+ *
+ * Copyright (c) 2013 Dmitry Kasatkin d.kasat...@samsung.com
+ *
+ * This program 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.
+ *
+ */
+
+#ifndef _CRYPTO_HASH_INFO_H
+#define _CRYPTO_HASH_INFO_H
+
+#include crypto/sha.h
+#include crypto/md5.h
+
+#include uapi/linux/hash_info.h
+
+/* not defined in include/crypto/ */
+#define RMD128_DIGEST_SIZE  16
+#define RMD160_DIGEST_SIZE 20
+#define RMD256_DIGEST_SIZE  32
+#define RMD320_DIGEST_SIZE  40
+
+/* not defined in include/crypto/ */
+#define

[RFC][PATCH 15/20] ima: define new template ima-ng and template fields d-ng and n-ng

2013-07-17 Thread Mimi Zohar
From: Roberto Sassu roberto.sa...@polito.it

This patch adds support for the new template 'ima-ng', whose format
is defined as 'd-ng|n-ng'.  These new field definitions remove the
size limitations of the original 'ima' template.  Further, the 'd-ng'
field prefixes the inode digest with the hash algorithim, when
displaying the new larger digest sizes.

Change log:
- scripts/Lindent fixes  - Mimi
- always true comparison - reported by Fengguang Wu, resolved Dmitry

Signed-off-by: Roberto Sassu roberto.sa...@polito.it
Signed-off-by: Mimi Zohar zo...@linux.vnet.ibm.com
---
 security/integrity/ima/ima_template.c |   7 +-
 security/integrity/ima/ima_template_lib.c | 155 ++
 security/integrity/ima/ima_template_lib.h |   8 ++
 3 files changed, 152 insertions(+), 18 deletions(-)

diff --git a/security/integrity/ima/ima_template.c 
b/security/integrity/ima/ima_template.c
index 8100422..bf38d1a 100644
--- a/security/integrity/ima/ima_template.c
+++ b/security/integrity/ima/ima_template.c
@@ -16,7 +16,8 @@
 #include ima_template_lib.h
 
 static struct ima_template_desc defined_templates[] = {
-   {.name = IMA_TEMPLATE_IMA_NAME,.fmt = IMA_TEMPLATE_IMA_FMT},
+   {.name = IMA_TEMPLATE_IMA_NAME, .fmt = IMA_TEMPLATE_IMA_FMT},
+   {.name = ima-ng,.fmt = d-ng|n-ng},
 };
 
 static struct ima_template_field supported_fields[] = {
@@ -24,6 +25,10 @@ static struct ima_template_field supported_fields[] = {
 .field_show = ima_show_template_digest},
{.field_id = n,.field_init = ima_eventname_init,
 .field_show = ima_show_template_string},
+   {.field_id = d-ng,.field_init = ima_eventdigest_ng_init,
+.field_show = ima_show_template_digest_ng},
+   {.field_id = n-ng,.field_init = ima_eventname_ng_init,
+.field_show = ima_show_template_string},
 };
 
 static struct ima_template_field *lookup_template_field(const char *field_id)
diff --git a/security/integrity/ima/ima_template_lib.c 
b/security/integrity/ima/ima_template_lib.c
index f1a2fcb..f0bc14f 100644
--- a/security/integrity/ima/ima_template_lib.c
+++ b/security/integrity/ima/ima_template_lib.c
@@ -12,9 +12,25 @@
  * File: ima_template_lib.c
  *  Library of supported template fields.
  */
+#include crypto/hash_info.h
+
 #include ima_template_lib.h
 
-enum data_formats { DATA_FMT_DIGEST = 0, DATA_FMT_EVENT_NAME, DATA_FMT_STRING 
};
+static bool ima_template_hash_algo_allowed(u8 algo)
+{
+   if (algo == HASH_ALGO_SHA1 || algo == HASH_ALGO_MD5)
+   return true;
+
+   return false;
+}
+
+enum data_formats {
+   DATA_FMT_DIGEST = 0,
+   DATA_FMT_DIGEST_WITH_ALGO,
+   DATA_FMT_EVENT_NAME,
+   DATA_FMT_STRING
+};
+
 static int ima_write_template_field_data(const void *data, const u32 datalen,
 enum data_formats datafmt,
 struct ima_field_data *field_data)
@@ -62,12 +78,22 @@ static void ima_show_template_data_ascii(struct seq_file *m,
 enum data_formats datafmt,
 struct ima_field_data *field_data)
 {
+   u8 *buf_ptr = field_data-data, buflen = field_data-len;
+
switch (datafmt) {
+   case DATA_FMT_DIGEST_WITH_ALGO:
+   buf_ptr = strnchr(field_data-data, buflen, ':');
+   if (buf_ptr != field_data-data)
+   seq_printf(m, %s, field_data-data);
+
+   /* skip ':' and '\0' */
+   buf_ptr += 2;
+   buflen -= buf_ptr - field_data-data;
case DATA_FMT_DIGEST:
-   ima_print_digest(m, field_data-data, field_data-len);
+   ima_print_digest(m, buf_ptr, buflen);
break;
case DATA_FMT_STRING:
-   seq_printf(m, %s, field_data-data);
+   seq_printf(m, %s, buf_ptr);
break;
default:
break;
@@ -79,7 +105,7 @@ static void ima_show_template_data_binary(struct seq_file *m,
  enum data_formats datafmt,
  struct ima_field_data *field_data)
 {
-   if (datafmt != DATA_FMT_DIGEST)
+   if (datafmt != DATA_FMT_DIGEST  datafmt != DATA_FMT_DIGEST_WITH_ALGO)
ima_putc(m, field_data-len, sizeof(u32));
ima_putc(m, field_data-data, field_data-len);
 }
@@ -107,14 +133,59 @@ void ima_show_template_digest(struct seq_file *m, enum 
ima_show_type show,
ima_show_template_field_data(m, show, DATA_FMT_DIGEST, field_data);
 }
 
+void ima_show_template_digest_ng(struct seq_file *m, enum ima_show_type show,
+struct ima_field_data *field_data)
+{
+   ima_show_template_field_data(m, show, DATA_FMT_DIGEST_WITH_ALGO,
+field_data);
+}
+
 void ima_show_template_string(struct seq_file *m, enum ima_show_type show,
  struct

[RFC][PATCH 18/20] ima: add Kconfig default measurement list template

2013-07-17 Thread Mimi Zohar
This patch adds a Kconfig option to select the default IMA
measurement list template.  The 'ima' template limited the
filedata hash to 20 bytes and the pathname to 255 charaters.
The 'ima-ng' measurement list template permits larger hash
digests and longer pathnames.

Changelog:
- keep 'select CRYPTO_HASH_INFO' in 'config IMA' section (Kconfig)
  (Roberto Sassu);
- removed trailing whitespaces (Roberto Sassu).
- Lindent fixes

Signed-off-by: Mimi Zohar zo...@us.ibm.com
Signed-off-by: Roberto Sassu roberto.sa...@polito.it
---
 security/integrity/ima/Kconfig| 25 +
 security/integrity/ima/ima_template.c |  4 ++--
 2 files changed, 27 insertions(+), 2 deletions(-)

diff --git a/security/integrity/ima/Kconfig b/security/integrity/ima/Kconfig
index e6628e7..de26cc8 100644
--- a/security/integrity/ima/Kconfig
+++ b/security/integrity/ima/Kconfig
@@ -46,6 +46,31 @@ config IMA_LSM_RULES
help
  Disabling this option will disregard LSM based policy rules.
 
+choice
+   prompt Default template
+   default IMA_NG_TEMPLATE
+   depends on IMA
+   help
+ Select the default IMA measurement template.
+
+ The original 'ima' measurement list template contains a
+ hash, defined as 20 bytes, and a null terminated pathname,
+ limited to 255 characters.  The 'ima-ng' measurement list
+ template permits both larger hash digests and longer
+ pathnames.
+
+   config IMA_TEMPLATE
+   bool ima
+   config IMA_NG_TEMPLATE
+   bool ima-ng (default)
+endchoice
+
+config IMA_DEFAULT_TEMPLATE
+   string
+   depends on IMA
+   default ima if IMA_TEMPLATE
+   default ima-ng if IMA_NG_TEMPLATE
+
 config IMA_APPRAISE
bool Appraise integrity measurements
depends on IMA
diff --git a/security/integrity/ima/ima_template.c 
b/security/integrity/ima/ima_template.c
index 1c4cf19..c28ff9b 100644
--- a/security/integrity/ima/ima_template.c
+++ b/security/integrity/ima/ima_template.c
@@ -127,8 +127,8 @@ static int init_defined_templates(void)
 struct ima_template_desc *ima_template_desc_current(void)
 {
if (!ima_template)
-   ima_template = lookup_template_desc(IMA_TEMPLATE_IMA_NAME);
-
+   ima_template =
+   lookup_template_desc(CONFIG_IMA_DEFAULT_TEMPLATE);
return ima_template;
 }
 
-- 
1.8.1.4

--
To unsubscribe from this list: send the line unsubscribe linux-crypto in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[RFC][PATCH 09/20] ima: ima_calc_boot_agregate must use SHA1

2013-07-17 Thread Mimi Zohar
From: Dmitry Kasatkin dmitry.kasat...@gmail.com

With multiple hash algorithms, ima_hash_tfm is no longer guarantied to be sha1.
Need to force to use sha1.

Changelog:
- pass ima_digest_data to ima_calc_boot_aggregate() instead of char *
  (Roberto Sassu);
- create an ima_digest_data structure in ima_add_boot_aggregate()
  (Roberto Sassu);
- pass hash-algo to ima_alloc_tfm() (Roberto Sassu, reported by Dmitry).
- move hash definition in ima_add_boot_aggregate() commit hunk to here.
- sparse warning fix - Fengguang Wu

Signed-off-by: Dmitry Kasatkin dmitry.kasat...@gmail.com
Signed-off-by: Roberto Sassu roberto.sa...@polito.it
Signed-off-by: Mimi Zohar zo...@linux.vnet.ibm.com
---
 security/integrity/ima/ima.h|  2 +-
 security/integrity/ima/ima_crypto.c | 24 +---
 security/integrity/ima/ima_init.c   | 10 +-
 3 files changed, 31 insertions(+), 5 deletions(-)

diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h
index 52393ed..e0e1cde 100644
--- a/security/integrity/ima/ima.h
+++ b/security/integrity/ima/ima.h
@@ -73,7 +73,7 @@ int ima_add_template_entry(struct ima_template_entry *entry, 
int violation,
 int ima_calc_file_hash(struct file *file, struct ima_digest_data *hash);
 int ima_calc_buffer_hash(const void *data, int len,
 struct ima_digest_data *hash);
-int ima_calc_boot_aggregate(char *digest);
+int __init ima_calc_boot_aggregate(struct ima_digest_data *hash);
 void ima_add_violation(struct inode *inode, const unsigned char *filename,
   const char *op, const char *cause);
 int ima_init_crypto(void);
diff --git a/security/integrity/ima/ima_crypto.c 
b/security/integrity/ima/ima_crypto.c
index e2be252..22be23f 100644
--- a/security/integrity/ima/ima_crypto.c
+++ b/security/integrity/ima/ima_crypto.c
@@ -184,16 +184,17 @@ static void __init ima_pcrread(int idx, u8 *pcr)
 /*
  * Calculate the boot aggregate hash
  */
-int __init ima_calc_boot_aggregate(char *digest)
+static int __init ima_calc_boot_aggregate_tfm(char *digest,
+ struct crypto_shash *tfm)
 {
u8 pcr_i[TPM_DIGEST_SIZE];
int rc, i;
struct {
struct shash_desc shash;
-   char ctx[crypto_shash_descsize(ima_shash_tfm)];
+   char ctx[crypto_shash_descsize(tfm)];
} desc;
 
-   desc.shash.tfm = ima_shash_tfm;
+   desc.shash.tfm = tfm;
desc.shash.flags = 0;
 
rc = crypto_shash_init(desc.shash);
@@ -210,3 +211,20 @@ int __init ima_calc_boot_aggregate(char *digest)
crypto_shash_final(desc.shash, digest);
return rc;
 }
+
+int __init ima_calc_boot_aggregate(struct ima_digest_data *hash)
+{
+   struct crypto_shash *tfm;
+   int rc;
+
+   tfm = ima_alloc_tfm(hash-algo);
+   if (IS_ERR(tfm))
+   return PTR_ERR(tfm);
+
+   hash-length = crypto_shash_digestsize(tfm);
+   rc = ima_calc_boot_aggregate_tfm(hash-digest, tfm);
+
+   ima_free_tfm(tfm);
+
+   return rc;
+}
diff --git a/security/integrity/ima/ima_init.c 
b/security/integrity/ima/ima_init.c
index 9d0243c..77cd500 100644
--- a/security/integrity/ima/ima_init.c
+++ b/security/integrity/ima/ima_init.c
@@ -18,6 +18,7 @@
 #include linux/scatterlist.h
 #include linux/slab.h
 #include linux/err.h
+#include crypto/hash_info.h
 #include ima.h
 
 /* name for boot aggregate entry */
@@ -46,6 +47,10 @@ static void __init ima_add_boot_aggregate(void)
const char *audit_cause = ENOMEM;
int result = -ENOMEM;
int violation = 1;
+   struct {
+   struct ima_digest_data hdr;
+   char digest[TPM_DIGEST_SIZE];
+   } hash;
 
entry = kmalloc(sizeof(*entry), GFP_KERNEL);
if (!entry)
@@ -56,12 +61,15 @@ static void __init ima_add_boot_aggregate(void)
IMA_EVENT_NAME_LEN_MAX);
if (ima_used_chip) {
violation = 0;
-   result = ima_calc_boot_aggregate(entry-template.digest);
+   hash.hdr.algo = HASH_ALGO_SHA1;
+   result = ima_calc_boot_aggregate(hash.hdr);
if (result  0) {
audit_cause = hashing_error;
kfree(entry);
goto err_out;
}
+   memcpy(entry-template.digest, hash.hdr.digest,
+  hash.hdr.length);
}
result = ima_store_template(entry, violation, NULL);
if (result  0)
-- 
1.8.1.4

--
To unsubscribe from this list: send the line unsubscribe linux-crypto in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[RFC][PATCH 08/20] ima: support arbitrary hash algorithms in ima_calc_buffer_hash

2013-07-17 Thread Mimi Zohar
From: Dmitry Kasatkin dmitry.kasat...@gmail.com

ima_calc_buffer_hash will be used with different hash algorithms.
This patch provides support for arbitrary hash algorithms in
ima_calc_buffer_hash.

Signed-off-by: Dmitry Kasatkin dmitry.kasat...@gmail.com
Signed-off-by: Mimi Zohar zo...@linux.vnet.ibm.com
---
 security/integrity/ima/ima_api.c|  3 +++
 security/integrity/ima/ima_crypto.c | 28 ++--
 2 files changed, 25 insertions(+), 6 deletions(-)

diff --git a/security/integrity/ima/ima_api.c b/security/integrity/ima/ima_api.c
index 2cc5dcc..bc1d128 100644
--- a/security/integrity/ima/ima_api.c
+++ b/security/integrity/ima/ima_api.c
@@ -18,6 +18,7 @@
 #include linux/fs.h
 #include linux/xattr.h
 #include linux/evm.h
+#include crypto/hash_info.h
 #include ima.h
 
 static const char *IMA_TEMPLATE_NAME = ima;
@@ -54,6 +55,8 @@ int ima_store_template(struct ima_template_entry *entry,
entry-template_len = sizeof(entry-template);
 
if (!violation) {
+   /* this function uses default algo */
+   hash.hdr.algo = HASH_ALGO_SHA1;
result = ima_calc_buffer_hash(entry-template,
  entry-template_len, hash.hdr);
if (result  0) {
diff --git a/security/integrity/ima/ima_crypto.c 
b/security/integrity/ima/ima_crypto.c
index e5d3ebf..e2be252 100644
--- a/security/integrity/ima/ima_crypto.c
+++ b/security/integrity/ima/ima_crypto.c
@@ -139,23 +139,39 @@ int ima_calc_file_hash(struct file *file, struct 
ima_digest_data *hash)
 /*
  * Calculate the hash of a given buffer
  */
-int ima_calc_buffer_hash(const void *buf, int len, struct ima_digest_data 
*hash)
+static int ima_calc_buffer_hash_tfm(const void *buf, int len,
+   struct ima_digest_data *hash,
+   struct crypto_shash *tfm)
 {
struct {
struct shash_desc shash;
-   char ctx[crypto_shash_descsize(ima_shash_tfm)];
+   char ctx[crypto_shash_descsize(tfm)];
} desc;
 
-   desc.shash.tfm = ima_shash_tfm;
+   desc.shash.tfm = tfm;
desc.shash.flags = 0;
 
-   /* this function uses default algo */
-   hash-algo = ima_hash_algo;
-   hash-length = crypto_shash_digestsize(ima_shash_tfm);
+   hash-length = crypto_shash_digestsize(tfm);
 
return crypto_shash_digest(desc.shash, buf, len, hash-digest);
 }
 
+int ima_calc_buffer_hash(const void *buf, int len, struct ima_digest_data 
*hash)
+{
+   struct crypto_shash *tfm;
+   int rc;
+
+   tfm = ima_alloc_tfm(hash-algo);
+   if (IS_ERR(tfm))
+   return PTR_ERR(tfm);
+
+   rc = ima_calc_buffer_hash_tfm(buf, len, hash, tfm);
+
+   ima_free_tfm(tfm);
+
+   return rc;
+}
+
 static void __init ima_pcrread(int idx, u8 *pcr)
 {
if (!ima_used_chip)
-- 
1.8.1.4

--
To unsubscribe from this list: send the line unsubscribe linux-crypto in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[RFC][PATCH 07/20] ima: provide dedicated hash algo allocation function

2013-07-17 Thread Mimi Zohar
From: Dmitry Kasatkin d.kasat...@samsung.com

This patch provides dedicated hash algo allocation and
deallocation function which can be used by different clients.

Signed-off-by: Dmitry Kasatkin d.kasat...@samsung.com
Signed-off-by: Mimi Zohar zo...@linux.vnet.ibm.com
---
 security/integrity/ima/ima_crypto.c | 43 +
 1 file changed, 29 insertions(+), 14 deletions(-)

diff --git a/security/integrity/ima/ima_crypto.c 
b/security/integrity/ima/ima_crypto.c
index 872c669..e5d3ebf 100644
--- a/security/integrity/ima/ima_crypto.c
+++ b/security/integrity/ima/ima_crypto.c
@@ -39,6 +39,28 @@ int ima_init_crypto(void)
return 0;
 }
 
+static struct crypto_shash *ima_alloc_tfm(enum hash_algo algo)
+{
+   struct crypto_shash *tfm = ima_shash_tfm;
+   int rc;
+
+   if (algo != ima_hash_algo  algo  HASH_ALGO__LAST) {
+   tfm = crypto_alloc_shash(hash_algo_name[algo], 0, 0);
+   if (IS_ERR(tfm)) {
+   rc = PTR_ERR(tfm);
+   pr_err(Can not allocate %s (reason: %d)\n,
+  hash_algo_name[algo], rc);
+   }
+   }
+   return tfm;
+}
+
+static void ima_free_tfm(struct crypto_shash *tfm)
+{
+   if (tfm != ima_shash_tfm)
+   crypto_free_shash(tfm);
+}
+
 /*
  * Calculate the MD5/SHA1 file digest
  */
@@ -57,6 +79,8 @@ static int ima_calc_file_hash_tfm(struct file *file,
desc.shash.tfm = tfm;
desc.shash.flags = 0;
 
+   hash-length = crypto_shash_digestsize(tfm);
+
rc = crypto_shash_init(desc.shash);
if (rc != 0)
return rc;
@@ -98,25 +122,16 @@ out:
 
 int ima_calc_file_hash(struct file *file, struct ima_digest_data *hash)
 {
-   struct crypto_shash *tfm = ima_shash_tfm;
+   struct crypto_shash *tfm;
int rc;
 
-   if (hash-algo != ima_hash_algo  hash-algo  HASH_ALGO__LAST) {
-   tfm = crypto_alloc_shash(hash_algo_name[hash-algo], 0, 0);
-   if (IS_ERR(tfm)) {
-   rc = PTR_ERR(tfm);
-   pr_err(Can not allocate %s (reason: %d)\n,
-  hash_algo_name[hash-algo], rc);
-   return rc;
-   }
-   }
-
-   hash-length = crypto_shash_digestsize(tfm);
+   tfm = ima_alloc_tfm(hash-algo);
+   if (IS_ERR(tfm))
+   return PTR_ERR(tfm);
 
rc = ima_calc_file_hash_tfm(file, hash, tfm);
 
-   if (tfm != ima_shash_tfm)
-   crypto_free_shash(tfm);
+   ima_free_tfm(tfm);
 
return rc;
 }
-- 
1.8.1.4

--
To unsubscribe from this list: send the line unsubscribe linux-crypto in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[RFC][PATCH 05/20] ima: use dynamically allocated hash storage

2013-07-17 Thread Mimi Zohar
From: Dmitry Kasatkin dmitry.kasat...@gmail.com

For each inode in the IMA policy, an iint is allocated.  To support
larger hash digests, the iint digest size changed from 20 bytes to
the maximum supported hash digest size.  Instead of allocating the
maximum size, which most likely is not needed, this patch dynamically
allocates the needed hash storage.

Changelog:
- fix krealloc bug

Signed-off-by: Dmitry Kasatkin d.kasat...@samsung.com
Signed-off-by: Mimi Zohar zo...@linux.vnet.ibm.com
---
 security/integrity/iint.c |  2 ++
 security/integrity/ima/ima_api.c  | 57 +++
 security/integrity/ima/ima_appraise.c | 16 +-
 security/integrity/integrity.h|  4 +--
 4 files changed, 49 insertions(+), 30 deletions(-)

diff --git a/security/integrity/iint.c b/security/integrity/iint.c
index 74522db..c49d3f1 100644
--- a/security/integrity/iint.c
+++ b/security/integrity/iint.c
@@ -70,6 +70,8 @@ struct integrity_iint_cache *integrity_iint_find(struct inode 
*inode)
 
 static void iint_free(struct integrity_iint_cache *iint)
 {
+   kfree(iint-ima_hash);
+   iint-ima_hash = NULL;
iint-version = 0;
iint-flags = 0UL;
iint-ima_file_status = INTEGRITY_UNKNOWN;
diff --git a/security/integrity/ima/ima_api.c b/security/integrity/ima/ima_api.c
index 1dba98e..5a7942e 100644
--- a/security/integrity/ima/ima_api.c
+++ b/security/integrity/ima/ima_api.c
@@ -44,7 +44,10 @@ int ima_store_template(struct ima_template_entry *entry,
const char *op = add_template_measure;
const char *audit_cause = hashing_error;
int result;
-   struct ima_digest_data hash;
+   struct {
+   struct ima_digest_data hdr;
+   char digest[IMA_MAX_DIGEST_SIZE];
+   } hash;
 
memset(entry-digest, 0, sizeof(entry-digest));
entry-template_name = IMA_TEMPLATE_NAME;
@@ -52,14 +55,14 @@ int ima_store_template(struct ima_template_entry *entry,
 
if (!violation) {
result = ima_calc_buffer_hash(entry-template,
- entry-template_len, hash);
+ entry-template_len, hash.hdr);
if (result  0) {
integrity_audit_msg(AUDIT_INTEGRITY_PCR, inode,
entry-template_name, op,
audit_cause, result, 0);
return result;
}
-   memcpy(entry-digest, hash.digest, hash.length);
+   memcpy(entry-digest, hash.hdr.digest, hash.hdr.length);
}
result = ima_add_template_entry(entry, violation, op, inode);
return result;
@@ -146,6 +149,10 @@ int ima_collect_measurement(struct integrity_iint_cache 
*iint,
struct inode *inode = file_inode(file);
const char *filename = file-f_dentry-d_name.name;
int result = 0;
+   struct {
+   struct ima_digest_data hdr;
+   char digest[IMA_MAX_DIGEST_SIZE];
+   } hash;
 
if (xattr_value)
*xattr_len = ima_read_xattr(file-f_dentry, xattr_value);
@@ -154,16 +161,23 @@ int ima_collect_measurement(struct integrity_iint_cache 
*iint,
u64 i_version = file_inode(file)-i_version;
 
/* use default hash algorithm */
-   iint-ima_hash.algo = ima_hash_algo;
+   hash.hdr.algo = ima_hash_algo;
 
if (xattr_value)
-   ima_get_hash_algo(*xattr_value, *xattr_len,
- iint-ima_hash);
+   ima_get_hash_algo(*xattr_value, *xattr_len, hash.hdr);
 
-   result = ima_calc_file_hash(file, iint-ima_hash);
+   result = ima_calc_file_hash(file, hash.hdr);
if (!result) {
-   iint-version = i_version;
-   iint-flags |= IMA_COLLECTED;
+   int length = sizeof(hash.hdr) + hash.hdr.length;
+   void *tmpbuf = krealloc(iint-ima_hash, length,
+   GFP_NOFS);
+   if (tmpbuf) {
+   iint-ima_hash = tmpbuf;
+   memcpy(iint-ima_hash, hash, length);
+   iint-version = i_version;
+   iint-flags |= IMA_COLLECTED;
+   } else
+   result = -ENOMEM;
}
}
if (result)
@@ -208,21 +222,24 @@ void ima_store_measurement(struct integrity_iint_cache 
*iint,
return;
}
memset(entry-template, 0, sizeof(entry-template));
-   if (iint-ima_hash.algo != ima_hash_algo) {
-   struct ima_digest_data hash;
+   if (iint-ima_hash-algo != ima_hash_algo) {
+   struct {
+   struct

[RFC][PATCH 16/20] ima: switch to new template management mechanism

2013-07-17 Thread Mimi Zohar
From: Roberto Sassu roberto.sa...@polito.it

This patch performs the switch to the new template mechanism by modifying
the functions ima_alloc_init_template(), ima_measurements_show() and
ima_ascii_measurements_show(). The old function ima_template_show() was
removed as it is no longer needed. Also, if the template descriptor used
to generate a measurement entry is not 'ima', the whole length of field
data stored for an entry is provided before the data itself through the
binary_runtime_measurement interface.

Changelog:
- unnecessary to use strncmp() (Mimi Zohar)
- create new variable 'field' in ima_alloc_init_template() (Roberto Sassu)
- use GFP_NOFS flag in ima_alloc_init_template() (Roberto Sassu)
- new variable 'num_fields' in ima_store_template() (Roberto Sassu,
  proposed by Mimi Zohar)
- rename ima_calc_buffer_hash/template_hash() to ima_calc_field_array_hash(),
  something more generic (Mimi, requested by Dmitry)
- sparse error fix - Fengguang Wu

Signed-off-by: Roberto Sassu roberto.sa...@polito.it
Signed-off-by: Mimi Zohar zo...@linux.vnet.ibm.com
---
 security/integrity/ima/ima.h  | 19 -
 security/integrity/ima/ima_api.c  | 73 +++
 security/integrity/ima/ima_crypto.c   | 31 +++
 security/integrity/ima/ima_fs.c   | 54 --
 security/integrity/ima/ima_template.c | 22 +++
 5 files changed, 101 insertions(+), 98 deletions(-)

diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h
index e1f081d..72d013e 100644
--- a/security/integrity/ima/ima.h
+++ b/security/integrity/ima/ima.h
@@ -72,17 +72,11 @@ struct ima_template_desc {
struct ima_template_field **fields;
 };
 
-/* IMA inode template definition */
-struct ima_template_data {
-   u8 digest[IMA_DIGEST_SIZE]; /* sha1/md5 measurement hash */
-   char file_name[IMA_EVENT_NAME_LEN_MAX + 1]; /* name + \0 */
-};
-
 struct ima_template_entry {
u8 digest[TPM_DIGEST_SIZE]; /* sha1 or md5 measurement hash */
-   const char *template_name;
-   int template_len;
-   struct ima_template_data template;
+   struct ima_template_desc *template_desc; /* template descriptor */
+   u32 template_data_len;
+   struct ima_field_data template_data[0]; /* template related data */
 };
 
 struct ima_queue_entry {
@@ -102,14 +96,16 @@ int ima_add_template_entry(struct ima_template_entry 
*entry, int violation,
   const char *op, struct inode *inode,
   const unsigned char *filename);
 int ima_calc_file_hash(struct file *file, struct ima_digest_data *hash);
-int ima_calc_buffer_hash(const void *data, int len,
-struct ima_digest_data *hash);
+int ima_calc_field_array_hash(struct ima_field_data *field_data, int 
num_fields,
+ struct ima_digest_data *hash);
 int __init ima_calc_boot_aggregate(struct ima_digest_data *hash);
 void ima_add_violation(struct file *file, const unsigned char *filename,
   const char *op, const char *cause);
 int ima_init_crypto(void);
 void ima_putc(struct seq_file *m, void *data, int datalen);
 void ima_print_digest(struct seq_file *m, u8 *digest, int size);
+struct ima_template_desc *ima_template_desc_current(void);
+int ima_init_template(void);
 
 int ima_init_template(void);
 
@@ -146,7 +142,6 @@ int ima_alloc_init_template(struct integrity_iint_cache 
*iint,
struct ima_template_entry **entry);
 int ima_store_template(struct ima_template_entry *entry, int violation,
   struct inode *inode, const unsigned char *filename);
-void ima_template_show(struct seq_file *m, void *e, enum ima_show_type show);
 const char *ima_d_path(struct path *path, char **pathbuf);
 
 /* rbtree tree calls to lookup, insert, delete
diff --git a/security/integrity/ima/ima_api.c b/security/integrity/ima/ima_api.c
index 29dd43d..974fbab 100644
--- a/security/integrity/ima/ima_api.c
+++ b/security/integrity/ima/ima_api.c
@@ -21,8 +21,6 @@
 #include crypto/hash_info.h
 #include ima.h
 
-static const char *IMA_TEMPLATE_NAME = ima;
-
 /*
  * ima_alloc_init_template - create and initialize a new template entry
  */
@@ -30,52 +28,28 @@ int ima_alloc_init_template(struct integrity_iint_cache 
*iint,
struct file *file, const unsigned char *filename,
struct ima_template_entry **entry)
 {
-   struct ima_template_entry *e;
-   int result = 0;
+   struct ima_template_desc *template_desc = ima_template_desc_current();
+   int i, result = 0;
 
-   e = kzalloc(sizeof(**entry), GFP_NOFS);
-   if (!e)
+   *entry = kzalloc(sizeof(**entry) + template_desc-num_fields *
+   sizeof(struct ima_field_data), GFP_NOFS);
+   if (!*entry)
return -ENOMEM;
 
-   memset((e)-template, 0, sizeof(e-template));
-   if (!iint

[RFC][PATCH 12/20] ima: define new function ima_alloc_init_template() to API

2013-07-17 Thread Mimi Zohar
From: Roberto Sassu roberto.sa...@polito.it

Instead of allocating and initializing the template entry from multiple
places (eg. boot aggregate, violation, and regular measurements), this
patch defines a new function called ima_alloc_init_template().  The new
function allocates and initializes the measurement entry with the inode
digest and the filename.

In respect to the current behavior, it truncates the file name passed
in the 'filename' argument if the latter's size is greater than 255 bytes
and the passed file descriptor is NULL.

Changelog:
- initialize 'hash' variable for non TPM case - Mimi
- conform to expectation for 'iint' to be defined as a pointer. - Mimi
- add missing 'file' dependency for recalculating file hash. - Mimi

Signed-off-by: Roberto Sassu roberto.sa...@polito.it
Signed-off-by: Mimi Zohar zo...@linux.vnet.ibm.com
---
 security/integrity/ima/ima.h  |  3 ++
 security/integrity/ima/ima_api.c  | 88 ++-
 security/integrity/ima/ima_init.c | 24 ++-
 3 files changed, 76 insertions(+), 39 deletions(-)

diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h
index 27d2ffb..da03d33 100644
--- a/security/integrity/ima/ima.h
+++ b/security/integrity/ima/ima.h
@@ -107,6 +107,9 @@ void ima_store_measurement(struct integrity_iint_cache 
*iint, struct file *file,
   const unsigned char *filename);
 void ima_audit_measurement(struct integrity_iint_cache *iint,
   const unsigned char *filename);
+int ima_alloc_init_template(struct integrity_iint_cache *iint,
+   struct file *file, const unsigned char *filename,
+   struct ima_template_entry **entry);
 int ima_store_template(struct ima_template_entry *entry, int violation,
   struct inode *inode, const unsigned char *filename);
 void ima_template_show(struct seq_file *m, void *e, enum ima_show_type show);
diff --git a/security/integrity/ima/ima_api.c b/security/integrity/ima/ima_api.c
index a0fe504..29dd43d 100644
--- a/security/integrity/ima/ima_api.c
+++ b/security/integrity/ima/ima_api.c
@@ -24,6 +24,62 @@
 static const char *IMA_TEMPLATE_NAME = ima;
 
 /*
+ * ima_alloc_init_template - create and initialize a new template entry
+ */
+int ima_alloc_init_template(struct integrity_iint_cache *iint,
+   struct file *file, const unsigned char *filename,
+   struct ima_template_entry **entry)
+{
+   struct ima_template_entry *e;
+   int result = 0;
+
+   e = kzalloc(sizeof(**entry), GFP_NOFS);
+   if (!e)
+   return -ENOMEM;
+
+   memset((e)-template, 0, sizeof(e-template));
+   if (!iint)  /* IMA measurement violation entry */
+   goto out;
+
+   if (iint-ima_hash-algo != ima_hash_algo) {
+   struct inode *inode;
+   struct {
+   struct ima_digest_data hdr;
+   char digest[IMA_MAX_DIGEST_SIZE];
+   } hash;
+
+   if (!file) {
+   result = -EINVAL;
+   goto out_free;
+   }
+
+   inode = file_inode(file);
+   hash.hdr.algo = ima_hash_algo;
+   hash.hdr.length = SHA1_DIGEST_SIZE;
+   result = ima_calc_file_hash(file, hash.hdr);
+   if (result) {
+   integrity_audit_msg(AUDIT_INTEGRITY_DATA, inode,
+   filename, collect_data,
+   failed, result, 0);
+   goto out_free;
+   } else
+   memcpy(e-template.digest, hash.hdr.digest,
+  hash.hdr.length);
+   } else
+   memcpy(e-template.digest, iint-ima_hash-digest,
+  iint-ima_hash-length);
+out:
+   strcpy(e-template.file_name,
+  (strlen(filename)  IMA_EVENT_NAME_LEN_MAX  file != NULL) ?
+  file-f_dentry-d_name.name : filename);
+   *entry = e;
+   return 0;
+out_free:
+   kfree(e);
+   return result;
+}
+
+/*
  * ima_store_template - store ima template measurements
  *
  * Calculate the hash of a template entry, add the template entry
@@ -90,13 +146,11 @@ void ima_add_violation(struct file *file, const unsigned 
char *filename,
/* can overflow, only indicator */
atomic_long_inc(ima_htable.violations);
 
-   entry = kmalloc(sizeof(*entry), GFP_KERNEL);
-   if (!entry) {
+   result = ima_alloc_init_template(NULL, file, filename, entry);
+   if (result  0) {
result = -ENOMEM;
goto err_out;
}
-   memset(entry-template, 0, sizeof(entry-template));
-   strncpy(entry-template.file_name, filename, IMA_EVENT_NAME_LEN_MAX);
result = ima_store_template(entry, violation, inode, filename

[RFC][PATCH 11/20] ima: pass the filename argument up to ima_add_template_entry()

2013-07-17 Thread Mimi Zohar
From: Roberto Sassu roberto.sa...@polito.it

Pass the filename argument to ima_add_template_entry() in order to
eliminate a dependency on template specific data (third argument of
integrity_audit_msg).

This change is required because, with the new template management
mechanism, the generation of a new measurement entry will be performed
by new specific functions (introduced in next patches) and the current IMA
code will not be aware anymore of how data is stored in the entry payload.

Signed-off-by: Roberto Sassu roberto.sa...@polito.it
Signed-off-by: Mimi Zohar zo...@linux.vnet.ibm.com
---
 security/integrity/ima/ima.h   | 5 +++--
 security/integrity/ima/ima_api.c   | 9 +
 security/integrity/ima/ima_init.c  | 3 ++-
 security/integrity/ima/ima_queue.c | 6 +++---
 4 files changed, 13 insertions(+), 10 deletions(-)

diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h
index d7bec6f..27d2ffb 100644
--- a/security/integrity/ima/ima.h
+++ b/security/integrity/ima/ima.h
@@ -69,7 +69,8 @@ int ima_fs_init(void);
 void ima_fs_cleanup(void);
 int ima_inode_alloc(struct inode *inode);
 int ima_add_template_entry(struct ima_template_entry *entry, int violation,
-  const char *op, struct inode *inode);
+  const char *op, struct inode *inode,
+  const unsigned char *filename);
 int ima_calc_file_hash(struct file *file, struct ima_digest_data *hash);
 int ima_calc_buffer_hash(const void *data, int len,
 struct ima_digest_data *hash);
@@ -107,7 +108,7 @@ void ima_store_measurement(struct integrity_iint_cache 
*iint, struct file *file,
 void ima_audit_measurement(struct integrity_iint_cache *iint,
   const unsigned char *filename);
 int ima_store_template(struct ima_template_entry *entry, int violation,
-  struct inode *inode);
+  struct inode *inode, const unsigned char *filename);
 void ima_template_show(struct seq_file *m, void *e, enum ima_show_type show);
 const char *ima_d_path(struct path *path, char **pathbuf);
 
diff --git a/security/integrity/ima/ima_api.c b/security/integrity/ima/ima_api.c
index 98160a3..a0fe504 100644
--- a/security/integrity/ima/ima_api.c
+++ b/security/integrity/ima/ima_api.c
@@ -40,7 +40,8 @@ static const char *IMA_TEMPLATE_NAME = ima;
  * Returns 0 on success, error code otherwise
  */
 int ima_store_template(struct ima_template_entry *entry,
-  int violation, struct inode *inode)
+  int violation, struct inode *inode,
+  const unsigned char *filename)
 {
const char *op = add_template_measure;
const char *audit_cause = hashing_error;
@@ -67,7 +68,7 @@ int ima_store_template(struct ima_template_entry *entry,
}
memcpy(entry-digest, hash.hdr.digest, hash.hdr.length);
}
-   result = ima_add_template_entry(entry, violation, op, inode);
+   result = ima_add_template_entry(entry, violation, op, inode, filename);
return result;
 }
 
@@ -96,7 +97,7 @@ void ima_add_violation(struct file *file, const unsigned char 
*filename,
}
memset(entry-template, 0, sizeof(entry-template));
strncpy(entry-template.file_name, filename, IMA_EVENT_NAME_LEN_MAX);
-   result = ima_store_template(entry, violation, inode);
+   result = ima_store_template(entry, violation, inode, filename);
if (result  0)
kfree(entry);
 err_out:
@@ -248,7 +249,7 @@ void ima_store_measurement(struct integrity_iint_cache 
*iint,
   (strlen(filename)  IMA_EVENT_NAME_LEN_MAX) ?
   file-f_dentry-d_name.name : filename);
 
-   result = ima_store_template(entry, violation, inode);
+   result = ima_store_template(entry, violation, inode, filename);
if (!result || result == -EEXIST)
iint-flags |= IMA_MEASURED;
if (result  0)
diff --git a/security/integrity/ima/ima_init.c 
b/security/integrity/ima/ima_init.c
index 77cd500..d42fac3 100644
--- a/security/integrity/ima/ima_init.c
+++ b/security/integrity/ima/ima_init.c
@@ -71,7 +71,8 @@ static void __init ima_add_boot_aggregate(void)
memcpy(entry-template.digest, hash.hdr.digest,
   hash.hdr.length);
}
-   result = ima_store_template(entry, violation, NULL);
+   result = ima_store_template(entry, violation, NULL,
+   boot_aggregate_name);
if (result  0)
kfree(entry);
return;
diff --git a/security/integrity/ima/ima_queue.c 
b/security/integrity/ima/ima_queue.c
index e63ff33..d85e997 100644
--- a/security/integrity/ima/ima_queue.c
+++ b/security/integrity/ima/ima_queue.c
@@ -104,7 +104,8 @@ static int ima_pcr_extend(const u8 *hash)
  * and extend the pcr.
  */
 int ima_add_template_entry(struct ima_template_entry *entry, int violation

[RFC][PATCH 06/20] ima: differentiate between template hash and file data hash sizes

2013-07-17 Thread Mimi Zohar
The TPM v1.2 limits the template hash size to 20 bytes.  This
patch differentiates between the template hash size, as defined
in the ima_template_entry, and the file data hash size, as
defined in the ima_template_data.  Subsequent patches add support
for different file data hash algorithms.

Change log:
- hash digest definition in ima_store_template() should be TPM_DIGEST_SIZE

Signed-off-by: Mimi Zohar zo...@us.ibm.com
---
 security/integrity/ima/ima.h|  2 +-
 security/integrity/ima/ima_api.c|  2 +-
 security/integrity/ima/ima_crypto.c |  4 ++--
 security/integrity/ima/ima_fs.c | 10 +-
 security/integrity/ima/ima_init.c   |  2 +-
 security/integrity/ima/ima_queue.c  |  4 ++--
 6 files changed, 12 insertions(+), 12 deletions(-)

diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h
index efcdef2..52393ed 100644
--- a/security/integrity/ima/ima.h
+++ b/security/integrity/ima/ima.h
@@ -49,7 +49,7 @@ struct ima_template_data {
 };
 
 struct ima_template_entry {
-   u8 digest[IMA_DIGEST_SIZE]; /* sha1 or md5 measurement hash */
+   u8 digest[TPM_DIGEST_SIZE]; /* sha1 or md5 measurement hash */
const char *template_name;
int template_len;
struct ima_template_data template;
diff --git a/security/integrity/ima/ima_api.c b/security/integrity/ima/ima_api.c
index 5a7942e..2cc5dcc 100644
--- a/security/integrity/ima/ima_api.c
+++ b/security/integrity/ima/ima_api.c
@@ -46,7 +46,7 @@ int ima_store_template(struct ima_template_entry *entry,
int result;
struct {
struct ima_digest_data hdr;
-   char digest[IMA_MAX_DIGEST_SIZE];
+   char digest[TPM_DIGEST_SIZE];
} hash;
 
memset(entry-digest, 0, sizeof(entry-digest));
diff --git a/security/integrity/ima/ima_crypto.c 
b/security/integrity/ima/ima_crypto.c
index 2fd1786..872c669 100644
--- a/security/integrity/ima/ima_crypto.c
+++ b/security/integrity/ima/ima_crypto.c
@@ -155,7 +155,7 @@ static void __init ima_pcrread(int idx, u8 *pcr)
  */
 int __init ima_calc_boot_aggregate(char *digest)
 {
-   u8 pcr_i[IMA_DIGEST_SIZE];
+   u8 pcr_i[TPM_DIGEST_SIZE];
int rc, i;
struct {
struct shash_desc shash;
@@ -173,7 +173,7 @@ int __init ima_calc_boot_aggregate(char *digest)
for (i = TPM_PCR0; i  TPM_PCR8; i++) {
ima_pcrread(i, pcr_i);
/* now accumulate with current aggregate */
-   rc = crypto_shash_update(desc.shash, pcr_i, IMA_DIGEST_SIZE);
+   rc = crypto_shash_update(desc.shash, pcr_i, TPM_DIGEST_SIZE);
}
if (!rc)
crypto_shash_final(desc.shash, digest);
diff --git a/security/integrity/ima/ima_fs.c b/security/integrity/ima/ima_fs.c
index 38477c9..89adf1d 100644
--- a/security/integrity/ima/ima_fs.c
+++ b/security/integrity/ima/ima_fs.c
@@ -134,7 +134,7 @@ static int ima_measurements_show(struct seq_file *m, void 
*v)
ima_putc(m, pcr, sizeof pcr);
 
/* 2nd: template digest */
-   ima_putc(m, e-digest, IMA_DIGEST_SIZE);
+   ima_putc(m, e-digest, TPM_DIGEST_SIZE);
 
/* 3rd: template name size */
namelen = strlen(e-template_name);
@@ -168,11 +168,11 @@ static const struct file_operations ima_measurements_ops 
= {
.release = seq_release,
 };
 
-static void ima_print_digest(struct seq_file *m, u8 *digest)
+static void ima_print_digest(struct seq_file *m, u8 *digest, int size)
 {
int i;
 
-   for (i = 0; i  IMA_DIGEST_SIZE; i++)
+   for (i = 0; i  size; i++)
seq_printf(m, %02x, *(digest + i));
 }
 
@@ -183,7 +183,7 @@ void ima_template_show(struct seq_file *m, void *e, enum 
ima_show_type show)
 
switch (show) {
case IMA_SHOW_ASCII:
-   ima_print_digest(m, entry-digest);
+   ima_print_digest(m, entry-digest, IMA_DIGEST_SIZE);
seq_printf(m,  %s\n, entry-file_name);
break;
case IMA_SHOW_BINARY:
@@ -213,7 +213,7 @@ static int ima_ascii_measurements_show(struct seq_file *m, 
void *v)
seq_printf(m, %2d , CONFIG_IMA_MEASURE_PCR_IDX);
 
/* 2nd: SHA1 template hash */
-   ima_print_digest(m, e-digest);
+   ima_print_digest(m, e-digest, TPM_DIGEST_SIZE);
 
/* 3th:  template name */
seq_printf(m,  %s , e-template_name);
diff --git a/security/integrity/ima/ima_init.c 
b/security/integrity/ima/ima_init.c
index 162ea72..9d0243c 100644
--- a/security/integrity/ima/ima_init.c
+++ b/security/integrity/ima/ima_init.c
@@ -74,7 +74,7 @@ err_out:
 
 int __init ima_init(void)
 {
-   u8 pcr_i[IMA_DIGEST_SIZE];
+   u8 pcr_i[TPM_DIGEST_SIZE];
int rc;
 
ima_used_chip = 0;
diff --git a/security/integrity/ima/ima_queue.c 
b/security/integrity/ima/ima_queue.c
index ff63fe0..e63ff33 100644
--- a/security/integrity/ima/ima_queue.c
+++ b/security/integrity/ima/ima_queue.c
@@ -50,7 +50,7 @@ static struct

[RFC][PATCH 14/20] ima: define template fields library and new helpers

2013-07-17 Thread Mimi Zohar
From: Roberto Sassu roberto.sa...@polito.it

This patch defines a library containing two initial template fields,
inode digest (d) and file name (n), the 'ima' template descriptor,
whose format is 'd|n', and two helper functions,
ima_write_template_field_data() and ima_show_template_field_data().

Changelog:
- replace ima_eventname_init() parameter NULL checking with BUG_ON.
  (suggested by Mimi)
- include new template fields for inode digest (d) and file name (n)
  definitions to fix a compiler warning.  - Mimi
- unnecessary to prefix static function names with 'ima_'. remove
  prefix to resolve Lindent formatting changes. - Mimi
- abbreviated/removed inline comments - Mimi

Signed-off-by: Roberto Sassu roberto.sa...@polito.it
Signed-off-by: Mimi Zohar zo...@linux.vnet.ibm.com
---
 security/integrity/ima/Makefile   |   2 +-
 security/integrity/ima/ima.h  |   5 +
 security/integrity/ima/ima_fs.c   |   4 +-
 security/integrity/ima/ima_template.c |  15 ++-
 security/integrity/ima/ima_template_lib.c | 192 ++
 security/integrity/ima/ima_template_lib.h |  31 +
 6 files changed, 241 insertions(+), 8 deletions(-)
 create mode 100644 security/integrity/ima/ima_template_lib.c
 create mode 100644 security/integrity/ima/ima_template_lib.h

diff --git a/security/integrity/ima/Makefile b/security/integrity/ima/Makefile
index 7fe4ae3..d79263d 100644
--- a/security/integrity/ima/Makefile
+++ b/security/integrity/ima/Makefile
@@ -6,5 +6,5 @@
 obj-$(CONFIG_IMA) += ima.o
 
 ima-y := ima_fs.o ima_queue.o ima_init.o ima_main.o ima_crypto.o ima_api.o \
-ima_policy.o ima_template.o
+ima_policy.o ima_template.o ima_template_lib.o
 ima-$(CONFIG_IMA_APPRAISE) += ima_appraise.o
diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h
index c85718f..e1f081d 100644
--- a/security/integrity/ima/ima.h
+++ b/security/integrity/ima/ima.h
@@ -39,6 +39,9 @@ enum tpm_pcrs { TPM_PCR0 = 0, TPM_PCR8 = 8 };
 #define IMA_TEMPLATE_FIELD_ID_MAX_LEN  16
 #define IMA_TEMPLATE_NUM_FIELDS_MAX15
 
+#define IMA_TEMPLATE_IMA_NAME ima
+#define IMA_TEMPLATE_IMA_FMT d|n
+
 /* set during initialization */
 extern int ima_initialized;
 extern int ima_used_chip;
@@ -105,6 +108,8 @@ int __init ima_calc_boot_aggregate(struct ima_digest_data 
*hash);
 void ima_add_violation(struct file *file, const unsigned char *filename,
   const char *op, const char *cause);
 int ima_init_crypto(void);
+void ima_putc(struct seq_file *m, void *data, int datalen);
+void ima_print_digest(struct seq_file *m, u8 *digest, int size);
 
 int ima_init_template(void);
 
diff --git a/security/integrity/ima/ima_fs.c b/security/integrity/ima/ima_fs.c
index 89adf1d..f9d8d05 100644
--- a/security/integrity/ima/ima_fs.c
+++ b/security/integrity/ima/ima_fs.c
@@ -100,7 +100,7 @@ static void ima_measurements_stop(struct seq_file *m, void 
*v)
 {
 }
 
-static void ima_putc(struct seq_file *m, void *data, int datalen)
+void ima_putc(struct seq_file *m, void *data, int datalen)
 {
while (datalen--)
seq_putc(m, *(char *)data++);
@@ -168,7 +168,7 @@ static const struct file_operations ima_measurements_ops = {
.release = seq_release,
 };
 
-static void ima_print_digest(struct seq_file *m, u8 *digest, int size)
+void ima_print_digest(struct seq_file *m, u8 *digest, int size)
 {
int i;
 
diff --git a/security/integrity/ima/ima_template.c 
b/security/integrity/ima/ima_template.c
index 7e86783..8100422 100644
--- a/security/integrity/ima/ima_template.c
+++ b/security/integrity/ima/ima_template.c
@@ -13,15 +13,20 @@
  *  Helpers to manage template descriptors.
  */
 #include ima.h
+#include ima_template_lib.h
 
 static struct ima_template_desc defined_templates[] = {
+   {.name = IMA_TEMPLATE_IMA_NAME,.fmt = IMA_TEMPLATE_IMA_FMT},
 };
 
 static struct ima_template_field supported_fields[] = {
+   {.field_id = d,.field_init = ima_eventdigest_init,
+.field_show = ima_show_template_digest},
+   {.field_id = n,.field_init = ima_eventname_init,
+.field_show = ima_show_template_string},
 };
 
-static struct ima_template_field *ima_lookup_template_field(
-   const char *field_id)
+static struct ima_template_field *lookup_template_field(const char *field_id)
 {
int i;
 
@@ -32,7 +37,7 @@ static struct ima_template_field *ima_lookup_template_field(
return NULL;
 }
 
-static int ima_template_fmt_size(char *template_fmt)
+static int template_fmt_size(char *template_fmt)
 {
char c;
int template_fmt_len = strlen(template_fmt);
@@ -53,7 +58,7 @@ static int template_desc_init_fields(char *template_fmt,
 int *num_fields)
 {
char *c, *template_fmt_ptr = template_fmt;
-   int template_num_fields = ima_template_fmt_size(template_fmt);
+   int template_num_fields = template_fmt_size(template_fmt

[RFC][PATCH 04/20] ima: read and use signature hash algorithm

2013-07-17 Thread Mimi Zohar
From: Dmitry Kasatkin dmitry.kasat...@gmail.com

All files on the filesystem, currently, are hashed using the same hash
algorithm.  In preparation for files from different packages being
signed using different hash algorithms, this patch adds support for
reading the signature hash algorithm from the 'security.ima' extended
attribute and calculates the appropriate file data hash based on it.

Changelog:
- fix scripts Lindent and checkpatch msgs - Mimi

Signed-off-by: Dmitry Kasatkin d.kasat...@samsung.com
Signed-off-by: Mimi Zohar zo...@linux.vnet.ibm.com
---
 security/integrity/digsig_asymmetric.c | 11 -
 security/integrity/ima/ima.h   | 29 ---
 security/integrity/ima/ima_api.c   | 12 +-
 security/integrity/ima/ima_appraise.c  | 42 +++---
 security/integrity/ima/ima_main.c  | 11 +++--
 security/integrity/integrity.h | 11 +
 6 files changed, 91 insertions(+), 25 deletions(-)

diff --git a/security/integrity/digsig_asymmetric.c 
b/security/integrity/digsig_asymmetric.c
index b475466..9eae480 100644
--- a/security/integrity/digsig_asymmetric.c
+++ b/security/integrity/digsig_asymmetric.c
@@ -20,17 +20,6 @@
 #include integrity.h
 
 /*
- * signature format v2 - for using with asymmetric keys
- */
-struct signature_v2_hdr {
-   uint8_t version;/* signature format version */
-   uint8_t hash_algo;  /* Digest algorithm [enum pkey_hash_algo] */
-   uint32_t keyid; /* IMA key identifier - not X509/PGP specific*/
-   uint16_t sig_size;  /* signature size */
-   uint8_t sig[0]; /* signature payload */
-} __packed;
-
-/*
  * Request an asymmetric key.
  */
 static struct key *request_asymmetric_key(struct key *keyring, uint32_t keyid)
diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h
index eb86032..efcdef2 100644
--- a/security/integrity/ima/ima.h
+++ b/security/integrity/ima/ima.h
@@ -99,7 +99,9 @@ static inline unsigned long ima_hash_key(u8 *digest)
 int ima_get_action(struct inode *inode, int mask, int function);
 int ima_must_measure(struct inode *inode, int mask, int function);
 int ima_collect_measurement(struct integrity_iint_cache *iint,
-   struct file *file);
+   struct file *file,
+   struct evm_ima_xattr_data **xattr_value,
+   int *xattr_len);
 void ima_store_measurement(struct integrity_iint_cache *iint, struct file 
*file,
   const unsigned char *filename);
 void ima_audit_measurement(struct integrity_iint_cache *iint,
@@ -132,17 +134,25 @@ void ima_delete_rules(void);
 
 #ifdef CONFIG_IMA_APPRAISE
 int ima_appraise_measurement(int func, struct integrity_iint_cache *iint,
-struct file *file, const unsigned char *filename);
+struct file *file, const unsigned char *filename,
+struct evm_ima_xattr_data *xattr_value,
+int xattr_len);
 int ima_must_appraise(struct inode *inode, int mask, enum ima_hooks func);
 void ima_update_xattr(struct integrity_iint_cache *iint, struct file *file);
 enum integrity_status ima_get_cache_status(struct integrity_iint_cache *iint,
   int func);
+void ima_get_hash_algo(struct evm_ima_xattr_data *xattr_value, int xattr_len,
+  struct ima_digest_data *hash);
+int ima_read_xattr(struct dentry *dentry,
+  struct evm_ima_xattr_data **xattr_value);
 
 #else
 static inline int ima_appraise_measurement(int func,
   struct integrity_iint_cache *iint,
   struct file *file,
-  const unsigned char *filename)
+  const unsigned char *filename,
+  struct evm_ima_xattr_data 
*xattr_value,
+  int xattr_len)
 {
return INTEGRITY_UNKNOWN;
 }
@@ -163,6 +173,19 @@ static inline enum integrity_status 
ima_get_cache_status(struct integrity_iint_c
 {
return INTEGRITY_UNKNOWN;
 }
+
+static inline void ima_get_hash_algo(struct evm_ima_xattr_data *xattr_value,
+int xattr_len,
+struct ima_digest_data *hash)
+{
+}
+
+static inline int ima_read_xattr(struct dentry *dentry,
+struct evm_ima_xattr_data **xattr_value)
+{
+   return 0;
+}
+
 #endif
 
 /* LSM based policy rules require audit */
diff --git a/security/integrity/ima/ima_api.c b/security/integrity/ima/ima_api.c
index e531fe2..1dba98e 100644
--- a/security/integrity/ima/ima_api.c
+++ b/security/integrity/ima/ima_api.c
@@ -139,17 +139,27 @@ int ima_must_measure(struct inode *inode, int mask, int 
function)
  * Return 0

[RFC][PATCH 19/20] ima: define kernel parameter 'ima_template=' to change configured default

2013-07-17 Thread Mimi Zohar
From: Roberto Sassu roberto.sa...@polito.it

This patch allows users to specify from the kernel command line the
template descriptor, among those defined, that will be used to generate
and display measurement entries. If an user specifies a wrong template,
IMA reverts to the template descriptor set in the kernel configuration.

Signed-off-by: Roberto Sassu roberto.sa...@polito.it
Signed-off-by: Mimi Zohar zo...@linux.vnet.ibm.com
---
 Documentation/kernel-parameters.txt   |  5 +
 security/integrity/ima/ima_template.c | 31 +++
 2 files changed, 36 insertions(+)

diff --git a/Documentation/kernel-parameters.txt 
b/Documentation/kernel-parameters.txt
index cb5daa1..7c60db3 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -1139,6 +1139,11 @@ bytes respectively. Such letter suffixes can also be 
entirely omitted.
programs exec'd, files mmap'd for exec, and all files
opened for read by uid=0.
 
+   ima_template=   [IMA]
+   Select one of defined IMA measurements template formats.
+   Formats: { ima | ima-ng }
+   Default: ima-ng
+
init=   [KNL]
Format: full_path
Run specified binary instead of /sbin/init as init
diff --git a/security/integrity/ima/ima_template.c 
b/security/integrity/ima/ima_template.c
index c28ff9b..0002214 100644
--- a/security/integrity/ima/ima_template.c
+++ b/security/integrity/ima/ima_template.c
@@ -12,6 +12,8 @@
  * File: ima_template.c
  *  Helpers to manage template descriptors.
  */
+#include crypto/hash_info.h
+
 #include ima.h
 #include ima_template_lib.h
 
@@ -32,6 +34,35 @@ static struct ima_template_field supported_fields[] = {
 };
 
 static struct ima_template_desc *ima_template;
+static struct ima_template_desc *lookup_template_desc(const char *name);
+
+static int __init ima_template_setup(char *str)
+{
+   struct ima_template_desc *template_desc;
+   int template_len = strlen(str);
+
+   /*
+* Verify that a template with the supplied name exists.
+* If not, use CONFIG_IMA_DEFAULT_TEMPLATE.
+*/
+   template_desc = lookup_template_desc(str);
+   if (!template_desc)
+   return 1;
+
+   /*
+* Verify whether the current hash algorithm is supported
+* by the 'ima' template.
+*/
+   if (template_len == 3  strcmp(str, IMA_TEMPLATE_IMA_NAME) == 0 
+   ima_hash_algo != HASH_ALGO_SHA1  ima_hash_algo != HASH_ALGO_MD5) {
+   pr_err(IMA: template does not support hash alg\n);
+   return 1;
+   }
+
+   ima_template = template_desc;
+   return 1;
+}
+__setup(ima_template=, ima_template_setup);
 
 static struct ima_template_desc *lookup_template_desc(const char *name)
 {
-- 
1.8.1.4

--
To unsubscribe from this list: send the line unsubscribe linux-crypto in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[RFC][PATCH 13/20] ima: new templates management mechanism

2013-07-17 Thread Mimi Zohar
From: Roberto Sassu roberto.sa...@polito.it

The original 'ima' template is fixed length, containing the filedata hash
and pathname.  The filedata hash is limited to 20 bytes (md5/sha1).  The
pathname is a null terminated string, limited to 255 characters.  To
overcome these limitations and to add additional file metadata, it is
necessary to extend the current version of IMA by defining additional
templates.

The main reason to introduce this feature is that, each time a new
template is defined, the functions that generate and display the
measurement list would include the code for handling a new format and,
thus, would significantly grow over time.

This patch set solves this problem by separating the template management
from the remaining IMA code. The core of this solution is the definition
of two new data structures: a template descriptor, to determine which
information should be included in the measurement list, and a template
field, to generate and display data of a given type.

To define a new template field, developers define the field identifier
and implement two functions, init() and show(), respectively to generate
and display measurement entries.  Initially, this patch set defines the
following template fields (support for additional data types will be
added later):
 - 'd': the digest of the event (i.e. the digest of a measured file),
calculated with the SHA1 or MD5 hash algorithm;
 - 'n': the name of the event (i.e. the file name), with size up to
255 bytes;
 - 'd-ng': the digest of the event, calculated with an arbitrary hash
   algorithm (field format: [hash algo:]digest, where the digest
   prefix is shown only if the hash algorithm is not SHA1 or MD5);
 - 'n-ng': the name of the event, without size limitations.

Defining a new template descriptor requires specifying the template format,
a string of field identifiers separated by the '|' character.  This patch
set defines the following template descriptors:
 - ima: its format is 'd|n';
 - ima-ng (default): its format is 'd-ng|n-ng'

Further details about the new template architecture can be found in
Documentation/security/IMA-templates.txt.

Changelog:
- don't defer calling ima_init_template() - Mimi
- don't define ima_lookup_template_desc() until used - Mimi
- squashed with documentation patch - Mimi

Signed-off-by: Roberto Sassu roberto.sa...@polito.it
Signed-off-by: Mimi Zohar zo...@linux.vnet.ibm.com
---
 Documentation/security/00-INDEX  |   2 +
 Documentation/security/IMA-templates.txt |  87 
 security/integrity/ima/Makefile  |   2 +-
 security/integrity/ima/ima.h |  29 
 security/integrity/ima/ima_init.c|   4 ++
 security/integrity/ima/ima_template.c| 112 +++
 6 files changed, 235 insertions(+), 1 deletion(-)
 create mode 100644 Documentation/security/IMA-templates.txt
 create mode 100644 security/integrity/ima/ima_template.c

diff --git a/Documentation/security/00-INDEX b/Documentation/security/00-INDEX
index 414235c..45c82fd 100644
--- a/Documentation/security/00-INDEX
+++ b/Documentation/security/00-INDEX
@@ -22,3 +22,5 @@ keys.txt
- description of the kernel key retention service.
 tomoyo.txt
- documentation on the TOMOYO Linux Security Module.
+IMA-templates.txt
+   - documentation on the template management mechanism for IMA.
diff --git a/Documentation/security/IMA-templates.txt 
b/Documentation/security/IMA-templates.txt
new file mode 100644
index 000..a777e5f
--- /dev/null
+++ b/Documentation/security/IMA-templates.txt
@@ -0,0 +1,87 @@
+   IMA Template Management Mechanism
+
+
+ INTRODUCTION 
+
+The original 'ima' template is fixed length, containing the filedata hash
+and pathname. The filedata hash is limited to 20 bytes (md5/sha1).
+The pathname is a null terminated string, limited to 255 characters.
+To overcome these limitations and to add additional file metadata, it is
+necessary to extend the current version of IMA by defining additional
+templates. For example, information that could be possibly reported are
+the inode UID/GID or the LSM labels either of the inode and of the process
+that is accessing it.
+
+However, the main problem to introduce this feature is that, each time
+a new template is defined, the functions that generate and display
+the measurements list would include the code for handling a new format
+and, thus, would significantly grow over the time.
+
+The proposed solution solves this problem by separating the template
+management from the remaining IMA code. The core of this solution is the
+definition of two new data structures: a template descriptor, to determine
+which information should be included in the measurement list; a template
+field, to generate and display data of a given type.
+
+Managing templates with these structures is very simple. To support
+a new data type, developers define the field identifier

Re: [RFC 1/1] ima: digital signature verification using asymmetric keys

2013-01-29 Thread Mimi Zohar
On Tue, 2013-01-29 at 15:10 -0500, Vivek Goyal wrote:
 On Tue, Jan 29, 2013 at 03:01:13PM -0500, Mimi Zohar wrote:
 
 [..]
   Hi Mimi,
   
   Can we add another field to ima_rule_entry, say .enforcement to control
   the behavior of .action. Possible values of .enforcement could be, say.
   
   ALL
   SIGNED_ONLY
   
   ALL will be default. And with .action= MEASURE, one could possibly use
   .enforcement=SIGNED_ONLY.
  
  Other than the .action being '.action=APPRAISE', not 'MEASURE',
  something like what you're suggesting, could work.  How about extending
  the new 'appraise_type=' option?   The appraise_type enforces a
  particular type (eg. hash, signature) of verification. 
  
  option: appraise_type:= [imasig[,signed_only]]
  eg. appraise_type=imasig,signed_only
 
 Right. Given the fact that signed_only things work only for appraise, it
 probably is better to extend ima_appraise= command line option.
 
 I just wrote something based on linus tree. That is introduce
 ima_appraise=enforce_labeled_only.
 
 But I would look at your next branch and try introducing
 imasig_signed_only.
 
 In the mean time here is the patch I used. I can now boot my unlabeled
 system with ima_appraise_tcb and ima_appraise=enforce_labeled_only.
 
 But somehow my system has slowed down significantly and I can feel
 slow boot as well as slow file operations on terminal.

The ima_appraise_tcb attempts to appraise all files owned by root, which
is not what you want.  As signatures do not change, you don't need to be
concerned with updating the hash on file close.  Try replacing the
ima_appraise_tcb policy with this one line policy:

appraise fowner=0 func=BPRM_CHECK appraise_type=imasig

thanks,

Mimi


 ---
  Documentation/kernel-parameters.txt   |3 ++-
  security/integrity/ima/ima.h  |1 +
  security/integrity/ima/ima_appraise.c |6 ++
  3 files changed, 9 insertions(+), 1 deletion(-)
 
 Index: linux-2.6/security/integrity/ima/ima_appraise.c
 ===
 --- linux-2.6.orig/security/integrity/ima/ima_appraise.c  2013-01-18 
 01:29:29.0 -0500
 +++ linux-2.6/security/integrity/ima/ima_appraise.c   2013-01-29 
 14:56:47.636620835 -0500
 @@ -24,6 +24,8 @@ static int __init default_appraise_setup
   ima_appraise = 0;
   else if (strncmp(str, fix, 3) == 0)
   ima_appraise = IMA_APPRAISE_FIX;
 + else if (strncmp(str, enforce_labeled_only, 21) == 0)
 + ima_appraise = IMA_APPRAISE_ENFORCE_LABELED_ONLY;
   return 1;
  }
 
 @@ -144,6 +146,10 @@ out:
   ima_fix_xattr(dentry, iint);
   status = INTEGRITY_PASS;
   }
 + if ((ima_appraise  IMA_APPRAISE_ENFORCE_LABELED_ONLY) 
 +(status == INTEGRITY_NOLABEL))
 + status = INTEGRITY_PASS;
 +
   integrity_audit_msg(AUDIT_INTEGRITY_DATA, inode, filename,
   op, cause, rc, 0);
   } else {
 Index: linux-2.6/security/integrity/ima/ima.h
 ===
 --- linux-2.6.orig/security/integrity/ima/ima.h   2013-01-18 
 01:29:29.0 -0500
 +++ linux-2.6/security/integrity/ima/ima.h2013-01-29 14:51:25.762610948 
 -0500
 @@ -140,6 +140,7 @@ void ima_delete_rules(void);
  #define IMA_APPRAISE_ENFORCE 0x01
  #define IMA_APPRAISE_FIX 0x02
  #define IMA_APPRAISE_MODULES 0x04
 +#define IMA_APPRAISE_ENFORCE_LABELED_ONLY0x08
 
  #ifdef CONFIG_IMA_APPRAISE
  int ima_appraise_measurement(struct integrity_iint_cache *iint,
 Index: linux-2.6/Documentation/kernel-parameters.txt
 ===
 --- linux-2.6.orig/Documentation/kernel-parameters.txt2013-01-18 
 01:29:29.0 -0500
 +++ linux-2.6/Documentation/kernel-parameters.txt 2013-01-29 
 14:52:44.455613365 -0500
 @@ -1064,7 +1064,8 @@ bytes respectively. Such letter suffixes
   Set number of hash buckets for inode cache.
 
   ima_appraise=   [IMA] appraise integrity measurements
 - Format: { off | enforce | fix }
 + Format: { off | enforce | fix |
 +   enforce_labeled_only}
   default: enforce
 
   ima_appraise_tcb [IMA]
 



--
To unsubscribe from this list: send the line unsubscribe linux-crypto in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [RFC 1/1] ima: digital signature verification using asymmetric keys

2013-01-28 Thread Mimi Zohar
On Mon, 2013-01-28 at 13:52 -0500, Vivek Goyal wrote:
 On Mon, Jan 28, 2013 at 05:20:20PM +0200, Kasatkin, Dmitry wrote:
 
 [..]
   Ok. I am hoping that it will be more than the kernel command line we
   support. In the sense that for digital signatures one needs to parse
   the signature, look at what hash algorithm has been used  and then
   collect the hash accordingly. It is little different then IMA requirement
   of calculating one pre-determine hash for all files.
  
  Yes... It is obvious. It's coming.
  But in general, signer should be aware of requirements and limitation
  of the platform.
  It is not really a problem...
 
 Ok, I have another question. I was looking at your slide deck here.
 
 http://selinuxproject.org/~jmorris/lss2011_slides/IMA_EVM_Digital_Signature_Support.pdf
 
 Slide 12 mentions that keys are loaded into the kernel from initramfs. If
 root can load any key, what are we protecting against.
 
 IOW, what good ima_appraise_tcb policy, which tries to appraise any root
 owned file.  A root can sign all the files using its own key and load its
 public key in IMA keyring and then integrity check should pass on all
 root files.

 So what's the idea behind digital signature appraisal? By allowing root to
 unconditionally load the keys in IMA keyring, it seems to circumvent the
 appraisal mechanism.

Vivek, you're asking obvious questions, without understanding that what
you want to do is only now possible because of the work that has gone
into upstreaming the different components of the linux-integrity
subsystem (eg. IMA, trusted/encrypted keys, EVM, (MPI library), and now
IMA-appraisal).  In case you weren't aware, Dmitry made the necessary
changes so that the MPI library could be upstreamed for
EVM/IMA-appraisal digital signature support.

I'm pretty sure that keyrings can be locked, preventing additional keys
from being added.  (If it isn't currently supported, it needs to be.)
The _evm and _ima keyrings should definitely be locked.  When/how this
is done, is yet to be defined.  I'm pretty sure there are a number of
people thinking about this, including David Howells, Dmitry Kataskin,
David Safford and myself.

As I previously said, the next steps are to integrate the
EVM/IMA-appraisal public keys in a safe and trusted manner, without
breaking the secure boot signature chain.

thanks,

Mimi

--
To unsubscribe from this list: send the line unsubscribe linux-crypto in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [RFC 1/1] ima: digital signature verification using asymmetric keys

2013-01-28 Thread Mimi Zohar
On Mon, 2013-01-28 at 13:56 -0500, Vivek Goyal wrote:
 On Mon, Jan 28, 2013 at 05:20:20PM +0200, Kasatkin, Dmitry wrote:
 
 [..]
   Ok. I am hoping that it will be more than the kernel command line we
   support. In the sense that for digital signatures one needs to parse
   the signature, look at what hash algorithm has been used  and then
   collect the hash accordingly. It is little different then IMA requirement
   of calculating one pre-determine hash for all files.
  
  Yes... It is obvious. It's coming.
  But in general, signer should be aware of requirements and limitation
  of the platform.
  It is not really a problem...
 
 One more question. I specified ima_appraise_tcb on kernel command line
 and I had an unbootable system. It refused to run init as it was not
 labeled/signed. Is there any policy/way where it appraises only signed
 files and does not refuse to open/execute unsigned ones.

The policy defines what needs to be measured/appraised, not the other
way around.  There's nothing preventing you from defining and loading a
different policy, one to your liking, before pivoting root.

thanks,

Mimi

--
To unsubscribe from this list: send the line unsubscribe linux-crypto in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [RFC 1/1] ima: digital signature verification using asymmetric keys

2013-01-28 Thread Mimi Zohar
On Mon, 2013-01-28 at 15:13 -0500, Vivek Goyal wrote:
 On Mon, Jan 28, 2013 at 02:51:34PM -0500, Mimi Zohar wrote:
  On Mon, 2013-01-28 at 13:52 -0500, Vivek Goyal wrote:
   On Mon, Jan 28, 2013 at 05:20:20PM +0200, Kasatkin, Dmitry wrote:
   
   [..]
 Ok. I am hoping that it will be more than the kernel command line we
 support. In the sense that for digital signatures one needs to parse
 the signature, look at what hash algorithm has been used  and then
 collect the hash accordingly. It is little different then IMA 
 requirement
 of calculating one pre-determine hash for all files.

Yes... It is obvious. It's coming.
But in general, signer should be aware of requirements and limitation
of the platform.
It is not really a problem...
   
   Ok, I have another question. I was looking at your slide deck here.
   
   http://selinuxproject.org/~jmorris/lss2011_slides/IMA_EVM_Digital_Signature_Support.pdf
   
   Slide 12 mentions that keys are loaded into the kernel from initramfs. If
   root can load any key, what are we protecting against.
   
   IOW, what good ima_appraise_tcb policy, which tries to appraise any root
   owned file.  A root can sign all the files using its own key and load its
   public key in IMA keyring and then integrity check should pass on all
   root files.
  
   So what's the idea behind digital signature appraisal? By allowing root to
   unconditionally load the keys in IMA keyring, it seems to circumvent the
   appraisal mechanism.
  
  Vivek, you're asking obvious questions, without understanding that what
  you want to do is only now possible because of the work that has gone
  into upstreaming the different components of the linux-integrity
  subsystem (eg. IMA, trusted/encrypted keys, EVM, (MPI library), and now
  IMA-appraisal).  In case you weren't aware, Dmitry made the necessary
  changes so that the MPI library could be upstreamed for
  EVM/IMA-appraisal digital signature support.
 
 Hi Mimi,
 
 Sure. I am just trying to understand that where are we and how can I 
 help improve things so that I can achieve my objectives.

The slides from the LSS 2012 linux-integrity subsystem status update,
are a bit dated, but at least shows where we're headed.

 The problem I am running into is that I can't find a single good 
 documentation here which explains how to use things. There is no
 single .txt file in Documentation/ directory which explains current
 state of affiars or which explains how to use any of the IMA/EVM
 functionality. 

Sorry, I've been lax in updating the linux-ima sourceforge website.
Usage questions should be posted on the linux-ima-user mailing list.

 So I have no way left but to read code and ask obivious questions
 on mailing list to figure out what components are working, what
 components are work in progress or what's the intent of components
 and how they are supposed to be used.

 So are we saying that all the appraisal and digital signature stuff
 is not useful till we figure a way out to lock down IMA keyring. Or
 it is useful only when root can load the keyring but we are trying
 to appraise only non-root files.

The IMA-appraisal hash was originally protected by EVM and the hmac key,
which was loaded once at boot time, from a TPM based trusted key or
initrd entered passphrase.  With IMA-appraisal digital signature
support, a new keyring for the IMA public keys was added, but without
the needed protection.  David Howell's new 'trusted' keyring would be an
excellent solution to control adding public keys.  (Using the term
'trusted' for both a key type and asymmetric keyring is confusing.)

  I'm pretty sure that keyrings can be locked, preventing additional keys
  from being added.  (If it isn't currently supported, it needs to be.)
  The _evm and _ima keyrings should definitely be locked.  When/how this
  is done, is yet to be defined.  I'm pretty sure there are a number of
  people thinking about this, including David Howells, Dmitry Kataskin,
  David Safford and myself.
  
  As I previously said, the next steps are to integrate the
  EVM/IMA-appraisal public keys in a safe and trusted manner, without
  breaking the secure boot signature chain.
 
 In a private conversation David howells mentioned that IMA keyring
 should allow loading only if new key is trusted by an already loaded
 key. He has already posted some patches for marking a keyring trusted
 and loading keys only if it is signed by a trusted key.

Please feel free to post patches for IMA-appraisal to use the new
'trusted' keyring.

 We were wondring that what use case is served by allowing the root
 to load keys unconditionally. By understanding the use case, atleast
 one can try not to break it.

At some point, there was a discussion on adding a new integrity
capability, with making the package installer a guard process.  With the
new 'trusted' keyring type, this probably isn't necessary.  

The 'trusted' keyring is a solution for installing only

Re: [RFC 1/1] ima: digital signature verification using asymmetric keys

2013-01-28 Thread Mimi Zohar
On Mon, 2013-01-28 at 15:22 -0500, Vivek Goyal wrote:
 On Mon, Jan 28, 2013 at 03:15:49PM -0500, Mimi Zohar wrote:
  On Mon, 2013-01-28 at 13:56 -0500, Vivek Goyal wrote:
   On Mon, Jan 28, 2013 at 05:20:20PM +0200, Kasatkin, Dmitry wrote:
   
   [..]
 Ok. I am hoping that it will be more than the kernel command line we
 support. In the sense that for digital signatures one needs to parse
 the signature, look at what hash algorithm has been used  and then
 collect the hash accordingly. It is little different then IMA 
 requirement
 of calculating one pre-determine hash for all files.

Yes... It is obvious. It's coming.
But in general, signer should be aware of requirements and limitation
of the platform.
It is not really a problem...
   
   One more question. I specified ima_appraise_tcb on kernel command line
   and I had an unbootable system. It refused to run init as it was not
   labeled/signed. Is there any policy/way where it appraises only signed
   files and does not refuse to open/execute unsigned ones.
  
  The policy defines what needs to be measured/appraised, not the other
  way around.  There's nothing preventing you from defining and loading a
  different policy, one to your liking, before pivoting root.
 
 Hi Mimi,
 
 By policy you mean ima rules here? So I can either enable default rules
 (tcb default rules for appraisal and measurement) by using kernel command
 line options or dynamically configure my own rules using /sysfs interface?
 
 If yes, AFAIK, existing inputtable policies do not allow this selective
 mode where we do appraisal only on signed executable. That means I shall
 have to extend the way policies can be specified so that one specify
 that appraise only signed files?

We've just added the ability of defining the method for appraising a
file and defining rules in terms of the filesystem UUID.  Extending the
IMA policy shouldn't be a problem, but I'm not sure how you would go
about adding support for only appraising files with digital signatures.

 Also given the fact that we allow loading policy from initramfs, root
 can rebuild initramfs and change the policy which takes effect over next
 reboot. So in priciple this works only when we are trying to impose some
 policy on non-root users?

The assumption has always been that the initramfs would be measured, for
trusted boot, and appraised, for secure boot, before being executed.

Mimi

--
To unsubscribe from this list: send the line unsubscribe linux-crypto in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [RFC 1/1] ima: digital signature verification using asymmetric keys

2013-01-22 Thread Mimi Zohar
On Tue, 2013-01-15 at 12:34 +0200, Dmitry Kasatkin wrote:
 Asymmetric keys were introduced in linux-3.7 to verify the signature on
 signed kernel modules.  The asymmetric keys infrastructure abstracts the
 signature verification from the crypto details.  This patch adds IMA/EVM
 signature verification using asymmetric keys.  Support for additional
 signature verification methods can now be delegated to the asymmetric
 key infrastructure.
 
 Signed-off-by: Dmitry Kasatkin dmitry.kasat...@intel.com
 ---
  security/integrity/Kconfig  |   12 +
  security/integrity/digsig.c |  103 
 ++-
  2 files changed, 114 insertions(+), 1 deletion(-)
 
 diff --git a/security/integrity/Kconfig b/security/integrity/Kconfig
 index 5bd1cc1..19c4187 100644
 --- a/security/integrity/Kconfig
 +++ b/security/integrity/Kconfig
 @@ -17,5 +17,17 @@ config INTEGRITY_SIGNATURE
 This is useful for evm and module keyrings, when keys are
 usually only added from initramfs.
 
 +config INTEGRITY_ASYMMETRIC_KEYS
 + boolean Digital signature verification using asymmetric keys
 + depends on INTEGRITY_SIGNATURE
 + default n
 +select ASYMMETRIC_KEY_TYPE
 +select ASYMMETRIC_PUBLIC_KEY_SUBTYPE
 +select PUBLIC_KEY_ALGO_RSA
 +select X509_CERTIFICATE_PARSER
 + help
 +   This option enables digital signature verification support
 +   using asymmetric keys.
 +
  source security/integrity/ima/Kconfig
  source security/integrity/evm/Kconfig
 diff --git a/security/integrity/digsig.c b/security/integrity/digsig.c
 index 2dc167d..1896537 100644
 --- a/security/integrity/digsig.c
 +++ b/security/integrity/digsig.c
 @@ -15,10 +15,22 @@
  #include linux/err.h
  #include linux/rbtree.h
  #include linux/key-type.h
 +#include crypto/public_key.h
 +#include keys/asymmetric-type.h
  #include linux/digsig.h
 
  #include integrity.h
 
 +/*
 + * signature format v2 - for using with asymmetric keys
 + */
 +struct signature_v2_hdr {
 + uint8_t version;/* signature format version */
 + uint8_t hash_algo;  /* Digest algorithm [enum pkey_hash_algo] */
 + uint8_t keyid[8];   /* IMA key identifier - not X509/PGP specific*/
 + uint8_t payload[0]; /* signature payload */
 +} __packed;
 +
  static struct key *keyring[INTEGRITY_KEYRING_MAX];
 
  static const char *keyring_name[INTEGRITY_KEYRING_MAX] = {
 @@ -27,6 +39,91 @@ static const char *keyring_name[INTEGRITY_KEYRING_MAX] = {
   _ima,
  };
 
 +#ifdef CONFIG_INTEGRITY_ASYMMETRIC_KEYS
 +
 +/*
 + * Request an asymmetric key.
 + */
 +static struct key *request_asymmetric_key(struct key *keyring, uint8_t 
 *keyid)
 +{
 + struct key *key;
 + char name[20];
 +
 + sprintf(name, %llX, __be64_to_cpup((uint64_t *)keyid));
 +
 + pr_debug(key search: \%s\\n, name);
 +
 + if (keyring) {
 + /* search in specific keyring */
 + key_ref_t kref;
 + kref = keyring_search(make_key_ref(keyring, 1),
 +   key_type_asymmetric, name);
 + if (IS_ERR(kref))
 + key = ERR_CAST(kref);
 + else
 + key = key_ref_to_ptr(kref);
 + } else {
 + key = request_key(key_type_asymmetric, name, NULL);
 + }
 +
 + if (IS_ERR(key)) {
 + pr_warn(Request for unknown key '%s' err %ld\n,
 + name, PTR_ERR(key));
 + switch (PTR_ERR(key)) {
 + /* Hide some search errors */
 + case -EACCES:
 + case -ENOTDIR:
 + case -EAGAIN:
 + return ERR_PTR(-ENOKEY);
 + default:
 + return key;
 + }
 + }
 +
 + pr_debug(%s() = 0 [%x]\n, __func__, key_serial(key));
 +
 + return key;
 +}
 +
 +static int asymmetric_verify(struct key *keyring, const char *sig,
 +  size_t siglen, const char *data, int datalen)
 +{
 + struct public_key_signature pks;
 + struct signature_v2_hdr *hdr = (struct signature_v2_hdr *)sig;
 + struct key *key;
 + int ret = -ENOMEM;
 +
 + if (siglen = sizeof(*hdr))
 + return -EBADMSG;
 +
 + siglen -= sizeof(*hdr);
 +
 + if (hdr-hash_algo = PKEY_HASH__LAST)
 + return -ENOPKG;
 +
 + key = request_asymmetric_key(keyring, hdr-keyid);
 + if (IS_ERR(key))
 + return PTR_ERR(key);
 +
 + memset(pks, 0, sizeof(pks));
 +
 + pks.pkey_hash_algo = hdr-hash_algo;
 + pks.digest = (u8 *)data;
 + pks.digest_size = datalen;
 + pks.nr_mpi = 1;
 + pks.rsa.s = mpi_read_from_buffer(hdr-payload, siglen);
 +
 + if (pks.rsa.s)
 + ret = verify_signature(key, pks);
 +
 + mpi_free(pks.rsa.s);
 + key_put(key);
 + pr_debug(%s() = %d\n, __func__, ret);
 + return ret;
 +}
 +
 +#endif /* CONFIG_INTEGRITY_ASYMMETRIC_KEYS */
 +
  int integrity_digsig_verify(const 

Re: [RFC 0/1] ima/evm: signature verification support using asymmetric keys

2013-01-18 Thread Mimi Zohar
On Thu, 2013-01-17 at 18:03 +, David Howells wrote:

 I would also like to have a look at altering your trusted key type[*] to be a
 subtype of asymmetric keys so that the asymmetric key type can cover keys from
 more sources:
 
   - Compiled-in keys.
   - Keys from UEFI db.
   - Keys from TPM (ie. the trusted key stuff).
   - Keys loaded by the administrator _if_ they are validated by a key the
 kernel already has.
   
 [*] I believe that that's your asymmetric key type and that your encrypted key
 type is your symmetric key type.

Both trusted and encrypted keys are random number symmetric keys.
Trusted keys are random number symmetric keys, generated and RSA-sealed
by the TPM.

Mimi


--
To unsubscribe from this list: send the line unsubscribe linux-crypto in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH 1/3] KEYS: Load *.x509 files into kernel keyring

2013-01-17 Thread Mimi Zohar
On Thu, 2013-01-17 at 18:03 +, David Howells wrote:
 Load all the files matching the pattern *.x509 that are to be found in 
 kernel
 base source dir and base build dir into the module signing keyring.

Do we really want certificates cluttering up the base source tree? Any
reason not to define an x509 directory?

 The extra_certificates file is then redundant.

Ok.

Mimi

--
To unsubscribe from this list: send the line unsubscribe linux-crypto in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [GIT PULL] Asymmetric keys and module signing

2012-09-26 Thread Mimi Zohar
On Wed, 2012-09-26 at 13:16 +0930, Rusty Russell wrote:
 David Howells dhowe...@redhat.com writes:
  The module signing patches provide:
 
   - Some fixes to Rusty's patch.  Also an additional patch to extend the 
  policy
 handling for modules signed with an unknown key and to handle FIPS mode.
 
 Ok, I merged some of this (after our previous accidentally-off-list
 discussion).

Rusty, have you pushed this branch out yet?

thanks,

Mimi

--
To unsubscribe from this list: send the line unsubscribe linux-crypto in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH 07/21] KEYS: Create a key type that can be used for general cryptographic operations [ver #3]

2012-01-16 Thread Mimi Zohar
On Fri, 2011-12-02 at 18:43 +, David Howells wrote:
 Create a key type that can be used for general cryptographic operations, such
 as encryption, decryption, signature generation and signature verification.
 
 The key type is crypto and can provide access to a variety of cryptographic
 algorithms.
 
 Signed-off-by: David Howells dhowe...@redhat.com

Nice! Basically the 'crypto' key type ties crypto/ with security/keys.
Other than the posted pgp key parser used for verifying kernel module
signatures, I assume another use case could be to expose kernel
cryptography to userspace.  As there was a submission
https://lkml.org/lkml/2010/8/20/103 to do just this, there must be
userspace apps that would benefit.  This architecture would address a
number of concerns raised with the prior submission. (Refer to
http://lwn.net/Articles/401548/.)

You'd probably want to move the 'crypto' key type to its own directory.

Acked-by: Mimi Zohar zo...@us.ibm.com

thanks,
Mimi

 ---
 
  Documentation/security/keys-crypto.txt |  181 +
  include/keys/crypto-subtype.h  |   56 
  include/keys/crypto-type.h |   25 +++
  security/keys/Kconfig  |8 +
  security/keys/Makefile |3 
  security/keys/crypto_keys.h|   28 
  security/keys/crypto_type.c|  230 
 
  7 files changed, 531 insertions(+), 0 deletions(-)
  create mode 100644 Documentation/security/keys-crypto.txt
  create mode 100644 include/keys/crypto-subtype.h
  create mode 100644 include/keys/crypto-type.h
  create mode 100644 security/keys/crypto_keys.h
  create mode 100644 security/keys/crypto_type.c
 
 
 diff --git a/Documentation/security/keys-crypto.txt 
 b/Documentation/security/keys-crypto.txt
 new file mode 100644
 index 000..97dee80
 --- /dev/null
 +++ b/Documentation/security/keys-crypto.txt
 @@ -0,0 +1,181 @@
 + ==
 + CRYPTOGRAPHIC KEY TYPE
 + ==
 +
 +Contents:
 +
 +  - Overview.
 +  - Key identification.
 +  - Accessing crypto keys.
 +  - Implementing crypto parsers.
 +  - Implementing crypto subtypes.
 +
 +
 +
 +OVERVIEW
 +
 +
 +The crypto key type is designed to be a container for cryptographic keys,
 +without imposing any particular restrictions on the form of the cryptography 
 or
 +the key.
 +
 +The crypto key is given a subtype that defines what sort of data is 
 associated
 +with the key and provides operations to describe and destroy it.  However, no
 +requirement is made that the key data actually be loaded into the key.
 +
 +The crypto key also has a number of data parsers registered with it.  The 
 data
 +parsers are responsible for extracing information the blobs of data passed to
 +the instantiator function.  The first data parser that recognises the blob 
 gets
 +to set the subtype of the key and define the operations that can be done on
 +that key.
 +
 +Completely in-kernel key retention and operation subtypes and parsers can be
 +defined, but it would also be possible to provide access to cryptographic
 +hardware (such as a TPM) that might be used to both retain the relevant key 
 and
 +perform operations using that key.  In such a case, the crypto key would then
 +merely be an interface to the TPM driver.
 +
 +
 +==
 +KEY IDENTIFICATION
 +==
 +
 +Because the identity of a key is not necessarily known and may not be easily
 +calculated when a crypto key is allocated, it may not be a simple matter to 
 set
 +a key description to something that's useful for determining whether this is
 +the key you're looking for.  Furthermore, it may be necessary to perform a
 +partial match upon the key identity.
 +
 +To help with this, when a key is loaded, the parser calculates the key
 +fingerprint and stores a copy in the key structure.
 +
 +The crypto key type's key matching function then performs more checks than 
 just
 +the straightforward comparison of the description with the criterion string:
 +
 + (1) If the criterion string is of the form id:hexdigits then the match
 + function will examine a key's fingerprint to see if the hex digits given
 + after the id: match the tail.  For instance:
 +
 + keyctl search @s crypto id:5acc2142
 +
 + will match a key with fingerprint:
 +
 + 1A00 2040 7601 7889 DE11  882C 3823 04AD 5ACC 2142
 +
 + (2) If the criterion string is of the form subtype:hexdigits then the
 + match will match the ID as in (1), but with the added restriction that
 + only keys of the specified subtype (e.g. dsa or rsa) will be matched.  
 For
 + instance:
 +
 + keyctl search @s crypto dsa:5acc2142
 +
 +Looking in /proc/keys, the last 8 hex digits of the key fingerprint are
 +displayed, along with the subtype:
 +
 + 1a39e171 I- 1 perm 3f01 0 0 cryptomodsign.0: 
 DSA

Re: [RFC][PATCH 00/21] Crypto keys and module signing [ver #3]

2012-01-08 Thread Mimi Zohar
On Fri, 2011-12-02 at 18:42 +, David Howells wrote:
 Here are a set of patches that create a framework for using cryptographic keys
 within the kernel.  The patches can also be found at:
 
   
 http://git.kernel.org/?p=linux/kernel/git/dhowells/linux-modsign.git;a=shortlog;h=refs/heads/devel

Patches 2, 4, 5, and 6 are simple, straight forward Key cleanup.  Please
add my Acks.

thanks,

Mimi

--
To unsubscribe from this list: send the line unsubscribe linux-crypto in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v2.2 6/7] integrity: digital signature verification using multiple keyrings

2011-11-04 Thread Mimi Zohar
On Wed, 2011-10-19 at 14:51 +0300, Dmitry Kasatkin wrote:
 Define separate keyrings for each of the different use cases - evm, ima,
 and modules. Using different keyrings improves search performance, and also
 allows locking specific keyring to prevent adding new keys.
 This is useful for evm and module keyrings, when keys are usually only
 added from initramfs.
 
 Signed-off-by: Dmitry Kasatkin dmitry.kasat...@intel.com

Thanks Dmitry!  Other than the couple of trailing whitespaces, the
patches look good.  I think adding the word 'public', above, to 'adding
new keys' clarifies that the keyrings are only used for the digital
signatures.

Acked-by: Mimi Zohar zo...@us.ibm.com

 ---
  security/integrity/Kconfig |   14 +++
  security/integrity/Makefile|1 +
  security/integrity/digsig.c|   48 
 
  security/integrity/integrity.h |   20 
  4 files changed, 83 insertions(+), 0 deletions(-)
  create mode 100644 security/integrity/digsig.c
 
 diff --git a/security/integrity/Kconfig b/security/integrity/Kconfig
 index 4bf00ac..d87fa2a 100644
 --- a/security/integrity/Kconfig
 +++ b/security/integrity/Kconfig
 @@ -3,5 +3,19 @@ config INTEGRITY
   def_bool y
   depends on IMA || EVM
 
 +config INTEGRITY_DIGSIG
 + boolean Digital signature verification using multiple keyrings
 + depends on INTEGRITY
 + default n
 + select DIGSIG
 + help
 +   This option enables digital signature verification support
 +   using multiple keyrings. It defines separate keyrings for each
 +   of the different use cases - evm, ima, and modules.
 +   Different keyrings improves search performance, but also allow
 +   to lock certain keyring to prevent adding new keys.
 +   This is useful for evm and module keyrings, when keys are
 +   usually only added from initramfs.
 +
  source security/integrity/ima/Kconfig
  source security/integrity/evm/Kconfig
 diff --git a/security/integrity/Makefile b/security/integrity/Makefile
 index 0ae44ae..bece056 100644
 --- a/security/integrity/Makefile
 +++ b/security/integrity/Makefile
 @@ -3,6 +3,7 @@
  #
 
  obj-$(CONFIG_INTEGRITY) += integrity.o
 +obj-$(CONFIG_INTEGRITY_DIGSIG) += digsig.o
 
  integrity-y := iint.o
 
 diff --git a/security/integrity/digsig.c b/security/integrity/digsig.c
 new file mode 100644
 index 000..b5d1e01
 --- /dev/null
 +++ b/security/integrity/digsig.c
 @@ -0,0 +1,48 @@
 +/*
 + * Copyright (C) 2011 Intel Corporation
 + *
 + * Author:
 + * Dmitry Kasatkin dmitry.kasat...@intel.com
 + *
 + * This program 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, version 2 of the License.
 + *
 + */
 +
 +#define pr_fmt(fmt) KBUILD_MODNAME :  fmt
 +
 +#include linux/err.h
 +#include linux/rbtree.h
 +#include linux/key-type.h
 +#include linux/digsig.h
 +
 +#include integrity.h
 +
 +static struct key *keyring[INTEGRITY_KEYRING_MAX];
 +
 +static const char *keyring_name[INTEGRITY_KEYRING_MAX] = {
 + _evm,
 + _module,
 + _ima,
 +};
 +
 +int integrity_digsig_verify(const unsigned int id, const char *sig, int 
 siglen,
 + const char *digest, int digestlen)
 +{
 + if (id = INTEGRITY_KEYRING_MAX)
 + return -EINVAL;
 +
 + if (!keyring[id]) {
 + keyring[id] =
 + request_key(key_type_keyring, keyring_name[id], NULL);
 + if (IS_ERR(keyring[id])) {
 + pr_err(no %s keyring: %ld\n, keyring_name[id],
 + PTR_ERR(keyring[id]));
 + keyring[id] = NULL;
 + return PTR_ERR(keyring[id]);
 + }
 + }
 +
 + return digsig_verify(keyring[id], sig, siglen, digest, digestlen);
 +}
 diff --git a/security/integrity/integrity.h b/security/integrity/integrity.h
 index e898094..9fc723b 100644
 --- a/security/integrity/integrity.h
 +++ b/security/integrity/integrity.h
 @@ -51,5 +51,25 @@ struct integrity_iint_cache {
  struct integrity_iint_cache *integrity_iint_insert(struct inode *inode);
  struct integrity_iint_cache *integrity_iint_find(struct inode *inode);
 
 +#define INTEGRITY_KEYRING_EVM0
 +#define INTEGRITY_KEYRING_MODULE 1
 +#define INTEGRITY_KEYRING_IMA2
 +#define INTEGRITY_KEYRING_MAX3
 +
 +#ifdef CONFIG_INTEGRITY_DIGSIG
 +
 +int integrity_digsig_verify(const unsigned int id, const char *sig, int 
 siglen,
 + const char *digest, int digestlen);
 +
 +#else
 +
 +static inline int integrity_digsig_verify(const unsigned int id, const char 
 *sig, int siglen,
 + const char *digest, int digestlen)
 +{
 + return -EOPNOTSUPP;
 +}
 +
 +#endif /* CONFIG_INTEGRITY_DIGSIG */
 +
  /* set during initialization

Re: [RFC v2.1 0/6] evm: digital signature verification extension

2011-09-20 Thread Mimi Zohar
On Tue, 2011-09-13 at 17:20 +0300, Dmitry Kasatkin wrote: 
 Hello,
 
 Changes to version 2.0:
 - MPI patch has been split to smaller in order to go to mailing lists.
   First 2 patches include only source and header files which are needed
   to build ksign verification. Headers and sources are split just to
   meet 100k kernel.org limit.
   Last patch adds all rest soures from original ported MPI library.
   
 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.

Hi Herbert

Back in March 2011, in preparation for EVM, Dmitry posted the GnuPG MPI
library patch here on linux-crypto. The reason given for not upstreaming
the MPI library, at the time, was for lack of an in kernel user
(http://www.mail-archive.com/linux-crypto@vger.kernel.org/msg05613.html).
With the recent merging of the EVM patches in linux-next, via
security-testing-2.6/#next, that is changing.  Any chance of re-opening
the discussion? 

thanks,

Mimi

--
To unsubscribe from this list: send the line unsubscribe linux-crypto in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v1.5 5/5] keys: add new key-type encrypted

2010-12-07 Thread Mimi Zohar
On Fri, 2010-12-03 at 13:42 +, David Howells wrote: 
 Mimi Zohar zo...@linux.vnet.ibm.com wrote:
 
  +#define KEY_TRUSTED_PREFIX trusted:
  +#define KEY_TRUSTED_PREFIX_LEN (sizeof (KEY_TRUSTED_PREFIX) - 1)
  +#define KEY_USER_PREFIX user:
  +#define KEY_USER_PREFIX_LEN (sizeof (KEY_USER_PREFIX) - 1)
 
 I'd recommend using static const char arrays.

Ok

  +static int datablob_parse(char *datablob, char **master_desc,
  ...
  +   *hex_encoded_data = *hex_encoded_iv + (2 * ivsize) + 2;
 
 Do you need to validate the length of the string here?

definitely. thanks!

  +static struct key *request_trusted_key(const char *trusted_desc,
  +  u8 **master_key,
  +  unsigned int *master_keylen)
 
 You need to annotate the function with an __acquires() to indicate that it
 returns with a lock held for Sparse checking.  I think you should be able to
 do:
 
   __acquires(tkey-sem)

hm, only after addding '__acquires' are there Sparse errors.

 on the line before the '{'.
 
  +static struct key *request_user_key(const char *master_desc, u8 
  **master_key,
  +   unsigned int *master_keylen)
 
 Ditto.
 
  +static struct sdesc *init_sdesc(struct crypto_shash *alg)
  +{
  +   struct sdesc *sdesc;
  +   int size;
  +
  +   size = sizeof(struct shash_desc) + crypto_shash_descsize(alg);
  +   sdesc = kmalloc(size, GFP_KERNEL);
 
 I think I'd call it alloc_sdesc() rather than init_sdesc().

Ok

  +static int calc_hmac(u8 *digest, const u8 *key, const unsigned int keylen,
  +const u8 *buf, const unsigned int buflen)
 
 size_t not 'const unsigned int' please.  There are multiple of these within
 the patch.

Have reverted adding the unnecessary 'const' and converted some
additional 'unsigned int' to 'size_t', but there are still some
remaining; those used as crypto options.

  +   sg_set_buf(sg_out[0], epayload-decrypted_data,
  +  (unsigned int)epayload-decrypted_datalen);
 
 Superfluous cast.
 
 David

thanks!

Mimi 

--
To unsubscribe from this list: send the line unsubscribe linux-crypto in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v1.5 5/5] keys: add new key-type encrypted

2010-11-24 Thread Mimi Zohar
Sorry for the multiple postings, misconfigured mailer bounced patch 5.
Resending ...

Define a new kernel key-type called 'encrypted'. Encrypted keys are kernel
generated random numbers, which are encrypted/decrypted with a 'trusted'
symmetric key. Encrypted keys are created/encrypted/decrypted in the kernel.
Userspace only ever sees/stores encrypted blobs.

Changelog:
- bug fix: replaced master-key rcu based locking with semaphore
  (reported by David Howells)
- Removed memset of crypto_shash_digest() digest output
- Replaced verification of 'key-type:key-desc' using strcspn(), with
  one based on string constants.
- Moved documentation to Documentation/keys-trusted-encrypted.txt
- Replace hash with shash (based on comments by David Howells)
- Make lengths/counts size_t where possible (based on comments by David Howells)
  Could not convert most lengths, as crypto expects 'unsigned int'
  (size_t: on 32 bit is defined as unsigned int, but on 64 bit is unsigned long)
- Add 'const' where possible (based on comments by David Howells)
- allocate derived_buf dynamically to support arbitrary length master key
  (fixed by Roberto Sassu)
- wait until late_initcall for crypto libraries to be registered
- cleanup security/Kconfig
- Add missing 'update' keyword (reported/fixed by Roberto Sassu)
- Free epayload on failure to create key (reported/fixed by Roberto Sassu)
- Increase the data size limit (requested by Roberto Sassu)
- Crypto return codes are always 0 on success and negative on failure,
  remove unnecessary tests.
- Replaced kzalloc() with kmalloc()

Signed-off-by: Mimi Zohar zo...@us.ibm.com
Signed-off-by: David Safford saff...@watson.ibm.com
Reviewed-by: Roberto Sassu roberto.sa...@polito.it
---
 include/keys/encrypted-type.h |   29 ++
 security/Kconfig  |   16 +
 security/keys/Makefile|1 +
 security/keys/encrypted_defined.c |  907 +
 security/keys/encrypted_defined.h |   56 +++
 5 files changed, 1009 insertions(+), 0 deletions(-)
 create mode 100644 include/keys/encrypted-type.h
 create mode 100644 security/keys/encrypted_defined.c
 create mode 100644 security/keys/encrypted_defined.h

diff --git a/include/keys/encrypted-type.h b/include/keys/encrypted-type.h
new file mode 100644
index 000..9585501
--- /dev/null
+++ b/include/keys/encrypted-type.h
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2010 IBM Corporation
+ * Author: Mimi Zohar zo...@us.ibm.com
+ *
+ * This program 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, version 2 of the License.
+ */
+
+#ifndef _KEYS_ENCRYPTED_TYPE_H
+#define _KEYS_ENCRYPTED_TYPE_H
+
+#include linux/key.h
+#include linux/rcupdate.h
+
+struct encrypted_key_payload {
+   struct rcu_head rcu;
+   char *master_desc;  /* datablob: master key name */
+   char *datalen;  /* datablob: decrypted key length */
+   u8 *iv; /* datablob: iv */
+   u8 *encrypted_data; /* datablob: encrypted data */
+   unsigned short datablob_len;/* length of datablob */
+   unsigned short decrypted_datalen;   /* decrypted data length */
+   u8 decrypted_data[0];   /* decrypted data +  datablob + hmac */
+};
+
+extern struct key_type key_type_encrypted;
+
+#endif /* _KEYS_ENCRYPTED_TYPE_H */
diff --git a/security/Kconfig b/security/Kconfig
index be2d1c6..de2a170 100644
--- a/security/Kconfig
+++ b/security/Kconfig
@@ -36,6 +36,22 @@ config TRUSTED_KEYS
 
  If you are unsure as to whether this is required, answer N.
 
+config ENCRYPTED_KEYS
+   tristate ENCRYPTED KEYS
+   depends on KEYS  TRUSTED_KEYS
+   select CRYPTO_AES
+   select CRYPTO_CBC
+   select CRYPTO_SHA256
+   select CRYPTO_RNG
+   help
+ This option provides support for create/encrypting/decrypting keys
+ in the kernel.  Encrypted keys are kernel generated random numbers,
+ which are encrypted/decrypted with a 'master' symmetric key. The
+ 'master' key can be either a trusted-key or user-key type.
+ Userspace only ever sees/stores encrypted blobs.
+
+ If you are unsure as to whether this is required, answer N.
+
 config KEYS_DEBUG_PROC_KEYS
bool Enable the /proc/keys file by which keys may be viewed
depends on KEYS
diff --git a/security/keys/Makefile b/security/keys/Makefile
index fcb1070..6c94105 100644
--- a/security/keys/Makefile
+++ b/security/keys/Makefile
@@ -14,6 +14,7 @@ obj-y := \
user_defined.o
 
 obj-$(CONFIG_TRUSTED_KEYS) += trusted_defined.o
+obj-$(CONFIG_ENCRYPTED_KEYS) += encrypted_defined.o
 obj-$(CONFIG_KEYS_COMPAT) += compat.o
 obj-$(CONFIG_PROC_FS) += proc.o
 obj-$(CONFIG_SYSCTL) += sysctl.o
diff --git a/security/keys/encrypted_defined.c 
b/security/keys/encrypted_defined.c
new file mode 100644
index 000..0e558dc
--- /dev/null
+++ b/security/keys

crypto_shash_digest API

2010-11-23 Thread Mimi Zohar
Hi!

Am having problems finding any shash API documentation.  Could someone
tell me if 'out' needs to be zeroed before calling crypto_shash_digest?

int crypto_shash_digest(struct shash_desc *desc, const u8 *data,
unsigned int len, u8 *out)

thanks,

Mimi

--
To unsubscribe from this list: send the line unsubscribe linux-crypto in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v1.5 0/5] keys: trusted and encrypted keys

2010-11-23 Thread Mimi Zohar
Changes in this patchset were again based on David Howell's comments,
including an encrypted key locking bugfix. The remaining changes are
listed in the individual patch changelogs. (This patchset applies to
security-testing/#next.)

Trusted and Encrypted Keys are two new key types added to the existing
kernel key ring service. Both of these new types are variable length
symmetic keys, and in both cases all keys are created in the kernel, and
user space sees, stores, and loads only encrypted blobs.  Trusted Keys
require the availability of a Trusted Platform Module (TPM) chip for
greater security, while Encrypted Keys can be used on any system. All
user level blobs, are displayed and loaded in hex ascii for convenience,
and are integrity verified.  

Trusted Keys use a TPM both to generate and to seal the keys.  Keys are
sealed under a 2048 bit RSA key in the TPM, and optionally sealed to
specified PCR (integrity measurement) values, and only unsealed by the
TPM, if PCRs and blob integrity verifications match.  A loaded Trusted
Key can be updated with new (future) PCR values, so keys are easily
migrated to new pcr values, such as when the kernel and initramfs are
updated.  The same key can have many saved blobs under different PCR
values, so multiple boots are easily supported.

By default, trusted keys are sealed under the SRK, which has the default
authorization value (20 zeros).  This can be set at takeownership time
with the trouser's utility: tpm_takeownership -u -z.

Usage:
keyctl add trusted name new keylen [options] ring
keyctl add trusted name load hex_blob [pcrlock=pcrnum] ring
keyctl update key update [options]
keyctl print keyid

options:
   keyhandle= ascii hex value of sealing key default 0x4000 (SRK)
   keyauth=   ascii hex auth for sealing key default 0x00...
  (40 ascii zeros)
   blobauth=  ascii hex auth for sealed data default 0x00...
  (40 ascii zeros)
   pcrinfo=   ascii hex of PCR_INFO or PCR_INFO_LONG (no default)
   pcrlock=   pcr number to be extended to lock blob
   migratable= 0|1 indicating permission to reseal to new PCR values, 
   default 1 (resealing allowed)

keyctl print returns an ascii hex copy of the sealed key, which is in
standard TPM_STORED_DATA format.  The key length for new keys are always
in bytes.  Trusted Keys can be 32 - 128 bytes (256 - 1024 bits), the
upper limit is to fit within the 2048 bit SRK (RSA) keylength, with all
necessary structure/padding. 

Encrypted keys do not depend on a TPM, and are faster, as they use AES
for encryption/decryption.  New keys are created from kernel generated
random numbers, and are encrypted/decrypted using a specified 'master'
key.  The 'master' key can either be a trusted-key or user-key type. The
main disadvantage of encrypted keys is that if they are not rooted in a
trusted key, they are only as secure as the user key encrypting them.
The master user key should therefore be loaded in as secure a way as
possible, preferably early in boot.

Usage:
  keyctl add encrypted name new master-key-name keylen ring
  keyctl add encrypted name load hex_blob ring
  keyctl update keyid update master-key-name

where 'key-type' is either 'trusted' or 'user'.

The initial consumer of trusted keys is EVM, which at boot time needs a
high quality symmetric key for HMAC protection of file metadata. The use
of a trusted key provides strong guarantees that the EVM key has not
been compromised by a user level problem, and when sealed to specific
boot PCR values, protects against boot and offline attacks.  Other uses
for trusted and encrypted keys, such as for disk and file encryption are
anticipated.

Mimi Zohar
David Safford

Mimi Zohar (5):
  lib: hex2bin converts ascii hexadecimal string to binary
  tpm: add module_put wrapper
  key: add tpm_send command
  keys: add new trusted key-type
  keys: add new key-type encrypted

 Documentation/keys-trusted-encrypted.txt |  145 
 drivers/char/tpm/tpm.c   |   20 +-
 drivers/char/tpm/tpm.h   |5 +
 include/keys/encrypted-type.h|   29 +
 include/keys/trusted-type.h  |   31 +
 include/linux/kernel.h   |1 +
 include/linux/tpm.h  |4 +
 include/linux/tpm_command.h  |   28 +
 lib/hexdump.c|   16 +
 security/Kconfig |   31 +
 security/keys/Makefile   |2 +
 security/keys/encrypted_defined.c|  907 +++
 security/keys/encrypted_defined.h|   56 ++
 security/keys/trusted_defined.c  | 1151 ++
 security/keys/trusted_defined.h  |  134 
 15 files changed, 2558 insertions(+), 2 deletions(-)
 create mode 100644 Documentation/keys-trusted-encrypted.txt
 create mode 100644 include/keys/encrypted-type.h
 create mode 100644 include/keys/trusted-type.h
 create

[PATCH v1.5 2/5] tpm: add module_put wrapper

2010-11-23 Thread Mimi Zohar
For readability, define a tpm_chip_put() wrapper to call module_put().
Replace existing module_put() calls with the wrapper.

(Change based on trusted/encrypted patchset review by David Howells.)

Signed-off-by: Mimi Zohar zo...@us.ibm.com
Signed-off-by: David Safford saff...@watson.ibm.com
Acked-by: David Howells dhowe...@redhat.com
---
 drivers/char/tpm/tpm.c |4 ++--
 drivers/char/tpm/tpm.h |5 +
 2 files changed, 7 insertions(+), 2 deletions(-)

diff --git a/drivers/char/tpm/tpm.c b/drivers/char/tpm/tpm.c
index 7c41335..26c09f3 100644
--- a/drivers/char/tpm/tpm.c
+++ b/drivers/char/tpm/tpm.c
@@ -736,7 +736,7 @@ int tpm_pcr_read(u32 chip_num, int pcr_idx, u8 *res_buf)
if (chip == NULL)
return -ENODEV;
rc = __tpm_pcr_read(chip, pcr_idx, res_buf);
-   module_put(chip-dev-driver-owner);
+   tpm_chip_put(chip);
return rc;
 }
 EXPORT_SYMBOL_GPL(tpm_pcr_read);
@@ -775,7 +775,7 @@ int tpm_pcr_extend(u32 chip_num, int pcr_idx, const u8 
*hash)
rc = transmit_cmd(chip, cmd, EXTEND_PCR_RESULT_SIZE,
  attempting extend a PCR value);
 
-   module_put(chip-dev-driver-owner);
+   tpm_chip_put(chip);
return rc;
 }
 EXPORT_SYMBOL_GPL(tpm_pcr_extend);
diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h
index 792868d..72ddb03 100644
--- a/drivers/char/tpm/tpm.h
+++ b/drivers/char/tpm/tpm.h
@@ -113,6 +113,11 @@ struct tpm_chip {
 
 #define to_tpm_chip(n) container_of(n, struct tpm_chip, vendor)
 
+static inline void tpm_chip_put(struct tpm_chip *chip)
+{
+   module_put(chip-dev-driver-owner);
+}
+
 static inline int tpm_read_index(int base, int index)
 {
outb(index, base);
-- 
1.7.2.2

--
To unsubscribe from this list: send the line unsubscribe linux-crypto in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v1.5 4/5] keys: add new trusted key-type

2010-11-23 Thread Mimi Zohar
Define a new kernel key-type called 'trusted'.  Trusted keys are random
number symmetric keys, generated and RSA-sealed by the TPM.  The TPM
only unseals the keys, if the boot PCRs and other criteria match.
Userspace can only ever see encrypted blobs.

Based on suggestions by Jason Gunthorpe, several new options have been
added to support additional usages.

The new options are:
migratable=  designates that the key may/may not ever be updated
 (resealed under a new key, new pcrinfo or new auth.)

pcrlock=nextends the designated PCR 'n' with a random value,
 so that a key sealed to that PCR may not be unsealed
 again until after a reboot.

keyhandle=   specifies the sealing/unsealing key handle.

keyauth= specifies the sealing/unsealing key auth.

blobauth=specifies the sealed data auth.

Implementation of a kernel reserved locality for trusted keys will be
investigated for a possible future extension.

Changelog:
- Updated and added examples to Documentation/keys-trusted-encrypted.txt
- Moved generic TPM constants to include/linux/tpm_command.h
  (David Howell's suggestion.)
- trusted_defined.c: replaced kzalloc with kmalloc, added pcrlock failure
  error handling, added const qualifiers where appropriate.
- moved to late_initcall
- updated from hash to shash (suggestion by David Howells)
- reduced worst stack usage (tpm_seal) from 530 to 312 bytes
- moved documentation to Documentation directory (suggestion by David Howells)
- all the other code cleanups suggested by David Howells
- Add pcrlock CAP_SYS_ADMIN dependency (based on comment by Jason Gunthorpe)
- New options: migratable, pcrlock, keyhandle, keyauth, blobauth (based on
  discussions with Jason Gunthorpe)
- Free payload on failure to create key(reported/fixed by Roberto Sassu)
- Updated Kconfig and other descriptions (based on Serge Hallyn's suggestion)
- Replaced kzalloc() with kmalloc() (reported by Serge Hallyn)

Signed-off-by: David Safford saff...@watson.ibm.com
Signed-off-by: Mimi Zohar zo...@us.ibm.com
---
 Documentation/keys-trusted-encrypted.txt |  145 
 include/keys/trusted-type.h  |   31 +
 include/linux/tpm_command.h  |   28 +
 security/Kconfig |   15 +
 security/keys/Makefile   |1 +
 security/keys/trusted_defined.c  | 1151 ++
 security/keys/trusted_defined.h  |  134 
 7 files changed, 1505 insertions(+), 0 deletions(-)
 create mode 100644 Documentation/keys-trusted-encrypted.txt
 create mode 100644 include/keys/trusted-type.h
 create mode 100644 include/linux/tpm_command.h
 create mode 100644 security/keys/trusted_defined.c
 create mode 100644 security/keys/trusted_defined.h

diff --git a/Documentation/keys-trusted-encrypted.txt 
b/Documentation/keys-trusted-encrypted.txt
new file mode 100644
index 000..8fb79bc
--- /dev/null
+++ b/Documentation/keys-trusted-encrypted.txt
@@ -0,0 +1,145 @@
+   Trusted and Encrypted Keys
+
+Trusted and Encrypted Keys are two new key types added to the existing kernel
+key ring service.  Both of these new types are variable length symmetic keys,
+and in both cases all keys are created in the kernel, and user space sees,
+stores, and loads only encrypted blobs.  Trusted Keys require the availability
+of a Trusted Platform Module (TPM) chip for greater security, while Encrypted
+Keys can be used on any system.  All user level blobs, are displayed and loaded
+in hex ascii for convenience, and are integrity verified.
+
+Trusted Keys use a TPM both to generate and to seal the keys.  Keys are sealed
+under a 2048 bit RSA key in the TPM, and optionally sealed to specified PCR
+(integrity measurement) values, and only unsealed by the TPM, if PCRs and blob
+integrity verifications match.  A loaded Trusted Key can be updated with new
+(future) PCR values, so keys are easily migrated to new pcr values, such as
+when the kernel and initramfs are updated.  The same key can have many saved
+blobs under different PCR values, so multiple boots are easily supported.
+
+By default, trusted keys are sealed under the SRK, which has the default
+authorization value (20 zeros).  This can be set at takeownership time with the
+trouser's utility: tpm_takeownership -u -z.
+
+Usage:
+keyctl add trusted name new keylen [options] ring
+keyctl add trusted name load hex_blob [pcrlock=pcrnum] ring
+keyctl update key update [options]
+keyctl print keyid
+
+options:
+   keyhandle= ascii hex value of sealing key default 0x4000 (SRK)
+   keyauth=  ascii hex auth for sealing key default 0x00...i
+ (40 ascii zeros)
+   blobauth=  ascii hex auth for sealed data default 0x00...
+ (40 ascii zeros)
+   blobauth=  ascii hex auth for sealed data default 0x00...
+ (40 ascii zeros)
+   pcrinfo=  ascii hex of PCR_INFO or PCR_INFO_LONG (no default

[PATCH v1.5 1/5] lib: hex2bin converts ascii hexadecimal string to binary

2010-11-23 Thread Mimi Zohar
Similar to the kgdb_hex2mem() code, hex2bin converts a string
to binary using the hex_to_bin() library call.

Changelog:
- Replace parameter names with src/dst (based on David Howell's comment)
- Add 'const' where needed (based on David Howell's comment)
- Replace int with size_t (based on David Howell's comment)

Signed-off-by: Mimi Zohar zo...@us.ibm.com
Acked-by: Serge E. Hallyn se...@hallyn.com
Acked-by: David Howells dhowe...@redhat.com
---
 include/linux/kernel.h |1 +
 lib/hexdump.c  |   16 
 2 files changed, 17 insertions(+), 0 deletions(-)

diff --git a/include/linux/kernel.h b/include/linux/kernel.h
index 3f648d2..fbca217 100644
--- a/include/linux/kernel.h
+++ b/include/linux/kernel.h
@@ -419,6 +419,7 @@ static inline char *pack_hex_byte(char *buf, u8 byte)
 }
 
 extern int hex_to_bin(char ch);
+extern void hex2bin(u8 *dst, const char *src, size_t count);
 
 #ifndef pr_fmt
 #define pr_fmt(fmt) fmt
diff --git a/lib/hexdump.c b/lib/hexdump.c
index 5d7a480..b66b2bd 100644
--- a/lib/hexdump.c
+++ b/lib/hexdump.c
@@ -34,6 +34,22 @@ int hex_to_bin(char ch)
 EXPORT_SYMBOL(hex_to_bin);
 
 /**
+ * hex2bin - convert an ascii hexadecimal string to its binary representation
+ * @dst: binary result
+ * @src: ascii hexadecimal string
+ * @count: result length
+ */
+void hex2bin(u8 *dst, const char *src, size_t count)
+{
+   while (count--) {
+   *dst = hex_to_bin(*src++)  4;
+   *dst += hex_to_bin(*src++);
+   dst++;
+   }
+}
+EXPORT_SYMBOL(hex2bin);
+
+/**
  * hex_dump_to_buffer - convert a blob of data to hex ASCII in memory
  * @buf: data blob to dump
  * @len: number of bytes in the @buf
-- 
1.7.2.2



--
To unsubscribe from this list: send the line unsubscribe linux-crypto in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v1.5 3/5] key: add tpm_send command

2010-11-23 Thread Mimi Zohar
Add internal kernel tpm_send() command used to seal/unseal keys.

Changelog:
- replaced module_put in tpm_send() with new tpm_chip_put() wrapper
  (suggested by David Howells)
- Make tpm_send() cmd argument a 'void *' (suggested by David Howells)

Signed-off-by: David Safford saff...@watson.ibm.com
Signed-off-by: Mimi Zohar zo...@us.ibm.com
Acked-by: David Howells dhowe...@redhat.com
---
 drivers/char/tpm/tpm.c |   16 
 include/linux/tpm.h|4 
 2 files changed, 20 insertions(+), 0 deletions(-)

diff --git a/drivers/char/tpm/tpm.c b/drivers/char/tpm/tpm.c
index 26c09f3..068bac8 100644
--- a/drivers/char/tpm/tpm.c
+++ b/drivers/char/tpm/tpm.c
@@ -780,6 +780,22 @@ int tpm_pcr_extend(u32 chip_num, int pcr_idx, const u8 
*hash)
 }
 EXPORT_SYMBOL_GPL(tpm_pcr_extend);
 
+int tpm_send(u32 chip_num, void *cmd, size_t buflen)
+{
+   struct tpm_chip *chip;
+   int rc;
+
+   chip = tpm_chip_find_get(chip_num);
+   if (chip == NULL)
+   return -ENODEV;
+
+   rc = transmit_cmd(chip, cmd, buflen, attempting tpm_cmd);
+
+   tpm_chip_put(chip);
+   return rc;
+}
+EXPORT_SYMBOL_GPL(tpm_send);
+
 ssize_t tpm_show_pcrs(struct device *dev, struct device_attribute *attr,
  char *buf)
 {
diff --git a/include/linux/tpm.h b/include/linux/tpm.h
index ac5d1c1..fdc718a 100644
--- a/include/linux/tpm.h
+++ b/include/linux/tpm.h
@@ -31,6 +31,7 @@
 
 extern int tpm_pcr_read(u32 chip_num, int pcr_idx, u8 *res_buf);
 extern int tpm_pcr_extend(u32 chip_num, int pcr_idx, const u8 *hash);
+extern int tpm_send(u32 chip_num, void *cmd, size_t buflen);
 #else
 static inline int tpm_pcr_read(u32 chip_num, int pcr_idx, u8 *res_buf) {
return -ENODEV;
@@ -38,5 +39,8 @@ static inline int tpm_pcr_read(u32 chip_num, int pcr_idx, u8 
*res_buf) {
 static inline int tpm_pcr_extend(u32 chip_num, int pcr_idx, const u8 *hash) {
return -ENODEV;
 }
+static inline int tpm_send(u32 chip_num, void *cmd, size_t buflen) {
+   return -ENODEV;
+}
 #endif
 #endif
-- 
1.7.2.2



--
To unsubscribe from this list: send the line unsubscribe linux-crypto in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v1.4 5/5] keys: add new key-type encrypted

2010-11-22 Thread Mimi Zohar
On Fri, 2010-11-19 at 16:43 +, David Howells wrote: 
 Mimi Zohar zo...@linux.vnet.ibm.com wrote:
 
  +static int datablob_format(char __user *buffer,
  +  struct encrypted_key_payload *epayload,
  +  int asciiblob_len)
 
 size_t?  There are other instances where you should be using size_t too.

Most of the crypto library calls use unsigned int. Obviously didn't
quite get everything else. Will look again.  thanks.

  +   index = strcspn(epayload-master_desc, :);
  +   if (index == strlen(epayload-master_desc))
  +   goto out;
 
 For single chars, use strchr() rather than strcspn(), and if you happen to
 know the length too, use memchr().  This also means you don't need to do the
 strlen() again to check the result.

Don't have the length, but getting it once and then using strchr/memchr,
should work. thanks.

  +   memset(derived_key, 0, sizeof derived_key);
  +   ret = get_derived_key(derived_key, AUTH_KEY, master_key, master_keylen)
 
 Is the memset() actually necessary?

not sure, will check.

  +   decrypted_datalen = (unsigned short)dlen;
 
 Unnecessary cast.

ok

  +   *(datablob + datalen) = 0;
  +   *(buf + datalen) = 0;
 
 Use [].

  +   if (index == strlen(new_master_desc)
  +   || (strncmp(new_master_desc, epayload-master_desc, index) != 0)) {
 
 Superfluous brackets.
 
 Mimi Zohar zo...@linux.vnet.ibm.com wrote:
 
  +   mkey = request_master_key(epayload, master_key, master_keylen);
  +   if (IS_ERR(mkey))
  +   return PTR_ERR(mkey);
  +
  +   memset(derived_key, 0, sizeof derived_key);
  +   ret = get_derived_key(derived_key, ENC_KEY, master_key, master_keylen);
  +   if (ret  0)
  +   goto out;
  +
  +   ret = derived_key_encrypt(epayload, derived_key, sizeof derived_key);
  +   if (ret  0)
  +   goto out;
  +
  +   ret = datablob_hmac_append(epayload, master_key, master_keylen);
  +   if (ret  0)
  +   goto out;
  +
  +   ret = datablob_format(buffer, epayload, asciiblob_len);
  +   if (ret  0)
  +   goto out;
  +
  +   rcu_read_unlock();
 
 NAK!  This is not safe.  You may not sleep whilst you hold the RCU read lock
 on the master key.  At the very least, datablob_format() may sleep as it
 writes to userspace.

datablob_format() could be split up into formatting the string returned
to userspace and copying it userspace, releasing the lock before copying
it, but that wouldn't resolve the other places it may sleep, like alloc.

 I think what you should do is ignore RCU entirely and read lock the master
 key's semaphore.

thanks, will do.

  +   ret = aes_get_sizes();
  +   return ret;
 
 Merge.
 
 David

ok

thanks,

Mimi

--
To unsubscribe from this list: send the line unsubscribe linux-crypto in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v1.3 4/4] keys: add new key-type encrypted

2010-11-20 Thread Mimi Zohar
On Tue, 2010-11-16 at 14:08 +, David Howells wrote: 
 Mimi Zohar zo...@linux.vnet.ibm.com wrote:
 
  Am assuming you mean something like this:
  
  keyctl add encrypted name new trusted:master-key-name keylen ring
  keyctl add encrypted name new user:master-key-name keylen ring
  
  and, as you said, works without changing the API.
 
 No, that's not what I mean.  I maeant that when your internal functions look
 for the user key, they should preface the description with a prefix.
 
 It should be handled in request_user_key() or request_master_key().  The
 description given to request_trusted_key() should have the prefix applied
 there.  There's no need to mention it at all in the encrypted key add_key
 command line.
 
 David

I actually like keyctl requiring 'trusted:' or 'user:'.  Forcing the
user to indicate which type of key they want, is actually good - no
misunderstandings. Another benefit, would be allowing 'keyctl update' to
update the key description, not the key type.

Mimi 

--
To unsubscribe from this list: send the line unsubscribe linux-crypto in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v1.4 0/5] keys: trusted and encrypted keys

2010-11-18 Thread Mimi Zohar
Changes were made in this patchset based on David Howell's comments.  The
major technical change was converting from the crypto hash to shash API.
The remaining changes are listed in the individual patch changelogs.

Trusted and Encrypted Keys are two new key types added to the existing
kernel key ring service. Both of these new types are variable length
symmetic keys, and in both cases all keys are created in the kernel, and
user space sees, stores, and loads only encrypted blobs.  Trusted Keys
require the availability of a Trusted Platform Module (TPM) chip for
greater security, while Encrypted Keys can be used on any system. All
user level blobs, are displayed and loaded in hex ascii for convenience,
and are integrity verified.  

Trusted Keys use a TPM both to generate and to seal the keys.  Keys are
sealed under a 2048 bit RSA key in the TPM, and optionally sealed to
specified PCR (integrity measurement) values, and only unsealed by the
TPM, if PCRs and blob integrity verifications match.  A loaded Trusted
Key can be updated with new (future) PCR values, so keys are easily
migrated to new pcr values, such as when the kernel and initramfs are
updated.  The same key can have many saved blobs under different PCR
values, so multiple boots are easily supported.

By default, trusted keys are sealed under the SRK, which has the default
authorization value (20 zeros).  This can be set at takeownership time
with the trouser's utility: tpm_takeownership -u -z.

Usage:
keyctl add trusted name new keylen [options] ring
keyctl add trusted name load hex_blob [pcrlock=pcrnum] ring
keyctl update key update [options]
keyctl print keyid

options:
   keyhandle= ascii hex value of sealing key default 0x4000 (SRK)
   keyauth=   ascii hex auth for sealing key default 0x00...
  (40 ascii zeros)
   blobauth=  ascii hex auth for sealed data default 0x00...
  (40 ascii zeros)
   pcrinfo=   ascii hex of PCR_INFO or PCR_INFO_LONG (no default)
   pcrlock=   pcr number to be extended to lock blob
   migratable= 0|1 indicating permission to reseal to new PCR values, 
   default 1 (resealing allowed)

keyctl print returns an ascii hex copy of the sealed key, which is in
standard TPM_STORED_DATA format.  The key length for new keys are always
in bytes.  Trusted Keys can be 32 - 128 bytes (256 - 1024 bits), the
upper limit is to fit within the 2048 bit SRK (RSA) keylength, with all
necessary structure/padding. 

Encrypted keys do not depend on a TPM, and are faster, as they use AES
for encryption/decryption.  New keys are created from kernel generated
random numbers, and are encrypted/decrypted using a specified 'master'
key.  The 'master' key can either be a trusted-key or user-key type. The
main disadvantage of encrypted keys is that if they are not rooted in a
trusted key, they are only as secure as the user key encrypting them.
The master user key should therefore be loaded in as secure a way as
possible, preferably early in boot.

Usage:
  keyctl add encrypted name new master-key-name keylen ring
  keyctl add encrypted name load key-type:master-key-name keylen hex_blob ring
  keyctl update keyid update master-key-name

where 'key-type' is either 'trusted' or 'user'.

The initial consumer of trusted keys is EVM, which at boot time needs a
high quality symmetric key for HMAC protection of file metadata. The use
of a trusted key provides strong guarantees that the EVM key has not
been compromised by a user level problem, and when sealed to specific
boot PCR values, protects against boot and offline attacks.  Other uses
for trusted and encrypted keys, such as for disk and file encryption are
anticipated.

Mimi Zohar
David Safford

Mimi Zohar (5):
  lib: hex2bin converts ascii hexadecimal string to binary
  tpm: add module_put wrapper
  key: add tpm_send command
  keys: add new trusted key-type
  keys: add new key-type encrypted

 Documentation/keys-trusted-encrypted.txt |   68 ++
 drivers/char/tpm/tpm.c   |   20 +-
 drivers/char/tpm/tpm.h   |5 +
 include/keys/encrypted-type.h|   29 +
 include/keys/trusted-type.h  |   31 +
 include/linux/kernel.h   |1 +
 include/linux/tpm.h  |4 +
 lib/hexdump.c|   16 +
 security/Kconfig |   31 +
 security/keys/Makefile   |2 +
 security/keys/encrypted_defined.c|  876 +++
 security/keys/encrypted_defined.h|   56 ++
 security/keys/trusted_defined.c  | 1136 ++
 security/keys/trusted_defined.h  |  147 
 14 files changed, 2420 insertions(+), 2 deletions(-)
 create mode 100644 Documentation/keys-trusted-encrypted.txt
 create mode 100644 include/keys/encrypted-type.h
 create mode 100644 include/keys/trusted-type.h
 create mode 100644 security/keys

[PATCH v1.4 1/5] lib: hex2bin converts ascii hexadecimal string to binary

2010-11-18 Thread Mimi Zohar
Similar to the kgdb_hex2mem() code, hex2bin converts a string
to binary using the hex_to_bin() library call.

Changelog:
- Replace parameter names with src/dst (based on David Howell's comment)
- Add 'const' where needed (based on David Howell's comment)
- Replace int with size_t (based on David Howell's comment)

Signed-off-by: Mimi Zohar zo...@us.ibm.com
Acked-by: Serge E. Hallyn se...@hallyn.com
---
 include/linux/kernel.h |1 +
 lib/hexdump.c  |   16 
 2 files changed, 17 insertions(+), 0 deletions(-)

diff --git a/include/linux/kernel.h b/include/linux/kernel.h
index 3f648d2..fbca217 100644
--- a/include/linux/kernel.h
+++ b/include/linux/kernel.h
@@ -419,6 +419,7 @@ static inline char *pack_hex_byte(char *buf, u8 byte)
 }
 
 extern int hex_to_bin(char ch);
+extern void hex2bin(u8 *dst, const char *src, size_t count);
 
 #ifndef pr_fmt
 #define pr_fmt(fmt) fmt
diff --git a/lib/hexdump.c b/lib/hexdump.c
index 5d7a480..0eea94d 100644
--- a/lib/hexdump.c
+++ b/lib/hexdump.c
@@ -34,6 +34,22 @@ int hex_to_bin(char ch)
 EXPORT_SYMBOL(hex_to_bin);
 
 /**
+ * hex2bin - convert an ascii hexadecimal string to its binary representation
+ * @dst: binary result
+ * @src: ascii hexadecimal string
+ * @count: result length
+ */
+void hex2bin(u8 *dst, const char *src, size_t count)
+{
+   while (count--) {
+   *dst = hex_to_bin(*src++)  4;
+   *dst += hex_to_bin(*src++);
+   dst++;
+   }
+}
+EXPORT_SYMBOL(hex2bin);
+
+/**
  * hex_dump_to_buffer - convert a blob of data to hex ASCII in memory
  * @buf: data blob to dump
  * @len: number of bytes in the @buf
-- 
1.7.2.2

--
To unsubscribe from this list: send the line unsubscribe linux-crypto in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


  1   2   >