Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 352878
b: refs/heads/master
c: e075125
h: refs/heads/master
v: v3
  • Loading branch information
Dmitry Kasatkin authored and Mimi Zohar committed Feb 7, 2013
1 parent fcaab69 commit 0dbb702
Show file tree
Hide file tree
Showing 6 changed files with 151 additions and 2 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 50af554466804bf51a52fa3d1d0a76f96bd33929
refs/heads/master: e0751257a64ea10cca96ccb06522bfb10e36cb5b
12 changes: 12 additions & 0 deletions trunk/security/integrity/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -17,5 +17,17 @@ config INTEGRITY_SIGNATURE
This is useful for evm and module keyrings, when keys are
usually only added from initramfs.

config INTEGRITY_ASYMMETRIC_KEYS
boolean "Enable asymmetric keys support"
depends on INTEGRITY_SIGNATURE
default n
select ASYMMETRIC_KEY_TYPE
select ASYMMETRIC_PUBLIC_KEY_SUBTYPE
select PUBLIC_KEY_ALGO_RSA
select X509_CERTIFICATE_PARSER
help
This option enables digital signature verification using
asymmetric keys.

source security/integrity/ima/Kconfig
source security/integrity/evm/Kconfig
1 change: 1 addition & 0 deletions trunk/security/integrity/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

obj-$(CONFIG_INTEGRITY) += integrity.o
obj-$(CONFIG_INTEGRITY_SIGNATURE) += digsig.o
obj-$(CONFIG_INTEGRITY_ASYMMETRIC_KEYS) += digsig_asymmetric.o

integrity-y := iint.o

Expand Down
11 changes: 10 additions & 1 deletion trunk/security/integrity/digsig.c
Original file line number Diff line number Diff line change
Expand Up @@ -44,5 +44,14 @@ int integrity_digsig_verify(const unsigned int id, const char *sig, int siglen,
}
}

return digsig_verify(keyring[id], sig, siglen, digest, digestlen);
switch (sig[0]) {
case 1:
return digsig_verify(keyring[id], sig, siglen,
digest, digestlen);
case 2:
return asymmetric_verify(keyring[id], sig, siglen,
digest, digestlen);
}

return -EOPNOTSUPP;
}
115 changes: 115 additions & 0 deletions trunk/security/integrity/digsig_asymmetric.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
/*
* Copyright (C) 2013 Intel Corporation
*
* Author:
* Dmitry Kasatkin <dmitry.kasatkin@intel.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, version 2 of the License.
*
*/

#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt

#include <linux/err.h>
#include <linux/key-type.h>
#include <crypto/public_key.h>
#include <keys/asymmetric-type.h>

#include "integrity.h"

/*
* signature format v2 - for using with asymmetric keys
*/
struct signature_v2_hdr {
uint8_t version; /* signature format version */
uint8_t hash_algo; /* Digest algorithm [enum pkey_hash_algo] */
uint32_t keyid; /* IMA key identifier - not X509/PGP specific*/
uint16_t sig_size; /* signature size */
uint8_t sig[0]; /* signature payload */
} __packed;

/*
* Request an asymmetric key.
*/
static struct key *request_asymmetric_key(struct key *keyring, uint32_t keyid)
{
struct key *key;
char name[12];

sprintf(name, "id:%x", keyid);

pr_debug("key search: \"%s\"\n", name);

if (keyring) {
/* search in specific keyring */
key_ref_t kref;
kref = keyring_search(make_key_ref(keyring, 1),
&key_type_asymmetric, name);
if (IS_ERR(kref))
key = ERR_CAST(kref);
else
key = key_ref_to_ptr(kref);
} else {
key = request_key(&key_type_asymmetric, name, NULL);
}

if (IS_ERR(key)) {
pr_warn("Request for unknown key '%s' err %ld\n",
name, PTR_ERR(key));
switch (PTR_ERR(key)) {
/* Hide some search errors */
case -EACCES:
case -ENOTDIR:
case -EAGAIN:
return ERR_PTR(-ENOKEY);
default:
return key;
}
}

pr_debug("%s() = 0 [%x]\n", __func__, key_serial(key));

return key;
}

int asymmetric_verify(struct key *keyring, const char *sig,
int siglen, const char *data, int datalen)
{
struct public_key_signature pks;
struct signature_v2_hdr *hdr = (struct signature_v2_hdr *)sig;
struct key *key;
int ret = -ENOMEM;

if (siglen <= sizeof(*hdr))
return -EBADMSG;

siglen -= sizeof(*hdr);

if (siglen != __be16_to_cpu(hdr->sig_size))
return -EBADMSG;

if (hdr->hash_algo >= PKEY_HASH__LAST)
return -ENOPKG;

key = request_asymmetric_key(keyring, __be32_to_cpu(hdr->keyid));
if (IS_ERR(key))
return PTR_ERR(key);

memset(&pks, 0, sizeof(pks));

pks.pkey_hash_algo = hdr->hash_algo;
pks.digest = (u8 *)data;
pks.digest_size = datalen;
pks.nr_mpi = 1;
pks.rsa.s = mpi_read_raw_data(hdr->sig, siglen);

if (pks.rsa.s)
ret = verify_signature(key, &pks);

mpi_free(pks.rsa.s);
key_put(key);
pr_debug("%s() = %d\n", __func__, ret);
return ret;
}
12 changes: 12 additions & 0 deletions trunk/security/integrity/integrity.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
#include <linux/types.h>
#include <linux/integrity.h>
#include <crypto/sha.h>
#include <linux/key.h>

/* iint action cache flags */
#define IMA_MEASURE 0x00000001
Expand Down Expand Up @@ -101,5 +102,16 @@ static inline int integrity_digsig_verify(const unsigned int id,

#endif /* CONFIG_INTEGRITY_SIGNATURE */

#ifdef CONFIG_INTEGRITY_ASYMMETRIC_KEYS
int asymmetric_verify(struct key *keyring, const char *sig,
int siglen, const char *data, int datalen);
#else
static inline int asymmetric_verify(struct key *keyring, const char *sig,
int siglen, const char *data, int datalen)
{
return -EOPNOTSUPP;
}
#endif

/* set during initialization */
extern int iint_initialized;

0 comments on commit 0dbb702

Please sign in to comment.