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

2014-06-23 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 

Thanks, Dmitry.  What type of values are you using for ima_ahash_size?
Have you specified ima_ahash_size, when booting with an initramfs?
ahash should probably only be used after pivoting root.

thanks,

Mimi

> ---
>  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 
>  #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);
> + pr_info("ima_ahash_size = %lld\n", ima_ahash_size);
> + return !rc;
> +}
> +__setup("ima_ahash_size=", ima_ahash_setup);
> 
>  /**
>   * 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);
> + 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:
> + 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,
> +   

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 
> ---
>  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 
>  #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);
> + re

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 
> ---
>  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


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 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 

> ---
>  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: 
> + 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 
>  #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;

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  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 
> >
> >> ---
> >>  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: 
> >> + 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 
> >>  #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)
> >> +{
> >

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  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 
> ---
>  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: 
> + Format: [,]
>   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 
>  #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 N

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 
> ---
>  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: 
> + 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: 
>   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 
> +#include 
> +#include 
>  #include 
>  #include 
>  #include 
> @@ -25,7 +27,18 @@
>  #include 
>  #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 calculati

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] security, crypto: LLVMLinux: Remove VLAIS from ima_crypto.c

2014-09-08 Thread Mimi Zohar
On Mon, 2014-09-08 at 07:25 -0500, Behan Webster wrote: 
> On 09/08/14 04:15, Dmitry Kasatkin wrote:
> > On 07/09/14 05:06, Behan Webster wrote:
> >> On 09/06/14 03:11, Thomas Gleixner wrote:
> >>> On Fri, 5 Sep 2014, Behan Webster wrote:
>  On 09/05/14 17:18, Thomas Gleixner wrote:
> >> Signed-off-by: Behan Webster 
> >> Signed-off-by: Mark Charlebois 
> >> Signed-off-by: Jan-Simon Möller 
> > This SOB chain is completely ass backwards. See Documentation/...
>  "The Signed-off-by: tag indicates that the signer was involved in the
>  development of the patch, or that he/she was in the patch's delivery
>  path."
> 
>  All three of us were involved. Does that not satisfy this rule?
> >>> No. Read #12
> >>>
> >>> The sign-off is a simple line at the end of the explanation for the
> >>> patch, which certifies that you wrote it or otherwise have the right to
> >>> pass it on as an open-source patch.
> >>>
> >>> So the above chain says:
> >>>
> >>>  Written-by:   Behan
> >>>  Passed-on-by: Mark
> >>>  Passed-on-by: Jan
> >>>
> >>> That would be correct if you sent the patch to Mark, Mark sent it to
> >>> Jan and Jan finally submitted it to LKML.
> >> I suppose "Reviewed-by" is probably more appropriate for the last 2
> >> then. Will fix.
> >>
> >> -struct {
> >> -struct shash_desc shash;
> >> -char ctx[crypto_shash_descsize(tfm)];
> >> -} desc;
> >> +char desc[sizeof(struct shash_desc) +
> >> +crypto_shash_descsize(tfm)] CRYPTO_MINALIGN_ATTR;
> >> +struct shash_desc *shash = (struct shash_desc *)desc;
> > That anon struct should have never happened in the first place.
>  Sadly this is a design pattern used in many places through out the
>  kernel, and
>  appears to be fundamental to the crypto system. I was advised *not*
>  to change
>  it, so we haven't.
> 
>  I agree that it's not a good practice.
> 
> > Not
> > your problem, but you are not making it any better. You replace open
> > coded crap with even more unreadable crap.
> >
> > Whats wrong with
> >
> >  SHASH_DESC_ON_STACK(shash, tfm);
>  Nothing is wrong with that. I would have actually preferred that.
>  But it would
>  have fundamentally changed a lot more code.
> >>> Errm. Why is
> >>>
> >>> #define SHASH_DESC_ON_STACK(shash, tfm)\
> >>>  char __shash[sizeof(.)];\
> >>>  struct shash_desc *shash = (struct shash_desc *) __shash
> >>>
> >>> requiring more fundamental than open coding the same thing a gazillion
> >>> times. You still need to change ALL usage sides of the anon struct.
> >>>
> >>> So in fact you could avoid the whole code change by making it
> >>>
> >>>  SHASH_DESC_ON_STACK(desc, tfm);
> >>>
> >>> and do the anon struct or a proper struct magic in the macro.
> >> I see. I thought you meant a more fundamental change to the crypto
> >> system API. My misunderstanding.
> >>
> >> Ironically we tried to stay away from macros since the last time we
> >> tried to replace VLAIS using macros (we've attempted patches to remove
> >> VLAIS a few times) we were told *not* to hide the implementation with
> >> macro magic. Though, to be fair, we were using more pointer math in
> >> our other macro-based effort, and the non-crypto uses of VLAIS are a
> >> lot more complex to replace.
> >>
> >> Like I said I'm actually a fan of hiding ugliness in macros. Will fix.
> >>
> >> Again, thanks for the feedback,
> >>
> >> Behan
> >>
> > Hi,
> >
> > Despite if it is crap or not, it was said already in this thread,
> > following "design pattern" is heavily used through out the kernel - by
> > crypto core itself and by many widely used clients.
> >
> >  struct {
> >  struct shash_desc shash;
> >  char ctx[crypto_shash_descsize(tfm)];
> >  } desc;
> >
> >
> > My question why do you want to change this particular piece of code?
> Because it employs Variable Length Arrays in Structs. A construct which 
> is explicitly forbidden by the C standard (C89, C99, C11). Because the 
> vast majority of kernel developers I've talked to about this have been 
> unaware of the use of VLAIS in the kernel and most find its use 
> objectionable (there is a similar objection to the use of nested 
> functions). Because implementing VLAIS in a compiler can severely impact 
> the generated instructions surrounding its use, which is why most 
> compilers don't implement VLAIS as a feature. Because using such a 
> construct precludes standards based compilers from competing with the 
> incumbent (my interest is enabling the use of clang and LLVM based 
> technologies as a toolchain choice to compile and develop the kernel).
> 
> > What about rest of the kernel?
> The LLVMLinux project is systematically working to remove the use of 
> VLAIS from the kernel (already removed from ext4, USB Gadget, netfilter, 
> mac802

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
> +++ b/security/integrity/ima/ima_appr

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 ima_get_cache_status(struct integrit

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  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_val

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  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 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 opened);
> +  

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

2017-08-17 Thread Mimi Zohar

> diff --git a/security/integrity/ima/ima_appraise.c 
> b/security/integrity/ima/ima_appraise.c
> index 87d2b601cf8e..5a244ebc61d9 100644
> --- a/security/integrity/ima/ima_appraise.c
> +++ b/security/integrity/ima/ima_appraise.c
> @@ -190,6 +190,64 @@ int ima_read_xattr(struct dentry *dentry,
>   return ret;
>  }
> 
> +static void process_xattr_error(int rc, struct integrity_iint_cache *iint,
> + int opened, char const **cause,
> + enum integrity_status *status)
> +{
> + if (rc && rc != -ENODATA)
> + return;
> +
> + *cause = iint->flags & IMA_DIGSIG_REQUIRED ?
> + "IMA-signature-required" : "missing-hash";
> + *status = INTEGRITY_NOLABEL;
> +
> + if (opened & FILE_CREATED)
> + iint->flags |= IMA_NEW_FILE;
> +
> + if ((iint->flags & IMA_NEW_FILE) &&
> + !(iint->flags & IMA_DIGSIG_REQUIRED))
> + *status = INTEGRITY_PASS;
> +}
> +
> +static int appraise_modsig(struct integrity_iint_cache *iint,
> +struct evm_ima_xattr_data *xattr_value,
> +int xattr_len)
> +{
> + enum hash_algo algo;
> + const void *digest;
> + void *buf;
> + int rc, len;
> + u8 dig_len;
> +
> + rc = ima_modsig_verify(INTEGRITY_KEYRING_IMA, xattr_value);
> + if (rc)
> + return rc;
> +
> + /*
> +  * The signature is good. Now let's put the sig hash
> +  * into the iint cache so that it gets stored in the
> +  * measurement list.
> +  */
> +
> + rc = ima_get_modsig_hash(xattr_value, &algo, &digest, &dig_len);
> + if (rc)
> + return rc;
> +
> + len = sizeof(iint->ima_hash) + dig_len;
> + buf = krealloc(iint->ima_hash, len, GFP_NOFS);
> + if (!buf)
> + return -ENOMEM;
> +
> + iint->ima_hash = buf;
> + iint->flags |= IMA_DIGSIG;
> + iint->ima_hash->algo = algo;
> + iint->ima_hash->length = dig_len;
> +
> + memcpy(iint->ima_hash->digest, digest, dig_len);
> +
> + return 0;
> +}

Depending on the IMA policy, the file could already have been
measured.  That measurement list entry might include the file
signature, as stored in the xattr, in the ima-sig template data.

I think even if a measurement list entry exists, we would want an
additional measurement list entry, which includes the appended
signature in the ima-sig template data.

Mimi



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, &xattr_value,
> &xattr_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 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 

Reviewed-by: Mimi Zohar 

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
> +obj-$(CONFIG_MODULE_SIG_FORMAT) += module_signing.o
> 

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 

Reviewed-by: Mimi Zohar 

> ---
>  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))
> + return PTR_ERR(pkcs7);
> +
> + re

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 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  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 
> >
> > Reviewed-by: Mimi Zohar 
> >
> > 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 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, &xattr_value, &xattr_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)

T

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: 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


