From 61950862971ef6630930e9889921959405f3f76e Mon Sep 17 00:00:00 2001 From: Nikos Mavrogiannopoulos Date: Wed, 25 Aug 2010 16:20:32 +0200 Subject: use the rfc3394 suffix. --- ncr-key-wrap.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ncr-key-wrap.c b/ncr-key-wrap.c index 93103b5a9a5..7acb5731d02 100644 --- a/ncr-key-wrap.c +++ b/ncr-key-wrap.c @@ -321,7 +321,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; @@ -557,7 +557,7 @@ int ret; switch(wrap.algorithm) { case NCR_WALG_AES_RFC3394: - ret = wrap_aes(wkey, key, data, &data_size, + ret = wrap_aes_rfc3394(wkey, key, data, &data_size, wrap.params.params.cipher.iv, wrap.params.params.cipher.iv_size); break; case NCR_WALG_AES_RFC5649: -- cgit From 68c4e5ec42e1151591aee19ba36a4dbe22715a91 Mon Sep 17 00:00:00 2001 From: Nikos Mavrogiannopoulos Date: Wed, 25 Aug 2010 17:45:44 +0200 Subject: The RFC5649 wrapping algorithm now includes a DER encoding of the data to distinguish between keys of different types. This prevents keys being unwrapped in a wrong type. --- examples/pk.c | 2 +- ncr-key-wrap.c | 191 ++++++++++++++++++++++++++++++++++++++++++++++++++------- ncr.h | 4 -- 3 files changed, 170 insertions(+), 27 deletions(-) diff --git a/examples/pk.c b/examples/pk.c index 032ae9864d9..ea5720c59ee 100644 --- a/examples/pk.c +++ b/examples/pk.c @@ -646,7 +646,7 @@ test_ncr_wrap_key3(int cfd) /* try unwrapping */ memset(&kwrap, 0, sizeof(kwrap)); kwrap.algorithm = NCR_WALG_AES_RFC5649; - kwrap.wrapped_key_algorithm = NCR_ALG_RSA; + kwrap.wrapped_key_flags = 0; kwrap.keytowrap = privkey; kwrap.key = key; kwrap.io = data; diff --git a/ncr-key-wrap.c b/ncr-key-wrap.c index 7acb5731d02..1107083eefc 100644 --- a/ncr-key-wrap.c +++ b/ncr-key-wrap.c @@ -39,7 +39,7 @@ typedef uint8_t val64_t[8]; static const val64_t initA = "\xA6\xA6\xA6\xA6\xA6\xA6\xA6\xA6"; static int key_to_packed_data( uint8_t** sdata, size_t * sdata_size, const struct key_item_st *key); -static int key_from_packed_data(ncr_algorithm_t algorithm, unsigned int flags, +static int key_from_packed_data(unsigned int flags, struct key_item_st* key, const void* data, size_t data_size); @@ -264,7 +264,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); @@ -303,7 +303,7 @@ size_t sdata_size = KEY_DATA_MAX_SIZE; goto fail; } - ret = key_from_packed_data(wrap_st->wrapped_key_algorithm, wrap_st->wrapped_key_flags, + ret = key_from_packed_data(wrap_st->wrapped_key_flags, output, sdata, sdata_size); if (ret < 0) { err(); @@ -808,11 +808,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 zero = 0; + unsigned long type; + unsigned long derlen; *sdata_size = KEY_DATA_MAX_SIZE; pkey = kmalloc(*sdata_size, GFP_KERNEL); @@ -821,49 +837,175 @@ 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, &zero, + 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; } -static int key_from_packed_data(ncr_algorithm_t algorithm, unsigned int flags, +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(NCR_ALG_AES_CBC); + break; + case 1: + key->type = NCR_KEY_TYPE_PRIVATE; + key->algorithm = _ncr_algo_to_properties(NCR_ALG_RSA); + break; + case 2: + key->type = NCR_KEY_TYPE_PUBLIC; + key->algorithm = _ncr_algo_to_properties(NCR_ALG_RSA); + break; + case 3: + key->type = NCR_KEY_TYPE_PRIVATE; + key->algorithm = _ncr_algo_to_properties(NCR_ALG_DSA); + break; + case 4: + key->type = NCR_KEY_TYPE_PUBLIC; + key->algorithm = _ncr_algo_to_properties(NCR_ALG_DSA); + break; + case 5: + key->type = NCR_KEY_TYPE_PRIVATE; + key->algorithm = _ncr_algo_to_properties(NCR_ALG_DH); + break; + case 6: + key->type = NCR_KEY_TYPE_PUBLIC; + key->algorithm = _ncr_algo_to_properties(NCR_ALG_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(unsigned int flags, struct key_item_st* key, const void* data, size_t data_size) { - 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_algo_to_properties(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; + } + + 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(); + ret = _ncr_tomerr(err); + goto fail; + } + + pkey_size = list[2].size; + + ret = packed_type_to_key_type(type, key); + if (ret < 0) { + err(); + goto fail; } - key->type = key->algorithm->key_type; ncr_key_assign_flags(key, flags); if (key->type == NCR_KEY_TYPE_SECRET) { @@ -871,12 +1013,12 @@ static int key_from_packed_data(ncr_algorithm_t algorithm, unsigned int flags, 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; @@ -886,5 +1028,10 @@ static int key_from_packed_data(ncr_algorithm_t algorithm, unsigned int flags, return -EINVAL; } - return 0; + ret = 0; + +fail: + kfree(pkey); + + return ret; } diff --git a/ncr.h b/ncr.h index af4c279b630..c3850e4e355 100644 --- a/ncr.h +++ b/ncr.h @@ -212,10 +212,6 @@ struct ncr_key_data_st { struct ncr_key_wrap_st { ncr_wrap_algorithm_t algorithm; - /* when unwrapping the algorithm of the wrapped key. - * For symmetric ciphers AES would do. - */ - ncr_algorithm_t wrapped_key_algorithm; unsigned int wrapped_key_flags; /* flags for the newly unwrapped key */ ncr_key_t keytowrap; -- cgit From e8372045818cb278ad2fe05ab64d3a76990cd1ed Mon Sep 17 00:00:00 2001 From: Nikos Mavrogiannopoulos Date: Wed, 25 Aug 2010 17:47:55 +0200 Subject: Added ENCRYPT, UNWRAPPING and VERIFY key flags --- examples/ncr.c | 4 ++-- examples/pk.c | 2 +- ncr-key-wrap.c | 2 +- ncr-key.c | 1 + ncr.h | 7 +++++-- 5 files changed, 10 insertions(+), 6 deletions(-) diff --git a/examples/ncr.c b/examples/ncr.c index 5169a149e31..3a665392c53 100644 --- a/examples/ncr.c +++ b/examples/ncr.c @@ -234,7 +234,7 @@ test_ncr_wrap_key(int cfd) keydata.key_id_size = 2; keydata.type = NCR_KEY_TYPE_SECRET; keydata.algorithm = NCR_ALG_AES_CBC; - keydata.flags = NCR_KEY_FLAG_EXPORTABLE|NCR_KEY_FLAG_WRAPPING; + keydata.flags = NCR_KEY_FLAG_EXPORTABLE|NCR_KEY_FLAG_WRAPPING|NCR_KEY_FLAG_UNWRAPPING; keydata.key = key; keydata.idata = "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F"; @@ -401,7 +401,7 @@ test_ncr_wrap_key2(int cfd) keydata.key_id_size = 2; keydata.type = NCR_KEY_TYPE_SECRET; keydata.algorithm = NCR_ALG_AES_CBC; - keydata.flags = NCR_KEY_FLAG_EXPORTABLE|NCR_KEY_FLAG_WRAPPING; + keydata.flags = NCR_KEY_FLAG_EXPORTABLE|NCR_KEY_FLAG_WRAPPING|NCR_KEY_FLAG_UNWRAPPING; keydata.key = key; keydata.idata = "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F"; diff --git a/examples/pk.c b/examples/pk.c index ea5720c59ee..78b6a10b34f 100644 --- a/examples/pk.c +++ b/examples/pk.c @@ -576,7 +576,7 @@ test_ncr_wrap_key3(int cfd) keydata.key_id_size = 2; keydata.type = NCR_KEY_TYPE_SECRET; keydata.algorithm = NCR_ALG_AES_CBC; - keydata.flags = NCR_KEY_FLAG_EXPORTABLE|NCR_KEY_FLAG_WRAPPING; + keydata.flags = NCR_KEY_FLAG_EXPORTABLE|NCR_KEY_FLAG_WRAPPING|NCR_KEY_FLAG_UNWRAPPING; keydata.key = key; keydata.idata = "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F"; diff --git a/ncr-key-wrap.c b/ncr-key-wrap.c index 1107083eefc..2f2695de6d7 100644 --- a/ncr-key-wrap.c +++ b/ncr-key-wrap.c @@ -624,7 +624,7 @@ int ret; goto fail; } - if (!(key->flags & NCR_KEY_FLAG_WRAPPING)) { + if (!(key->flags & NCR_KEY_FLAG_UNWRAPPING)) { err(); ret = -EPERM; goto fail; diff --git a/ncr-key.c b/ncr-key.c index 8f74ade80e3..f9fdcf4d5b5 100644 --- a/ncr-key.c +++ b/ncr-key.c @@ -315,6 +315,7 @@ void ncr_key_assign_flags(struct key_item_st* item, unsigned int flags) item->flags = flags; } else { item->flags = flags & (~(NCR_KEY_FLAG_WRAPPING)); + item->flags = flags & (~(NCR_KEY_FLAG_UNWRAPPING)); } } diff --git a/ncr.h b/ncr.h index c3850e4e355..701210e74da 100644 --- a/ncr.h +++ b/ncr.h @@ -70,10 +70,13 @@ typedef int 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_params_st { ncr_algorithm_t algorithm; /* just a cipher algorithm when -- cgit From 3b521fbc223cafd360def97841544d34d7396dc2 Mon Sep 17 00:00:00 2001 From: Nikos Mavrogiannopoulos Date: Wed, 25 Aug 2010 18:04:20 +0200 Subject: enforce the key wrap version. --- ncr-key-wrap.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/ncr-key-wrap.c b/ncr-key-wrap.c index 2f2695de6d7..08689cb4759 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"; @@ -826,7 +828,7 @@ static int key_to_packed_data( uint8_t** sdata, size_t * sdata_size, const struc uint8_t * derkey = NULL; uint32_t pkey_size; int ret, err; - unsigned long zero = 0; + unsigned long version = KEY_WRAP_VERSION; unsigned long type; unsigned long derlen; @@ -887,7 +889,7 @@ static int key_to_packed_data( uint8_t** sdata, size_t * sdata_size, const struc } err = der_encode_sequence_multi(derkey, &derlen, - LTC_ASN1_SHORT_INTEGER, 1UL, &zero, + 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); @@ -998,6 +1000,12 @@ static int key_from_packed_data(unsigned int flags, 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); -- cgit From 1f30d575e5b413e522d6b3e95d3e348df9e9c69e Mon Sep 17 00:00:00 2001 From: Nikos Mavrogiannopoulos Date: Thu, 26 Aug 2010 16:08:47 +0200 Subject: Unwrapping keys are restricted the same way as wrapping keys. --- ncr-key.c | 2 +- ncr-sessions.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/ncr-key.c b/ncr-key.c index f9fdcf4d5b5..295a58ed05d 100644 --- a/ncr-key.c +++ b/ncr-key.c @@ -723,7 +723,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 0a48b23b7f6..e0f8b7bdd12 100644 --- a/ncr-sessions.c +++ b/ncr-sessions.c @@ -253,7 +253,7 @@ static int _ncr_session_init(struct ncr_lists* lists, struct ncr_session_st* ses /* 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; @@ -331,7 +331,7 @@ static int _ncr_session_init(struct ncr_lists* lists, struct ncr_session_st* ses /* 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; -- cgit