diff options
author | Miloslav Trmač <mitr@redhat.com> | 2010-08-27 07:46:15 +0200 |
---|---|---|
committer | Miloslav Trmač <mitr@redhat.com> | 2010-08-27 07:46:15 +0200 |
commit | 9f0a6ce7f41043dad38b272cd6ad165f98827b8b (patch) | |
tree | 909f5dcc886a1ad32ab0a00bc0455c566e1037c2 | |
parent | c07dc584248074d16c371d2a478bc23520bef69f (diff) | |
parent | 1f30d575e5b413e522d6b3e95d3e348df9e9c69e (diff) | |
download | kernel-crypto-9f0a6ce7f41043dad38b272cd6ad165f98827b8b.tar.gz kernel-crypto-9f0a6ce7f41043dad38b272cd6ad165f98827b8b.tar.xz kernel-crypto-9f0a6ce7f41043dad38b272cd6ad165f98827b8b.zip |
Merge remote branch 'origin/newapi'
Conflicts:
examples/ncr.c
examples/pk.c
ncr-key-wrap.c
ncr-key.c
ncr.h
-rw-r--r-- | crypto.4 | 4 | ||||
-rw-r--r-- | examples/ncr.c | 14 | ||||
-rw-r--r-- | examples/pk.c | 20 | ||||
-rw-r--r-- | ncr-key-wrap.c | 201 | ||||
-rw-r--r-- | ncr-key.c | 5 | ||||
-rw-r--r-- | ncr-sessions.c | 4 | ||||
-rw-r--r-- | ncr.h | 7 |
7 files changed, 194 insertions, 61 deletions
@@ -431,14 +431,10 @@ members. The following input attributes are recognized: .RS -.IP \fBNCR_ATTR_ALGORITHM\fP -Mandatory. .IP \fBNCR_ATTR_IV\fP Optional, an empty IV is used if not present. .IP \fBNCR_ATTR_KEY_FLAGS\fP Optional, flags are unchanged if not present. -.IP \fBNCR_ATTR_KEY_TYPE\fP -Mandatory. .IP \fBNCR_ATTR_WRAPPING_ALGORITHM\fP Mandatory. .RE diff --git a/examples/ncr.c b/examples/ncr.c index 203951646fa..9691fea5dc1 100644 --- a/examples/ncr.c +++ b/examples/ncr.c @@ -375,10 +375,6 @@ test_ncr_wrap_key(int cfd) struct ncr_key_unwrap f; struct nlattr wrap_algo_head ALIGN_NL; char wrap_algo[sizeof(NCR_WALG_AES_RFC3394)] ALIGN_NL; - struct nlattr algo_head ALIGN_NL; - char algo[sizeof(ALG_AES_CBC)] ALIGN_NL; - struct nlattr type_head ALIGN_NL; - uint32_t type ALIGN_NL; struct nlattr flags_head ALIGN_NL; uint32_t flags ALIGN_NL; } kunwrap; @@ -417,7 +413,7 @@ test_ncr_wrap_key(int cfd) strcpy(kimport.algo, ALG_AES_CBC); kimport.flags_head.nla_len = NLA_HDRLEN + sizeof(kimport.flags); kimport.flags_head.nla_type = NCR_ATTR_KEY_FLAGS; - kimport.flags = NCR_KEY_FLAG_EXPORTABLE|NCR_KEY_FLAG_WRAPPING; + kimport.flags = NCR_KEY_FLAG_EXPORTABLE|NCR_KEY_FLAG_WRAPPING|NCR_KEY_FLAG_UNWRAPPING; ret = ioctl(cfd, NCRIO_KEY_IMPORT, &kimport); if (geteuid() == 0 && ret) { @@ -518,12 +514,6 @@ test_ncr_wrap_key(int cfd) kunwrap.wrap_algo_head.nla_len = NLA_HDRLEN + sizeof(kunwrap.wrap_algo); kunwrap.wrap_algo_head.nla_type = NCR_ATTR_WRAPPING_ALGORITHM; strcpy(kunwrap.wrap_algo, NCR_WALG_AES_RFC3394); - kunwrap.algo_head.nla_len = NLA_HDRLEN + sizeof(kunwrap.algo); - kunwrap.algo_head.nla_type = NCR_ATTR_ALGORITHM; - strcpy(kunwrap.algo, ALG_AES_CBC); - kunwrap.type_head.nla_len = NLA_HDRLEN + sizeof(kunwrap.type); - kunwrap.type_head.nla_type = NCR_ATTR_KEY_TYPE; - kunwrap.type = NCR_KEY_TYPE_SECRET; kunwrap.flags_head.nla_len = NLA_HDRLEN + sizeof(kunwrap.flags); kunwrap.flags_head.nla_type = NCR_ATTR_KEY_FLAGS; kunwrap.flags = NCR_KEY_FLAG_EXPORTABLE|NCR_KEY_FLAG_WRAPPABLE; @@ -629,7 +619,7 @@ test_ncr_wrap_key2(int cfd) strcpy(kimport.algo, ALG_AES_CBC); kimport.flags_head.nla_len = NLA_HDRLEN + sizeof(kimport.flags); kimport.flags_head.nla_type = NCR_ATTR_KEY_FLAGS; - kimport.flags = NCR_KEY_FLAG_EXPORTABLE|NCR_KEY_FLAG_WRAPPING; + kimport.flags = NCR_KEY_FLAG_EXPORTABLE|NCR_KEY_FLAG_WRAPPING|NCR_KEY_FLAG_UNWRAPPING; if (ioctl(cfd, NCRIO_KEY_IMPORT, &kimport)) { fprintf(stderr, "Error: %s:%d\n", __func__, __LINE__); diff --git a/examples/pk.c b/examples/pk.c index 6acbadf12b0..81c5b49263d 100644 --- a/examples/pk.c +++ b/examples/pk.c @@ -624,10 +624,8 @@ test_ncr_wrap_key3(int cfd) struct ncr_key_unwrap f; struct nlattr wrap_algo_head ALIGN_NL; char wrap_algo[sizeof(NCR_WALG_AES_RFC5649)] ALIGN_NL; - struct nlattr algo_head ALIGN_NL; - char algo[sizeof(ALG_RSA)] ALIGN_NL; - struct nlattr type_head ALIGN_NL; - uint32_t type ALIGN_NL; + struct nlattr flags_head ALIGN_NL; + uint32_t flags ALIGN_NL; } kunwrap; struct __attribute__((packed)) { struct ncr_key_generate_pair f; @@ -694,7 +692,7 @@ test_ncr_wrap_key3(int cfd) strcpy(kimport.algo, ALG_AES_CBC); kimport.flags_head.nla_len = NLA_HDRLEN + sizeof(kimport.flags); kimport.flags_head.nla_type = NCR_ATTR_KEY_FLAGS; - kimport.flags = NCR_KEY_FLAG_EXPORTABLE|NCR_KEY_FLAG_WRAPPING; + kimport.flags = NCR_KEY_FLAG_EXPORTABLE|NCR_KEY_FLAG_WRAPPING|NCR_KEY_FLAG_UNWRAPPING; if (ioctl(cfd, NCRIO_KEY_IMPORT, &kimport)) { fprintf(stderr, "Error: %s:%d\n", __func__, __LINE__); @@ -782,14 +780,10 @@ test_ncr_wrap_key3(int cfd) kunwrap.wrap_algo_head.nla_type = NCR_ATTR_WRAPPING_ALGORITHM; strcpy(kunwrap.wrap_algo, NCR_WALG_AES_RFC5649); - kunwrap.algo_head.nla_len - = NLA_HDRLEN + sizeof(kunwrap.algo); - kunwrap.algo_head.nla_type = NCR_ATTR_ALGORITHM; - strcpy(kunwrap.algo, ALG_RSA); - kunwrap.type_head.nla_len - = NLA_HDRLEN + sizeof(kunwrap.type); - kunwrap.type_head.nla_type = NCR_ATTR_KEY_TYPE; - kunwrap.type = NCR_KEY_TYPE_PRIVATE; + kunwrap.flags_head.nla_len + = NLA_HDRLEN + sizeof(kunwrap.flags); + kunwrap.flags_head.nla_type = NCR_ATTR_KEY_FLAGS; + kunwrap.flags = 0; ret = ioctl(cfd, NCRIO_KEY_UNWRAP, &kunwrap); if (ret) { diff --git a/ncr-key-wrap.c b/ncr-key-wrap.c index 25bd9e10686..7ea70cfc847 100644 --- a/ncr-key-wrap.c +++ b/ncr-key-wrap.c @@ -34,6 +34,8 @@ #include "ncr-int.h" #include "cryptodev_int.h" +#define KEY_WRAP_VERSION 0 + typedef uint8_t val64_t[8]; static const val64_t initA = "\xA6\xA6\xA6\xA6\xA6\xA6\xA6\xA6"; @@ -264,7 +266,7 @@ static int wrap_aes_rfc5649(struct key_item_st* tobewrapped, struct key_item_st void* output, size_t* output_size, const void* iv, size_t iv_size) { int ret; -uint8_t* sdata; +uint8_t* sdata = NULL; size_t sdata_size = 0; ret = key_to_packed_data(&sdata, &sdata_size, tobewrapped); @@ -329,7 +331,7 @@ fail: /* Wraps using the RFC3394 way. */ -static int wrap_aes(struct key_item_st* tobewrapped, struct key_item_st *kek, +static int wrap_aes_rfc3394(struct key_item_st* tobewrapped, struct key_item_st *kek, void* output, size_t *output_size, const void* iv, size_t iv_size) { size_t key_size, n; @@ -594,7 +596,8 @@ int ret; goto fail; } if (nla_strcmp(nla, NCR_WALG_AES_RFC3394) == 0) - ret = wrap_aes(wkey, key, data, &data_size, iv, iv_size); + ret = wrap_aes_rfc3394(wkey, key, data, &data_size, iv, + iv_size); else if (nla_strcmp(nla, NCR_WALG_AES_RFC5649) == 0) ret = wrap_aes_rfc5649(wkey, key, data, &data_size, iv, iv_size); @@ -649,7 +652,7 @@ int ret; goto fail; } - if (!(key->flags & NCR_KEY_FLAG_WRAPPING)) { + if (!(key->flags & NCR_KEY_FLAG_UNWRAPPING)) { err(); ret = -EPERM; goto fail; @@ -823,11 +826,27 @@ fail: return ret; } +#define DER_KEY_MAX_SIZE (KEY_DATA_MAX_SIZE+16) + +/* Packed data are DER encoded: + * PackedData ::= SEQUENCE { + * version INTEGER { v1(0) } + * type INTEGER { secret_key(0), rsa_privkey(1), rsa_pubkey(2), dsa_privkey(3), dsa_pubkey(4), + * dh_privkey(5), dh_pubkey(6) }, + * data OCTET STRING + * } + * + * This allows distinguishing types of wrapped keys. + */ static int key_to_packed_data( uint8_t** sdata, size_t * sdata_size, const struct key_item_st *key) { - uint8_t * pkey; - uint32_t usize; - int ret; + uint8_t * pkey = NULL; + uint8_t * derkey = NULL; + uint32_t pkey_size; + int ret, err; + unsigned long version = KEY_WRAP_VERSION; + unsigned long type; + unsigned long derlen; *sdata_size = KEY_DATA_MAX_SIZE; pkey = kmalloc(*sdata_size, GFP_KERNEL); @@ -836,55 +855,180 @@ static int key_to_packed_data( uint8_t** sdata, size_t * sdata_size, const struc return -ENOMEM; } + derlen = DER_KEY_MAX_SIZE; + derkey = kmalloc(derlen, GFP_KERNEL); + if (derkey == NULL) { + err(); + goto fail; + } + if (key->type == NCR_KEY_TYPE_SECRET) { memcpy(pkey, key->key.secret.data, key->key.secret.size); - *sdata_size = key->key.secret.size; + pkey_size = key->key.secret.size; + + type = 0; } else if (key->type == NCR_KEY_TYPE_PRIVATE || key->type == NCR_KEY_TYPE_PUBLIC) { - usize = *sdata_size; - ret = ncr_pk_pack( key, pkey, &usize); + pkey_size = *sdata_size; + ret = ncr_pk_pack( key, pkey, &pkey_size); if (ret < 0) { err(); goto fail; } - *sdata_size = usize; + + switch (key->algorithm->algo) { + case NCR_ALG_RSA: + if (key->type == NCR_KEY_TYPE_PUBLIC) + type = 2; + else type = 1; + break; + case NCR_ALG_DSA: + if (key->type == NCR_KEY_TYPE_PUBLIC) + type = 4; + else type = 3; + break; + case NCR_ALG_DH: + if (key->type == NCR_KEY_TYPE_PUBLIC) + type = 6; + else type = 5; + break; + default: + /* unsupported yet */ + ret = -EINVAL; + err(); + goto fail; + } + } else { err(); ret = -EINVAL; goto fail; } - *sdata = (void*)pkey; + err = der_encode_sequence_multi(derkey, &derlen, + LTC_ASN1_SHORT_INTEGER, 1UL, &version, + LTC_ASN1_SHORT_INTEGER, 1UL, &type, + LTC_ASN1_OCTET_STRING, (unsigned long)pkey_size, pkey, + LTC_ASN1_EOL, 0UL, NULL); + + kfree(pkey); + + if (err != CRYPT_OK) { + err(); + ret = _ncr_tomerr(err); + goto fail; + } + + *sdata = (void*)derkey; + *sdata_size = derlen; return 0; fail: kfree(pkey); + kfree(derkey); return ret; } +inline static int packed_type_to_key_type(unsigned long type, struct key_item_st* key) +{ + switch(type) { + case 0: + key->type = NCR_KEY_TYPE_SECRET; + key->algorithm = _ncr_algo_to_properties("cbc(aes)"); + break; + case 1: + key->type = NCR_KEY_TYPE_PRIVATE; + key->algorithm = _ncr_algo_to_properties("rsa"); + break; + case 2: + key->type = NCR_KEY_TYPE_PUBLIC; + key->algorithm = _ncr_algo_to_properties("rsa"); + break; + case 3: + key->type = NCR_KEY_TYPE_PRIVATE; + key->algorithm = _ncr_algo_to_properties("dsa"); + break; + case 4: + key->type = NCR_KEY_TYPE_PUBLIC; + key->algorithm = _ncr_algo_to_properties("dsa"); + break; + case 5: + key->type = NCR_KEY_TYPE_PRIVATE; + key->algorithm = _ncr_algo_to_properties("dh"); + break; + case 6: + key->type = NCR_KEY_TYPE_PUBLIC; + key->algorithm = _ncr_algo_to_properties("dh"); + break; + default: + err(); + return -EINVAL; + } + + if (key->algorithm == NULL) { + err(); + return -EINVAL; + } + + return 0; +} + + + +/* Unpack, or better decode the DER data + */ static int key_from_packed_data(struct nlattr *tb[], struct key_item_st *key, const void *data, size_t data_size) { - const struct nlattr *nla; - int ret; + ltc_asn1_list list[6]; + int ret, i = 0, pkey_size, err; + unsigned long version, type; + uint8_t * pkey = NULL; - if (data_size > KEY_DATA_MAX_SIZE) { + if (data_size > DER_KEY_MAX_SIZE) { err(); return -EINVAL; } - key->algorithm = _ncr_nla_to_properties(tb[NCR_ATTR_ALGORITHM]); - if (key->algorithm == NULL) { + pkey_size = KEY_DATA_MAX_SIZE; + pkey = kmalloc(pkey_size, GFP_KERNEL); + if (pkey == NULL) { err(); - return -EINVAL; + return -ENOMEM; } - nla = tb[NCR_ATTR_KEY_TYPE]; - if (tb == NULL) { + list[i].type = LTC_ASN1_SHORT_INTEGER; + list[i].size = 1; + list[i++].data = &version; + + list[i].type = LTC_ASN1_SHORT_INTEGER; + list[i].size = 1; + list[i++].data = &type; + + list[i].type = LTC_ASN1_OCTET_STRING; + list[i].size = pkey_size; + list[i++].data = pkey; + + err = der_decode_sequence(data, data_size, list, i); + if (err != CRYPT_OK) { err(); - return -EINVAL; + ret = _ncr_tomerr(err); + goto fail; + } + + if (version != KEY_WRAP_VERSION) { + err(); + ret = -EINVAL; + goto fail; + } + + pkey_size = list[2].size; + + ret = packed_type_to_key_type(type, key); + if (ret < 0) { + err(); + goto fail; } - key->type = nla_get_u32(nla); ret = ncr_key_update_flags(key, tb[NCR_ATTR_KEY_FLAGS]); if (ret != 0) { @@ -897,12 +1041,12 @@ static int key_from_packed_data(struct nlattr *tb[], struct key_item_st *key, err(); return -EINVAL; } - key->key.secret.size = data_size; - memcpy(key->key.secret.data, data, data_size); + key->key.secret.size = pkey_size; + memcpy(key->key.secret.data, pkey, pkey_size); } else if (key->type == NCR_KEY_TYPE_PUBLIC || key->type == NCR_KEY_TYPE_PRIVATE) { - ret = ncr_pk_unpack( key, data, data_size); + ret = ncr_pk_unpack( key, pkey, pkey_size); if (ret < 0) { err(); return ret; @@ -912,5 +1056,10 @@ static int key_from_packed_data(struct nlattr *tb[], struct key_item_st *key, return -EINVAL; } - return 0; + ret = 0; + +fail: + kfree(pkey); + + return ret; } diff --git a/ncr-key.c b/ncr-key.c index ca8ab5f80de..406e03299c3 100644 --- a/ncr-key.c +++ b/ncr-key.c @@ -294,7 +294,8 @@ int ncr_key_update_flags(struct key_item_st* item, const struct nlattr *nla) if (nla == NULL) return 0; flags = nla_get_u32(nla); - if (!capable(CAP_SYS_ADMIN) && (flags & NCR_KEY_FLAG_WRAPPING) != 0) + if (!capable(CAP_SYS_ADMIN) + && (flags & (NCR_KEY_FLAG_WRAPPING | NCR_KEY_FLAG_UNWRAPPING)) != 0) return -EPERM; item->flags = flags; return 0; @@ -743,7 +744,7 @@ struct key_item_st* newkey = NULL; /* wrapping keys cannot be used for anything except wrapping. */ - if (key->flags & NCR_KEY_FLAG_WRAPPING) { + if (key->flags & NCR_KEY_FLAG_WRAPPING || key->flags & NCR_KEY_FLAG_UNWRAPPING) { err(); ret = -EINVAL; goto fail; diff --git a/ncr-sessions.c b/ncr-sessions.c index aa9026d32e9..0e48865c599 100644 --- a/ncr-sessions.c +++ b/ncr-sessions.c @@ -429,7 +429,7 @@ static struct session_item_st *_ncr_session_init(struct ncr_lists *lists, /* wrapping keys cannot be used for encryption or decryption */ - if (ns->key->flags & NCR_KEY_FLAG_WRAPPING) { + if (ns->key->flags & NCR_KEY_FLAG_WRAPPING || ns->key->flags & NCR_KEY_FLAG_UNWRAPPING) { err(); ret = -EINVAL; goto fail; @@ -519,7 +519,7 @@ static struct session_item_st *_ncr_session_init(struct ncr_lists *lists, /* wrapping keys cannot be used for anything except wrapping. */ - if (ns->key->flags & NCR_KEY_FLAG_WRAPPING) { + if (ns->key->flags & NCR_KEY_FLAG_WRAPPING || ns->key->flags & NCR_KEY_FLAG_UNWRAPPING) { err(); ret = -EINVAL; goto fail; @@ -95,10 +95,13 @@ typedef __s32 ncr_key_t; */ #define NCR_KEY_FLAG_DECRYPT (1<<2) #define NCR_KEY_FLAG_SIGN (1<<3) -/* This flag can only be set by administrator, to prevent +#define NCR_KEY_FLAG_ENCRYPT (1<<4) +#define NCR_KEY_FLAG_VERIFY (1<<5) +/* These flags can only be set by administrator, to prevent * adversaries exporting wrappable keys with random ones. */ -#define NCR_KEY_FLAG_WRAPPING (1<<4) +#define NCR_KEY_FLAG_WRAPPING (1<<6) +#define NCR_KEY_FLAG_UNWRAPPING (1<<7) struct ncr_key_generate { __u32 input_size, output_size; |