[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(&sg_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: [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 
> Signed-off-by: Herbert Xu 
> 
> 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(&sg_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


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  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  wrote:
> > On Wed, 2015-10-21 at 13:21 -0400, Josh Boyer wrote:
> >> On Wed, Oct 21, 2015 at 1:02 PM, Mimi Zohar  
> >> 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: [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: [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: [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: [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: [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 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, &pks);
> -
> - 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, &pks);
>   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 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 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 */
> -};
> -
> -/*
> - * Modul

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 
> 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 
> ---
>  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_KERNEL_CHECK",
> - "KEXEC_INITRAMFS_CHECK&qu

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), &xattr_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, &size, &xattr_value,
> +   &xattr_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),
> +&xattr_value);
> + }
> 

Suppose 

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 

Acked-by: Mimi Zohar 

> ---
>  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(&res->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(&res->completion);
> - reinit_completion(&res->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(&res.completion);
> + crypto_init_wait(&wait);
>   ahash_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG |
>  CRYPTO_TFM_REQ_MAY_SLEEP,
> -ahash_complete, &res);
> +crypto_req_done, &wait);
> 
> - rc = ahash_wait(crypto_ahash_init(req), &res);
> + rc = ahash_wait(crypto_ahash_init(req), &wait);
>   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, &res);
> + rc = ahash_wait(ahash_rc, &wait);
>   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, &res);
> + rc = ahash_wait(ahash_rc, &wait);
>   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, &res);
> + rc = ahash_wait(ahash_rc, &wait);
>  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), &res);
> + rc = ahash_wait(crypto_ahash_final(req), &wait);
>   }
>  out1:
>   ahash_request_free(req);
> @@ -527,7 

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 +17,8 @@ if INTEGRITY
> 
>  confi

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 

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 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 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 integrity_iint_cache *integrity_

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  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 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  writes:
> 
> > On Wed, 2017-06-21 at 14:45 -0300, Thiago Jung Bauermann wrote:
> >> Mimi Zohar  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), 
> >> >> &xattr_value);
> >> >> -
> >> >> -   hash_algo = ima_get_h

[RFC][PATCH 1/4] lib: hex2bin converts ascii hexadecimal string to binary

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

Signed-off-by: Mimi Zohar 
---
 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 2b0a35e..69ddea8 100644
--- a/include/linux/kernel.h
+++ b/include/linux/kernel.h
@@ -396,6 +396,7 @@ static inline char *pack_hex_byte(char *buf, u8 byte)
 }
 
 extern int hex_to_bin(char ch);
+extern void hex2bin(unsigned char *mem, char *buf, int count);
 
 #ifndef pr_fmt
 #define pr_fmt(fmt) fmt
diff --git a/lib/hexdump.c b/lib/hexdump.c
index 5d7a480..66f96bb 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
+ * @mem: result
+ * @buf: ascii hexadecimal string
+ * @count: result length
+ */
+void hex2bin(unsigned char *mem, char *buf, int count)
+{
+   while (count--) {
+   *mem = hex_to_bin(*buf++) << 4;
+   *mem += hex_to_bin(*buf++);
+   mem++;
+   }
+}
+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


[RFC][PATCH 0/4] keys: trusted and encrypted keys

2010-09-28 Thread Mimi Zohar
Sorry for the duplicate posting. Am cc'ing the crypto mailing 
list as well. 

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.

Trusted Keys are sealed under the SRK, which must have 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 [hex_pcrinfo]" ring
keyctl add trusted name "LOAD hex_blob" ring
keyctl update key "UPDATE hex_pcrinfo"
keyctl print keyid
keyctl pipe keyid > filename

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. The keywords NEW, LOAD, and
UPDATE can be all upper or all lower case.

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 master-key-name keylen hex_blob" ring
  keyctl update keyid "UPDATE master-key-name"

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
Dave Safford

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

 drivers/char/tpm/tpm.c|   17 +
 include/keys/encrypted-type.h |   30 ++
 include/keys/trusted-type.h   |   33 ++
 include/linux/kernel.h|1 +
 include/linux/tpm.h   |3 +
 lib/hexdump.c |   16 +
 security/Kconfig  |   33 ++
 security/keys/Makefile|2 +
 security/keys/encrypted_defined.c |  781 +
 security/keys/encrypted_defined.h |   52 ++
 security/keys/trusted_defined.c   |  997 +
 security/keys/trusted_defined.h   |  125 +
 12 files changed, 2090 insertions(+), 0 deletions(-)
 create mode 100644 include/keys/encrypted-type.h
 create mode 100644 include/keys/trusted-type.h
 create mode 100644 security/keys/encrypted_defined.c
 create mode 100644 security/keys/encrypted_defined.h
 create mode 100644 security/keys/trusted_defined.c
 create mode 100644 security/keys/trusted_defined.h

-- 
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


[RFC][PATCH 2/4] key: add tpm_send command

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

Signed-off-by: David Safford 
Reviewd-by: Mimi Zohar 
---
 drivers/char/tpm/tpm.c |   17 +
 include/linux/tpm.h|3 +++
 2 files changed, 20 insertions(+), 0 deletions(-)

diff --git a/drivers/char/tpm/tpm.c b/drivers/char/tpm/tpm.c
index 05ad4a1..37c16a8 100644
--- a/drivers/char/tpm/tpm.c
+++ b/drivers/char/tpm/tpm.c
@@ -770,6 +770,23 @@ 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, char *cmd, int buflen)
+{
+   struct tpm_chip *chip;
+   int rc;
+
+   chip = tpm_chip_find_get(chip_num);
+   if (chip == NULL)
+   return -ENODEV;
+
+   rc = transmit_cmd(chip, (struct tpm_cmd_t *)cmd, buflen,
+ "attempting tpm_cmd");
+
+   module_put(chip->dev->driver->owner);
+   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..a0ecaa9 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, char *cmd, int buflen);
 #else
 static inline int tpm_pcr_read(u32 chip_num, int pcr_idx, u8 *res_buf) {
return -ENODEV;
@@ -38,5 +39,7 @@ 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, char *cmd, int 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


[RFC][PATCH 3/4] keys: add new trusted key-type

2010-09-28 Thread Mimi Zohar
Defines a new kernel key-type called 'trusted'. Trusted keys are TPM
generated random numbers, RSA sealed by the TPM, and only unsealed by
the TPM, if boot PCRs and other criteria match. Trusted keys are
created/encrypted/decrypted in the kernel.  Userspace ever only
sees/stores encrypted blobs.

Signed-off-by: David Safford 
Signed-off-by: Mimi Zohar 
---
 include/keys/trusted-type.h |   33 ++
 security/Kconfig|   16 +
 security/keys/Makefile  |1 +
 security/keys/trusted_defined.c |  997 +++
 security/keys/trusted_defined.h |  125 +
 5 files changed, 1172 insertions(+), 0 deletions(-)
 create mode 100644 include/keys/trusted-type.h
 create mode 100644 security/keys/trusted_defined.c
 create mode 100644 security/keys/trusted_defined.h

diff --git a/include/keys/trusted-type.h b/include/keys/trusted-type.h
new file mode 100644
index 000..be7d44e
--- /dev/null
+++ b/include/keys/trusted-type.h
@@ -0,0 +1,33 @@
+/* trusted-type.h: trusted-defined key type
+ *
+ * Copyright (C) 2010 IBM Corporation
+ * Author: David Safford 
+ *
+ * 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_TRUSTED_TYPE_H
+#define _KEYS_TRUSTED_TYPE_H
+
+#include 
+#include 
+
+#define MAX_KEY_SIZE   128
+#define MAX_BLOB_SIZE  320
+#define MAX_PCRINFO_SIZE   64
+
+struct trusted_key_payload {
+   struct rcu_head rcu;/* RCU destructor */
+   unsigned int key_len;
+   unsigned int blob_len;
+   unsigned int pcrinfo_len;
+   unsigned char key[MAX_KEY_SIZE];
+   unsigned char blob[MAX_BLOB_SIZE];
+   unsigned char pcrinfo[MAX_PCRINFO_SIZE];
+};
+
+extern struct key_type key_type_trusted;
+
+#endif /* _KEYS_TRUSTED_TYPE_H */
diff --git a/security/Kconfig b/security/Kconfig
index bd72ae6..f9681e5 100644
--- a/security/Kconfig
+++ b/security/Kconfig
@@ -21,6 +21,22 @@ config KEYS
 
  If you are unsure as to whether this is required, answer N.
 
+config TRUSTED_KEYS
+   tristate "TRUSTED KEYS"
+   depends on KEYS && TCG_TPM
+   select CRYPTO
+   select CRYPTO_HMAC
+   select CRYPTO_SHA1
+   select LIBCRC32C
+   help
+ This option provides support for creating/sealing/unsealing keys
+ in the kernel. Trusted keys are TPM generated random numbers
+ symmetric keys, RSA sealed by the TPM, and only unsealed by the
+ TPM, if boot PCRs and other criteria match.  Userspace ever only
+ 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 74d5447..fcb1070 100644
--- a/security/keys/Makefile
+++ b/security/keys/Makefile
@@ -13,6 +13,7 @@ obj-y := \
request_key_auth.o \
user_defined.o
 
+obj-$(CONFIG_TRUSTED_KEYS) += trusted_defined.o
 obj-$(CONFIG_KEYS_COMPAT) += compat.o
 obj-$(CONFIG_PROC_FS) += proc.o
 obj-$(CONFIG_SYSCTL) += sysctl.o
diff --git a/security/keys/trusted_defined.c b/security/keys/trusted_defined.c
new file mode 100644
index 000..aedad16
--- /dev/null
+++ b/security/keys/trusted_defined.c
@@ -0,0 +1,997 @@
+/*
+ * Copyright (C) 2010 IBM Corporation
+ *
+ * Author:
+ * David Safford 
+ *
+ * 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.
+ *
+ * File: trusted_defined.c
+ *
+ * Defines a new kernel key-type called 'trusted'. Trusted keys are
+ * TPM generated random numbers, RSA sealed by the TPM, and only unsealed
+ * by the TPM, if boot PCRs and other criteria match. Trusted keys are
+ * created/sealed/unsealed in the kernel. Userspace ever only sees/stores
+ * encrypted blobs.
+ *
+ * Keys are sealed under the SRK, which must have 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 [hex_pcrinfo]" ring
+ *   keyctl add trusted name "LOAD hex_blob" ring
+ *   keyctl update key "UPDATE hex_pcrinfo"
+ *   keyctl print keyid
+ * keys can be 32 - 128 bytes, blob max is 1024 hex ascii characters
+ * binary pcrinfo max is 512 hex ascii characters
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "trusted_defined.h"
+
+static char hmac_alg[] = "hmac(sha1

[RFC][PATCH 4/4] keys: add new key-type encrypted

2010-09-28 Thread Mimi Zohar
Defines 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.

Signed-off-by: Mimi Zohar 
Signed-off-by: David Safford 
---
 include/keys/encrypted-type.h |   30 ++
 security/Kconfig  |   17 +
 security/keys/Makefile|1 +
 security/keys/encrypted_defined.c |  781 +
 security/keys/encrypted_defined.h |   52 +++
 5 files changed, 881 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..e2312e0
--- /dev/null
+++ b/include/keys/encrypted-type.h
@@ -0,0 +1,30 @@
+/* encrypted-type.h: encrypted-defined key type
+ *
+ * Copyright (C) 2010 IBM Corporation
+ * Author: Mimi Zohar 
+ *
+ * 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 
+#include 
+
+struct encrypted_key_payload {
+   struct rcu_head rcu;/* RCU destructor */
+   char *master_desc;  /* datablob: master key name */
+   char *datalen;  /* datablob: decrypted key length */
+   void *iv;   /* datablob: iv */
+   void *encrypted_data;   /* datablob: encrypted key */
+   unsigned short datablob_len;/* length of datablob */
+   unsigned short decrypted_datalen;   /* decrypted data length */
+   char 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 f9681e5..b03187d 100644
--- a/security/Kconfig
+++ b/security/Kconfig
@@ -37,6 +37,23 @@ 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 LIBCRC32C
+   select CONFIG_CRYPTO_AES
+   select CRYPTO_HMAC
+   select CRYPTO_SHA256
+   select BLOCK_CBC
+   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..6b26db6
--- /dev/null
+++ b/security/keys/encrypted_defined.c
@@ -0,0 +1,781 @@
+/*
+ * Copyright (C) 2010 IBM Corporation
+ *
+ * Author:
+ * Mimi Zohar 
+ *
+ * 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.
+ *
+ * File: encrypted_defined.c
+ *
+ * Defines a new kernel key-type called 'encrypted'. Encrypted keys
+ * are kernel generated random numbers, which are encrypted/decrypted
+ * using a 'master' key. The 'master' key can either be a trusted-key or
+ * user-key type. Encrypted keys are created/encrypted/decrypted in the
+ * kernel. Userspace ever only sees/stores encrypted blobs.
+ *
+ * keyctl add "encrypted" "name" "NEW master-key-name keylen" ring
+ * keyctl add "encrypted" "name" "LOAD master-key-name keylen hex_blob" ring
+ * keyctl update keyid "UPDATE master-key-name"
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "encrypted_defined.h"
+
+static char hash_alg[] = 

Re: [RFC][PATCH 4/4] keys: add new key-type encrypted

2010-09-29 Thread Mimi Zohar
On Wed, 2010-09-29 at 12:00 +0200, Roberto Sassu wrote:
> When a new encrypted key is created through the keyctl utility, the master
> key specified is not searched in the keyring and the operation is performed 
> even 
> if it is missing.

Yes, and why is this a problem?  After creating a new key, the first
thing done should be to save it.  At that point, you'd find out the
master-key doesn't exist, requiring you to either load it or change the
master-key name using 'keyctl update'.

Mimi

> The following patch moves the master key request in the encrypted_init() 
> function, 
> in order to deny a new key creation if the former is not present.
> 
> 
> Signed-off-by: Roberto Sassu 
> ---
>  security/keys/encrypted_defined.c |   23 +--
>  1 files changed, 13 insertions(+), 10 deletions(-)
> 
> diff --git a/security/keys/encrypted_defined.c 
> b/security/keys/encrypted_defined.c
> index 6b26db6..48e627e 100644
> --- a/security/keys/encrypted_defined.c
> +++ b/security/keys/encrypted_defined.c
> @@ -491,12 +491,10 @@ static struct encrypted_key_payload 
> *encrypted_key_alloc(struct key *key,
>  }
>  
>  static int encrypted_key_decrypt(struct encrypted_key_payload *epayload,
> -  char *hex_encoded_iv, char *hex_encoded_data)
> +  char *hex_encoded_iv, char *hex_encoded_data,
> +  void *master_key, unsigned int master_keylen)
>  {
>   char derived_key[hash_size];
> - struct key *mkey;
> - void *master_key;
> - unsigned int master_keylen;
>   size_t encrypted_datalen;
>   char *hmac;
>   int ret;
> @@ -508,10 +506,6 @@ static int encrypted_key_decrypt(struct 
> encrypted_key_payload *epayload,
>   hmac = epayload->master_desc + epayload->datablob_len;
>   hex2bin(hmac, hex_encoded_data + (encrypted_datalen * 2), hash_size);
>  
> - mkey = request_master_key(epayload, &master_key, &master_keylen);
> - if (IS_ERR(mkey))
> - return PTR_ERR(mkey);
> -
>   ret = datablob_hmac_verify(epayload, master_key, master_keylen);
>   if (ret) {
>   pr_err("encrypted_key: bad hmac (%d)\n", ret);
> @@ -527,7 +521,6 @@ static int encrypted_key_decrypt(struct 
> encrypted_key_payload *epayload,
>   if (ret)
>   pr_err("encrypted_key: failed to decrypt key (%d)\n", ret);
>  out:
> - key_put(mkey);
>   return ret;
>  }
>  
> @@ -555,8 +548,16 @@ static int encrypted_init(struct encrypted_key_payload 
> *epayload,
> char *hex_encoded_iv, char *hex_encoded_data)
>  {
>   int ret = 0;
> + struct key *mkey;
> + void *master_key;
> + unsigned int master_keylen;
>  
>   __ekey_init(epayload, master_desc, datalen);
> +
> + mkey = request_master_key(epayload, &master_key, &master_keylen);
> + if (IS_ERR(mkey))
> + return PTR_ERR(mkey);
> + 
>   if (!hex_encoded_data) {
>   get_random_bytes(epayload->iv, ivsize);
>  
> @@ -564,7 +565,9 @@ static int encrypted_init(struct encrypted_key_payload 
> *epayload,
>epayload->decrypted_datalen);
>   } else
>   ret = encrypted_key_decrypt(epayload, hex_encoded_iv,
> - hex_encoded_data);
> + hex_encoded_data, master_key, 
> master_keylen);
> +
> + key_put(mkey);
>   return ret;
>  }
>  
> -- 
> 1.7.2.3
> 
> 
> On Tuesday, September 28, 2010 08:36:33 pm Mimi Zohar wrote:
> > Defines 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.
> > 
> > Signed-off-by: Mimi Zohar 
> > Signed-off-by: David Safford 
> > ---
> >  include/keys/encrypted-type.h |   30 ++
> >  security/Kconfig  |   17 +
> >  security/keys/Makefile|1 +
> >  security/keys/encrypted_defined.c |  781 
> > +
> >  security/keys/encrypted_defined.h |   52 +++
> >  5 files changed, 881 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/encrypte

Re: [RFC][PATCH 4/4] keys: add new key-type encrypted

2010-09-29 Thread Mimi Zohar
On Wed, 2010-09-29 at 14:40 +0200, Roberto Sassu wrote:
> On Wednesday, September 29, 2010 01:57:36 pm Mimi Zohar wrote:
> > On Wed, 2010-09-29 at 12:00 +0200, Roberto Sassu wrote:
> > > When a new encrypted key is created through the keyctl utility, the master
> > > key specified is not searched in the keyring and the operation is 
> > > performed even 
> > > if it is missing.
> > 
> > Yes, and why is this a problem?  After creating a new key, the first
> > thing done should be to save it.  At that point, you'd find out the
> > master-key doesn't exist, requiring you to either load it or change the
> > master-key name using 'keyctl update'.
> > 
> 
> I think the master key verification is important at least for one reason:
> i suppose to have one encrypted key which depends on a trusted key unsealed
> during the boot process. 

Yes, this would be the normal scenario - decrypting the encrypted key
with a trusted key.

> If the former key is present in the keyring, this does not mean
> that the platform is in a good status (condition required for the unsealing), 
>  
> since an attacker can generate another encryption key with the same name that 
> may be used by users to encrypt their personal data.

True, the existence of an encrypted key with the expected name does not
imply anything about the key.  However, using this 'fake' key will fail
to decrypt anything already encrypted with the real key. I'm not clear
how requiring the existence of the master-key prevents creating a 'fake'
key.

> The create check is probably wrong, what i mean is that key generation is an 
> administrative task and trusted and encrypted keys should be usable only 
> after 
> decryption with the key they depend to.

I understand your concern, but checking the existence of the master-key
at creation doesn't imply that it will exist later, when needed to save
the new key.  So immediately after creating a new key, it's important to
save both the master-key and the encrypted 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: [RFC][PATCH 1/4] lib: hex2bin converts ascii hexadecimal string to binary

2010-09-29 Thread Mimi Zohar
On Wed, 2010-09-29 at 13:11 +0100, David Howells wrote:
> Mimi Zohar  wrote:
> 
> > --- 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
> > + * @mem: result
> > + * @buf: ascii hexadecimal string
> > + * @count: result length
> > + */
> > +void hex2bin(unsigned char *mem, char *buf, int count)
> 
> Hmmm...  It might be better to put this in its own file in lib, otherwise it
> will drag in all the other functions in that file if used, and vice versa.
> 
> David

hex2bin calls hex_to_bin() which is defined right above it in the same
file. But the reverse, as you suggested, is still true.

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


crypto: return codes

2010-10-05 Thread Mimi Zohar
Hi,

Looking at different examples of the same crypto call, it's unclear
whether it only returns negative error values. Some examples only test
for negative values, while others test for not 0. tcrypt.c does "if
(ret)".  Would appreciate some clarification.

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 0/4] keys: trusted and encrypted keys

2010-10-07 Thread Mimi Zohar
Since the original posting, the encrypted keys are started at
late_initcall, in order to wait for the crypto API to be
initialized, minor changes were made to Kconfig, and the
TPM Maintainer acked the second patch.

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.

Trusted Keys are sealed under the SRK, which must have 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 [hex_pcrinfo]" ring
keyctl add trusted name "LOAD hex_blob" ring
keyctl update key "UPDATE hex_pcrinfo"
keyctl print keyid
keyctl pipe keyid > filename

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. The keywords NEW, LOAD, and
UPDATE can be all upper or all lower case.

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 master-key-name keylen hex_blob" ring
  keyctl update keyid "UPDATE master-key-name"

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
Dave Safford

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

 drivers/char/tpm/tpm.c|   17 +
 include/keys/encrypted-type.h |   30 ++
 include/keys/trusted-type.h   |   33 ++
 include/linux/kernel.h|1 +
 include/linux/tpm.h   |3 +
 lib/hexdump.c |   16 +
 security/Kconfig  |   31 ++
 security/keys/Makefile|2 +
 security/keys/encrypted_defined.c |  782 +
 security/keys/encrypted_defined.h |   52 ++
 security/keys/trusted_defined.c   |  997 +
 security/keys/trusted_defined.h   |  125 +
 12 files changed, 2089 insertions(+), 0 deletions(-)
 create mode 100644 include/keys/encrypted-type.h
 create mode 100644 include/keys/trusted-type.h
 create mode 100644 security/keys/encrypted_defined.c
 create mode 100644 security/keys/encrypted_defined.h
 create mode 100644 security/keys/trusted_defined.c
 create mode 100644 security/keys/trusted_defined.h

-- 
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 1/4] lib: hex2bin converts ascii hexadecimal string to binary

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

Signed-off-by: Mimi Zohar 
---
 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 2b0a35e..69ddea8 100644
--- a/include/linux/kernel.h
+++ b/include/linux/kernel.h
@@ -396,6 +396,7 @@ static inline char *pack_hex_byte(char *buf, u8 byte)
 }
 
 extern int hex_to_bin(char ch);
+extern void hex2bin(unsigned char *mem, char *buf, int count);
 
 #ifndef pr_fmt
 #define pr_fmt(fmt) fmt
diff --git a/lib/hexdump.c b/lib/hexdump.c
index 5d7a480..66f96bb 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
+ * @mem: result
+ * @buf: ascii hexadecimal string
+ * @count: result length
+ */
+void hex2bin(unsigned char *mem, char *buf, int count)
+{
+   while (count--) {
+   *mem = hex_to_bin(*buf++) << 4;
+   *mem += hex_to_bin(*buf++);
+   mem++;
+   }
+}
+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 2/4] key: add tpm_send command

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

Signed-off-by: David Safford 
Reviewd-by: Mimi Zohar 
Acked-by: Rajiv Andrade 
---
 drivers/char/tpm/tpm.c |   17 +
 include/linux/tpm.h|3 +++
 2 files changed, 20 insertions(+), 0 deletions(-)

diff --git a/drivers/char/tpm/tpm.c b/drivers/char/tpm/tpm.c
index 7c41335..5987d9c 100644
--- a/drivers/char/tpm/tpm.c
+++ b/drivers/char/tpm/tpm.c
@@ -780,6 +780,23 @@ 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, char *cmd, int buflen)
+{
+   struct tpm_chip *chip;
+   int rc;
+
+   chip = tpm_chip_find_get(chip_num);
+   if (chip == NULL)
+   return -ENODEV;
+
+   rc = transmit_cmd(chip, (struct tpm_cmd_t *)cmd, buflen,
+ "attempting tpm_cmd");
+
+   module_put(chip->dev->driver->owner);
+   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..a0ecaa9 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, char *cmd, int buflen);
 #else
 static inline int tpm_pcr_read(u32 chip_num, int pcr_idx, u8 *res_buf) {
return -ENODEV;
@@ -38,5 +39,7 @@ 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, char *cmd, int 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


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

2010-10-07 Thread Mimi Zohar
Defines a new kernel key-type called 'trusted'. Trusted keys are TPM
generated random numbers, RSA sealed by the TPM, and only unsealed by
the TPM, if boot PCRs and other criteria match. Trusted keys are
created/encrypted/decrypted in the kernel.  Userspace ever only
sees/stores encrypted blobs.

Signed-off-by: David Safford 
Signed-off-by: Mimi Zohar 
---
 include/keys/trusted-type.h |   33 ++
 security/Kconfig|   15 +
 security/keys/Makefile  |1 +
 security/keys/trusted_defined.c |  997 +++
 security/keys/trusted_defined.h |  125 +
 5 files changed, 1171 insertions(+), 0 deletions(-)
 create mode 100644 include/keys/trusted-type.h
 create mode 100644 security/keys/trusted_defined.c
 create mode 100644 security/keys/trusted_defined.h

diff --git a/include/keys/trusted-type.h b/include/keys/trusted-type.h
new file mode 100644
index 000..be7d44e
--- /dev/null
+++ b/include/keys/trusted-type.h
@@ -0,0 +1,33 @@
+/* trusted-type.h: trusted-defined key type
+ *
+ * Copyright (C) 2010 IBM Corporation
+ * Author: David Safford 
+ *
+ * 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_TRUSTED_TYPE_H
+#define _KEYS_TRUSTED_TYPE_H
+
+#include 
+#include 
+
+#define MAX_KEY_SIZE   128
+#define MAX_BLOB_SIZE  320
+#define MAX_PCRINFO_SIZE   64
+
+struct trusted_key_payload {
+   struct rcu_head rcu;/* RCU destructor */
+   unsigned int key_len;
+   unsigned int blob_len;
+   unsigned int pcrinfo_len;
+   unsigned char key[MAX_KEY_SIZE];
+   unsigned char blob[MAX_BLOB_SIZE];
+   unsigned char pcrinfo[MAX_PCRINFO_SIZE];
+};
+
+extern struct key_type key_type_trusted;
+
+#endif /* _KEYS_TRUSTED_TYPE_H */
diff --git a/security/Kconfig b/security/Kconfig
index bd72ae6..38fdaf6 100644
--- a/security/Kconfig
+++ b/security/Kconfig
@@ -21,6 +21,21 @@ config KEYS
 
  If you are unsure as to whether this is required, answer N.
 
+config TRUSTED_KEYS
+   tristate "TRUSTED KEYS"
+   depends on KEYS && TCG_TPM
+   select CRYPTO
+   select CRYPTO_HMAC
+   select CRYPTO_SHA1
+   help
+ This option provides support for creating/sealing/unsealing keys
+ in the kernel. Trusted keys are TPM generated random numbers
+ symmetric keys, RSA sealed by the TPM, and only unsealed by the
+ TPM, if boot PCRs and other criteria match.  Userspace ever only
+ 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 74d5447..fcb1070 100644
--- a/security/keys/Makefile
+++ b/security/keys/Makefile
@@ -13,6 +13,7 @@ obj-y := \
request_key_auth.o \
user_defined.o
 
+obj-$(CONFIG_TRUSTED_KEYS) += trusted_defined.o
 obj-$(CONFIG_KEYS_COMPAT) += compat.o
 obj-$(CONFIG_PROC_FS) += proc.o
 obj-$(CONFIG_SYSCTL) += sysctl.o
diff --git a/security/keys/trusted_defined.c b/security/keys/trusted_defined.c
new file mode 100644
index 000..aedad16
--- /dev/null
+++ b/security/keys/trusted_defined.c
@@ -0,0 +1,997 @@
+/*
+ * Copyright (C) 2010 IBM Corporation
+ *
+ * Author:
+ * David Safford 
+ *
+ * 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.
+ *
+ * File: trusted_defined.c
+ *
+ * Defines a new kernel key-type called 'trusted'. Trusted keys are
+ * TPM generated random numbers, RSA sealed by the TPM, and only unsealed
+ * by the TPM, if boot PCRs and other criteria match. Trusted keys are
+ * created/sealed/unsealed in the kernel. Userspace ever only sees/stores
+ * encrypted blobs.
+ *
+ * Keys are sealed under the SRK, which must have 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 [hex_pcrinfo]" ring
+ *   keyctl add trusted name "LOAD hex_blob" ring
+ *   keyctl update key "UPDATE hex_pcrinfo"
+ *   keyctl print keyid
+ * keys can be 32 - 128 bytes, blob max is 1024 hex ascii characters
+ * binary pcrinfo max is 512 hex ascii characters
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "trusted_defined.h"
+
+static char hmac_alg[] = "hmac(sha1)";
+static char

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

2010-10-07 Thread Mimi Zohar
Defines 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:
- wait until late_initcall for crypto libraries to be registered
- cleanup security/Kconfig

Signed-off-by: Mimi Zohar 
Signed-off-by: David Safford 
---
 include/keys/encrypted-type.h |   30 ++
 security/Kconfig  |   16 +
 security/keys/Makefile|1 +
 security/keys/encrypted_defined.c |  782 +
 security/keys/encrypted_defined.h |   52 +++
 5 files changed, 881 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..e2312e0
--- /dev/null
+++ b/include/keys/encrypted-type.h
@@ -0,0 +1,30 @@
+/* encrypted-type.h: encrypted-defined key type
+ *
+ * Copyright (C) 2010 IBM Corporation
+ * Author: Mimi Zohar 
+ *
+ * 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 
+#include 
+
+struct encrypted_key_payload {
+   struct rcu_head rcu;/* RCU destructor */
+   char *master_desc;  /* datablob: master key name */
+   char *datalen;  /* datablob: decrypted key length */
+   void *iv;   /* datablob: iv */
+   void *encrypted_data;   /* datablob: encrypted key */
+   unsigned short datablob_len;/* length of datablob */
+   unsigned short decrypted_datalen;   /* decrypted data length */
+   char 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 38fdaf6..d591398 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..68fff82
--- /dev/null
+++ b/security/keys/encrypted_defined.c
@@ -0,0 +1,782 @@
+/*
+ * Copyright (C) 2010 IBM Corporation
+ *
+ * Author:
+ * Mimi Zohar 
+ *
+ * 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.
+ *
+ * File: encrypted_defined.c
+ *
+ * Defines a new kernel key-type called 'encrypted'. Encrypted keys
+ * are kernel generated random numbers, which are encrypted/decrypted
+ * using a 'master' key. The 'master' key can either be a trusted-key or
+ * user-key type. Encrypted keys are created/encrypted/decrypted in the
+ * kernel. Userspace ever only sees/stores encrypted blobs.
+ *
+ * keyctl add "encrypted" "name" "NEW master-key-name keylen" ring
+ * keyctl add "encrypted" "name" "LOAD master-key-name keylen hex_blob" ring
+ * keyctl update keyid "UPDATE master-key-name"
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+

Re: [PATCH 1/2] keys: fixed handling of update method of the encrypted key type

2010-10-07 Thread Mimi Zohar
Nice! This patch applies cleanly to the trusted/encrypted patch set
posted today.

thanks,

Acked-by: Mimi Zohar 

On Thu, 2010-10-07 at 14:29 +0200, Roberto Sassu wrote:
> This patch adds the UPDATE keyword for encrypted key types:
> prevents updating existent keys if UPDATE is missing and creating
> new keys when UPDATE is specified.
> 
> Signed-off-by: Roberto Sassu 
> ---
>  security/keys/encrypted_defined.c |   31 +++
>  1 files changed, 23 insertions(+), 8 deletions(-)
> 
> diff --git a/security/keys/encrypted_defined.c 
> b/security/keys/encrypted_defined.c
> index 6b26db6..54c0f0f 100644
> --- a/security/keys/encrypted_defined.c
> +++ b/security/keys/encrypted_defined.c
> @@ -64,7 +64,8 @@ static int aes_get_sizes(int *ivsize, int *blksize)
>  }
>  
>  enum {
> - Opt_err = -1, Opt_new = 1, Opt_load, Opt_NEW, Opt_LOAD
> + Opt_err = -1, Opt_new = 1, Opt_load, 
> + Opt_update, Opt_NEW, Opt_LOAD, Opt_UPDATE
>  };
>  
>  static match_table_t key_tokens = {
> @@ -72,6 +73,8 @@ static match_table_t key_tokens = {
>   {Opt_NEW, "NEW"},
>   {Opt_load, "load"},
>   {Opt_LOAD, "LOAD"},
> + {Opt_update, "update"},
> + {Opt_UPDATE, "UPDATE"},
>   {Opt_err, NULL}
>  };
>  
> @@ -81,6 +84,7 @@ static match_table_t key_tokens = {
>   * datablob format:
>   * NEW  
>   * LOAD   
> + * UPDATE 
>   *
>   * Tokenizes a copy of the keyctl data, returning a pointer to each token,
>   * which is null terminated.
> @@ -104,23 +108,36 @@ static int datablob_parse(char *datablob, char 
> **master_desc,
>   *master_desc = strsep(&datablob, " \t");
>   if (!*master_desc)
>   goto out;
> - *decrypted_datalen = strsep(&datablob, " \t");
> - if (!*decrypted_datalen)
> - goto out;
> +
> + if (decrypted_datalen) {
> + *decrypted_datalen = strsep(&datablob, " \t");
> + if (!*decrypted_datalen)
> + goto out;
> + }
>  
>   switch (key_cmd) {
>   case Opt_new:
>   case Opt_NEW:
> + if (!decrypted_datalen)
> + break;
>   ret = 0;
>   break;
>   case Opt_load:
>   case Opt_LOAD:
> + if (!decrypted_datalen)
> + break;
>   *hex_encoded_iv = strsep(&datablob, " \t");
>   if (!*hex_encoded_iv)
>   break;
>   *hex_encoded_data = *hex_encoded_iv + (2 * ivsize) + 2;
>   ret = 0;
>   break;
> + case Opt_update:
> + case Opt_UPDATE:
> + if (decrypted_datalen)
> + break;
> + ret = 0;
> + break;
>   case Opt_err:
>   break;
>   }
> @@ -647,11 +664,9 @@ static int encrypted_update(struct key *key, const void 
> *data, size_t datalen)
>   return -ENOMEM;
>  
>   memcpy(buf, data, datalen);
> - new_master_desc = strsep(&buf, " \t");
> - if (!*new_master_desc) {
> - ret = -EINVAL;
> + ret = datablob_parse(buf, &new_master_desc, NULL, NULL, NULL);
> + if (ret < 0)
>   goto out;
> - }
>  
>   new_epayload = encrypted_key_alloc(key, new_master_desc,
>  epayload->datalen);


--
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 2/2] keys: added cleanup code for trusted and encrypted key types

2010-10-07 Thread Mimi Zohar
Thanks for catching this! This patch applies cleanly to the
trusted/encrypted patch set posted today.

thanks,

Acked-by: Mimi Zohar 

On Thu, 2010-10-07 at 14:30 +0200, Roberto Sassu wrote:
> This patch frees the payload at the end of the instantiate
> method of both trusted and encrypted key types if an error occurs.
> 
> Signed-off-by: Roberto Sassu 
> ---
>  security/keys/encrypted_defined.c |6 ++
>  security/keys/trusted_defined.c   |4 
>  2 files changed, 10 insertions(+), 0 deletions(-)
> 
> diff --git a/security/keys/encrypted_defined.c 
> b/security/keys/encrypted_defined.c
> index 54c0f0f..8426e66 100644
> --- a/security/keys/encrypted_defined.c
> +++ b/security/keys/encrypted_defined.c
> @@ -624,7 +624,13 @@ static int encrypted_instantiate(struct key *key, const 
> void *data,
>   }
>   ret = encrypted_init(epayload, master_desc, decrypted_datalen,
>hex_encoded_iv, hex_encoded_data);
> + if (ret)
> + goto out_free_epayload;
> +
>   rcu_assign_pointer(key->payload.data, epayload);
> +out_free_epayload:
> + if (ret)
> + kfree(epayload);
>  out:
>   kfree(datablob);
>   return ret > 0 ? -EINVAL : ret;
> diff --git a/security/keys/trusted_defined.c b/security/keys/trusted_defined.c
> index aedad16..ab7c7f9 100644
> --- a/security/keys/trusted_defined.c
> +++ b/security/keys/trusted_defined.c
> @@ -848,6 +848,10 @@ static int trusted_instantiate(struct key *key, const 
> void *data,
>  out:
>   if (!ret)
>   rcu_assign_pointer(key->payload.data, p);
> + else {
> + if (p)
> + kfree(p);
> + }
>   kfree(datablob);
>   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: crypto: return codes

2010-10-09 Thread Mimi Zohar
On Sat, 2010-10-09 at 09:29 +0800, Herbert Xu wrote:
> Mimi Zohar  wrote:
> > Hi,
> > 
> > Looking at different examples of the same crypto call, it's unclear
> > whether it only returns negative error values. Some examples only test
> > for negative values, while others test for not 0. tcrypt.c does "if
> > (ret)".  Would appreciate some clarification.
> 
> Unless the call can return positive values then it makes no
> difference.  Which particular call are you talking about?
> 
> Cheers,

Just to name a few: crypto_hash_init(), crypto_hash_update(),
crypto_hash_final(). Also crypto_blkcipher_decrypt/encrypt().  Would be
nice to know definitively that they return < 0 on error and 0 for
success.

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.1 0/4] keys: trusted and encrypted keys

2010-10-11 Thread Mimi Zohar
Since the original posting, the encrypted keys are started at
late_initcall, in order to wait for the crypto API to be
initialized, minor changes were made to Kconfig, Roberto Sassu's
fixes (adding missing 'update' keyword, freeing allocated memory
on failure) were merged, increased the data size limit, based on
Roberto's request, and added Rajiv Andrade's ack for the TPM
patch.

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.

Trusted Keys are sealed under the SRK, which must have 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 [hex_pcrinfo]" ring
keyctl add trusted name "LOAD hex_blob" ring
keyctl update key "UPDATE hex_pcrinfo"
keyctl print keyid
keyctl pipe keyid > filename

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. The keywords NEW, LOAD, and
UPDATE can be all upper or all lower case.

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 master-key-name keylen hex_blob" ring
  keyctl update keyid "UPDATE master-key-name"

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
Dave Safford

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

 drivers/char/tpm/tpm.c|   17 +
 include/keys/encrypted-type.h |   30 ++
 include/keys/trusted-type.h   |   33 ++
 include/linux/kernel.h|1 +
 include/linux/tpm.h   |3 +
 lib/hexdump.c |   16 +
 security/Kconfig  |   31 ++
 security/keys/Makefile|2 +
 security/keys/encrypted_defined.c |  782 +
 security/keys/encrypted_defined.h |   52 ++
 security/keys/trusted_defined.c   |  997 +
 security/keys/trusted_defined.h   |  125 +
 12 files changed, 2089 insertions(+), 0 deletions(-)
 create mode 100644 include/keys/encrypted-type.h
 create mode 100644 include/keys/trusted-type.h
 create mode 100644 security/keys/encrypted_defined.c
 create mode 100644 security/keys/encrypted_defined.h
 create mode 100644 security/keys/trusted_defined.c
 create mode 100644 security/keys/trusted_defined.h

-- 
1.7.2.2

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

 drivers/char/tpm/tpm.c|   17 +
 include/keys/encrypted-type.h |   30 ++
 include/keys/trusted-type.h   |   33 ++
 include/linux/kernel.h|1 +
 include/linux/tpm.h   |3 +
 lib/he

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

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

Signed-off-by: Mimi Zohar 
---
 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 2b0a35e..69ddea8 100644
--- a/include/linux/kernel.h
+++ b/include/linux/kernel.h
@@ -396,6 +396,7 @@ static inline char *pack_hex_byte(char *buf, u8 byte)
 }
 
 extern int hex_to_bin(char ch);
+extern void hex2bin(unsigned char *mem, char *buf, int count);
 
 #ifndef pr_fmt
 #define pr_fmt(fmt) fmt
diff --git a/lib/hexdump.c b/lib/hexdump.c
index 5d7a480..66f96bb 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
+ * @mem: result
+ * @buf: ascii hexadecimal string
+ * @count: result length
+ */
+void hex2bin(unsigned char *mem, char *buf, int count)
+{
+   while (count--) {
+   *mem = hex_to_bin(*buf++) << 4;
+   *mem += hex_to_bin(*buf++);
+   mem++;
+   }
+}
+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.1 2/4] key: add tpm_send command

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

Signed-off-by: David Safford 
Reviewd-by: Mimi Zohar 
Acked-by: Rajiv Andrade 
---
 drivers/char/tpm/tpm.c |   17 +
 include/linux/tpm.h|3 +++
 2 files changed, 20 insertions(+), 0 deletions(-)

diff --git a/drivers/char/tpm/tpm.c b/drivers/char/tpm/tpm.c
index 7c41335..5987d9c 100644
--- a/drivers/char/tpm/tpm.c
+++ b/drivers/char/tpm/tpm.c
@@ -780,6 +780,23 @@ 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, char *cmd, int buflen)
+{
+   struct tpm_chip *chip;
+   int rc;
+
+   chip = tpm_chip_find_get(chip_num);
+   if (chip == NULL)
+   return -ENODEV;
+
+   rc = transmit_cmd(chip, (struct tpm_cmd_t *)cmd, buflen,
+ "attempting tpm_cmd");
+
+   module_put(chip->dev->driver->owner);
+   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..a0ecaa9 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, char *cmd, int buflen);
 #else
 static inline int tpm_pcr_read(u32 chip_num, int pcr_idx, u8 *res_buf) {
return -ENODEV;
@@ -38,5 +39,7 @@ 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, char *cmd, int 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


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

2010-10-11 Thread Mimi Zohar
Defines a new kernel key-type called 'trusted'. Trusted keys are TPM
generated random numbers, RSA sealed by the TPM, and only unsealed by
the TPM, if boot PCRs and other criteria match. Trusted keys are
created/encrypted/decrypted in the kernel.  Userspace ever only
sees/stores encrypted blobs.

Changelog:
- Free payload on failure to create key(reported/fixed by Roberto Sassu)

Signed-off-by: David Safford 
Signed-off-by: Mimi Zohar 
---
 include/keys/trusted-type.h |   33 ++
 security/Kconfig|   15 +
 security/keys/Makefile  |1 +
 security/keys/trusted_defined.c |  999 +++
 security/keys/trusted_defined.h |  125 +
 5 files changed, 1173 insertions(+), 0 deletions(-)
 create mode 100644 include/keys/trusted-type.h
 create mode 100644 security/keys/trusted_defined.c
 create mode 100644 security/keys/trusted_defined.h

diff --git a/include/keys/trusted-type.h b/include/keys/trusted-type.h
new file mode 100644
index 000..be7d44e
--- /dev/null
+++ b/include/keys/trusted-type.h
@@ -0,0 +1,33 @@
+/* trusted-type.h: trusted-defined key type
+ *
+ * Copyright (C) 2010 IBM Corporation
+ * Author: David Safford 
+ *
+ * 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_TRUSTED_TYPE_H
+#define _KEYS_TRUSTED_TYPE_H
+
+#include 
+#include 
+
+#define MAX_KEY_SIZE   128
+#define MAX_BLOB_SIZE  320
+#define MAX_PCRINFO_SIZE   64
+
+struct trusted_key_payload {
+   struct rcu_head rcu;/* RCU destructor */
+   unsigned int key_len;
+   unsigned int blob_len;
+   unsigned int pcrinfo_len;
+   unsigned char key[MAX_KEY_SIZE];
+   unsigned char blob[MAX_BLOB_SIZE];
+   unsigned char pcrinfo[MAX_PCRINFO_SIZE];
+};
+
+extern struct key_type key_type_trusted;
+
+#endif /* _KEYS_TRUSTED_TYPE_H */
diff --git a/security/Kconfig b/security/Kconfig
index bd72ae6..38fdaf6 100644
--- a/security/Kconfig
+++ b/security/Kconfig
@@ -21,6 +21,21 @@ config KEYS
 
  If you are unsure as to whether this is required, answer N.
 
+config TRUSTED_KEYS
+   tristate "TRUSTED KEYS"
+   depends on KEYS && TCG_TPM
+   select CRYPTO
+   select CRYPTO_HMAC
+   select CRYPTO_SHA1
+   help
+ This option provides support for creating/sealing/unsealing keys
+ in the kernel. Trusted keys are TPM generated random numbers
+ symmetric keys, RSA sealed by the TPM, and only unsealed by the
+ TPM, if boot PCRs and other criteria match.  Userspace ever only
+ 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 74d5447..fcb1070 100644
--- a/security/keys/Makefile
+++ b/security/keys/Makefile
@@ -13,6 +13,7 @@ obj-y := \
request_key_auth.o \
user_defined.o
 
+obj-$(CONFIG_TRUSTED_KEYS) += trusted_defined.o
 obj-$(CONFIG_KEYS_COMPAT) += compat.o
 obj-$(CONFIG_PROC_FS) += proc.o
 obj-$(CONFIG_SYSCTL) += sysctl.o
diff --git a/security/keys/trusted_defined.c b/security/keys/trusted_defined.c
new file mode 100644
index 000..0bd935f
--- /dev/null
+++ b/security/keys/trusted_defined.c
@@ -0,0 +1,999 @@
+/*
+ * Copyright (C) 2010 IBM Corporation
+ *
+ * Author:
+ * David Safford 
+ *
+ * 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.
+ *
+ * File: trusted_defined.c
+ *
+ * Defines a new kernel key-type called 'trusted'. Trusted keys are
+ * TPM generated random numbers, RSA sealed by the TPM, and only unsealed
+ * by the TPM, if boot PCRs and other criteria match. Trusted keys are
+ * created/sealed/unsealed in the kernel. Userspace ever only sees/stores
+ * encrypted blobs.
+ *
+ * Keys are sealed under the SRK, which must have 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 [hex_pcrinfo]" ring
+ *   keyctl add trusted name "LOAD hex_blob" ring
+ *   keyctl update key "UPDATE hex_pcrinfo"
+ *   keyctl print keyid
+ * keys can be 32 - 128 bytes, blob max is 1024 hex ascii characters
+ * binary pcrinfo max is 512 hex ascii characters
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "trusted_de

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

2010-10-11 Thread Mimi Zohar
Defines 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:
- 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.

Signed-off-by: Mimi Zohar 
Signed-off-by: David Safford 
Reviewed-by: Roberto Sassu 
---
 include/keys/encrypted-type.h |   30 ++
 security/Kconfig  |   16 +
 security/keys/Makefile|1 +
 security/keys/encrypted_defined.c |  804 +
 security/keys/encrypted_defined.h |   52 +++
 5 files changed, 903 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..e2312e0
--- /dev/null
+++ b/include/keys/encrypted-type.h
@@ -0,0 +1,30 @@
+/* encrypted-type.h: encrypted-defined key type
+ *
+ * Copyright (C) 2010 IBM Corporation
+ * Author: Mimi Zohar 
+ *
+ * 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 
+#include 
+
+struct encrypted_key_payload {
+   struct rcu_head rcu;/* RCU destructor */
+   char *master_desc;  /* datablob: master key name */
+   char *datalen;  /* datablob: decrypted key length */
+   void *iv;   /* datablob: iv */
+   void *encrypted_data;   /* datablob: encrypted key */
+   unsigned short datablob_len;/* length of datablob */
+   unsigned short decrypted_datalen;   /* decrypted data length */
+   char 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 38fdaf6..d591398 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..5331925
--- /dev/null
+++ b/security/keys/encrypted_defined.c
@@ -0,0 +1,804 @@
+/*
+ * Copyright (C) 2010 IBM Corporation
+ *
+ * Author:
+ * Mimi Zohar 
+ *
+ * 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.
+ *
+ * File: encrypted_defined.c
+ *
+ * Defines a new kernel key-type called 'encrypted'. Encrypted keys
+ * are kernel generated random numbers, which are encrypted/decrypted
+ * using a 'master' key. The 'master' key can either be a trusted-key or
+ * user-key type. Encrypted keys are created/encrypted/decrypted in the
+ * kernel. Userspace ever only sees/stores encrypted blobs.
+ *
+ * keyctl add "encrypted" "name" "NEW master-key-name keylen" ring
+ * k

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

2010-10-12 Thread Mimi Zohar
On Mon, 2010-10-11 at 20:22 -0500, Serge E. Hallyn wrote: 
> Quoting Mimi Zohar (zo...@linux.vnet.ibm.com):
> 
> Looks fine to me, and very useful.
> 
> Acked-by: Serge E. Hallyn 
> 
> (for 1-3, haven't looked at 4 yet and won't tonight)

Thanks Serge!

> > +config TRUSTED_KEYS
> > +   tristate "TRUSTED KEYS"
> > +   depends on KEYS && TCG_TPM
> > +   select CRYPTO
> > +   select CRYPTO_HMAC
> > +   select CRYPTO_SHA1
> > +   help
> > + This option provides support for creating/sealing/unsealing keys
> > + in the kernel. Trusted keys are TPM generated random numbers
> > + symmetric keys, RSA sealed by the TPM, and only unsealed by the
> > + TPM, if boot PCRs and other criteria match.  Userspace ever only
> > + sees/stores encrypted blobs.
> 
> "
> This option provides support for creating, sealing, and unsealing keys
> in the kernel.  Trusted keys are ramdon symmetric keys created
> RSA-sealed, and stored in the TPM.  The TPM only unseals the keys if the
> boot PCRs and other criteria match.  Userspace can only ever see
> encrypted blobs.
> "

Better, but keys are not stored in the TPM. How about:

This option provides support for creating, sealing, and unsealing keys
in the kernel.  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.

> > diff --git a/security/keys/trusted_defined.c 
> > b/security/keys/trusted_defined.c
> > new file mode 100644
> > index 000..0bd935f
> > --- /dev/null
> > +++ b/security/keys/trusted_defined.c
> > @@ -0,0 +1,999 @@
> > +/*
> > + * Copyright (C) 2010 IBM Corporation
> > + *
> > + * Author:
> > + * David Safford 
> > + *
> > + * 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.
> > + *
> > + * File: trusted_defined.c
> 
> (don't put filenames in comments :)

There are plenty of examples containing the filename.  I guess this
changed at some point. Thanks for bringing it to my attention.

> > + * Defines a new kernel key-type called 'trusted'. Trusted keys are
> > + * TPM generated random numbers, RSA sealed by the TPM, and only unsealed
> > + * by the TPM, if boot PCRs and other criteria match. Trusted keys are
> > + * created/sealed/unsealed in the kernel. Userspace ever only sees/stores
> > + * encrypted blobs.
> > + *
> > + * Keys are sealed under the SRK, which must have the default
> > + * authorization value (20 zeros).
> 
> What does this mean?  They have to be sealed by a key that starts
> with 20 zeros?  (of course it doesn't mean that, but i don't understand
> what it does mean :)

Defines 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.

Trusted keys are sealed with the Storage Root Key(SRK). The SRK usage
authorization value is the well-known authorization value of 20 zeroes. 

(In english this means we follow accepted convention and do not bother 
with a password on the SRK.)

> > This can be set at takeownership
> > + * time with the trouser's utility "tpm_takeownership -u -z".
> > + *
> > + * Usage:
> > + *   keyctl add trusted name "NEW keylen [hex_pcrinfo]" ring
> > + *   keyctl add trusted name "LOAD hex_blob" ring
> > + *   keyctl update key "UPDATE hex_pcrinfo"
> > + *   keyctl print keyid
> > + * keys can be 32 - 128 bytes, blob max is 1024 hex ascii characters
> > + * binary pcrinfo max is 512 hex ascii characters
> > + */
> > +
> > +#include 
> > +#include 
> > +#include 
> > +#include 
> > +#include 
> > +#include 
> > +#include 
> > +#include 
> > +#include 
> > +#include 
> > +#include 
> > +#include 
> > +#include 
> > +#include 
> > +#include 
> > +
> > +#include "trusted_defined.h"
> > +
> > +static char hmac_alg[] = "hmac(sha1)";
> > +static char hash_alg[] = "sha1";
> > +
> > +static int init_sha1_desc(struct hash_desc *desc)
> > +{
> > +   int rc;
> > +
> > +   desc->tfm = crypto_alloc_hash(hash_alg, 0, CRYPTO_ALG_ASYNC);
> > +   if (IS_ERR(desc-

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

2010-11-02 Thread Mimi Zohar
On Tue, 2010-11-02 at 10:30 +0100, Roberto Sassu wrote:
> The buffer 'derived_buf' in the function get_derived_key() must be
> allocated dynamically in order to make room for an arbitrary length
> master key.
> 
> Signed-off-by: Roberto Sassu 
> ---
>  security/keys/encrypted_defined.c |   15 +--
>  1 files changed, 13 insertions(+), 2 deletions(-)
> 
> diff --git a/security/keys/encrypted_defined.c 
> b/security/keys/encrypted_defined.c
> index 5331925..65d9b13 100644
> --- a/security/keys/encrypted_defined.c
> +++ b/security/keys/encrypted_defined.c
> @@ -289,10 +289,20 @@ enum derived_key_type { ENC_KEY, AUTH_KEY };
>  static int get_derived_key(char *derived_key, enum derived_key_type key_type,
>  void *master_key, unsigned int master_keylen)
>  {
> - char derived_buf[hash_size + 10];
> + char *derived_buf;
>   int ret;
> + unsigned int derived_buf_len;
> +
> + derived_buf_len = strlen("AUTH_KEY") + 1 + master_keylen;
> + if (derived_buf_len < hash_size)
> + derived_buf_len = hash_size;
> +
> + derived_buf = kzalloc(derived_buf_len, GFP_KERNEL);
> + if (!derived_buf) {
> + pr_err("encrypted_key: out of memory\n");
> + return -ENOMEM;
> + }
>  
> - memset(derived_buf, 0, sizeof derived_buf);

Thanks Roberto!

>   if (key_type)
>   strcpy(derived_buf, "AUTH_KEY");
>   else
> @@ -301,6 +311,7 @@ static int get_derived_key(char *derived_key, enum 
> derived_key_type key_type,
>   memcpy(derived_buf + strlen(derived_buf) + 1, master_key,
>  master_keylen);
>   ret = calc_hash(derived_key, derived_buf, sizeof derived_buf);
> + kfree(derived_buf);
>   return ret;
>  }
>  

Yes, and the length in calc_hash() would then need to be
derived_buf_len.

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.2 1/4] lib: hex2bin converts ascii hexadecimal string to binary

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

Signed-off-by: Mimi Zohar 
Acked-by: Serge E. Hallyn 
---
 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 450092c..efe0e1e 100644
--- a/include/linux/kernel.h
+++ b/include/linux/kernel.h
@@ -417,6 +417,7 @@ static inline char *pack_hex_byte(char *buf, u8 byte)
 }
 
 extern int hex_to_bin(char ch);
+extern void hex2bin(unsigned char *mem, char *buf, int count);
 
 #ifndef pr_fmt
 #define pr_fmt(fmt) fmt
diff --git a/lib/hexdump.c b/lib/hexdump.c
index 5d7a480..66f96bb 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
+ * @mem: result
+ * @buf: ascii hexadecimal string
+ * @count: result length
+ */
+void hex2bin(unsigned char *mem, char *buf, int count)
+{
+   while (count--) {
+   *mem = hex_to_bin(*buf++) << 4;
+   *mem += hex_to_bin(*buf++);
+   mem++;
+   }
+}
+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.2 0/4] keys: trusted and encrypted keys

2010-11-08 Thread Mimi Zohar
The major change, since the previous posting, are serveral new
trusted-key options (migratable, pcrlock, keyhandle, keyauth, blobauth),
described below, based on suggestions by Jason Gunthorpe. By default,
trusted keys work as previously described. 

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)
 
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 master-key-name keylen hex_blob" ring
  keyctl update keyid "update master-key-name"

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
Dave Safford

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

 drivers/char/tpm/tpm.c|   17 +
 include/keys/encrypted-type.h |   30 +
 include/keys/trusted-type.h   |   32 ++
 include/linux/kernel.h|1 +
 include/linux/tpm.h   |3 +
 lib/hexdump.c |   16 +
 security/Kconfig  |   31 +
 security/keys/Makefile|2 +
 security/keys/encrypted_defined.c |  816 +++
 security/keys/encrypted_defined.h |   52 ++
 security/keys/trusted_defined.c   | 1096 +
 security/keys/trusted_defined.h   |  147 +
 12 files changed, 2243 insertions(+), 0 deletions(-)
 create mode 100644 include/keys/encrypted-type.h
 create mode 100644 include/keys/trusted-type.h
 create mode 100644 security/keys/encrypted_defined.c
 create mode 100644 security/keys/encrypted_defined.h
 create mode 100644 security/keys/trusted_defined.c
 create mode 100644 security/keys/trusted_defined.h

-- 
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.2 3/4] keys: add new trusted key-type

2010-11-08 Thread Mimi Zohar
Defines 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:
- 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 
Signed-off-by: Mimi Zohar 
---
 include/keys/trusted-type.h |   32 ++
 security/Kconfig|   15 +
 security/keys/Makefile  |1 +
 security/keys/trusted_defined.c | 1096 +++
 security/keys/trusted_defined.h |  147 ++
 5 files changed, 1291 insertions(+), 0 deletions(-)
 create mode 100644 include/keys/trusted-type.h
 create mode 100644 security/keys/trusted_defined.c
 create mode 100644 security/keys/trusted_defined.h

diff --git a/include/keys/trusted-type.h b/include/keys/trusted-type.h
new file mode 100644
index 000..5c3a158
--- /dev/null
+++ b/include/keys/trusted-type.h
@@ -0,0 +1,32 @@
+/* trusted-type.h: trusted-defined key type
+ *
+ * Copyright (C) 2010 IBM Corporation
+ * Author: David Safford 
+ *
+ * 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_TRUSTED_TYPE_H
+#define _KEYS_TRUSTED_TYPE_H
+
+#include 
+#include 
+
+#define MIN_KEY_SIZE   32
+#define MAX_KEY_SIZE   128
+#define MAX_BLOB_SIZE  320
+
+struct trusted_key_payload {
+   struct rcu_head rcu;/* RCU destructor */
+   unsigned int key_len;
+   unsigned int blob_len;
+   unsigned char migratable;
+   unsigned char key[MAX_KEY_SIZE+1];
+   unsigned char blob[MAX_BLOB_SIZE];
+};
+
+extern struct key_type key_type_trusted;
+
+#endif /* _KEYS_TRUSTED_TYPE_H */
diff --git a/security/Kconfig b/security/Kconfig
index bd72ae6..415422e 100644
--- a/security/Kconfig
+++ b/security/Kconfig
@@ -21,6 +21,21 @@ config KEYS
 
  If you are unsure as to whether this is required, answer N.
 
+config TRUSTED_KEYS
+   tristate "TRUSTED KEYS"
+   depends on KEYS && TCG_TPM
+   select CRYPTO
+   select CRYPTO_HMAC
+   select CRYPTO_SHA1
+   help
+ This option provides support for creating, sealing, and unsealing
+ keys in the kernel. 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.
+
+ 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 74d5447..fcb1070 100644
--- a/security/keys/Makefile
+++ b/security/keys/Makefile
@@ -13,6 +13,7 @@ obj-y := \
request_key_auth.o \
user_defined.o
 
+obj-$(CONFIG_TRUSTED_KEYS) += trusted_defined.o
 obj-$(CONFIG_KEYS_COMPAT) += compat.o
 obj-$(CONFIG_PROC_FS) += proc.o
 obj-$(CONFIG_SYSCTL) += sysctl.o
diff --git a/security/keys/trusted_defined.c b/security/keys/trusted_defined.c
new file mode 100644
index 000..a16a63f
--- /dev/null
+++ b/security/keys/trusted_defined.c
@@ -0,0 +1,1096 @@
+/*
+ * Copyright (C) 2010 IBM Corporation
+ *
+ * Author:
+ * David Safford 
+ *
+ * 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.
+ *
+ * Defines 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 matc

[PATCH v1.2 2/4] key: add tpm_send command

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

Signed-off-by: David Safford 
Reviewd-by: Mimi Zohar 
Acked-by: Rajiv Andrade 
Acked-by: Serge E. Hallyn 
---
 drivers/char/tpm/tpm.c |   17 +
 include/linux/tpm.h|3 +++
 2 files changed, 20 insertions(+), 0 deletions(-)

diff --git a/drivers/char/tpm/tpm.c b/drivers/char/tpm/tpm.c
index 7c41335..5987d9c 100644
--- a/drivers/char/tpm/tpm.c
+++ b/drivers/char/tpm/tpm.c
@@ -780,6 +780,23 @@ 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, char *cmd, int buflen)
+{
+   struct tpm_chip *chip;
+   int rc;
+
+   chip = tpm_chip_find_get(chip_num);
+   if (chip == NULL)
+   return -ENODEV;
+
+   rc = transmit_cmd(chip, (struct tpm_cmd_t *)cmd, buflen,
+ "attempting tpm_cmd");
+
+   module_put(chip->dev->driver->owner);
+   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..a0ecaa9 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, char *cmd, int buflen);
 #else
 static inline int tpm_pcr_read(u32 chip_num, int pcr_idx, u8 *res_buf) {
return -ENODEV;
@@ -38,5 +39,7 @@ 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, char *cmd, int 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


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

2010-11-08 Thread Mimi Zohar
Defines 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:
- 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 
Signed-off-by: David Safford 
Reviewed-by: Roberto Sassu 
---
 include/keys/encrypted-type.h |   30 ++
 security/Kconfig  |   16 +
 security/keys/Makefile|1 +
 security/keys/encrypted_defined.c |  816 +
 security/keys/encrypted_defined.h |   52 +++
 5 files changed, 915 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..e2312e0
--- /dev/null
+++ b/include/keys/encrypted-type.h
@@ -0,0 +1,30 @@
+/* encrypted-type.h: encrypted-defined key type
+ *
+ * Copyright (C) 2010 IBM Corporation
+ * Author: Mimi Zohar 
+ *
+ * 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 
+#include 
+
+struct encrypted_key_payload {
+   struct rcu_head rcu;/* RCU destructor */
+   char *master_desc;  /* datablob: master key name */
+   char *datalen;  /* datablob: decrypted key length */
+   void *iv;   /* datablob: iv */
+   void *encrypted_data;   /* datablob: encrypted key */
+   unsigned short datablob_len;/* length of datablob */
+   unsigned short decrypted_datalen;   /* decrypted data length */
+   char 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 415422e..a031ebb 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..1d41228
--- /dev/null
+++ b/security/keys/encrypted_defined.c
@@ -0,0 +1,816 @@
+/*
+ * Copyright (C) 2010 IBM Corporation
+ *
+ * Author:
+ * Mimi Zohar 
+ *
+ * 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.
+ *
+ * File: encrypted_defined.c
+ *
+ * Defines a new kernel key-type called 'encrypted'. Encrypted keys
+ * are kernel generated random numbers, which are encrypted/decrypted
+ * using a 'master' key. The 'master' key can either be a trusted-key or
+ * user-key type. Encrypted keys are created/encrypted/decrypted in the
+ * kernel. Userspace ever only sees/st

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

2010-11-10 Thread Mimi Zohar
The previous posting added serveral new trusted-key options (migratable,
pcrlock, keyhandle, keyauth, blobauth), described below, based on
suggestions by Jason Gunthorpe. This patch requires the pcrlock option
be executed with CAP_SYS_ADMIN privileges.  By default, trusted keys
work as previously described. 

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)
 
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 master-key-name keylen hex_blob" ring
  keyctl update keyid "update master-key-name"

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 (4):
  lib: hex2bin converts ascii hexadecimal string to binary
  key: add tpm_send command
  keys: add new trusted key-type
  keys: add new key-type encrypted

 drivers/char/tpm/tpm.c|   17 +
 include/keys/encrypted-type.h |   30 +
 include/keys/trusted-type.h   |   32 ++
 include/linux/kernel.h|1 +
 include/linux/tpm.h   |3 +
 lib/hexdump.c |   16 +
 security/Kconfig  |   31 +
 security/keys/Makefile|2 +
 security/keys/encrypted_defined.c |  816 +++
 security/keys/encrypted_defined.h |   52 ++
 security/keys/trusted_defined.c   | 1101 +
 security/keys/trusted_defined.h   |  147 +
 12 files changed, 2248 insertions(+), 0 deletions(-)
 create mode 100644 include/keys/encrypted-type.h
 create mode 100644 include/keys/trusted-type.h
 create mode 100644 security/keys/encrypted_defined.c
 create mode 100644 security/keys/encrypted_defined.h
 create mode 100644 security/keys/trusted_defined.c
 create mode 100644 security/keys/trusted_defined.h

-- 
1.7.2.2

--
To unsubscribe from this list: send the line "unsubscribe linu

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

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

Signed-off-by: Mimi Zohar 
Acked-by: Serge E. Hallyn 
---
 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..b03aa43 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(unsigned char *mem, char *buf, int count);
 
 #ifndef pr_fmt
 #define pr_fmt(fmt) fmt
diff --git a/lib/hexdump.c b/lib/hexdump.c
index 5d7a480..66f96bb 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
+ * @mem: result
+ * @buf: ascii hexadecimal string
+ * @count: result length
+ */
+void hex2bin(unsigned char *mem, char *buf, int count)
+{
+   while (count--) {
+   *mem = hex_to_bin(*buf++) << 4;
+   *mem += hex_to_bin(*buf++);
+   mem++;
+   }
+}
+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.3 3/4] keys: add new trusted key-type

2010-11-10 Thread Mimi Zohar
Defines 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:
- 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 
Signed-off-by: Mimi Zohar 
---
 include/keys/trusted-type.h |   32 ++
 security/Kconfig|   15 +
 security/keys/Makefile  |1 +
 security/keys/trusted_defined.c | 1101 +++
 security/keys/trusted_defined.h |  147 ++
 5 files changed, 1296 insertions(+), 0 deletions(-)
 create mode 100644 include/keys/trusted-type.h
 create mode 100644 security/keys/trusted_defined.c
 create mode 100644 security/keys/trusted_defined.h

diff --git a/include/keys/trusted-type.h b/include/keys/trusted-type.h
new file mode 100644
index 000..5c3a158
--- /dev/null
+++ b/include/keys/trusted-type.h
@@ -0,0 +1,32 @@
+/* trusted-type.h: trusted-defined key type
+ *
+ * Copyright (C) 2010 IBM Corporation
+ * Author: David Safford 
+ *
+ * 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_TRUSTED_TYPE_H
+#define _KEYS_TRUSTED_TYPE_H
+
+#include 
+#include 
+
+#define MIN_KEY_SIZE   32
+#define MAX_KEY_SIZE   128
+#define MAX_BLOB_SIZE  320
+
+struct trusted_key_payload {
+   struct rcu_head rcu;/* RCU destructor */
+   unsigned int key_len;
+   unsigned int blob_len;
+   unsigned char migratable;
+   unsigned char key[MAX_KEY_SIZE+1];
+   unsigned char blob[MAX_BLOB_SIZE];
+};
+
+extern struct key_type key_type_trusted;
+
+#endif /* _KEYS_TRUSTED_TYPE_H */
diff --git a/security/Kconfig b/security/Kconfig
index bd72ae6..415422e 100644
--- a/security/Kconfig
+++ b/security/Kconfig
@@ -21,6 +21,21 @@ config KEYS
 
  If you are unsure as to whether this is required, answer N.
 
+config TRUSTED_KEYS
+   tristate "TRUSTED KEYS"
+   depends on KEYS && TCG_TPM
+   select CRYPTO
+   select CRYPTO_HMAC
+   select CRYPTO_SHA1
+   help
+ This option provides support for creating, sealing, and unsealing
+ keys in the kernel. 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.
+
+ 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 74d5447..fcb1070 100644
--- a/security/keys/Makefile
+++ b/security/keys/Makefile
@@ -13,6 +13,7 @@ obj-y := \
request_key_auth.o \
user_defined.o
 
+obj-$(CONFIG_TRUSTED_KEYS) += trusted_defined.o
 obj-$(CONFIG_KEYS_COMPAT) += compat.o
 obj-$(CONFIG_PROC_FS) += proc.o
 obj-$(CONFIG_SYSCTL) += sysctl.o
diff --git a/security/keys/trusted_defined.c b/security/keys/trusted_defined.c
new file mode 100644
index 000..d45964d
--- /dev/null
+++ b/security/keys/trusted_defined.c
@@ -0,0 +1,1101 @@
+/*
+ * Copyright (C) 2010 IBM Corporation
+ *
+ * Author:
+ * David Safford 
+ *
+ * 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.
+ *
+ * Defines a new kernel key-type called 'trusted'.  Trusted keys are random
+ * number symmetric keys, generated and RSA-sealed by the TPM

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

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

Signed-off-by: David Safford 
Reviewd-by: Mimi Zohar 
Acked-by: Rajiv Andrade 
Acked-by: Serge E. Hallyn 
---
 drivers/char/tpm/tpm.c |   17 +
 include/linux/tpm.h|3 +++
 2 files changed, 20 insertions(+), 0 deletions(-)

diff --git a/drivers/char/tpm/tpm.c b/drivers/char/tpm/tpm.c
index 7c41335..5987d9c 100644
--- a/drivers/char/tpm/tpm.c
+++ b/drivers/char/tpm/tpm.c
@@ -780,6 +780,23 @@ 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, char *cmd, int buflen)
+{
+   struct tpm_chip *chip;
+   int rc;
+
+   chip = tpm_chip_find_get(chip_num);
+   if (chip == NULL)
+   return -ENODEV;
+
+   rc = transmit_cmd(chip, (struct tpm_cmd_t *)cmd, buflen,
+ "attempting tpm_cmd");
+
+   module_put(chip->dev->driver->owner);
+   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..a0ecaa9 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, char *cmd, int buflen);
 #else
 static inline int tpm_pcr_read(u32 chip_num, int pcr_idx, u8 *res_buf) {
return -ENODEV;
@@ -38,5 +39,7 @@ 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, char *cmd, int 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


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

2010-11-10 Thread Mimi Zohar
Defines 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:
- 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 
Signed-off-by: David Safford 
Reviewed-by: Roberto Sassu 
---
 include/keys/encrypted-type.h |   30 ++
 security/Kconfig  |   16 +
 security/keys/Makefile|1 +
 security/keys/encrypted_defined.c |  816 +
 security/keys/encrypted_defined.h |   52 +++
 5 files changed, 915 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..e2312e0
--- /dev/null
+++ b/include/keys/encrypted-type.h
@@ -0,0 +1,30 @@
+/* encrypted-type.h: encrypted-defined key type
+ *
+ * Copyright (C) 2010 IBM Corporation
+ * Author: Mimi Zohar 
+ *
+ * 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 
+#include 
+
+struct encrypted_key_payload {
+   struct rcu_head rcu;/* RCU destructor */
+   char *master_desc;  /* datablob: master key name */
+   char *datalen;  /* datablob: decrypted key length */
+   void *iv;   /* datablob: iv */
+   void *encrypted_data;   /* datablob: encrypted key */
+   unsigned short datablob_len;/* length of datablob */
+   unsigned short decrypted_datalen;   /* decrypted data length */
+   char 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 415422e..a031ebb 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..1d41228
--- /dev/null
+++ b/security/keys/encrypted_defined.c
@@ -0,0 +1,816 @@
+/*
+ * Copyright (C) 2010 IBM Corporation
+ *
+ * Author:
+ * Mimi Zohar 
+ *
+ * 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.
+ *
+ * File: encrypted_defined.c
+ *
+ * Defines a new kernel key-type called 'encrypted'. Encrypted keys
+ * are kernel generated random numbers, which are encrypted/decrypted
+ * using a 'master' key. The 'master' key can either be a trusted-key or
+ * user-key type. Encrypted keys are created/encrypted/decrypted in the
+ * kernel. Userspace ever only sees/st

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

2010-11-11 Thread Mimi Zohar
On Thu, 2010-11-11 at 19:48 +, David Howells wrote:
> Mimi Zohar  wrote:
> 
> > +void hex2bin(unsigned char *mem, char *buf, int count)
> 
> I think this needs a little adjustment.  I would recommend something like the
> following declaration:
> 
>   void hex2bin(u8 *buf, const char *data, size_t count)
> 
> since the output data is binary (so use u8*), you're only reading the source
> data (so should use a const pointer) and you don't want to see a negative
> count (so use size_t).

right, thanks.

> Also, I'd suggest calling the source arg 'data' and the output arg 'buf' or
> maybe src/dst.
> 
> David

Definitely better. (Remnant from kgdb_hex2mem() naming.)

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 2/4] key: add tpm_send command

2010-11-11 Thread Mimi Zohar
On Thu, 2010-11-11 at 19:48 +, David Howells wrote:
> Mimi Zohar  wrote:
> 
> > Reviewd-by: Mimi Zohar 
> 
> You've missed an 'e'.

thanks, will fix

> > +int tpm_send(u32 chip_num, char *cmd, int buflen)
> > +{
> > ...
> > +   rc = transmit_cmd(chip, (struct tpm_cmd_t *)cmd, buflen,
> > + "attempting tpm_cmd");
> 
> Make cmd 'void *' to obviate the cast.  Preferably it should be const too.

will do

> > +   module_put(chip->dev->driver->owner);
> 
> Where's the corresponding module_get()?  I suspect this should be wrapped to
> match tpm_chip_find_get().
> 
> David

The module_get() is in tpm_chip_find_get(), which is just a helper.
(It's used this way throughout tpm.c)

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-12 Thread Mimi Zohar
On Fri, 2010-11-12 at 19:45 +, David Howells wrote:
> Mimi Zohar  wrote:
> 
> > Defines a new kernel key-type called 'encrypted'. Encrypted keys are
> 
> Many of the comments I made against patch #3 also apply here.  Use 'Define'
> rather than 'Defines' here for example.

Was expecting your comments. Already started making the changes ...

> > index 000..e2312e0
> > --- /dev/null
> > +++ b/include/keys/encrypted-type.h
> > @@ -0,0 +1,30 @@
> > +/* encrypted-type.h: encrypted-defined key type
> 
> Don't include the names of files in the files.
> 
> > +struct encrypted_key_payload {
> > +   struct rcu_head rcu;/* RCU destructor */
> 
> That comment is not really needed.
> 
> > +   char *master_desc;  /* datablob: master key name */
> > +   char *datalen;  /* datablob: decrypted key length */
> > +   void *iv;   /* datablob: iv */
> > +   void *encrypted_data;   /* datablob: encrypted key */
> 
> But the variable name is 'encrypted_data'...
> 
> > +   unsigned short datablob_len;/* length of datablob */
> > +   unsigned short decrypted_datalen;   /* decrypted data length */
> > +   char decrypted_data[0]; /* decrypted data +  datablob + hmac */
> 
> If any of these are binary data rather than character data, I'd use u8 rather
> than char.
> 
> > --- /dev/null
> > +++ b/security/keys/encrypted_defined.c
> > @@ -0,0 +1,816 @@
> > +/*
> > + * Copyright (C) 2010 IBM Corporation
> > + *
> > + * Author:
> > + * Mimi Zohar 
> > + *
> > + * 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.
> > + *
> > + * File: encrypted_defined.c
> 
> Don't do that.
> 
> > + *
> > + * Defines a new kernel key-type called 'encrypted'. Encrypted keys
> > + * are kernel generated random numbers, which are encrypted/decrypted
> > + * using a 'master' key. The 'master' key can either be a trusted-key or
> > + * user-key type. Encrypted keys are created/encrypted/decrypted in the
> > + * kernel. Userspace ever only sees/stores encrypted blobs.
> > + *
> > + * keyctl add "encrypted" "name" "NEW master-key-name keylen" ring
> > + * keyctl add "encrypted" "name" "LOAD master-key-name keylen hex_blob" 
> > ring
> > + * keyctl update keyid "UPDATE master-key-name"
> 
> Merge with the documentation file in Documentation/ from patch 3 and stick a
> pointer to that file here.
> 
> > +static char hash_alg[] = "sha256";
> > +static char hmac_alg[] = "hmac(sha256)";
> 
> const.
> 
> > +static int hash_size = SHA256_DIGEST_SIZE;
> 
> ???  This is a numeric constant, but you're telling the compiler you want to
> store it in the .data section.  Is there a reason?
> 
> > +static char blkcipher_alg[] = "cbc(aes)";
> 
> const.
> 
> > +static int ivsize;
> > +static int blksize;
> > +static int MAX_DATA_SIZE = 4096;
> > +static int MIN_DATA_SIZE = 20;
> 
> Initialised numeric constants.
> 
> > +static int aes_get_sizes(int *ivsize, int *blksize)
> 
> It's only used in one place in the file, and it only sets global vars.  Why
> pass pointers to them?

agreed

> > +enum {
> > +   Opt_err = -1, Opt_new = 1, Opt_load,
> > +   Opt_update, Opt_NEW, Opt_LOAD, Opt_UPDATE
> > +};
> 
> Why skip 0?
> 
> > +static match_table_t key_tokens = {
> 
> const.
> 
> > +   {Opt_new, "new"},
> > +   {Opt_NEW, "NEW"},
> > +   {Opt_load, "load"},
> > +   {Opt_LOAD, "LOAD"},
> > +   {Opt_update, "update"},
> > +   {Opt_UPDATE, "UPDATE"},
> > +   {Opt_err, NULL}
> 
> Is case significant?  If not, you don't need duplicated constants.  Why do you
> care about the capitalisation here (and only in a restricted sense) when you
> didn't in the trusted keys patch?

No, was being consistent with trusted keys, and then uppercase was
removed there, but left here. Will remove.

> > +/* datablob_format - format as an ascii string, before copying to 
> > userspace */
> 
> I would split this over three lines.
> 
> > +static int datablob_format(char __user *buffer,
> > +  struct encrypted_key_payload *epayload,
> > +  int asciiblob_le

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

2010-11-13 Thread Mimi Zohar
On Fri, 2010-11-12 at 21:23 +, David Howells wrote:
> Mimi Zohar  wrote:
> 
> > > Why do you allow the master key to be supplied by a user-defined key 
> > > rather
> > > than requiring a trusted-key unconditionally?
> > 
> > This is for systems without a TPM. The logic needs to exist, whether it
> > is here or in EVM.  By doing it here, a user could provide a passphrase
> > in the initramfs, which is used to decrypt the encrypted key.
> 
> I thought that might be the case.  In which case, it might be better to allow
> someone to add a trusted key, supplying both encrypted and unencrypted
> versions of the data so that the TPM need not be consulted.  You might want to
> mark such a key so that it can be seen when it is dumped.

At least to me, the name 'trusted' implies some form of HW. 

> But if you're going to use a user-defined key, you really need to prefix the
> description with something suitable.
> 
> David

Agreed. So instead of: 
keyctl add encrypted name "new master-key-name keylen" ring

the description would be prefixed with the key type like:   
keyctl add encrypted name "new trusted|user master-key-name keylen" ring

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-15 Thread Mimi Zohar
On Mon, 2010-11-15 at 16:18 +, David Howells wrote:
> Mimi Zohar  wrote:

> > > But if you're going to use a user-defined key, you really need to prefix
> > > the description with something suitable.
> > 
> > Agreed. So instead of: 
> > keyctl add encrypted name "new master-key-name keylen" ring
> > 
> > the description would be prefixed with the key type like:   
> > keyctl add encrypted name "new trusted|user master-key-name keylen" ring
> 
> I don't think you understood what I meant.  If you look at the following
> function:

> +static struct key *request_master_key(struct encrypted_key_payload *epayload,
> + void **master_key,
> + unsigned int *master_keylen)
> +{
> + struct key *mkey;
> +
> + mkey = request_trusted_key(epayload->master_desc,
> +master_key, master_keylen);
> + if (IS_ERR(mkey)) {
> + mkey = request_user_key(epayload->master_desc,
> + master_key, master_keylen);
> + if (IS_ERR(mkey)) {
> + pr_info("encrypted_key: trusted/user key %s not found",
> + epayload->master_desc);
> + return mkey;
> + }
> + }
> + dump_master_key(*master_key, *master_keylen);
> + return mkey;
> +}
> 
> In the bit where you go for a user key (having failed to get a trusted key),
> you should prefix the description here (or in request_user_key()) with
> something like "trusted:".  Then you don't need to change the user interface.
> 
> David

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.

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-16 Thread Mimi Zohar
On Tue, 2010-11-16 at 17:50 +, David Howells wrote:
> Mimi Zohar  wrote:
> 
> > I actually like keyctl requiring 'trusted:' or 'user:'.  Forcing the
> > user to indicate which type of key they want, is actually good - no
> > misunderstandings.
> 
> You still need to prefix the description of a user-defined key so that you
> don't collide with other people who're also using user-defined keys for 
> random things.

ok

> > Another benefit, would be allowing 'keyctl update' to update the key
> > description, not the key type.
> 
> You mean you want to change the description on a key?
> 
> David

No, this just updates the name of the key used to encrypt/decrypt the
encrypted key. For example, the encrypted key evm-key is initially
encrypted/decrypted using 'kmk-trusted'.  After the update, it is
encrypted/decrypted with 'kmk'.  Both now are trusted keys.

$ keyctl show
Session Keyring
   -3 --alswrv500   500  keyring: _ses
117908125 --alswrv500-1   \_ keyring: _uid.500
501967942 --alswrv500   500   \_ trusted: kmk-trusted
317523177 --alswrv500   500   \_ encrypted: evm-key
666437381 --alswrv500   500   \_ trusted: kmk
$ keyctl print 317523177
trusted:kmk-trusted 32 ca0ebb83594f14781460 ...

$ keyctl update 317523177 "update trusted:kmk"
$ keyctl print 317523177
trusted:kmk 32 ca0ebb83594f1478146 

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-16 Thread Mimi Zohar
On Tue, 2010-11-16 at 17:50 +, David Howells wrote:
> Mimi Zohar  wrote:
> 
> > I actually like keyctl requiring 'trusted:' or 'user:'.  Forcing the
> > user to indicate which type of key they want, is actually good - no
> > misunderstandings.
> 
> You still need to prefix the description of a user-defined key so that you
> don't collide with other people who're also using user-defined keys for 
> random things.

Although I previously agreed to this change, I'm really not convinced it
is necessary.  encrypted keys don't create new trusted or user keys,
they only use existing keys to encrypt/decrypt encrypted
keys(instantiate,read).  Key names, user or otherwise, should be left up
to the person creating them.

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.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-

[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 
Acked-by: Serge E. Hallyn 
---
 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


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

2010-11-18 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 
Signed-off-by: David Safford 
---
 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.4 4/5] keys: add new trusted key-type

2010-11-18 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:
- 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 
Signed-off-by: Mimi Zohar 
---
 Documentation/keys-trusted-encrypted.txt |   68 ++
 include/keys/trusted-type.h  |   31 +
 security/Kconfig |   15 +
 security/keys/Makefile   |1 +
 security/keys/trusted_defined.c  | 1136 ++
 security/keys/trusted_defined.h  |  147 
 6 files changed, 1398 insertions(+), 0 deletions(-)
 create mode 100644 Documentation/keys-trusted-encrypted.txt
 create mode 100644 include/keys/trusted-type.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..6e6db62
--- /dev/null
+++ b/Documentation/keys-trusted-encrypted.txt
@@ -0,0 +1,68 @@
+   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)
+   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.

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

2010-11-18 Thread Mimi Zohar
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:
- 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 
Signed-off-by: David Safford 
Reviewed-by: Roberto Sassu 
---
 include/keys/encrypted-type.h |   29 ++
 security/Kconfig  |   16 +
 security/keys/Makefile|1 +
 security/keys/encrypted_defined.c |  876 +
 security/keys/encrypted_defined.h |   56 +++
 5 files changed, 978 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 
+ *
+ * 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 
+#include 
+
+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..f2105a7
--- /dev/null
+++ b/security/keys/encrypted_defined.c
@@ -0,0 +1,876 @@
+/*
+ * Copyright (C) 2010 IBM Corporation
+ *
+ * Author:
+ * Mimi Zohar 
+ *
+ * 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.
+ *
+ * See Documentation/

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

2010-11-18 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 
Signed-off-by: Mimi Zohar 
---
 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..b737cf3 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, int 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..a25ab8f 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, int 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, int 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.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  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


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  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  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


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


  1   2   >