From 5507ea6f51bd227ce4af661d550ad4d4de80674b Mon Sep 17 00:00:00 2001 From: Nikos Mavrogiannopoulos Date: Thu, 19 Aug 2010 18:20:26 +0200 Subject: Added KEY_WRAPPING flag that allows a key to be used for wrapping other keys. Only superuser can enable this flag. Prevent short keys to wrap longer ones. Added initial stuff for supporting wrapping of private and public keys. --- examples/ncr.c | 107 +++++++++++++++++++++++++++++++++++++++++++++++--- examples/pk.c | 116 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ ncr-dh.c | 12 ++++++ ncr-dh.h | 2 + ncr-int.h | 1 + ncr-key-wrap.c | 57 +++++++++++++++++++++++---- ncr-key.c | 120 ++++++++++++++++++++++++++++++++++++++++++++++++++++++--- ncr-pk.c | 24 ++++++++++++ ncr-pk.h | 4 ++ ncr.h | 4 ++ 10 files changed, 428 insertions(+), 19 deletions(-) diff --git a/examples/ncr.c b/examples/ncr.c index 9a75a996e58..5169a149e31 100644 --- a/examples/ncr.c +++ b/examples/ncr.c @@ -208,7 +208,7 @@ test_ncr_key(int cfd) static int test_ncr_wrap_key(int cfd) { - int i; + int i, ret; ncr_key_t key, key2; struct ncr_key_data_st keydata; struct ncr_key_wrap_st kwrap; @@ -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_WRAPPABLE; + keydata.flags = NCR_KEY_FLAG_EXPORTABLE|NCR_KEY_FLAG_WRAPPING; keydata.key = key; keydata.idata = "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F"; @@ -279,12 +279,20 @@ test_ncr_wrap_key(int cfd) kwrap.io = data; kwrap.io_size = sizeof(data); - if (ioctl(cfd, NCRIO_KEY_WRAP, &kwrap)) { + ret = ioctl(cfd, NCRIO_KEY_WRAP, &kwrap); + + if (geteuid() == 0 && ret) { fprintf(stderr, "Error: %s:%d\n", __func__, __LINE__); perror("ioctl(NCRIO_KEY_WRAP)"); return 1; } + if (geteuid() != 0) { + /* cannot test further */ + fprintf(stdout, "\t(Wrapping test not completed. Run as root)\n"); + return 0; + } + data_size = kwrap.io_size; if (kwrap.io_size != 24 || memcmp(data, @@ -298,9 +306,6 @@ test_ncr_wrap_key(int cfd) return 1; } - - - /* test unwrapping */ fprintf(stdout, "\tKey Unwrap test...\n"); @@ -360,7 +365,94 @@ test_ncr_wrap_key(int cfd) #endif return 0; +} + +/* check whether wrapping of long keys is not allowed with + * shorted wrapping keys */ +static int +test_ncr_wrap_key2(int cfd) +{ + int ret; + ncr_key_t key, key2; + struct ncr_key_data_st keydata; + struct ncr_key_wrap_st kwrap; + uint8_t data[WRAPPED_KEY_DATA_SIZE]; + + /* test 1: generate a key in userspace import it + * to kernel via data and export it. + */ + + fprintf(stdout, "\tKey Wrap test II...\n"); + + if (geteuid() != 0) { + /* cannot test further */ + fprintf(stdout, "\t(Wrapping test not completed. Run as root)\n"); + return 0; + } + + /* convert it to key */ + if (ioctl(cfd, NCRIO_KEY_INIT, &key)) { + perror("ioctl(NCRIO_KEY_INIT)"); + return 1; + } + + keydata.key_id[0] = 'a'; + keydata.key_id[2] = 'b'; + 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.key = key; + keydata.idata = "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F"; + keydata.idata_size = 16; + + if (ioctl(cfd, NCRIO_KEY_IMPORT, &keydata)) { + fprintf(stderr, "Error: %s:%d\n", __func__, __LINE__); + perror("ioctl(NCRIO_KEY_IMPORT)"); + return 1; + } + + + /* convert it to key */ + if (ioctl(cfd, NCRIO_KEY_INIT, &key2)) { + perror("ioctl(NCRIO_KEY_INIT)"); + return 1; + } + keydata.key_id[0] = 'b'; + keydata.key_id[2] = 'a'; + 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_WRAPPABLE; + + keydata.key = key2; + keydata.idata = "\x00\x11\x22\x33\x44\x55\x66\x77\x88\x99\xAA\xBB\xCC\xDD\xEE\xFF\x00\x11\x22\x33\x44\x55\x66\x77\x88\x99\xAA\xBB\xCC\xDD\xEE\xFF"; + keydata.idata_size = 32; + + if (ioctl(cfd, NCRIO_KEY_IMPORT, &keydata)) { + fprintf(stderr, "Error: %s:%d\n", __func__, __LINE__); + perror("ioctl(NCRIO_KEY_IMPORT)"); + return 1; + } + + /* now try wrapping key2 using key */ + memset(&kwrap, 0, sizeof(kwrap)); + kwrap.algorithm = NCR_WALG_AES_RFC3394; + kwrap.keytowrap = key2; + kwrap.key = key; + kwrap.io = data; + kwrap.io_size = sizeof(data); + + ret = ioctl(cfd, NCRIO_KEY_WRAP, &kwrap); + if (!ret) { + fprintf(stderr, "Error: %s:%d\n", __func__, __LINE__); + /* wrapping shouldn't have been allowed */ + return 1; + } + + return 0; } static int @@ -939,6 +1031,9 @@ main() if (test_ncr_wrap_key(fd)) return 1; + if (test_ncr_wrap_key2(fd)) + return 1; + if (test_ncr_store_wrap_key(fd)) return 1; diff --git a/examples/pk.c b/examples/pk.c index 3102a3b1abd..5f7c72a3e00 100644 --- a/examples/pk.c +++ b/examples/pk.c @@ -524,6 +524,119 @@ struct ncr_key_derivation_params_st kderive; return 0; } +/* check whether wrapping of long keys is not allowed with + * shorted wrapping keys */ +static int +test_ncr_wrap_key3(int cfd) +{ + int ret, i; + ncr_key_t key; + struct ncr_key_data_st keydata; + struct ncr_key_wrap_st kwrap; + struct ncr_key_generate_st kgen; + ncr_key_t pubkey, privkey; + uint8_t data[DATA_SIZE]; + /* only the first two should be allowed to be wrapped */ + const int sizes[] = {1024, 3248, 5200}; + + fprintf(stdout, "Tests on key wrapping: "); + fflush(stdout); + + /* convert it to key */ + if (ioctl(cfd, NCRIO_KEY_INIT, &privkey)) { + fprintf(stderr, "Error: %s:%d\n", __func__, __LINE__); + perror("ioctl(NCRIO_KEY_INIT)"); + return 1; + } + + if (ioctl(cfd, NCRIO_KEY_INIT, &pubkey)) { + fprintf(stderr, "Error: %s:%d\n", __func__, __LINE__); + perror("ioctl(NCRIO_KEY_INIT)"); + return 1; + } + + if (geteuid() != 0) { + /* cannot test further */ + fprintf(stdout, "\t(Wrapping test not completed. Run as root)\n"); + return 0; + } + + /* make a wrapping key */ + if (ioctl(cfd, NCRIO_KEY_INIT, &key)) { + perror("ioctl(NCRIO_KEY_INIT)"); + return 1; + } + + keydata.key_id[0] = 'a'; + keydata.key_id[2] = 'b'; + 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.key = key; + keydata.idata = "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F"; + keydata.idata_size = 16; + + if (ioctl(cfd, NCRIO_KEY_IMPORT, &keydata)) { + fprintf(stderr, "Error: %s:%d\n", __func__, __LINE__); + perror("ioctl(NCRIO_KEY_IMPORT)"); + return 1; + } + + for (i=0;ip); + if (ret <= 0) { + err(); + return -EINVAL; + } + + return ret; +} diff --git a/ncr-dh.h b/ncr-dh.h index cc45d3206cc..183f7909154 100644 --- a/ncr-dh.h +++ b/ncr-dh.h @@ -22,4 +22,6 @@ int dh_import(const uint8_t *in, size_t inlen, dh_key *key); int dh_derive_gxy(struct key_item_st* newkey, dh_key * key, void* pk, size_t pk_size); +int ncr_pk_get_dh_size( dh_key* key); + #endif diff --git a/ncr-int.h b/ncr-int.h index 84bca9e3f68..df53ce3bd4a 100644 --- a/ncr-int.h +++ b/ncr-int.h @@ -169,5 +169,6 @@ int key_to_storage_data( uint8_t** data, size_t * data_size, const struct key_it const struct algo_properties_st *_ncr_algo_to_properties(ncr_algorithm_t algo); const struct algo_properties_st *ncr_key_params_get_sign_hash(const struct algo_properties_st *algo, struct ncr_key_params_st * params); +int _ncr_key_get_sec_level(struct key_item_st* item); #endif diff --git a/ncr-key-wrap.c b/ncr-key-wrap.c index 0c56def27f7..eb68d92de05 100644 --- a/ncr-key-wrap.c +++ b/ncr-key-wrap.c @@ -430,6 +430,37 @@ cleanup: return ret; } +/* will check if the kek is of equal or higher security level than + * wkey. To prevent encrypting a 256 bit key with an 128 bit one. + */ +int check_key_level(struct key_item_st* kek, struct key_item_st* wkey) +{ +int kek_level, wkey_level; + + /* allow wrapping of public keys with any key */ + if (wkey->type == NCR_KEY_TYPE_PUBLIC) + return 0; + + kek_level = _ncr_key_get_sec_level(kek); + if (kek_level < 0) { + err(); + return kek_level; + } + + wkey_level = _ncr_key_get_sec_level(wkey); + if (wkey_level < 0) { + err(); + return wkey_level; + } + + if (wkey_level > kek_level) { + err(); + return -EPERM; + } + + return 0; +} + int ncr_key_wrap(struct ncr_lists *lst, void __user* arg) { struct ncr_key_wrap_st wrap; @@ -462,6 +493,18 @@ int ret; goto fail; } + if (!(key->flags & NCR_KEY_FLAG_WRAPPING)) { + err(); + ret = -EPERM; + goto fail; + } + + ret = check_key_level(key, wkey); + if (ret < 0) { + err(); + goto fail; + } + data_size = wrap.io_size; data = kmalloc(data_size, GFP_KERNEL); if (data == NULL) { @@ -539,6 +582,12 @@ int ret; goto fail; } + if (!(key->flags & NCR_KEY_FLAG_WRAPPING)) { + err(); + ret = -EPERM; + goto fail; + } + data_size = wrap.io_size; data = kmalloc(data_size, GFP_KERNEL); if (data == NULL) { @@ -601,12 +650,6 @@ int ret; return ret; } - if (!(wkey->flags & NCR_KEY_FLAG_WRAPPABLE)) { - err(); - ret = -EPERM; - goto fail; - } - data_size = wrap.io_size; data = kmalloc(data_size, GFP_KERNEL); if (data == NULL) { @@ -698,8 +741,6 @@ int ret; goto fail; } - wkey->flags = NCR_KEY_FLAG_WRAPPABLE; - ret = _unwrap_aes_rfc5649(sdata, &sdata_size, &master_key, data, data_size, NULL, 0); if (ret < 0) { err(); diff --git a/ncr-key.c b/ncr-key.c index bf438fa22cc..e34367e221c 100644 --- a/ncr-key.c +++ b/ncr-key.c @@ -311,6 +311,15 @@ fail: } +unsigned int assign_key_flags(unsigned int flags) +{ + if (current_euid()==0) { + return flags; + } else { + return flags & (~(NCR_KEY_FLAG_WRAPPING)); + } +} + /* "imports" a key from a data item. If the key is not exportable * to userspace then the key item will also not be. */ @@ -356,7 +365,7 @@ size_t tmp_size; ret = -EINVAL; goto fail; } - item->flags = data.flags; + item->flags = assign_key_flags(data.flags); if (data.key_id_size > MAX_KEY_ID_SIZE) { err(); @@ -370,7 +379,6 @@ size_t tmp_size; switch(item->type) { case NCR_KEY_TYPE_SECRET: - if (tmp_size > NCR_CIPHER_MAX_KEY_LEN) { err(); ret = -EINVAL; @@ -445,7 +453,8 @@ size_t size; ncr_key_clear(item); /* we generate only secret keys */ - item->flags = gen.params.keyflags; + item->flags = assign_key_flags(gen.params.keyflags); + algo = _ncr_algo_to_properties(gen.params.algorithm); if (algo == NULL) { err(); @@ -486,6 +495,106 @@ fail: return ret; } +/* Those values are derived from "ECRYPT II Yearly Report on Algorithms and + * Keysizes (2009-2010)". It maps the strength of public key algorithms to + * symmetric ones. Should be kept up to date. + */ +struct { + unsigned int bits; /* sec level */ + unsigned int rsa_bits; + unsigned int dlog_bits; +} ecrypt_vals[] = { + {64, 816, 816}, + {80, 1248, 1248}, + {112, 2432, 2432}, + {128, 3248, 3248}, + {160, 5312, 5312}, + {192, 7936, 7936}, + {256, 15424, 15424}, + {0,0,0} +}; + +unsigned int rsa_to_bits(unsigned int rsa_bits) +{ +int i = 1; + + if (rsa_bits <= ecrypt_vals[0].rsa_bits) + return ecrypt_vals[0].rsa_bits; + + do { + if (rsa_bits <= ecrypt_vals[i].rsa_bits && + rsa_bits > ecrypt_vals[i-1].rsa_bits) { + + return ecrypt_vals[i].bits; + } + } while(ecrypt_vals[++i].bits != 0); + + /* return the highest found so far */ + return ecrypt_vals[i-1].bits; +} + +unsigned int dlog_to_bits(unsigned int dlog_bits) +{ +int i = 1; + + if (dlog_bits <= ecrypt_vals[0].dlog_bits) + return ecrypt_vals[0].dlog_bits; + + do { + if (dlog_bits <= ecrypt_vals[i].dlog_bits && + dlog_bits > ecrypt_vals[i-1].dlog_bits) { + + return ecrypt_vals[i].bits; + } + } while(ecrypt_vals[++i].bits != 0); + + /* return the highest found so far */ + return ecrypt_vals[i-1].bits; +} + +/* returns the security level of the key in bits. Private/Public keys + * are mapped to symmetric key bits using the ECRYPT II 2010 recommendation. + */ +int _ncr_key_get_sec_level(struct key_item_st* item) +{ +int bits; + + if (item->type == NCR_KEY_TYPE_SECRET) { + return item->key.secret.size*8; + } else if (item->type == NCR_KEY_TYPE_PRIVATE) { + switch(item->algorithm->algo) { + case NCR_ALG_RSA: + bits = ncr_pk_get_rsa_size(&item->key.pk.rsa); + if (bits < 0) { + err(); + return bits; + } + + return rsa_to_bits(bits); + case NCR_ALG_DSA: + bits = ncr_pk_get_dsa_size(&item->key.pk.dsa); + if (bits < 0) { + err(); + return bits; + } + + return dlog_to_bits(bits); + case NCR_ALG_DH: + bits = ncr_pk_get_dh_size(&item->key.pk.dh); + if (bits < 0) { + err(); + return bits; + } + + return dlog_to_bits(bits); + default: + return -EINVAL; + } + } else { + return -EINVAL; + } +} + int ncr_key_info(struct ncr_lists *lst, void __user* arg) { struct ncr_key_info_st info; @@ -549,7 +658,8 @@ int ret; ncr_key_clear(private); /* we generate only secret keys */ - private->flags = public->flags = gen.params.keyflags; + private->flags = public->flags = assign_key_flags(gen.params.keyflags); + private->algorithm = public->algorithm = _ncr_algo_to_properties(gen.params.algorithm); if (private->algorithm == NULL) { err(); @@ -614,7 +724,7 @@ struct key_item_st* newkey = NULL; ncr_key_clear(newkey); - newkey->flags = data.keyflags; + newkey->flags = assign_key_flags(data.keyflags); switch (key->type) { case NCR_KEY_TYPE_PUBLIC: diff --git a/ncr-pk.c b/ncr-pk.c index 1e83163c155..76b78c094ff 100644 --- a/ncr-pk.c +++ b/ncr-pk.c @@ -714,3 +714,27 @@ fail: kfree(tmp); return ret; } + +int ncr_pk_get_rsa_size( rsa_key* key) +{ +int ret; + ret = mp_count_bits(&key->N); + if (ret <= 0) { + err(); + return -EINVAL; + } + + return ret; +} + +int ncr_pk_get_dsa_size( dsa_key* key) +{ +int ret; + ret = mp_count_bits(&key->p); + if (ret <= 0) { + err(); + return -EINVAL; + } + + return ret; +} diff --git a/ncr-pk.h b/ncr-pk.h index 25a057120f9..1c8d7208737 100644 --- a/ncr-pk.h +++ b/ncr-pk.h @@ -52,4 +52,8 @@ int _ncr_tomerr(int err); int ncr_pk_derive(struct key_item_st* newkey, struct key_item_st* oldkey, struct ncr_key_derivation_params_st * params); +int ncr_pk_get_rsa_size( rsa_key* key); +int ncr_pk_get_dsa_size( dsa_key* key); + + #endif diff --git a/ncr.h b/ncr.h index a3778248630..cddde078f1e 100644 --- a/ncr.h +++ b/ncr.h @@ -70,6 +70,10 @@ 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 + * adversaries exporting wrappable keys with random ones. + */ +#define NCR_KEY_FLAG_WRAPPING (1<<4) struct ncr_key_generate_params_st { ncr_algorithm_t algorithm; /* just a cipher algorithm when -- cgit From 88d38939bcf937e62b32f39d006d4e86ca89083c Mon Sep 17 00:00:00 2001 From: Nikos Mavrogiannopoulos Date: Fri, 20 Aug 2010 09:54:41 +0200 Subject: Increased RSA size to 8192. Return error on wrong arguments. --- libtomcrypt/headers/tomcrypt_argchk.h | 4 ++-- libtomcrypt/headers/tomcrypt_cfg.h | 4 ++-- libtomcrypt/headers/tomcrypt_pk.h | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/libtomcrypt/headers/tomcrypt_argchk.h b/libtomcrypt/headers/tomcrypt_argchk.h index 1b94434ccb3..1ba08c7ffad 100644 --- a/libtomcrypt/headers/tomcrypt_argchk.h +++ b/libtomcrypt/headers/tomcrypt_argchk.h @@ -25,8 +25,8 @@ void crypt_argchk(char *v, char *s, int d); #elif ARGTYPE == 4 -#define LTC_ARGCHK(x) if (!(x)) return CRYPT_INVALID_ARG; -#define LTC_ARGCHKVD(x) if (!(x)) return; +#define LTC_ARGCHK(x) if (!(x)) { printk( "\nwarning: ARGCHK failed at %s:%d\n", __FILE__, __LINE__); return CRYPT_INVALID_ARG; } +#define LTC_ARGCHKVD(x) if (!(x)) { printk( "\nwarning: ARGCHK failed at %s:%d\n", __FILE__, __LINE__); return; } #endif diff --git a/libtomcrypt/headers/tomcrypt_cfg.h b/libtomcrypt/headers/tomcrypt_cfg.h index b750c8be78c..8ad90bce4b0 100644 --- a/libtomcrypt/headers/tomcrypt_cfg.h +++ b/libtomcrypt/headers/tomcrypt_cfg.h @@ -42,9 +42,9 @@ LTC_EXPORT int LTC_CALL XSTRCMP(const char *s1, const char *s2); #endif -/* type of argument checking, 0=default, 1=fatal and 2=error+continue, 3=nothing */ +/* type of argument checking, 0=default, 1=fatal and 2=error+continue, 3=nothing, 4=return error */ #ifndef ARGTYPE - #define ARGTYPE 0 + #define ARGTYPE 4 #endif /* Controls endianess and size of registers. Leave uncommented to get platform neutral [slower] code diff --git a/libtomcrypt/headers/tomcrypt_pk.h b/libtomcrypt/headers/tomcrypt_pk.h index 145165efe51..73348805748 100644 --- a/libtomcrypt/headers/tomcrypt_pk.h +++ b/libtomcrypt/headers/tomcrypt_pk.h @@ -26,7 +26,7 @@ int rand_prime(mp_int *N, long len); /* Min and Max RSA key sizes (in bits) */ #define MIN_RSA_SIZE 1024 -#define MAX_RSA_SIZE 4096 +#define MAX_RSA_SIZE 8192 /** RSA LTC_PKCS style key */ typedef struct Rsa_key { -- cgit From 5543826bf1a2b550d8ce4fe116288178537ec902 Mon Sep 17 00:00:00 2001 From: Nikos Mavrogiannopoulos Date: Sat, 21 Aug 2010 10:11:16 +0200 Subject: Prevent usage of wrapping keys for anything else except wrapping. --- ncr-sessions.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/ncr-sessions.c b/ncr-sessions.c index 2916729b91a..0a48b23b7f6 100644 --- a/ncr-sessions.c +++ b/ncr-sessions.c @@ -250,6 +250,15 @@ static int _ncr_session_init(struct ncr_lists* lists, struct ncr_session_st* ses err(); goto fail; } + + /* wrapping keys cannot be used for encryption or decryption + */ + if (ns->key->flags & NCR_KEY_FLAG_WRAPPING) { + err(); + ret = -EINVAL; + goto fail; + } + if (ns->key->type == NCR_KEY_TYPE_SECRET) { int keysize = ns->key->key.secret.size; @@ -320,6 +329,14 @@ static int _ncr_session_init(struct ncr_lists* lists, struct ncr_session_st* ses goto fail; } + /* wrapping keys cannot be used for anything except wrapping. + */ + if (ns->key->flags & NCR_KEY_FLAG_WRAPPING) { + err(); + ret = -EINVAL; + goto fail; + } + if (ns->algorithm->is_hmac && ns->key->type == NCR_KEY_TYPE_SECRET) { if (ns->algorithm->kstr == NULL) { err(); -- cgit From 7b2f60fb851e7fe728ff80e5f9416b34ba47dde1 Mon Sep 17 00:00:00 2001 From: Nikos Mavrogiannopoulos Date: Sat, 21 Aug 2010 10:11:38 +0200 Subject: export ncr_key_clear(). And disallow key derivation from wrapping keys. --- ncr-int.h | 2 ++ ncr-key.c | 12 +++++++++--- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/ncr-int.h b/ncr-int.h index df53ce3bd4a..9f7ee0ded64 100644 --- a/ncr-int.h +++ b/ncr-int.h @@ -110,6 +110,8 @@ int ncr_ioctl(struct ncr_lists*, struct file *filp, /* key derivation */ int ncr_key_derive(struct ncr_lists *lst, void __user* arg); +void ncr_key_clear(struct key_item_st* item); + /* key handling */ int ncr_key_init(struct ncr_lists *lst, void __user* arg); int ncr_key_deinit(struct ncr_lists *lst, void __user* arg); diff --git a/ncr-key.c b/ncr-key.c index e34367e221c..4b9b26ff659 100644 --- a/ncr-key.c +++ b/ncr-key.c @@ -32,8 +32,6 @@ #include "ncr.h" #include "ncr-int.h" -static void ncr_key_clear(struct key_item_st* item); - static int key_list_deinit_fn(int id, void *item, void *unused) { (void)unused; @@ -413,7 +411,7 @@ fail: return ret; } -static void ncr_key_clear(struct key_item_st* item) +void ncr_key_clear(struct key_item_st* item) { /* clears any previously allocated parameters */ if (item->type == NCR_KEY_TYPE_PRIVATE || @@ -715,6 +713,14 @@ struct key_item_st* newkey = NULL; err(); return ret; } + + /* wrapping keys cannot be used for anything except wrapping. + */ + if (key->flags & NCR_KEY_FLAG_WRAPPING) { + err(); + ret = -EINVAL; + goto fail; + } ret = ncr_key_item_get_write( &newkey, lst, data.newkey); if (ret < 0) { -- cgit From 8f6ef273e5e0ef9bad24ebe6b95cbf90f82e74b9 Mon Sep 17 00:00:00 2001 From: Nikos Mavrogiannopoulos Date: Sat, 21 Aug 2010 12:24:22 +0200 Subject: Corrected bug in importing RSA private keys. --- libtomcrypt/pk/rsa/rsa_import.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libtomcrypt/pk/rsa/rsa_import.c b/libtomcrypt/pk/rsa/rsa_import.c index 9f3c5bfa642..87cb1030d47 100644 --- a/libtomcrypt/pk/rsa/rsa_import.c +++ b/libtomcrypt/pk/rsa/rsa_import.c @@ -84,7 +84,7 @@ int rsa_import(const unsigned char *in, unsigned long inlen, rsa_key *key) } /* it's a private key */ if ((err = der_decode_sequence_multi(in, inlen, - LTC_ASN1_INTEGER, 1UL, zero, + LTC_ASN1_INTEGER, 1UL, &zero, LTC_ASN1_INTEGER, 1UL, &key->N, LTC_ASN1_INTEGER, 1UL, &key->e, LTC_ASN1_INTEGER, 1UL, &key->d, -- cgit From 7c6e3b075e7d7a0cdeafaa0b9701a9f6dd29cdee Mon Sep 17 00:00:00 2001 From: Nikos Mavrogiannopoulos Date: Sat, 21 Aug 2010 12:26:54 +0200 Subject: Fix in export of DH keys. --- ncr-pk.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ncr-pk.c b/ncr-pk.c index 76b78c094ff..104c047df8e 100644 --- a/ncr-pk.c +++ b/ncr-pk.c @@ -167,8 +167,9 @@ int ncr_pk_pack( const struct key_item_st * key, uint8_t * packed, uint32_t * pa } break; case NCR_ALG_DH: - ret = dh_export(packed, &max_size, key->key.pk.dsa.type, (void*)&key->key.pk.dsa); + ret = dh_export(packed, &max_size, key->key.pk.dh.type, (void*)&key->key.pk.dh); if (ret < 0) { + *packed_size = max_size; err(); return ret; } -- cgit From 3c7ca7cc92736ff56ec241b1c3da890b7496e5cc Mon Sep 17 00:00:00 2001 From: Nikos Mavrogiannopoulos Date: Sat, 21 Aug 2010 12:33:16 +0200 Subject: key generation must be done interruptible. --- TODO | 1 + 1 file changed, 1 insertion(+) diff --git a/TODO b/TODO index 875738e40cb..3a5a1abc424 100644 --- a/TODO +++ b/TODO @@ -4,3 +4,4 @@ * Documentation for functions * Is a writev() like interface needed? * Implement the NIST DSA generation algorithm. +* Make key generation interruptible. -- cgit From 659f7452456f4fa5cee8694f808d61da6f840b32 Mon Sep 17 00:00:00 2001 From: Nikos Mavrogiannopoulos Date: Sat, 21 Aug 2010 12:41:23 +0200 Subject: Improvements in key wrapping. Allowed symmetric keys to wrap assymetric ones. --- examples/pk.c | 31 +++++++++++- ncr-int.h | 1 + ncr-key-wrap.c | 155 +++++++++++++++++++++++++++++++++++++++++++++++++++------ ncr-key.c | 17 ++++--- ncr.h | 8 +++ 5 files changed, 188 insertions(+), 24 deletions(-) diff --git a/examples/pk.c b/examples/pk.c index 5f7c72a3e00..629ca6adfde 100644 --- a/examples/pk.c +++ b/examples/pk.c @@ -531,6 +531,7 @@ test_ncr_wrap_key3(int cfd) { int ret, i; ncr_key_t key; + size_t data_size; struct ncr_key_data_st keydata; struct ncr_key_wrap_st kwrap; struct ncr_key_generate_st kgen; @@ -539,7 +540,7 @@ test_ncr_wrap_key3(int cfd) /* only the first two should be allowed to be wrapped */ const int sizes[] = {1024, 3248, 5200}; - fprintf(stdout, "Tests on key wrapping: "); + fprintf(stdout, "Tests on key wrapping (might take long): "); fflush(stdout); /* convert it to key */ @@ -585,6 +586,10 @@ test_ncr_wrap_key3(int cfd) } for (i=0;itype != NCR_KEY_TYPE_SECRET) { +int ret; +uint8_t* sdata; +size_t sdata_size = 0; + + ret = key_to_packed_data(&sdata, &sdata_size, tobewrapped); + if (ret < 0) { err(); - return -EINVAL; + return ret; } - return _wrap_aes_rfc5649(tobewrapped->key.secret.data, tobewrapped->key.secret.size, + ret = _wrap_aes_rfc5649(sdata, sdata_size, kek, output, output_size, iv, iv_size); + + kfree(sdata); + return ret; } static int unwrap_aes_rfc5649(struct key_item_st* output, struct key_item_st *kek, - void* wrapped, size_t wrapped_size, const void* iv, size_t iv_size) + void* wrapped, size_t wrapped_size, + struct ncr_key_wrap_st* wrap_st) { - output->type = NCR_KEY_TYPE_SECRET; +int ret; +void * sdata; +size_t sdata_size = KEY_DATA_MAX_SIZE; + + sdata = kmalloc(sdata_size, GFP_KERNEL); + if (sdata == NULL) { + err(); + return -ENOMEM; + } + + ret = _unwrap_aes_rfc5649(sdata, &sdata_size, kek, + wrapped, wrapped_size, + wrap_st->params.params.cipher.iv, wrap_st->params.params.cipher.iv_size); + if (ret < 0) { + err(); + goto fail; + } + + ret = key_from_packed_data(wrap_st->wrapped_key_algorithm, wrap_st->wrapped_key_flags, + output, sdata, sdata_size); + if (ret < 0) { + err(); + goto fail; + } + + ret = 0; + +fail: + kfree(sdata); + return ret; - return _unwrap_aes_rfc5649(output->key.secret.data, &output->key.secret.size, kek, - wrapped, wrapped_size, iv, iv_size); } @@ -358,14 +398,16 @@ void print_val64(char* str, val64_t val) } #endif -static int unwrap_aes(struct key_item_st* output, struct key_item_st *kek, - void* wrapped_key, size_t wrapped_key_size, const void* iv, size_t iv_size) +static int unwrap_aes_rfc3394(struct key_item_st* output, struct key_item_st *kek, + void* wrapped_key, size_t wrapped_key_size, struct ncr_key_wrap_st *wrap_st) { size_t n; val64_t A; int i, ret; struct cipher_data ctx; val64_t * R = NULL; +int iv_size = wrap_st->params.params.cipher.iv_size; +const uint8_t * iv = wrap_st->params.params.cipher.iv; if (iv_size < sizeof(initA)) { iv_size = sizeof(initA); @@ -418,7 +460,7 @@ val64_t * R = NULL; memcpy(&output->key.secret.data[i*8], R[i], sizeof(R[i])); } output->key.secret.size = n*8; - output->flags = NCR_KEY_FLAG_WRAPPABLE; + ncr_key_assign_flags(output, wrap_st->wrapped_key_flags); output->type = NCR_KEY_TYPE_SECRET; ret = 0; @@ -601,15 +643,17 @@ int ret; ret = -EFAULT; goto fail; } + + ncr_key_clear(wkey); switch(wrap.algorithm) { case NCR_WALG_AES_RFC3394: - ret = unwrap_aes(wkey, key, data, data_size, - wrap.params.params.cipher.iv, wrap.params.params.cipher.iv_size); + ret = unwrap_aes_rfc3394(wkey, key, data, data_size, + &wrap); break; case NCR_WALG_AES_RFC5649: - ret = unwrap_aes_rfc5649(wkey, key, data, data_size, - wrap.params.params.cipher.iv, wrap.params.params.cipher.iv_size); + ret = unwrap_aes_rfc5649(wkey, key, + data, data_size, &wrap); break; default: err(); @@ -747,6 +791,8 @@ int ret; goto fail; } + ncr_key_clear(wkey); + ret = key_from_storage_data(wkey, sdata, sdata_size); if (ret < 0) { err(); @@ -761,3 +807,84 @@ fail: return ret; } + +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; + + *sdata_size = KEY_DATA_MAX_SIZE; + pkey = kmalloc(*sdata_size, GFP_KERNEL); + if (pkey == NULL) { + err(); + return -ENOMEM; + } + + if (key->type == NCR_KEY_TYPE_SECRET) { + memcpy(pkey, key->key.secret.data, key->key.secret.size); + *sdata_size = key->key.secret.size; + } else if (key->type == NCR_KEY_TYPE_PRIVATE || key->type == NCR_KEY_TYPE_PUBLIC) { + usize = *sdata_size; + ret = ncr_pk_pack( key, pkey, &usize); + if (ret < 0) { + err(); + goto fail; + } + *sdata_size = usize; + } else { + err(); + ret = -EINVAL; + goto fail; + } + + *sdata = (void*)pkey; + + return 0; +fail: + kfree(pkey); + + return ret; +} + +static int key_from_packed_data(ncr_algorithm_t algorithm, unsigned int flags, + struct key_item_st* key, const void* data, size_t data_size) +{ + int ret; + + if (data_size > KEY_DATA_MAX_SIZE) { + err(); + return -EINVAL; + } + + key->algorithm = _ncr_algo_to_properties(algorithm); + if (key->algorithm == NULL) { + err(); + return -EINVAL; + } + + key->type = key->algorithm->key_type; + ncr_key_assign_flags(key, flags); + + if (key->type == NCR_KEY_TYPE_SECRET) { + if (data_size > NCR_CIPHER_MAX_KEY_LEN) { + err(); + return -EINVAL; + } + key->key.secret.size = data_size; + memcpy(key->key.secret.data, data, data_size); + } else if (key->type == NCR_KEY_TYPE_PUBLIC + || key->type == NCR_KEY_TYPE_PRIVATE) { + + ret = ncr_pk_unpack( key, data, data_size); + if (ret < 0) { + err(); + return ret; + } + } else { + err(); + return -EINVAL; + } + + return 0; +} diff --git a/ncr-key.c b/ncr-key.c index 4b9b26ff659..37e78542b24 100644 --- a/ncr-key.c +++ b/ncr-key.c @@ -309,12 +309,12 @@ fail: } -unsigned int assign_key_flags(unsigned int flags) +void ncr_key_assign_flags(struct key_item_st* item, unsigned int flags) { if (current_euid()==0) { - return flags; + item->flags = flags; } else { - return flags & (~(NCR_KEY_FLAG_WRAPPING)); + item->flags = flags & (~(NCR_KEY_FLAG_WRAPPING)); } } @@ -363,7 +363,7 @@ size_t tmp_size; ret = -EINVAL; goto fail; } - item->flags = assign_key_flags(data.flags); + ncr_key_assign_flags(item, data.flags); if (data.key_id_size > MAX_KEY_ID_SIZE) { err(); @@ -451,7 +451,7 @@ size_t size; ncr_key_clear(item); /* we generate only secret keys */ - item->flags = assign_key_flags(gen.params.keyflags); + ncr_key_assign_flags(item, gen.params.keyflags); algo = _ncr_algo_to_properties(gen.params.algorithm); if (algo == NULL) { @@ -656,8 +656,6 @@ int ret; ncr_key_clear(private); /* we generate only secret keys */ - private->flags = public->flags = assign_key_flags(gen.params.keyflags); - private->algorithm = public->algorithm = _ncr_algo_to_properties(gen.params.algorithm); if (private->algorithm == NULL) { err(); @@ -666,6 +664,9 @@ int ret; } public->type = public->algorithm->key_type; private->type = NCR_KEY_TYPE_PRIVATE; + ncr_key_assign_flags(private, gen.params.keyflags); + ncr_key_assign_flags(public, gen.params.keyflags); + public->flags |= (NCR_KEY_FLAG_EXPORTABLE|NCR_KEY_FLAG_WRAPPABLE); if (public->type == NCR_KEY_TYPE_PUBLIC) { @@ -730,7 +731,7 @@ struct key_item_st* newkey = NULL; ncr_key_clear(newkey); - newkey->flags = assign_key_flags(data.keyflags); + ncr_key_assign_flags(newkey, data.keyflags); switch (key->type) { case NCR_KEY_TYPE_PUBLIC: diff --git a/ncr.h b/ncr.h index cddde078f1e..af4c279b630 100644 --- a/ncr.h +++ b/ncr.h @@ -199,6 +199,7 @@ struct ncr_key_data_st { #define NCRIO_KEY_DERIVE _IOR ('c', 207, struct ncr_key_derivation_params_st) /* return information on a key */ #define NCRIO_KEY_GET_INFO _IOWR('c', 208, struct ncr_key_info_st) + /* export a secret key */ #define NCRIO_KEY_EXPORT _IOWR('c', 209, struct ncr_key_data_st) /* import a secret key */ @@ -210,6 +211,13 @@ 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; ncr_key_t key; -- cgit From 5f0a8311feda0c7d4a152bc2f6913a9bd888cd7b Mon Sep 17 00:00:00 2001 From: Nikos Mavrogiannopoulos Date: Sat, 21 Aug 2010 12:42:43 +0200 Subject: Document that assymetric keys cannot wrap symmetric ones. --- TODO | 1 + 1 file changed, 1 insertion(+) diff --git a/TODO b/TODO index 3a5a1abc424..89cfa328bee 100644 --- a/TODO +++ b/TODO @@ -5,3 +5,4 @@ * Is a writev() like interface needed? * Implement the NIST DSA generation algorithm. * Make key generation interruptible. +* Allow assymetric keys to wrap other keys. -- cgit From 172a5b864f3ae6890b1cfc297cf9053b33fd8ee1 Mon Sep 17 00:00:00 2001 From: Nikos Mavrogiannopoulos Date: Sat, 21 Aug 2010 12:43:48 +0200 Subject: more text --- examples/pk.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/examples/pk.c b/examples/pk.c index 629ca6adfde..032ae9864d9 100644 --- a/examples/pk.c +++ b/examples/pk.c @@ -537,7 +537,10 @@ test_ncr_wrap_key3(int cfd) struct ncr_key_generate_st kgen; ncr_key_t pubkey, privkey; uint8_t data[DATA_SIZE]; - /* only the first two should be allowed to be wrapped */ + /* only the first two should be allowed to be wrapped. + * the latter shouldn't because it has security level larger + * then 128 bits (the size of the wrapping key). + */ const int sizes[] = {1024, 3248, 5200}; fprintf(stdout, "Tests on key wrapping (might take long): "); -- cgit From accc6fa7aa2d52f338fa5123b28292e594b605e9 Mon Sep 17 00:00:00 2001 From: Nikos Mavrogiannopoulos Date: Sun, 22 Aug 2010 11:16:00 +0200 Subject: When calculating algorithm strength consider 3DES as 112 bit cipher. --- ncr-key.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/ncr-key.c b/ncr-key.c index 37e78542b24..8f74ade80e3 100644 --- a/ncr-key.c +++ b/ncr-key.c @@ -557,7 +557,12 @@ int _ncr_key_get_sec_level(struct key_item_st* item) { int bits; + /* FIXME: should we move everything here into algorithm properties? + */ if (item->type == NCR_KEY_TYPE_SECRET) { + if (item->algorithm->algo == NCR_ALG_3DES_CBC) + return 112; + return item->key.secret.size*8; } else if (item->type == NCR_KEY_TYPE_PRIVATE) { switch(item->algorithm->algo) { -- cgit From af2c2e1da1a898c8968281824ba8a4d9616670dc Mon Sep 17 00:00:00 2001 From: Nikos Mavrogiannopoulos Date: Mon, 23 Aug 2010 18:54:03 +0200 Subject: Compare cryptodev to NCR on a fair basis. --- examples/speed.c | 48 ++++++++++++++++++++++++------------------------ 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/examples/speed.c b/examples/speed.c index 5898aaae76e..1cdd3afb71c 100644 --- a/examples/speed.c +++ b/examples/speed.c @@ -68,7 +68,7 @@ static void value2human(double bytes, double time, double* data, double* speed,c } -int encrypt_data(struct session_op *sess, int fdc, int chunksize) +int encrypt_data(int cipher, int fdc, int chunksize) { struct crypt_op cop; char *buffer, iv[32]; @@ -76,7 +76,15 @@ int encrypt_data(struct session_op *sess, int fdc, int chunksize) struct timeval start, end; double total = 0; double secs, ddata, dspeed; + struct session_op sess; char metric[16]; + char keybuf[16]; + int keylen; + + memset(keybuf, 0x42, 16); + if (cipher == CRYPTO_NULL) + keylen = 0; + else keylen = 16; buffer = malloc(chunksize); memset(iv, 0x23, 32); @@ -91,8 +99,17 @@ int encrypt_data(struct session_op *sess, int fdc, int chunksize) gettimeofday(&start, NULL); do { + memset(&sess, 0, sizeof(sess)); + sess.cipher = cipher; + sess.keylen = keylen; + sess.key = (unsigned char *)keybuf; + if (ioctl(fdc, CIOCGSESSION, &sess)) { + perror("ioctl(CIOCGSESSION)"); + return 1; + } + memset(&cop, 0, sizeof(cop)); - cop.ses = sess->ses; + cop.ses = sess.ses; cop.len = chunksize; cop.iv = (unsigned char *)iv; cop.op = COP_ENCRYPT; @@ -103,6 +120,9 @@ int encrypt_data(struct session_op *sess, int fdc, int chunksize) perror("ioctl(CIOCCRYPT)"); return 1; } + + ioctl(fdc, CIOCFSESSION, &sess.ses); + total+=chunksize; } while(must_finish==0); gettimeofday(&end, NULL); @@ -192,8 +212,6 @@ int encrypt_data_ncr_direct(int cfd, int algo, int chunksize) int main(void) { int fd, i, fdc = -1; - struct session_op sess; - char keybuf[32]; signal(SIGALRM, alarm_handler); @@ -207,17 +225,9 @@ int main(void) } fprintf(stderr, "Testing NULL cipher: \n"); - memset(&sess, 0, sizeof(sess)); - sess.cipher = CRYPTO_NULL; - sess.keylen = 0; - sess.key = (unsigned char *)keybuf; - if (ioctl(fdc, CIOCGSESSION, &sess)) { - perror("ioctl(CIOCGSESSION)"); - return 1; - } for (i = 256; i <= (64 * 1024); i *= 2) { - if (encrypt_data(&sess, fdc, i)) + if (encrypt_data(CRYPTO_NULL, fdc, i)) break; } @@ -227,20 +237,10 @@ int main(void) break; } - fprintf(stderr, "\nTesting AES-128-CBC cipher: \n"); - memset(&sess, 0, sizeof(sess)); - sess.cipher = CRYPTO_AES_CBC; - sess.keylen = 16; - memset(keybuf, 0x42, 16); - sess.key = (unsigned char *)keybuf; - if (ioctl(fdc, CIOCGSESSION, &sess)) { - perror("ioctl(CIOCGSESSION)"); - return 1; - } for (i = 256; i <= (64 * 1024); i *= 2) { - if (encrypt_data(&sess, fdc, i)) + if (encrypt_data(CRYPTO_AES_CBC, fdc, i)) break; } -- cgit From 014124ef6c43f2eadbf07318c03691c5305b6183 Mon Sep 17 00:00:00 2001 From: Miloslav Trmač Date: Tue, 17 Aug 2010 20:11:44 +0200 Subject: Drop unnecessary "file *" argument to ncr_ioctl() --- cryptodev_main.c | 2 +- ncr-int.h | 3 +-- ncr.c | 3 +-- 3 files changed, 3 insertions(+), 5 deletions(-) diff --git a/cryptodev_main.c b/cryptodev_main.c index a056b447731..da75672615a 100644 --- a/cryptodev_main.c +++ b/cryptodev_main.c @@ -828,7 +828,7 @@ cryptodev_ioctl(struct inode *inode, struct file *filp, return 0; default: - return ncr_ioctl(pcr->ncr, filp, cmd, arg_); + return ncr_ioctl(pcr->ncr, cmd, arg_); } } diff --git a/ncr-int.h b/ncr-int.h index 4694cdae054..53df9dfccaa 100644 --- a/ncr-int.h +++ b/ncr-int.h @@ -104,8 +104,7 @@ struct ncr_lists { void* ncr_init_lists(void); void ncr_deinit_lists(struct ncr_lists *lst); -int ncr_ioctl(struct ncr_lists*, struct file *filp, - unsigned int cmd, unsigned long arg); +int ncr_ioctl(struct ncr_lists *lst, unsigned int cmd, unsigned long arg); /* key derivation */ int ncr_key_derive(struct ncr_lists *lst, void __user* arg); diff --git a/ncr.c b/ncr.c index 86c8c7ad8ad..81e3fa32cef 100644 --- a/ncr.c +++ b/ncr.c @@ -117,8 +117,7 @@ struct ncr_master_key_st st; } int -ncr_ioctl(struct ncr_lists* lst, struct file *filp, - unsigned int cmd, unsigned long arg_) +ncr_ioctl(struct ncr_lists *lst, unsigned int cmd, unsigned long arg_) { void __user *arg = (void __user *)arg_; -- cgit From 9d84f5fe384751085e07ed60b634359a0a3b9370 Mon Sep 17 00:00:00 2001 From: Miloslav Trmač Date: Fri, 6 Aug 2010 02:51:46 +0200 Subject: Support IV size as large as does (removing the last dependency on in the process). --- cryptodev_int.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/cryptodev_int.h b/cryptodev_int.h index b4059febbb0..a113ba0fd8b 100644 --- a/cryptodev_int.h +++ b/cryptodev_int.h @@ -12,6 +12,7 @@ #include #include #include +#include #define PFX "cryptodev: " #define dprintk(level,severity,format,a...) \ @@ -45,7 +46,7 @@ struct cipher_data struct crypto_ablkcipher* s; struct cryptodev_result *result; struct ablkcipher_request *request; - uint8_t iv[EALG_MAX_BLOCK_LEN]; + uint8_t iv[NCR_CIPHER_MAX_BLOCK_LEN]; } async; }; -- cgit From 6ac025f801eaaf1aec4f652b951424522ec00686 Mon Sep 17 00:00:00 2001 From: Miloslav Trmač Date: Fri, 30 Jul 2010 23:46:52 +0200 Subject: Drop Also drop implementation of its ioctls, examples, openssl patch. --- .gitignore | 2 - Makefile | 3 +- cryptodev.h | 154 ----- cryptodev_cipher.c | 1 - cryptodev_int.h | 38 -- cryptodev_main.c | 825 +-------------------------- examples/Makefile | 12 +- examples/cipher.c | 230 -------- examples/hmac.c | 210 ------- examples/speed.c | 95 +-- extras/openssl-0.9.8k-cryptodev-linux.diff | 74 --- extras/openssl-0.9.8l-cryptodev-aes256.patch | 112 ---- ncr-dh.c | 1 - ncr-key-storage.c | 1 - ncr-key-wrap.c | 1 - ncr-key.c | 1 - ncr-limits.c | 1 - ncr-pk.c | 1 - ncr-sessions.c | 1 - ncr.c | 1 - 20 files changed, 22 insertions(+), 1742 deletions(-) delete mode 100644 cryptodev.h delete mode 100644 examples/cipher.c delete mode 100644 examples/hmac.c delete mode 100644 extras/openssl-0.9.8k-cryptodev-linux.diff delete mode 100644 extras/openssl-0.9.8l-cryptodev-aes256.patch diff --git a/.gitignore b/.gitignore index 4379d92e956..46c85a4058e 100644 --- a/.gitignore +++ b/.gitignore @@ -7,8 +7,6 @@ Module.symvers *.o *.mod.c modules.order -examples/cipher -examples/hmac examples/ncr examples/pk examples/speed diff --git a/Makefile b/Makefile index 0e3354053d3..093f777d25d 100644 --- a/Makefile +++ b/Makefile @@ -80,8 +80,7 @@ build: install: $(MAKE) -C $(KERNEL_DIR) SUBDIRS=`pwd` modules_install - @echo "Installing cryptodev.h in /usr/include/crypto ..." - @install -D cryptodev.h /usr/include/crypto/cryptodev.h + @echo "Installing ncr.h in /usr/include/crypto ..." @install -D ncr.h /usr/include/crypto/ncr.h clean: diff --git a/cryptodev.h b/cryptodev.h deleted file mode 100644 index 4a546b88d2d..00000000000 --- a/cryptodev.h +++ /dev/null @@ -1,154 +0,0 @@ -/* This is a source compatible implementation with the original API of - * cryptodev by Angelos D. Keromytis, found at openbsd cryptodev.h. - * Placed under public domain */ - -#ifndef L_CRYPTODEV_H -#define L_CRYPTODEV_H - -#include -#ifndef __KERNEL__ -#define __user -#endif - -/* API extensions for linux */ -#define CRYPTO_HMAC_MAX_KEY_LEN 512 -#define CRYPTO_CIPHER_MAX_KEY_LEN 64 - -/* All the supported algorithms - */ -typedef enum { - CRYPTO_DES_CBC=1, - CRYPTO_3DES_CBC=2, - CRYPTO_BLF_CBC=3, - CRYPTO_CAST_CBC=4, - CRYPTO_SKIPJACK_CBC=5, - CRYPTO_MD5_HMAC=6, - CRYPTO_SHA1_HMAC=7, - CRYPTO_RIPEMD160_HMAC=8, - CRYPTO_MD5_KPDK=9, - CRYPTO_SHA1_KPDK=10, - CRYPTO_RIJNDAEL128_CBC=11, - CRYPTO_AES_CBC=CRYPTO_RIJNDAEL128_CBC, - CRYPTO_ARC4=12, - CRYPTO_MD5=13, - CRYPTO_SHA1=14, - CRYPTO_DEFLATE_COMP=15, - CRYPTO_NULL=16, - CRYPTO_LZS_COMP=17, - CRYPTO_SHA2_256_HMAC=18, - CRYPTO_SHA2_384_HMAC=19, - CRYPTO_SHA2_512_HMAC=20, - CRYPTO_AES_CTR=21, - CRYPTO_AES_XTS=22, - - CRYPTO_CAMELLIA_CBC=101, - CRYPTO_RIPEMD160, - CRYPTO_SHA2_256, - CRYPTO_SHA2_384, - CRYPTO_SHA2_512, - CRYPTO_ALGORITHM_ALL, /* Keep updated - see below */ -} cryptodev_crypto_op_t; -#define CRYPTO_ALGORITHM_MAX (CRYPTO_ALGORITHM_ALL - 1) - -/* Values for ciphers */ -#define DES_BLOCK_LEN 8 -#define DES3_BLOCK_LEN 8 -#define RIJNDAEL128_BLOCK_LEN 16 -#define AES_BLOCK_LEN RIJNDAEL128_BLOCK_LEN -#define CAMELLIA_BLOCK_LEN -#define BLOWFISH_BLOCK_LEN 8 -#define SKIPJACK_BLOCK_LEN 8 -#define CAST128_BLOCK_LEN 8 - -/* the maximum of the above */ -#define EALG_MAX_BLOCK_LEN 16 - -/* Values for hashes/MAC */ -#define AALG_MAX_RESULT_LEN 64 - -/* input of CIOCGSESSION */ -struct session_op { - /* Specify either cipher or mac - */ - __u32 cipher; /* cryptodev_crypto_op_t */ - __u32 mac; /* cryptodev_crypto_op_t */ - - __u32 keylen; - __u8 __user *key; - __u32 mackeylen; - __u8 __user *mackey; - - __u32 ses; /* session identifier */ -}; - -#define COP_ENCRYPT 0 -#define COP_DECRYPT 1 - -/* input of CIOCCRYPT */ - struct crypt_op { - __u32 ses; /* session identifier */ - __u16 op; /* COP_ENCRYPT or COP_DECRYPT */ - __u16 flags; /* no usage so far, use 0 */ - __u32 len; /* length of source data */ - __u8 __user *src; /* source data */ - __u8 __user *dst; /* pointer to output data */ - __u8 __user *mac; /* pointer to output data for hash/MAC operations */ - __u8 __user *iv; /* initialization vector for encryption operations */ -}; - -/* Stuff for bignum arithmetic and public key - * cryptography - not supported yet by linux - * cryptodev. - */ - -#define CRYPTO_ALG_FLAG_SUPPORTED 1 -#define CRYPTO_ALG_FLAG_RNG_ENABLE 2 -#define CRYPTO_ALG_FLAG_DSA_SHA 4 - -struct crparam { - __u8* crp_p; - __u32 crp_nbits; -}; - -#define CRK_MAXPARAM 8 - -/* input of CIOCKEY */ -struct crypt_kop { - __u32 crk_op; /* cryptodev_crk_ot_t */ - __u32 crk_status; - __u16 crk_iparams; - __u16 crk_oparams; - __u32 crk_pad1; - struct crparam crk_param[CRK_MAXPARAM]; -}; - -typedef enum { - CRK_MOD_EXP=0, - CRK_MOD_EXP_CRT=1, - CRK_DSA_SIGN=2, - CRK_DSA_VERIFY=3, - CRK_DH_COMPUTE_KEY=4, - CRK_ALGORITHM_ALL -} cryptodev_crk_op_t; - -#define CRK_ALGORITHM_MAX CRK_ALGORITHM_ALL-1 - -/* features to be queried with CIOCASYMFEAT ioctl - */ -#define CRF_MOD_EXP (1 << CRK_MOD_EXP) -#define CRF_MOD_EXP_CRT (1 << CRK_MOD_EXP_CRT) -#define CRF_DSA_SIGN (1 << CRK_DSA_SIGN) -#define CRF_DSA_VERIFY (1 << CRK_DSA_VERIFY) -#define CRF_DH_COMPUTE_KEY (1 << CRK_DH_COMPUTE_KEY) - - -/* ioctl's. Compatible with old linux cryptodev.h - */ -#define CRIOGET _IOWR('c', 101, __u32) -#define CIOCGSESSION _IOWR('c', 102, struct session_op) -#define CIOCFSESSION _IOW('c', 103, __u32) -#define CIOCCRYPT _IOWR('c', 104, struct crypt_op) -#define CIOCKEY _IOWR('c', 105, struct crypt_kop) -#define CIOCASYMFEAT _IOR('c', 106, __u32) - -#endif /* L_CRYPTODEV_H */ diff --git a/cryptodev_cipher.c b/cryptodev_cipher.c index 832202789b6..4e74fcc39d0 100644 --- a/cryptodev_cipher.c +++ b/cryptodev_cipher.c @@ -31,7 +31,6 @@ #include #include #include -#include "cryptodev.h" #include "cryptodev_int.h" diff --git a/cryptodev_int.h b/cryptodev_int.h index a113ba0fd8b..e38150545b0 100644 --- a/cryptodev_int.h +++ b/cryptodev_int.h @@ -11,7 +11,6 @@ #include #include #include -#include #include #define PFX "cryptodev: " @@ -80,41 +79,4 @@ int cryptodev_hash_reset( struct hash_data* hdata); void cryptodev_hash_deinit(struct hash_data* hdata); int cryptodev_hash_init( struct hash_data* hdata, const char* alg_name, int hmac_mode, void* mackey, size_t mackeylen); -/* compatibility stuff */ -#ifdef CONFIG_COMPAT -#include - -/* input of CIOCGSESSION */ -struct compat_session_op { - /* Specify either cipher or mac - */ - uint32_t cipher; /* cryptodev_crypto_op_t */ - uint32_t mac; /* cryptodev_crypto_op_t */ - - uint32_t keylen; - compat_uptr_t key; /* pointer to key data */ - uint32_t mackeylen; - compat_uptr_t mackey; /* pointer to mac key data */ - - uint32_t ses; /* session identifier */ -}; - -/* input of CIOCCRYPT */ - struct compat_crypt_op { - uint32_t ses; /* session identifier */ - uint16_t op; /* COP_ENCRYPT or COP_DECRYPT */ - uint16_t flags; /* no usage so far, use 0 */ - uint32_t len; /* length of source data */ - compat_uptr_t src; /* source data */ - compat_uptr_t dst; /* pointer to output data */ - compat_uptr_t mac; /* pointer to output data for hash/MAC operations */ - compat_uptr_t iv; /* initialization vector for encryption operations */ -}; - -/* compat ioctls, defined for the above structs */ -#define COMPAT_CIOCGSESSION _IOWR('c', 102, struct compat_session_op) -#define COMPAT_CIOCCRYPT _IOWR('c', 104, struct compat_crypt_op) - -#endif /* CONFIG_COMPAT */ - #endif /* CRYPTODEV_INT_H */ diff --git a/cryptodev_main.c b/cryptodev_main.c index a056b447731..f3f1f08012e 100644 --- a/cryptodev_main.c +++ b/cryptodev_main.c @@ -39,7 +39,6 @@ #include #include #include -#include "cryptodev.h" #include #include "cryptodev_int.h" #include "ncr-int.h" @@ -50,452 +49,13 @@ MODULE_AUTHOR("Nikos Mavrogiannopoulos "); MODULE_DESCRIPTION("CryptoDev driver"); MODULE_LICENSE("GPL"); -/* ====== Compile-time config ====== */ - -#define CRYPTODEV_STATS - /* ====== Module parameters ====== */ int cryptodev_verbosity = 0; module_param(cryptodev_verbosity, int, 0644); MODULE_PARM_DESC(cryptodev_verbosity, "0: normal, 1: verbose, 2: debug"); -#ifdef CRYPTODEV_STATS -static int enable_stats = 0; -module_param(enable_stats, int, 0644); -MODULE_PARM_DESC(enable_stats, "collect statictics about cryptodev usage"); -#endif - /* ====== CryptoAPI ====== */ -struct fcrypt { - struct list_head list; - struct semaphore sem; -}; - -struct crypt_priv { - void * ncr; - struct fcrypt fcrypt; -}; - -#define FILL_SG(sg,ptr,len) \ - do { \ - (sg)->page = virt_to_page(ptr); \ - (sg)->offset = offset_in_page(ptr); \ - (sg)->length = len; \ - (sg)->dma_address = 0; \ - } while (0) - -struct csession { - struct list_head entry; - struct semaphore sem; - struct cipher_data cdata; - struct hash_data hdata; - uint32_t sid; -#ifdef CRYPTODEV_STATS -#if ! ((COP_ENCRYPT < 2) && (COP_DECRYPT < 2)) -#error Struct csession.stat uses COP_{ENCRYPT,DECRYPT} as indices. Do something! -#endif - unsigned long long stat[2]; - size_t stat_max_size, stat_count; -#endif - int array_size; - struct page **pages; - struct scatterlist *sg; -}; - -/* Prepare session for future use. */ -static int -crypto_create_session(struct fcrypt *fcr, struct session_op *sop) -{ - struct csession *ses_new = NULL, *ses_ptr; - int ret = 0; - const char *alg_name=NULL; - const char *hash_name=NULL; - int hmac_mode = 1; - - /* Does the request make sense? */ - if (unlikely(!sop->cipher && !sop->mac)) { - dprintk(1,KERN_DEBUG,"Both 'cipher' and 'mac' unset.\n"); - return -EINVAL; - } - - switch (sop->cipher) { - case 0: - break; - case CRYPTO_DES_CBC: - alg_name = "cbc(des)"; - break; - case CRYPTO_3DES_CBC: - alg_name = "cbc(des3_ede)"; - break; - case CRYPTO_BLF_CBC: - alg_name = "cbc(blowfish)"; - break; - case CRYPTO_AES_CBC: - alg_name = "cbc(aes)"; - break; - case CRYPTO_CAMELLIA_CBC: - alg_name = "cbc(camelia)"; - break; - case CRYPTO_AES_CTR: - alg_name = "ctr(aes)"; - break; - case CRYPTO_NULL: - alg_name = "ecb(cipher_null)"; - break; - default: - dprintk(1,KERN_DEBUG,"%s: bad cipher: %d\n", __func__, sop->cipher); - return -EINVAL; - } - - switch (sop->mac) { - case 0: - break; - case CRYPTO_MD5_HMAC: - hash_name = "hmac(md5)"; - break; - case CRYPTO_RIPEMD160_HMAC: - hash_name = "hmac(rmd160)"; - break; - case CRYPTO_SHA1_HMAC: - hash_name = "hmac(sha1)"; - break; - case CRYPTO_SHA2_256_HMAC: - hash_name = "hmac(sha256)"; - break; - case CRYPTO_SHA2_384_HMAC: - hash_name = "hmac(sha384)"; - break; - case CRYPTO_SHA2_512_HMAC: - hash_name = "hmac(sha512)"; - break; - - /* non-hmac cases */ - case CRYPTO_MD5: - hash_name = "md5"; - hmac_mode = 0; - break; - case CRYPTO_RIPEMD160: - hash_name = "rmd160"; - hmac_mode = 0; - break; - case CRYPTO_SHA1: - hash_name = "sha1"; - hmac_mode = 0; - break; - case CRYPTO_SHA2_256: - hash_name = "sha256"; - hmac_mode = 0; - break; - case CRYPTO_SHA2_384: - hash_name = "sha384"; - hmac_mode = 0; - break; - case CRYPTO_SHA2_512: - hash_name = "sha512"; - hmac_mode = 0; - break; - - default: - dprintk(1,KERN_DEBUG,"%s: bad mac: %d\n", __func__, sop->mac); - return -EINVAL; - } - - /* Create a session and put it to the list. */ - ses_new = kzalloc(sizeof(*ses_new), GFP_KERNEL); - if(!ses_new) { - return -ENOMEM; - } - - /* Set-up crypto transform. */ - if (alg_name) { - uint8_t keyp[CRYPTO_CIPHER_MAX_KEY_LEN]; - - if (unlikely(sop->keylen > CRYPTO_CIPHER_MAX_KEY_LEN)) { - dprintk(1,KERN_DEBUG,"Setting key failed for %s-%zu.\n", - alg_name, (size_t)sop->keylen*8); - ret = -EINVAL; - goto error_cipher; - } - - if (unlikely(copy_from_user(keyp, sop->key, sop->keylen))) { - ret = -EFAULT; - goto error_cipher; - } - - ret = cryptodev_cipher_init(&ses_new->cdata, alg_name, keyp, sop->keylen); - if (ret < 0) { - dprintk(1,KERN_DEBUG,"%s: Failed to load cipher for %s\n", __func__, - alg_name); - ret = -EINVAL; - goto error_cipher; - } - } - - if (hash_name) { - uint8_t keyp[CRYPTO_HMAC_MAX_KEY_LEN]; - - if (unlikely(sop->mackeylen > CRYPTO_HMAC_MAX_KEY_LEN)) { - dprintk(1,KERN_DEBUG,"Setting key failed for %s-%zu.\n", - alg_name, (size_t)sop->mackeylen*8); - ret = -EINVAL; - goto error_hash; - } - - if (unlikely(copy_from_user(keyp, sop->mackey, - sop->mackeylen))) { - ret = -EFAULT; - goto error_hash; - } - - ret = cryptodev_hash_init(&ses_new->hdata, hash_name, hmac_mode, keyp, sop->mackeylen); - if (ret != 0) { - dprintk(1,KERN_DEBUG,"%s: Failed to load hash for %s\n", __func__, - hash_name); - ret = -EINVAL; - goto error_hash; - } - } - - ses_new->array_size = DEFAULT_PREALLOC_PAGES; - dprintk(2, KERN_DEBUG, "%s: preallocating for %d user pages\n", - __func__, ses_new->array_size); - ses_new->pages = kzalloc(ses_new->array_size * - sizeof(struct page *), GFP_KERNEL); - ses_new->sg = kzalloc(ses_new->array_size * - sizeof(struct scatterlist), GFP_KERNEL); - if (ses_new->sg == NULL || ses_new->pages == NULL) { - dprintk(0,KERN_DEBUG,"Memory error\n"); - ret = -ENOMEM; - goto error_hash; - } - - /* put the new session to the list */ - get_random_bytes(&ses_new->sid, sizeof(ses_new->sid)); - init_MUTEX(&ses_new->sem); - - down(&fcr->sem); -restart: - list_for_each_entry(ses_ptr, &fcr->list, entry) { - /* Check for duplicate SID */ - if (unlikely(ses_new->sid == ses_ptr->sid)) { - get_random_bytes(&ses_new->sid, sizeof(ses_new->sid)); - /* Unless we have a broken RNG this - shouldn't loop forever... ;-) */ - goto restart; - } - } - - list_add(&ses_new->entry, &fcr->list); - up(&fcr->sem); - - /* Fill in some values for the user. */ - sop->ses = ses_new->sid; - - return 0; - -error_hash: - cryptodev_cipher_deinit( &ses_new->cdata); - kfree(ses_new->sg); - kfree(ses_new->pages); -error_cipher: - if (ses_new) kfree(ses_new); - - return ret; - -} - -/* Everything that needs to be done when remowing a session. */ -static inline void -crypto_destroy_session(struct csession *ses_ptr) -{ - if(down_trylock(&ses_ptr->sem)) { - dprintk(2, KERN_DEBUG, "Waiting for semaphore of sid=0x%08X\n", - ses_ptr->sid); - down(&ses_ptr->sem); - } - dprintk(2, KERN_DEBUG, "Removed session 0x%08X\n", ses_ptr->sid); -#if defined(CRYPTODEV_STATS) - if(enable_stats) - dprintk(2, KERN_DEBUG, - "Usage in Bytes: enc=%llu, dec=%llu, max=%zu, avg=%lu, cnt=%zu\n", - ses_ptr->stat[COP_ENCRYPT], ses_ptr->stat[COP_DECRYPT], - ses_ptr->stat_max_size, ses_ptr->stat_count > 0 - ? ((unsigned long)(ses_ptr->stat[COP_ENCRYPT]+ - ses_ptr->stat[COP_DECRYPT]) / - ses_ptr->stat_count) : 0, - ses_ptr->stat_count); -#endif - cryptodev_cipher_deinit(&ses_ptr->cdata); - cryptodev_hash_deinit(&ses_ptr->hdata); - dprintk(2, KERN_DEBUG, "%s: freeing space for %d user pages\n", - __func__, ses_ptr->array_size); - kfree(ses_ptr->pages); - kfree(ses_ptr->sg); - - up(&ses_ptr->sem); - kfree(ses_ptr); -} - -/* Look up a session by ID and remove. */ -static int -crypto_finish_session(struct fcrypt *fcr, uint32_t sid) -{ - struct csession *tmp, *ses_ptr; - struct list_head *head; - int ret = 0; - - down(&fcr->sem); - head = &fcr->list; - list_for_each_entry_safe(ses_ptr, tmp, head, entry) { - if(ses_ptr->sid == sid) { - list_del(&ses_ptr->entry); - crypto_destroy_session(ses_ptr); - break; - } - } - - if (unlikely(!ses_ptr)) { - dprintk(1, KERN_ERR, "Session with sid=0x%08X not found!\n", sid); - ret = -ENOENT; - } - up(&fcr->sem); - - return ret; -} - -/* Remove all sessions when closing the file */ -static int -crypto_finish_all_sessions(struct fcrypt *fcr) -{ - struct csession *tmp, *ses_ptr; - struct list_head *head; - - down(&fcr->sem); - - head = &fcr->list; - list_for_each_entry_safe(ses_ptr, tmp, head, entry) { - list_del(&ses_ptr->entry); - crypto_destroy_session(ses_ptr); - } - up(&fcr->sem); - - return 0; -} - -/* Look up session by session ID. The returned session is locked. */ -static struct csession * -crypto_get_session_by_sid(struct fcrypt *fcr, uint32_t sid) -{ - struct csession *ses_ptr; - - down(&fcr->sem); - list_for_each_entry(ses_ptr, &fcr->list, entry) { - if(ses_ptr->sid == sid) { - down(&ses_ptr->sem); - break; - } - } - up(&fcr->sem); - - return ses_ptr; -} - -static int -hash_n_crypt(struct csession *ses_ptr, struct crypt_op *cop, - struct scatterlist *src_sg, struct scatterlist *dst_sg, uint32_t len) -{ - int ret; - - /* Always hash before encryption and after decryption. Maybe - * we should introduce a flag to switch... TBD later on. - */ - if (cop->op == COP_ENCRYPT) { - if (ses_ptr->hdata.init != 0) { - ret = cryptodev_hash_update(&ses_ptr->hdata, src_sg, len); - if (unlikely(ret)) - goto out_err; - } - if (ses_ptr->cdata.init != 0) { - ret = cryptodev_cipher_encrypt( &ses_ptr->cdata, src_sg, dst_sg, len); - - if (unlikely(ret)) - goto out_err; - } - } else { - if (ses_ptr->cdata.init != 0) { - ret = cryptodev_cipher_decrypt( &ses_ptr->cdata, src_sg, dst_sg, len); - - if (unlikely(ret)) - goto out_err; - } - - if (ses_ptr->hdata.init != 0) { - ret = cryptodev_hash_update(&ses_ptr->hdata, dst_sg, len); - if (unlikely(ret)) - goto out_err; - } - } - return 0; -out_err: - dprintk(0, KERN_ERR, "CryptoAPI failure: %d\n",ret); - return ret; -} - -/* This is the main crypto function - feed it with plaintext - and get a ciphertext (or vice versa :-) */ -static int -__crypto_run_std(struct csession *ses_ptr, struct crypt_op *cop) -{ - char *data; - char __user *src, *dst; - struct scatterlist sg; - size_t nbytes, bufsize; - int ret = 0; - - nbytes = cop->len; - data = (char*)__get_free_page(GFP_KERNEL); - - if (unlikely(!data)) { - return -ENOMEM; - } - bufsize = PAGE_SIZE < nbytes ? PAGE_SIZE : nbytes; - - src = cop->src; - dst = cop->dst; - - while(nbytes > 0) { - size_t current_len = nbytes > bufsize ? bufsize : nbytes; - - if (unlikely(copy_from_user(data, src, current_len))) { - ret = -EFAULT; - break; - } - - sg_init_one(&sg, data, current_len); - - ret = hash_n_crypt(ses_ptr, cop, &sg, &sg, current_len); - - if (unlikely(ret)) - break; - - if (ses_ptr->cdata.init != 0) { - if (unlikely(copy_to_user(dst, data, current_len))) { - ret = -EFAULT; - break; - } - } - - dst += current_len; - nbytes -= current_len; - src += current_len; - } - - free_page((unsigned long)data); - return ret; -} - -#ifndef DISABLE_ZCOPY void release_user_pages(struct page **pg, int pagecount) { @@ -538,412 +98,59 @@ int __get_userbuf(uint8_t __user *addr, uint32_t len, int write, return 0; } -/* make cop->src and cop->dst available in scatterlists */ -static int get_userbuf(struct csession *ses, - struct crypt_op *cop, struct scatterlist **src_sg, - struct scatterlist **dst_sg, int *tot_pages) -{ - int src_pagecount, dst_pagecount = 0, pagecount, write_src = 1; - - if (cop->src == NULL) { - return -EINVAL; - } - - src_pagecount = PAGECOUNT(cop->src, cop->len); - if (!ses->cdata.init) { /* hashing only */ - write_src = 0; - } else if (cop->src != cop->dst) { /* non-in-situ transformation */ - if (cop->dst == NULL) { - return -EINVAL; - } - dst_pagecount = PAGECOUNT(cop->dst, cop->len); - write_src = 0; - } - (*tot_pages) = pagecount = src_pagecount + dst_pagecount; - - if (pagecount > ses->array_size) { - struct scatterlist *sg; - struct page **pages; - int array_size; - - for (array_size = ses->array_size; array_size < pagecount; - array_size *= 2) - ; - - dprintk(2, KERN_DEBUG, "%s: reallocating to %d elements\n", - __func__, array_size); - pages = krealloc(ses->pages, array_size * sizeof(struct page *), - GFP_KERNEL); - if (pages == NULL) - return -ENOMEM; - ses->pages = pages; - sg = krealloc(ses->sg, array_size * sizeof(struct scatterlist), - GFP_KERNEL); - if (sg == NULL) - return -ENOMEM; - ses->sg = sg; - ses->array_size = array_size; - } - - if (__get_userbuf(cop->src, cop->len, write_src, - src_pagecount, ses->pages, ses->sg)) { - dprintk(1, KERN_ERR, "failed to get user pages for data input\n"); - return -EINVAL; - } - (*src_sg) = (*dst_sg) = ses->sg; - - if (dst_pagecount) { - (*dst_sg) = ses->sg + src_pagecount; - - if (__get_userbuf(cop->dst, cop->len, 1, dst_pagecount, - ses->pages + src_pagecount, *dst_sg)) { - dprintk(1, KERN_ERR, "failed to get user pages for data output\n"); - release_user_pages(ses->pages, src_pagecount); - return -EINVAL; - } - } - return 0; -} - -/* This is the main crypto function - zero-copy edition */ -static int -__crypto_run_zc(struct csession *ses_ptr, struct crypt_op *cop) -{ - struct scatterlist *src_sg, *dst_sg; - int ret = 0, pagecount; - - ret = get_userbuf(ses_ptr, cop, &src_sg, &dst_sg, &pagecount); - if (unlikely(ret)) { - dprintk(1, KERN_ERR, "Error getting user pages. Falling back to non zero copy.\n"); - return __crypto_run_std(ses_ptr, cop); - } - - ret = hash_n_crypt(ses_ptr, cop, src_sg, dst_sg, cop->len); - - release_user_pages(ses_ptr->pages, pagecount); - return ret; -} - -#endif /* DISABLE_ZCOPY */ - -static int crypto_run(struct fcrypt *fcr, struct crypt_op *cop) -{ - struct csession *ses_ptr; - uint8_t hash_output[AALG_MAX_RESULT_LEN]; - int ret; - - if (unlikely(cop->op != COP_ENCRYPT && cop->op != COP_DECRYPT)) { - dprintk(1, KERN_DEBUG, "invalid operation op=%u\n", cop->op); - return -EINVAL; - } - - /* this also enters ses_ptr->sem */ - ses_ptr = crypto_get_session_by_sid(fcr, cop->ses); - if (unlikely(!ses_ptr)) { - dprintk(1, KERN_ERR, "invalid session ID=0x%08X\n", cop->ses); - return -EINVAL; - } - - if (ses_ptr->hdata.init != 0) { - ret = cryptodev_hash_reset(&ses_ptr->hdata); - if (unlikely(ret)) { - dprintk(1, KERN_ERR, - "error in cryptodev_hash_reset()\n"); - goto out_unlock; - } - } - - if (ses_ptr->cdata.init != 0) { - int blocksize = ses_ptr->cdata.blocksize; - - if (unlikely(cop->len % blocksize)) { - dprintk(1, KERN_ERR, - "data size (%u) isn't a multiple of block size (%u)\n", - cop->len, blocksize); - ret = -EINVAL; - goto out_unlock; - } - - if (cop->iv) { - uint8_t iv[EALG_MAX_BLOCK_LEN]; - - ret = copy_from_user(iv, cop->iv, min( (int)sizeof(iv), (ses_ptr->cdata.ivsize))); - if (unlikely(ret)) { - dprintk(1, KERN_ERR, "error copying IV (%d bytes)\n", min( (int)sizeof(iv), (ses_ptr->cdata.ivsize))); - ret = -EFAULT; - goto out_unlock; - } - - cryptodev_cipher_set_iv(&ses_ptr->cdata, iv, ses_ptr->cdata.ivsize); - } - } - -#ifdef DISABLE_ZCOPY - ret = __crypto_run_std(ses_ptr, cop); -#else /* normal */ - ret = __crypto_run_zc(ses_ptr, cop); -#endif - if (unlikely(ret)) - goto out_unlock; - - if (ses_ptr->hdata.init != 0) { - ret = cryptodev_hash_final(&ses_ptr->hdata, hash_output); - if (unlikely(ret)) { - dprintk(0, KERN_ERR, "CryptoAPI failure: %d\n",ret); - goto out_unlock; - } - - if (unlikely(copy_to_user(cop->mac, hash_output, ses_ptr->hdata.digestsize))) { - ret = -EFAULT; - goto out_unlock; - } - } - -#if defined(CRYPTODEV_STATS) - if (enable_stats) { - /* this is safe - we check cop->op at the function entry */ - ses_ptr->stat[cop->op] += cop->len; - if (ses_ptr->stat_max_size < cop->len) - ses_ptr->stat_max_size = cop->len; - ses_ptr->stat_count++; - } -#endif - -out_unlock: - up(&ses_ptr->sem); - return ret; -} - - /* ====== /dev/crypto ====== */ static int cryptodev_open(struct inode *inode, struct file *filp) { - struct crypt_priv *pcr; + void *ncr; - pcr = kmalloc(sizeof(*pcr), GFP_KERNEL); - if(!pcr) - return -ENOMEM; - - memset(pcr, 0, sizeof(*pcr)); - init_MUTEX(&pcr->fcrypt.sem); - INIT_LIST_HEAD(&pcr->fcrypt.list); - - pcr->ncr = ncr_init_lists(); - if (pcr->ncr == NULL) { - kfree(pcr); + ncr = ncr_init_lists(); + if (ncr == NULL) { return -ENOMEM; } - filp->private_data = pcr; + filp->private_data = ncr; return 0; } static int cryptodev_release(struct inode *inode, struct file *filp) { - struct crypt_priv *pcr = filp->private_data; + void *ncr = filp->private_data; - if(pcr) { - crypto_finish_all_sessions(&pcr->fcrypt); - ncr_deinit_lists(pcr->ncr); - kfree(pcr); + if (ncr) { + ncr_deinit_lists(ncr); filp->private_data = NULL; } return 0; } -static int -clonefd(struct file *filp) -{ - int ret; - ret = get_unused_fd(); - if (ret >= 0) { - get_file(filp); - fd_install(ret, filp); - } - - return ret; -} - static int cryptodev_ioctl(struct inode *inode, struct file *filp, - unsigned int cmd, unsigned long arg_) + unsigned int cmd, unsigned long arg) { - void __user *arg = (void __user *)arg_; - int __user *p = arg; - struct session_op sop; - struct crypt_op cop; - struct crypt_priv *pcr = filp->private_data; - struct fcrypt * fcr; - uint32_t ses; - int ret, fd; - - if (unlikely(!pcr)) - BUG(); + void *ncr = filp->private_data; - fcr = &pcr->fcrypt; + if (unlikely(!ncr)) + BUG(); - switch (cmd) { - case CIOCASYMFEAT: - return put_user(0, p); - case CRIOGET: - fd = clonefd(filp); - ret = put_user(fd, p); - if (unlikely(ret)) { - sys_close(fd); - return ret; - } - return ret; - case CIOCGSESSION: - if (unlikely(copy_from_user(&sop, arg, sizeof(sop)))) - return -EFAULT; - - ret = crypto_create_session(fcr, &sop); - if (unlikely(ret)) - return ret; - ret = copy_to_user(arg, &sop, sizeof(sop)); - if (unlikely(ret)) { - crypto_finish_session(fcr, sop.ses); - return -EFAULT; - } - return ret; - case CIOCFSESSION: - ret = get_user(ses, (uint32_t __user *)arg); - if (unlikely(ret)) - return ret; - ret = crypto_finish_session(fcr, ses); - return ret; - case CIOCCRYPT: - if (unlikely(copy_from_user(&cop, arg, sizeof(cop)))) - return -EFAULT; - - ret = crypto_run(fcr, &cop); - if (unlikely(ret)) - return ret; - if (unlikely(copy_to_user(arg, &cop, sizeof(cop)))) - return -EFAULT; - return 0; - - default: - return ncr_ioctl(pcr->ncr, filp, cmd, arg_); - } + return ncr_ioctl(ncr, filp, cmd, arg); } /* compatibility code for 32bit userlands */ #ifdef CONFIG_COMPAT -static inline void -compat_to_session_op(struct compat_session_op *compat, struct session_op *sop) -{ - sop->cipher = compat->cipher; - sop->mac = compat->mac; - sop->keylen = compat->keylen; - - sop->key = compat_ptr(compat->key); - sop->mackeylen = compat->mackeylen; - sop->mackey = compat_ptr(compat->mackey); - sop->ses = compat->ses; -} - -static inline void -session_op_to_compat(struct session_op *sop, struct compat_session_op *compat) -{ - compat->cipher = sop->cipher; - compat->mac = sop->mac; - compat->keylen = sop->keylen; - - compat->key = ptr_to_compat(sop->key); - compat->mackeylen = sop->mackeylen; - compat->mackey = ptr_to_compat(sop->mackey); - compat->ses = sop->ses; -} - -static inline void -compat_to_crypt_op(struct compat_crypt_op *compat, struct crypt_op *cop) -{ - cop->ses = compat->ses; - cop->op = compat->op; - cop->flags = compat->flags; - cop->len = compat->len; - - cop->src = compat_ptr(compat->src); - cop->dst = compat_ptr(compat->dst); - cop->mac = compat_ptr(compat->mac); - cop->iv = compat_ptr(compat->iv); -} - -static inline void -crypt_op_to_compat(struct crypt_op *cop, struct compat_crypt_op *compat) -{ - compat->ses = cop->ses; - compat->op = cop->op; - compat->flags = cop->flags; - compat->len = cop->len; - - compat->src = ptr_to_compat(cop->src); - compat->dst = ptr_to_compat(cop->dst); - compat->mac = ptr_to_compat(cop->mac); - compat->iv = ptr_to_compat(cop->iv); -} - static long -cryptodev_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg_) +cryptodev_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { - void __user *arg = (void __user *)arg_; - struct fcrypt *fcr = file->private_data; - struct session_op sop; - struct compat_session_op compat_sop; - struct crypt_op cop; - struct compat_crypt_op compat_cop; - int ret; - - if (unlikely(!fcr)) + void *ncr = file->private_data; + + if (unlikely(!ncr)) BUG(); switch (cmd) { - case CIOCASYMFEAT: - case CRIOGET: - case CIOCFSESSION: - return cryptodev_ioctl(NULL, file, cmd, arg_); - - case COMPAT_CIOCGSESSION: - if (unlikely(copy_from_user(&compat_sop, arg, - sizeof(compat_sop)))) - return -EFAULT; - compat_to_session_op(&compat_sop, &sop); - - ret = crypto_create_session(fcr, &sop); - if (unlikely(ret)) - return ret; - - session_op_to_compat(&sop, &compat_sop); - ret = copy_to_user(arg, &compat_sop, sizeof(compat_sop)); - if (unlikely(ret)) { - crypto_finish_session(fcr, sop.ses); - return -EFAULT; - } - return ret; - - case COMPAT_CIOCCRYPT: - if (unlikely(copy_from_user(&compat_cop, arg, - sizeof(compat_cop)))) - return -EFAULT; - - compat_to_crypt_op(&compat_cop, &cop); - - ret = crypto_run(fcr, &cop); - if (unlikely(ret)) - return ret; - - crypt_op_to_compat(&cop, &compat_cop); - if (unlikely(copy_to_user(arg, &compat_cop, - sizeof(compat_cop)))) - return -EFAULT; - return 0; - default: return -EINVAL; } diff --git a/examples/Makefile b/examples/Makefile index 100cc490600..d14908866bb 100644 --- a/examples/Makefile +++ b/examples/Makefile @@ -1,19 +1,13 @@ CC = gcc CFLAGS = -Wall -g -O2 -progs := cipher hmac ncr pk speed +progs := ncr pk speed all: $(progs) -cipher: cipher.c - $(CC) $(CFLAGS) $< -o $@ - speed: speed.c $(CC) $(CFLAGS) $< -o $@ -hmac: hmac.c - $(CC) $(CFLAGS) $< -o $@ - ncr: ncr.c $(CC) $(CFLAGS) $< -o $@ @@ -23,9 +17,7 @@ pk: pk.c check: $(progs) ./ncr ./pk - ./cipher - ./hmac ./speed clean: - rm -f *.o *~ hmac cipher ncr pk speed \ No newline at end of file + rm -f *.o *~ ncr pk speed diff --git a/examples/cipher.c b/examples/cipher.c deleted file mode 100644 index 52b4996f4a6..00000000000 --- a/examples/cipher.c +++ /dev/null @@ -1,230 +0,0 @@ -/* - * Demo on how to use /dev/crypto device for ciphering. - * - * Placed under public domain. - * - */ -#include -#include -#include -#include -#include - -#include -#include "../cryptodev.h" - -#define DATA_SIZE 4096 -#define BLOCK_SIZE 16 -#define KEY_SIZE 16 - -static int -test_crypto(int cfd) -{ - uint8_t plaintext[DATA_SIZE]; - uint8_t ciphertext[DATA_SIZE]; - uint8_t iv[BLOCK_SIZE]; - uint8_t key[KEY_SIZE]; - - struct session_op sess; - struct crypt_op cryp; - - memset(&sess, 0, sizeof(sess)); - memset(&cryp, 0, sizeof(cryp)); - - memset(plaintext, 0x15, sizeof(plaintext)); - memset(key, 0x33, sizeof(key)); - memset(iv, 0x03, sizeof(iv)); - - /* Get crypto session for AES128 */ - sess.cipher = CRYPTO_AES_CBC; - sess.keylen = KEY_SIZE; - sess.key = key; - if (ioctl(cfd, CIOCGSESSION, &sess)) { - perror("ioctl(CIOCGSESSION)"); - return 1; - } - - /* Encrypt data.in to data.encrypted */ - cryp.ses = sess.ses; - cryp.len = sizeof(plaintext); - cryp.src = plaintext; - cryp.dst = ciphertext; - cryp.iv = iv; - cryp.op = COP_ENCRYPT; - if (ioctl(cfd, CIOCCRYPT, &cryp)) { - perror("ioctl(CIOCCRYPT)"); - return 1; - } - - if (ioctl(cfd, CIOCGSESSION, &sess)) { - perror("ioctl(CIOCGSESSION)"); - return 1; - } - - /* Decrypt data.encrypted to data.decrypted */ - cryp.ses = sess.ses; - cryp.len = sizeof(plaintext); - cryp.src = ciphertext; - cryp.dst = ciphertext; - cryp.iv = iv; - cryp.op = COP_DECRYPT; - if (ioctl(cfd, CIOCCRYPT, &cryp)) { - perror("ioctl(CIOCCRYPT)"); - return 1; - } - - /* Verify the result */ - if (memcmp(plaintext, ciphertext, sizeof(plaintext)) != 0) { - fprintf(stderr, - "FAIL: Decrypted data are different from the input data.\n"); - return 1; - } else - printf("Test passed\n"); - - /* Finish crypto session */ - if (ioctl(cfd, CIOCFSESSION, &sess.ses)) { - perror("ioctl(CIOCFSESSION)"); - return 1; - } - - return 0; -} - -static int test_aes(int cfd) -{ - uint8_t plaintext1[BLOCK_SIZE]; - uint8_t ciphertext1[BLOCK_SIZE] = { 0xdf, 0x55, 0x6a, 0x33, 0x43, 0x8d, 0xb8, 0x7b, 0xc4, 0x1b, 0x17, 0x52, 0xc5, 0x5e, 0x5e, 0x49 }; - uint8_t iv1[BLOCK_SIZE]; - uint8_t key1[KEY_SIZE] = { 0xff, 0xff, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; - uint8_t plaintext2[BLOCK_SIZE] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc0, 0x00 }; - uint8_t ciphertext2[BLOCK_SIZE] = { 0xb7, 0x97, 0x2b, 0x39, 0x41, 0xc4, 0x4b, 0x90, 0xaf, 0xa7, 0xb2, 0x64, 0xbf, 0xba, 0x73, 0x87 }; - uint8_t iv2[BLOCK_SIZE]; - uint8_t key2[KEY_SIZE]; - - struct session_op sess; - struct crypt_op cryp; - - memset(&sess, 0, sizeof(sess)); - memset(&cryp, 0, sizeof(cryp)); - - memset(plaintext1, 0x0, sizeof(plaintext1)); - memset(iv1, 0x0, sizeof(iv1)); - - /* Get crypto session for AES128 */ - sess.cipher = CRYPTO_AES_CBC; - sess.keylen = KEY_SIZE; - sess.key = key1; - if (ioctl(cfd, CIOCGSESSION, &sess)) { - perror("ioctl(CIOCGSESSION)"); - return 1; - } - - /* Encrypt data.in to data.encrypted */ - cryp.ses = sess.ses; - cryp.len = sizeof(plaintext1); - cryp.src = plaintext1; - cryp.dst = plaintext1; - cryp.iv = iv1; - cryp.op = COP_ENCRYPT; - if (ioctl(cfd, CIOCCRYPT, &cryp)) { - perror("ioctl(CIOCCRYPT)"); - return 1; - } - - /* Verify the result */ - if (memcmp(plaintext1, ciphertext1, sizeof(plaintext1)) != 0) { - fprintf(stderr, - "FAIL: Decrypted data are different from the input data.\n"); - return 1; - } - - /* Test 2 */ - - memset(key2, 0x0, sizeof(key2)); - memset(iv2, 0x0, sizeof(iv2)); - - /* Get crypto session for AES128 */ - sess.cipher = CRYPTO_AES_CBC; - sess.keylen = KEY_SIZE; - sess.key = key2; - if (ioctl(cfd, CIOCGSESSION, &sess)) { - perror("ioctl(CIOCGSESSION)"); - return 1; - } - - /* Encrypt data.in to data.encrypted */ - cryp.ses = sess.ses; - cryp.len = sizeof(plaintext2); - cryp.src = plaintext2; - cryp.dst = plaintext2; - cryp.iv = iv2; - cryp.op = COP_ENCRYPT; - if (ioctl(cfd, CIOCCRYPT, &cryp)) { - perror("ioctl(CIOCCRYPT)"); - return 1; - } - - /* Verify the result */ - if (memcmp(plaintext2, ciphertext2, sizeof(plaintext2)) != 0) { - fprintf(stderr, - "FAIL: Decrypted data are different from the input data.\n"); - return 1; - } - - printf("AES Test passed\n"); - - /* Finish crypto session */ - if (ioctl(cfd, CIOCFSESSION, &sess.ses)) { - perror("ioctl(CIOCFSESSION)"); - return 1; - } - - return 0; -} - -int -main() -{ - int fd = -1, cfd = -1; - - /* Open the crypto device */ - fd = open("/dev/crypto", O_RDWR, 0); - if (fd < 0) { - perror("open(/dev/crypto)"); - return 1; - } - - /* Clone file descriptor */ - if (ioctl(fd, CRIOGET, &cfd)) { - perror("ioctl(CRIOGET)"); - return 1; - } - - /* Set close-on-exec (not really neede here) */ - if (fcntl(cfd, F_SETFD, 1) == -1) { - perror("fcntl(F_SETFD)"); - return 1; - } - - /* Run the test itself */ - if (test_aes(cfd)) - return 1; - - if (test_crypto(cfd)) - return 1; - - /* Close cloned descriptor */ - if (close(cfd)) { - perror("close(cfd)"); - return 1; - } - - /* Close the original descriptor */ - if (close(fd)) { - perror("close(fd)"); - return 1; - } - - return 0; -} - diff --git a/examples/hmac.c b/examples/hmac.c deleted file mode 100644 index c54d7419a34..00000000000 --- a/examples/hmac.c +++ /dev/null @@ -1,210 +0,0 @@ -/* - * Demo on how to use /dev/crypto device for HMAC. - * - * Placed under public domain. - * - */ -#include -#include -#include -#include -#include - -#include -#include "../cryptodev.h" - -#define DATA_SIZE 4096 -#define BLOCK_SIZE 16 -#define KEY_SIZE 16 -#define SHA1_HASH_LEN 20 - -static int -test_crypto(int cfd) -{ - struct { - uint8_t in[DATA_SIZE], - encrypted[DATA_SIZE], - decrypted[DATA_SIZE], - iv[BLOCK_SIZE], - key[KEY_SIZE]; - } data; - struct session_op sess; - struct crypt_op cryp; - uint8_t mac[AALG_MAX_RESULT_LEN]; - uint8_t oldmac[AALG_MAX_RESULT_LEN]; - uint8_t md5_hmac_out[] = "\x75\x0c\x78\x3e\x6a\xb0\xb5\x03\xea\xa8\x6e\x31\x0a\x5d\xb7\x38"; - uint8_t sha1_out[] = "\x8f\x82\x03\x94\xf9\x53\x35\x18\x20\x45\xda\x24\xf3\x4d\xe5\x2b\xf8\xbc\x34\x32"; - int i; - - memset(&sess, 0, sizeof(sess)); - memset(&cryp, 0, sizeof(cryp)); - - /* Use the garbage that is on the stack :-) */ - /* memset(&data, 0, sizeof(data)); */ - - /* SHA1 plain test */ - memset(mac, 0, sizeof(mac)); - - sess.cipher = 0; - sess.mac = CRYPTO_SHA1; - if (ioctl(cfd, CIOCGSESSION, &sess)) { - perror("ioctl(CIOCGSESSION)"); - return 1; - } - - cryp.ses = sess.ses; - cryp.len = sizeof("what do ya want for nothing?")-1; - cryp.src = "what do ya want for nothing?"; - cryp.mac = mac; - cryp.op = COP_ENCRYPT; - if (ioctl(cfd, CIOCCRYPT, &cryp)) { - perror("ioctl(CIOCCRYPT)"); - return 1; - } - - if (memcmp(mac, sha1_out, 20)!=0) { - printf("mac: "); - for (i=0;i #include #include -#include "../cryptodev.h" #include "../ncr.h" static double udifftimeval(struct timeval start, struct timeval end) @@ -68,75 +67,6 @@ static void value2human(double bytes, double time, double* data, double* speed,c } -int encrypt_data(int cipher, int fdc, int chunksize) -{ - struct crypt_op cop; - char *buffer, iv[32]; - static int val = 23; - struct timeval start, end; - double total = 0; - double secs, ddata, dspeed; - struct session_op sess; - char metric[16]; - char keybuf[16]; - int keylen; - - memset(keybuf, 0x42, 16); - if (cipher == CRYPTO_NULL) - keylen = 0; - else keylen = 16; - - buffer = malloc(chunksize); - memset(iv, 0x23, 32); - - printf("\tEncrypting in chunks of %d bytes: ", chunksize); - fflush(stdout); - - memset(buffer, val++, chunksize); - - must_finish = 0; - alarm(5); - - gettimeofday(&start, NULL); - do { - memset(&sess, 0, sizeof(sess)); - sess.cipher = cipher; - sess.keylen = keylen; - sess.key = (unsigned char *)keybuf; - if (ioctl(fdc, CIOCGSESSION, &sess)) { - perror("ioctl(CIOCGSESSION)"); - return 1; - } - - memset(&cop, 0, sizeof(cop)); - cop.ses = sess.ses; - cop.len = chunksize; - cop.iv = (unsigned char *)iv; - cop.op = COP_ENCRYPT; - cop.flags = 0; - cop.src = cop.dst = (unsigned char *)buffer; - - if (ioctl(fdc, CIOCCRYPT, &cop)) { - perror("ioctl(CIOCCRYPT)"); - return 1; - } - - ioctl(fdc, CIOCFSESSION, &sess.ses); - - total+=chunksize; - } while(must_finish==0); - gettimeofday(&end, NULL); - - secs = udifftimeval(start, end)/ 1000000.0; - - value2human(total, secs, &ddata, &dspeed, metric); - printf ("done. %.2f %s in %.2f secs: ", ddata, metric, secs); - printf ("%.2f %s/sec\n", dspeed, metric); - - return 0; -} - - int encrypt_data_ncr_direct(int cfd, int algo, int chunksize) { char *buffer, iv[32]; @@ -211,7 +141,7 @@ int encrypt_data_ncr_direct(int cfd, int algo, int chunksize) int main(void) { - int fd, i, fdc = -1; + int fd, i; signal(SIGALRM, alarm_handler); @@ -219,39 +149,20 @@ int main(void) perror("open()"); return 1; } - if (ioctl(fd, CRIOGET, &fdc)) { - perror("ioctl(CRIOGET)"); - return 1; - } - - fprintf(stderr, "Testing NULL cipher: \n"); - - for (i = 256; i <= (64 * 1024); i *= 2) { - if (encrypt_data(CRYPTO_NULL, fdc, i)) - break; - } fprintf(stderr, "\nTesting NCR-DIRECT with NULL cipher: \n"); for (i = 256; i <= (64 * 1024); i *= 2) { - if (encrypt_data_ncr_direct(fdc, NCR_ALG_NULL, i)) + if (encrypt_data_ncr_direct(fd, NCR_ALG_NULL, i)) break; } - fprintf(stderr, "\nTesting AES-128-CBC cipher: \n"); - - for (i = 256; i <= (64 * 1024); i *= 2) { - if (encrypt_data(CRYPTO_AES_CBC, fdc, i)) - break; - } fprintf(stderr, "\nTesting NCR-DIRECT with AES-128-CBC cipher: \n"); for (i = 256; i <= (64 * 1024); i *= 2) { - if (encrypt_data_ncr_direct(fdc, NCR_ALG_AES_CBC, i)) + if (encrypt_data_ncr_direct(fd, NCR_ALG_AES_CBC, i)) break; } - - close(fdc); close(fd); return 0; } diff --git a/extras/openssl-0.9.8k-cryptodev-linux.diff b/extras/openssl-0.9.8k-cryptodev-linux.diff deleted file mode 100644 index 0a43e635ae9..00000000000 --- a/extras/openssl-0.9.8k-cryptodev-linux.diff +++ /dev/null @@ -1,74 +0,0 @@ -diff -ur openssl-0.9.8k/crypto/engine/eng_all.c openssl-0.9.8k.new/crypto/engine/eng_all.c ---- openssl-0.9.8k/crypto/engine/eng_all.c 2008-06-04 21:01:39.000000000 +0300 -+++ openssl-0.9.8k.new/crypto/engine/eng_all.c 2009-11-24 13:41:49.000000000 +0200 -@@ -104,16 +104,15 @@ - #endif - #endif - #ifndef OPENSSL_NO_HW --#if defined(__OpenBSD__) || defined(__FreeBSD__) -+# if (OpenBSD >= 200112) || ((__FreeBSD_version >= 470101 && __FreeBSD_version < 500000) || __FreeBSD_version >= 500041) || defined(__linux__) - ENGINE_load_cryptodev(); --#endif -+# endif - #if defined(OPENSSL_SYS_WIN32) && !defined(OPENSSL_NO_CAPIENG) - ENGINE_load_capi(); - #endif - #endif - } - --#if defined(__OpenBSD__) || defined(__FreeBSD__) - void ENGINE_setup_bsd_cryptodev(void) { - static int bsd_cryptodev_default_loaded = 0; - if (!bsd_cryptodev_default_loaded) { -@@ -122,4 +121,3 @@ - } - bsd_cryptodev_default_loaded=1; - } --#endif -diff -ur openssl-0.9.8k/crypto/engine/eng_cryptodev.c openssl-0.9.8k.new/crypto/engine/eng_cryptodev.c ---- openssl-0.9.8k/crypto/engine/eng_cryptodev.c 2004-06-15 14:45:42.000000000 +0300 -+++ openssl-0.9.8k.new/crypto/engine/eng_cryptodev.c 2009-11-24 13:45:31.000000000 +0200 -@@ -34,14 +34,15 @@ - #if (defined(__unix__) || defined(unix)) && !defined(USG) && \ - (defined(OpenBSD) || defined(__FreeBSD_version)) - #include --# if (OpenBSD >= 200112) || ((__FreeBSD_version >= 470101 && __FreeBSD_version < 500000) || __FreeBSD_version >= 500041) --# define HAVE_CRYPTODEV --# endif - # if (OpenBSD >= 200110) - # define HAVE_SYSLOG_R - # endif - #endif - -+#if (OpenBSD >= 200112) || ((__FreeBSD_version >= 470101 && __FreeBSD_version < 500000) || __FreeBSD_version >= 500041) || defined(__linux__) -+# define HAVE_CRYPTODEV -+#endif -+ - #ifndef HAVE_CRYPTODEV - - void -diff -ur openssl-0.9.8k/crypto/engine/engine.h openssl-0.9.8k.new/crypto/engine/engine.h ---- openssl-0.9.8k/crypto/engine/engine.h 2008-06-04 21:01:40.000000000 +0300 -+++ openssl-0.9.8k.new/crypto/engine/engine.h 2009-11-24 13:41:49.000000000 +0200 -@@ -703,9 +703,7 @@ - * values. */ - void *ENGINE_get_static_state(void); - --#if defined(__OpenBSD__) || defined(__FreeBSD__) - void ENGINE_setup_bsd_cryptodev(void); --#endif - - /* BEGIN ERROR CODES */ - /* The following lines are auto generated by the script mkerr.pl. Any changes -diff -ur openssl-0.9.8k/crypto/evp/c_all.c openssl-0.9.8k.new/crypto/evp/c_all.c ---- openssl-0.9.8k/crypto/evp/c_all.c 2004-08-29 19:36:04.000000000 +0300 -+++ openssl-0.9.8k.new/crypto/evp/c_all.c 2009-11-24 13:41:49.000000000 +0200 -@@ -83,8 +83,6 @@ - OpenSSL_add_all_ciphers(); - OpenSSL_add_all_digests(); - #ifndef OPENSSL_NO_ENGINE --# if defined(__OpenBSD__) || defined(__FreeBSD__) - ENGINE_setup_bsd_cryptodev(); --# endif - #endif - } diff --git a/extras/openssl-0.9.8l-cryptodev-aes256.patch b/extras/openssl-0.9.8l-cryptodev-aes256.patch deleted file mode 100644 index cf9bbbc80c6..00000000000 --- a/extras/openssl-0.9.8l-cryptodev-aes256.patch +++ /dev/null @@ -1,112 +0,0 @@ -This is http://people.freebsd.org/~pjd/patches/hw_cryptodev.c.patch adopted for -openssl-0.9.8l. It makes AES192 and AES256 CBC known to the cryptodev engine. - -There's also http://people.freebsd.org/~pjd/patches/eng_cryptodev.c.patch, -which seems more current, also adds SHA digests and does somehting CTX-related -to cryptodev_rsa_nocrt_mod_exp(). But since digests are disabled in -cryptodev_usable_digests() anyway and cryptodev_rsa_nocrt_mod_exp() is used for -RSA only, I didn't bother with it. - ---- openssl-0.9.8l/crypto/engine/eng_cryptodev.caes256 2004-06-15 13:45:42.000000000 +0200 -+++ openssl-0.9.8l/crypto/engine/eng_cryptodev.c 2010-02-16 21:57:15.000000000 +0100 -@@ -133,11 +133,14 @@ - { CRYPTO_DES_CBC, NID_des_cbc, 8, 8, }, - { CRYPTO_3DES_CBC, NID_des_ede3_cbc, 8, 24, }, - { CRYPTO_AES_CBC, NID_aes_128_cbc, 16, 16, }, -+ { CRYPTO_AES_CBC, NID_aes_192_cbc, 16, 24, }, -+ { CRYPTO_AES_CBC, NID_aes_256_cbc, 16, 32, }, - { CRYPTO_BLF_CBC, NID_bf_cbc, 8, 16, }, - { CRYPTO_CAST_CBC, NID_cast5_cbc, 8, 16, }, - { CRYPTO_SKIPJACK_CBC, NID_undef, 0, 0, }, - { 0, NID_undef, 0, 0, }, - }; -+#define NCIPHERS (sizeof(ciphers) / sizeof(ciphers[0])) - - static struct { - int id; -@@ -229,8 +232,8 @@ - int i; - - for (i = 0; ciphers[i].id; i++) -- if (ciphers[i].id == cipher) -- return (ciphers[i].keylen == len); -+ if (ciphers[i].id == cipher && ciphers[i].keylen == len) -+ return (1); - return (0); - } - -@@ -255,7 +258,7 @@ - static int - get_cryptodev_ciphers(const int **cnids) - { -- static int nids[CRYPTO_ALGORITHM_MAX]; -+ static int nids[NCIPHERS]; - struct session_op sess; - int fd, i, count = 0; - -@@ -266,7 +269,7 @@ - memset(&sess, 0, sizeof(sess)); - sess.key = (caddr_t)"123456781234567812345678"; - -- for (i = 0; ciphers[i].id && count < CRYPTO_ALGORITHM_MAX; i++) { -+ for (i = 0; ciphers[i].id && count < NCIPHERS; i++) { - if (ciphers[i].nid == NID_undef) - continue; - sess.cipher = ciphers[i].id; -@@ -550,7 +553,7 @@ - NULL - }; - --const EVP_CIPHER cryptodev_aes_cbc = { -+const EVP_CIPHER cryptodev_aes128_cbc = { - NID_aes_128_cbc, - 16, 16, 16, - EVP_CIPH_CBC_MODE, -@@ -563,6 +566,32 @@ - NULL - }; - -+const EVP_CIPHER cryptodev_aes192_cbc = { -+ NID_aes_192_cbc, -+ 16, 24, 16, -+ EVP_CIPH_CBC_MODE, -+ cryptodev_init_key, -+ cryptodev_cipher, -+ cryptodev_cleanup, -+ sizeof(struct dev_crypto_state), -+ EVP_CIPHER_set_asn1_iv, -+ EVP_CIPHER_get_asn1_iv, -+ NULL -+}; -+ -+const EVP_CIPHER cryptodev_aes256_cbc = { -+ NID_aes_256_cbc, -+ 16, 32, 16, -+ EVP_CIPH_CBC_MODE, -+ cryptodev_init_key, -+ cryptodev_cipher, -+ cryptodev_cleanup, -+ sizeof(struct dev_crypto_state), -+ EVP_CIPHER_set_asn1_iv, -+ EVP_CIPHER_get_asn1_iv, -+ NULL -+}; -+ - /* - * Registered by the ENGINE when used to find out how to deal with - * a particular NID in the ENGINE. this says what we'll do at the -@@ -589,7 +618,13 @@ - *cipher = &cryptodev_cast_cbc; - break; - case NID_aes_128_cbc: -- *cipher = &cryptodev_aes_cbc; -+ *cipher = &cryptodev_aes128_cbc; -+ break; -+ case NID_aes_192_cbc: -+ *cipher = &cryptodev_aes192_cbc; -+ break; -+ case NID_aes_256_cbc: -+ *cipher = &cryptodev_aes256_cbc; - break; - default: - *cipher = NULL; diff --git a/ncr-dh.c b/ncr-dh.c index 04df2b381f2..bc45723fe3e 100644 --- a/ncr-dh.c +++ b/ncr-dh.c @@ -27,7 +27,6 @@ #include #include #include -#include "cryptodev.h" #include #include #include diff --git a/ncr-key-storage.c b/ncr-key-storage.c index fc6948f5c61..f00bce8d9e7 100644 --- a/ncr-key-storage.c +++ b/ncr-key-storage.c @@ -26,7 +26,6 @@ #include #include #include -#include "cryptodev.h" #include #include "ncr.h" #include "ncr-int.h" diff --git a/ncr-key-wrap.c b/ncr-key-wrap.c index 93103b5a9a5..c6f394eaac7 100644 --- a/ncr-key-wrap.c +++ b/ncr-key-wrap.c @@ -28,7 +28,6 @@ #include #include #include -#include "cryptodev.h" #include #include "ncr.h" #include "ncr-int.h" diff --git a/ncr-key.c b/ncr-key.c index 8f74ade80e3..95228f22859 100644 --- a/ncr-key.c +++ b/ncr-key.c @@ -27,7 +27,6 @@ #include #include #include -#include "cryptodev.h" #include #include "ncr.h" #include "ncr-int.h" diff --git a/ncr-limits.c b/ncr-limits.c index 34acac708d0..0c12824a211 100644 --- a/ncr-limits.c +++ b/ncr-limits.c @@ -29,7 +29,6 @@ #include #include #include -#include "cryptodev.h" #include #include #include diff --git a/ncr-pk.c b/ncr-pk.c index 104c047df8e..f3f4265fd61 100644 --- a/ncr-pk.c +++ b/ncr-pk.c @@ -27,7 +27,6 @@ #include #include #include -#include "cryptodev.h" #include #include "ncr.h" #include "ncr-int.h" diff --git a/ncr-sessions.c b/ncr-sessions.c index 0a48b23b7f6..711963b618e 100644 --- a/ncr-sessions.c +++ b/ncr-sessions.c @@ -25,7 +25,6 @@ #include #include -#include "cryptodev.h" #include "ncr.h" #include "ncr-int.h" #include diff --git a/ncr.c b/ncr.c index 86c8c7ad8ad..ec9998ca83f 100644 --- a/ncr.c +++ b/ncr.c @@ -28,7 +28,6 @@ #include #include #include -#include "cryptodev.h" #include #include #include -- cgit From 5c340eee0020717c793fd9d7e74e5f065225a8f3 Mon Sep 17 00:00:00 2001 From: Miloslav Trmač Date: Tue, 24 Aug 2010 20:17:51 +0200 Subject: Provide file_operations::unlocked_ioctl. file_operations::ioctl is no longer supported in recent kernels. compat_ioctl is not running under the BKL, so the code has to do its own locking anyway (although not everything currently does). --- cryptodev_main.c | 9 ++++----- ncr-int.h | 2 +- ncr.c | 2 +- 3 files changed, 6 insertions(+), 7 deletions(-) diff --git a/cryptodev_main.c b/cryptodev_main.c index da75672615a..541f17748e5 100644 --- a/cryptodev_main.c +++ b/cryptodev_main.c @@ -768,9 +768,8 @@ clonefd(struct file *filp) return ret; } -static int -cryptodev_ioctl(struct inode *inode, struct file *filp, - unsigned int cmd, unsigned long arg_) +static long +cryptodev_ioctl(struct file *filp, unsigned int cmd, unsigned long arg_) { void __user *arg = (void __user *)arg_; int __user *p = arg; @@ -907,7 +906,7 @@ cryptodev_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg_) case CIOCASYMFEAT: case CRIOGET: case CIOCFSESSION: - return cryptodev_ioctl(NULL, file, cmd, arg_); + return cryptodev_ioctl(file, cmd, arg_); case COMPAT_CIOCGSESSION: if (unlikely(copy_from_user(&compat_sop, arg, @@ -955,7 +954,7 @@ static const struct file_operations cryptodev_fops = { .owner = THIS_MODULE, .open = cryptodev_open, .release = cryptodev_release, - .ioctl = cryptodev_ioctl, + .unlocked_ioctl = cryptodev_ioctl, #ifdef CONFIG_COMPAT .compat_ioctl = cryptodev_compat_ioctl, #endif /* CONFIG_COMPAT */ diff --git a/ncr-int.h b/ncr-int.h index 53df9dfccaa..6277619b257 100644 --- a/ncr-int.h +++ b/ncr-int.h @@ -104,7 +104,7 @@ struct ncr_lists { void* ncr_init_lists(void); void ncr_deinit_lists(struct ncr_lists *lst); -int ncr_ioctl(struct ncr_lists *lst, unsigned int cmd, unsigned long arg); +long ncr_ioctl(struct ncr_lists *lst, unsigned int cmd, unsigned long arg); /* key derivation */ int ncr_key_derive(struct ncr_lists *lst, void __user* arg); diff --git a/ncr.c b/ncr.c index 81e3fa32cef..615b29d0f7d 100644 --- a/ncr.c +++ b/ncr.c @@ -116,7 +116,7 @@ struct ncr_master_key_st st; return 0; } -int +long ncr_ioctl(struct ncr_lists *lst, unsigned int cmd, unsigned long arg_) { void __user *arg = (void __user *)arg_; -- cgit From 51a92d357aebc84b45cf8c90061319d22b170bb5 Mon Sep 17 00:00:00 2001 From: Miloslav Trmač Date: Tue, 24 Aug 2010 20:43:13 +0200 Subject: Reject prohibited key flags immediately Silently ignoring user's requests is unexpected. --- examples/ncr.c | 18 ++++++++---------- ncr-int.h | 2 +- ncr-key-wrap.c | 13 +++++++++++-- ncr-key.c | 41 ++++++++++++++++++++++++++++++----------- 4 files changed, 50 insertions(+), 24 deletions(-) diff --git a/examples/ncr.c b/examples/ncr.c index 5169a149e31..7de67ee9a61 100644 --- a/examples/ncr.c +++ b/examples/ncr.c @@ -240,12 +240,18 @@ test_ncr_wrap_key(int cfd) keydata.idata = "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F"; keydata.idata_size = 16; - if (ioctl(cfd, NCRIO_KEY_IMPORT, &keydata)) { + ret = ioctl(cfd, NCRIO_KEY_IMPORT, &keydata); + if (geteuid() == 0 && ret) { fprintf(stderr, "Error: %s:%d\n", __func__, __LINE__); perror("ioctl(NCRIO_KEY_IMPORT)"); return 1; } + if (geteuid() != 0) { + /* cannot test further */ + fprintf(stdout, "\t(Wrapping test not completed. Run as root)\n"); + return 0; + } /* convert it to key */ if (ioctl(cfd, NCRIO_KEY_INIT, &key2)) { @@ -279,19 +285,11 @@ test_ncr_wrap_key(int cfd) kwrap.io = data; kwrap.io_size = sizeof(data); - ret = ioctl(cfd, NCRIO_KEY_WRAP, &kwrap); - - if (geteuid() == 0 && ret) { + if (ioctl(cfd, NCRIO_KEY_WRAP, &kwrap)) { fprintf(stderr, "Error: %s:%d\n", __func__, __LINE__); perror("ioctl(NCRIO_KEY_WRAP)"); return 1; } - - if (geteuid() != 0) { - /* cannot test further */ - fprintf(stdout, "\t(Wrapping test not completed. Run as root)\n"); - return 0; - } data_size = kwrap.io_size; diff --git a/ncr-int.h b/ncr-int.h index 6277619b257..03ad298b4d1 100644 --- a/ncr-int.h +++ b/ncr-int.h @@ -110,7 +110,7 @@ long ncr_ioctl(struct ncr_lists *lst, unsigned int cmd, unsigned long arg); int ncr_key_derive(struct ncr_lists *lst, void __user* arg); void ncr_key_clear(struct key_item_st* item); -void ncr_key_assign_flags(struct key_item_st* item, unsigned int flags); +int ncr_key_assign_flags(struct key_item_st *item, unsigned int flags); /* key handling */ int ncr_key_init(struct ncr_lists *lst, void __user* arg); diff --git a/ncr-key-wrap.c b/ncr-key-wrap.c index 93103b5a9a5..eea252ee85c 100644 --- a/ncr-key-wrap.c +++ b/ncr-key-wrap.c @@ -455,12 +455,17 @@ const uint8_t * iv = wrap_st->params.params.cipher.iv; goto cleanup; } + ret = ncr_key_assign_flags(output, wrap_st->wrapped_key_flags); + if (ret != 0) { + err(); + goto cleanup; + } + memset(&output->key, 0, sizeof(output->key)); for (i=0;ikey.secret.data[i*8], R[i], sizeof(R[i])); } output->key.secret.size = n*8; - ncr_key_assign_flags(output, wrap_st->wrapped_key_flags); output->type = NCR_KEY_TYPE_SECRET; ret = 0; @@ -864,7 +869,11 @@ static int key_from_packed_data(ncr_algorithm_t algorithm, unsigned int flags, } key->type = key->algorithm->key_type; - ncr_key_assign_flags(key, flags); + ret = ncr_key_assign_flags(key, flags); + if (ret != 0) { + err(); + return ret; + } if (key->type == NCR_KEY_TYPE_SECRET) { if (data_size > NCR_CIPHER_MAX_KEY_LEN) { diff --git a/ncr-key.c b/ncr-key.c index 8f74ade80e3..3860f7f54f4 100644 --- a/ncr-key.c +++ b/ncr-key.c @@ -309,13 +309,12 @@ fail: } -void ncr_key_assign_flags(struct key_item_st* item, unsigned int flags) +int ncr_key_assign_flags(struct key_item_st* item, unsigned int flags) { - if (current_euid()==0) { - item->flags = flags; - } else { - item->flags = flags & (~(NCR_KEY_FLAG_WRAPPING)); - } + if (current_euid() != 0 && (flags & NCR_KEY_FLAG_WRAPPING) != 0) + return -EPERM; + item->flags = flags; + return 0; } /* "imports" a key from a data item. If the key is not exportable @@ -363,7 +362,11 @@ size_t tmp_size; ret = -EINVAL; goto fail; } - ncr_key_assign_flags(item, data.flags); + ret = ncr_key_assign_flags(item, data.flags); + if (ret < 0) { + err(); + goto fail; + } if (data.key_id_size > MAX_KEY_ID_SIZE) { err(); @@ -451,7 +454,11 @@ size_t size; ncr_key_clear(item); /* we generate only secret keys */ - ncr_key_assign_flags(item, gen.params.keyflags); + ret = ncr_key_assign_flags(item, gen.params.keyflags); + if (ret < 0) { + err(); + goto fail; + } algo = _ncr_algo_to_properties(gen.params.algorithm); if (algo == NULL) { @@ -669,8 +676,16 @@ int ret; } public->type = public->algorithm->key_type; private->type = NCR_KEY_TYPE_PRIVATE; - ncr_key_assign_flags(private, gen.params.keyflags); - ncr_key_assign_flags(public, gen.params.keyflags); + ret = ncr_key_assign_flags(private, gen.params.keyflags); + if (ret < 0) { + err(); + goto fail; + } + ret = ncr_key_assign_flags(public, gen.params.keyflags); + if (ret < 0) { + err(); + goto fail; + } public->flags |= (NCR_KEY_FLAG_EXPORTABLE|NCR_KEY_FLAG_WRAPPABLE); @@ -736,7 +751,11 @@ struct key_item_st* newkey = NULL; ncr_key_clear(newkey); - ncr_key_assign_flags(newkey, data.keyflags); + ret = ncr_key_assign_flags(newkey, data.keyflags); + if (ret < 0) { + err(); + goto fail; + } switch (key->type) { case NCR_KEY_TYPE_PUBLIC: -- cgit From f9b9503e757b5fc69ab93bc1e4f7e80de85f0831 Mon Sep 17 00:00:00 2001 From: Miloslav Trmač Date: Tue, 24 Aug 2010 20:43:59 +0200 Subject: Base access decisions only on capable(), not euid --- ncr-key.c | 2 +- ncr.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ncr-key.c b/ncr-key.c index 3860f7f54f4..a7019f5cfba 100644 --- a/ncr-key.c +++ b/ncr-key.c @@ -311,7 +311,7 @@ fail: int ncr_key_assign_flags(struct key_item_st* item, unsigned int flags) { - if (current_euid() != 0 && (flags & NCR_KEY_FLAG_WRAPPING) != 0) + if (!capable(CAP_SYS_ADMIN) && (flags & NCR_KEY_FLAG_WRAPPING) != 0) return -EPERM; item->flags = flags; return 0; diff --git a/ncr.c b/ncr.c index 615b29d0f7d..f9f6026160e 100644 --- a/ncr.c +++ b/ncr.c @@ -79,7 +79,7 @@ static int ncr_master_key_set(void __user *arg) { struct ncr_master_key_st st; - if (current_euid() != 0 && !capable(CAP_SYS_ADMIN)) { + if (!capable(CAP_SYS_ADMIN)) { err(); return -EPERM; } -- cgit From 1ba66cab0563708d551e3462c249f1da21695882 Mon Sep 17 00:00:00 2001 From: Miloslav Trmač Date: Tue, 24 Aug 2010 20:56:09 +0200 Subject: Make it possible to import private keys --- examples/ncr.c | 4 ++++ examples/pk.c | 1 + ncr-key-wrap.c | 20 +++++++++++++------- ncr.h | 1 + 4 files changed, 19 insertions(+), 7 deletions(-) diff --git a/examples/ncr.c b/examples/ncr.c index 7de67ee9a61..a02f750b72d 100644 --- a/examples/ncr.c +++ b/examples/ncr.c @@ -321,6 +321,10 @@ test_ncr_wrap_key(int cfd) memset(&kwrap, 0, sizeof(kwrap)); kwrap.algorithm = NCR_WALG_AES_RFC3394; kwrap.keytowrap = key2; + kwrap.wrapped_key_algorithm = NCR_ALG_AES_CBC; + kwrap.wrapped_key_type = NCR_KEY_TYPE_SECRET; + kwrap.wrapped_key_flags + = NCR_KEY_FLAG_EXPORTABLE|NCR_KEY_FLAG_WRAPPABLE; kwrap.key = key; kwrap.io = data; kwrap.io_size = data_size; diff --git a/examples/pk.c b/examples/pk.c index 032ae9864d9..7199d53f113 100644 --- a/examples/pk.c +++ b/examples/pk.c @@ -647,6 +647,7 @@ test_ncr_wrap_key3(int cfd) memset(&kwrap, 0, sizeof(kwrap)); kwrap.algorithm = NCR_WALG_AES_RFC5649; kwrap.wrapped_key_algorithm = NCR_ALG_RSA; + kwrap.wrapped_key_type = NCR_KEY_TYPE_PRIVATE; kwrap.keytowrap = privkey; kwrap.key = key; kwrap.io = data; diff --git a/ncr-key-wrap.c b/ncr-key-wrap.c index eea252ee85c..0f9f0fe1831 100644 --- a/ncr-key-wrap.c +++ b/ncr-key-wrap.c @@ -39,8 +39,10 @@ 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, - struct key_item_st* key, const void* data, size_t data_size); +static int key_from_packed_data(ncr_algorithm_t algorithm, + ncr_key_type_t key_type, unsigned int flags, + struct key_item_st* key, const void* data, + size_t data_size); static void val64_xor( val64_t val, uint32_t x) @@ -303,8 +305,10 @@ 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, - output, sdata, sdata_size); + ret = key_from_packed_data(wrap_st->wrapped_key_algorithm, + wrap_st->wrapped_key_type, + wrap_st->wrapped_key_flags, output, sdata, + sdata_size); if (ret < 0) { err(); goto fail; @@ -852,8 +856,10 @@ fail: return ret; } -static int key_from_packed_data(ncr_algorithm_t algorithm, unsigned int flags, - struct key_item_st* key, const void* data, size_t data_size) +static int key_from_packed_data(ncr_algorithm_t algorithm, + ncr_key_type_t key_type, unsigned int flags, + struct key_item_st* key, const void* data, + size_t data_size) { int ret; @@ -868,7 +874,7 @@ static int key_from_packed_data(ncr_algorithm_t algorithm, unsigned int flags, return -EINVAL; } - key->type = key->algorithm->key_type; + key->type = key_type; ret = ncr_key_assign_flags(key, flags); if (ret != 0) { err(); diff --git a/ncr.h b/ncr.h index af4c279b630..94d14331ecb 100644 --- a/ncr.h +++ b/ncr.h @@ -216,6 +216,7 @@ struct ncr_key_wrap_st { * For symmetric ciphers AES would do. */ ncr_algorithm_t wrapped_key_algorithm; + ncr_key_type_t wrapped_key_type; unsigned int wrapped_key_flags; /* flags for the newly unwrapped key */ ncr_key_t keytowrap; -- cgit From 9c0650117290c30b94e1c3513b67808fb5f7a143 Mon Sep 17 00:00:00 2001 From: Miloslav Trmač Date: Tue, 17 Aug 2010 20:11:44 +0200 Subject: Drop unnecessary "file *" argument to ncr_ioctl() --- cryptodev_main.c | 2 +- ncr-int.h | 3 +-- ncr.c | 3 +-- 3 files changed, 3 insertions(+), 5 deletions(-) diff --git a/cryptodev_main.c b/cryptodev_main.c index f3f1f08012e..0a20888fab3 100644 --- a/cryptodev_main.c +++ b/cryptodev_main.c @@ -136,7 +136,7 @@ cryptodev_ioctl(struct inode *inode, struct file *filp, if (unlikely(!ncr)) BUG(); - return ncr_ioctl(ncr, filp, cmd, arg); + return ncr_ioctl(ncr, cmd, arg); } /* compatibility code for 32bit userlands */ diff --git a/ncr-int.h b/ncr-int.h index 4694cdae054..53df9dfccaa 100644 --- a/ncr-int.h +++ b/ncr-int.h @@ -104,8 +104,7 @@ struct ncr_lists { void* ncr_init_lists(void); void ncr_deinit_lists(struct ncr_lists *lst); -int ncr_ioctl(struct ncr_lists*, struct file *filp, - unsigned int cmd, unsigned long arg); +int ncr_ioctl(struct ncr_lists *lst, unsigned int cmd, unsigned long arg); /* key derivation */ int ncr_key_derive(struct ncr_lists *lst, void __user* arg); diff --git a/ncr.c b/ncr.c index ec9998ca83f..99d2786f7f1 100644 --- a/ncr.c +++ b/ncr.c @@ -116,8 +116,7 @@ struct ncr_master_key_st st; } int -ncr_ioctl(struct ncr_lists* lst, struct file *filp, - unsigned int cmd, unsigned long arg_) +ncr_ioctl(struct ncr_lists *lst, unsigned int cmd, unsigned long arg_) { void __user *arg = (void __user *)arg_; -- cgit From 22482a34969ead83c1ead01cff483998ef5960d4 Mon Sep 17 00:00:00 2001 From: Miloslav Trmač Date: Tue, 17 Aug 2010 20:37:06 +0200 Subject: Add compat_ioctl infrastructure --- cryptodev_main.c | 5 +---- ncr-int.h | 2 ++ ncr.c | 15 +++++++++++++++ 3 files changed, 18 insertions(+), 4 deletions(-) diff --git a/cryptodev_main.c b/cryptodev_main.c index 0a20888fab3..9c484f5259d 100644 --- a/cryptodev_main.c +++ b/cryptodev_main.c @@ -150,10 +150,7 @@ cryptodev_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) if (unlikely(!ncr)) BUG(); - switch (cmd) { - default: - return -EINVAL; - } + return ncr_compat_ioctl(ncr, cmd, arg); } #endif /* CONFIG_COMPAT */ diff --git a/ncr-int.h b/ncr-int.h index 53df9dfccaa..b7c6ed4b132 100644 --- a/ncr-int.h +++ b/ncr-int.h @@ -105,6 +105,8 @@ void* ncr_init_lists(void); void ncr_deinit_lists(struct ncr_lists *lst); int ncr_ioctl(struct ncr_lists *lst, unsigned int cmd, unsigned long arg); +long ncr_compat_ioctl(struct ncr_lists *lst, unsigned int cmd, + unsigned long arg); /* key derivation */ int ncr_key_derive(struct ncr_lists *lst, void __user* arg); diff --git a/ncr.c b/ncr.c index 99d2786f7f1..9549b93a697 100644 --- a/ncr.c +++ b/ncr.c @@ -22,6 +22,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ +#include #include #include #include @@ -163,3 +164,17 @@ ncr_ioctl(struct ncr_lists *lst, unsigned int cmd, unsigned long arg_) return -EINVAL; } } + +#ifdef CONFIG_COMPAT +long +ncr_compat_ioctl(struct ncr_lists *lst, unsigned int cmd, unsigned long arg_) +{ + if (unlikely(!lst)) + BUG(); + + switch (cmd) { + default: + return -EINVAL; + } +} +#endif -- cgit From 8b354238d31bafea348dd8099f75ab23f0d9d4da Mon Sep 17 00:00:00 2001 From: Miloslav Trmač Date: Tue, 17 Aug 2010 20:38:46 +0200 Subject: Use more specific types to avoid compat_ioctl Using "int" would require conversions from compat_int_t. --- ncr.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ncr.h b/ncr.h index af4c279b630..a8ae1e3a5a2 100644 --- a/ncr.h +++ b/ncr.h @@ -57,7 +57,7 @@ typedef enum { /* Key handling */ -typedef int ncr_key_t; +typedef __s32 ncr_key_t; #define NCR_KEY_INVALID ((ncr_key_t)-1) @@ -262,7 +262,7 @@ typedef enum { NCR_OP_VERIFY, } ncr_crypto_op_t; -typedef int ncr_session_t; +typedef __s32 ncr_session_t; #define NCR_SESSION_INVALID ((ncr_session_t)-1) /* input of CIOCGSESSION */ -- cgit From f1382e005ed777e286c4c88fd8320ba133f8c0c6 Mon Sep 17 00:00:00 2001 From: Miloslav Trmač Date: Wed, 18 Aug 2010 03:24:21 +0200 Subject: Add input argument and attribute handling infrastructure --- Makefile | 2 +- ncr.h | 32 +++++++++ utils.c | 247 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ utils.h | 98 +++++++++++++++++++++++++ 4 files changed, 378 insertions(+), 1 deletion(-) create mode 100644 utils.c create mode 100644 utils.h diff --git a/Makefile b/Makefile index 093f777d25d..cdaab9339e3 100644 --- a/Makefile +++ b/Makefile @@ -68,7 +68,7 @@ TOMCRYPT_OBJECTS = libtomcrypt/misc/zeromem.o libtomcrypt/misc/crypt/crypt_argch cryptodev-objs = cryptodev_main.o cryptodev_cipher.o ncr.o \ ncr-key.o ncr-limits.o ncr-pk.o ncr-sessions.o ncr-dh.o \ - ncr-key-wrap.o ncr-key-storage.o $(TOMMATH_OBJECTS) \ + ncr-key-wrap.o ncr-key-storage.o utils.o $(TOMMATH_OBJECTS) \ $(TOMCRYPT_OBJECTS) diff --git a/ncr.h b/ncr.h index a8ae1e3a5a2..5819168620c 100644 --- a/ncr.h +++ b/ncr.h @@ -6,6 +6,38 @@ #define __user #endif +/* Serves to make sure the structure is suitably aligned to continue with + a struct nlattr without external padding. + + 4 is NLA_ALIGNTO from , but if we + included , the user would have to include + as well for no obvious reason. "4" is fixed by ABI. */ +#define __NL_ATTRIBUTES char __align[] __attribute__((aligned(4))) + +/* In all ioctls, input_size specifies size of the ncr_* structure and the + following attributes. + + output_size specifies space available for returning output, including the + initial ncr_* structure, and is updated by the ioctl() with the space + actually used. + + There are two special cases: input_size 0 means not attributes are supplied, + and is treated equivalent to sizeof(struct ncr_*). output_size 0 means no + space for output attributes is available, and is not updated. */ + +enum { + NCR_ATTR_UNSPEC, /* 0 is special in lib/nlattr.c. */ + /* FIXME: Use NLA_STRING for this, later */ + NCR_ATTR_ALGORITHM, /* NLA_U32 - ncr_algorithm_t */ + NCR_ATTR_KEY_FLAGS, /* NLA_U32 - NCR_KEY_FLAG_* */ + NCR_ATTR_SECRET_KEY_BITS, /* NLA_U32 */ + + /* Add new attributes here */ + + NCR_ATTR_END__, + NCR_ATTR_MAX = NCR_ATTR_END__ - 1 +}; + #define NCR_CIPHER_MAX_BLOCK_LEN 32 #define NCR_HASH_MAX_OUTPUT_SIZE 64 diff --git a/utils.c b/utils.c new file mode 100644 index 00000000000..45ca86f64ab --- /dev/null +++ b/utils.c @@ -0,0 +1,247 @@ +/* + * New driver for /dev/crypto device (aka CryptoDev) + * + * Copyright (c) 2010 Red Hat Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. + * + * Red Hat Author: Miloslav Trmač + * + */ + +#include +#include +#include +#include "ncr-int.h" +#include "utils.h" + +static const struct nla_policy ncr_attr_policy[NCR_ATTR_MAX + 1] = { + [NCR_ATTR_ALGORITHM] = { NLA_U32, 0 }, + [NCR_ATTR_KEY_FLAGS] = { NLA_U32, 0 }, + [NCR_ATTR_SECRET_KEY_BITS] = { NLA_U32, 0 }, +}; + +void *__ncr_get_input_args(void *fixed, struct nlattr *tb[], size_t fixed_size, + u32 *input_size_ptr, const void __user *arg) +{ + size_t input_size, buf_size; + void *buf; + int ret; + + if (unlikely(copy_from_user(fixed, arg, fixed_size))) { + err(); + return ERR_PTR(-EFAULT); + } + input_size = *input_size_ptr; + + /* NCR_GET_INPUT_ARGS/NCR_GET_INPUT_ARGS_NO_OUTPUT has verified + fixed_size is correctly aligned for a struct nlattr. */ + if (input_size == 0) + input_size = fixed_size; + else if (unlikely(input_size < fixed_size)) { + err(); + return ERR_PTR(-EINVAL); + } + buf_size = input_size - fixed_size; + if (unlikely(buf_size > NCR_MAX_ATTR_SIZE)) { + err(); + return ERR_PTR(-EOVERFLOW); + } + + if (buf_size == 0) + buf = NULL; + else { + const char __user *var_arg; + + buf = kmalloc(buf_size, GFP_KERNEL); + if (unlikely(buf == NULL)) { + err(); + return ERR_PTR(-ENOMEM); + } + var_arg = (const char __user *)arg + fixed_size; + if (unlikely(copy_from_user(buf, var_arg, buf_size))) { + err(); + ret = -EFAULT; + goto err_buf; + } + } + + ret = nla_parse(tb, NCR_ATTR_MAX, buf, buf_size, ncr_attr_policy); + if (ret != 0) { + err(); + goto err_buf; + } + + return buf; + +err_buf: + kfree(buf); + return ERR_PTR(ret); +} + +static int update_output_size(void __user *arg, size_t output_size_offset, + u32 old_value, u32 new_value) +{ + if (old_value != 0 && old_value != new_value) { + u32 __user *dest; + + dest = (u32 __user *)((char __user *)arg + output_size_offset); + return put_user(new_value, dest); + } + return 0; +} + +void *__ncr_get_input_args_no_output(void *fixed, struct nlattr *tb[], + size_t fixed_size, u32 *input_size_ptr, + size_t output_size_offset, + void __user *arg) +{ + void *attr_buf; + u32 output_size; + int ret; + + attr_buf = __ncr_get_input_args(fixed, tb, fixed_size, input_size_ptr, + arg); + if (IS_ERR(attr_buf)) + return attr_buf; + + output_size = *(const u32 *)((const char *)fixed + output_size_offset); + ret = update_output_size(arg, output_size_offset, output_size, + fixed_size); + if (ret != 0) { + kfree(attr_buf); + return ERR_PTR(ret); + } + return attr_buf; +} + +int __ncr_out_init(struct ncr_out *out, const void *fixed, size_t fixed_size, + size_t output_size_offset, void __user *arg) +{ + u32 output_size; + + /* NCR_OUT_INIT has verified fixed_size is correctly aligned for a + struct nlattr. */ + output_size = *(const u32 *)((const char *)fixed + output_size_offset); + if (output_size == 0) + out->left = 0; + else { + /* NCR_OUT_INIT has verified fixed_size is correctly aligned for + a struct nlattr. */ + if (output_size < fixed_size) + return -EINVAL; + out->left = min_t(size_t, output_size - fixed_size, + NCR_MAX_ATTR_SIZE); + } + out->buf = kmalloc(out->left, GFP_KERNEL); + if (out->buf == NULL) + return -ENOMEM; + out->p = out->buf; + out->arg = arg; + out->output_size_offset = output_size_offset; + out->fixed_size = fixed_size; + out->orig_output_size = output_size; + return 0; +} + +int ncr_out_finish(struct ncr_out *out) +{ + size_t buf_size; + + buf_size = (char *)out->p - (char *)out->buf; + if (buf_size != 0) { + if (unlikely(copy_to_user((char __user *)out->arg + + out->fixed_size, + out->buf, buf_size))) + return -EFAULT; + } + + return update_output_size(out->arg, out->output_size_offset, + out->orig_output_size, + out->fixed_size + buf_size); +} + +void ncr_out_free(struct ncr_out *out) +{ + kfree(out->buf); +} + +struct nlattr *ncr_out_reserve(struct ncr_out *out, int attrtype, int attrlen) +{ + size_t needed; + struct nlattr *nla; + + needed = nla_total_size(attrlen); + if (out->left < needed) + ERR_PTR(-ERANGE); + nla = out->p; + out->p = (char *)out->p + needed; + out->left -= needed; + + nla->nla_len = nla_attr_size(attrlen); + nla->nla_type = attrtype; + memset((unsigned char *)nla + nla->nla_len, 0, nla_padlen(attrlen)); + return nla; +} + +int ncr_out_put(struct ncr_out *out, int attrtype, int attrlen, const void *data) +{ + struct nlattr *nla; + + nla = ncr_out_reserve(out, attrtype, attrlen); + if (IS_ERR(nla)) + return PTR_ERR(nla); + memcpy(nla_data(nla), data, attrlen); + return 0; +} + +/** + * Initialize a nlattr with @attrtype as a buffer of maximum possible size in + * @out. The buffer must be finalized using ncr_out_commit_buffer. + */ +struct nlattr *ncr_out_begin_buffer(struct ncr_out *out, int attrtype) +{ + struct nlattr *nla; + + if (out->left < NLA_HDRLEN) + return ERR_PTR(-ERANGE); + nla = out->p; + + /* Ensure the rounding down of out->left does not decrease it below + NLA_HDRLEN. */ + BUILD_BUG_ON(NLA_ALIGN(NLA_HDRLEN) != NLA_HDRLEN); + nla->nla_len = out->left & ~(NLA_ALIGNTO - 1); + nla->nla_type = attrtype; + return nla; +} + +/** + * Set the length of buffer initialied in @out with ncr_out_begin_buffer() to + * @attrlen and allow adding more attributes. + */ +void ncr_out_commit_buffer(struct ncr_out *out, int attrlen) +{ + struct nlattr *nla; + size_t total; + + nla = out->p; + nla->nla_len = nla_attr_size(attrlen); + memset((unsigned char *)nla + nla->nla_len, 0, nla_padlen(attrlen)); + total = nla_total_size(attrlen); + + out->p = (char *)out->p + total; + out->left -= total; +} diff --git a/utils.h b/utils.h new file mode 100644 index 00000000000..2802afa7758 --- /dev/null +++ b/utils.h @@ -0,0 +1,98 @@ +#ifndef NCR_UTILS_H +#define NCR_UTILS_H + +#include +#include + +#define NCR_MAX_ATTR_SIZE 4096 + +struct nlattr; + +struct ncr_out { + void *buf, *p; + size_t left; + void __user *arg; + size_t output_size_offset, fixed_size; + u32 orig_output_size; +}; + +#define __NCR_VERIFY_FIXED_SIZE(fixed) \ + (BUILD_BUG_ON(sizeof(*(fixed)) != NLA_ALIGN(sizeof(*(fixed))))) +#define __NCR_VERIFY_TB(tb) (BUILD_BUG_ON(ARRAY_SIZE(tb) != NCR_ATTR_MAX + 1)) + +extern u32 __ncr_u32_type_check; +#define __OUT_SIZE_OFF(fixed) \ + ((void)(&(fixed)->output_size == &__ncr_u32_type_check), \ + (char *)&(fixed)->output_size - (char *)(fixed)) + + +/** + * Load *@fixed and a sequence of netlink-like attributes from @arg. @fixed + * contains "input_size", which is an u32 filled with total input size, + * including the attributes, which are parsed into @tb. + */ +#define NCR_GET_INPUT_ARGS(fixed, tb, arg) \ + (__NCR_VERIFY_FIXED_SIZE(fixed), \ + __NCR_VERIFY_TB(tb), \ + __ncr_get_input_args(fixed, tb, sizeof(*(fixed)), \ + &(fixed)->input_size, arg)) +void *__ncr_get_input_args(void *fixed, struct nlattr *tb[], size_t fixed_size, + u32 *input_size_ptr, const void __user *arg); + +/** + * Load *@fixed and a sequence of netlink-like attributes from @arg. @fixed + * contains "input_size", which is an u32 filled with total input size, + * including the attributes, which are parsed into @tb. In addition, indicate + * to the user through u32 "output_size" that no output attributes will be + * returned. + */ +#define NCR_GET_INPUT_ARGS_NO_OUTPUT(fixed, tb, arg) \ + (__NCR_VERIFY_FIXED_SIZE(fixed), \ + __NCR_VERIFY_TB(tb), \ + __ncr_get_input_args_no_output(fixed, tb, sizeof(*(fixed)), \ + &(fixed)->input_size, \ + __OUT_SIZE_OFF(fixed), arg)) +void *__ncr_get_input_args_no_output(void *fixed, struct nlattr *tb[], + size_t fixed_size, u32 *input_size_ptr, + size_t output_size_offset, + void __user *arg); + +/** + * Return a new output attribute context for attributes of *@fixed. @fixed + * contains "output_size", an u32 containing total output size, including + * @fixed. Store @arg for later ncr_out_finish(). + */ +#define NCR_OUT_INIT(out, fixed, arg) \ + (__NCR_VERIFY_FIXED_SIZE(fixed), \ + __ncr_out_init((out), (fixed), sizeof(*(fixed)), \ + __OUT_SIZE_OFF(fixed), (arg))) +int __ncr_out_init(struct ncr_out *out, const void *fixed, size_t fixed_size, + size_t output_size_offset, void __user *arg); + +/** + * Write attributes from @out to user space and update user-space output_size. + */ +int ncr_out_finish(struct ncr_out *out); + +void ncr_out_free(struct ncr_out *out); + +int ncr_out_put(struct ncr_out *out, int attrtype, int attrlen, + const void *data); + +static inline int ncr_out_put_u32(struct ncr_out *out, int attrtype, u32 value) +{ + return ncr_out_put(out, attrtype, sizeof(value), &value); +} + +static inline int ncr_out_put_string(struct ncr_out *out, int attrtype, + const char *value) +{ + return ncr_out_put(out, attrtype, strlen(value) + 1, value); +} + +struct nlattr *ncr_out_reserve(struct ncr_out *out, int attrtype, int attrlen); + +struct nlattr *ncr_out_begin_buffer(struct ncr_out *out, int attrtype); +void ncr_out_commit_buffer(struct ncr_out *out, int attrlen); + +#endif -- cgit From dbb2f11a32cdde060798c14cdac33f95e22f39bb Mon Sep 17 00:00:00 2001 From: Miloslav Trmač Date: Wed, 18 Aug 2010 03:29:12 +0200 Subject: Simplify algorithm lookup by nla --- ncr-int.h | 3 +++ ncr-sessions.c | 8 ++++++++ 2 files changed, 11 insertions(+) diff --git a/ncr-int.h b/ncr-int.h index b7c6ed4b132..2a459071a33 100644 --- a/ncr-int.h +++ b/ncr-int.h @@ -14,6 +14,8 @@ #define err() printk(KERN_DEBUG"ncr: %s: %s: %d\n", __FILE__, __func__, __LINE__) +struct nlattr; + struct algo_properties_st { ncr_algorithm_t algo; const char *kstr; @@ -172,6 +174,7 @@ int key_to_storage_data( uint8_t** data, size_t * data_size, const struct key_it /* misc helper macros */ const struct algo_properties_st *_ncr_algo_to_properties(ncr_algorithm_t algo); +const struct algo_properties_st *_ncr_nla_to_properties(const struct nlattr *nla); const struct algo_properties_st *ncr_key_params_get_sign_hash(const struct algo_properties_st *algo, struct ncr_key_params_st * params); int _ncr_key_get_sec_level(struct key_item_st* item); diff --git a/ncr-sessions.c b/ncr-sessions.c index 711963b618e..320a061d506 100644 --- a/ncr-sessions.c +++ b/ncr-sessions.c @@ -29,6 +29,7 @@ #include "ncr-int.h" #include #include +#include static int _ncr_session_update_key(struct ncr_lists* lists, struct ncr_session_op_st* op); static void _ncr_session_remove(struct ncr_lists *lst, ncr_session_t desc); @@ -214,6 +215,13 @@ const struct algo_properties_st *_ncr_algo_to_properties(ncr_algorithm_t algo) return NULL; } +const struct algo_properties_st *_ncr_nla_to_properties(const struct nlattr *nla) +{ + if (nla == NULL) + return NULL; + return _ncr_algo_to_properties(nla_get_u32(nla)); +} + static int _ncr_session_init(struct ncr_lists* lists, struct ncr_session_st* session) { struct session_item_st* ns = NULL; -- cgit From 491fc6dd6fff9b4d9676e03189ae76538184b51d Mon Sep 17 00:00:00 2001 From: Miloslav Trmač Date: Wed, 11 Aug 2010 17:46:44 +0200 Subject: Convert *_KEY_INIT --- examples/ncr.c | 33 ++++++++++++++++++++++----------- examples/pk.c | 30 ++++++++++++++++++++---------- examples/speed.c | 3 ++- ncr-int.h | 2 +- ncr-key.c | 9 ++------- ncr.c | 6 ++++-- ncr.h | 2 +- 7 files changed, 52 insertions(+), 33 deletions(-) diff --git a/examples/ncr.c b/examples/ncr.c index 5169a149e31..8b3320662ea 100644 --- a/examples/ncr.c +++ b/examples/ncr.c @@ -51,7 +51,8 @@ test_ncr_key(int cfd) memcpy(data_bak, data, sizeof(data)); /* convert it to key */ - if (ioctl(cfd, NCRIO_KEY_INIT, &key)) { + key = ioctl(cfd, NCRIO_KEY_INIT); + if (key == -1) { perror("ioctl(NCRIO_KEY_INIT)"); return 1; } @@ -112,7 +113,8 @@ test_ncr_key(int cfd) fprintf(stdout, "\tKey import...\n"); /* convert it to key */ - if (ioctl(cfd, NCRIO_KEY_INIT, &key)) { + key = ioctl(cfd, NCRIO_KEY_INIT); + if (key == -1) { fprintf(stderr, "Error: %s:%d\n", __func__, __LINE__); perror("ioctl(NCRIO_KEY_INIT)"); return 1; @@ -162,7 +164,8 @@ test_ncr_key(int cfd) * try to export it. */ fprintf(stdout, "\tKey protection of non-exportable keys...\n"); - if (ioctl(cfd, NCRIO_KEY_INIT, &key)) { + key = ioctl(cfd, NCRIO_KEY_INIT); + if (key == -1) { fprintf(stderr, "Error: %s:%d\n", __func__, __LINE__); perror("ioctl(NCRIO_KEY_INIT)"); return 1; @@ -224,7 +227,8 @@ test_ncr_wrap_key(int cfd) fprintf(stdout, "\tKey Wrap test...\n"); /* convert it to key */ - if (ioctl(cfd, NCRIO_KEY_INIT, &key)) { + key = ioctl(cfd, NCRIO_KEY_INIT); + if (key == -1) { perror("ioctl(NCRIO_KEY_INIT)"); return 1; } @@ -248,7 +252,8 @@ test_ncr_wrap_key(int cfd) /* convert it to key */ - if (ioctl(cfd, NCRIO_KEY_INIT, &key2)) { + key2 = ioctl(cfd, NCRIO_KEY_INIT); + if (key2 == -1) { perror("ioctl(NCRIO_KEY_INIT)"); return 1; } @@ -315,7 +320,8 @@ test_ncr_wrap_key(int cfd) return 1; } - if (ioctl(cfd, NCRIO_KEY_INIT, &key2)) { + key2 = ioctl(cfd, NCRIO_KEY_INIT); + if (key2 == -1) { perror("ioctl(NCRIO_KEY_INIT)"); return 1; } @@ -474,7 +480,8 @@ test_ncr_store_wrap_key(int cfd) fprintf(stdout, "\tKey Storage wrap test...\n"); /* convert it to key */ - if (ioctl(cfd, NCRIO_KEY_INIT, &key2)) { + key2 = ioctl(cfd, NCRIO_KEY_INIT); + if (key2 == -1) { perror("ioctl(NCRIO_KEY_INIT)"); return 1; } @@ -520,7 +527,8 @@ test_ncr_store_wrap_key(int cfd) return 1; } - if (ioctl(cfd, NCRIO_KEY_INIT, &key2)) { + key2 = ioctl(cfd, NCRIO_KEY_INIT); + if (key2 == -1) { fprintf(stderr, "Error: %s:%d\n", __func__, __LINE__); perror("ioctl(NCRIO_KEY_INIT)"); return 1; @@ -608,7 +616,8 @@ test_ncr_aes(int cfd) int data_size; /* convert it to key */ - if (ioctl(cfd, NCRIO_KEY_INIT, &key)) { + key = ioctl(cfd, NCRIO_KEY_INIT); + if (key == -1) { perror("ioctl(NCRIO_KEY_INIT)"); return 1; } @@ -816,7 +825,8 @@ test_ncr_hash(int cfd) struct ncr_session_once_op_st nop; /* convert it to key */ - if (ioctl(cfd, NCRIO_KEY_INIT, &key)) { + key = ioctl(cfd, NCRIO_KEY_INIT); + if (key == -1) { perror("ioctl(NCRIO_KEY_INIT)"); return 1; } @@ -902,7 +912,8 @@ test_ncr_hash_key(int cfd) const uint8_t *output = (void*)"\xe2\xd7\x2c\x2e\x14\xad\x97\xc8\xd2\xdb\xce\xd8\xb3\x52\x9f\x1c\xb3\x2c\x5c\xec"; /* convert it to key */ - if (ioctl(cfd, NCRIO_KEY_INIT, &key)) { + key = ioctl(cfd, NCRIO_KEY_INIT); + if (key == -1) { perror("ioctl(NCRIO_KEY_INIT)"); return 1; } diff --git a/examples/pk.c b/examples/pk.c index 032ae9864d9..d2e74a92444 100644 --- a/examples/pk.c +++ b/examples/pk.c @@ -346,13 +346,15 @@ struct ncr_key_derivation_params_st kderive; } /* generate a DH key */ - if (ioctl(cfd, NCRIO_KEY_INIT, &private1)) { + private1 = ioctl(cfd, NCRIO_KEY_INIT); + if (private1 == -1) { fprintf(stderr, "Error: %s:%d\n", __func__, __LINE__); perror("ioctl(NCRIO_KEY_INIT)"); return 1; } - if (ioctl(cfd, NCRIO_KEY_INIT, &public1)) { + public1 = ioctl(cfd, NCRIO_KEY_INIT); + if (public1 == -1) { fprintf(stderr, "Error: %s:%d\n", __func__, __LINE__); perror("ioctl(NCRIO_KEY_INIT)"); return 1; @@ -375,13 +377,15 @@ struct ncr_key_derivation_params_st kderive; } /* generate another DH key */ - if (ioctl(cfd, NCRIO_KEY_INIT, &private2)) { + private2 = ioctl(cfd, NCRIO_KEY_INIT); + if (private2 == -1) { fprintf(stderr, "Error: %s:%d\n", __func__, __LINE__); perror("ioctl(NCRIO_KEY_INIT)"); return 1; } - if (ioctl(cfd, NCRIO_KEY_INIT, &public2)) { + public2 = ioctl(cfd, NCRIO_KEY_INIT); + if (public2 == -1) { fprintf(stderr, "Error: %s:%d\n", __func__, __LINE__); perror("ioctl(NCRIO_KEY_INIT)"); return 1; @@ -432,7 +436,8 @@ struct ncr_key_derivation_params_st kderive; y2_size = keydata.idata_size; /* z1=y1^x2 */ - if (ioctl(cfd, NCRIO_KEY_INIT, &z1)) { + z1 = ioctl(cfd, NCRIO_KEY_INIT); + if (z1 == -1) { fprintf(stderr, "Error: %s:%d\n", __func__, __LINE__); perror("ioctl(NCRIO_KEY_INIT)"); return 1; @@ -453,7 +458,8 @@ struct ncr_key_derivation_params_st kderive; } /* z2=y2^x1 */ - if (ioctl(cfd, NCRIO_KEY_INIT, &z2)) { + z2 = ioctl(cfd, NCRIO_KEY_INIT); + if (z2 == -1) { fprintf(stderr, "Error: %s:%d\n", __func__, __LINE__); perror("ioctl(NCRIO_KEY_INIT)"); return 1; @@ -889,13 +895,15 @@ static int test_ncr_rsa(int cfd) fflush(stdout); /* convert it to key */ - if (ioctl(cfd, NCRIO_KEY_INIT, &privkey)) { + privkey = ioctl(cfd, NCRIO_KEY_INIT); + if (privkey == -1) { fprintf(stderr, "Error: %s:%d\n", __func__, __LINE__); perror("ioctl(NCRIO_KEY_INIT)"); return 1; } - if (ioctl(cfd, NCRIO_KEY_INIT, &pubkey)) { + pubkey = ioctl(cfd, NCRIO_KEY_INIT); + if (pubkey == -1) { fprintf(stderr, "Error: %s:%d\n", __func__, __LINE__); perror("ioctl(NCRIO_KEY_INIT)"); return 1; @@ -1000,13 +1008,15 @@ static int test_ncr_dsa(int cfd) fflush(stdout); /* convert it to key */ - if (ioctl(cfd, NCRIO_KEY_INIT, &privkey)) { + privkey = ioctl(cfd, NCRIO_KEY_INIT); + if (privkey == -1) { fprintf(stderr, "Error: %s:%d\n", __func__, __LINE__); perror("ioctl(NCRIO_KEY_INIT)"); return 1; } - if (ioctl(cfd, NCRIO_KEY_INIT, &pubkey)) { + pubkey = ioctl(cfd, NCRIO_KEY_INIT); + if (pubkey == -1) { fprintf(stderr, "Error: %s:%d\n", __func__, __LINE__); perror("ioctl(NCRIO_KEY_INIT)"); return 1; diff --git a/examples/speed.c b/examples/speed.c index a46cedbc146..6227cad4b40 100644 --- a/examples/speed.c +++ b/examples/speed.c @@ -79,7 +79,8 @@ int encrypt_data_ncr_direct(int cfd, int algo, int chunksize) struct ncr_key_generate_st kgen; struct ncr_session_once_op_st nop; - if (ioctl(cfd, NCRIO_KEY_INIT, &key)) { + key = ioctl(cfd, NCRIO_KEY_INIT); + if (key == -1) { fprintf(stderr, "Error: %s:%d\n", __func__, __LINE__); perror("ioctl(NCRIO_KEY_INIT)"); return 1; diff --git a/ncr-int.h b/ncr-int.h index 2a459071a33..06ed48364cb 100644 --- a/ncr-int.h +++ b/ncr-int.h @@ -117,7 +117,7 @@ void ncr_key_clear(struct key_item_st* item); void ncr_key_assign_flags(struct key_item_st* item, unsigned int flags); /* key handling */ -int ncr_key_init(struct ncr_lists *lst, void __user* arg); +int ncr_key_init(struct ncr_lists *lst); int ncr_key_deinit(struct ncr_lists *lst, void __user* arg); int ncr_key_export(struct ncr_lists *lst, void __user* arg); int ncr_key_import(struct ncr_lists *lst, void __user* arg); diff --git a/ncr-key.c b/ncr-key.c index 95228f22859..f54ef334efb 100644 --- a/ncr-key.c +++ b/ncr-key.c @@ -148,7 +148,7 @@ static void _ncr_key_remove(struct ncr_lists *lst, ncr_key_t desc) _ncr_key_item_put(item); } -int ncr_key_init(struct ncr_lists *lst, void __user* arg) +int ncr_key_init(struct ncr_lists *lst) { ncr_key_t desc; struct key_item_st* key; @@ -187,12 +187,7 @@ int ncr_key_init(struct ncr_lists *lst, void __user* arg) desc = key->desc; mutex_unlock(&lst->key_idr_mutex); - ret = copy_to_user(arg, &desc, sizeof(desc)); - if (unlikely(ret)) { - _ncr_key_remove(lst, desc); - return -EFAULT; - } - return ret; + return desc; err_limits: ncr_limits_remove(current_euid(), task_pid_nr(current), LIMIT_TYPE_KEY); diff --git a/ncr.c b/ncr.c index 9549b93a697..ec00b7d9750 100644 --- a/ncr.c +++ b/ncr.c @@ -125,8 +125,8 @@ ncr_ioctl(struct ncr_lists *lst, unsigned int cmd, unsigned long arg_) BUG(); switch (cmd) { - case NCRIO_KEY_INIT: - return ncr_key_init(lst, arg); + case NCRIO_KEY_INIT: + return ncr_key_init(lst); case NCRIO_KEY_DEINIT: return ncr_key_deinit(lst, arg); case NCRIO_KEY_GENERATE: @@ -173,6 +173,8 @@ ncr_compat_ioctl(struct ncr_lists *lst, unsigned int cmd, unsigned long arg_) BUG(); switch (cmd) { + case NCRIO_KEY_INIT: + return ncr_ioctl(lst, cmd, arg_); default: return -EINVAL; } diff --git a/ncr.h b/ncr.h index 5819168620c..691a4dab22c 100644 --- a/ncr.h +++ b/ncr.h @@ -222,7 +222,7 @@ struct ncr_key_data_st { ncr_algorithm_t algorithm; /* valid for public/private keys */ }; -#define NCRIO_KEY_INIT _IOW ('c', 204, ncr_key_t) +#define NCRIO_KEY_INIT _IO('c', 204) /* generate a secret key */ #define NCRIO_KEY_GENERATE _IOR ('c', 205, struct ncr_key_generate_st) /* generate a public key pair */ -- cgit From 2c51dc1a549816a34cb78230bf656537ecd21961 Mon Sep 17 00:00:00 2001 From: Miloslav Trmač Date: Wed, 18 Aug 2010 03:42:55 +0200 Subject: Convert *_KEY_GENERATE --- examples/ncr.c | 54 +++++++++++++++++++++++++++++++++++++++++------------- examples/speed.c | 30 +++++++++++++++++++++++------- ncr-int.h | 3 ++- ncr-key.c | 33 ++++++++++++++++++++------------- ncr.c | 24 ++++++++++++++++++++++-- ncr.h | 8 +++++++- 6 files changed, 115 insertions(+), 37 deletions(-) diff --git a/examples/ncr.c b/examples/ncr.c index 8b3320662ea..568b63cb068 100644 --- a/examples/ncr.c +++ b/examples/ncr.c @@ -13,11 +13,15 @@ #include #include #include +#include +#include #include "../ncr.h" #include #define DATA_SIZE 4096 +#define ALIGN_NL __attribute__((aligned(NLA_ALIGNTO))) + static void randomize_data(uint8_t * data, size_t data_size) { int i; @@ -33,7 +37,15 @@ int i; static int test_ncr_key(int cfd) { - struct ncr_key_generate_st kgen; + struct __attribute__((packed)) { + struct ncr_key_generate f; + struct nlattr algo_head ALIGN_NL; + uint32_t algo ALIGN_NL; + struct nlattr flags_head ALIGN_NL; + uint32_t flags ALIGN_NL; + struct nlattr bits_head ALIGN_NL; + uint32_t bits ALIGN_NL; + } kgen; ncr_key_t key; struct ncr_key_data_st keydata; uint8_t data[KEY_DATA_SIZE]; @@ -120,14 +132,22 @@ test_ncr_key(int cfd) return 1; } - kgen.desc = key; - kgen.params.algorithm = NCR_ALG_AES_CBC; - kgen.params.keyflags = NCR_KEY_FLAG_EXPORTABLE; - kgen.params.params.secret.bits = 128; /* 16 bytes */ - + memset(&kgen.f, 0, sizeof(kgen.f)); + kgen.f.input_size = sizeof(kgen); + kgen.f.key = key; + kgen.algo_head.nla_len = NLA_HDRLEN + sizeof(kgen.algo); + kgen.algo_head.nla_type = NCR_ATTR_ALGORITHM; + kgen.algo = NCR_ALG_AES_CBC; + kgen.flags_head.nla_len = NLA_HDRLEN + sizeof(kgen.flags); + kgen.flags_head.nla_type = NCR_ATTR_KEY_FLAGS; + kgen.flags = NCR_KEY_FLAG_EXPORTABLE; + kgen.bits_head.nla_len = NLA_HDRLEN + sizeof(kgen.bits); + kgen.bits_head.nla_type = NCR_ATTR_SECRET_KEY_BITS; + kgen.bits = 128; /* 16 bytes */ + if (ioctl(cfd, NCRIO_KEY_GENERATE, &kgen)) { fprintf(stderr, "Error: %s:%d\n", __func__, __LINE__); - perror("ioctl(NCRIO_KEY_IMPORT)"); + perror("ioctl(NCRIO_KEY_GENERATE)"); return 1; } @@ -171,13 +191,21 @@ test_ncr_key(int cfd) return 1; } - kgen.desc = key; - kgen.params.algorithm = NCR_ALG_AES_CBC; - kgen.params.keyflags = 0; - kgen.params.params.secret.bits = 128; /* 16 bytes */ - + memset(&kgen.f, 0, sizeof(kgen.f)); + kgen.f.input_size = sizeof(kgen); + kgen.f.key = key; + kgen.algo_head.nla_len = NLA_HDRLEN + sizeof(kgen.algo); + kgen.algo_head.nla_type = NCR_ATTR_ALGORITHM; + kgen.algo = NCR_ALG_AES_CBC; + kgen.flags_head.nla_len = NLA_HDRLEN + sizeof(kgen.flags); + kgen.flags_head.nla_type = NCR_ATTR_KEY_FLAGS; + kgen.flags = 0; + kgen.bits_head.nla_len = NLA_HDRLEN + sizeof(kgen.flags); + kgen.bits_head.nla_type = NCR_ATTR_SECRET_KEY_BITS; + kgen.bits = 128; /* 16 bytes */ + if (ioctl(cfd, NCRIO_KEY_GENERATE, &kgen)) { - perror("ioctl(NCRIO_KEY_IMPORT)"); + perror("ioctl(NCRIO_KEY_GENERATE)"); return 1; } diff --git a/examples/speed.c b/examples/speed.c index 6227cad4b40..9c2e8b8d935 100644 --- a/examples/speed.c +++ b/examples/speed.c @@ -17,6 +17,7 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ #include +#include #include #include #include @@ -24,10 +25,14 @@ #include #include #include +#include #include #include +#include #include "../ncr.h" +#define ALIGN_NL __attribute__((aligned(NLA_ALIGNTO))) + static double udifftimeval(struct timeval start, struct timeval end) { return (double)(end.tv_usec - start.tv_usec) + @@ -76,7 +81,13 @@ int encrypt_data_ncr_direct(int cfd, int algo, int chunksize) double secs, ddata, dspeed; char metric[16]; ncr_key_t key; - struct ncr_key_generate_st kgen; + struct __attribute__((packed)) { + struct ncr_key_generate f; + struct nlattr algo_head ALIGN_NL; + uint32_t algo ALIGN_NL; + struct nlattr bits_head ALIGN_NL; + uint32_t bits ALIGN_NL; + } kgen; struct ncr_session_once_op_st nop; key = ioctl(cfd, NCRIO_KEY_INIT); @@ -86,14 +97,19 @@ int encrypt_data_ncr_direct(int cfd, int algo, int chunksize) return 1; } - kgen.desc = key; - kgen.params.algorithm = NCR_ALG_AES_CBC; - kgen.params.keyflags = NCR_KEY_FLAG_EXPORTABLE; - kgen.params.params.secret.bits = 128; /* 16 bytes */ - + memset(&kgen.f, 0, sizeof(kgen.f)); + kgen.f.input_size = sizeof(kgen); + kgen.f.key = key; + kgen.algo_head.nla_len = NLA_HDRLEN + sizeof(kgen.algo); + kgen.algo_head.nla_type = NCR_ATTR_ALGORITHM; + kgen.algo = NCR_ALG_AES_CBC; + kgen.bits_head.nla_len = NLA_HDRLEN + sizeof(kgen.bits); + kgen.bits_head.nla_type = NCR_ATTR_SECRET_KEY_BITS; + kgen.bits = 128; /* 16 bytes */ + if (ioctl(cfd, NCRIO_KEY_GENERATE, &kgen)) { fprintf(stderr, "Error: %s:%d\n", __func__, __LINE__); - perror("ioctl(NCRIO_KEY_IMPORT)"); + perror("ioctl(NCRIO_KEY_GENERATE)"); return 1; } diff --git a/ncr-int.h b/ncr-int.h index 06ed48364cb..2a7e2f4072c 100644 --- a/ncr-int.h +++ b/ncr-int.h @@ -122,7 +122,8 @@ int ncr_key_deinit(struct ncr_lists *lst, void __user* arg); int ncr_key_export(struct ncr_lists *lst, void __user* arg); int ncr_key_import(struct ncr_lists *lst, void __user* arg); void ncr_key_list_deinit(struct ncr_lists *lst); -int ncr_key_generate(struct ncr_lists *lst, void __user* arg); +int ncr_key_generate(struct ncr_lists *lst, const struct ncr_key_generate *gen, + struct nlattr *tb[]); int ncr_key_info(struct ncr_lists *lst, void __user* arg); int ncr_key_generate_pair(struct ncr_lists *lst, void __user* arg); diff --git a/ncr-key.c b/ncr-key.c index f54ef334efb..4462ef11284 100644 --- a/ncr-key.c +++ b/ncr-key.c @@ -28,6 +28,7 @@ #include #include #include +#include #include "ncr.h" #include "ncr-int.h" @@ -423,20 +424,16 @@ void ncr_key_clear(struct key_item_st* item) /* Generate a secret key */ -int ncr_key_generate(struct ncr_lists *lst, void __user* arg) +int ncr_key_generate(struct ncr_lists *lst, const struct ncr_key_generate *gen, + struct nlattr *tb[]) { -struct ncr_key_generate_st gen; +const struct nlattr *nla; struct key_item_st* item = NULL; const struct algo_properties_st *algo; int ret; size_t size; - if (unlikely(copy_from_user(&gen, arg, sizeof(gen)))) { - err(); - return -EFAULT; - } - - ret = ncr_key_item_get_write( &item, lst, gen.desc); + ret = ncr_key_item_get_write(&item, lst, gen->key); if (ret < 0) { err(); return ret; @@ -445,9 +442,11 @@ size_t size; ncr_key_clear(item); /* we generate only secret keys */ - ncr_key_assign_flags(item, gen.params.keyflags); + nla = tb[NCR_ATTR_KEY_FLAGS]; + if (nla != NULL) + ncr_key_assign_flags(item, nla_get_u32(nla)); - algo = _ncr_algo_to_properties(gen.params.algorithm); + algo = _ncr_nla_to_properties(tb[NCR_ATTR_ALGORITHM]); if (algo == NULL) { err(); ret = -EINVAL; @@ -455,11 +454,19 @@ size_t size; } item->type = algo->key_type; if (item->type == NCR_KEY_TYPE_SECRET) { + u32 key_bits; + item->algorithm = algo; - size = gen.params.params.secret.bits/8; - if ((gen.params.params.secret.bits % 8 != 0) || - (size > NCR_CIPHER_MAX_KEY_LEN)) { + nla = tb[NCR_ATTR_SECRET_KEY_BITS]; + if (nla == NULL) { + err(); + ret = -EINVAL; + goto fail; + } + key_bits = nla_get_u32(nla); + size = key_bits / 8; + if (key_bits % 8 != 0 || size > NCR_CIPHER_MAX_KEY_LEN) { err(); ret = -EINVAL; goto fail; diff --git a/ncr.c b/ncr.c index ec00b7d9750..bc78ede107a 100644 --- a/ncr.c +++ b/ncr.c @@ -34,6 +34,7 @@ #include #include "ncr.h" #include "ncr-int.h" +#include "utils.h" #include /* This is the master wrapping key for storage of keys @@ -120,17 +121,32 @@ int ncr_ioctl(struct ncr_lists *lst, unsigned int cmd, unsigned long arg_) { void __user *arg = (void __user *)arg_; + struct nlattr *tb[NCR_ATTR_MAX + 1]; + void *attr_buf; + int ret; if (unlikely(!lst)) BUG(); switch (cmd) { +#define CASE_NO_OUTPUT(LABEL, STRUCT, FUNCTION) \ + case (LABEL): { \ + struct STRUCT data; \ + \ + attr_buf = NCR_GET_INPUT_ARGS_NO_OUTPUT(&data, tb, arg); \ + if (IS_ERR(attr_buf)) { \ + err(); \ + return PTR_ERR(attr_buf); \ + } \ + ret = (FUNCTION)(lst, &data, tb); \ + break; \ + } + case NCRIO_KEY_INIT: return ncr_key_init(lst); + CASE_NO_OUTPUT(NCRIO_KEY_GENERATE, ncr_key_generate, ncr_key_generate); case NCRIO_KEY_DEINIT: return ncr_key_deinit(lst, arg); - case NCRIO_KEY_GENERATE: - return ncr_key_generate(lst, arg); case NCRIO_KEY_EXPORT: return ncr_key_export(lst, arg); case NCRIO_KEY_IMPORT: @@ -162,7 +178,10 @@ ncr_ioctl(struct ncr_lists *lst, unsigned int cmd, unsigned long arg_) return ncr_key_derive(lst, arg); default: return -EINVAL; +#undef CASE_NO_OUTPUT } + kfree(attr_buf); + return ret; } #ifdef CONFIG_COMPAT @@ -174,6 +193,7 @@ ncr_compat_ioctl(struct ncr_lists *lst, unsigned int cmd, unsigned long arg_) switch (cmd) { case NCRIO_KEY_INIT: + case NCRIO_KEY_GENERATE: return ncr_ioctl(lst, cmd, arg_); default: return -EINVAL; diff --git a/ncr.h b/ncr.h index 691a4dab22c..542c3cc520b 100644 --- a/ncr.h +++ b/ncr.h @@ -148,6 +148,12 @@ struct ncr_key_generate_st { struct ncr_key_generate_params_st params; }; +struct ncr_key_generate { + __u32 input_size, output_size; + ncr_key_t key; + __NL_ATTRIBUTES; +}; + typedef enum { RSA_PKCS1_V1_5, /* both signatures and encryption */ RSA_PKCS1_OAEP, /* for encryption only */ @@ -224,7 +230,7 @@ struct ncr_key_data_st { #define NCRIO_KEY_INIT _IO('c', 204) /* generate a secret key */ -#define NCRIO_KEY_GENERATE _IOR ('c', 205, struct ncr_key_generate_st) +#define NCRIO_KEY_GENERATE _IOWR('c', 205, struct ncr_key_generate) /* generate a public key pair */ #define NCRIO_KEY_GENERATE_PAIR _IOR ('c', 206, struct ncr_key_generate_st) /* derive a new key from an old one */ -- cgit From b327f41fefe390d6db4832fe44f3cf37d86514c0 Mon Sep 17 00:00:00 2001 From: Miloslav Trmač Date: Thu, 12 Aug 2010 18:44:36 +0200 Subject: Convert *_KEY_GENERATE_PAIR --- examples/pk.c | 166 +++++++++++++++++++++++++++++++++++++++++++--------------- ncr-int.h | 4 +- ncr-key.c | 27 +++++----- ncr-pk.c | 100 +++++++++++++++++++---------------- ncr-pk.h | 5 +- ncr.c | 5 +- ncr.h | 57 ++++++-------------- utils.c | 6 +++ 8 files changed, 225 insertions(+), 145 deletions(-) diff --git a/examples/pk.c b/examples/pk.c index d2e74a92444..bb73f289103 100644 --- a/examples/pk.c +++ b/examples/pk.c @@ -4,6 +4,7 @@ * Placed under public domain. * */ +#include #include #include #include @@ -11,8 +12,10 @@ #include #include #include +#include #include #include +#include #include "../ncr.h" #include #include @@ -23,6 +26,8 @@ #define DATA_SIZE 4096 +#define ALIGN_NL __attribute__((aligned(NLA_ALIGNTO))) + static void print_hex_datum (gnutls_datum_t * dat) { @@ -307,7 +312,15 @@ const char dh_params_txt[] = "-----BEGIN DH PARAMETERS-----\n"\ static int test_ncr_dh(int cfd) { -struct ncr_key_generate_st kgen; +struct __attribute__((packed)) { + struct ncr_key_generate_pair f; + struct nlattr algo_head ALIGN_NL; + uint32_t algo ALIGN_NL; + struct nlattr flags_head ALIGN_NL; + uint32_t flags ALIGN_NL; + unsigned char buffer[DATA_SIZE] ALIGN_NL; +} kgen; +struct nlattr *nla; ncr_key_t private1, public1, public2, private2; ncr_key_t z1, z2; int ret; @@ -360,19 +373,30 @@ struct ncr_key_derivation_params_st kderive; return 1; } - memset(&kgen, 0, sizeof(kgen)); - kgen.desc = private1; - kgen.desc2 = public1; - kgen.params.algorithm = NCR_ALG_DH; - kgen.params.keyflags = NCR_KEY_FLAG_EXPORTABLE; - kgen.params.params.dh.p = p.data; - kgen.params.params.dh.p_size = p.size; - kgen.params.params.dh.g = g.data; - kgen.params.params.dh.g_size = g.size; + memset(&kgen.f, 0, sizeof(kgen.f)); + kgen.f.private_key = private1; + kgen.f.public_key = public1; + kgen.algo_head.nla_len = NLA_HDRLEN + sizeof(kgen.algo); + kgen.algo_head.nla_type = NCR_ATTR_ALGORITHM; + kgen.algo = NCR_ALG_DH; + kgen.flags_head.nla_len = NLA_HDRLEN + sizeof(kgen.flags); + kgen.flags_head.nla_type = NCR_ATTR_KEY_FLAGS; + kgen.flags = NCR_KEY_FLAG_EXPORTABLE; + nla = (struct nlattr *)kgen.buffer; + nla->nla_len = NLA_HDRLEN + p.size; + nla->nla_type = NCR_ATTR_DH_PRIME; + memcpy((char *)nla + NLA_HDRLEN, p.data, p.size); + nla = (struct nlattr *)((char *)nla + NLA_ALIGN(nla->nla_len)); + nla->nla_len = NLA_HDRLEN + g.size; + nla->nla_type = NCR_ATTR_DH_BASE; + memcpy((char *)nla + NLA_HDRLEN, g.data, g.size); + nla = (struct nlattr *)((char *)nla + NLA_ALIGN(nla->nla_len)); + kgen.f.input_size = (char *)nla - (char *)&kgen; + assert(kgen.f.input_size <= sizeof(kgen)); if (ioctl(cfd, NCRIO_KEY_GENERATE_PAIR, &kgen)) { fprintf(stderr, "Error: %s:%d\n", __func__, __LINE__); - perror("ioctl(NCRIO_KEY_GENERATE)"); + perror("ioctl(NCRIO_KEY_GENERATE_PAIR)"); return 1; } @@ -391,19 +415,30 @@ struct ncr_key_derivation_params_st kderive; return 1; } - memset(&kgen, 0, sizeof(kgen)); - kgen.desc = private2; - kgen.desc2 = public2; - kgen.params.algorithm = NCR_ALG_DH; - kgen.params.keyflags = NCR_KEY_FLAG_EXPORTABLE; - kgen.params.params.dh.p = p.data; - kgen.params.params.dh.p_size = p.size; - kgen.params.params.dh.g = g.data; - kgen.params.params.dh.g_size = g.size; + memset(&kgen.f, 0, sizeof(kgen.f)); + kgen.f.private_key = private2; + kgen.f.public_key = public2; + kgen.algo_head.nla_len = NLA_HDRLEN + sizeof(kgen.algo); + kgen.algo_head.nla_type = NCR_ATTR_ALGORITHM; + kgen.algo = NCR_ALG_DH; + kgen.flags_head.nla_len = NLA_HDRLEN + sizeof(kgen.flags); + kgen.flags_head.nla_type = NCR_ATTR_KEY_FLAGS; + kgen.flags = NCR_KEY_FLAG_EXPORTABLE; + nla = (struct nlattr *)kgen.buffer; + nla->nla_len = NLA_HDRLEN + p.size; + nla->nla_type = NCR_ATTR_DH_PRIME; + memcpy((char *)nla + NLA_HDRLEN, p.data, p.size); + nla = (struct nlattr *)((char *)nla + NLA_ALIGN(nla->nla_len)); + nla->nla_len = NLA_HDRLEN + g.size; + nla->nla_type = NCR_ATTR_DH_BASE; + memcpy((char *)nla + NLA_HDRLEN, g.data, g.size); + nla = (struct nlattr *)((char *)nla + NLA_ALIGN(nla->nla_len)); + kgen.f.input_size = (char *)nla - (char *)&kgen; + assert(kgen.f.input_size <= sizeof(kgen)); if (ioctl(cfd, NCRIO_KEY_GENERATE_PAIR, &kgen)) { fprintf(stderr, "Error: %s:%d\n", __func__, __LINE__); - perror("ioctl(NCRIO_KEY_GENERATE)"); + perror("ioctl(NCRIO_KEY_GENERATE_PAIR)"); return 1; } @@ -540,7 +575,15 @@ test_ncr_wrap_key3(int cfd) size_t data_size; struct ncr_key_data_st keydata; struct ncr_key_wrap_st kwrap; - struct ncr_key_generate_st kgen; + struct __attribute__((packed)) { + struct ncr_key_generate_pair f; + struct nlattr algo_head ALIGN_NL; + uint32_t algo ALIGN_NL; + struct nlattr flags_head ALIGN_NL; + uint32_t flags ALIGN_NL; + struct nlattr bits_head ALIGN_NL; + uint32_t bits ALIGN_NL; + } kgen; ncr_key_t pubkey, privkey; uint8_t data[DATA_SIZE]; /* only the first two should be allowed to be wrapped. @@ -599,12 +642,19 @@ test_ncr_wrap_key3(int cfd) fprintf(stdout, "."); fflush(stdout); - memset(&kgen, 0, sizeof(kgen)); - kgen.desc = privkey; - kgen.desc2 = pubkey; - kgen.params.algorithm = NCR_ALG_RSA; - kgen.params.keyflags = NCR_KEY_FLAG_EXPORTABLE|NCR_KEY_FLAG_WRAPPABLE; - kgen.params.params.rsa.bits = sizes[i]; + memset(&kgen.f, 0, sizeof(kgen.f)); + kgen.f.input_size = sizeof(kgen); + kgen.f.private_key = privkey; + kgen.f.public_key = pubkey; + kgen.algo_head.nla_len = NLA_HDRLEN + sizeof(kgen.algo); + kgen.algo_head.nla_type = NCR_ATTR_ALGORITHM; + kgen.algo = NCR_ALG_RSA; + kgen.flags_head.nla_len = NLA_HDRLEN + sizeof(kgen.flags); + kgen.flags_head.nla_type = NCR_ATTR_KEY_FLAGS; + kgen.flags = NCR_KEY_FLAG_EXPORTABLE|NCR_KEY_FLAG_WRAPPABLE; + kgen.bits_head.nla_len = NLA_HDRLEN + sizeof(kgen.bits); + kgen.bits_head.nla_type = NCR_ATTR_RSA_MODULUS_BITS; + kgen.bits = sizes[i]; if (ioctl(cfd, NCRIO_KEY_GENERATE_PAIR, &kgen)) { fprintf(stderr, "Error[%d-%d]: %s:%d\n", i, sizes[i], __func__, __LINE__); @@ -885,7 +935,15 @@ static int dsa_key_sign_verify(int cfd, ncr_key_t privkey, ncr_key_t pubkey) static int test_ncr_rsa(int cfd) { int ret; - struct ncr_key_generate_st kgen; + struct __attribute__((packed)) { + struct ncr_key_generate_pair f; + struct nlattr algo_head ALIGN_NL; + uint32_t algo ALIGN_NL; + struct nlattr flags_head ALIGN_NL; + uint32_t flags ALIGN_NL; + struct nlattr bits_head ALIGN_NL; + uint32_t bits ALIGN_NL; + } kgen; ncr_key_t pubkey, privkey; struct ncr_key_data_st keydata; uint8_t data[DATA_SIZE]; @@ -910,11 +968,18 @@ static int test_ncr_rsa(int cfd) } memset(&kgen, 0, sizeof(kgen)); - kgen.desc = privkey; - kgen.desc2 = pubkey; - kgen.params.algorithm = NCR_ALG_RSA; - kgen.params.keyflags = NCR_KEY_FLAG_EXPORTABLE|NCR_KEY_FLAG_WRAPPABLE; - kgen.params.params.rsa.bits = 1024; + kgen.f.input_size = sizeof(kgen); + kgen.f.private_key = privkey; + kgen.f.public_key = pubkey; + kgen.algo_head.nla_len = NLA_HDRLEN + sizeof(kgen.algo); + kgen.algo_head.nla_type = NCR_ATTR_ALGORITHM; + kgen.algo = NCR_ALG_RSA; + kgen.flags_head.nla_len = NLA_HDRLEN + sizeof(kgen.flags); + kgen.flags_head.nla_type = NCR_ATTR_KEY_FLAGS; + kgen.flags = NCR_KEY_FLAG_EXPORTABLE|NCR_KEY_FLAG_WRAPPABLE; + kgen.bits_head.nla_len = NLA_HDRLEN + sizeof(kgen.bits); + kgen.bits_head.nla_type = NCR_ATTR_RSA_MODULUS_BITS; + kgen.bits = 1024; if (ioctl(cfd, NCRIO_KEY_GENERATE_PAIR, &kgen)) { fprintf(stderr, "Error: %s:%d\n", __func__, __LINE__); @@ -998,7 +1063,17 @@ static int test_ncr_rsa(int cfd) static int test_ncr_dsa(int cfd) { int ret; - struct ncr_key_generate_st kgen; + struct __attribute__((packed)) { + struct ncr_key_generate_pair f; + struct nlattr algo_head ALIGN_NL; + uint32_t algo ALIGN_NL; + struct nlattr flags_head ALIGN_NL; + uint32_t flags ALIGN_NL; + struct nlattr q_bits_head ALIGN_NL; + uint32_t q_bits ALIGN_NL; + struct nlattr p_bits_head ALIGN_NL; + uint32_t p_bits ALIGN_NL; + } kgen; ncr_key_t pubkey, privkey; struct ncr_key_data_st keydata; uint8_t data[DATA_SIZE]; @@ -1023,12 +1098,21 @@ static int test_ncr_dsa(int cfd) } memset(&kgen, 0, sizeof(kgen)); - kgen.desc = privkey; - kgen.desc2 = pubkey; - kgen.params.algorithm = NCR_ALG_DSA; - kgen.params.keyflags = NCR_KEY_FLAG_EXPORTABLE|NCR_KEY_FLAG_WRAPPABLE; - kgen.params.params.dsa.q_bits = 160; - kgen.params.params.dsa.p_bits = 1024; + kgen.f.input_size = sizeof(kgen); + kgen.f.private_key = privkey; + kgen.f.public_key = pubkey; + kgen.algo_head.nla_len = NLA_HDRLEN + sizeof(kgen.algo); + kgen.algo_head.nla_type = NCR_ATTR_ALGORITHM; + kgen.algo = NCR_ALG_DSA; + kgen.flags_head.nla_len = NLA_HDRLEN + sizeof(kgen.flags); + kgen.flags_head.nla_type = NCR_ATTR_KEY_FLAGS; + kgen.flags = NCR_KEY_FLAG_EXPORTABLE|NCR_KEY_FLAG_WRAPPABLE; + kgen.q_bits_head.nla_len = NLA_HDRLEN + sizeof(kgen.q_bits); + kgen.q_bits_head.nla_type = NCR_ATTR_DSA_Q_BITS; + kgen.q_bits = 160; + kgen.p_bits_head.nla_len = NLA_HDRLEN + sizeof(kgen.p_bits); + kgen.p_bits_head.nla_type = NCR_ATTR_DSA_P_BITS; + kgen.p_bits = 1024; if (ioctl(cfd, NCRIO_KEY_GENERATE_PAIR, &kgen)) { fprintf(stderr, "Error: %s:%d\n", __func__, __LINE__); diff --git a/ncr-int.h b/ncr-int.h index 2a7e2f4072c..172c51ce600 100644 --- a/ncr-int.h +++ b/ncr-int.h @@ -126,7 +126,9 @@ int ncr_key_generate(struct ncr_lists *lst, const struct ncr_key_generate *gen, struct nlattr *tb[]); int ncr_key_info(struct ncr_lists *lst, void __user* arg); -int ncr_key_generate_pair(struct ncr_lists *lst, void __user* arg); +int ncr_key_generate_pair(struct ncr_lists *lst, + const struct ncr_key_generate_pair *gen, + struct nlattr *tb[]); int ncr_key_get_public(struct ncr_lists *lst, void __user* arg); int ncr_key_item_get_read(struct key_item_st**st, struct ncr_lists *lst, diff --git a/ncr-key.c b/ncr-key.c index 4462ef11284..90ba45ea020 100644 --- a/ncr-key.c +++ b/ncr-key.c @@ -634,25 +634,22 @@ fail: return ret; } -int ncr_key_generate_pair(struct ncr_lists *lst, void __user* arg) +int ncr_key_generate_pair(struct ncr_lists *lst, + const struct ncr_key_generate_pair *gen, + struct nlattr *tb[]) { -struct ncr_key_generate_st gen; +const struct nlattr *nla; struct key_item_st* private = NULL; struct key_item_st* public = NULL; int ret; - if (unlikely(copy_from_user(&gen, arg, sizeof(gen)))) { - err(); - return -EFAULT; - } - - ret = ncr_key_item_get_write( &private, lst, gen.desc); + ret = ncr_key_item_get_write(&private, lst, gen->private_key); if (ret < 0) { err(); goto fail; } - ret = ncr_key_item_get_write( &public, lst, gen.desc2); + ret = ncr_key_item_get_write(&public, lst, gen->public_key); if (ret < 0) { err(); goto fail; @@ -662,7 +659,8 @@ int ret; ncr_key_clear(private); /* we generate only secret keys */ - private->algorithm = public->algorithm = _ncr_algo_to_properties(gen.params.algorithm); + private->algorithm = public->algorithm + = _ncr_nla_to_properties(tb[NCR_ATTR_ALGORITHM]); if (private->algorithm == NULL) { err(); ret = -EINVAL; @@ -670,13 +668,16 @@ int ret; } public->type = public->algorithm->key_type; private->type = NCR_KEY_TYPE_PRIVATE; - ncr_key_assign_flags(private, gen.params.keyflags); - ncr_key_assign_flags(public, gen.params.keyflags); + nla = tb[NCR_ATTR_KEY_FLAGS]; + if (nla != NULL) { + ncr_key_assign_flags(private, nla_get_u32(nla)); + ncr_key_assign_flags(public, nla_get_u32(nla)); + } public->flags |= (NCR_KEY_FLAG_EXPORTABLE|NCR_KEY_FLAG_WRAPPABLE); if (public->type == NCR_KEY_TYPE_PUBLIC) { - ret = ncr_pk_generate(public->algorithm, &gen.params, private, public); + ret = ncr_pk_generate(public->algorithm, tb, private, public); if (ret < 0) { err(); goto fail; diff --git a/ncr-pk.c b/ncr-pk.c index f3f4265fd61..f8989184bd6 100644 --- a/ncr-pk.c +++ b/ncr-pk.c @@ -28,6 +28,7 @@ #include #include #include +#include #include "ncr.h" #include "ncr-int.h" #include @@ -222,75 +223,88 @@ int ncr_pk_unpack( struct key_item_st * key, const void * packed, size_t packed_ return 0; } -struct keygen_st { -}; +static int binary_to_ulong(unsigned long *dest, const struct nlattr *nla) +{ + unsigned long value; + const uint8_t *start, *end, *p; + + value = 0; + start = nla_data(nla); + end = start + nla_len(nla); + for (p = start; p < end; p++) { + if (value > (ULONG_MAX - *p) / 256) + return -EOVERFLOW; + value = value * 256 + *p; + } + *dest = value; + return 0; +} -int ncr_pk_generate(const struct algo_properties_st *algo, - struct ncr_key_generate_params_st * params, +int ncr_pk_generate(const struct algo_properties_st *algo, struct nlattr *tb[], struct key_item_st* private, struct key_item_st* public) { + const struct nlattr *nla; unsigned long e; int cret, ret; - uint8_t * tmp = NULL; private->algorithm = public->algorithm = algo; ret = 0; switch(algo->algo) { case NCR_ALG_RSA: - e = params->params.rsa.e; - - if (e == 0) + nla = tb[NCR_ATTR_RSA_E]; + if (nla != NULL) { + ret = binary_to_ulong(&e, nla); + if (ret != 0) + break; + } else e = 65537; - cret = rsa_make_key(params->params.rsa.bits/8, e, &private->key.pk.rsa); + + nla = tb[NCR_ATTR_RSA_MODULUS_BITS]; + if (nla == NULL) { + ret = -EINVAL; + break; + } + cret = rsa_make_key(nla_get_u32(nla) / 8, e, &private->key.pk.rsa); if (cret != CRYPT_OK) { err(); return _ncr_tomerr(cret); } break; - case NCR_ALG_DSA: - if (params->params.dsa.q_bits==0) - params->params.dsa.q_bits = 160; - if (params->params.dsa.p_bits==0) - params->params.dsa.p_bits = 1024; + case NCR_ALG_DSA: { + u32 q_bits, p_bits; - cret = dsa_make_key(params->params.dsa.q_bits/8, - params->params.dsa.p_bits/8, &private->key.pk.dsa); + nla = tb[NCR_ATTR_DSA_Q_BITS]; + if (nla != NULL) + q_bits = nla_get_u32(nla); + else + q_bits = 160; + nla = tb[NCR_ATTR_DSA_P_BITS]; + if (nla != NULL) + p_bits = nla_get_u32(nla); + else + p_bits = 1024; + cret = dsa_make_key(q_bits / 8, p_bits / 8, + &private->key.pk.dsa); if (cret != CRYPT_OK) { err(); return _ncr_tomerr(cret); } break; + } case NCR_ALG_DH: { - uint8_t * p, *g; - size_t p_size, g_size; - - p_size = params->params.dh.p_size; - g_size = params->params.dh.g_size; - - tmp = kmalloc(g_size+p_size, GFP_KERNEL); - if (tmp == NULL) { - err(); - ret = -ENOMEM; - goto fail; - } - - p = tmp; - g = &tmp[p_size]; - - if (unlikely(copy_from_user(p, params->params.dh.p, p_size))) { - err(); - ret = -EFAULT; - goto fail; - } + const struct nlattr *p, *g; - if (unlikely(copy_from_user(g, params->params.dh.g, g_size))) { - err(); - ret = -EFAULT; + p = tb[NCR_ATTR_DH_PRIME]; + g = tb[NCR_ATTR_DH_BASE]; + if (p == NULL || g == NULL) { + ret = -EINVAL; goto fail; } - - ret = dh_import_params(&private->key.pk.dh, p, p_size, g, g_size); + + ret = dh_import_params(&private->key.pk.dh, nla_data(p), + nla_len(p), nla_data(g), + nla_len(g)); if (ret < 0) { err(); goto fail; @@ -309,8 +323,6 @@ int ncr_pk_generate(const struct algo_properties_st *algo, } fail: - kfree(tmp); - if (ret < 0) { err(); return ret; diff --git a/ncr-pk.h b/ncr-pk.h index 1c8d7208737..722d1eae12b 100644 --- a/ncr-pk.h +++ b/ncr-pk.h @@ -3,6 +3,8 @@ #include +struct nlattr; + struct ncr_pk_ctx { const struct algo_properties_st *algorithm; /* algorithm */ @@ -19,8 +21,7 @@ struct ncr_pk_ctx { /* PK */ void ncr_pk_clear(struct key_item_st* key); -int ncr_pk_generate(const struct algo_properties_st *algo, - struct ncr_key_generate_params_st * params, +int ncr_pk_generate(const struct algo_properties_st *algo, struct nlattr *tb[], struct key_item_st* private, struct key_item_st* public); int ncr_pk_pack( const struct key_item_st * key, uint8_t * packed, uint32_t * packed_size); int ncr_pk_unpack( struct key_item_st * key, const void * packed, size_t packed_size); diff --git a/ncr.c b/ncr.c index bc78ede107a..4cff5090146 100644 --- a/ncr.c +++ b/ncr.c @@ -145,6 +145,8 @@ ncr_ioctl(struct ncr_lists *lst, unsigned int cmd, unsigned long arg_) case NCRIO_KEY_INIT: return ncr_key_init(lst); CASE_NO_OUTPUT(NCRIO_KEY_GENERATE, ncr_key_generate, ncr_key_generate); + CASE_NO_OUTPUT(NCRIO_KEY_GENERATE_PAIR, ncr_key_generate_pair, + ncr_key_generate_pair); case NCRIO_KEY_DEINIT: return ncr_key_deinit(lst, arg); case NCRIO_KEY_EXPORT: @@ -172,8 +174,6 @@ ncr_ioctl(struct ncr_lists *lst, unsigned int cmd, unsigned long arg_) case NCRIO_MASTER_KEY_SET: return ncr_master_key_set(arg); - case NCRIO_KEY_GENERATE_PAIR: - return ncr_key_generate_pair(lst, arg); case NCRIO_KEY_DERIVE: return ncr_key_derive(lst, arg); default: @@ -194,6 +194,7 @@ ncr_compat_ioctl(struct ncr_lists *lst, unsigned int cmd, unsigned long arg_) switch (cmd) { case NCRIO_KEY_INIT: case NCRIO_KEY_GENERATE: + case NCRIO_KEY_GENERATE_PAIR: return ncr_ioctl(lst, cmd, arg_); default: return -EINVAL; diff --git a/ncr.h b/ncr.h index 542c3cc520b..19ba1789055 100644 --- a/ncr.h +++ b/ncr.h @@ -25,12 +25,19 @@ and is treated equivalent to sizeof(struct ncr_*). output_size 0 means no space for output attributes is available, and is not updated. */ +/* FIXME: better names for algorithm parameters? */ enum { NCR_ATTR_UNSPEC, /* 0 is special in lib/nlattr.c. */ /* FIXME: Use NLA_STRING for this, later */ NCR_ATTR_ALGORITHM, /* NLA_U32 - ncr_algorithm_t */ NCR_ATTR_KEY_FLAGS, /* NLA_U32 - NCR_KEY_FLAG_* */ NCR_ATTR_SECRET_KEY_BITS, /* NLA_U32 */ + NCR_ATTR_RSA_MODULUS_BITS, /* NLA_U32 */ + NCR_ATTR_RSA_E, /* NLA_BINARY */ + NCR_ATTR_DSA_P_BITS, /* NLA_U32 */ + NCR_ATTR_DSA_Q_BITS, /* NLA_U32 */ + NCR_ATTR_DH_PRIME, /* NLA_BINARY */ + NCR_ATTR_DH_BASE, /* NLA_BINARY */ /* Add new attributes here */ @@ -107,53 +114,19 @@ typedef __s32 ncr_key_t; */ #define NCR_KEY_FLAG_WRAPPING (1<<4) -struct ncr_key_generate_params_st { - ncr_algorithm_t algorithm; /* just a cipher algorithm when - * generating secret keys - */ - - unsigned int keyflags; - union { - struct { - unsigned int bits; - } secret; - struct { - unsigned int bits; - unsigned long e; /* use zero for default */ - } rsa; - struct { - /* For DSS standard allowed values - * are: p:1024 q: 160 - * p:2048 q: 224 - * p:2048 q: 256 - * p:3072 q: 256 - */ - unsigned int p_bits; - unsigned int q_bits; - } dsa; - struct { - __u8 __user *p; /* prime */ - __kernel_size_t p_size; - __u8 __user *g; /* generator */ - __kernel_size_t g_size; - } dh; - } params; -}; - -/* used in generation - */ -struct ncr_key_generate_st { - ncr_key_t desc; - ncr_key_t desc2; /* public key when called with GENERATE_PAIR */ - struct ncr_key_generate_params_st params; -}; - struct ncr_key_generate { __u32 input_size, output_size; ncr_key_t key; __NL_ATTRIBUTES; }; +struct ncr_key_generate_pair { + __u32 input_size, output_size; + ncr_key_t private_key; + ncr_key_t public_key; + __NL_ATTRIBUTES; +}; + typedef enum { RSA_PKCS1_V1_5, /* both signatures and encryption */ RSA_PKCS1_OAEP, /* for encryption only */ @@ -232,7 +205,7 @@ struct ncr_key_data_st { /* generate a secret key */ #define NCRIO_KEY_GENERATE _IOWR('c', 205, struct ncr_key_generate) /* generate a public key pair */ -#define NCRIO_KEY_GENERATE_PAIR _IOR ('c', 206, struct ncr_key_generate_st) +#define NCRIO_KEY_GENERATE_PAIR _IOWR('c', 206, struct ncr_key_generate_pair) /* derive a new key from an old one */ #define NCRIO_KEY_DERIVE _IOR ('c', 207, struct ncr_key_derivation_params_st) /* return information on a key */ diff --git a/utils.c b/utils.c index 45ca86f64ab..acb72386f1b 100644 --- a/utils.c +++ b/utils.c @@ -32,6 +32,12 @@ static const struct nla_policy ncr_attr_policy[NCR_ATTR_MAX + 1] = { [NCR_ATTR_ALGORITHM] = { NLA_U32, 0 }, [NCR_ATTR_KEY_FLAGS] = { NLA_U32, 0 }, [NCR_ATTR_SECRET_KEY_BITS] = { NLA_U32, 0 }, + [NCR_ATTR_RSA_MODULUS_BITS] = { NLA_U32, 0 }, + [NCR_ATTR_RSA_E] = { NLA_BINARY, 0 }, + [NCR_ATTR_DSA_P_BITS] = { NLA_U32, 0 }, + [NCR_ATTR_DSA_Q_BITS] = { NLA_U32, 0 }, + [NCR_ATTR_DH_PRIME] = { NLA_BINARY, 0 }, + [NCR_ATTR_DH_BASE] = { NLA_BINARY, 0 }, }; void *__ncr_get_input_args(void *fixed, struct nlattr *tb[], size_t fixed_size, -- cgit From d6e4385206d32171d63abe33ee11a349dc9d6e3a Mon Sep 17 00:00:00 2001 From: Miloslav Trmač Date: Wed, 18 Aug 2010 03:28:31 +0200 Subject: Convert *_KEY_DERIVE --- examples/pk.c | 60 ++++++++++++++++++++++++++++++++++++++++++----------------- ncr-int.h | 3 ++- ncr-key.c | 29 +++++++++-------------------- ncr-pk.c | 39 ++++++++++++++++---------------------- ncr-pk.h | 2 +- ncr.c | 4 ++-- ncr.h | 24 +++++++++++------------- utils.c | 2 ++ 8 files changed, 86 insertions(+), 77 deletions(-) diff --git a/examples/pk.c b/examples/pk.c index bb73f289103..84373226004 100644 --- a/examples/pk.c +++ b/examples/pk.c @@ -329,7 +329,15 @@ gnutls_dh_params_t dhp; unsigned char y1[1024], y2[1024]; size_t y1_size, y2_size; struct ncr_key_data_st keydata; -struct ncr_key_derivation_params_st kderive; +struct __attribute__((packed)) { + struct ncr_key_derive f; + struct nlattr algo_head ALIGN_NL; + uint32_t algo ALIGN_NL; + struct nlattr flags_head ALIGN_NL; + uint32_t flags ALIGN_NL; + struct nlattr public_head ALIGN_NL; + unsigned char public[DATA_SIZE] ALIGN_NL; +} kderive; fprintf(stdout, "Tests on DH key exchange:"); fflush(stdout); @@ -478,17 +486,26 @@ struct ncr_key_derivation_params_st kderive; return 1; } - memset(&kderive, 0, sizeof(kderive)); - kderive.derive = NCR_DERIVE_DH; - kderive.newkey = z1; - kderive.keyflags = NCR_KEY_FLAG_EXPORTABLE; - kderive.key = private1; - kderive.params.params.dh.pub = y2; - kderive.params.params.dh.pub_size = y2_size; + memset(&kderive.f, 0, sizeof(kderive.f)); + kderive.f.input_key = private1; + kderive.f.new_key = z1; + kderive.algo_head.nla_len = NLA_HDRLEN + sizeof(kderive.algo); + kderive.algo_head.nla_type = NCR_ATTR_DERIVATION_ALGORITHM; + kderive.algo = NCR_DERIVE_DH; + kderive.flags_head.nla_len = NLA_HDRLEN + sizeof(kderive.flags); + kderive.flags_head.nla_type = NCR_ATTR_KEY_FLAGS; + kderive.flags = NCR_KEY_FLAG_EXPORTABLE; + kderive.public_head.nla_len = NLA_HDRLEN + y2_size; + kderive.public_head.nla_type = NCR_ATTR_DH_PUBLIC; + memcpy(kderive.public, y2, y2_size); + nla = (struct nlattr *)((char *)&kderive.public_head + + NLA_ALIGN(kderive.public_head.nla_len)); + kderive.f.input_size = (char *)nla - (char *)&kderive; + assert(kderive.f.input_size <= sizeof(kderive)); if (ioctl(cfd, NCRIO_KEY_DERIVE, &kderive)) { fprintf(stderr, "Error: %s:%d\n", __func__, __LINE__); - perror("ioctl(NCRIO_KEY_INIT)"); + perror("ioctl(NCRIO_KEY_DERIVE)"); return 1; } @@ -500,17 +517,26 @@ struct ncr_key_derivation_params_st kderive; return 1; } - memset(&kderive, 0, sizeof(kderive)); - kderive.derive = NCR_DERIVE_DH; - kderive.newkey = z2; - kderive.keyflags = NCR_KEY_FLAG_EXPORTABLE; - kderive.key = private2; - kderive.params.params.dh.pub = y1; - kderive.params.params.dh.pub_size = y1_size; + memset(&kderive.f, 0, sizeof(kderive.f)); + kderive.f.input_key = private2; + kderive.f.new_key = z2; + kderive.algo_head.nla_len = NLA_HDRLEN + sizeof(kderive.algo); + kderive.algo_head.nla_type = NCR_ATTR_DERIVATION_ALGORITHM; + kderive.algo = NCR_DERIVE_DH; + kderive.flags_head.nla_len = NLA_HDRLEN + sizeof(kderive.flags); + kderive.flags_head.nla_type = NCR_ATTR_KEY_FLAGS; + kderive.flags = NCR_KEY_FLAG_EXPORTABLE; + kderive.public_head.nla_len = NLA_HDRLEN + y2_size; + kderive.public_head.nla_type = NCR_ATTR_DH_PUBLIC; + memcpy(kderive.public, y1, y1_size); + nla = (struct nlattr *)((char *)&kderive.public_head + + NLA_ALIGN(kderive.public_head.nla_len)); + kderive.f.input_size = (char *)nla - (char *)&kderive; + assert(kderive.f.input_size <= sizeof(kderive)); if (ioctl(cfd, NCRIO_KEY_DERIVE, &kderive)) { fprintf(stderr, "Error: %s:%d\n", __func__, __LINE__); - perror("ioctl(NCRIO_KEY_INIT)"); + perror("ioctl(NCRIO_KEY_DERIVE)"); return 1; } diff --git a/ncr-int.h b/ncr-int.h index 172c51ce600..0ae042b148c 100644 --- a/ncr-int.h +++ b/ncr-int.h @@ -111,7 +111,8 @@ long ncr_compat_ioctl(struct ncr_lists *lst, unsigned int cmd, unsigned long arg); /* key derivation */ -int ncr_key_derive(struct ncr_lists *lst, void __user* arg); +int ncr_key_derive(struct ncr_lists *lst, const struct ncr_key_derive *data, + struct nlattr *tb[]); void ncr_key_clear(struct key_item_st* item); void ncr_key_assign_flags(struct key_item_st* item, unsigned int flags); diff --git a/ncr-key.c b/ncr-key.c index 90ba45ea020..15e90fee10c 100644 --- a/ncr-key.c +++ b/ncr-key.c @@ -701,22 +701,15 @@ fail: return ret; } -/* "exports" a key to a data item. If the key is not exportable - * to userspace then the data item will also not be. - */ -int ncr_key_derive(struct ncr_lists *lst, void __user* arg) +int ncr_key_derive(struct ncr_lists *lst, const struct ncr_key_derive *data, + struct nlattr *tb[]) { -struct ncr_key_derivation_params_st data; +const struct nlattr *nla; int ret; struct key_item_st* key = NULL; struct key_item_st* newkey = NULL; - if (unlikely(copy_from_user(&data, arg, sizeof(data)))) { - err(); - return -EFAULT; - } - - ret = ncr_key_item_get_read( &key, lst, data.key); + ret = ncr_key_item_get_read(&key, lst, data->input_key); if (ret < 0) { err(); return ret; @@ -730,7 +723,7 @@ struct key_item_st* newkey = NULL; goto fail; } - ret = ncr_key_item_get_write( &newkey, lst, data.newkey); + ret = ncr_key_item_get_write(&newkey, lst, data->new_key); if (ret < 0) { err(); goto fail; @@ -738,12 +731,14 @@ struct key_item_st* newkey = NULL; ncr_key_clear(newkey); - ncr_key_assign_flags(newkey, data.keyflags); + nla = tb[NCR_ATTR_KEY_FLAGS]; + if (nla != NULL) + ncr_key_assign_flags(newkey, nla_get_u32(nla)); switch (key->type) { case NCR_KEY_TYPE_PUBLIC: case NCR_KEY_TYPE_PRIVATE: - ret = ncr_pk_derive(newkey, key, &data); + ret = ncr_pk_derive(newkey, key, tb); if (ret < 0) { err(); goto fail; @@ -755,12 +750,6 @@ struct key_item_st* newkey = NULL; goto fail; } - if (unlikely(copy_to_user(arg, &data, sizeof(data)))) { - err(); - ret = -EFAULT; - } else - ret = 0; - fail: if (key) _ncr_key_item_put(key); diff --git a/ncr-pk.c b/ncr-pk.c index f8989184bd6..921b19304a5 100644 --- a/ncr-pk.c +++ b/ncr-pk.c @@ -681,38 +681,34 @@ fail: } int ncr_pk_derive(struct key_item_st* newkey, struct key_item_st* oldkey, - struct ncr_key_derivation_params_st * params) + struct nlattr *tb[]) { +const struct nlattr *nla; int ret; -void* tmp = NULL; -size_t size; - switch(params->derive) { + nla = tb[NCR_ATTR_DERIVATION_ALGORITHM]; + if (nla == NULL) { + err(); + return -EINVAL; + } + switch(nla_get_u32(nla)) { case NCR_DERIVE_DH: if (oldkey->type != NCR_KEY_TYPE_PRIVATE && oldkey->algorithm->algo != NCR_ALG_DH) { err(); return -EINVAL; } - - size = params->params.params.dh.pub_size; - tmp = kmalloc(size, GFP_KERNEL); - if (tmp == NULL) { + + nla = tb[NCR_ATTR_DH_PUBLIC]; + if (nla == NULL) { err(); - return -ENOMEM; - } - - if (unlikely(copy_from_user(tmp, params->params.params.dh.pub, - size))) { - err(); - ret = -EFAULT; - goto fail; + return -EINVAL; } - - ret = dh_derive_gxy(newkey, &oldkey->key.pk.dh, tmp, size); + ret = dh_derive_gxy(newkey, &oldkey->key.pk.dh, + nla_data(nla), nla_len(nla)); if (ret < 0) { err(); - goto fail; + return ret; } break; @@ -721,10 +717,7 @@ size_t size; return -EINVAL; } - ret = 0; -fail: - kfree(tmp); - return ret; + return 0; } int ncr_pk_get_rsa_size( rsa_key* key) diff --git a/ncr-pk.h b/ncr-pk.h index 722d1eae12b..ba35e45634d 100644 --- a/ncr-pk.h +++ b/ncr-pk.h @@ -51,7 +51,7 @@ int ncr_pk_cipher_verify(const struct ncr_pk_ctx* ctx, int _ncr_tomerr(int err); int ncr_pk_derive(struct key_item_st* newkey, struct key_item_st* oldkey, - struct ncr_key_derivation_params_st * params); + struct nlattr *tb[]); int ncr_pk_get_rsa_size( rsa_key* key); int ncr_pk_get_dsa_size( dsa_key* key); diff --git a/ncr.c b/ncr.c index 4cff5090146..7f905f20063 100644 --- a/ncr.c +++ b/ncr.c @@ -147,6 +147,7 @@ ncr_ioctl(struct ncr_lists *lst, unsigned int cmd, unsigned long arg_) CASE_NO_OUTPUT(NCRIO_KEY_GENERATE, ncr_key_generate, ncr_key_generate); CASE_NO_OUTPUT(NCRIO_KEY_GENERATE_PAIR, ncr_key_generate_pair, ncr_key_generate_pair); + CASE_NO_OUTPUT(NCRIO_KEY_DERIVE, ncr_key_derive, ncr_key_derive); case NCRIO_KEY_DEINIT: return ncr_key_deinit(lst, arg); case NCRIO_KEY_EXPORT: @@ -174,8 +175,6 @@ ncr_ioctl(struct ncr_lists *lst, unsigned int cmd, unsigned long arg_) case NCRIO_MASTER_KEY_SET: return ncr_master_key_set(arg); - case NCRIO_KEY_DERIVE: - return ncr_key_derive(lst, arg); default: return -EINVAL; #undef CASE_NO_OUTPUT @@ -195,6 +194,7 @@ ncr_compat_ioctl(struct ncr_lists *lst, unsigned int cmd, unsigned long arg_) case NCRIO_KEY_INIT: case NCRIO_KEY_GENERATE: case NCRIO_KEY_GENERATE_PAIR: + case NCRIO_KEY_DERIVE: return ncr_ioctl(lst, cmd, arg_); default: return -EINVAL; diff --git a/ncr.h b/ncr.h index 19ba1789055..34caa61245b 100644 --- a/ncr.h +++ b/ncr.h @@ -26,10 +26,13 @@ space for output attributes is available, and is not updated. */ /* FIXME: better names for algorithm parameters? */ +/* FIXME: Split key generation/derivation attributes to decrease the number + of attributes used for the frequent operations? */ enum { NCR_ATTR_UNSPEC, /* 0 is special in lib/nlattr.c. */ /* FIXME: Use NLA_STRING for this, later */ NCR_ATTR_ALGORITHM, /* NLA_U32 - ncr_algorithm_t */ + NCR_ATTR_DERIVATION_ALGORITHM, /* NLA_U32 - ncr_algorithm_t */ NCR_ATTR_KEY_FLAGS, /* NLA_U32 - NCR_KEY_FLAG_* */ NCR_ATTR_SECRET_KEY_BITS, /* NLA_U32 */ NCR_ATTR_RSA_MODULUS_BITS, /* NLA_U32 */ @@ -38,6 +41,7 @@ enum { NCR_ATTR_DSA_Q_BITS, /* NLA_U32 */ NCR_ATTR_DH_PRIME, /* NLA_BINARY */ NCR_ATTR_DH_BASE, /* NLA_BINARY */ + NCR_ATTR_DH_PUBLIC, /* NLA_BINARY */ /* Add new attributes here */ @@ -133,7 +137,7 @@ typedef enum { RSA_PKCS1_PSS, /* for signatures only */ } ncr_rsa_type_t; -/* used in derivation/encryption +/* used in encryption */ struct ncr_key_params_st { /* this structure always corresponds to a key. Hence the @@ -144,10 +148,6 @@ struct ncr_key_params_st { __u8 iv[NCR_CIPHER_MAX_BLOCK_LEN]; __kernel_size_t iv_size; } cipher; - struct { - __u8 __user *pub; - __kernel_size_t pub_size; - } dh; struct { ncr_rsa_type_t type; ncr_algorithm_t oaep_hash; /* for OAEP */ @@ -164,14 +164,12 @@ typedef enum { NCR_DERIVE_DH=1, } ncr_derive_t; -struct ncr_key_derivation_params_st { - ncr_derive_t derive; /* the derivation algorithm */ - ncr_key_t newkey; - unsigned int keyflags; /* for new key */ - - ncr_key_t key; - struct ncr_key_params_st params; +struct ncr_key_derive { + __u32 input_size, output_size; + ncr_key_t input_key; + ncr_key_t new_key; + __NL_ATTRIBUTES; }; #define MAX_KEY_ID_SIZE 20 @@ -207,7 +205,7 @@ struct ncr_key_data_st { /* generate a public key pair */ #define NCRIO_KEY_GENERATE_PAIR _IOWR('c', 206, struct ncr_key_generate_pair) /* derive a new key from an old one */ -#define NCRIO_KEY_DERIVE _IOR ('c', 207, struct ncr_key_derivation_params_st) +#define NCRIO_KEY_DERIVE _IOWR('c', 207, struct ncr_key_derive) /* return information on a key */ #define NCRIO_KEY_GET_INFO _IOWR('c', 208, struct ncr_key_info_st) diff --git a/utils.c b/utils.c index acb72386f1b..e96c72ca91d 100644 --- a/utils.c +++ b/utils.c @@ -30,6 +30,7 @@ static const struct nla_policy ncr_attr_policy[NCR_ATTR_MAX + 1] = { [NCR_ATTR_ALGORITHM] = { NLA_U32, 0 }, + [NCR_ATTR_DERIVATION_ALGORITHM] = { NLA_U32, 0 }, [NCR_ATTR_KEY_FLAGS] = { NLA_U32, 0 }, [NCR_ATTR_SECRET_KEY_BITS] = { NLA_U32, 0 }, [NCR_ATTR_RSA_MODULUS_BITS] = { NLA_U32, 0 }, @@ -38,6 +39,7 @@ static const struct nla_policy ncr_attr_policy[NCR_ATTR_MAX + 1] = { [NCR_ATTR_DSA_Q_BITS] = { NLA_U32, 0 }, [NCR_ATTR_DH_PRIME] = { NLA_BINARY, 0 }, [NCR_ATTR_DH_BASE] = { NLA_BINARY, 0 }, + [NCR_ATTR_DH_PUBLIC] = { NLA_BINARY, 0 }, }; void *__ncr_get_input_args(void *fixed, struct nlattr *tb[], size_t fixed_size, -- cgit From 7c70b1f992d02daa3c5d435355ac7875a6b1b95b Mon Sep 17 00:00:00 2001 From: Miloslav Trmač Date: Thu, 12 Aug 2010 21:51:20 +0200 Subject: Convert *_KEY_GET_INFO --- examples/ncr.c | 85 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ncr-int.h | 4 ++- ncr-key.c | 54 ++++++++++++++++++++++++++++--------- ncr.c | 21 +++++++++++++-- ncr.h | 17 +++++------- utils.c | 2 ++ 6 files changed, 157 insertions(+), 26 deletions(-) diff --git a/examples/ncr.c b/examples/ncr.c index 568b63cb068..b999003cc97 100644 --- a/examples/ncr.c +++ b/examples/ncr.c @@ -46,10 +46,22 @@ test_ncr_key(int cfd) struct nlattr bits_head ALIGN_NL; uint32_t bits ALIGN_NL; } kgen; + struct __attribute__((packed)) { + struct ncr_key_get_info f; + /* This union is only here to stop gcc from complaining about + aliasing. */ + union { + unsigned char __reserve[DATA_SIZE]; + struct nlattr first_header; + } u ALIGN_NL; + } kinfo; + struct nlattr *nla; ncr_key_t key; struct ncr_key_data_st keydata; uint8_t data[KEY_DATA_SIZE]; uint8_t data_bak[KEY_DATA_SIZE]; + uint16_t *attr_p; + int got_algo, got_flags, got_type; fprintf(stdout, "Tests on Keys:\n"); @@ -174,6 +186,79 @@ test_ncr_key(int cfd) return 1; } + memset(&kinfo.f, 0, sizeof(kinfo.f)); + kinfo.f.output_size = sizeof(kinfo); + kinfo.f.key = key; + nla = &kinfo.u.first_header; + nla->nla_type = NCR_ATTR_WANTED_ATTRS; + attr_p = (uint16_t *)((char *)nla + NLA_HDRLEN); + *attr_p++ = NCR_ATTR_ALGORITHM; + *attr_p++ = NCR_ATTR_KEY_FLAGS; + *attr_p++ = NCR_ATTR_KEY_TYPE; + nla->nla_len = (char *)attr_p - (char *)nla; + kinfo.f.input_size = (char *)attr_p - (char *)&kinfo; + + if (ioctl(cfd, NCRIO_KEY_GET_INFO, &kinfo)) { + fprintf(stderr, "Error: %s:%d\n", __func__, __LINE__); + perror("ioctl(NCRIO_KEY_GET_INFO)"); + return 1; + } + + got_algo = got_flags = got_type = 0; + if (kinfo.f.output_size < + (char *)&kinfo.u.first_header - (char *)&kinfo) { + fprintf(stderr, "No nlattr returned\n"); + return 1; + } + nla = &kinfo.u.first_header; + for (;;) { + void *data; + + if (nla->nla_len < NLA_HDRLEN + sizeof(uint32_t)) { + fprintf(stderr, "Attribute too small\n"); + return 1; + } + if (nla->nla_len > + kinfo.f.output_size - ((char *)nla - (char *)&kinfo)) { + fprintf(stderr, "Attributes overflow\n"); + return 1; + } + data = (char *)nla + NLA_HDRLEN; + switch (nla->nla_type) { + case NCR_ATTR_ALGORITHM: + if (*(uint32_t *)data != NCR_ALG_AES_CBC) { + fprintf(stderr, "Unexpected algorithm\n"); + return 1; + } + got_algo++; + break; + case NCR_ATTR_KEY_FLAGS: + if (*(uint32_t *)data != NCR_KEY_FLAG_EXPORTABLE) { + fprintf(stderr, "Unexpected key flags\n"); + return 1; + } + got_flags++; + break; + case NCR_ATTR_KEY_TYPE: + if (*(uint32_t *)data != NCR_KEY_TYPE_SECRET) { + fprintf(stderr, "Unexpected key type\n"); + return 1; + } + got_type++; + break; + } + + if (NLA_ALIGN(nla->nla_len) + NLA_HDRLEN > + kinfo.f.output_size - ((char *)nla - (char *)&kinfo)) + break; + nla = (struct nlattr *)((char *)nla + NLA_ALIGN(nla->nla_len)); + } + if (got_algo != 1 || got_flags != 1 || got_type != 1) { + fprintf(stderr, "Unexpected attrs - %d, %d, %d\n", got_algo, + got_flags, got_type); + return 1; + } + if (ioctl(cfd, NCRIO_KEY_DEINIT, &key)) { fprintf(stderr, "Error: %s:%d\n", __func__, __LINE__); perror("ioctl(NCRIO_KEY_DEINIT)"); diff --git a/ncr-int.h b/ncr-int.h index 0ae042b148c..9330abf3759 100644 --- a/ncr-int.h +++ b/ncr-int.h @@ -15,6 +15,7 @@ #define err() printk(KERN_DEBUG"ncr: %s: %s: %d\n", __FILE__, __func__, __LINE__) struct nlattr; +struct ncr_out; struct algo_properties_st { ncr_algorithm_t algo; @@ -125,7 +126,8 @@ int ncr_key_import(struct ncr_lists *lst, void __user* arg); void ncr_key_list_deinit(struct ncr_lists *lst); int ncr_key_generate(struct ncr_lists *lst, const struct ncr_key_generate *gen, struct nlattr *tb[]); -int ncr_key_info(struct ncr_lists *lst, void __user* arg); +int ncr_key_get_info(struct ncr_lists *lst, struct ncr_out *out, + const struct ncr_key_get_info *info, struct nlattr *tb[]); int ncr_key_generate_pair(struct ncr_lists *lst, const struct ncr_key_generate_pair *gen, diff --git a/ncr-key.c b/ncr-key.c index 15e90fee10c..b0e8a97cc4f 100644 --- a/ncr-key.c +++ b/ncr-key.c @@ -31,6 +31,7 @@ #include #include "ncr.h" #include "ncr-int.h" +#include "utils.h" static int key_list_deinit_fn(int id, void *item, void *unused) { @@ -599,18 +600,15 @@ int bits; } } -int ncr_key_info(struct ncr_lists *lst, void __user* arg) +int ncr_key_get_info(struct ncr_lists *lst, struct ncr_out *out, + const struct ncr_key_get_info *info, struct nlattr *tb[]) { -struct ncr_key_info_st info; +const struct nlattr *nla; +const u16 *attr, *attr_end; struct key_item_st* item = NULL; int ret; - if (unlikely(copy_from_user(&info, arg, sizeof(info)))) { - err(); - return -EFAULT; - } - - ret = ncr_key_item_get_read(&item, lst, info.key); + ret = ncr_key_item_get_read(&item, lst, info->key); if (ret < 0) { err(); return ret; @@ -622,11 +620,41 @@ int ret; goto fail; } - info.flags = item->flags; - info.type = item->type; - info.algorithm = item->algorithm->algo; - - ret = 0; + nla = tb[NCR_ATTR_WANTED_ATTRS]; + if (nla == NULL || nla_len(nla) % sizeof(u16) != 0) { + err(); + ret = -EINVAL; + goto fail; + } + attr = nla_data(nla); + attr_end = attr + nla_len(nla) / sizeof(u16); + while (attr < attr_end) { + switch (*attr) { + case NCR_ATTR_KEY_FLAGS: + ret = ncr_out_put_u32(out, *attr, item->flags); + break; + case NCR_ATTR_KEY_TYPE: + ret = ncr_out_put_u32(out, *attr, item->type); + break; + case NCR_ATTR_ALGORITHM: + ret = ncr_out_put_u32(out, *attr, + item->algorithm->algo); + break; + default: + break; /* Silently ignore */ + } + if (ret != 0) { + err(); + goto fail; + } + attr++; + } + + ret = ncr_out_finish(out); + if (ret != 0) { + err(); + goto fail; + } fail: _ncr_key_item_put( item); diff --git a/ncr.c b/ncr.c index 7f905f20063..796ca327003 100644 --- a/ncr.c +++ b/ncr.c @@ -148,14 +148,30 @@ ncr_ioctl(struct ncr_lists *lst, unsigned int cmd, unsigned long arg_) CASE_NO_OUTPUT(NCRIO_KEY_GENERATE_PAIR, ncr_key_generate_pair, ncr_key_generate_pair); CASE_NO_OUTPUT(NCRIO_KEY_DERIVE, ncr_key_derive, ncr_key_derive); + case NCRIO_KEY_GET_INFO: { + struct ncr_key_get_info data; + struct ncr_out out; + + attr_buf = NCR_GET_INPUT_ARGS(&data, tb, arg); + if (IS_ERR(attr_buf)) { + err(); + return PTR_ERR(attr_buf); + } + ret = NCR_OUT_INIT(&out, &data, arg); + if (ret != 0) { + err(); + break; + } + ret = ncr_key_get_info(lst, &out, &data, tb); + ncr_out_free(&out); + break; + } case NCRIO_KEY_DEINIT: return ncr_key_deinit(lst, arg); case NCRIO_KEY_EXPORT: return ncr_key_export(lst, arg); case NCRIO_KEY_IMPORT: return ncr_key_import(lst, arg); - case NCRIO_KEY_GET_INFO: - return ncr_key_info(lst, arg); case NCRIO_KEY_WRAP: return ncr_key_wrap(lst, arg); case NCRIO_KEY_UNWRAP: @@ -195,6 +211,7 @@ ncr_compat_ioctl(struct ncr_lists *lst, unsigned int cmd, unsigned long arg_) case NCRIO_KEY_GENERATE: case NCRIO_KEY_GENERATE_PAIR: case NCRIO_KEY_DERIVE: + case NCRIO_KEY_GET_INFO: return ncr_ioctl(lst, cmd, arg_); default: return -EINVAL; diff --git a/ncr.h b/ncr.h index 34caa61245b..d4d1d6a11bd 100644 --- a/ncr.h +++ b/ncr.h @@ -34,6 +34,7 @@ enum { NCR_ATTR_ALGORITHM, /* NLA_U32 - ncr_algorithm_t */ NCR_ATTR_DERIVATION_ALGORITHM, /* NLA_U32 - ncr_algorithm_t */ NCR_ATTR_KEY_FLAGS, /* NLA_U32 - NCR_KEY_FLAG_* */ + NCR_ATTR_KEY_TYPE, /* NLA_U32 - ncr_key_type_t */ NCR_ATTR_SECRET_KEY_BITS, /* NLA_U32 */ NCR_ATTR_RSA_MODULUS_BITS, /* NLA_U32 */ NCR_ATTR_RSA_E, /* NLA_BINARY */ @@ -42,6 +43,7 @@ enum { NCR_ATTR_DH_PRIME, /* NLA_BINARY */ NCR_ATTR_DH_BASE, /* NLA_BINARY */ NCR_ATTR_DH_PUBLIC, /* NLA_BINARY */ + NCR_ATTR_WANTED_ATTRS, /* NLA_BINARY - array of u16 IDs */ /* Add new attributes here */ @@ -174,15 +176,10 @@ struct ncr_key_derive { #define MAX_KEY_ID_SIZE 20 -struct ncr_key_info_st { - ncr_key_t key; /* input */ - - unsigned int flags; - ncr_key_type_t type; - ncr_algorithm_t algorithm; /* valid for public/private keys */ - - __u8 key_id[MAX_KEY_ID_SIZE]; - __kernel_size_t key_id_size; +struct ncr_key_get_info { + __u32 input_size, output_size; + ncr_key_t key; + __NL_ATTRIBUTES; }; struct ncr_key_data_st { @@ -207,7 +204,7 @@ struct ncr_key_data_st { /* derive a new key from an old one */ #define NCRIO_KEY_DERIVE _IOWR('c', 207, struct ncr_key_derive) /* return information on a key */ -#define NCRIO_KEY_GET_INFO _IOWR('c', 208, struct ncr_key_info_st) +#define NCRIO_KEY_GET_INFO _IOWR('c', 208, struct ncr_key_get_info) /* export a secret key */ #define NCRIO_KEY_EXPORT _IOWR('c', 209, struct ncr_key_data_st) diff --git a/utils.c b/utils.c index e96c72ca91d..655dc825b27 100644 --- a/utils.c +++ b/utils.c @@ -32,6 +32,7 @@ static const struct nla_policy ncr_attr_policy[NCR_ATTR_MAX + 1] = { [NCR_ATTR_ALGORITHM] = { NLA_U32, 0 }, [NCR_ATTR_DERIVATION_ALGORITHM] = { NLA_U32, 0 }, [NCR_ATTR_KEY_FLAGS] = { NLA_U32, 0 }, + [NCR_ATTR_KEY_TYPE] = { NLA_U32, 0 }, [NCR_ATTR_SECRET_KEY_BITS] = { NLA_U32, 0 }, [NCR_ATTR_RSA_MODULUS_BITS] = { NLA_U32, 0 }, [NCR_ATTR_RSA_E] = { NLA_BINARY, 0 }, @@ -40,6 +41,7 @@ static const struct nla_policy ncr_attr_policy[NCR_ATTR_MAX + 1] = { [NCR_ATTR_DH_PRIME] = { NLA_BINARY, 0 }, [NCR_ATTR_DH_BASE] = { NLA_BINARY, 0 }, [NCR_ATTR_DH_PUBLIC] = { NLA_BINARY, 0 }, + [NCR_ATTR_WANTED_ATTRS] = { NLA_BINARY, 0 }, }; void *__ncr_get_input_args(void *fixed, struct nlattr *tb[], size_t fixed_size, -- cgit From 827e65e77c32da30ce675e8e7c05de73d9aeab5a Mon Sep 17 00:00:00 2001 From: Miloslav Trmač Date: Fri, 13 Aug 2010 19:17:16 +0200 Subject: Convert *_KEY_EXPORT --- examples/ncr.c | 61 ++++++++++++++----------------- examples/pk.c | 113 +++++++++++++++++++++++++++------------------------------ ncr-int.h | 3 +- ncr-key.c | 34 ++++++----------- ncr-pk.c | 2 +- ncr.c | 45 ++++++++++++++++++++++- ncr.h | 10 ++++- 7 files changed, 149 insertions(+), 119 deletions(-) diff --git a/examples/ncr.c b/examples/ncr.c index b999003cc97..2c2ca7c023c 100644 --- a/examples/ncr.c +++ b/examples/ncr.c @@ -58,6 +58,7 @@ test_ncr_key(int cfd) struct nlattr *nla; ncr_key_t key; struct ncr_key_data_st keydata; + struct ncr_key_export kexport; uint8_t data[KEY_DATA_SIZE]; uint8_t data_bak[KEY_DATA_SIZE]; uint16_t *attr_p; @@ -101,20 +102,14 @@ test_ncr_key(int cfd) /* now try to read it */ fprintf(stdout, "\tKey export...\n"); - memset(&keydata, 0, sizeof(keydata)); - keydata.key = key; - keydata.idata = data; - keydata.idata_size = sizeof(data); + memset(&kexport, 0, sizeof(kexport)); + kexport.key = key; + kexport.buffer = data; + kexport.buffer_size = sizeof(data); - if (ioctl(cfd, NCRIO_KEY_EXPORT, &keydata)) { - fprintf(stderr, "Error: %s:%d\n", __func__, __LINE__); - perror("ioctl(NCRIO_KEY_IMPORT)"); - return 1; - } - - if (keydata.idata_size != sizeof(data)) { + if (ioctl(cfd, NCRIO_KEY_EXPORT, &kexport) != sizeof(data)) { fprintf(stderr, "Error: %s:%d\n", __func__, __LINE__); - fprintf(stderr, "data returned but differ!\n"); + perror("ioctl(NCRIO_KEY_EXPORT)"); return 1; } @@ -165,18 +160,18 @@ test_ncr_key(int cfd) memset(data, 0, sizeof(data)); - memset(&keydata, 0, sizeof(keydata)); - keydata.key = key; - keydata.idata = data; - keydata.idata_size = sizeof(data); + memset(&kexport, 0, sizeof(kexport)); + kexport.key = key; + kexport.buffer = data; + kexport.buffer_size = sizeof(data); - if (ioctl(cfd, NCRIO_KEY_EXPORT, &keydata)) { + if (ioctl(cfd, NCRIO_KEY_EXPORT, &kexport) != sizeof(data)) { fprintf(stderr, "Error: %s:%d\n", __func__, __LINE__); - perror("ioctl(NCRIO_KEY_IMPORT)"); + perror("ioctl(NCRIO_KEY_EXPORT)"); return 1; } - if (keydata.idata_size == 0 || (data[0] == 0 && data[1] == 0 && data[2] == 0 && data[4] == 0)) { + if (data[0] == 0 && data[1] == 0 && data[2] == 0 && data[4] == 0) { fprintf(stderr, "Error: %s:%d\n", __func__, __LINE__); fprintf(stderr, "Generated key: %.2x.%.2x.%.2x.%.2x.%.2x.%.2x.%.2x.%.2x." "%.2x.%.2x.%.2x.%.2x.%.2x.%.2x.%.2x.%.2x\n", data[0], data[1], @@ -296,14 +291,14 @@ test_ncr_key(int cfd) memset(data, 0, sizeof(data)); - memset(&keydata, 0, sizeof(keydata)); - keydata.key = key; - keydata.idata = data; - keydata.idata_size = sizeof(data); + memset(&kexport, 0, sizeof(kexport)); + kexport.key = key; + kexport.buffer = data; + kexport.buffer_size = sizeof(data); /* try to get the output data - should fail */ - if (ioctl(cfd, NCRIO_KEY_EXPORT, &keydata)==0) { + if (ioctl(cfd, NCRIO_KEY_EXPORT, &kexport) >= 0) { fprintf(stderr, "Error: %s:%d\n", __func__, __LINE__); fprintf(stderr, "Data were exported, but shouldn't be!\n"); return 1; @@ -580,6 +575,7 @@ test_ncr_store_wrap_key(int cfd) int i; ncr_key_t key2; struct ncr_key_data_st keydata; + struct ncr_key_export kexport; struct ncr_key_storage_wrap_st kwrap; uint8_t data[DATA_SIZE]; int data_size; @@ -659,20 +655,19 @@ test_ncr_store_wrap_key(int cfd) } /* now export the unwrapped */ - memset(&keydata, 0, sizeof(keydata)); - keydata.key = key2; - keydata.idata = data; - keydata.idata_size = sizeof(data); + memset(&kexport, 0, sizeof(kexport)); + kexport.key = key2; + kexport.buffer = data; + kexport.buffer_size = sizeof(data); - if (ioctl(cfd, NCRIO_KEY_EXPORT, &keydata)) { + data_size = ioctl(cfd, NCRIO_KEY_EXPORT, &kexport); + if (data_size != 16) { fprintf(stderr, "Error: %s:%d\n", __func__, __LINE__); - perror("ioctl(NCRIO_KEY_IMPORT)"); + perror("ioctl(NCRIO_KEY_EXPORT)"); return 1; } - - data_size = keydata.idata_size; - if (data_size != 16 || memcmp(data, DKEY, 16) != 0) { + if (memcmp(data, DKEY, 16) != 0) { fprintf(stderr, "Unwrapped data do not match.\n"); fprintf(stderr, "Data[%d]: ", (int) data_size); for(i=0;ibuffer_size < 0) { err(); - return -EFAULT; + return -EINVAL; } - ret = ncr_key_item_get_read( &item, lst, data.key); + ret = ncr_key_item_get_read(&item, lst, data->key); if (ret < 0) { err(); return ret; @@ -240,15 +237,15 @@ int ret; switch (item->type) { case NCR_KEY_TYPE_SECRET: - if (item->key.secret.size > data.idata_size) { + if (item->key.secret.size > data->buffer_size) { err(); - ret = -EINVAL; + ret = -ERANGE; goto fail; } /* found */ if (item->key.secret.size > 0) { - ret = copy_to_user(data.idata, item->key.secret.data, item->key.secret.size); + ret = copy_to_user(data->buffer, item->key.secret.data, item->key.secret.size); if (unlikely(ret)) { err(); ret = -EFAULT; @@ -256,11 +253,11 @@ int ret; } } - data.idata_size = item->key.secret.size; + ret = item->key.secret.size; break; case NCR_KEY_TYPE_PUBLIC: case NCR_KEY_TYPE_PRIVATE: - tmp_size = data.idata_size; + tmp_size = data->buffer_size; tmp = kmalloc(tmp_size, GFP_KERNEL); if (tmp == NULL) { @@ -270,20 +267,19 @@ int ret; } ret = ncr_pk_pack(item, tmp, &tmp_size); - data.idata_size = tmp_size; - if (ret < 0) { err(); goto fail; } - ret = copy_to_user(data.idata, tmp, tmp_size); + ret = copy_to_user(data->buffer, tmp, tmp_size); if (unlikely(ret)) { err(); ret = -EFAULT; goto fail; } + ret = tmp_size; break; default: err(); @@ -291,12 +287,6 @@ int ret; goto fail; } - if (unlikely(copy_to_user(arg, &data, sizeof(data)))) { - err(); - ret = -EFAULT; - } else - ret = 0; - fail: kfree(tmp); if (item) diff --git a/ncr-pk.c b/ncr-pk.c index 921b19304a5..c96f494ed90 100644 --- a/ncr-pk.c +++ b/ncr-pk.c @@ -37,7 +37,7 @@ int _ncr_tomerr(int err) { switch (err) { case CRYPT_BUFFER_OVERFLOW: - return -EOVERFLOW; + return -ERANGE; case CRYPT_MEM: return -ENOMEM; default: diff --git a/ncr.c b/ncr.c index 796ca327003..bc19e248bf8 100644 --- a/ncr.c +++ b/ncr.c @@ -166,10 +166,9 @@ ncr_ioctl(struct ncr_lists *lst, unsigned int cmd, unsigned long arg_) ncr_out_free(&out); break; } + CASE_NO_OUTPUT(NCRIO_KEY_EXPORT, ncr_key_export, ncr_key_export); case NCRIO_KEY_DEINIT: return ncr_key_deinit(lst, arg); - case NCRIO_KEY_EXPORT: - return ncr_key_export(lst, arg); case NCRIO_KEY_IMPORT: return ncr_key_import(lst, arg); case NCRIO_KEY_WRAP: @@ -200,9 +199,31 @@ ncr_ioctl(struct ncr_lists *lst, unsigned int cmd, unsigned long arg_) } #ifdef CONFIG_COMPAT +struct compat_ncr_key_export { + __u32 input_size, output_size; + ncr_key_t key; + compat_uptr_t buffer; + compat_int_t buffer_size; + __NL_ATTRIBUTES; +}; +#define COMPAT_NCRIO_KEY_EXPORT _IOWR('c', 209, struct compat_ncr_key_export) + +static void convert_ncr_key_export(struct ncr_key_export *new, + const struct compat_ncr_key_export *old) +{ + new->key = old->key; + new->buffer = compat_ptr(old->buffer); + new->buffer_size = old->buffer_size; +} + long ncr_compat_ioctl(struct ncr_lists *lst, unsigned int cmd, unsigned long arg_) { + void __user *arg = (void __user *)arg_; + struct nlattr *tb[NCR_ATTR_MAX + 1]; + void *attr_buf; + int ret; + if (unlikely(!lst)) BUG(); @@ -213,8 +234,28 @@ ncr_compat_ioctl(struct ncr_lists *lst, unsigned int cmd, unsigned long arg_) case NCRIO_KEY_DERIVE: case NCRIO_KEY_GET_INFO: return ncr_ioctl(lst, cmd, arg_); + +#define CASE_NO_OUTPUT(LABEL, STRUCT, FUNCTION) \ + case (LABEL): { \ + struct compat_##STRUCT old; \ + struct STRUCT new; \ + \ + attr_buf = NCR_GET_INPUT_ARGS_NO_OUTPUT(&old, tb, arg); \ + if (IS_ERR(attr_buf)) { \ + err(); \ + return PTR_ERR(attr_buf); \ + } \ + convert_##STRUCT(&new, &old); \ + ret = (FUNCTION)(lst, &new, tb); \ + break; \ + } + + CASE_NO_OUTPUT(COMPAT_NCRIO_KEY_EXPORT, ncr_key_export, ncr_key_export); default: return -EINVAL; +#undef CASE_NO_OUTPUT } + kfree(attr_buf); + return ret; } #endif diff --git a/ncr.h b/ncr.h index d4d1d6a11bd..f6982de176e 100644 --- a/ncr.h +++ b/ncr.h @@ -196,6 +196,14 @@ struct ncr_key_data_st { ncr_algorithm_t algorithm; /* valid for public/private keys */ }; +struct ncr_key_export { + __u32 input_size, output_size; + ncr_key_t key; + void __user *buffer; + int buffer_size; + __NL_ATTRIBUTES; +}; + #define NCRIO_KEY_INIT _IO('c', 204) /* generate a secret key */ #define NCRIO_KEY_GENERATE _IOWR('c', 205, struct ncr_key_generate) @@ -207,7 +215,7 @@ struct ncr_key_data_st { #define NCRIO_KEY_GET_INFO _IOWR('c', 208, struct ncr_key_get_info) /* export a secret key */ -#define NCRIO_KEY_EXPORT _IOWR('c', 209, struct ncr_key_data_st) +#define NCRIO_KEY_EXPORT _IOWR('c', 209, struct ncr_key_export) /* import a secret key */ #define NCRIO_KEY_IMPORT _IOWR('c', 210, struct ncr_key_data_st) -- cgit From af980a4453d1d36486c5d75c49d389b0cc7e2c79 Mon Sep 17 00:00:00 2001 From: Miloslav Trmač Date: Mon, 16 Aug 2010 14:30:45 +0200 Subject: Convert *_KEY_IMPORT --- examples/ncr.c | 395 ++++++++++++++++++++++++++++++++++++++++----------------- examples/pk.c | 44 +++++-- ncr-int.h | 3 +- ncr-key.c | 51 ++++---- ncr.c | 21 ++- ncr.h | 19 +-- utils.c | 1 + 7 files changed, 365 insertions(+), 169 deletions(-) diff --git a/examples/ncr.c b/examples/ncr.c index 2c2ca7c023c..56a59ceafe6 100644 --- a/examples/ncr.c +++ b/examples/ncr.c @@ -57,7 +57,17 @@ test_ncr_key(int cfd) } kinfo; struct nlattr *nla; ncr_key_t key; - struct ncr_key_data_st keydata; + struct __attribute__((packed)) { + struct ncr_key_import f; + struct nlattr id_head ALIGN_NL; + uint8_t id[2] ALIGN_NL; + struct nlattr type_head ALIGN_NL; + uint32_t type ALIGN_NL; + struct nlattr algo_head ALIGN_NL; + uint32_t algo ALIGN_NL; + struct nlattr flags_head ALIGN_NL; + uint32_t flags ALIGN_NL; + } kimport; struct ncr_key_export kexport; uint8_t data[KEY_DATA_SIZE]; uint8_t data_bak[KEY_DATA_SIZE]; @@ -82,18 +92,26 @@ test_ncr_key(int cfd) return 1; } - keydata.key_id[0] = 'a'; - keydata.key_id[2] = 'b'; - keydata.key_id_size = 2; - keydata.type = NCR_KEY_TYPE_SECRET; - keydata.algorithm = NCR_ALG_AES_CBC; - keydata.flags = NCR_KEY_FLAG_EXPORTABLE; - - keydata.key = key; - keydata.idata = data; - keydata.idata_size = sizeof(data); - - if (ioctl(cfd, NCRIO_KEY_IMPORT, &keydata)) { + memset(&kimport.f, 0, sizeof(kimport.f)); + kimport.f.input_size = sizeof(kimport); + kimport.f.key = key; + kimport.f.data = data; + kimport.f.data_size = sizeof(data); + kimport.id_head.nla_len = NLA_HDRLEN + sizeof(kimport.id); + kimport.id_head.nla_type = NCR_ATTR_KEY_ID; + kimport.id[0] = 'a'; + kimport.id[1] = 'b'; + kimport.type_head.nla_len = NLA_HDRLEN + sizeof(kimport.type); + kimport.type_head.nla_type = NCR_ATTR_KEY_TYPE; + kimport.type = NCR_KEY_TYPE_SECRET; + kimport.algo_head.nla_len = NLA_HDRLEN + sizeof(kimport.algo); + kimport.algo_head.nla_type = NCR_ATTR_ALGORITHM; + kimport.algo = NCR_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; + + if (ioctl(cfd, NCRIO_KEY_IMPORT, &kimport)) { fprintf(stderr, "Error: %s:%d\n", __func__, __LINE__); perror("ioctl(NCRIO_KEY_IMPORT)"); return 1; @@ -321,7 +339,17 @@ test_ncr_wrap_key(int cfd) { int i, ret; ncr_key_t key, key2; - struct ncr_key_data_st keydata; + struct __attribute__((packed)) { + struct ncr_key_import f; + struct nlattr id_head ALIGN_NL; + uint8_t id[2] ALIGN_NL; + struct nlattr type_head ALIGN_NL; + uint32_t type ALIGN_NL; + struct nlattr algo_head ALIGN_NL; + uint32_t algo ALIGN_NL; + struct nlattr flags_head ALIGN_NL; + uint32_t flags ALIGN_NL; + } kimport; struct ncr_key_wrap_st kwrap; uint8_t data[WRAPPED_KEY_DATA_SIZE]; int data_size; @@ -341,18 +369,26 @@ test_ncr_wrap_key(int cfd) return 1; } - keydata.key_id[0] = 'a'; - keydata.key_id[2] = 'b'; - 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.key = key; - keydata.idata = "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F"; - keydata.idata_size = 16; - - if (ioctl(cfd, NCRIO_KEY_IMPORT, &keydata)) { + memset(&kimport.f, 0, sizeof(kimport.f)); + kimport.f.input_size = sizeof(kimport); + kimport.f.key = key; + kimport.f.data = "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F"; + kimport.f.data_size = 16; + kimport.id_head.nla_len = NLA_HDRLEN + sizeof(kimport.id); + kimport.id_head.nla_type = NCR_ATTR_KEY_ID; + kimport.id[0] = 'a'; + kimport.id[1] = 'b'; + kimport.type_head.nla_len = NLA_HDRLEN + sizeof(kimport.type); + kimport.type_head.nla_type = NCR_ATTR_KEY_TYPE; + kimport.type = NCR_KEY_TYPE_SECRET; + kimport.algo_head.nla_len = NLA_HDRLEN + sizeof(kimport.algo); + kimport.algo_head.nla_type = NCR_ATTR_ALGORITHM; + kimport.algo = NCR_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; + + if (ioctl(cfd, NCRIO_KEY_IMPORT, &kimport)) { fprintf(stderr, "Error: %s:%d\n", __func__, __LINE__); perror("ioctl(NCRIO_KEY_IMPORT)"); return 1; @@ -366,19 +402,27 @@ test_ncr_wrap_key(int cfd) return 1; } - keydata.key_id[0] = 'b'; - keydata.key_id[2] = 'a'; - 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_WRAPPABLE; - - keydata.key = key2; + memset(&kimport.f, 0, sizeof(kimport.f)); + kimport.f.input_size = sizeof(kimport); + kimport.f.key = key2; #define DKEY "\x00\x11\x22\x33\x44\x55\x66\x77\x88\x99\xAA\xBB\xCC\xDD\xEE\xFF" - keydata.idata = DKEY; - keydata.idata_size = 16; - - if (ioctl(cfd, NCRIO_KEY_IMPORT, &keydata)) { + kimport.f.data = DKEY; + kimport.f.data_size = 16; + kimport.id_head.nla_len = NLA_HDRLEN + sizeof(kimport.id); + kimport.id_head.nla_type = NCR_ATTR_KEY_ID; + kimport.id[0] = 'b'; + kimport.id[1] = 'a'; + kimport.type_head.nla_len = NLA_HDRLEN + sizeof(kimport.type); + kimport.type_head.nla_type = NCR_ATTR_KEY_TYPE; + kimport.type = NCR_KEY_TYPE_SECRET; + kimport.algo_head.nla_len = NLA_HDRLEN + sizeof(kimport.algo); + kimport.algo_head.nla_type = NCR_ATTR_ALGORITHM; + kimport.algo = NCR_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_WRAPPABLE; + + if (ioctl(cfd, NCRIO_KEY_IMPORT, &kimport)) { fprintf(stderr, "Error: %s:%d\n", __func__, __LINE__); perror("ioctl(NCRIO_KEY_IMPORT)"); return 1; @@ -488,7 +532,17 @@ test_ncr_wrap_key2(int cfd) { int ret; ncr_key_t key, key2; - struct ncr_key_data_st keydata; + struct __attribute__((packed)) { + struct ncr_key_import f; + struct nlattr id_head ALIGN_NL; + uint8_t id[2] ALIGN_NL; + struct nlattr type_head ALIGN_NL; + uint32_t type ALIGN_NL; + struct nlattr algo_head ALIGN_NL; + uint32_t algo ALIGN_NL; + struct nlattr flags_head ALIGN_NL; + uint32_t flags ALIGN_NL; + } kimport; struct ncr_key_wrap_st kwrap; uint8_t data[WRAPPED_KEY_DATA_SIZE]; @@ -510,18 +564,26 @@ test_ncr_wrap_key2(int cfd) return 1; } - keydata.key_id[0] = 'a'; - keydata.key_id[2] = 'b'; - 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.key = key; - keydata.idata = "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F"; - keydata.idata_size = 16; - - if (ioctl(cfd, NCRIO_KEY_IMPORT, &keydata)) { + memset(&kimport.f, 0, sizeof(kimport.f)); + kimport.f.input_size = sizeof(kimport); + kimport.f.key = key; + kimport.f.data = "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F"; + kimport.f.data_size = 16; + kimport.id_head.nla_len = NLA_HDRLEN + sizeof(kimport.id); + kimport.id_head.nla_type = NCR_ATTR_KEY_ID; + kimport.id[0] = 'a'; + kimport.id[1] = 'b'; + kimport.type_head.nla_len = NLA_HDRLEN + sizeof(kimport.type); + kimport.type_head.nla_type = NCR_ATTR_KEY_TYPE; + kimport.type = NCR_KEY_TYPE_SECRET; + kimport.algo_head.nla_len = NLA_HDRLEN + sizeof(kimport.algo); + kimport.algo_head.nla_type = NCR_ATTR_ALGORITHM; + kimport.algo = NCR_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; + + if (ioctl(cfd, NCRIO_KEY_IMPORT, &kimport)) { fprintf(stderr, "Error: %s:%d\n", __func__, __LINE__); perror("ioctl(NCRIO_KEY_IMPORT)"); return 1; @@ -534,18 +596,26 @@ test_ncr_wrap_key2(int cfd) return 1; } - keydata.key_id[0] = 'b'; - keydata.key_id[2] = 'a'; - 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_WRAPPABLE; - - keydata.key = key2; - keydata.idata = "\x00\x11\x22\x33\x44\x55\x66\x77\x88\x99\xAA\xBB\xCC\xDD\xEE\xFF\x00\x11\x22\x33\x44\x55\x66\x77\x88\x99\xAA\xBB\xCC\xDD\xEE\xFF"; - keydata.idata_size = 32; - - if (ioctl(cfd, NCRIO_KEY_IMPORT, &keydata)) { + memset(&kimport.f, 0, sizeof(kimport.f)); + kimport.f.input_size = sizeof(kimport); + kimport.f.key = key2; + kimport.f.data = "\x00\x11\x22\x33\x44\x55\x66\x77\x88\x99\xAA\xBB\xCC\xDD\xEE\xFF\x00\x11\x22\x33\x44\x55\x66\x77\x88\x99\xAA\xBB\xCC\xDD\xEE\xFF"; + kimport.f.data_size = 32; + kimport.id_head.nla_len = NLA_HDRLEN + sizeof(kimport.id); + kimport.id_head.nla_type = NCR_ATTR_KEY_ID; + kimport.id[0] = 'b'; + kimport.id[1] = 'a'; + kimport.type_head.nla_len = NLA_HDRLEN + sizeof(kimport.type); + kimport.type_head.nla_type = NCR_ATTR_KEY_TYPE; + kimport.type = NCR_KEY_TYPE_SECRET; + kimport.algo_head.nla_len = NLA_HDRLEN + sizeof(kimport.algo); + kimport.algo_head.nla_type = NCR_ATTR_ALGORITHM; + kimport.algo = NCR_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_WRAPPABLE; + + if (ioctl(cfd, NCRIO_KEY_IMPORT, &kimport)) { fprintf(stderr, "Error: %s:%d\n", __func__, __LINE__); perror("ioctl(NCRIO_KEY_IMPORT)"); return 1; @@ -574,7 +644,17 @@ test_ncr_store_wrap_key(int cfd) { int i; ncr_key_t key2; - struct ncr_key_data_st keydata; + struct __attribute__((packed)) { + struct ncr_key_import f; + struct nlattr id_head ALIGN_NL; + uint8_t id[2] ALIGN_NL; + struct nlattr type_head ALIGN_NL; + uint32_t type ALIGN_NL; + struct nlattr algo_head ALIGN_NL; + uint32_t algo ALIGN_NL; + struct nlattr flags_head ALIGN_NL; + uint32_t flags ALIGN_NL; + } kimport; struct ncr_key_export kexport; struct ncr_key_storage_wrap_st kwrap; uint8_t data[DATA_SIZE]; @@ -595,19 +675,27 @@ test_ncr_store_wrap_key(int cfd) return 1; } - keydata.key_id[0] = 'b'; - keydata.key_id[2] = 'a'; - 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_WRAPPABLE; - - keydata.key = key2; + memset(&kimport.f, 0, sizeof(kimport.f)); + kimport.f.input_size = sizeof(kimport); + kimport.f.key = key2; #define DKEY "\x00\x11\x22\x33\x44\x55\x66\x77\x88\x99\xAA\xBB\xCC\xDD\xEE\xFF" - keydata.idata = DKEY; - keydata.idata_size = 16; - - if (ioctl(cfd, NCRIO_KEY_IMPORT, &keydata)) { + kimport.f.data = DKEY; + kimport.f.data_size = 16; + kimport.id_head.nla_len = NLA_HDRLEN + sizeof(kimport.id); + kimport.id_head.nla_type = NCR_ATTR_KEY_ID; + kimport.id[0] = 'b'; + kimport.id[1] = 'a'; + kimport.type_head.nla_len = NLA_HDRLEN + sizeof(kimport.type); + kimport.type_head.nla_type = NCR_ATTR_KEY_TYPE; + kimport.type = NCR_KEY_TYPE_SECRET; + kimport.algo_head.nla_len = NLA_HDRLEN + sizeof(kimport.algo); + kimport.algo_head.nla_type = NCR_ATTR_ALGORITHM; + kimport.algo = NCR_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_WRAPPABLE; + + if (ioctl(cfd, NCRIO_KEY_IMPORT, &kimport)) { fprintf(stderr, "Error: %s:%d\n", __func__, __LINE__); perror("ioctl(NCRIO_KEY_IMPORT)"); return 1; @@ -717,7 +805,17 @@ static int test_ncr_aes(int cfd) { ncr_key_t key; - struct ncr_key_data_st keydata; + struct __attribute__((packed)) { + struct ncr_key_import f; + struct nlattr id_head ALIGN_NL; + uint8_t id[2] ALIGN_NL; + struct nlattr type_head ALIGN_NL; + uint32_t type ALIGN_NL; + struct nlattr algo_head ALIGN_NL; + uint32_t algo ALIGN_NL; + struct nlattr flags_head ALIGN_NL; + uint32_t flags ALIGN_NL; + } kimport; uint8_t data[KEY_DATA_SIZE]; int i, j; struct ncr_session_once_op_st nop; @@ -730,21 +828,28 @@ test_ncr_aes(int cfd) return 1; } - keydata.key_id[0] = 'a'; - keydata.key_id[2] = 'b'; - keydata.key_id_size = 2; - keydata.type = NCR_KEY_TYPE_SECRET; - keydata.algorithm = NCR_ALG_AES_CBC; - keydata.flags = NCR_KEY_FLAG_EXPORTABLE; - - fprintf(stdout, "Tests on AES Encryption\n"); for (i=0;ikey); if (ret < 0) { err(); return ret; @@ -328,38 +321,50 @@ size_t tmp_size; ncr_key_clear(item); - tmp = kmalloc(data.idata_size, GFP_KERNEL); + tmp = kmalloc(data->data_size, GFP_KERNEL); if (tmp == NULL) { err(); ret = -ENOMEM; goto fail; } - if (unlikely(copy_from_user(tmp, data.idata, data.idata_size))) { + if (unlikely(copy_from_user(tmp, data->data, data->data_size))) { err(); ret = -EFAULT; goto fail; } - tmp_size = data.idata_size; - - item->type = data.type; - item->algorithm = _ncr_algo_to_properties(data.algorithm); - if (item->algorithm == NULL) { + tmp_size = data->data_size; + + nla = tb[NCR_ATTR_KEY_TYPE]; + if (tb == NULL) { err(); ret = -EINVAL; goto fail; } - ncr_key_assign_flags(item, data.flags); + item->type = nla_get_u32(nla); - if (data.key_id_size > MAX_KEY_ID_SIZE) { + item->algorithm = _ncr_nla_to_properties(tb[NCR_ATTR_ALGORITHM]); + if (item->algorithm == NULL) { err(); ret = -EINVAL; goto fail; } - item->key_id_size = data.key_id_size; - if (data.key_id_size > 0) - memcpy(item->key_id, data.key_id, data.key_id_size); + nla = tb[NCR_ATTR_KEY_FLAGS]; + if (nla != NULL) + ncr_key_assign_flags(item, nla_get_u32(nla)); + + nla = tb[NCR_ATTR_KEY_ID]; + if (nla != NULL) { + if (nla_len(nla) > MAX_KEY_ID_SIZE) { + err(); + ret = -EOVERFLOW; + goto fail; + } + + item->key_id_size = nla_len(nla); + memcpy(item->key_id, nla_data(nla), item->key_id_size); + } switch(item->type) { case NCR_KEY_TYPE_SECRET: diff --git a/ncr.c b/ncr.c index bc19e248bf8..2244253aebb 100644 --- a/ncr.c +++ b/ncr.c @@ -167,10 +167,9 @@ ncr_ioctl(struct ncr_lists *lst, unsigned int cmd, unsigned long arg_) break; } CASE_NO_OUTPUT(NCRIO_KEY_EXPORT, ncr_key_export, ncr_key_export); + CASE_NO_OUTPUT(NCRIO_KEY_IMPORT, ncr_key_import, ncr_key_import); case NCRIO_KEY_DEINIT: return ncr_key_deinit(lst, arg); - case NCRIO_KEY_IMPORT: - return ncr_key_import(lst, arg); case NCRIO_KEY_WRAP: return ncr_key_wrap(lst, arg); case NCRIO_KEY_UNWRAP: @@ -216,6 +215,23 @@ static void convert_ncr_key_export(struct ncr_key_export *new, new->buffer_size = old->buffer_size; } +struct compat_ncr_key_import { + __u32 input_size, output_size; + ncr_key_t key; + compat_uptr_t data; + __u32 data_size; + __NL_ATTRIBUTES; +}; +#define COMPAT_NCRIO_KEY_IMPORT _IOWR('c', 210, struct compat_ncr_key_import) + +static void convert_ncr_key_import(struct ncr_key_import *new, + const struct compat_ncr_key_import *old) +{ + new->key = old->key; + new->data = compat_ptr(old->data); + new->data_size = old->data_size; +} + long ncr_compat_ioctl(struct ncr_lists *lst, unsigned int cmd, unsigned long arg_) { @@ -251,6 +267,7 @@ ncr_compat_ioctl(struct ncr_lists *lst, unsigned int cmd, unsigned long arg_) } CASE_NO_OUTPUT(COMPAT_NCRIO_KEY_EXPORT, ncr_key_export, ncr_key_export); + CASE_NO_OUTPUT(COMPAT_NCRIO_KEY_IMPORT, ncr_key_import, ncr_key_import); default: return -EINVAL; #undef CASE_NO_OUTPUT diff --git a/ncr.h b/ncr.h index f6982de176e..81c7621b866 100644 --- a/ncr.h +++ b/ncr.h @@ -34,6 +34,7 @@ enum { NCR_ATTR_ALGORITHM, /* NLA_U32 - ncr_algorithm_t */ NCR_ATTR_DERIVATION_ALGORITHM, /* NLA_U32 - ncr_algorithm_t */ NCR_ATTR_KEY_FLAGS, /* NLA_U32 - NCR_KEY_FLAG_* */ + NCR_ATTR_KEY_ID, /* NLA_BINARY */ NCR_ATTR_KEY_TYPE, /* NLA_U32 - ncr_key_type_t */ NCR_ATTR_SECRET_KEY_BITS, /* NLA_U32 */ NCR_ATTR_RSA_MODULUS_BITS, /* NLA_U32 */ @@ -182,18 +183,12 @@ struct ncr_key_get_info { __NL_ATTRIBUTES; }; -struct ncr_key_data_st { +struct ncr_key_import { + __u32 input_size, output_size; ncr_key_t key; - - void __user *idata; - __kernel_size_t idata_size; /* rw in get */ - - /* in case of import this will be used as key id */ - __u8 key_id[MAX_KEY_ID_SIZE]; - __kernel_size_t key_id_size; - ncr_key_type_t type; - unsigned int flags; - ncr_algorithm_t algorithm; /* valid for public/private keys */ + const void __user *data; + __u32 data_size; + __NL_ATTRIBUTES; }; struct ncr_key_export { @@ -217,7 +212,7 @@ struct ncr_key_export { /* export a secret key */ #define NCRIO_KEY_EXPORT _IOWR('c', 209, struct ncr_key_export) /* import a secret key */ -#define NCRIO_KEY_IMPORT _IOWR('c', 210, struct ncr_key_data_st) +#define NCRIO_KEY_IMPORT _IOWR('c', 210, struct ncr_key_import) #define NCRIO_KEY_DEINIT _IOR ('c', 215, ncr_key_t) diff --git a/utils.c b/utils.c index 655dc825b27..fe57c5a4169 100644 --- a/utils.c +++ b/utils.c @@ -32,6 +32,7 @@ static const struct nla_policy ncr_attr_policy[NCR_ATTR_MAX + 1] = { [NCR_ATTR_ALGORITHM] = { NLA_U32, 0 }, [NCR_ATTR_DERIVATION_ALGORITHM] = { NLA_U32, 0 }, [NCR_ATTR_KEY_FLAGS] = { NLA_U32, 0 }, + [NCR_ATTR_KEY_ID] = { NLA_BINARY, 0 }, [NCR_ATTR_KEY_TYPE] = { NLA_U32, 0 }, [NCR_ATTR_SECRET_KEY_BITS] = { NLA_U32, 0 }, [NCR_ATTR_RSA_MODULUS_BITS] = { NLA_U32, 0 }, -- cgit From 9aa6874612bf258f0a9795371db9b3dc514376aa Mon Sep 17 00:00:00 2001 From: Miloslav Trmač Date: Mon, 16 Aug 2010 15:08:29 +0200 Subject: Convert *_KEY_DEINIT --- ncr-int.h | 2 +- ncr-key.c | 10 +--------- ncr.c | 13 +++++++++++-- 3 files changed, 13 insertions(+), 12 deletions(-) diff --git a/ncr-int.h b/ncr-int.h index 79bdc14ba64..ff7e08eb44b 100644 --- a/ncr-int.h +++ b/ncr-int.h @@ -120,7 +120,7 @@ void ncr_key_assign_flags(struct key_item_st* item, unsigned int flags); /* key handling */ int ncr_key_init(struct ncr_lists *lst); -int ncr_key_deinit(struct ncr_lists *lst, void __user* arg); +int ncr_key_deinit(struct ncr_lists *lst, ncr_key_t desc); int ncr_key_export(struct ncr_lists *lst, const struct ncr_key_export *data, struct nlattr *tb[]); int ncr_key_import(struct ncr_lists *lst, const struct ncr_key_import *data, diff --git a/ncr-key.c b/ncr-key.c index 01109c7987f..56708d8fba7 100644 --- a/ncr-key.c +++ b/ncr-key.c @@ -196,17 +196,9 @@ err_limits: return ret; } -int ncr_key_deinit(struct ncr_lists *lst, void __user* arg) +int ncr_key_deinit(struct ncr_lists *lst, ncr_key_t desc) { - ncr_key_t desc; - - if (unlikely(copy_from_user(&desc, arg, sizeof(desc)))) { - err(); - return -EFAULT; - } - _ncr_key_remove(lst, desc); - return 0; } diff --git a/ncr.c b/ncr.c index 2244253aebb..fb8645c1895 100644 --- a/ncr.c +++ b/ncr.c @@ -168,8 +168,16 @@ ncr_ioctl(struct ncr_lists *lst, unsigned int cmd, unsigned long arg_) } CASE_NO_OUTPUT(NCRIO_KEY_EXPORT, ncr_key_export, ncr_key_export); CASE_NO_OUTPUT(NCRIO_KEY_IMPORT, ncr_key_import, ncr_key_import); - case NCRIO_KEY_DEINIT: - return ncr_key_deinit(lst, arg); + case NCRIO_KEY_DEINIT: { + ncr_key_t key; + + ret = get_user(key, (const ncr_key_t __user *)arg); + if (unlikely(ret)) { + err(); + return ret; + } + return ncr_key_deinit(lst, key); + } case NCRIO_KEY_WRAP: return ncr_key_wrap(lst, arg); case NCRIO_KEY_UNWRAP: @@ -249,6 +257,7 @@ ncr_compat_ioctl(struct ncr_lists *lst, unsigned int cmd, unsigned long arg_) case NCRIO_KEY_GENERATE_PAIR: case NCRIO_KEY_DERIVE: case NCRIO_KEY_GET_INFO: + case NCRIO_KEY_DEINIT: return ncr_ioctl(lst, cmd, arg_); #define CASE_NO_OUTPUT(LABEL, STRUCT, FUNCTION) \ -- cgit From 3ab6fc7d0d19f62b48ecef310249014192289613 Mon Sep 17 00:00:00 2001 From: Miloslav Trmač Date: Mon, 16 Aug 2010 16:06:43 +0200 Subject: Convert *_KEY_WRAP --- examples/ncr.c | 76 +++++++++++++++++++++++++++++++++------------------------- examples/pk.c | 65 ++++++++++++++++++++++++++++--------------------- ncr-int.h | 3 ++- ncr-key-wrap.c | 55 ++++++++++++++++++++++++++---------------- ncr.c | 23 ++++++++++++++++-- ncr.h | 13 +++++++++- utils.c | 2 ++ 7 files changed, 153 insertions(+), 84 deletions(-) diff --git a/examples/ncr.c b/examples/ncr.c index 56a59ceafe6..7324c1681e2 100644 --- a/examples/ncr.c +++ b/examples/ncr.c @@ -337,7 +337,7 @@ test_ncr_key(int cfd) static int test_ncr_wrap_key(int cfd) { - int i, ret; + int i; ncr_key_t key, key2; struct __attribute__((packed)) { struct ncr_key_import f; @@ -350,7 +350,12 @@ test_ncr_wrap_key(int cfd) struct nlattr flags_head ALIGN_NL; uint32_t flags ALIGN_NL; } kimport; - struct ncr_key_wrap_st kwrap; + struct __attribute__((packed)) { + struct ncr_key_wrap f; + struct nlattr algo_head ALIGN_NL; + uint32_t algo ALIGN_NL; + } kwrap; + struct ncr_key_wrap_st kunwrap; uint8_t data[WRAPPED_KEY_DATA_SIZE]; int data_size; @@ -429,16 +434,18 @@ test_ncr_wrap_key(int cfd) } /* now try wrapping key2 using key */ - memset(&kwrap, 0, sizeof(kwrap)); - kwrap.algorithm = NCR_WALG_AES_RFC3394; - kwrap.keytowrap = key2; - kwrap.key = key; - kwrap.io = data; - kwrap.io_size = sizeof(data); - - ret = ioctl(cfd, NCRIO_KEY_WRAP, &kwrap); - - if (geteuid() == 0 && ret) { + memset(&kwrap.f, 0, sizeof(kwrap.f)); + kwrap.f.input_size = sizeof(kwrap); + kwrap.f.wrapping_key = key; + kwrap.f.source_key = key2; + kwrap.f.buffer = data; + kwrap.f.buffer_size = sizeof(data); + kwrap.algo_head.nla_len = NLA_HDRLEN + sizeof(kwrap.algo); + kwrap.algo_head.nla_type = NCR_ATTR_WRAPPING_ALGORITHM; + kwrap.algo = NCR_WALG_AES_RFC3394; + + data_size = ioctl(cfd, NCRIO_KEY_WRAP, &kwrap); + if (geteuid() == 0 && data_size < 0) { fprintf(stderr, "Error: %s:%d\n", __func__, __LINE__); perror("ioctl(NCRIO_KEY_WRAP)"); return 1; @@ -450,14 +457,12 @@ test_ncr_wrap_key(int cfd) return 0; } - data_size = kwrap.io_size; - - if (kwrap.io_size != 24 || memcmp(data, + if (data_size != 24 || memcmp(data, "\x1F\xA6\x8B\x0A\x81\x12\xB4\x47\xAE\xF3\x4B\xD8\xFB\x5A\x7B\x82\x9D\x3E\x86\x23\x71\xD2\xCF\xE5", 24) != 0) { fprintf(stderr, "Wrapped data do not match.\n"); - fprintf(stderr, "Data[%d]: ",(int) kwrap.io_size); - for(i=0;i= 0 && i == 2) { fprintf(stderr, "Error[%d-%d]: %s:%d\n", i, sizes[i], __func__, __LINE__); /* wrapping shouldn't have been allowed */ return 1; } - if (ret == 0) { - data_size = kwrap.io_size; + if (ret >= 0) { + data_size = ret; /* try unwrapping */ - memset(&kwrap, 0, sizeof(kwrap)); - kwrap.algorithm = NCR_WALG_AES_RFC5649; - kwrap.wrapped_key_algorithm = NCR_ALG_RSA; - kwrap.keytowrap = privkey; - kwrap.key = key; - kwrap.io = data; - kwrap.io_size = data_size; - - ret = ioctl(cfd, NCRIO_KEY_UNWRAP, &kwrap); + memset(&kunwrap, 0, sizeof(kunwrap)); + kunwrap.algorithm = NCR_WALG_AES_RFC5649; + kunwrap.wrapped_key_algorithm = NCR_ALG_RSA; + kunwrap.keytowrap = privkey; + kunwrap.key = key; + kunwrap.io = data; + kunwrap.io_size = data_size; + + ret = ioctl(cfd, NCRIO_KEY_UNWRAP, &kunwrap); if (ret) { fprintf(stderr, "Error[%d-%d]: %s:%d\n", i, sizes[i], __func__, __LINE__); return 1; diff --git a/ncr-int.h b/ncr-int.h index ff7e08eb44b..f49f2efd400 100644 --- a/ncr-int.h +++ b/ncr-int.h @@ -153,7 +153,8 @@ int ncr_limits_add_and_check(uid_t uid, pid_t pid, limits_type_t type); void ncr_limits_init(void); void ncr_limits_deinit(void); -int ncr_key_wrap(struct ncr_lists *lst, void __user* arg); +int ncr_key_wrap(struct ncr_lists *lst, const struct ncr_key_wrap *wrap, + struct nlattr *tb[]); int ncr_key_unwrap(struct ncr_lists *lst, void __user* arg); int ncr_key_storage_wrap(struct ncr_lists *lst, void __user* arg); int ncr_key_storage_unwrap(struct ncr_lists *lst, void __user* arg); diff --git a/ncr-key-wrap.c b/ncr-key-wrap.c index c6f394eaac7..1cac811af23 100644 --- a/ncr-key-wrap.c +++ b/ncr-key-wrap.c @@ -29,6 +29,7 @@ #include #include #include +#include #include "ncr.h" #include "ncr-int.h" #include "cryptodev_int.h" @@ -59,7 +60,7 @@ int i,j; if (*output_size < (n+1)*8) { err(); - return -EINVAL; + return -ERANGE; } memcpy(A, iv, 8); @@ -502,21 +503,23 @@ int kek_level, wkey_level; return 0; } -int ncr_key_wrap(struct ncr_lists *lst, void __user* arg) +int ncr_key_wrap(struct ncr_lists *lst, const struct ncr_key_wrap *wrap, + struct nlattr *tb[]) { -struct ncr_key_wrap_st wrap; +const struct nlattr *nla; struct key_item_st* wkey = NULL; struct key_item_st* key = NULL; void* data = NULL; -size_t data_size; +const void *iv; +size_t data_size, iv_size; int ret; - if (unlikely(copy_from_user(&wrap, arg, sizeof(wrap)))) { + if (wrap->buffer_size < 0) { err(); - return -EFAULT; + return -EINVAL; } - ret = ncr_key_item_get_read( &wkey, lst, wrap.keytowrap); + ret = ncr_key_item_get_read(&wkey, lst, wrap->source_key); if (ret < 0) { err(); return ret; @@ -528,7 +531,7 @@ int ret; goto fail; } - ret = ncr_key_item_get_read( &key, lst, wrap.key); + ret = ncr_key_item_get_read(&key, lst, wrap->wrapping_key); if (ret < 0) { err(); goto fail; @@ -546,7 +549,7 @@ int ret; goto fail; } - data_size = wrap.io_size; + data_size = wrap->buffer_size; data = kmalloc(data_size, GFP_KERNEL); if (data == NULL) { err(); @@ -554,14 +557,29 @@ int ret; goto fail; } - switch(wrap.algorithm) { + nla = tb[NCR_ATTR_IV]; + if (nla != NULL) { + iv = nla_data(nla); + iv_size = nla_len(nla); + } else { + iv = NULL; + iv_size = 0; + } + + nla = tb[NCR_ATTR_WRAPPING_ALGORITHM]; + if (nla == NULL) { + err(); + ret = -EINVAL; + goto fail; + } + switch (nla_get_u32(nla)) { case NCR_WALG_AES_RFC3394: - ret = wrap_aes(wkey, key, data, &data_size, - wrap.params.params.cipher.iv, wrap.params.params.cipher.iv_size); + ret = wrap_aes(wkey, key, data, &data_size, iv, + iv_size); break; case NCR_WALG_AES_RFC5649: - ret = wrap_aes_rfc5649(wkey, key, data, &data_size, - wrap.params.params.cipher.iv, wrap.params.params.cipher.iv_size); + ret = wrap_aes_rfc5649(wkey, key, data, &data_size, iv, + iv_size); break; default: err(); @@ -573,18 +591,13 @@ int ret; goto fail; } - ret = copy_to_user(wrap.io, data, data_size); + ret = copy_to_user(wrap->buffer, data, data_size); if (unlikely(ret)) { ret = -EFAULT; goto fail; } - wrap.io_size = data_size; - - ret = copy_to_user(arg, &wrap, sizeof(wrap)); - if (unlikely(ret)) { - ret = -EFAULT; - } + ret = data_size; fail: if (wkey != NULL) _ncr_key_item_put(wkey); diff --git a/ncr.c b/ncr.c index fb8645c1895..202ddc926b4 100644 --- a/ncr.c +++ b/ncr.c @@ -178,8 +178,7 @@ ncr_ioctl(struct ncr_lists *lst, unsigned int cmd, unsigned long arg_) } return ncr_key_deinit(lst, key); } - case NCRIO_KEY_WRAP: - return ncr_key_wrap(lst, arg); + CASE_NO_OUTPUT(NCRIO_KEY_WRAP, ncr_key_wrap, ncr_key_wrap); case NCRIO_KEY_UNWRAP: return ncr_key_unwrap(lst, arg); case NCRIO_KEY_STORAGE_WRAP: @@ -240,6 +239,25 @@ static void convert_ncr_key_import(struct ncr_key_import *new, new->data_size = old->data_size; } +struct compat_ncr_key_wrap { + __u32 input_size, output_size; + ncr_key_t wrapping_key; + ncr_key_t source_key; + compat_uptr_t buffer; + compat_int_t buffer_size; + __NL_ATTRIBUTES; +}; +#define COMPAT_NCRIO_KEY_WRAP _IOWR('c', 250, struct compat_ncr_key_wrap) + +static void convert_ncr_key_wrap(struct ncr_key_wrap *new, + const struct compat_ncr_key_wrap *old) +{ + new->wrapping_key = old->wrapping_key; + new->source_key = old->source_key; + new->buffer = compat_ptr(old->buffer); + new->buffer_size = old->buffer_size; +} + long ncr_compat_ioctl(struct ncr_lists *lst, unsigned int cmd, unsigned long arg_) { @@ -277,6 +295,7 @@ ncr_compat_ioctl(struct ncr_lists *lst, unsigned int cmd, unsigned long arg_) CASE_NO_OUTPUT(COMPAT_NCRIO_KEY_EXPORT, ncr_key_export, ncr_key_export); CASE_NO_OUTPUT(COMPAT_NCRIO_KEY_IMPORT, ncr_key_import, ncr_key_import); + CASE_NO_OUTPUT(COMPAT_NCRIO_KEY_WRAP, ncr_key_wrap, ncr_key_wrap); default: return -EINVAL; #undef CASE_NO_OUTPUT diff --git a/ncr.h b/ncr.h index 81c7621b866..508665cd1ee 100644 --- a/ncr.h +++ b/ncr.h @@ -33,9 +33,11 @@ enum { /* FIXME: Use NLA_STRING for this, later */ NCR_ATTR_ALGORITHM, /* NLA_U32 - ncr_algorithm_t */ NCR_ATTR_DERIVATION_ALGORITHM, /* NLA_U32 - ncr_algorithm_t */ + NCR_ATTR_WRAPPING_ALGORITHM, /* NLA_U32 - ncr_wrap_algorithm_t */ NCR_ATTR_KEY_FLAGS, /* NLA_U32 - NCR_KEY_FLAG_* */ NCR_ATTR_KEY_ID, /* NLA_BINARY */ NCR_ATTR_KEY_TYPE, /* NLA_U32 - ncr_key_type_t */ + NCR_ATTR_IV, /* NLA_BINARY */ NCR_ATTR_SECRET_KEY_BITS, /* NLA_U32 */ NCR_ATTR_RSA_MODULUS_BITS, /* NLA_U32 */ NCR_ATTR_RSA_E, /* NLA_BINARY */ @@ -218,6 +220,15 @@ struct ncr_key_export { /* Key wrap ioctls */ +struct ncr_key_wrap { + __u32 input_size, output_size; + ncr_key_t wrapping_key; + ncr_key_t source_key; + void __user *buffer; + int buffer_size; + __NL_ATTRIBUTES; +}; + struct ncr_key_wrap_st { ncr_wrap_algorithm_t algorithm; @@ -237,7 +248,7 @@ struct ncr_key_wrap_st { __kernel_size_t io_size; }; -#define NCRIO_KEY_WRAP _IOWR ('c', 250, struct ncr_key_wrap_st) +#define NCRIO_KEY_WRAP _IOWR('c', 250, struct ncr_key_wrap) #define NCRIO_KEY_UNWRAP _IOR ('c', 251, struct ncr_key_wrap_st) /* Internal ops */ diff --git a/utils.c b/utils.c index fe57c5a4169..1ae66fc1320 100644 --- a/utils.c +++ b/utils.c @@ -31,9 +31,11 @@ static const struct nla_policy ncr_attr_policy[NCR_ATTR_MAX + 1] = { [NCR_ATTR_ALGORITHM] = { NLA_U32, 0 }, [NCR_ATTR_DERIVATION_ALGORITHM] = { NLA_U32, 0 }, + [NCR_ATTR_WRAPPING_ALGORITHM] = { NLA_U32, 0 }, [NCR_ATTR_KEY_FLAGS] = { NLA_U32, 0 }, [NCR_ATTR_KEY_ID] = { NLA_BINARY, 0 }, [NCR_ATTR_KEY_TYPE] = { NLA_U32, 0 }, + [NCR_ATTR_IV] = { NLA_BINARY, 0 }, [NCR_ATTR_SECRET_KEY_BITS] = { NLA_U32, 0 }, [NCR_ATTR_RSA_MODULUS_BITS] = { NLA_U32, 0 }, [NCR_ATTR_RSA_E] = { NLA_BINARY, 0 }, -- cgit From 96ec7e16575010e4d48c47ade593ca91690c105b Mon Sep 17 00:00:00 2001 From: Miloslav Trmač Date: Mon, 16 Aug 2010 16:18:07 +0200 Subject: Convert *_KEY_UNWRAP --- examples/ncr.c | 26 ++++++++++++----- examples/pk.c | 30 ++++++++++++++------ ncr-int.h | 3 +- ncr-key-wrap.c | 89 ++++++++++++++++++++++++++++++++++++---------------------- ncr.c | 23 +++++++++++++-- ncr.h | 26 ++++++----------- 6 files changed, 128 insertions(+), 69 deletions(-) diff --git a/examples/ncr.c b/examples/ncr.c index 7324c1681e2..d4af05d098d 100644 --- a/examples/ncr.c +++ b/examples/ncr.c @@ -355,7 +355,13 @@ test_ncr_wrap_key(int cfd) struct nlattr algo_head ALIGN_NL; uint32_t algo ALIGN_NL; } kwrap; - struct ncr_key_wrap_st kunwrap; + struct __attribute__((packed)) { + struct ncr_key_unwrap f; + struct nlattr wrap_algo_head ALIGN_NL; + uint32_t wrap_algo ALIGN_NL; + struct nlattr algo_head ALIGN_NL; + uint32_t algo ALIGN_NL; + } kunwrap; uint8_t data[WRAPPED_KEY_DATA_SIZE]; int data_size; @@ -483,12 +489,18 @@ test_ncr_wrap_key(int cfd) return 1; } - memset(&kunwrap, 0, sizeof(kunwrap)); - kunwrap.algorithm = NCR_WALG_AES_RFC3394; - kunwrap.keytowrap = key2; - kunwrap.key = key; - kunwrap.io = data; - kunwrap.io_size = data_size; + memset(&kunwrap.f, 0, sizeof(kunwrap.f)); + kunwrap.f.input_size = sizeof(kunwrap); + kunwrap.f.wrapping_key = key; + kunwrap.f.dest_key = key2; + kunwrap.f.data = data; + kunwrap.f.data_size = data_size; + kunwrap.wrap_algo_head.nla_len = NLA_HDRLEN + sizeof(kunwrap.wrap_algo); + kunwrap.wrap_algo_head.nla_type = NCR_ATTR_WRAPPING_ALGORITHM; + 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; + kunwrap.algo = NCR_ALG_AES_CBC; if (ioctl(cfd, NCRIO_KEY_UNWRAP, &kunwrap)) { perror("ioctl(NCRIO_KEY_UNWRAP)"); diff --git a/examples/pk.c b/examples/pk.c index f2a8a689dda..ac95820adaa 100644 --- a/examples/pk.c +++ b/examples/pk.c @@ -613,7 +613,13 @@ test_ncr_wrap_key3(int cfd) struct nlattr algo_head ALIGN_NL; uint32_t algo ALIGN_NL; } kwrap; - struct ncr_key_wrap_st kunwrap; + struct __attribute__((packed)) { + struct ncr_key_unwrap f; + struct nlattr wrap_algo_head ALIGN_NL; + uint32_t wrap_algo ALIGN_NL; + struct nlattr algo_head ALIGN_NL; + uint32_t algo ALIGN_NL; + } kunwrap; struct __attribute__((packed)) { struct ncr_key_generate_pair f; struct nlattr algo_head ALIGN_NL; @@ -753,13 +759,21 @@ test_ncr_wrap_key3(int cfd) data_size = ret; /* try unwrapping */ - memset(&kunwrap, 0, sizeof(kunwrap)); - kunwrap.algorithm = NCR_WALG_AES_RFC5649; - kunwrap.wrapped_key_algorithm = NCR_ALG_RSA; - kunwrap.keytowrap = privkey; - kunwrap.key = key; - kunwrap.io = data; - kunwrap.io_size = data_size; + memset(&kunwrap.f, 0, sizeof(kunwrap.f)); + kunwrap.f.input_size = sizeof(kunwrap); + kunwrap.f.wrapping_key = key; + kunwrap.f.dest_key = privkey; + kunwrap.f.data = data; + kunwrap.f.data_size = data_size; + kunwrap.wrap_algo_head.nla_len + = NLA_HDRLEN + sizeof(kunwrap.wrap_algo); + kunwrap.wrap_algo_head.nla_type + = NCR_ATTR_WRAPPING_ALGORITHM; + 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; + kunwrap.algo = NCR_ALG_RSA; ret = ioctl(cfd, NCRIO_KEY_UNWRAP, &kunwrap); if (ret) { diff --git a/ncr-int.h b/ncr-int.h index f49f2efd400..6f4fb94bc72 100644 --- a/ncr-int.h +++ b/ncr-int.h @@ -155,7 +155,8 @@ void ncr_limits_deinit(void); int ncr_key_wrap(struct ncr_lists *lst, const struct ncr_key_wrap *wrap, struct nlattr *tb[]); -int ncr_key_unwrap(struct ncr_lists *lst, void __user* arg); +int ncr_key_unwrap(struct ncr_lists *lst, const struct ncr_key_unwrap *wrap, + struct nlattr *tb[]); int ncr_key_storage_wrap(struct ncr_lists *lst, void __user* arg); int ncr_key_storage_unwrap(struct ncr_lists *lst, void __user* arg); diff --git a/ncr-key-wrap.c b/ncr-key-wrap.c index 1cac811af23..725b5949153 100644 --- a/ncr-key-wrap.c +++ b/ncr-key-wrap.c @@ -39,8 +39,8 @@ 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, - struct key_item_st* key, const void* data, size_t data_size); +static int key_from_packed_data(struct nlattr *tb[], struct key_item_st* key, + const void* data, size_t data_size); static void val64_xor( val64_t val, uint32_t x) @@ -282,12 +282,13 @@ size_t sdata_size = 0; } static int unwrap_aes_rfc5649(struct key_item_st* output, struct key_item_st *kek, - void* wrapped, size_t wrapped_size, - struct ncr_key_wrap_st* wrap_st) + void *wrapped, size_t wrapped_size, struct nlattr *tb[]) { -int ret; +const struct nlattr *nla; +int ret, iv_size; void * sdata; size_t sdata_size = KEY_DATA_MAX_SIZE; +const uint8_t *iv; sdata = kmalloc(sdata_size, GFP_KERNEL); if (sdata == NULL) { @@ -295,16 +296,23 @@ size_t sdata_size = KEY_DATA_MAX_SIZE; return -ENOMEM; } + nla = tb[NCR_ATTR_IV]; + if (nla != NULL) { + iv = nla_data(nla); + iv_size = nla_len(nla); + } else { + iv = NULL; + iv_size = 0; + } + ret = _unwrap_aes_rfc5649(sdata, &sdata_size, kek, - wrapped, wrapped_size, - wrap_st->params.params.cipher.iv, wrap_st->params.params.cipher.iv_size); + wrapped, wrapped_size, iv, iv_size); if (ret < 0) { err(); goto fail; } - ret = key_from_packed_data(wrap_st->wrapped_key_algorithm, wrap_st->wrapped_key_flags, - output, sdata, sdata_size); + ret = key_from_packed_data(tb, output, sdata, sdata_size); if (ret < 0) { err(); goto fail; @@ -399,16 +407,24 @@ void print_val64(char* str, val64_t val) #endif static int unwrap_aes_rfc3394(struct key_item_st* output, struct key_item_st *kek, - void* wrapped_key, size_t wrapped_key_size, struct ncr_key_wrap_st *wrap_st) + void* wrapped_key, size_t wrapped_key_size, + struct nlattr *tb[]) { +const struct nlattr *nla; size_t n; val64_t A; int i, ret; struct cipher_data ctx; val64_t * R = NULL; -int iv_size = wrap_st->params.params.cipher.iv_size; -const uint8_t * iv = wrap_st->params.params.cipher.iv; +int iv_size; +const uint8_t *iv; + nla = tb[NCR_ATTR_IV]; + if (nla != NULL) { + iv = nla_data(nla); + iv_size = nla_len(nla); + } else + iv_size = 0; if (iv_size < sizeof(initA)) { iv_size = sizeof(initA); iv = initA; @@ -460,7 +476,9 @@ const uint8_t * iv = wrap_st->params.params.cipher.iv; memcpy(&output->key.secret.data[i*8], R[i], sizeof(R[i])); } output->key.secret.size = n*8; - ncr_key_assign_flags(output, wrap_st->wrapped_key_flags); + nla = tb[NCR_ATTR_KEY_FLAGS]; + if (nla != NULL) + ncr_key_assign_flags(output, nla_get_u32(nla)); output->type = NCR_KEY_TYPE_SECRET; ret = 0; @@ -610,27 +628,23 @@ fail: /* Unwraps keys. All keys unwrapped are not accessible by * userspace. */ -int ncr_key_unwrap(struct ncr_lists *lst, void __user* arg) +int ncr_key_unwrap(struct ncr_lists *lst, const struct ncr_key_unwrap *wrap, + struct nlattr *tb[]) { -struct ncr_key_wrap_st wrap; +const struct nlattr *nla; struct key_item_st* wkey = NULL; struct key_item_st* key = NULL; void* data = NULL; size_t data_size; int ret; - if (unlikely(copy_from_user(&wrap, arg, sizeof(wrap)))) { - err(); - return -EFAULT; - } - - ret = ncr_key_item_get_write( &wkey, lst, wrap.keytowrap); + ret = ncr_key_item_get_write(&wkey, lst, wrap->dest_key); if (ret < 0) { err(); return ret; } - ret = ncr_key_item_get_read( &key, lst, wrap.key); + ret = ncr_key_item_get_read(&key, lst, wrap->wrapping_key); if (ret < 0) { err(); goto fail; @@ -642,7 +656,7 @@ int ret; goto fail; } - data_size = wrap.io_size; + data_size = wrap->data_size; data = kmalloc(data_size, GFP_KERNEL); if (data == NULL) { err(); @@ -650,7 +664,7 @@ int ret; goto fail; } - if (unlikely(copy_from_user(data, wrap.io, data_size))) { + if (unlikely(copy_from_user(data, wrap->data, data_size))) { err(); ret = -EFAULT; goto fail; @@ -658,14 +672,20 @@ int ret; ncr_key_clear(wkey); - switch(wrap.algorithm) { + nla = tb[NCR_ATTR_WRAPPING_ALGORITHM]; + if (nla == NULL) { + err(); + ret = -EINVAL; + goto fail; + } + switch (nla_get_u32(nla)) { case NCR_WALG_AES_RFC3394: - ret = unwrap_aes_rfc3394(wkey, key, data, data_size, - &wrap); + ret = unwrap_aes_rfc3394(wkey, key, data, data_size, + tb); break; case NCR_WALG_AES_RFC5649: - ret = unwrap_aes_rfc5649(wkey, key, - data, data_size, &wrap); + ret = unwrap_aes_rfc5649(wkey, key, data, data_size, + tb); break; default: err(); @@ -859,9 +879,10 @@ fail: return ret; } -static int key_from_packed_data(ncr_algorithm_t algorithm, unsigned int flags, - struct key_item_st* key, const void* data, size_t data_size) +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; if (data_size > KEY_DATA_MAX_SIZE) { @@ -869,14 +890,16 @@ static int key_from_packed_data(ncr_algorithm_t algorithm, unsigned int flags, return -EINVAL; } - key->algorithm = _ncr_algo_to_properties(algorithm); + key->algorithm = _ncr_nla_to_properties(tb[NCR_ATTR_ALGORITHM]); if (key->algorithm == NULL) { err(); return -EINVAL; } key->type = key->algorithm->key_type; - ncr_key_assign_flags(key, flags); + nla = tb[NCR_ATTR_KEY_FLAGS]; + if (nla != NULL) + ncr_key_assign_flags(key, nla_get_u32(nla)); if (key->type == NCR_KEY_TYPE_SECRET) { if (data_size > NCR_CIPHER_MAX_KEY_LEN) { diff --git a/ncr.c b/ncr.c index 202ddc926b4..5913f9d9cda 100644 --- a/ncr.c +++ b/ncr.c @@ -179,8 +179,7 @@ ncr_ioctl(struct ncr_lists *lst, unsigned int cmd, unsigned long arg_) return ncr_key_deinit(lst, key); } CASE_NO_OUTPUT(NCRIO_KEY_WRAP, ncr_key_wrap, ncr_key_wrap); - case NCRIO_KEY_UNWRAP: - return ncr_key_unwrap(lst, arg); + CASE_NO_OUTPUT(NCRIO_KEY_UNWRAP, ncr_key_unwrap, ncr_key_unwrap); case NCRIO_KEY_STORAGE_WRAP: return ncr_key_storage_wrap(lst, arg); case NCRIO_KEY_STORAGE_UNWRAP: @@ -258,6 +257,25 @@ static void convert_ncr_key_wrap(struct ncr_key_wrap *new, new->buffer_size = old->buffer_size; } +struct compat_ncr_key_unwrap { + __u32 input_size, output_size; + ncr_key_t wrapping_key; + ncr_key_t dest_key; + compat_uptr_t data; + __u32 data_size; + __NL_ATTRIBUTES; +}; +#define COMPAT_NCRIO_KEY_UNWRAP _IOWR('c', 251, struct compat_ncr_key_unwrap) + +static void convert_ncr_key_unwrap(struct ncr_key_unwrap *new, + const struct compat_ncr_key_unwrap *old) +{ + new->wrapping_key = old->wrapping_key; + new->dest_key = old->dest_key; + new->data = compat_ptr(old->data); + new->data_size = old->data_size; +} + long ncr_compat_ioctl(struct ncr_lists *lst, unsigned int cmd, unsigned long arg_) { @@ -296,6 +314,7 @@ ncr_compat_ioctl(struct ncr_lists *lst, unsigned int cmd, unsigned long arg_) CASE_NO_OUTPUT(COMPAT_NCRIO_KEY_EXPORT, ncr_key_export, ncr_key_export); CASE_NO_OUTPUT(COMPAT_NCRIO_KEY_IMPORT, ncr_key_import, ncr_key_import); CASE_NO_OUTPUT(COMPAT_NCRIO_KEY_WRAP, ncr_key_wrap, ncr_key_wrap); + CASE_NO_OUTPUT(COMPAT_NCRIO_KEY_UNWRAP, ncr_key_unwrap, ncr_key_unwrap); default: return -EINVAL; #undef CASE_NO_OUTPUT diff --git a/ncr.h b/ncr.h index 508665cd1ee..2b45fe8a4a9 100644 --- a/ncr.h +++ b/ncr.h @@ -229,27 +229,17 @@ struct ncr_key_wrap { __NL_ATTRIBUTES; }; -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; - - ncr_key_t key; - struct ncr_key_params_st params; - - void __user * io; /* encrypted keytowrap */ - /* this will be updated by the actual size on wrap */ - __kernel_size_t io_size; +struct ncr_key_unwrap { + __u32 input_size, output_size; + ncr_key_t wrapping_key; + ncr_key_t dest_key; + const void __user *data; + __u32 data_size; + __NL_ATTRIBUTES; }; #define NCRIO_KEY_WRAP _IOWR('c', 250, struct ncr_key_wrap) -#define NCRIO_KEY_UNWRAP _IOR ('c', 251, struct ncr_key_wrap_st) +#define NCRIO_KEY_UNWRAP _IOWR('c', 251, struct ncr_key_unwrap) /* Internal ops */ struct ncr_master_key_st { -- cgit From 2039b544b32e37bb4aea4ed06ac9ef905f656326 Mon Sep 17 00:00:00 2001 From: Miloslav Trmač Date: Mon, 16 Aug 2010 16:56:49 +0200 Subject: Convert *_KEY_STORAGE_WRAP --- examples/ncr.c | 23 ++++++++++++----------- ncr-int.h | 4 +++- ncr-key-wrap.c | 22 +++++++++------------- ncr.c | 24 ++++++++++++++++++++++-- ncr.h | 10 +++++++++- 5 files changed, 55 insertions(+), 28 deletions(-) diff --git a/examples/ncr.c b/examples/ncr.c index d4af05d098d..52cc9edeb27 100644 --- a/examples/ncr.c +++ b/examples/ncr.c @@ -680,7 +680,8 @@ test_ncr_store_wrap_key(int cfd) uint32_t flags ALIGN_NL; } kimport; struct ncr_key_export kexport; - struct ncr_key_storage_wrap_st kwrap; + struct ncr_key_storage_wrap kwrap; + struct ncr_key_storage_wrap_st kunwrap; uint8_t data[DATA_SIZE]; int data_size; @@ -727,18 +728,18 @@ test_ncr_store_wrap_key(int cfd) /* now try wrapping key2 using key */ memset(&kwrap, 0, sizeof(kwrap)); - kwrap.keytowrap = key2; - kwrap.io = data; - kwrap.io_size = sizeof(data); + kwrap.key = key2; + kwrap.buffer = data; + kwrap.buffer_size = sizeof(data); - if (ioctl(cfd, NCRIO_KEY_STORAGE_WRAP, &kwrap)) { + data_size = ioctl(cfd, NCRIO_KEY_STORAGE_WRAP, &kwrap); + if (data_size < 0) { fprintf(stderr, "Error: %s:%d\n", __func__, __LINE__); perror("ioctl(NCRIO_KEY_STORAGE_WRAP)"); return 1; } /* test unwrapping */ - data_size = kwrap.io_size; fprintf(stdout, "\tKey Storage Unwrap test...\n"); /* reset key2 */ @@ -755,12 +756,12 @@ test_ncr_store_wrap_key(int cfd) return 1; } - memset(&kwrap, 0, sizeof(kwrap)); - kwrap.keytowrap = key2; - kwrap.io = data; - kwrap.io_size = data_size; + memset(&kunwrap, 0, sizeof(kunwrap)); + kunwrap.keytowrap = key2; + kunwrap.io = data; + kunwrap.io_size = data_size; - if (ioctl(cfd, NCRIO_KEY_STORAGE_UNWRAP, &kwrap)) { + if (ioctl(cfd, NCRIO_KEY_STORAGE_UNWRAP, &kunwrap)) { fprintf(stderr, "Error: %s:%d\n", __func__, __LINE__); perror("ioctl(NCRIO_KEY_STORAGE_UNWRAP)"); return 1; diff --git a/ncr-int.h b/ncr-int.h index 6f4fb94bc72..419b9e69930 100644 --- a/ncr-int.h +++ b/ncr-int.h @@ -157,7 +157,9 @@ int ncr_key_wrap(struct ncr_lists *lst, const struct ncr_key_wrap *wrap, struct nlattr *tb[]); int ncr_key_unwrap(struct ncr_lists *lst, const struct ncr_key_unwrap *wrap, struct nlattr *tb[]); -int ncr_key_storage_wrap(struct ncr_lists *lst, void __user* arg); +int ncr_key_storage_wrap(struct ncr_lists *lst, + const struct ncr_key_storage_wrap *wrap, + struct nlattr *tb[]); int ncr_key_storage_unwrap(struct ncr_lists *lst, void __user* arg); /* sessions */ diff --git a/ncr-key-wrap.c b/ncr-key-wrap.c index 725b5949153..1da90f5cbda 100644 --- a/ncr-key-wrap.c +++ b/ncr-key-wrap.c @@ -700,9 +700,10 @@ fail: return ret; } -int ncr_key_storage_wrap(struct ncr_lists *lst, void __user* arg) +int ncr_key_storage_wrap(struct ncr_lists *lst, + const struct ncr_key_storage_wrap *wrap, + struct nlattr *tb[]) { -struct ncr_key_storage_wrap_st wrap; struct key_item_st* wkey = NULL; void* data = NULL; size_t data_size; @@ -715,18 +716,18 @@ int ret; return -ENOKEY; } - if (unlikely(copy_from_user(&wrap, arg, sizeof(wrap)))) { + if (wrap->buffer_size < 0) { err(); - return -EFAULT; + return -EINVAL; } - ret = ncr_key_item_get_read( &wkey, lst, wrap.keytowrap); + ret = ncr_key_item_get_read(&wkey, lst, wrap->key); if (ret < 0) { err(); return ret; } - data_size = wrap.io_size; + data_size = wrap->buffer_size; data = kmalloc(data_size, GFP_KERNEL); if (data == NULL) { err(); @@ -746,18 +747,13 @@ int ret; goto fail; } - ret = copy_to_user(wrap.io, data, data_size); + ret = copy_to_user(wrap->buffer, data, data_size); if (unlikely(ret)) { ret = -EFAULT; goto fail; } - wrap.io_size = data_size; - - ret = copy_to_user(arg, &wrap, sizeof(wrap)); - if (unlikely(ret)) { - ret = -EFAULT; - } + ret = data_size; fail: if (wkey != NULL) _ncr_key_item_put(wkey); diff --git a/ncr.c b/ncr.c index 5913f9d9cda..76c1971358c 100644 --- a/ncr.c +++ b/ncr.c @@ -180,8 +180,8 @@ ncr_ioctl(struct ncr_lists *lst, unsigned int cmd, unsigned long arg_) } CASE_NO_OUTPUT(NCRIO_KEY_WRAP, ncr_key_wrap, ncr_key_wrap); CASE_NO_OUTPUT(NCRIO_KEY_UNWRAP, ncr_key_unwrap, ncr_key_unwrap); - case NCRIO_KEY_STORAGE_WRAP: - return ncr_key_storage_wrap(lst, arg); + CASE_NO_OUTPUT(NCRIO_KEY_STORAGE_WRAP, ncr_key_storage_wrap, + ncr_key_storage_wrap); case NCRIO_KEY_STORAGE_UNWRAP: return ncr_key_storage_unwrap(lst, arg); case NCRIO_SESSION_INIT: @@ -276,6 +276,24 @@ static void convert_ncr_key_unwrap(struct ncr_key_unwrap *new, new->data_size = old->data_size; } +struct compat_ncr_key_storage_wrap { + __u32 input_size, output_size; + ncr_key_t key; + compat_uptr_t buffer; + compat_int_t buffer_size; + __NL_ATTRIBUTES; +}; +#define COMPAT_NCRIO_KEY_STORAGE_WRAP \ + _IOWR('c', 261, struct compat_ncr_key_storage_wrap) + +static void convert_ncr_key_storage_wrap(struct ncr_key_storage_wrap *new, + const struct compat_ncr_key_storage_wrap *old) +{ + new->key = old->key; + new->buffer = compat_ptr(old->buffer); + new->buffer_size = old->buffer_size; +} + long ncr_compat_ioctl(struct ncr_lists *lst, unsigned int cmd, unsigned long arg_) { @@ -315,6 +333,8 @@ ncr_compat_ioctl(struct ncr_lists *lst, unsigned int cmd, unsigned long arg_) CASE_NO_OUTPUT(COMPAT_NCRIO_KEY_IMPORT, ncr_key_import, ncr_key_import); CASE_NO_OUTPUT(COMPAT_NCRIO_KEY_WRAP, ncr_key_wrap, ncr_key_wrap); CASE_NO_OUTPUT(COMPAT_NCRIO_KEY_UNWRAP, ncr_key_unwrap, ncr_key_unwrap); + CASE_NO_OUTPUT(COMPAT_NCRIO_KEY_STORAGE_WRAP, ncr_key_storage_wrap, + ncr_key_storage_wrap); default: return -EINVAL; #undef CASE_NO_OUTPUT diff --git a/ncr.h b/ncr.h index 2b45fe8a4a9..10d1f719fe4 100644 --- a/ncr.h +++ b/ncr.h @@ -251,6 +251,14 @@ struct ncr_master_key_st { /* These are similar to key_wrap and unwrap except that will store some extra * fields to be able to recover a key */ +struct ncr_key_storage_wrap { + __u32 input_size, output_size; + ncr_key_t key; + void __user *buffer; + int buffer_size; + __NL_ATTRIBUTES; +}; + struct ncr_key_storage_wrap_st { ncr_key_t keytowrap; @@ -259,7 +267,7 @@ struct ncr_key_storage_wrap_st { __kernel_size_t io_size; }; -#define NCRIO_KEY_STORAGE_WRAP _IOWR ('c', 261, struct ncr_key_storage_wrap_st) +#define NCRIO_KEY_STORAGE_WRAP _IOWR('c', 261, struct ncr_key_storage_wrap) #define NCRIO_KEY_STORAGE_UNWRAP _IOR ('c', 262, struct ncr_key_storage_wrap_st) /* Crypto Operations ioctls -- cgit From e536df1a394cf653ecc5964ece0551b0259abeb4 Mon Sep 17 00:00:00 2001 From: Miloslav Trmač Date: Mon, 16 Aug 2010 17:18:10 +0200 Subject: Convert *_KEY_STORAGE_UNWRAP --- examples/ncr.c | 8 ++++---- ncr-int.h | 4 +++- ncr-key-wrap.c | 19 ++++++------------- ncr.c | 24 ++++++++++++++++++++++-- ncr.h | 14 +++++++------- 5 files changed, 42 insertions(+), 27 deletions(-) diff --git a/examples/ncr.c b/examples/ncr.c index 52cc9edeb27..49f5e38dec0 100644 --- a/examples/ncr.c +++ b/examples/ncr.c @@ -681,7 +681,7 @@ test_ncr_store_wrap_key(int cfd) } kimport; struct ncr_key_export kexport; struct ncr_key_storage_wrap kwrap; - struct ncr_key_storage_wrap_st kunwrap; + struct ncr_key_storage_unwrap kunwrap; uint8_t data[DATA_SIZE]; int data_size; @@ -757,9 +757,9 @@ test_ncr_store_wrap_key(int cfd) } memset(&kunwrap, 0, sizeof(kunwrap)); - kunwrap.keytowrap = key2; - kunwrap.io = data; - kunwrap.io_size = data_size; + kunwrap.key = key2; + kunwrap.data = data; + kunwrap.data_size = data_size; if (ioctl(cfd, NCRIO_KEY_STORAGE_UNWRAP, &kunwrap)) { fprintf(stderr, "Error: %s:%d\n", __func__, __LINE__); diff --git a/ncr-int.h b/ncr-int.h index 419b9e69930..b8f12503ec6 100644 --- a/ncr-int.h +++ b/ncr-int.h @@ -160,7 +160,9 @@ int ncr_key_unwrap(struct ncr_lists *lst, const struct ncr_key_unwrap *wrap, int ncr_key_storage_wrap(struct ncr_lists *lst, const struct ncr_key_storage_wrap *wrap, struct nlattr *tb[]); -int ncr_key_storage_unwrap(struct ncr_lists *lst, void __user* arg); +int ncr_key_storage_unwrap(struct ncr_lists *lst, + const struct ncr_key_storage_unwrap *wrap, + struct nlattr *tb[]); /* sessions */ struct session_item_st* ncr_session_new(struct ncr_lists *lst); diff --git a/ncr-key-wrap.c b/ncr-key-wrap.c index 1da90f5cbda..de4bcdd5ff4 100644 --- a/ncr-key-wrap.c +++ b/ncr-key-wrap.c @@ -763,12 +763,10 @@ fail: return ret; } -/* Unwraps keys. All keys unwrapped are not accessible by - * userspace. - */ -int ncr_key_storage_unwrap(struct ncr_lists *lst, void __user* arg) +int ncr_key_storage_unwrap(struct ncr_lists *lst, + const struct ncr_key_storage_unwrap *wrap, + struct nlattr *tb[]) { -struct ncr_key_storage_wrap_st wrap; struct key_item_st* wkey = NULL; void* data = NULL; uint8_t * sdata = NULL; @@ -780,18 +778,13 @@ int ret; return -ENOKEY; } - if (unlikely(copy_from_user(&wrap, arg, sizeof(wrap)))) { - err(); - return -EFAULT; - } - - ret = ncr_key_item_get_write( &wkey, lst, wrap.keytowrap); + ret = ncr_key_item_get_write(&wkey, lst, wrap->key); if (ret < 0) { err(); return ret; } - data_size = wrap.io_size; + data_size = wrap->data_size; data = kmalloc(data_size, GFP_KERNEL); if (data == NULL) { err(); @@ -799,7 +792,7 @@ int ret; goto fail; } - if (unlikely(copy_from_user(data, wrap.io, data_size))) { + if (unlikely(copy_from_user(data, wrap->data, data_size))) { err(); ret = -EFAULT; goto fail; diff --git a/ncr.c b/ncr.c index 76c1971358c..1bee991234c 100644 --- a/ncr.c +++ b/ncr.c @@ -182,8 +182,8 @@ ncr_ioctl(struct ncr_lists *lst, unsigned int cmd, unsigned long arg_) CASE_NO_OUTPUT(NCRIO_KEY_UNWRAP, ncr_key_unwrap, ncr_key_unwrap); CASE_NO_OUTPUT(NCRIO_KEY_STORAGE_WRAP, ncr_key_storage_wrap, ncr_key_storage_wrap); - case NCRIO_KEY_STORAGE_UNWRAP: - return ncr_key_storage_unwrap(lst, arg); + CASE_NO_OUTPUT(NCRIO_KEY_STORAGE_UNWRAP, ncr_key_storage_unwrap, + ncr_key_storage_unwrap); case NCRIO_SESSION_INIT: return ncr_session_init(lst, arg); case NCRIO_SESSION_UPDATE: @@ -294,6 +294,24 @@ static void convert_ncr_key_storage_wrap(struct ncr_key_storage_wrap *new, new->buffer_size = old->buffer_size; } +struct compat_ncr_key_storage_unwrap { + __u32 input_size, output_size; + ncr_key_t key; + compat_uptr_t data; + __u32 data_size; + __NL_ATTRIBUTES; +}; +#define COMPAT_NCRIO_KEY_STORAGE_UNWRAP \ + _IOWR('c', 262, struct compat_ncr_key_storage_wrap) + +static void convert_ncr_key_storage_unwrap(struct ncr_key_storage_unwrap *new, + const struct compat_ncr_key_storage_unwrap *old) +{ + new->key = old->key; + new->data = compat_ptr(old->data); + new->data_size = old->data_size; +} + long ncr_compat_ioctl(struct ncr_lists *lst, unsigned int cmd, unsigned long arg_) { @@ -335,6 +353,8 @@ ncr_compat_ioctl(struct ncr_lists *lst, unsigned int cmd, unsigned long arg_) CASE_NO_OUTPUT(COMPAT_NCRIO_KEY_UNWRAP, ncr_key_unwrap, ncr_key_unwrap); CASE_NO_OUTPUT(COMPAT_NCRIO_KEY_STORAGE_WRAP, ncr_key_storage_wrap, ncr_key_storage_wrap); + CASE_NO_OUTPUT(COMPAT_NCRIO_KEY_STORAGE_UNWRAP, ncr_key_storage_unwrap, + ncr_key_storage_unwrap); default: return -EINVAL; #undef CASE_NO_OUTPUT diff --git a/ncr.h b/ncr.h index 10d1f719fe4..46cf8cbdf99 100644 --- a/ncr.h +++ b/ncr.h @@ -259,16 +259,16 @@ struct ncr_key_storage_wrap { __NL_ATTRIBUTES; }; -struct ncr_key_storage_wrap_st { - ncr_key_t keytowrap; - - void __user * io; /* encrypted keytowrap */ - /* this will be updated by the actual size on wrap */ - __kernel_size_t io_size; +struct ncr_key_storage_unwrap { + __u32 input_size, output_size; + ncr_key_t key; + const void __user *data; + __u32 data_size; + __NL_ATTRIBUTES; }; #define NCRIO_KEY_STORAGE_WRAP _IOWR('c', 261, struct ncr_key_storage_wrap) -#define NCRIO_KEY_STORAGE_UNWRAP _IOR ('c', 262, struct ncr_key_storage_wrap_st) +#define NCRIO_KEY_STORAGE_UNWRAP _IOWR('c', 262, struct ncr_key_storage_wrap) /* Crypto Operations ioctls */ -- cgit From 7017a63132bc03462ba75e399c083e00f4e19573 Mon Sep 17 00:00:00 2001 From: Miloslav Trmač Date: Mon, 16 Aug 2010 22:50:56 +0200 Subject: Convert *_SESSION_* --- examples/ncr.c | 218 ++++++++++++++--------- examples/pk.c | 334 +++++++++++++++++++++++++----------- examples/speed.c | 48 ++++-- ncr-int.h | 42 ++++- ncr-pk.c | 150 +++++----------- ncr-pk.h | 15 +- ncr-sessions.c | 514 +++++++++++++++++++++++++++---------------------------- ncr.c | 117 +++++++++++-- ncr.h | 112 +++++------- utils.c | 37 ++++ 10 files changed, 937 insertions(+), 650 deletions(-) diff --git a/examples/ncr.c b/examples/ncr.c index 49f5e38dec0..facecd88ec0 100644 --- a/examples/ncr.c +++ b/examples/ncr.c @@ -843,8 +843,18 @@ test_ncr_aes(int cfd) } kimport; uint8_t data[KEY_DATA_SIZE]; int i, j; - struct ncr_session_once_op_st nop; - int data_size; + struct __attribute__((packed)) { + struct ncr_session_once f; + struct nlattr algo_head ALIGN_NL; + uint32_t algo ALIGN_NL; + struct nlattr key_head ALIGN_NL; + uint32_t key ALIGN_NL; + struct nlattr input_head ALIGN_NL; + struct ncr_session_input_data input ALIGN_NL; + struct nlattr output_head ALIGN_NL; + struct ncr_session_output_buffer output ALIGN_NL; + } op; + size_t data_size; /* convert it to key */ key = ioctl(cfd, NCRIO_KEY_INIT); @@ -881,23 +891,30 @@ test_ncr_aes(int cfd) } /* encrypt */ - memset(&nop, 0, sizeof(nop)); - nop.init.algorithm = NCR_ALG_AES_ECB; - nop.init.key = key; - nop.init.op = NCR_OP_ENCRYPT; - nop.op.data.udata.input = (void*)aes_vectors[i].plaintext; - nop.op.data.udata.input_size = 16; - nop.op.data.udata.output = data; - nop.op.data.udata.output_size = sizeof(data); - nop.op.type = NCR_DIRECT_DATA; - - if (ioctl(cfd, NCRIO_SESSION_ONCE, &nop)) { + memset(&op.f, 0, sizeof(op.f)); + op.f.input_size = sizeof(op); + op.f.op = NCR_OP_ENCRYPT; + op.algo_head.nla_len = NLA_HDRLEN + sizeof(op.algo); + op.algo_head.nla_type = NCR_ATTR_ALGORITHM; + op.algo = NCR_ALG_AES_ECB; + op.key_head.nla_len = NLA_HDRLEN + sizeof(op.key); + op.key_head.nla_type = NCR_ATTR_KEY; + op.key = key; + op.input_head.nla_len = NLA_HDRLEN + sizeof(op.input); + op.input_head.nla_type = NCR_ATTR_UPDATE_INPUT_DATA; + op.input.data = aes_vectors[i].plaintext; + op.input.data_size = 16; + op.output_head.nla_len = NLA_HDRLEN + sizeof(op.output); + op.output_head.nla_type = NCR_ATTR_UPDATE_OUTPUT_BUFFER; + op.output.buffer = data; + op.output.buffer_size = sizeof(data); + op.output.result_size_ptr = &data_size; + + if (ioctl(cfd, NCRIO_SESSION_ONCE, &op)) { fprintf(stderr, "Error: %s:%d\n", __func__, __LINE__); perror("ioctl(NCRIO_SESSION_ONCE)"); return 1; } - - data_size = nop.op.data.udata.output_size; /* verify */ if (data_size != 16 || memcmp(data, aes_vectors[i].ciphertext, 16) != 0) { @@ -944,24 +961,30 @@ test_ncr_aes(int cfd) } /* decrypt */ - memset(&nop, 0, sizeof(nop)); - nop.init.algorithm = NCR_ALG_AES_ECB; - nop.init.key = key; - nop.init.op = NCR_OP_DECRYPT; - nop.op.data.udata.input = (void*)aes_vectors[i].ciphertext; - nop.op.data.udata.input_size = 16; - nop.op.data.udata.output = data; - nop.op.data.udata.output_size = sizeof(data); - nop.op.type = NCR_DIRECT_DATA; - - if (ioctl(cfd, NCRIO_SESSION_ONCE, &nop)) { + memset(&op.f, 0, sizeof(op.f)); + op.f.input_size = sizeof(op); + op.f.op = NCR_OP_DECRYPT; + op.algo_head.nla_len = NLA_HDRLEN + sizeof(op.algo); + op.algo_head.nla_type = NCR_ATTR_ALGORITHM; + op.algo = NCR_ALG_AES_ECB; + op.key_head.nla_len = NLA_HDRLEN + sizeof(op.key); + op.key_head.nla_type = NCR_ATTR_KEY; + op.key = key; + op.input_head.nla_len = NLA_HDRLEN + sizeof(op.input); + op.input_head.nla_type = NCR_ATTR_UPDATE_INPUT_DATA; + op.input.data = aes_vectors[i].ciphertext; + op.input.data_size = 16; + op.output_head.nla_len = NLA_HDRLEN + sizeof(op.output); + op.output_head.nla_type = NCR_ATTR_UPDATE_OUTPUT_BUFFER; + op.output.buffer = data; + op.output.buffer_size = sizeof(data); + op.output.result_size_ptr = &data_size; + + if (ioctl(cfd, NCRIO_SESSION_ONCE, &op)) { fprintf(stderr, "Error: %s:%d\n", __func__, __LINE__); perror("ioctl(NCRIO_SESSION_ONCE)"); return 1; } - - data_size = nop.op.data.udata.output_size; - if (data_size != 16 || memcmp(data, aes_vectors[i].plaintext, 16) != 0) { fprintf(stderr, "AES test vector %d failed!\n", i); @@ -1084,8 +1107,19 @@ test_ncr_hash(int cfd) uint32_t flags ALIGN_NL; } kimport; uint8_t data[HASH_DATA_SIZE]; - int i, j, data_size; - struct ncr_session_once_op_st nop; + int i, j; + size_t data_size; + struct __attribute__((packed)) { + struct ncr_session_once f; + struct nlattr algo_head ALIGN_NL; + uint32_t algo ALIGN_NL; + struct nlattr key_head ALIGN_NL; + uint32_t key ALIGN_NL; + struct nlattr input_head ALIGN_NL; + struct ncr_session_input_data input ALIGN_NL; + struct nlattr output_head ALIGN_NL; + struct ncr_session_output_buffer output ALIGN_NL; + } op; /* convert it to key */ key = ioctl(cfd, NCRIO_KEY_INIT); @@ -1130,26 +1164,30 @@ test_ncr_hash(int cfd) } } - /* encrypt */ - memset(&nop, 0, sizeof(nop)); - nop.init.algorithm = hash_vectors[i].algorithm; - if (hash_vectors[i].key != NULL) - nop.init.key = key; - nop.init.op = hash_vectors[i].op; - nop.op.data.udata.input = (void*)hash_vectors[i].plaintext; - nop.op.data.udata.input_size = hash_vectors[i].plaintext_size; - nop.op.data.udata.output = data; - nop.op.data.udata.output_size = sizeof(data); - nop.op.type = NCR_DIRECT_DATA; - - if (ioctl(cfd, NCRIO_SESSION_ONCE, &nop)) { + memset(&op.f, 0, sizeof(op.f)); + op.f.input_size = sizeof(op); + op.f.op = hash_vectors[i].op; + op.algo_head.nla_len = NLA_HDRLEN + sizeof(op.algo); + op.algo_head.nla_type = NCR_ATTR_ALGORITHM; + op.algo = hash_vectors[i].algorithm; + op.key_head.nla_len = NLA_HDRLEN + sizeof(op.key); + op.key_head.nla_type = NCR_ATTR_KEY; + op.key = hash_vectors[i].key != NULL ? key : NCR_KEY_INVALID; + op.input_head.nla_len = NLA_HDRLEN + sizeof(op.input); + op.input_head.nla_type = NCR_ATTR_UPDATE_INPUT_DATA; + op.input.data = hash_vectors[i].plaintext; + op.input.data_size = hash_vectors[i].plaintext_size; + op.output_head.nla_len = NLA_HDRLEN + sizeof(op.output); + op.output_head.nla_type = NCR_ATTR_FINAL_OUTPUT_BUFFER; + op.output.buffer = data; + op.output.buffer_size = sizeof(data); + op.output.result_size_ptr = &data_size; + + if (ioctl(cfd, NCRIO_SESSION_ONCE, &op)) { fprintf(stderr, "Error: %s:%d\n", __func__, __LINE__); perror("ioctl(NCRIO_SESSION_ONCE)"); return 1; } - - data_size = nop.op.data.udata.output_size; - if (data_size != hash_vectors[i].output_size || memcmp(data, hash_vectors[i].output, hash_vectors[i].output_size) != 0) { @@ -1178,6 +1216,7 @@ static int test_ncr_hash_key(int cfd) { ncr_key_t key; + ncr_session_t ses; struct __attribute__((packed)) { struct ncr_key_import f; struct nlattr id_head ALIGN_NL; @@ -1190,9 +1229,28 @@ test_ncr_hash_key(int cfd) uint32_t flags ALIGN_NL; } kimport; uint8_t data[HASH_DATA_SIZE]; - int j, data_size; - struct ncr_session_op_st op; - struct ncr_session_st op_init; + int j; + size_t data_size; + struct __attribute__((packed)) { + struct ncr_session_init f; + struct nlattr algo_head ALIGN_NL; + uint32_t algo ALIGN_NL; + } op_init; + struct __attribute__((packed)) { + struct ncr_session_update f; + struct nlattr data_head ALIGN_NL; + struct ncr_session_input_data data ALIGN_NL; + } op_up_data; + struct __attribute__((packed)) { + struct ncr_session_update f; + struct nlattr key_head ALIGN_NL; + uint32_t key; + } op_up_key; + struct __attribute__((packed)) { + struct ncr_session_final f; + struct nlattr output_head ALIGN_NL; + struct ncr_session_output_buffer output ALIGN_NL; + } op_final; const uint8_t *output = (void*)"\xe2\xd7\x2c\x2e\x14\xad\x97\xc8\xd2\xdb\xce\xd8\xb3\x52\x9f\x1c\xb3\x2c\x5c\xec"; /* convert it to key */ @@ -1230,58 +1288,62 @@ test_ncr_hash_key(int cfd) return 1; } - /* encrypt */ - memset(&op_init, 0, sizeof(op_init)); - op_init.algorithm = hash_vectors[0].algorithm; - op_init.op = hash_vectors[0].op; + memset(&op_init.f, 0, sizeof(op_init.f)); + op_init.f.input_size = sizeof(op_init); + op_init.f.op = hash_vectors[0].op; + op_init.algo_head.nla_len = NLA_HDRLEN + sizeof(op_init.algo); + op_init.algo_head.nla_type = NCR_ATTR_ALGORITHM; + op_init.algo = hash_vectors[0].algorithm; - if (ioctl(cfd, NCRIO_SESSION_INIT, &op_init)) { + ses = ioctl(cfd, NCRIO_SESSION_INIT, &op_init); + if (ses < 0) { fprintf(stderr, "Error: %s:%d\n", __func__, __LINE__); perror("ioctl(NCRIO_SESSION_INIT)"); return 1; } - memset(&op, 0, sizeof(op)); - op.ses = op_init.ses; - op.data.udata.input = (void*)hash_vectors[0].plaintext; - op.data.udata.input_size = hash_vectors[0].plaintext_size; - op.data.udata.output = NULL; - op.data.udata.output_size = 0; - op.type = NCR_DIRECT_DATA; + memset(&op_up_data.f, 0, sizeof(op_up_data.f)); + op_up_data.f.input_size = sizeof(op_up_data); + op_up_data.f.ses = ses; + op_up_data.data_head.nla_len = NLA_HDRLEN + sizeof(op_up_data.data); + op_up_data.data_head.nla_type = NCR_ATTR_UPDATE_INPUT_DATA; + op_up_data.data.data = hash_vectors[0].plaintext; + op_up_data.data.data_size = hash_vectors[0].plaintext_size; - if (ioctl(cfd, NCRIO_SESSION_UPDATE, &op)) { + if (ioctl(cfd, NCRIO_SESSION_UPDATE, &op_up_data)) { fprintf(stderr, "Error: %s:%d\n", __func__, __LINE__); perror("ioctl(NCRIO_SESSION_UPDATE)"); return 1; } - memset(&op, 0, sizeof(op)); - op.ses = op_init.ses; - op.data.kdata.input = key; - op.data.kdata.output = NULL; - op.data.kdata.output_size = 0; - op.type = NCR_KEY_DATA; + memset(&op_up_key.f, 0, sizeof(op_up_key.f)); + op_up_key.f.input_size = sizeof(op_up_key); + op_up_key.f.ses = ses; + op_up_key.key_head.nla_len = NLA_HDRLEN + sizeof(op_up_key.key); + op_up_key.key_head.nla_type = NCR_ATTR_UPDATE_INPUT_KEY_AS_DATA; + op_up_key.key = key; - if (ioctl(cfd, NCRIO_SESSION_UPDATE, &op)) { + if (ioctl(cfd, NCRIO_SESSION_UPDATE, &op_up_key)) { fprintf(stderr, "Error: %s:%d\n", __func__, __LINE__); perror("ioctl(NCRIO_SESSION_UPDATE)"); return 1; } - op.data.udata.input = NULL; - op.data.udata.input_size = 0; - op.data.udata.output = data; - op.data.udata.output_size = sizeof(data); - op.type = NCR_DIRECT_DATA; + memset(&op_final.f, 0, sizeof(op_final.f)); + op_final.f.input_size = sizeof(op_final); + op_final.f.ses = ses; + op_final.output_head.nla_len = NLA_HDRLEN + sizeof(op_final.output); + op_final.output_head.nla_type = NCR_ATTR_FINAL_OUTPUT_BUFFER; + op_final.output.buffer = data; + op_final.output.buffer_size = sizeof(data); + op_final.output.result_size_ptr = &data_size; - if (ioctl(cfd, NCRIO_SESSION_FINAL, &op)) { + if (ioctl(cfd, NCRIO_SESSION_FINAL, &op_final)) { fprintf(stderr, "Error: %s:%d\n", __func__, __LINE__); perror("ioctl(NCRIO_SESSION_FINAL)"); return 1; } - data_size = op.data.udata.output_size; - if (data_size != hash_vectors[0].output_size || memcmp(data, output, hash_vectors[0].output_size) != 0) { diff --git a/examples/pk.c b/examples/pk.c index ac95820adaa..8645fd45661 100644 --- a/examples/pk.c +++ b/examples/pk.c @@ -794,10 +794,24 @@ test_ncr_wrap_key3(int cfd) static int rsa_key_encrypt(int cfd, ncr_key_t privkey, ncr_key_t pubkey, int oaep) { - struct ncr_session_once_op_st nop; + struct __attribute__((packed)) { + struct ncr_session_once f; + struct nlattr algo_head ALIGN_NL; + uint32_t algo ALIGN_NL; + struct nlattr key_head ALIGN_NL; + uint32_t key ALIGN_NL; + struct nlattr rsa_head ALIGN_NL; + uint32_t rsa ALIGN_NL; + struct nlattr oaep_hash_head ALIGN_NL; + uint32_t oaep_hash ALIGN_NL; + struct nlattr input_head ALIGN_NL; + struct ncr_session_input_data input ALIGN_NL; + struct nlattr output_head ALIGN_NL; + struct ncr_session_output_buffer output ALIGN_NL; + } op; uint8_t data[DATA_SIZE]; uint8_t vdata[RSA_ENCRYPT_SIZE]; - int enc_size; + size_t enc_size, dec_size; fprintf(stdout, "Tests on RSA (%s) key encryption:", (oaep!=0)?"OAEP":"PKCS V1.5"); fflush(stdout); @@ -806,55 +820,79 @@ static int rsa_key_encrypt(int cfd, ncr_key_t privkey, ncr_key_t pubkey, int oae memcpy(vdata, data, sizeof(vdata)); /* do encryption */ - memset(&nop, 0, sizeof(nop)); - nop.init.algorithm = NCR_ALG_RSA; - nop.init.key = pubkey; + memset(&op.f, 0, sizeof(op.f)); + op.f.input_size = sizeof(op); + op.f.op = NCR_OP_ENCRYPT; + op.algo_head.nla_len = NLA_HDRLEN + sizeof(op.algo); + op.algo_head.nla_type = NCR_ATTR_ALGORITHM; + op.algo = NCR_ALG_RSA; + op.key_head.nla_len = NLA_HDRLEN + sizeof(op.key); + op.key_head.nla_type = NCR_ATTR_KEY; + op.key = pubkey; + op.rsa_head.nla_len = NLA_HDRLEN + sizeof(op.rsa); + op.rsa_head.nla_type = NCR_ATTR_RSA_ENCODING_METHOD; if (oaep) { - nop.init.params.params.rsa.type = RSA_PKCS1_OAEP; - nop.init.params.params.rsa.oaep_hash = NCR_ALG_SHA1; + op.rsa = RSA_PKCS1_OAEP; } else { - nop.init.params.params.rsa.type = RSA_PKCS1_V1_5; + op.rsa = RSA_PKCS1_V1_5; } - nop.init.op = NCR_OP_ENCRYPT; - nop.op.data.udata.input = data; - nop.op.data.udata.input_size = RSA_ENCRYPT_SIZE; - nop.op.data.udata.output = data; - nop.op.data.udata.output_size = sizeof(data); - nop.op.type = NCR_DIRECT_DATA; - - if (ioctl(cfd, NCRIO_SESSION_ONCE, &nop)) { + op.oaep_hash_head.nla_len = NLA_HDRLEN + sizeof(op.oaep_hash); + op.oaep_hash_head.nla_type = NCR_ATTR_RSA_OAEP_HASH_ALGORITHM; + op.oaep_hash = NCR_ALG_SHA1; /* Ignored if not using OAEP */ + op.input_head.nla_len = NLA_HDRLEN + sizeof(op.input); + op.input_head.nla_type = NCR_ATTR_UPDATE_INPUT_DATA; + op.input.data = data; + op.input.data_size = RSA_ENCRYPT_SIZE; + op.output_head.nla_len = NLA_HDRLEN + sizeof(op.output); + op.output_head.nla_type = NCR_ATTR_UPDATE_OUTPUT_BUFFER; + op.output.buffer = data; + op.output.buffer_size = sizeof(data); + op.output.result_size_ptr = &enc_size; + + if (ioctl(cfd, NCRIO_SESSION_ONCE, &op)) { fprintf(stderr, "Error: %s:%d\n", __func__, __LINE__); perror("ioctl(NCRIO_SESSION_ONCE)"); return 1; } - - enc_size = nop.op.data.udata.output_size; /* decrypt data */ - memset(&nop, 0, sizeof(nop)); - nop.init.algorithm = NCR_ALG_RSA; - nop.init.key = privkey; - nop.init.op = NCR_OP_DECRYPT; + memset(&op.f, 0, sizeof(op.f)); + op.f.input_size = sizeof(op); + op.f.op = NCR_OP_DECRYPT; + op.algo_head.nla_len = NLA_HDRLEN + sizeof(op.algo); + op.algo_head.nla_type = NCR_ATTR_ALGORITHM; + op.algo = NCR_ALG_RSA; + op.key_head.nla_len = NLA_HDRLEN + sizeof(op.key); + op.key_head.nla_type = NCR_ATTR_KEY; + op.key = privkey; + op.rsa_head.nla_len = NLA_HDRLEN + sizeof(op.rsa); + op.rsa_head.nla_type = NCR_ATTR_RSA_ENCODING_METHOD; if (oaep) { - nop.init.params.params.rsa.type = RSA_PKCS1_OAEP; - nop.init.params.params.rsa.oaep_hash = NCR_ALG_SHA1; + op.rsa = RSA_PKCS1_OAEP; } else { - nop.init.params.params.rsa.type = RSA_PKCS1_V1_5; + op.rsa = RSA_PKCS1_V1_5; } - nop.op.data.udata.input = data; - nop.op.data.udata.input_size = enc_size; - nop.op.data.udata.output = data; - nop.op.data.udata.output_size = sizeof(data); - nop.op.type = NCR_DIRECT_DATA; - - - if (ioctl(cfd, NCRIO_SESSION_ONCE, &nop)) { + op.oaep_hash_head.nla_len = NLA_HDRLEN + sizeof(op.oaep_hash); + op.oaep_hash_head.nla_type = NCR_ATTR_RSA_OAEP_HASH_ALGORITHM; + op.oaep_hash = NCR_ALG_SHA1; /* Ignored if not using OAEP */ + op.input_head.nla_len = NLA_HDRLEN + sizeof(op.input); + op.input_head.nla_type = NCR_ATTR_UPDATE_INPUT_DATA; + op.input.data = data; + op.input.data_size = enc_size; + op.output_head.nla_len = NLA_HDRLEN + sizeof(op.output); + op.output_head.nla_type = NCR_ATTR_UPDATE_OUTPUT_BUFFER; + op.output.buffer = data; + op.output.buffer_size = sizeof(data); + op.output.result_size_ptr = &dec_size; + + if (ioctl(cfd, NCRIO_SESSION_ONCE, &op)) { fprintf(stderr, "Error: %s:%d\n", __func__, __LINE__); perror("ioctl(NCRIO_SESSION_ONCE)"); return 1; } - if (memcmp(vdata, data, sizeof(vdata)) != 0) { + if (dec_size != sizeof(vdata) + || memcmp(vdata, data, sizeof(vdata)) != 0) { fprintf(stderr, "Error: %s:%d\n", __func__, __LINE__); fprintf(stderr, "Decrypted data do not match!\n"); return 1; @@ -870,61 +908,113 @@ static int rsa_key_encrypt(int cfd, ncr_key_t privkey, ncr_key_t pubkey, int oae static int rsa_key_sign_verify(int cfd, ncr_key_t privkey, ncr_key_t pubkey, int pss) { - struct ncr_session_once_op_st nop; + struct __attribute__((packed)) { + struct ncr_session_once f; + struct nlattr algo_head ALIGN_NL; + uint32_t algo ALIGN_NL; + struct nlattr key_head ALIGN_NL; + uint32_t key ALIGN_NL; + struct nlattr rsa_head ALIGN_NL; + uint32_t rsa ALIGN_NL; + struct nlattr sign_hash_head ALIGN_NL; + uint32_t sign_hash ALIGN_NL; + struct nlattr input_head ALIGN_NL; + struct ncr_session_input_data input ALIGN_NL; + struct nlattr signature_head ALIGN_NL; + struct ncr_session_output_buffer signature ALIGN_NL; + } ksign; + struct __attribute__((packed)) { + struct ncr_session_once f; + struct nlattr algo_head ALIGN_NL; + uint32_t algo ALIGN_NL; + struct nlattr key_head ALIGN_NL; + uint32_t key ALIGN_NL; + struct nlattr rsa_head ALIGN_NL; + uint32_t rsa ALIGN_NL; + struct nlattr sign_hash_head ALIGN_NL; + uint32_t sign_hash ALIGN_NL; + struct nlattr input_head ALIGN_NL; + struct ncr_session_input_data input ALIGN_NL; + struct nlattr signature_head ALIGN_NL; + struct ncr_session_input_data signature ALIGN_NL; + } kverify; uint8_t data[DATA_SIZE]; uint8_t sig[DATA_SIZE]; - int sig_size; + size_t sig_size; + int ret; fprintf(stdout, "Tests on RSA (%s) key signature:", (pss!=0)?"PSS":"PKCS V1.5"); fflush(stdout); memset(data, 0x3, sizeof(data)); - /* sign datad */ - memset(&nop, 0, sizeof(nop)); - nop.init.algorithm = NCR_ALG_RSA; - nop.init.key = privkey; - nop.init.params.params.rsa.type = (pss!=0)?RSA_PKCS1_PSS:RSA_PKCS1_V1_5; - nop.init.params.params.rsa.sign_hash = NCR_ALG_SHA1; - - nop.init.op = NCR_OP_SIGN; - nop.op.data.udata.input = data; - nop.op.data.udata.input_size = DATA_TO_SIGN; - nop.op.data.udata.output = sig; - nop.op.data.udata.output_size = sizeof(sig); - nop.op.type = NCR_DIRECT_DATA; - - if (ioctl(cfd, NCRIO_SESSION_ONCE, &nop)) { + /* sign data */ + memset(&ksign.f, 0, sizeof(ksign.f)); + ksign.f.input_size = sizeof(ksign); + ksign.f.op = NCR_OP_SIGN; + ksign.algo_head.nla_len = NLA_HDRLEN + sizeof(ksign.algo); + ksign.algo_head.nla_type = NCR_ATTR_ALGORITHM; + ksign.algo = NCR_ALG_RSA; + ksign.key_head.nla_len = NLA_HDRLEN + sizeof(ksign.key); + ksign.key_head.nla_type = NCR_ATTR_KEY; + ksign.key = privkey; + ksign.rsa_head.nla_len = NLA_HDRLEN + sizeof(ksign.rsa); + ksign.rsa_head.nla_type = NCR_ATTR_RSA_ENCODING_METHOD; + ksign.rsa = (pss != 0) ? RSA_PKCS1_PSS : RSA_PKCS1_V1_5; + ksign.sign_hash_head.nla_len = NLA_HDRLEN + sizeof(ksign.sign_hash); + ksign.sign_hash_head.nla_type = NCR_ATTR_SIGNATURE_HASH_ALGORITHM; + ksign.sign_hash = NCR_ALG_SHA1; + ksign.input_head.nla_len = NLA_HDRLEN + sizeof(ksign.input); + ksign.input_head.nla_type = NCR_ATTR_UPDATE_INPUT_DATA; + ksign.input.data = data; + ksign.input.data_size = DATA_TO_SIGN; + ksign.signature_head.nla_len = NLA_HDRLEN + sizeof(ksign.signature); + ksign.signature_head.nla_type = NCR_ATTR_FINAL_OUTPUT_BUFFER; + ksign.signature.buffer = sig; + ksign.signature.buffer_size = sizeof(sig); + ksign.signature.result_size_ptr = &sig_size; + + if (ioctl(cfd, NCRIO_SESSION_ONCE, &ksign)) { fprintf(stderr, "Error: %s:%d\n", __func__, __LINE__); perror("ioctl(NCRIO_SESSION_ONCE)"); return 1; } - - sig_size = nop.op.data.udata.output_size; /* verify signature */ - memset(&nop, 0, sizeof(nop)); - nop.init.algorithm = NCR_ALG_RSA; - nop.init.key = pubkey; - nop.init.params.params.rsa.type = (pss!=0)?RSA_PKCS1_PSS:RSA_PKCS1_V1_5; - nop.init.params.params.rsa.sign_hash = NCR_ALG_SHA1; - memset(data, 0x3, sizeof(data)); - nop.init.op = NCR_OP_VERIFY; - nop.op.data.udata.input = data; - nop.op.data.udata.input_size = DATA_TO_SIGN; - nop.op.data.udata.output = sig; - nop.op.data.udata.output_size = sig_size; - nop.op.type = NCR_DIRECT_DATA; - - if (ioctl(cfd, NCRIO_SESSION_ONCE, &nop)) { + memset(&kverify.f, 0, sizeof(kverify.f)); + kverify.f.input_size = sizeof(kverify); + kverify.f.op = NCR_OP_VERIFY; + kverify.algo_head.nla_len = NLA_HDRLEN + sizeof(kverify.algo); + kverify.algo_head.nla_type = NCR_ATTR_ALGORITHM; + kverify.algo = NCR_ALG_RSA; + kverify.key_head.nla_len = NLA_HDRLEN + sizeof(kverify.key); + kverify.key_head.nla_type = NCR_ATTR_KEY; + kverify.key = pubkey; + kverify.rsa_head.nla_len = NLA_HDRLEN + sizeof(kverify.rsa); + kverify.rsa_head.nla_type = NCR_ATTR_RSA_ENCODING_METHOD; + kverify.rsa = (pss != 0) ? RSA_PKCS1_PSS : RSA_PKCS1_V1_5; + kverify.sign_hash_head.nla_len = NLA_HDRLEN + sizeof(kverify.sign_hash); + kverify.sign_hash_head.nla_type = NCR_ATTR_SIGNATURE_HASH_ALGORITHM; + kverify.sign_hash = NCR_ALG_SHA1; + kverify.input_head.nla_len = NLA_HDRLEN + sizeof(kverify.input); + kverify.input_head.nla_type = NCR_ATTR_UPDATE_INPUT_DATA; + kverify.input.data = data; + kverify.input.data_size = DATA_TO_SIGN; + kverify.signature_head.nla_len = NLA_HDRLEN + sizeof(kverify.signature); + kverify.signature_head.nla_type = NCR_ATTR_FINAL_INPUT_DATA; + kverify.signature.data = sig; + kverify.signature.data_size = sig_size; + + ret = ioctl(cfd, NCRIO_SESSION_ONCE, &kverify); + if (ret < 0) { fprintf(stderr, "Error: %s:%d\n", __func__, __LINE__); perror("ioctl(NCRIO_SESSION_ONCE)"); return 1; } - if (nop.op.err == NCR_SUCCESS) + if (ret) fprintf(stdout, " Success\n"); else { fprintf(stdout, " Verification Failed!\n"); @@ -937,57 +1027,101 @@ static int rsa_key_sign_verify(int cfd, ncr_key_t privkey, ncr_key_t pubkey, int static int dsa_key_sign_verify(int cfd, ncr_key_t privkey, ncr_key_t pubkey) { - struct ncr_session_once_op_st nop; + struct __attribute__((packed)) { + struct ncr_session_once f; + struct nlattr algo_head ALIGN_NL; + uint32_t algo ALIGN_NL; + struct nlattr key_head ALIGN_NL; + uint32_t key ALIGN_NL; + struct nlattr sign_hash_head ALIGN_NL; + uint32_t sign_hash ALIGN_NL; + struct nlattr input_head ALIGN_NL; + struct ncr_session_input_data input ALIGN_NL; + struct nlattr signature_head ALIGN_NL; + struct ncr_session_output_buffer signature ALIGN_NL; + } ksign; + struct __attribute__((packed)) { + struct ncr_session_once f; + struct nlattr algo_head ALIGN_NL; + uint32_t algo ALIGN_NL; + struct nlattr key_head ALIGN_NL; + uint32_t key ALIGN_NL; + struct nlattr sign_hash_head ALIGN_NL; + uint32_t sign_hash ALIGN_NL; + struct nlattr input_head ALIGN_NL; + struct ncr_session_input_data input ALIGN_NL; + struct nlattr signature_head ALIGN_NL; + struct ncr_session_input_data signature ALIGN_NL; + } kverify; uint8_t data[DATA_SIZE]; uint8_t sig[DATA_SIZE]; - int sig_size; + size_t sig_size; + int ret; fprintf(stdout, "Tests on DSA key signature:"); fflush(stdout); memset(data, 0x3, sizeof(data)); - /* sign datad */ - memset(&nop, 0, sizeof(nop)); - nop.init.algorithm = NCR_ALG_DSA; - nop.init.key = privkey; - nop.init.params.params.dsa.sign_hash = NCR_ALG_SHA1; - - nop.init.op = NCR_OP_SIGN; - nop.op.data.udata.input = data; - nop.op.data.udata.input_size = DATA_TO_SIGN; - nop.op.data.udata.output = sig; - nop.op.data.udata.output_size = sizeof(sig); - nop.op.type = NCR_DIRECT_DATA; - - if (ioctl(cfd, NCRIO_SESSION_ONCE, &nop)) { + /* sign data */ + memset(&ksign.f, 0, sizeof(ksign.f)); + ksign.f.input_size = sizeof(ksign); + ksign.f.op = NCR_OP_SIGN; + ksign.algo_head.nla_len = NLA_HDRLEN + sizeof(ksign.algo); + ksign.algo_head.nla_type = NCR_ATTR_ALGORITHM; + ksign.algo = NCR_ALG_DSA; + ksign.key_head.nla_len = NLA_HDRLEN + sizeof(ksign.key); + ksign.key_head.nla_type = NCR_ATTR_KEY; + ksign.key = privkey; + ksign.sign_hash_head.nla_len = NLA_HDRLEN + sizeof(ksign.sign_hash); + ksign.sign_hash_head.nla_type = NCR_ATTR_SIGNATURE_HASH_ALGORITHM; + ksign.sign_hash = NCR_ALG_SHA1; + ksign.input_head.nla_len = NLA_HDRLEN + sizeof(ksign.input); + ksign.input_head.nla_type = NCR_ATTR_UPDATE_INPUT_DATA; + ksign.input.data = data; + ksign.input.data_size = DATA_TO_SIGN; + ksign.signature_head.nla_len = NLA_HDRLEN + sizeof(ksign.signature); + ksign.signature_head.nla_type = NCR_ATTR_FINAL_OUTPUT_BUFFER; + ksign.signature.buffer = sig; + ksign.signature.buffer_size = sizeof(sig); + ksign.signature.result_size_ptr = &sig_size; + + if (ioctl(cfd, NCRIO_SESSION_ONCE, &ksign)) { fprintf(stderr, "Error: %s:%d\n", __func__, __LINE__); perror("ioctl(NCRIO_SESSION_ONCE)"); return 1; } - - sig_size = nop.op.data.udata.output_size; /* verify signature */ - memset(&nop, 0, sizeof(nop)); - nop.init.algorithm = NCR_ALG_DSA; - nop.init.key = pubkey; - nop.init.params.params.dsa.sign_hash = NCR_ALG_SHA1; - - nop.init.op = NCR_OP_VERIFY; - nop.op.data.udata.input = data; - nop.op.data.udata.input_size = DATA_TO_SIGN; - nop.op.data.udata.output = sig; - nop.op.data.udata.output_size = sizeof(sig); - nop.op.type = NCR_DIRECT_DATA; - - if (ioctl(cfd, NCRIO_SESSION_ONCE, &nop)) { + memset(&kverify.f, 0, sizeof(kverify.f)); + kverify.f.input_size = sizeof(kverify); + kverify.f.op = NCR_OP_VERIFY; + kverify.algo_head.nla_len = NLA_HDRLEN + sizeof(kverify.algo); + kverify.algo_head.nla_type = NCR_ATTR_ALGORITHM; + kverify.algo = NCR_ALG_DSA; + kverify.key_head.nla_len = NLA_HDRLEN + sizeof(kverify.key); + kverify.key_head.nla_type = NCR_ATTR_KEY; + kverify.key = pubkey; + kverify.sign_hash_head.nla_len = NLA_HDRLEN + sizeof(kverify.sign_hash); + kverify.sign_hash_head.nla_type = NCR_ATTR_SIGNATURE_HASH_ALGORITHM; + kverify.sign_hash = NCR_ALG_SHA1; + kverify.input_head.nla_len = NLA_HDRLEN + sizeof(kverify.input); + kverify.input_head.nla_type = NCR_ATTR_UPDATE_INPUT_DATA; + kverify.input.data = data; + kverify.input.data_size = DATA_TO_SIGN; + kverify.signature_head.nla_len = NLA_HDRLEN + sizeof(kverify.signature); + kverify.signature_head.nla_type = NCR_ATTR_FINAL_INPUT_DATA; + kverify.signature.data = sig; + kverify.signature.data_size = sizeof(sig); + + ret = ioctl(cfd, NCRIO_SESSION_ONCE, &kverify); + if (ret < 0) { fprintf(stderr, "Error: %s:%d\n", __func__, __LINE__); perror("ioctl(NCRIO_SESSION_ONCE)"); return 1; } - if (nop.op.err == NCR_SUCCESS) + if (ret) fprintf(stdout, " Success\n"); else { fprintf(stdout, " Verification Failed!\n"); diff --git a/examples/speed.c b/examples/speed.c index 9c2e8b8d935..a75009e736b 100644 --- a/examples/speed.c +++ b/examples/speed.c @@ -88,7 +88,18 @@ int encrypt_data_ncr_direct(int cfd, int algo, int chunksize) struct nlattr bits_head ALIGN_NL; uint32_t bits ALIGN_NL; } kgen; - struct ncr_session_once_op_st nop; + struct __attribute__((packed)) { + struct ncr_session_once f; + struct nlattr algo_head ALIGN_NL; + uint32_t algo ALIGN_NL; + struct nlattr key_head ALIGN_NL; + uint32_t key ALIGN_NL; + struct nlattr input_head ALIGN_NL; + struct ncr_session_input_data input ALIGN_NL; + struct nlattr output_head ALIGN_NL; + struct ncr_session_output_buffer output ALIGN_NL; + struct nlattr iv_head ALIGN_NL; + } op; key = ioctl(cfd, NCRIO_KEY_INIT); if (key == -1) { @@ -127,17 +138,30 @@ int encrypt_data_ncr_direct(int cfd, int algo, int chunksize) gettimeofday(&start, NULL); do { - memset(&nop, 0, sizeof(nop)); - nop.init.algorithm = algo; - nop.init.key = key; - nop.init.op = NCR_OP_ENCRYPT; - nop.op.data.udata.input = buffer; - nop.op.data.udata.input_size = chunksize; - nop.op.data.udata.output = buffer; - nop.op.data.udata.output_size = chunksize; - nop.op.type = NCR_DIRECT_DATA; - - if (ioctl(cfd, NCRIO_SESSION_ONCE, &nop)) { + size_t output_size; + + memset(&op.f, 0, sizeof(op.f)); + op.f.input_size = sizeof(op); + op.f.op = NCR_OP_ENCRYPT; + op.algo_head.nla_len = NLA_HDRLEN + sizeof(op.algo); + op.algo_head.nla_type = NCR_ATTR_ALGORITHM; + op.algo = algo; + op.key_head.nla_len = NLA_HDRLEN + sizeof(op.key); + op.key_head.nla_type = NCR_ATTR_KEY; + op.key = key; + op.input_head.nla_len = NLA_HDRLEN + sizeof(op.input); + op.input_head.nla_type = NCR_ATTR_UPDATE_INPUT_DATA; + op.input.data = buffer; + op.input.data_size = chunksize; + op.output_head.nla_len = NLA_HDRLEN + sizeof(op.output); + op.output_head.nla_type = NCR_ATTR_UPDATE_OUTPUT_BUFFER; + op.output.buffer = buffer; + op.output.buffer_size = chunksize; + op.output.result_size_ptr = &output_size; + op.iv_head.nla_len = NLA_HDRLEN + 0; + op.iv_head.nla_type = NCR_ATTR_IV; + + if (ioctl(cfd, NCRIO_SESSION_ONCE, &op)) { fprintf(stderr, "Error: %s:%d\n", __func__, __LINE__); perror("ioctl(NCRIO_SESSION_ONCE)"); return 1; diff --git a/ncr-int.h b/ncr-int.h index b8f12503ec6..669c1a2c983 100644 --- a/ncr-int.h +++ b/ncr-int.h @@ -1,6 +1,7 @@ #ifndef NCR_INT_H # define NCR_INT_H +#include #include #include #include "ncr.h" @@ -170,10 +171,18 @@ void _ncr_sessions_item_put( struct session_item_st* item); struct session_item_st* ncr_sessions_item_get(struct ncr_lists *lst, ncr_session_t desc); void ncr_sessions_list_deinit(struct ncr_lists *lst); -int ncr_session_init(struct ncr_lists* lists, void __user* arg); -int ncr_session_update(struct ncr_lists* lists, void __user* arg); -int ncr_session_final(struct ncr_lists* lists, void __user* arg); -int ncr_session_once(struct ncr_lists* lists, void __user* arg); +int ncr_session_init(struct ncr_lists *lists, + const struct ncr_session_init *session, + struct nlattr *tb[]); +int ncr_session_update(struct ncr_lists *lists, + const struct ncr_session_update *op, struct nlattr *tb[], + int compat); +int ncr_session_final(struct ncr_lists *lists, + const struct ncr_session_final *op, struct nlattr *tb[], + int compat); +int ncr_session_once(struct ncr_lists *lists, + const struct ncr_session_once *once, struct nlattr *tb[], + int compat); /* master key */ extern struct key_item_st master_key; @@ -189,7 +198,30 @@ int key_to_storage_data( uint8_t** data, size_t * data_size, const struct key_it const struct algo_properties_st *_ncr_algo_to_properties(ncr_algorithm_t algo); const struct algo_properties_st *_ncr_nla_to_properties(const struct nlattr *nla); -const struct algo_properties_st *ncr_key_params_get_sign_hash(const struct algo_properties_st *algo, struct ncr_key_params_st * params); int _ncr_key_get_sec_level(struct key_item_st* item); +/* CONFIG_COMPAT handling */ + +#ifdef CONFIG_COMPAT +struct compat_ncr_session_input_data { + compat_uptr_t data; + compat_size_t data_size; +}; + +struct compat_ncr_session_output_buffer { + compat_uptr_t buffer; + compat_size_t buffer_size; + compat_uptr_t result_size_ptr; +}; +#endif + +int ncr_session_input_data_from_nla(struct ncr_session_input_data *dest, + const struct nlattr *nla, int compat); + +int ncr_session_output_buffer_from_nla(struct ncr_session_output_buffer *dest, + const struct nlattr *nla, int compat); + +int ncr_session_output_buffer_set_size(const struct ncr_session_output_buffer *dest, + size_t size, int compat); + #endif diff --git a/ncr-pk.c b/ncr-pk.c index c96f494ed90..ed904d60d4a 100644 --- a/ncr-pk.c +++ b/ncr-pk.c @@ -337,25 +337,6 @@ fail: return 0; } -const struct algo_properties_st *ncr_key_params_get_sign_hash( - const struct algo_properties_st *algo, - struct ncr_key_params_st * params) -{ - ncr_algorithm_t id; - - switch(algo->algo) { - case NCR_ALG_RSA: - id = params->params.rsa.sign_hash; - break; - case NCR_ALG_DSA: - id = params->params.dsa.sign_hash; - break; - default: - return ERR_PTR(-EINVAL); - } - return _ncr_algo_to_properties(id); -} - /* Encryption/Decryption */ @@ -368,9 +349,12 @@ void ncr_pk_cipher_deinit(struct ncr_pk_ctx* ctx) } int ncr_pk_cipher_init(const struct algo_properties_st *algo, - struct ncr_pk_ctx* ctx, struct ncr_key_params_st* params, - struct key_item_st *key, const struct algo_properties_st *sign_hash) + struct ncr_pk_ctx* ctx, struct nlattr *tb[], + struct key_item_st *key, + const struct algo_properties_st *sign_hash) { + const struct nlattr *nla; + memset(ctx, 0, sizeof(*ctx)); if (key->algorithm != algo) { @@ -381,26 +365,38 @@ int ncr_pk_cipher_init(const struct algo_properties_st *algo, ctx->algorithm = algo; ctx->key = key; ctx->sign_hash = sign_hash; + ctx->salt_len = 0; switch(algo->algo) { case NCR_ALG_RSA: - if (params->params.rsa.type == RSA_PKCS1_V1_5) + nla = tb[NCR_ATTR_RSA_ENCODING_METHOD]; + if (nla == NULL) { + err(); + return -EINVAL; + } + switch (nla_get_u32(nla)) { + case RSA_PKCS1_V1_5: ctx->type = LTC_LTC_PKCS_1_V1_5; - else if (params->params.rsa.type == RSA_PKCS1_OAEP) { + break; + case RSA_PKCS1_OAEP: ctx->type = LTC_LTC_PKCS_1_OAEP; - ctx->oaep_hash = _ncr_algo_to_properties(params->params.rsa.oaep_hash); + nla = tb[NCR_ATTR_RSA_OAEP_HASH_ALGORITHM]; + ctx->oaep_hash = _ncr_nla_to_properties(nla); if (ctx->oaep_hash == NULL) { err(); return -EINVAL; } - } else if (params->params.rsa.type == RSA_PKCS1_PSS) { + break; + case RSA_PKCS1_PSS: ctx->type = LTC_LTC_PKCS_1_PSS; - } else { + nla = tb[NCR_ATTR_RSA_PSS_SALT_LENGTH]; + if (nla != NULL) + ctx->salt_len = nla_get_u32(nla); + break; + default: err(); return -EINVAL; } - - ctx->salt_len = params->params.rsa.pss_salt; break; case NCR_ALG_DSA: break; @@ -543,30 +539,11 @@ fail: return ret; } -int ncr_pk_cipher_sign(const struct ncr_pk_ctx* ctx, - const struct scatterlist* isg, unsigned int isg_cnt, size_t isg_size, - struct scatterlist *osg, unsigned int osg_cnt, size_t* osg_size) +int ncr_pk_cipher_sign(const struct ncr_pk_ctx *ctx, const void *hash, + size_t hash_size, void *sig, size_t *sig_size) { -int cret, ret; -unsigned long osize = *osg_size; -uint8_t* tmp; -void * input, *output; - - tmp = kmalloc(isg_size + *osg_size, GFP_KERNEL); - if (tmp == NULL) { - err(); - return -ENOMEM; - } - - input = tmp; - output = &tmp[isg_size]; - - ret = sg_copy_to_buffer((struct scatterlist*)isg, isg_cnt, input, isg_size); - if (ret != isg_size) { - err(); - ret = -EINVAL; - goto fail; - } + int cret; + unsigned long osize = *sig_size; switch(ctx->algorithm->algo) { case NCR_ALG_RSA: @@ -574,63 +551,35 @@ void * input, *output; err(); return -EINVAL; } - cret = rsa_sign_hash_ex( input, isg_size, output, &osize, + cret = rsa_sign_hash_ex(hash, hash_size, sig, &osize, ctx->type, ctx->sign_hash, ctx->salt_len, &ctx->key->key.pk.rsa); if (cret != CRYPT_OK) { err(); return _ncr_tomerr(cret); } - *osg_size = osize; + *sig_size = osize; break; case NCR_ALG_DSA: - cret = dsa_sign_hash( input, isg_size, output, &osize, + cret = dsa_sign_hash(hash, hash_size, sig, &osize, &ctx->key->key.pk.dsa); if (cret != CRYPT_OK) { err(); return _ncr_tomerr(cret); } - *osg_size = osize; + *sig_size = osize; break; default: err(); - ret = -EINVAL; - goto fail; - } - - ret = sg_copy_from_buffer(osg, osg_cnt, output, *osg_size); - if (ret != *osg_size) { - err(); - ret = -EINVAL; - goto fail; + return -EINVAL; } - ret = 0; -fail: - kfree(tmp); - - return ret; + return 0; } -int ncr_pk_cipher_verify(const struct ncr_pk_ctx* ctx, - const struct scatterlist* sign_sg, unsigned int sign_sg_cnt, size_t sign_sg_size, - const void* hash, size_t hash_size, ncr_error_t* err) +int ncr_pk_cipher_verify(const struct ncr_pk_ctx* ctx, const void *sig, + size_t sig_size, const void *hash, size_t hash_size) { -int cret, ret; -int stat = 0; -uint8_t* sig; - - sig = kmalloc(sign_sg_size, GFP_KERNEL); - if (sig == NULL) { - err(); - return -ENOMEM; - } - - ret = sg_copy_to_buffer((struct scatterlist*)sign_sg, sign_sg_cnt, sig, sign_sg_size); - if (ret != sign_sg_size) { - err(); - ret = -EINVAL; - goto fail; - } + int cret, ret, stat; switch(ctx->algorithm->algo) { case NCR_ALG_RSA: @@ -638,35 +587,28 @@ uint8_t* sig; err(); return -EINVAL; } - cret = rsa_verify_hash_ex( sig, sign_sg_size, - hash, hash_size, ctx->type, ctx->sign_hash, - ctx->salt_len, &stat, &ctx->key->key.pk.rsa); + cret = rsa_verify_hash_ex(sig, sig_size, hash, + hash_size, ctx->type, + ctx->sign_hash, ctx->salt_len, + &stat, &ctx->key->key.pk.rsa); if (cret != CRYPT_OK) { err(); ret = _ncr_tomerr(cret); goto fail; } - if (stat == 1) - *err = 0; - else - *err = NCR_VERIFICATION_FAILED; - + ret = (stat == 1); break; case NCR_ALG_DSA: - cret = dsa_verify_hash( sig, sign_sg_size, - hash, hash_size, &stat, &ctx->key->key.pk.dsa); + cret = dsa_verify_hash(sig, sig_size, hash, hash_size, + &stat, &ctx->key->key.pk.dsa); if (cret != CRYPT_OK) { err(); ret = _ncr_tomerr(cret); goto fail; } - if (stat == 1) - *err = 0; - else - *err = NCR_VERIFICATION_FAILED; - + ret = (stat == 1); break; default: err(); @@ -674,9 +616,7 @@ uint8_t* sig; goto fail; } - ret = 0; fail: - kfree(sig); return ret; } diff --git a/ncr-pk.h b/ncr-pk.h index ba35e45634d..fb9aba5b5ee 100644 --- a/ncr-pk.h +++ b/ncr-pk.h @@ -28,8 +28,9 @@ int ncr_pk_unpack( struct key_item_st * key, const void * packed, size_t packed_ /* encryption/decryption */ int ncr_pk_cipher_init(const struct algo_properties_st *algo, - struct ncr_pk_ctx* ctx, struct ncr_key_params_st* params, - struct key_item_st *key, const struct algo_properties_st *sign_hash); + struct ncr_pk_ctx* ctx, struct nlattr *tb[], + struct key_item_st *key, + const struct algo_properties_st *sign_hash); void ncr_pk_cipher_deinit(struct ncr_pk_ctx* ctx); int ncr_pk_cipher_encrypt(const struct ncr_pk_ctx* ctx, @@ -40,13 +41,11 @@ int ncr_pk_cipher_decrypt(const struct ncr_pk_ctx* ctx, const struct scatterlist* isg, unsigned int isg_cnt, size_t isg_size, struct scatterlist *osg, unsigned int osg_cnt, size_t* osg_size); -int ncr_pk_cipher_sign(const struct ncr_pk_ctx* ctx, - const struct scatterlist* isg, unsigned int isg_cnt, size_t isg_size, - struct scatterlist *osg, unsigned int osg_cnt, size_t* osg_size); +int ncr_pk_cipher_sign(const struct ncr_pk_ctx *ctx, const void *hash, + size_t hash_size, void *sig, size_t *sig_size); -int ncr_pk_cipher_verify(const struct ncr_pk_ctx* ctx, - const struct scatterlist* sign_sg, unsigned int sign_sg_cnt, size_t sign_sg_size, - const void* hash, size_t hash_size, ncr_error_t* err); +int ncr_pk_cipher_verify(const struct ncr_pk_ctx* ctx, const void *sig, + size_t sig_size, const void *hash, size_t hash_size); int _ncr_tomerr(int err); diff --git a/ncr-sessions.c b/ncr-sessions.c index 320a061d506..8f3e721de8d 100644 --- a/ncr-sessions.c +++ b/ncr-sessions.c @@ -31,7 +31,8 @@ #include #include -static int _ncr_session_update_key(struct ncr_lists* lists, struct ncr_session_op_st* op); +static int _ncr_session_update_key(struct ncr_lists *lists, ncr_session_t ses, + struct nlattr *tb[]); static void _ncr_session_remove(struct ncr_lists *lst, ncr_session_t desc); static int session_list_deinit_fn(int id, void *item, void *unused) @@ -222,8 +223,28 @@ const struct algo_properties_st *_ncr_nla_to_properties(const struct nlattr *nla return _ncr_algo_to_properties(nla_get_u32(nla)); } -static int _ncr_session_init(struct ncr_lists* lists, struct ncr_session_st* session) +static int key_item_get_nla_read(struct key_item_st **st, + struct ncr_lists *lists, + const struct nlattr *nla) { + int ret; + + if (nla == NULL) { + err(); + return -EINVAL; + } + ret = ncr_key_item_get_read(st, lists, nla_get_u32(nla)); + if (ret < 0) { + err(); + return ret; + } + return ret; +} + +static int _ncr_session_init(struct ncr_lists *lists, ncr_crypto_op_t op, + struct nlattr *tb[]) +{ + const struct nlattr *nla; struct session_item_st* ns = NULL; int ret; const struct algo_properties_st *sign_hash; @@ -234,15 +255,15 @@ static int _ncr_session_init(struct ncr_lists* lists, struct ncr_session_st* ses return -ENOMEM; } - ns->op = session->op; - ns->algorithm = _ncr_algo_to_properties(session->algorithm); + ns->op = op; + ns->algorithm = _ncr_nla_to_properties(tb[NCR_ATTR_ALGORITHM]); if (ns->algorithm == NULL) { err(); ret = -EINVAL; goto fail; } - switch(session->op) { + switch(op) { case NCR_OP_ENCRYPT: case NCR_OP_DECRYPT: if (!ns->algorithm->can_encrypt) { @@ -252,7 +273,8 @@ static int _ncr_session_init(struct ncr_lists* lists, struct ncr_session_st* ses } /* read key */ - ret = ncr_key_item_get_read( &ns->key, lists, session->key); + ret = key_item_get_nla_read(&ns->key, lists, + tb[NCR_ATTR_KEY]); if (ret < 0) { err(); goto fail; @@ -269,7 +291,7 @@ static int _ncr_session_init(struct ncr_lists* lists, struct ncr_session_st* ses if (ns->key->type == NCR_KEY_TYPE_SECRET) { int keysize = ns->key->key.secret.size; - if (session->algorithm == NCR_ALG_NULL) + if (ns->algorithm->algo == NCR_ALG_NULL) keysize = 0; if (ns->algorithm->kstr == NULL) { @@ -286,16 +308,19 @@ static int _ncr_session_init(struct ncr_lists* lists, struct ncr_session_st* ses } if (ns->algorithm->needs_iv) { - if (session->params.params.cipher.iv_size > sizeof(session->params.params.cipher.iv)) { + nla = tb[NCR_ATTR_IV]; + if (nla == NULL) { err(); ret = -EINVAL; goto fail; } - cryptodev_cipher_set_iv(&ns->cipher, session->params.params.cipher.iv, session->params.params.cipher.iv_size); + cryptodev_cipher_set_iv(&ns->cipher, + nla_data(nla), + nla_len(nla)); } } else if (ns->key->type == NCR_KEY_TYPE_PRIVATE || ns->key->type == NCR_KEY_TYPE_PUBLIC) { ret = ncr_pk_cipher_init(ns->algorithm, &ns->pk, - &session->params, ns->key, NULL); + tb, ns->key, NULL); if (ret < 0) { err(); goto fail; @@ -330,7 +355,8 @@ static int _ncr_session_init(struct ncr_lists* lists, struct ncr_session_st* ses } else { /* read key */ - ret = ncr_key_item_get_read( &ns->key, lists, session->key); + ret = key_item_get_nla_read(&ns->key, lists, + tb[NCR_ATTR_KEY]); if (ret < 0) { err(); goto fail; @@ -359,10 +385,11 @@ static int _ncr_session_init(struct ncr_lists* lists, struct ncr_session_st* ses } } else if (ns->algorithm->is_pk && (ns->key->type == NCR_KEY_TYPE_PRIVATE || ns->key->type == NCR_KEY_TYPE_PUBLIC)) { - sign_hash = ncr_key_params_get_sign_hash(ns->key->algorithm, &session->params); - if (IS_ERR(sign_hash)) { + nla = tb[NCR_ATTR_SIGNATURE_HASH_ALGORITHM]; + sign_hash = _ncr_nla_to_properties(nla); + if (sign_hash == NULL) { err(); - ret = PTR_ERR(sign_hash); + ret = -EINVAL; goto fail; } @@ -379,7 +406,7 @@ static int _ncr_session_init(struct ncr_lists* lists, struct ncr_session_st* ses } ret = ncr_pk_cipher_init(ns->algorithm, &ns->pk, - &session->params, ns->key, sign_hash); + tb, ns->key, sign_hash); if (ret < 0) { err(); goto fail; @@ -404,8 +431,7 @@ static int _ncr_session_init(struct ncr_lists* lists, struct ncr_session_st* ses goto fail; } - ret = 0; - session->ses = ns->desc; + ret = ns->desc; fail: if (ret < 0) { @@ -416,29 +442,11 @@ fail: return ret; } -int ncr_session_init(struct ncr_lists* lists, void __user* arg) +int ncr_session_init(struct ncr_lists *lists, + const struct ncr_session_init *session, + struct nlattr *tb[]) { - struct ncr_session_st session; - int ret; - - if (unlikely(copy_from_user(&session, arg, sizeof(session)))) { - err(); - return -EFAULT; - } - - ret = _ncr_session_init(lists, &session); - if (unlikely(ret)) { - err(); - return ret; - } - - ret = copy_to_user( arg, &session, sizeof(session)); - if (unlikely(ret)) { - err(); - _ncr_session_remove(lists, session.ses); - return -EFAULT; - } - return ret; + return _ncr_session_init(lists, session->op, tb); } static int _ncr_session_encrypt(struct session_item_st* sess, const struct scatterlist* input, unsigned input_cnt, @@ -542,66 +550,64 @@ static int _ncr_session_grow_pages(struct session_item_st *ses, int pagecount) return 0; } -/* Only the output buffer is given as scatterlist */ -static int get_userbuf1(struct session_item_st* ses, - void __user * udata, size_t udata_size, struct scatterlist **dst_sg, unsigned *dst_cnt) +/* Make NCR_ATTR_UPDATE_INPUT_DATA and NCR_ATTR_UPDATE_OUTPUT_BUFFER available + in scatterlists */ +static int get_userbuf2(struct session_item_st *ses, struct nlattr *tb[], + struct scatterlist **src_sg, unsigned *src_cnt, + size_t *src_size, struct ncr_session_output_buffer *dst, + struct scatterlist **dst_sg, unsigned *dst_cnt, + int compat) { - int pagecount = 0; - - if (unlikely(udata == NULL)) { - err(); - return -EINVAL; - } + const struct nlattr *src_nla, *dst_nla; + struct ncr_session_input_data src; + int src_pagecount, dst_pagecount = 0, pagecount, write_src = 1, ret; + size_t input_size; - pagecount = PAGECOUNT(udata, udata_size); - _ncr_session_grow_pages(ses, pagecount); + src_nla = tb[NCR_ATTR_UPDATE_INPUT_DATA]; + dst_nla = tb[NCR_ATTR_UPDATE_OUTPUT_BUFFER]; - if (__get_userbuf(udata, udata_size, 1, - pagecount, ses->pages, ses->sg)) { + ret = ncr_session_input_data_from_nla(&src, src_nla, compat); + if (unlikely(ret != 0)) { err(); - return -EINVAL; + return ret; } - (*dst_sg) = ses->sg; - *dst_cnt = pagecount; + *src_size = src.data_size; - ses->available_pages = pagecount; - - return 0; -} - -/* make op->data.udata.input and op->data.udata.output available in scatterlists */ -static int get_userbuf2(struct session_item_st* ses, - struct ncr_session_op_st* op, struct scatterlist **src_sg, - unsigned *src_cnt, struct scatterlist **dst_sg, unsigned *dst_cnt) -{ - int src_pagecount, dst_pagecount = 0, pagecount, write_src = 1; - size_t input_size = op->data.udata.input_size; - - if (unlikely(op->data.udata.input == NULL)) { - err(); - return -EINVAL; + if (dst_nla != NULL) { + ret = ncr_session_output_buffer_from_nla(dst, dst_nla, compat); + if (unlikely(ret != 0)) { + err(); + return ret; + } } - src_pagecount = PAGECOUNT(op->data.udata.input, input_size); + input_size = src.data_size; + src_pagecount = PAGECOUNT(src.data, input_size); - if (op->data.udata.input != op->data.udata.output) { /* non-in-situ transformation */ + if (dst_nla == NULL || src.data != dst->buffer) { /* non-in-situ transformation */ write_src = 0; - if (op->data.udata.output != NULL) { - dst_pagecount = PAGECOUNT(op->data.udata.output, op->data.udata.output_size); + if (dst_nla != NULL) { + dst_pagecount = PAGECOUNT(dst->buffer, + dst->buffer_size); } else { dst_pagecount = 0; } } else { - src_pagecount = max((int)(PAGECOUNT(op->data.udata.output, op->data.udata.output_size)), - src_pagecount); - input_size = max(input_size, (size_t)op->data.udata.output_size); + src_pagecount = max((int)(PAGECOUNT(dst->buffer, + dst->buffer_size)), + src_pagecount); + input_size = max(input_size, dst->buffer_size); } pagecount = src_pagecount + dst_pagecount; - _ncr_session_grow_pages(ses, pagecount); + ret = _ncr_session_grow_pages(ses, pagecount); + if (ret != 0) { + err(); + return ret; + } - if (__get_userbuf(op->data.udata.input, input_size, write_src, - src_pagecount, ses->pages, ses->sg)) { + if (__get_userbuf((void __user *)src.data, input_size, write_src, + src_pagecount, ses->pages, ses->sg)) { err(); printk("write: %d\n", write_src); return -EINVAL; @@ -613,14 +619,15 @@ static int get_userbuf2(struct session_item_st* ses, *dst_cnt = dst_pagecount; (*dst_sg) = ses->sg + src_pagecount; - if (__get_userbuf(op->data.udata.output, op->data.udata.output_size, 1, dst_pagecount, - ses->pages + src_pagecount, *dst_sg)) { + if (__get_userbuf(dst->buffer, dst->buffer_size, 1, + dst_pagecount, ses->pages + src_pagecount, + *dst_sg)) { err(); release_user_pages(ses->pages, src_pagecount); return -EINVAL; } } else { - if (op->data.udata.output != NULL) { + if (dst_nla != NULL) { *dst_cnt = src_pagecount; (*dst_sg) = (*src_sg); } else { @@ -635,16 +642,18 @@ static int get_userbuf2(struct session_item_st* ses, } /* Called when userspace buffers are used */ -static int _ncr_session_update(struct ncr_lists* lists, struct ncr_session_op_st* op) +static int _ncr_session_update(struct ncr_lists *lists, ncr_session_t ses, + struct nlattr *tb[], int compat) { int ret; struct session_item_st* sess; - struct scatterlist *isg; - struct scatterlist *osg; + struct scatterlist *isg = NULL; + struct scatterlist *osg = NULL; unsigned osg_cnt=0, isg_cnt=0; - size_t isg_size, osg_size; + size_t isg_size = 0, osg_size; + struct ncr_session_output_buffer out; - sess = ncr_sessions_item_get(lists, op->ses); + sess = ncr_sessions_item_get(lists, ses); if (sess == NULL) { err(); return -EINVAL; @@ -656,13 +665,12 @@ static int _ncr_session_update(struct ncr_lists* lists, struct ncr_session_op_st return -ERESTARTSYS; } - ret = get_userbuf2(sess, op, &isg, &isg_cnt, &osg, &osg_cnt); + ret = get_userbuf2(sess, tb, &isg, &isg_cnt, &isg_size, &out, &osg, + &osg_cnt, compat); if (ret < 0) { err(); goto fail; } - isg_size = op->data.udata.input_size; - osg_size = op->data.udata.output_size; switch(sess->op) { case NCR_OP_ENCRYPT: @@ -672,6 +680,7 @@ static int _ncr_session_update(struct ncr_lists* lists, struct ncr_session_op_st goto fail; } + osg_size = out.buffer_size; if (osg_size < isg_size) { err(); ret = -EINVAL; @@ -684,8 +693,13 @@ static int _ncr_session_update(struct ncr_lists* lists, struct ncr_session_op_st err(); goto fail; } - op->data.udata.output_size = osg_size; - + + ret = ncr_session_output_buffer_set_size(&out, osg_size, + compat); + if (ret != 0) { + err(); + goto fail; + } break; case NCR_OP_DECRYPT: if (osg == NULL) { @@ -694,6 +708,7 @@ static int _ncr_session_update(struct ncr_lists* lists, struct ncr_session_op_st goto fail; } + osg_size = out.buffer_size; if (osg_size < isg_size) { err(); ret = -EINVAL; @@ -706,8 +721,13 @@ static int _ncr_session_update(struct ncr_lists* lists, struct ncr_session_op_st err(); goto fail; } - op->data.udata.output_size = osg_size; + ret = ncr_session_output_buffer_set_size(&out, osg_size, + compat); + if (ret != 0) { + err(); + goto fail; + } break; case NCR_OP_SIGN: @@ -737,40 +757,34 @@ fail: return ret; } -static int try_session_update(struct ncr_lists* lists, struct ncr_session_op_st* op) +static int try_session_update(struct ncr_lists *lists, ncr_session_t ses, + struct nlattr *tb[], int compat) { - if (op->type == NCR_KEY_DATA) { - if (op->data.kdata.input != NCR_KEY_INVALID) - return _ncr_session_update_key(lists, op); - } else if (op->type == NCR_DIRECT_DATA) { - if (op->data.udata.input != NULL) - return _ncr_session_update(lists, op); - } + if (tb[NCR_ATTR_UPDATE_INPUT_KEY_AS_DATA] != NULL) + return _ncr_session_update_key(lists, ses, tb); + else if (tb[NCR_ATTR_UPDATE_INPUT_DATA] != NULL) + return _ncr_session_update(lists, ses, tb, compat); return 0; } -static int _ncr_session_final(struct ncr_lists* lists, struct ncr_session_op_st* op) +static int _ncr_session_final(struct ncr_lists *lists, ncr_session_t ses, + struct nlattr *tb[], int compat) { + const struct nlattr *nla; int ret; struct session_item_st* sess; int digest_size; uint8_t digest[NCR_HASH_MAX_OUTPUT_SIZE]; - uint8_t vdigest[NCR_HASH_MAX_OUTPUT_SIZE]; - struct scatterlist *osg; - unsigned osg_cnt=0; - size_t osg_size = 0; - size_t orig_osg_size; - void __user * udata = NULL; - size_t *udata_size; - - sess = ncr_sessions_item_get(lists, op->ses); + void *buffer = NULL; + + sess = ncr_sessions_item_get(lists, ses); if (sess == NULL) { err(); return -EINVAL; } - ret = try_session_update(lists, op); + ret = try_session_update(lists, ses, tb, compat); if (ret < 0) { err(); _ncr_sessions_item_put(sess); @@ -782,129 +796,138 @@ static int _ncr_session_final(struct ncr_lists* lists, struct ncr_session_op_st* _ncr_sessions_item_put(sess); return -ERESTARTSYS; } - - if (op->type == NCR_DIRECT_DATA) { - udata = op->data.udata.output; - udata_size = &op->data.udata.output_size; - } else if (op->type == NCR_KEY_DATA) { - udata = op->data.kdata.output; - udata_size = &op->data.kdata.output_size; - } else { - err(); - ret = -EINVAL; - goto fail; - } switch(sess->op) { - case NCR_OP_ENCRYPT: - case NCR_OP_DECRYPT: - break; - case NCR_OP_VERIFY: - ret = get_userbuf1(sess, udata, *udata_size, &osg, &osg_cnt); + case NCR_OP_ENCRYPT: + case NCR_OP_DECRYPT: + break; + case NCR_OP_VERIFY: { + struct ncr_session_input_data src; + + nla = tb[NCR_ATTR_FINAL_INPUT_DATA]; + ret = ncr_session_input_data_from_nla(&src, nla, compat); + if (unlikely(ret != 0)) { + err(); + goto fail; + } + + buffer = kmalloc(src.data_size, GFP_KERNEL); + if (buffer == NULL) { + err(); + ret = -ENOMEM; + goto fail; + } + if (unlikely(copy_from_user(buffer, src.data, src.data_size))) { + err(); + ret = -EFAULT; + goto fail; + } + + digest_size = sess->hash.digestsize; + if (digest_size == 0 || sizeof(digest) < digest_size) { + err(); + ret = -EINVAL; + goto fail; + } + ret = cryptodev_hash_final(&sess->hash, digest); + if (ret < 0) { + err(); + goto fail; + } + + if (!sess->algorithm->is_pk) + ret = (digest_size == src.data_size + && memcmp(buffer, digest, digest_size) == 0); + else { + ret = ncr_pk_cipher_verify(&sess->pk, buffer, + src.data_size, digest, + digest_size); if (ret < 0) { err(); goto fail; } - orig_osg_size = osg_size = *udata_size; + } + break; + } - digest_size = sess->hash.digestsize; - if (digest_size == 0 || sizeof(digest) < digest_size) { - err(); - ret = -EINVAL; - goto fail; - } - ret = cryptodev_hash_final(&sess->hash, digest); - if (ret < 0) { + case NCR_OP_SIGN: { + struct ncr_session_output_buffer dst; + size_t output_size; + + nla = tb[NCR_ATTR_FINAL_OUTPUT_BUFFER]; + ret = ncr_session_output_buffer_from_nla(&dst, nla, compat); + if (unlikely(ret != 0)) { + err(); + goto fail; + } + + digest_size = sess->hash.digestsize; + if (digest_size == 0) { + err(); + ret = -EINVAL; + goto fail; + } + + ret = cryptodev_hash_final(&sess->hash, digest); + if (ret < 0) { + err(); + goto fail; + } + + cryptodev_hash_deinit(&sess->hash); + + if (!sess->algorithm->is_pk) { + if (dst.buffer_size < digest_size) { err(); + ret = -ERANGE; goto fail; } - - if (sess->algorithm->is_hmac) { - ret = sg_copy_to_buffer(osg, osg_cnt, vdigest, digest_size); - if (ret != digest_size) { - err(); - ret = -EINVAL; - goto fail; - } - - if (digest_size != osg_size || - memcmp(vdigest, digest, digest_size) != 0) { - - op->err = NCR_VERIFICATION_FAILED; - } else { - op->err = NCR_SUCCESS; - } - } else { - /* PK signature */ - ret = ncr_pk_cipher_verify(&sess->pk, osg, osg_cnt, osg_size, - digest, digest_size, &op->err); - if (ret < 0) { - err(); - goto fail; - } - } - break; - - case NCR_OP_SIGN: - ret = get_userbuf1(sess, udata, *udata_size, &osg, &osg_cnt); - if (ret < 0) { + if (unlikely(copy_to_user(dst.buffer, digest, + digest_size))) { err(); + ret = -EFAULT; goto fail; } - orig_osg_size = osg_size = *udata_size; - - digest_size = sess->hash.digestsize; - if (digest_size == 0 || osg_size < digest_size) { + output_size = digest_size; + } else { + output_size = dst.buffer_size; + buffer = kmalloc(output_size, GFP_KERNEL); + if (buffer == NULL) { err(); - ret = -EINVAL; + ret = -ENOMEM; goto fail; } - - ret = cryptodev_hash_final(&sess->hash, digest); + ret = ncr_pk_cipher_sign(&sess->pk, digest, digest_size, + buffer, &output_size); if (ret < 0) { err(); goto fail; } - - ret = sg_copy_from_buffer(osg, osg_cnt, digest, digest_size); - if (ret != digest_size) { + if (unlikely(copy_to_user(dst.buffer, buffer, + output_size))) { err(); - ret = -EINVAL; + ret = -EFAULT; goto fail; } - osg_size = digest_size; - - cryptodev_hash_deinit(&sess->hash); + } - if (sess->algorithm->is_pk) { - /* PK signature */ - - ret = ncr_pk_cipher_sign(&sess->pk, osg, osg_cnt, osg_size, - osg, osg_cnt, &orig_osg_size); - if (ret < 0) { - err(); - goto fail; - } - osg_size = orig_osg_size; - } - break; - default: + ret = ncr_session_output_buffer_set_size(&dst, output_size, + compat); + if (ret != 0) { err(); - ret = -EINVAL; goto fail; + } + break; + } + default: + err(); + ret = -EINVAL; + goto fail; } - - if (osg_size > 0) - *udata_size = osg_size; - - ret = 0; fail: - if (sess->available_pages) { - release_user_pages(sess->pages, sess->available_pages); - sess->available_pages = 0; - } mutex_unlock(&sess->mem_mutex); + kfree(buffer); cryptodev_hash_deinit(&sess->hash); if (sess->algorithm->is_symmetric) { @@ -914,27 +937,28 @@ fail: } _ncr_sessions_item_put(sess); - _ncr_session_remove(lists, op->ses); + _ncr_session_remove(lists, ses); return ret; } /* Direct with key: Allows to hash a key */ -/* Called when userspace buffers are used */ -static int _ncr_session_update_key(struct ncr_lists* lists, struct ncr_session_op_st* op) +static int _ncr_session_update_key(struct ncr_lists *lists, ncr_session_t ses, + struct nlattr *tb[]) { int ret; struct session_item_st* sess; struct key_item_st* key = NULL; - sess = ncr_sessions_item_get(lists, op->ses); + sess = ncr_sessions_item_get(lists, ses); if (sess == NULL) { err(); return -EINVAL; } /* read key */ - ret = ncr_key_item_get_read( &key, lists, op->data.kdata.input); + ret = key_item_get_nla_read(&key, lists, + tb[NCR_ATTR_UPDATE_INPUT_KEY_AS_DATA]); if (ret < 0) { err(); goto fail; @@ -976,20 +1000,16 @@ fail: return ret; } -int ncr_session_update(struct ncr_lists* lists, void __user* arg) +int ncr_session_update(struct ncr_lists *lists, + const struct ncr_session_update *op, struct nlattr *tb[], + int compat) { - struct ncr_session_op_st op; int ret; - if (unlikely(copy_from_user( &op, arg, sizeof(op)))) { - err(); - return -EFAULT; - } - - if (op.type == NCR_DIRECT_DATA) - ret = _ncr_session_update(lists, &op); - else if (op.type == NCR_KEY_DATA) - ret = _ncr_session_update_key(lists, &op); + if (tb[NCR_ATTR_UPDATE_INPUT_DATA] != NULL) + ret = _ncr_session_update(lists, op->ses, tb, compat); + else if (tb[NCR_ATTR_UPDATE_INPUT_KEY_AS_DATA] != NULL) + ret = _ncr_session_update_key(lists, op->ses, tb); else ret = -EINVAL; @@ -998,61 +1018,33 @@ int ncr_session_update(struct ncr_lists* lists, void __user* arg) return ret; } - if (unlikely(copy_to_user(arg, &op, sizeof(op)))) { - err(); - return -EFAULT; - } - return 0; } -int ncr_session_final(struct ncr_lists* lists, void __user* arg) +int ncr_session_final(struct ncr_lists *lists, + const struct ncr_session_final *op, struct nlattr *tb[], + int compat) { - struct ncr_session_op_st op; - int ret; - - if (unlikely(copy_from_user(&op, arg, sizeof(op)))) { - err(); - return -EFAULT; - } - - ret = _ncr_session_final(lists, &op); - if (unlikely(ret)) { - err(); - return ret; - } - - if (unlikely(copy_to_user(arg, &op, sizeof(op)))) { - err(); - return -EFAULT; - } - return 0; + return _ncr_session_final(lists, op->ses, tb, compat); } -int ncr_session_once(struct ncr_lists* lists, void __user* arg) +int ncr_session_once(struct ncr_lists *lists, + const struct ncr_session_once *once, struct nlattr *tb[], + int compat) { - struct ncr_session_once_op_st kop; int ret; - if (unlikely(copy_from_user(&kop, arg, sizeof(kop)))) { - err(); - return -EFAULT; - } - - ret = _ncr_session_init(lists, &kop.init); + ret = _ncr_session_init(lists, once->op, tb); if (ret < 0) { err(); return ret; } - kop.op.ses = kop.init.ses; - ret = _ncr_session_final(lists, &kop.op); + ret = _ncr_session_final(lists, ret, tb, compat); if (ret < 0) { err(); return ret; } - if (unlikely(copy_to_user(arg, &kop, sizeof(kop)))) - return -EFAULT; - return 0; + return ret; } diff --git a/ncr.c b/ncr.c index 1bee991234c..54047cbeb07 100644 --- a/ncr.c +++ b/ncr.c @@ -32,6 +32,7 @@ #include #include #include +#include #include "ncr.h" #include "ncr-int.h" #include "utils.h" @@ -129,7 +130,7 @@ ncr_ioctl(struct ncr_lists *lst, unsigned int cmd, unsigned long arg_) BUG(); switch (cmd) { -#define CASE_NO_OUTPUT(LABEL, STRUCT, FUNCTION) \ +#define CASE_(LABEL, STRUCT, FUNCTION, ARGS) \ case (LABEL): { \ struct STRUCT data; \ \ @@ -138,9 +139,13 @@ ncr_ioctl(struct ncr_lists *lst, unsigned int cmd, unsigned long arg_) err(); \ return PTR_ERR(attr_buf); \ } \ - ret = (FUNCTION)(lst, &data, tb); \ + ret = (FUNCTION)ARGS; \ break; \ } +#define CASE_NO_OUTPUT(LABEL, STRUCT, FUNCTION) \ + CASE_(LABEL, STRUCT, FUNCTION, (lst, &data, tb)) +#define CASE_NO_OUTPUT_COMPAT(LABEL, STRUCT, FUNCTION) \ + CASE_(LABEL, STRUCT, FUNCTION, (lst, &data, tb, 0)) case NCRIO_KEY_INIT: return ncr_key_init(lst); @@ -184,20 +189,21 @@ ncr_ioctl(struct ncr_lists *lst, unsigned int cmd, unsigned long arg_) ncr_key_storage_wrap); CASE_NO_OUTPUT(NCRIO_KEY_STORAGE_UNWRAP, ncr_key_storage_unwrap, ncr_key_storage_unwrap); - case NCRIO_SESSION_INIT: - return ncr_session_init(lst, arg); - case NCRIO_SESSION_UPDATE: - return ncr_session_update(lst, arg); - case NCRIO_SESSION_FINAL: - return ncr_session_final(lst, arg); - case NCRIO_SESSION_ONCE: - return ncr_session_once(lst, arg); + CASE_NO_OUTPUT(NCRIO_SESSION_INIT, ncr_session_init, ncr_session_init); + CASE_NO_OUTPUT_COMPAT(NCRIO_SESSION_UPDATE, ncr_session_update, + ncr_session_update); + CASE_NO_OUTPUT_COMPAT(NCRIO_SESSION_FINAL, ncr_session_final, + ncr_session_final); + CASE_NO_OUTPUT_COMPAT(NCRIO_SESSION_ONCE, ncr_session_once, + ncr_session_once); case NCRIO_MASTER_KEY_SET: return ncr_master_key_set(arg); default: return -EINVAL; +#undef CASE_ #undef CASE_NO_OUTPUT +#undef CASE_NO_OUTPUT_COMPAT } kfree(attr_buf); return ret; @@ -330,6 +336,7 @@ ncr_compat_ioctl(struct ncr_lists *lst, unsigned int cmd, unsigned long arg_) case NCRIO_KEY_DERIVE: case NCRIO_KEY_GET_INFO: case NCRIO_KEY_DEINIT: + case NCRIO_SESSION_INIT: return ncr_ioctl(lst, cmd, arg_); #define CASE_NO_OUTPUT(LABEL, STRUCT, FUNCTION) \ @@ -347,6 +354,19 @@ ncr_compat_ioctl(struct ncr_lists *lst, unsigned int cmd, unsigned long arg_) break; \ } +#define CASE_COMPAT_ONLY(LABEL, STRUCT, FUNCTION) \ + case (LABEL): { \ + struct STRUCT data; \ + \ + attr_buf = NCR_GET_INPUT_ARGS_NO_OUTPUT(&data, tb, arg); \ + if (IS_ERR(attr_buf)) { \ + err(); \ + return PTR_ERR(attr_buf); \ + } \ + ret = (FUNCTION)(lst, &data, tb, 1); \ + break; \ + } + CASE_NO_OUTPUT(COMPAT_NCRIO_KEY_EXPORT, ncr_key_export, ncr_key_export); CASE_NO_OUTPUT(COMPAT_NCRIO_KEY_IMPORT, ncr_key_import, ncr_key_import); CASE_NO_OUTPUT(COMPAT_NCRIO_KEY_WRAP, ncr_key_wrap, ncr_key_wrap); @@ -355,11 +375,88 @@ ncr_compat_ioctl(struct ncr_lists *lst, unsigned int cmd, unsigned long arg_) ncr_key_storage_wrap); CASE_NO_OUTPUT(COMPAT_NCRIO_KEY_STORAGE_UNWRAP, ncr_key_storage_unwrap, ncr_key_storage_unwrap); + CASE_COMPAT_ONLY(NCRIO_SESSION_UPDATE, ncr_session_update, + ncr_session_update); + CASE_COMPAT_ONLY(NCRIO_SESSION_FINAL, ncr_session_final, + ncr_session_final); + CASE_COMPAT_ONLY(NCRIO_SESSION_ONCE, ncr_session_once, + ncr_session_once); default: return -EINVAL; #undef CASE_NO_OUTPUT +#undef CASE_COMPAT_ONLY } kfree(attr_buf); return ret; } #endif + +int ncr_session_input_data_from_nla(struct ncr_session_input_data *dest, + const struct nlattr *nla, int compat) +{ + if (unlikely(nla == NULL)) + return -EINVAL; +#ifdef CONFIG_COMPAT + if (!compat) { +#endif + if (unlikely(nla_len(nla) < sizeof(dest))) + return -ERANGE; /* nla_validate would return -ERANGE. */ + memcpy(dest, nla_data(nla), sizeof(*dest)); +#ifdef CONFIG_COMPAT + } else { + struct compat_ncr_session_input_data old; + + if (unlikely(nla_len(nla) < sizeof(old))) + return -ERANGE; + memcpy(&old, nla_data(nla), sizeof(old)); + dest->data = compat_ptr(old.data); + dest->data_size = old.data_size; + } +#endif + return 0; +} + +int ncr_session_output_buffer_from_nla(struct ncr_session_output_buffer *dest, + const struct nlattr *nla, int compat) +{ + if (unlikely(nla == NULL)) + return -EINVAL; +#ifdef CONFIG_COMPAT + if (!compat) { +#endif + if (unlikely(nla_len(nla) < sizeof(dest))) + return -ERANGE; /* nla_validate would return -ERANGE. */ + memcpy(dest, nla_data(nla), sizeof(*dest)); +#ifdef CONFIG_COMPAT + } else { + struct compat_ncr_session_output_buffer old; + + if (unlikely(nla_len(nla) < sizeof(old))) + return -ERANGE; + memcpy(&old, nla_data(nla), sizeof(old)); + dest->buffer = compat_ptr(old.buffer); + dest->buffer_size = old.buffer_size; + dest->result_size_ptr = compat_ptr(old.result_size_ptr); + } +#endif + return 0; +} + + +int ncr_session_output_buffer_set_size(const struct ncr_session_output_buffer *dest, + size_t size, int compat) +{ +#ifdef CONFIG_COMPAT + if (!compat) +#endif + return put_user(size, dest->result_size_ptr); +#ifdef CONFIG_COMPAT + else { + compat_size_t old; + + old = size; + return put_user(old, + (compat_size_t __user *)dest->result_size_ptr); + } +#endif +} diff --git a/ncr.h b/ncr.h index 46cf8cbdf99..f1db01f240b 100644 --- a/ncr.h +++ b/ncr.h @@ -33,7 +33,16 @@ enum { /* FIXME: Use NLA_STRING for this, later */ NCR_ATTR_ALGORITHM, /* NLA_U32 - ncr_algorithm_t */ NCR_ATTR_DERIVATION_ALGORITHM, /* NLA_U32 - ncr_algorithm_t */ + NCR_ATTR_SIGNATURE_HASH_ALGORITHM, /* NLA_U32 - ncr_algorithm_t */ NCR_ATTR_WRAPPING_ALGORITHM, /* NLA_U32 - ncr_wrap_algorithm_t */ + NCR_ATTR_UPDATE_INPUT_DATA, /* NLA_BINARY - ncr_session_input_data */ + /* NLA_BINARY - ncr_session_output_buffer */ + NCR_ATTR_UPDATE_OUTPUT_BUFFER, + NCR_ATTR_UPDATE_INPUT_KEY_AS_DATA, /* NLA_U32 - ncr_key_t */ + NCR_ATTR_FINAL_INPUT_DATA, /* NLA_BINARY - ncr_session_input_data */ + /* NLA_BINARY - ncr_session_output_buffer */ + NCR_ATTR_FINAL_OUTPUT_BUFFER, + NCR_ATTR_KEY, /* NLA_U32 - ncr_key_t */ NCR_ATTR_KEY_FLAGS, /* NLA_U32 - NCR_KEY_FLAG_* */ NCR_ATTR_KEY_ID, /* NLA_BINARY */ NCR_ATTR_KEY_TYPE, /* NLA_U32 - ncr_key_type_t */ @@ -41,6 +50,9 @@ enum { NCR_ATTR_SECRET_KEY_BITS, /* NLA_U32 */ NCR_ATTR_RSA_MODULUS_BITS, /* NLA_U32 */ NCR_ATTR_RSA_E, /* NLA_BINARY */ + NCR_ATTR_RSA_ENCODING_METHOD, /* NLA_U32 - ncr_rsa_type_t */ + NCR_ATTR_RSA_OAEP_HASH_ALGORITHM, /* NLA_U32 - ncr_algorithm_t */ + NCR_ATTR_RSA_PSS_SALT_LENGTH, /* NLA_U32 */ NCR_ATTR_DSA_P_BITS, /* NLA_U32 */ NCR_ATTR_DSA_Q_BITS, /* NLA_U32 */ NCR_ATTR_DH_PRIME, /* NLA_BINARY */ @@ -142,29 +154,6 @@ typedef enum { RSA_PKCS1_PSS, /* for signatures only */ } ncr_rsa_type_t; -/* used in encryption - */ -struct ncr_key_params_st { - /* this structure always corresponds to a key. Hence the - * parameters of the union selected are based on the corresponding - * key */ - union { - struct { - __u8 iv[NCR_CIPHER_MAX_BLOCK_LEN]; - __kernel_size_t iv_size; - } cipher; - struct { - ncr_rsa_type_t type; - ncr_algorithm_t oaep_hash; /* for OAEP */ - ncr_algorithm_t sign_hash; /* for signatures */ - unsigned int pss_salt; /* PSS signatures */ - } rsa; - struct { - ncr_algorithm_t sign_hash; /* for signatures */ - } dsa; - } params; -}; - typedef enum { NCR_DERIVE_DH=1, } ncr_derive_t; @@ -283,65 +272,46 @@ typedef enum { typedef __s32 ncr_session_t; #define NCR_SESSION_INVALID ((ncr_session_t)-1) -/* input of CIOCGSESSION */ -struct ncr_session_st { - /* input */ - ncr_algorithm_t algorithm; - - ncr_key_t key; - struct ncr_key_params_st params; - ncr_crypto_op_t op; - - /* output */ - ncr_session_t ses; /* session identifier */ +struct ncr_session_input_data { + const void __user *data; + __kernel_size_t data_size; }; -typedef enum { - NCR_SUCCESS = 0, - NCR_ERROR_GENERIC = -1, - NCR_VERIFICATION_FAILED = -2, -} ncr_error_t; +struct ncr_session_output_buffer { + void __user *buffer; + __kernel_size_t buffer_size; + __kernel_size_t __user *result_size_ptr; +}; -typedef enum { - NCR_KEY_DATA, - NCR_DIRECT_DATA, -} ncr_data_type_t; +struct ncr_session_init { + __u32 input_size, output_size; + __u32 op; /* ncr_crypto_op_t */ + __NL_ATTRIBUTES; +}; -struct ncr_session_op_st { - /* input */ +struct ncr_session_update { + __u32 input_size, output_size; ncr_session_t ses; + __NL_ATTRIBUTES; +}; - union { - struct { - ncr_key_t input; - void __user * output; /* when verifying signature this is - * the place of the signature. - */ - __kernel_size_t output_size; - } kdata; /* NCR_KEY_DATA */ - struct { - void __user * input; - __kernel_size_t input_size; - void __user * output; - __kernel_size_t output_size; - } udata; /* NCR_DIRECT_DATA */ - } data; - ncr_data_type_t type; - - /* output of verification */ - ncr_error_t err; +struct ncr_session_final { + __u32 input_size, output_size; + ncr_session_t ses; + __NL_ATTRIBUTES; }; -struct ncr_session_once_op_st { - struct ncr_session_st init; - struct ncr_session_op_st op; +struct ncr_session_once { + __u32 input_size, output_size; + ncr_crypto_op_t op; + __NL_ATTRIBUTES; }; -#define NCRIO_SESSION_INIT _IOR ('c', 300, struct ncr_session_st) -#define NCRIO_SESSION_UPDATE _IOWR ('c', 301, struct ncr_session_op_st) -#define NCRIO_SESSION_FINAL _IOWR ('c', 302, struct ncr_session_op_st) +#define NCRIO_SESSION_INIT _IOWR('c', 300, struct ncr_session_init) +#define NCRIO_SESSION_UPDATE _IOWR('c', 301, struct ncr_session_update) +#define NCRIO_SESSION_FINAL _IOWR('c', 302, struct ncr_session_final) /* everything in one call */ -#define NCRIO_SESSION_ONCE _IOWR ('c', 303, struct ncr_session_once_op_st) +#define NCRIO_SESSION_ONCE _IOWR('c', 303, struct ncr_session_once) #endif diff --git a/utils.c b/utils.c index 1ae66fc1320..8118a1d9e57 100644 --- a/utils.c +++ b/utils.c @@ -28,10 +28,44 @@ #include "ncr-int.h" #include "utils.h" +#ifdef CONFIG_COMPAT +/* max() is too clever for compile-time constants */ +#define CONST_MAX(A, B) ((A) > (B) ? (A) : (B)) + +#define MAX_SESSION_INPUT_DATA_SIZE \ + (CONST_MAX(sizeof(struct ncr_session_input_data), \ + sizeof(struct compat_ncr_session_input_data))) +#define MAX_SESSION_OUTPUT_BUFFER_SIZE \ + (CONST_MAX(sizeof(struct ncr_session_output_buffer), \ + sizeof(struct compat_ncr_session_output_buffer))) + +#else /* !CONFIG_COMPAT */ + +#define MAX_SESSION_INPUT_DATA_SIZE (sizeof(struct ncr_session_input_data)) +#define MAX_SESSION_OUTPUT_BUFFER_SIZE \ + (sizeof(struct ncr_session_output_buffer)) + +#endif /* !CONFIG_COMPAT */ + static const struct nla_policy ncr_attr_policy[NCR_ATTR_MAX + 1] = { [NCR_ATTR_ALGORITHM] = { NLA_U32, 0 }, [NCR_ATTR_DERIVATION_ALGORITHM] = { NLA_U32, 0 }, + [NCR_ATTR_SIGNATURE_HASH_ALGORITHM] = { NLA_U32, 0 }, [NCR_ATTR_WRAPPING_ALGORITHM] = { NLA_U32, 0 }, + [NCR_ATTR_UPDATE_INPUT_DATA] = { + NLA_BINARY, MAX_SESSION_INPUT_DATA_SIZE + }, + [NCR_ATTR_UPDATE_OUTPUT_BUFFER] = { + NLA_BINARY, MAX_SESSION_OUTPUT_BUFFER_SIZE + }, + [NCR_ATTR_UPDATE_INPUT_KEY_AS_DATA] = { NLA_U32, 0 }, + [NCR_ATTR_FINAL_INPUT_DATA] = { + NLA_BINARY, MAX_SESSION_INPUT_DATA_SIZE + }, + [NCR_ATTR_FINAL_OUTPUT_BUFFER] = { + NLA_BINARY, MAX_SESSION_OUTPUT_BUFFER_SIZE + }, + [NCR_ATTR_KEY] = { NLA_U32, 0 }, [NCR_ATTR_KEY_FLAGS] = { NLA_U32, 0 }, [NCR_ATTR_KEY_ID] = { NLA_BINARY, 0 }, [NCR_ATTR_KEY_TYPE] = { NLA_U32, 0 }, @@ -39,6 +73,9 @@ static const struct nla_policy ncr_attr_policy[NCR_ATTR_MAX + 1] = { [NCR_ATTR_SECRET_KEY_BITS] = { NLA_U32, 0 }, [NCR_ATTR_RSA_MODULUS_BITS] = { NLA_U32, 0 }, [NCR_ATTR_RSA_E] = { NLA_BINARY, 0 }, + [NCR_ATTR_RSA_ENCODING_METHOD] = { NLA_U32, 0 }, + [NCR_ATTR_RSA_OAEP_HASH_ALGORITHM] = { NLA_U32, 0 }, + [NCR_ATTR_RSA_PSS_SALT_LENGTH] = { NLA_U32, 0 }, [NCR_ATTR_DSA_P_BITS] = { NLA_U32, 0 }, [NCR_ATTR_DSA_Q_BITS] = { NLA_U32, 0 }, [NCR_ATTR_DH_PRIME] = { NLA_BINARY, 0 }, -- cgit From b4024f760733f5a246406ad7a97b8e2da6065bfb Mon Sep 17 00:00:00 2001 From: Miloslav Trmač Date: Mon, 16 Aug 2010 16:43:35 +0200 Subject: Convert *_MASTER_KEY_SET --- ncr.c | 53 ++++++++++++++++++++++++++++++++++------------------- ncr.h | 10 ++++++---- userspace/setkey.c | 2 +- 3 files changed, 41 insertions(+), 24 deletions(-) diff --git a/ncr.c b/ncr.c index 54047cbeb07..8d7c008ad9b 100644 --- a/ncr.c +++ b/ncr.c @@ -77,26 +77,20 @@ void ncr_master_key_reset(void) memset(&master_key, 0, sizeof(master_key)); } -static int ncr_master_key_set(void __user *arg) +static int ncr_master_key_set(const struct ncr_master_key_set *st, + struct nlattr *tb[]) { -struct ncr_master_key_st st; - if (current_euid() != 0 && !capable(CAP_SYS_ADMIN)) { err(); return -EPERM; } - if (unlikely(copy_from_user(&st, arg, sizeof(st)))) { - err(); - return -EFAULT; - } - - if (st.key_size > sizeof(master_key.key.secret.data)) { + if (st->key_size > sizeof(master_key.key.secret.data)) { err(); return -EINVAL; } - if (st.key_size != 16 && st.key_size != 24 && st.key_size != 32) { + if (st->key_size != 16 && st->key_size != 24 && st->key_size != 32) { dprintk(0, KERN_DEBUG, "Master key size must be 16,24 or 32.\n"); return -EINVAL; } @@ -105,7 +99,8 @@ struct ncr_master_key_st st; dprintk(0, KERN_DEBUG, "Master key was previously initialized.\n"); } - if (unlikely(copy_from_user(master_key.key.secret.data, st.key, st.key_size))) { + if (unlikely(copy_from_user(master_key.key.secret.data, st->key, + st->key_size))) { err(); return -EFAULT; } @@ -113,7 +108,7 @@ struct ncr_master_key_st st; dprintk(0, KERN_INFO, "Initializing master key.\n"); master_key.type = NCR_KEY_TYPE_SECRET; - master_key.key.secret.size = st.key_size; + master_key.key.secret.size = st->key_size; return 0; } @@ -196,11 +191,10 @@ ncr_ioctl(struct ncr_lists *lst, unsigned int cmd, unsigned long arg_) ncr_session_final); CASE_NO_OUTPUT_COMPAT(NCRIO_SESSION_ONCE, ncr_session_once, ncr_session_once); - - case NCRIO_MASTER_KEY_SET: - return ncr_master_key_set(arg); - default: - return -EINVAL; + CASE_(NCRIO_MASTER_KEY_SET, ncr_master_key_set, ncr_master_key_set, + (&data, tb)); + default: + return -EINVAL; #undef CASE_ #undef CASE_NO_OUTPUT #undef CASE_NO_OUTPUT_COMPAT @@ -318,6 +312,22 @@ static void convert_ncr_key_storage_unwrap(struct ncr_key_storage_unwrap *new, new->data_size = old->data_size; } +struct compat_ncr_master_key_set { + __u32 input_size, output_size; + compat_uptr_t key; + __u32 key_size; + __NL_ATTRIBUTES; +}; +#define COMPAT_NCRIO_MASTER_KEY_SET \ + _IOWR('c', 260, struct compat_ncr_master_key_set) + +static void convert_ncr_master_key_set(struct ncr_master_key_set *new, + const struct compat_ncr_master_key_set *old) +{ + new->key = compat_ptr(old->key); + new->key_size = old->key_size; +} + long ncr_compat_ioctl(struct ncr_lists *lst, unsigned int cmd, unsigned long arg_) { @@ -339,7 +349,7 @@ ncr_compat_ioctl(struct ncr_lists *lst, unsigned int cmd, unsigned long arg_) case NCRIO_SESSION_INIT: return ncr_ioctl(lst, cmd, arg_); -#define CASE_NO_OUTPUT(LABEL, STRUCT, FUNCTION) \ +#define CASE_(LABEL, STRUCT, FUNCTION, ARGS) \ case (LABEL): { \ struct compat_##STRUCT old; \ struct STRUCT new; \ @@ -350,9 +360,11 @@ ncr_compat_ioctl(struct ncr_lists *lst, unsigned int cmd, unsigned long arg_) return PTR_ERR(attr_buf); \ } \ convert_##STRUCT(&new, &old); \ - ret = (FUNCTION)(lst, &new, tb); \ + ret = (FUNCTION)ARGS; \ break; \ } +#define CASE_NO_OUTPUT(LABEL, STRUCT, FUNCTION) \ + CASE_(LABEL, STRUCT, FUNCTION, (lst, &new, tb)) #define CASE_COMPAT_ONLY(LABEL, STRUCT, FUNCTION) \ case (LABEL): { \ @@ -381,8 +393,11 @@ ncr_compat_ioctl(struct ncr_lists *lst, unsigned int cmd, unsigned long arg_) ncr_session_final); CASE_COMPAT_ONLY(NCRIO_SESSION_ONCE, ncr_session_once, ncr_session_once); + CASE_(COMPAT_NCRIO_MASTER_KEY_SET, ncr_master_key_set, + ncr_master_key_set, (&new, tb)); default: return -EINVAL; +#undef CASE_ #undef CASE_NO_OUTPUT #undef CASE_COMPAT_ONLY } diff --git a/ncr.h b/ncr.h index f1db01f240b..bc681acf43d 100644 --- a/ncr.h +++ b/ncr.h @@ -231,12 +231,14 @@ struct ncr_key_unwrap { #define NCRIO_KEY_UNWRAP _IOWR('c', 251, struct ncr_key_unwrap) /* Internal ops */ -struct ncr_master_key_st { - __u8 __user * key; - __u16 key_size; +struct ncr_master_key_set { + __u32 input_size, output_size; + const void __user *key; + __u32 key_size; + __NL_ATTRIBUTES; }; -#define NCRIO_MASTER_KEY_SET _IOR ('c', 260, struct ncr_master_key_st) +#define NCRIO_MASTER_KEY_SET _IOWR('c', 260, struct ncr_master_key_set) /* These are similar to key_wrap and unwrap except that will store some extra * fields to be able to recover a key */ diff --git a/userspace/setkey.c b/userspace/setkey.c index b090bd50306..10e22b9cab6 100644 --- a/userspace/setkey.c +++ b/userspace/setkey.c @@ -23,7 +23,7 @@ int main(int argc, char** argv) { int fd = -1; FILE* fp; - struct ncr_master_key_st key; + struct ncr_master_key_set key; int size, ret; struct stat st; uint8_t rawkey[32]; -- cgit From fd2e58ac4f74dcaab4a91c5280408bd6049df5c2 Mon Sep 17 00:00:00 2001 From: Miloslav Trmač Date: Wed, 18 Aug 2010 00:54:53 +0200 Subject: Update TODO: ioctl_compat is done --- TODO | 1 - 1 file changed, 1 deletion(-) diff --git a/TODO b/TODO index 89cfa328bee..876b1f2d6f2 100644 --- a/TODO +++ b/TODO @@ -1,4 +1,3 @@ -* ioctl_compat() mode for ncr.h API as it is in cryptodev.h * Put limits to sessions * Export private keys to PKCS #8 format (can it be implemented?) * Documentation for functions -- cgit From 650b6caa69d41753d6ad61f20dc6d46bc24b96ea Mon Sep 17 00:00:00 2001 From: Miloslav Trmač Date: Wed, 18 Aug 2010 05:30:26 +0200 Subject: Add version ID to key storage wrapping format --- ncr-key-storage.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/ncr-key-storage.c b/ncr-key-storage.c index f00bce8d9e7..149c45a3197 100644 --- a/ncr-key-storage.c +++ b/ncr-key-storage.c @@ -32,6 +32,7 @@ #include "cryptodev_int.h" struct packed_key { + uint32_t version; uint8_t type; uint32_t flags; uint16_t algorithm; /* valid for public/private keys */ @@ -42,6 +43,8 @@ struct packed_key { uint32_t raw_size; } __attribute__((__packed__)); +#define THIS_VERSION 1 + int key_to_storage_data( uint8_t** sdata, size_t * sdata_size, const struct key_item_st *key) { struct packed_key * pkey; @@ -53,6 +56,7 @@ int key_to_storage_data( uint8_t** sdata, size_t * sdata_size, const struct key_ return -ENOMEM; } + pkey->version = THIS_VERSION; pkey->type = key->type; pkey->flags = key->flags; pkey->algorithm = key->algorithm->algo; @@ -90,7 +94,8 @@ int key_from_storage_data(struct key_item_st* key, const void* data, size_t data const struct packed_key * pkey = data; int ret; - if (data_size != sizeof(*pkey) || pkey->key_id_size > MAX_KEY_ID_SIZE) { + if (data_size != sizeof(*pkey) || pkey->version != THIS_VERSION + || pkey->key_id_size > MAX_KEY_ID_SIZE) { err(); return -EINVAL; } -- cgit From eef7de54be0cd38abb689de7b0a749154b04c694 Mon Sep 17 00:00:00 2001 From: Miloslav Trmač Date: Wed, 18 Aug 2010 05:31:14 +0200 Subject: Replace ncr_algorithm_t by NLA_NUL_STRING --- examples/ncr.c | 145 +++++++++++++++++++++++++++++------------------------- examples/pk.c | 77 ++++++++++++++++------------- examples/speed.c | 25 +++++----- ncr-int.h | 24 ++++++++- ncr-key-storage.c | 6 ++- ncr-key.c | 4 +- ncr-pk.c | 3 +- ncr-sessions.c | 96 +++++++++++++++++++++--------------- ncr.h | 40 ++------------- utils.c | 6 +-- 10 files changed, 227 insertions(+), 199 deletions(-) diff --git a/examples/ncr.c b/examples/ncr.c index facecd88ec0..a9b0cea70d2 100644 --- a/examples/ncr.c +++ b/examples/ncr.c @@ -22,6 +22,9 @@ #define ALIGN_NL __attribute__((aligned(NLA_ALIGNTO))) +#define ALG_AES_CBC "cbc(aes)" +#define ALG_AES_ECB "ecb(aes)" + static void randomize_data(uint8_t * data, size_t data_size) { int i; @@ -40,7 +43,7 @@ test_ncr_key(int cfd) struct __attribute__((packed)) { struct ncr_key_generate f; struct nlattr algo_head ALIGN_NL; - uint32_t algo ALIGN_NL; + char algo[sizeof(ALG_AES_CBC)] ALIGN_NL; struct nlattr flags_head ALIGN_NL; uint32_t flags ALIGN_NL; struct nlattr bits_head ALIGN_NL; @@ -64,7 +67,7 @@ test_ncr_key(int cfd) struct nlattr type_head ALIGN_NL; uint32_t type ALIGN_NL; struct nlattr algo_head ALIGN_NL; - uint32_t algo ALIGN_NL; + char algo[sizeof(ALG_AES_CBC)] ALIGN_NL; struct nlattr flags_head ALIGN_NL; uint32_t flags ALIGN_NL; } kimport; @@ -106,7 +109,7 @@ test_ncr_key(int cfd) kimport.type = NCR_KEY_TYPE_SECRET; kimport.algo_head.nla_len = NLA_HDRLEN + sizeof(kimport.algo); kimport.algo_head.nla_type = NCR_ATTR_ALGORITHM; - kimport.algo = NCR_ALG_AES_CBC; + 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; @@ -162,7 +165,7 @@ test_ncr_key(int cfd) kgen.f.key = key; kgen.algo_head.nla_len = NLA_HDRLEN + sizeof(kgen.algo); kgen.algo_head.nla_type = NCR_ATTR_ALGORITHM; - kgen.algo = NCR_ALG_AES_CBC; + strcpy(kgen.algo, ALG_AES_CBC); kgen.flags_head.nla_len = NLA_HDRLEN + sizeof(kgen.flags); kgen.flags_head.nla_type = NCR_ATTR_KEY_FLAGS; kgen.flags = NCR_KEY_FLAG_EXPORTABLE; @@ -227,10 +230,6 @@ test_ncr_key(int cfd) for (;;) { void *data; - if (nla->nla_len < NLA_HDRLEN + sizeof(uint32_t)) { - fprintf(stderr, "Attribute too small\n"); - return 1; - } if (nla->nla_len > kinfo.f.output_size - ((char *)nla - (char *)&kinfo)) { fprintf(stderr, "Attributes overflow\n"); @@ -239,13 +238,26 @@ test_ncr_key(int cfd) data = (char *)nla + NLA_HDRLEN; switch (nla->nla_type) { case NCR_ATTR_ALGORITHM: - if (*(uint32_t *)data != NCR_ALG_AES_CBC) { + if (nla->nla_len < NLA_HDRLEN + 1) { + fprintf(stderr, "Attribute too small\n"); + return 1; + } + if (((char *)data)[nla->nla_len - NLA_HDRLEN - 1] + != 0) { + fprintf(stderr, "NUL missing\n"); + return 1; + } + if (strcmp(data, ALG_AES_CBC) != 0) { fprintf(stderr, "Unexpected algorithm\n"); return 1; } got_algo++; break; case NCR_ATTR_KEY_FLAGS: + if (nla->nla_len < NLA_HDRLEN + sizeof(uint32_t)) { + fprintf(stderr, "Attribute too small\n"); + return 1; + } if (*(uint32_t *)data != NCR_KEY_FLAG_EXPORTABLE) { fprintf(stderr, "Unexpected key flags\n"); return 1; @@ -253,6 +265,10 @@ test_ncr_key(int cfd) got_flags++; break; case NCR_ATTR_KEY_TYPE: + if (nla->nla_len < NLA_HDRLEN + sizeof(uint32_t)) { + fprintf(stderr, "Attribute too small\n"); + return 1; + } if (*(uint32_t *)data != NCR_KEY_TYPE_SECRET) { fprintf(stderr, "Unexpected key type\n"); return 1; @@ -294,7 +310,7 @@ test_ncr_key(int cfd) kgen.f.key = key; kgen.algo_head.nla_len = NLA_HDRLEN + sizeof(kgen.algo); kgen.algo_head.nla_type = NCR_ATTR_ALGORITHM; - kgen.algo = NCR_ALG_AES_CBC; + strcpy(kgen.algo, ALG_AES_CBC); kgen.flags_head.nla_len = NLA_HDRLEN + sizeof(kgen.flags); kgen.flags_head.nla_type = NCR_ATTR_KEY_FLAGS; kgen.flags = 0; @@ -346,7 +362,7 @@ test_ncr_wrap_key(int cfd) struct nlattr type_head ALIGN_NL; uint32_t type ALIGN_NL; struct nlattr algo_head ALIGN_NL; - uint32_t algo ALIGN_NL; + char algo[sizeof(ALG_AES_CBC)] ALIGN_NL; struct nlattr flags_head ALIGN_NL; uint32_t flags ALIGN_NL; } kimport; @@ -360,7 +376,7 @@ test_ncr_wrap_key(int cfd) struct nlattr wrap_algo_head ALIGN_NL; uint32_t wrap_algo ALIGN_NL; struct nlattr algo_head ALIGN_NL; - uint32_t algo ALIGN_NL; + char algo[sizeof(ALG_AES_CBC)] ALIGN_NL; } kunwrap; uint8_t data[WRAPPED_KEY_DATA_SIZE]; int data_size; @@ -394,7 +410,7 @@ test_ncr_wrap_key(int cfd) kimport.type = NCR_KEY_TYPE_SECRET; kimport.algo_head.nla_len = NLA_HDRLEN + sizeof(kimport.algo); kimport.algo_head.nla_type = NCR_ATTR_ALGORITHM; - kimport.algo = NCR_ALG_AES_CBC; + 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; @@ -428,7 +444,7 @@ test_ncr_wrap_key(int cfd) kimport.type = NCR_KEY_TYPE_SECRET; kimport.algo_head.nla_len = NLA_HDRLEN + sizeof(kimport.algo); kimport.algo_head.nla_type = NCR_ATTR_ALGORITHM; - kimport.algo = NCR_ALG_AES_CBC; + 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_WRAPPABLE; @@ -500,7 +516,7 @@ test_ncr_wrap_key(int cfd) 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; - kunwrap.algo = NCR_ALG_AES_CBC; + strcpy(kunwrap.algo, ALG_AES_CBC); if (ioctl(cfd, NCRIO_KEY_UNWRAP, &kunwrap)) { perror("ioctl(NCRIO_KEY_UNWRAP)"); @@ -556,7 +572,7 @@ test_ncr_wrap_key2(int cfd) struct nlattr type_head ALIGN_NL; uint32_t type ALIGN_NL; struct nlattr algo_head ALIGN_NL; - uint32_t algo ALIGN_NL; + char algo[sizeof(ALG_AES_CBC)] ALIGN_NL; struct nlattr flags_head ALIGN_NL; uint32_t flags ALIGN_NL; } kimport; @@ -599,7 +615,7 @@ test_ncr_wrap_key2(int cfd) kimport.type = NCR_KEY_TYPE_SECRET; kimport.algo_head.nla_len = NLA_HDRLEN + sizeof(kimport.algo); kimport.algo_head.nla_type = NCR_ATTR_ALGORITHM; - kimport.algo = NCR_ALG_AES_CBC; + 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; @@ -631,7 +647,7 @@ test_ncr_wrap_key2(int cfd) kimport.type = NCR_KEY_TYPE_SECRET; kimport.algo_head.nla_len = NLA_HDRLEN + sizeof(kimport.algo); kimport.algo_head.nla_type = NCR_ATTR_ALGORITHM; - kimport.algo = NCR_ALG_AES_CBC; + 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_WRAPPABLE; @@ -675,7 +691,7 @@ test_ncr_store_wrap_key(int cfd) struct nlattr type_head ALIGN_NL; uint32_t type ALIGN_NL; struct nlattr algo_head ALIGN_NL; - uint32_t algo ALIGN_NL; + char algo[sizeof(ALG_AES_CBC)] ALIGN_NL; struct nlattr flags_head ALIGN_NL; uint32_t flags ALIGN_NL; } kimport; @@ -715,7 +731,7 @@ test_ncr_store_wrap_key(int cfd) kimport.type = NCR_KEY_TYPE_SECRET; kimport.algo_head.nla_len = NLA_HDRLEN + sizeof(kimport.algo); kimport.algo_head.nla_type = NCR_ATTR_ALGORITHM; - kimport.algo = NCR_ALG_AES_CBC; + 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_WRAPPABLE; @@ -837,7 +853,7 @@ test_ncr_aes(int cfd) struct nlattr type_head ALIGN_NL; uint32_t type ALIGN_NL; struct nlattr algo_head ALIGN_NL; - uint32_t algo ALIGN_NL; + char algo[sizeof(ALG_AES_ECB)] ALIGN_NL; struct nlattr flags_head ALIGN_NL; uint32_t flags ALIGN_NL; } kimport; @@ -846,7 +862,7 @@ test_ncr_aes(int cfd) struct __attribute__((packed)) { struct ncr_session_once f; struct nlattr algo_head ALIGN_NL; - uint32_t algo ALIGN_NL; + char algo[sizeof(ALG_AES_ECB)] ALIGN_NL; struct nlattr key_head ALIGN_NL; uint32_t key ALIGN_NL; struct nlattr input_head ALIGN_NL; @@ -880,7 +896,7 @@ test_ncr_aes(int cfd) kimport.type = NCR_KEY_TYPE_SECRET; kimport.algo_head.nla_len = NLA_HDRLEN + sizeof(kimport.algo); kimport.algo_head.nla_type = NCR_ATTR_ALGORITHM; - kimport.algo = NCR_ALG_AES_CBC; + strcpy(kimport.algo, ALG_AES_ECB); 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; @@ -896,7 +912,7 @@ test_ncr_aes(int cfd) op.f.op = NCR_OP_ENCRYPT; op.algo_head.nla_len = NLA_HDRLEN + sizeof(op.algo); op.algo_head.nla_type = NCR_ATTR_ALGORITHM; - op.algo = NCR_ALG_AES_ECB; + strcpy(op.algo, ALG_AES_ECB); op.key_head.nla_len = NLA_HDRLEN + sizeof(op.key); op.key_head.nla_type = NCR_ATTR_KEY; op.key = key; @@ -950,7 +966,7 @@ test_ncr_aes(int cfd) kimport.type = NCR_KEY_TYPE_SECRET; kimport.algo_head.nla_len = NLA_HDRLEN + sizeof(kimport.algo); kimport.algo_head.nla_type = NCR_ATTR_ALGORITHM; - kimport.algo = NCR_ALG_AES_CBC; + 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; @@ -966,7 +982,7 @@ test_ncr_aes(int cfd) op.f.op = NCR_OP_DECRYPT; op.algo_head.nla_len = NLA_HDRLEN + sizeof(op.algo); op.algo_head.nla_type = NCR_ATTR_ALGORITHM; - op.algo = NCR_ALG_AES_ECB; + strcpy(op.algo, ALG_AES_ECB); op.key_head.nla_len = NLA_HDRLEN + sizeof(op.key); op.key_head.nla_type = NCR_ATTR_KEY; op.key = key; @@ -1010,8 +1026,7 @@ test_ncr_aes(int cfd) } struct hash_vectors_st { - const char* name; - ncr_algorithm_t algorithm; + const char* algorithm; const uint8_t* key; /* if hmac */ int key_size; const uint8_t* plaintext; @@ -1021,8 +1036,7 @@ struct hash_vectors_st { ncr_crypto_op_t op; } hash_vectors[] = { { - .name = "SHA1", - .algorithm = NCR_ALG_SHA1, + .algorithm = "sha1", .key = NULL, .plaintext = (uint8_t*)"what do ya want for nothing?", .plaintext_size = sizeof("what do ya want for nothing?")-1, @@ -1031,8 +1045,7 @@ struct hash_vectors_st { .op = NCR_OP_SIGN, }, { - .name = "HMAC-MD5", - .algorithm = NCR_ALG_HMAC_MD5, + .algorithm = "hmac(md5)", .key = (uint8_t*)"Jefe", .key_size = 4, .plaintext = (uint8_t*)"what do ya want for nothing?", @@ -1043,8 +1056,7 @@ struct hash_vectors_st { }, /* from rfc4231 */ { - .name = "HMAC-SHA224", - .algorithm = NCR_ALG_HMAC_SHA2_224, + .algorithm = "hmac(sha224)", .key = (uint8_t*)"\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b", .key_size = 20, .plaintext = (uint8_t*)"Hi There", @@ -1054,8 +1066,7 @@ struct hash_vectors_st { .op = NCR_OP_SIGN, }, { - .name = "HMAC-SHA256", - .algorithm = NCR_ALG_HMAC_SHA2_256, + .algorithm = "hmac(sha256)", .key = (uint8_t*)"\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b", .key_size = 20, .plaintext = (uint8_t*)"Hi There", @@ -1065,8 +1076,7 @@ struct hash_vectors_st { .op = NCR_OP_SIGN, }, { - .name = "HMAC-SHA384", - .algorithm = NCR_ALG_HMAC_SHA2_384, + .algorithm = "hmac(sha384)", .key = (uint8_t*)"\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b", .key_size = 20, .plaintext = (uint8_t*)"Hi There", @@ -1076,8 +1086,7 @@ struct hash_vectors_st { .op = NCR_OP_SIGN, }, { - .name = "HMAC-SHA512", - .algorithm = NCR_ALG_HMAC_SHA2_512, + .algorithm = "hmac(sha512)", .key = (uint8_t*)"\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b", .key_size = 20, .plaintext = (uint8_t*)"Hi There", @@ -1101,24 +1110,24 @@ test_ncr_hash(int cfd) uint8_t id[2] ALIGN_NL; struct nlattr type_head ALIGN_NL; uint32_t type ALIGN_NL; - struct nlattr algo_head ALIGN_NL; - uint32_t algo ALIGN_NL; struct nlattr flags_head ALIGN_NL; uint32_t flags ALIGN_NL; + struct nlattr algo_head ALIGN_NL; + char algo[128] ALIGN_NL; } kimport; uint8_t data[HASH_DATA_SIZE]; int i, j; size_t data_size; struct __attribute__((packed)) { struct ncr_session_once f; - struct nlattr algo_head ALIGN_NL; - uint32_t algo ALIGN_NL; struct nlattr key_head ALIGN_NL; uint32_t key ALIGN_NL; struct nlattr input_head ALIGN_NL; struct ncr_session_input_data input ALIGN_NL; struct nlattr output_head ALIGN_NL; struct ncr_session_output_buffer output ALIGN_NL; + struct nlattr algo_head ALIGN_NL; + char algo[128] ALIGN_NL; } op; /* convert it to key */ @@ -1130,13 +1139,14 @@ test_ncr_hash(int cfd) fprintf(stdout, "Tests on Hashes\n"); for (i=0;iversion = THIS_VERSION; pkey->type = key->type; pkey->flags = key->flags; - pkey->algorithm = key->algorithm->algo; + BUG_ON(strlen(key->algorithm->kstr) > sizeof(pkey->algorithm) - 1); + strcpy(pkey->algorithm, key->algorithm->kstr); pkey->key_id_size = key->key_id_size; memcpy(pkey->key_id, key->key_id, key->key_id_size); @@ -95,6 +96,7 @@ int key_from_storage_data(struct key_item_st* key, const void* data, size_t data int ret; if (data_size != sizeof(*pkey) || pkey->version != THIS_VERSION + || memchr(pkey->algorithm, '\0', sizeof(pkey->algorithm)) == NULL || pkey->key_id_size > MAX_KEY_ID_SIZE) { err(); return -EINVAL; diff --git a/ncr-key.c b/ncr-key.c index 56708d8fba7..6e682451375 100644 --- a/ncr-key.c +++ b/ncr-key.c @@ -624,8 +624,8 @@ int ret; ret = ncr_out_put_u32(out, *attr, item->type); break; case NCR_ATTR_ALGORITHM: - ret = ncr_out_put_u32(out, *attr, - item->algorithm->algo); + ret = ncr_out_put_string(out, *attr, + item->algorithm->kstr); break; default: break; /* Silently ignore */ diff --git a/ncr-pk.c b/ncr-pk.c index ed904d60d4a..ecac4c777b2 100644 --- a/ncr-pk.c +++ b/ncr-pk.c @@ -123,7 +123,8 @@ static int ncr_pk_make_public_and_id( struct key_item_st * private, struct key_i } key_id_size = MAX_KEY_ID_SIZE; - cret = hash_memory(_ncr_algo_to_properties(NCR_ALG_SHA1), tmp, max_size, private->key_id, &key_id_size); + cret = hash_memory(_ncr_algo_to_properties("sha1"), tmp, max_size, + private->key_id, &key_id_size); if (cret != CRYPT_OK) { err(); ret = _ncr_tomerr(cret); diff --git a/ncr-sessions.c b/ncr-sessions.c index 8f3e721de8d..41f8a4c9000 100644 --- a/ncr-sessions.c +++ b/ncr-sessions.c @@ -130,87 +130,91 @@ err_sess: } static const struct algo_properties_st algo_properties[] = { - { .algo = NCR_ALG_NULL, .kstr = "ecb(cipher_null)", +#define KSTR(x) .kstr = x, .kstr_len = sizeof(x) - 1 + { .algo = NCR_ALG_NULL, KSTR("ecb(cipher_null)"), .needs_iv = 0, .is_symmetric=1, .can_encrypt=1, .key_type = NCR_KEY_TYPE_INVALID }, - { .algo = NCR_ALG_3DES_CBC, .kstr = "cbc(des3_ede)", + { .algo = NCR_ALG_3DES_CBC, KSTR("cbc(des3_ede)"), .needs_iv = 1, .is_symmetric=1, .can_encrypt=1, .key_type = NCR_KEY_TYPE_SECRET }, - { .algo = NCR_ALG_AES_CBC, .kstr = "cbc(aes)", + { KSTR("cbc(aes)"), .needs_iv = 1, .is_symmetric=1, .can_encrypt=1, .key_type = NCR_KEY_TYPE_SECRET }, - { .algo = NCR_ALG_CAMELLIA_CBC, .kstr = "cbc(camelia)", + { KSTR("cbc(camelia)"), .needs_iv = 1, .is_symmetric=1, .can_encrypt=1, .key_type = NCR_KEY_TYPE_SECRET }, - { .algo = NCR_ALG_AES_CTR, .kstr = "ctr(aes)", + { KSTR("ctr(aes)"), .needs_iv = 1, .is_symmetric=1, .can_encrypt=1, .key_type = NCR_KEY_TYPE_SECRET }, - { .algo = NCR_ALG_CAMELLIA_CTR, .kstr = "ctr(camelia)", + { KSTR("ctr(camelia)"), .needs_iv = 1, .is_symmetric=1, .can_encrypt=1, .key_type = NCR_KEY_TYPE_SECRET }, - { .algo = NCR_ALG_ARCFOUR, .kstr = NULL, + { KSTR("ecb(aes)"), .needs_iv = 0, .is_symmetric=1, .can_encrypt=1, .key_type = NCR_KEY_TYPE_SECRET }, - { .algo = NCR_ALG_AES_ECB, .kstr = "ecb(aes)", + { KSTR("ecb(camelia)"), .needs_iv = 0, .is_symmetric=1, .can_encrypt=1, .key_type = NCR_KEY_TYPE_SECRET }, - { .algo = NCR_ALG_CAMELLIA_ECB, .kstr = "ecb(camelia)", - .needs_iv = 0, .is_symmetric=1, .can_encrypt=1, - .key_type = NCR_KEY_TYPE_SECRET }, - { .algo = NCR_ALG_SHA1, .kstr = "sha1", + { .algo = NCR_ALG_SHA1, KSTR("sha1"), .digest_size = 20, .can_digest=1, .key_type = NCR_KEY_TYPE_INVALID }, - { .algo = NCR_ALG_MD5, .kstr = "md5", + { .algo = NCR_ALG_MD5, KSTR("md5"), .digest_size = 16, .can_digest=1, .key_type = NCR_KEY_TYPE_INVALID }, - { .algo = NCR_ALG_SHA2_224, .kstr = "sha224", + { .algo = NCR_ALG_SHA2_224, KSTR("sha224"), .digest_size = 28, .can_digest=1, .key_type = NCR_KEY_TYPE_INVALID }, - { .algo = NCR_ALG_SHA2_256, .kstr = "sha256", + { .algo = NCR_ALG_SHA2_256, KSTR("sha256"), .digest_size = 32, .can_digest=1, .key_type = NCR_KEY_TYPE_INVALID }, - { .algo = NCR_ALG_SHA2_384, .kstr = "sha384", + { .algo = NCR_ALG_SHA2_384, KSTR("sha384"), .digest_size = 48, .can_digest=1, .key_type = NCR_KEY_TYPE_INVALID }, - { .algo = NCR_ALG_SHA2_512, .kstr = "sha512", + { .algo = NCR_ALG_SHA2_512, KSTR("sha512"), .digest_size = 64, .can_digest=1, .key_type = NCR_KEY_TYPE_INVALID }, - { .algo = NCR_ALG_HMAC_SHA1, .is_hmac = 1, .kstr = "hmac(sha1)", + { .is_hmac = 1, KSTR("hmac(sha1)"), .digest_size = 20, .can_sign=1, .key_type = NCR_KEY_TYPE_SECRET }, - { .algo = NCR_ALG_HMAC_MD5, .is_hmac = 1, .kstr = "hmac(md5)", + { .is_hmac = 1, KSTR("hmac(md5)"), .digest_size = 16, .can_sign=1, .key_type = NCR_KEY_TYPE_SECRET }, - { .algo = NCR_ALG_HMAC_SHA2_224, .is_hmac = 1, .kstr = "hmac(sha224)", + { .is_hmac = 1, KSTR("hmac(sha224)"), .digest_size = 28, .can_sign=1, .key_type = NCR_KEY_TYPE_SECRET }, - { .algo = NCR_ALG_HMAC_SHA2_256, .is_hmac = 1, .kstr = "hmac(sha256)", + { .is_hmac = 1, KSTR("hmac(sha256)"), .digest_size = 32, .can_sign=1, .key_type = NCR_KEY_TYPE_SECRET }, - { .algo = NCR_ALG_HMAC_SHA2_384, .is_hmac = 1, .kstr = "hmac(sha384)", + { .is_hmac = 1, KSTR("hmac(sha384)"), .digest_size = 48, .can_sign=1, .key_type = NCR_KEY_TYPE_SECRET }, - { .algo = NCR_ALG_HMAC_SHA2_512, .is_hmac = 1, .kstr = "hmac(sha512)", + { .is_hmac = 1, KSTR("hmac(sha512)"), .digest_size = 64, .can_sign=1, .key_type = NCR_KEY_TYPE_SECRET }, - { .algo = NCR_ALG_RSA, .kstr = NULL, .is_pk = 1, + /* NOTE: These algorithm names are not available through the kernel API + (yet). */ + { .algo = NCR_ALG_RSA, KSTR("rsa"), .is_pk = 1, .can_encrypt=1, .can_sign=1, .key_type = NCR_KEY_TYPE_PUBLIC }, - { .algo = NCR_ALG_DSA, .kstr = NULL, .is_pk = 1, + { .algo = NCR_ALG_DSA, KSTR("dsa"), .is_pk = 1, .can_sign=1, .key_type = NCR_KEY_TYPE_PUBLIC }, - { .algo = NCR_ALG_DH, .kstr = NULL, .is_pk = 1, + { .algo = NCR_ALG_DH, KSTR("dh"), .is_pk = 1, .can_kx=1, .key_type = NCR_KEY_TYPE_PUBLIC }, - { .algo = NCR_ALG_NONE } - +#undef KSTR }; -const struct algo_properties_st *_ncr_algo_to_properties(ncr_algorithm_t algo) +/* The lookups by string are inefficient - can we look up all we need from + crypto API? */ +const struct algo_properties_st *_ncr_algo_to_properties(const char *algo) { - ncr_algorithm_t a; - int i = 0; - - for (i = 0; (a = algo_properties[i].algo) != NCR_ALG_NONE; i++) { - if (a == algo) - return &algo_properties[i]; + const struct algo_properties_st *a; + size_t name_len; + + name_len = strlen(algo); + for (a = algo_properties; + a < algo_properties + ARRAY_SIZE(algo_properties); a++) { + if (a->kstr_len == name_len + && memcmp(a->kstr, algo, name_len) == 0) + return a; } return NULL; @@ -218,9 +222,21 @@ const struct algo_properties_st *_ncr_algo_to_properties(ncr_algorithm_t algo) const struct algo_properties_st *_ncr_nla_to_properties(const struct nlattr *nla) { + const struct algo_properties_st *a; + size_t name_len; + if (nla == NULL) return NULL; - return _ncr_algo_to_properties(nla_get_u32(nla)); + + /* nla_len() >= 1 ensured by validate_nla() case NLA_NUL_STRING */ + name_len = nla_len(nla) - 1; + for (a = algo_properties; + a < algo_properties + ARRAY_SIZE(algo_properties); a++) { + if (a->kstr_len == name_len + && memcmp(a->kstr, nla_data(nla), name_len + 1) == 0) + return a; + } + return NULL; } static int key_item_get_nla_read(struct key_item_st **st, @@ -294,7 +310,7 @@ static int _ncr_session_init(struct ncr_lists *lists, ncr_crypto_op_t op, if (ns->algorithm->algo == NCR_ALG_NULL) keysize = 0; - if (ns->algorithm->kstr == NULL) { + if (ns->algorithm->is_pk) { err(); ret = -EINVAL; goto fail; @@ -341,7 +357,7 @@ static int _ncr_session_init(struct ncr_lists *lists, ncr_crypto_op_t op, } if (ns->algorithm->can_digest) { - if (ns->algorithm->kstr == NULL) { + if (ns->algorithm->is_pk) { err(); ret = -EINVAL; goto fail; @@ -371,7 +387,7 @@ static int _ncr_session_init(struct ncr_lists *lists, ncr_crypto_op_t op, } if (ns->algorithm->is_hmac && ns->key->type == NCR_KEY_TYPE_SECRET) { - if (ns->algorithm->kstr == NULL) { + if (ns->algorithm->is_pk) { err(); ret = -EINVAL; goto fail; @@ -399,7 +415,7 @@ static int _ncr_session_init(struct ncr_lists *lists, ncr_crypto_op_t op, goto fail; } - if (sign_hash->kstr == NULL) { + if (sign_hash->is_pk) { err(); ret = -EINVAL; goto fail; diff --git a/ncr.h b/ncr.h index bc681acf43d..3dae3f38eb8 100644 --- a/ncr.h +++ b/ncr.h @@ -30,10 +30,9 @@ of attributes used for the frequent operations? */ enum { NCR_ATTR_UNSPEC, /* 0 is special in lib/nlattr.c. */ - /* FIXME: Use NLA_STRING for this, later */ - NCR_ATTR_ALGORITHM, /* NLA_U32 - ncr_algorithm_t */ + NCR_ATTR_ALGORITHM, /* NLA_NUL_STRING */ NCR_ATTR_DERIVATION_ALGORITHM, /* NLA_U32 - ncr_algorithm_t */ - NCR_ATTR_SIGNATURE_HASH_ALGORITHM, /* NLA_U32 - ncr_algorithm_t */ + NCR_ATTR_SIGNATURE_HASH_ALGORITHM, /* NLA_NUL_STRING */ NCR_ATTR_WRAPPING_ALGORITHM, /* NLA_U32 - ncr_wrap_algorithm_t */ NCR_ATTR_UPDATE_INPUT_DATA, /* NLA_BINARY - ncr_session_input_data */ /* NLA_BINARY - ncr_session_output_buffer */ @@ -51,7 +50,7 @@ enum { NCR_ATTR_RSA_MODULUS_BITS, /* NLA_U32 */ NCR_ATTR_RSA_E, /* NLA_BINARY */ NCR_ATTR_RSA_ENCODING_METHOD, /* NLA_U32 - ncr_rsa_type_t */ - NCR_ATTR_RSA_OAEP_HASH_ALGORITHM, /* NLA_U32 - ncr_algorithm_t */ + NCR_ATTR_RSA_OAEP_HASH_ALGORITHM, /* NLA_NUL_STRING */ NCR_ATTR_RSA_PSS_SALT_LENGTH, /* NLA_U32 */ NCR_ATTR_DSA_P_BITS, /* NLA_U32 */ NCR_ATTR_DSA_Q_BITS, /* NLA_U32 */ @@ -69,39 +68,6 @@ enum { #define NCR_CIPHER_MAX_BLOCK_LEN 32 #define NCR_HASH_MAX_OUTPUT_SIZE 64 -typedef enum { - NCR_ALG_NONE, - NCR_ALG_NULL, - NCR_ALG_3DES_CBC, - NCR_ALG_AES_CBC, - NCR_ALG_CAMELLIA_CBC, - NCR_ALG_ARCFOUR, - NCR_ALG_AES_ECB, - NCR_ALG_CAMELLIA_ECB, - NCR_ALG_AES_CTR, - NCR_ALG_CAMELLIA_CTR, - - NCR_ALG_SHA1=40, - NCR_ALG_MD5, - NCR_ALG_SHA2_224, - NCR_ALG_SHA2_256, - NCR_ALG_SHA2_384, - NCR_ALG_SHA2_512, - - NCR_ALG_HMAC_SHA1=80, - NCR_ALG_HMAC_MD5, - NCR_ALG_HMAC_SHA2_224, - NCR_ALG_HMAC_SHA2_256, - NCR_ALG_HMAC_SHA2_384, - NCR_ALG_HMAC_SHA2_512, - - NCR_ALG_RSA=140, - NCR_ALG_DSA, - NCR_ALG_DH, /* DH as in PKCS #3 */ -} ncr_algorithm_t; - - - typedef enum { NCR_WALG_AES_RFC3394, /* for secret keys only */ NCR_WALG_AES_RFC5649, /* can wrap arbitrary key */ diff --git a/utils.c b/utils.c index 8118a1d9e57..23d75f126d5 100644 --- a/utils.c +++ b/utils.c @@ -48,9 +48,9 @@ #endif /* !CONFIG_COMPAT */ static const struct nla_policy ncr_attr_policy[NCR_ATTR_MAX + 1] = { - [NCR_ATTR_ALGORITHM] = { NLA_U32, 0 }, + [NCR_ATTR_ALGORITHM] = { NLA_NUL_STRING, 0 }, [NCR_ATTR_DERIVATION_ALGORITHM] = { NLA_U32, 0 }, - [NCR_ATTR_SIGNATURE_HASH_ALGORITHM] = { NLA_U32, 0 }, + [NCR_ATTR_SIGNATURE_HASH_ALGORITHM] = { NLA_NUL_STRING, 0 }, [NCR_ATTR_WRAPPING_ALGORITHM] = { NLA_U32, 0 }, [NCR_ATTR_UPDATE_INPUT_DATA] = { NLA_BINARY, MAX_SESSION_INPUT_DATA_SIZE @@ -74,7 +74,7 @@ static const struct nla_policy ncr_attr_policy[NCR_ATTR_MAX + 1] = { [NCR_ATTR_RSA_MODULUS_BITS] = { NLA_U32, 0 }, [NCR_ATTR_RSA_E] = { NLA_BINARY, 0 }, [NCR_ATTR_RSA_ENCODING_METHOD] = { NLA_U32, 0 }, - [NCR_ATTR_RSA_OAEP_HASH_ALGORITHM] = { NLA_U32, 0 }, + [NCR_ATTR_RSA_OAEP_HASH_ALGORITHM] = { NLA_NUL_STRING, 0 }, [NCR_ATTR_RSA_PSS_SALT_LENGTH] = { NLA_U32, 0 }, [NCR_ATTR_DSA_P_BITS] = { NLA_U32, 0 }, [NCR_ATTR_DSA_Q_BITS] = { NLA_U32, 0 }, -- cgit From f9fa90899a4691ce01244593e2902111fe9bf2c6 Mon Sep 17 00:00:00 2001 From: Miloslav Trmač Date: Wed, 18 Aug 2010 05:51:32 +0200 Subject: Replace ncr_derive_t by NLA_NUL_STRING --- examples/pk.c | 6 +++--- ncr-pk.c | 39 ++++++++++++++++++--------------------- ncr.h | 6 ++---- utils.c | 2 +- 4 files changed, 24 insertions(+), 29 deletions(-) diff --git a/examples/pk.c b/examples/pk.c index 25032755504..599f396cf9a 100644 --- a/examples/pk.c +++ b/examples/pk.c @@ -339,7 +339,7 @@ struct ncr_key_export kexport; struct __attribute__((packed)) { struct ncr_key_derive f; struct nlattr algo_head ALIGN_NL; - uint32_t algo ALIGN_NL; + char algo[sizeof(NCR_DERIVE_DH)] ALIGN_NL; struct nlattr flags_head ALIGN_NL; uint32_t flags ALIGN_NL; struct nlattr public_head ALIGN_NL; @@ -496,7 +496,7 @@ struct __attribute__((packed)) { kderive.f.new_key = z1; kderive.algo_head.nla_len = NLA_HDRLEN + sizeof(kderive.algo); kderive.algo_head.nla_type = NCR_ATTR_DERIVATION_ALGORITHM; - kderive.algo = NCR_DERIVE_DH; + strcpy(kderive.algo, NCR_DERIVE_DH); kderive.flags_head.nla_len = NLA_HDRLEN + sizeof(kderive.flags); kderive.flags_head.nla_type = NCR_ATTR_KEY_FLAGS; kderive.flags = NCR_KEY_FLAG_EXPORTABLE; @@ -527,7 +527,7 @@ struct __attribute__((packed)) { kderive.f.new_key = z2; kderive.algo_head.nla_len = NLA_HDRLEN + sizeof(kderive.algo); kderive.algo_head.nla_type = NCR_ATTR_DERIVATION_ALGORITHM; - kderive.algo = NCR_DERIVE_DH; + strcpy(kderive.algo, NCR_DERIVE_DH); kderive.flags_head.nla_len = NLA_HDRLEN + sizeof(kderive.flags); kderive.flags_head.nla_type = NCR_ATTR_KEY_FLAGS; kderive.flags = NCR_KEY_FLAG_EXPORTABLE; diff --git a/ncr-pk.c b/ncr-pk.c index ecac4c777b2..c6055dba1d5 100644 --- a/ncr-pk.c +++ b/ncr-pk.c @@ -632,30 +632,27 @@ int ret; err(); return -EINVAL; } - switch(nla_get_u32(nla)) { - case NCR_DERIVE_DH: - if (oldkey->type != NCR_KEY_TYPE_PRIVATE && - oldkey->algorithm->algo != NCR_ALG_DH) { - err(); - return -EINVAL; - } + if (nla_strcmp(nla, NCR_DERIVE_DH) == 0) { + if (oldkey->type != NCR_KEY_TYPE_PRIVATE && + oldkey->algorithm->algo != NCR_ALG_DH) { + err(); + return -EINVAL; + } - nla = tb[NCR_ATTR_DH_PUBLIC]; - if (nla == NULL) { - err(); - return -EINVAL; - } - ret = dh_derive_gxy(newkey, &oldkey->key.pk.dh, - nla_data(nla), nla_len(nla)); - if (ret < 0) { - err(); - return ret; - } - - break; - default: + nla = tb[NCR_ATTR_DH_PUBLIC]; + if (nla == NULL) { err(); return -EINVAL; + } + ret = dh_derive_gxy(newkey, &oldkey->key.pk.dh, nla_data(nla), + nla_len(nla)); + if (ret < 0) { + err(); + return ret; + } + } else { + err(); + return -EINVAL; } return 0; diff --git a/ncr.h b/ncr.h index 3dae3f38eb8..7f8fba40740 100644 --- a/ncr.h +++ b/ncr.h @@ -31,7 +31,7 @@ enum { NCR_ATTR_UNSPEC, /* 0 is special in lib/nlattr.c. */ NCR_ATTR_ALGORITHM, /* NLA_NUL_STRING */ - NCR_ATTR_DERIVATION_ALGORITHM, /* NLA_U32 - ncr_algorithm_t */ + NCR_ATTR_DERIVATION_ALGORITHM, /* NLA_NUL_STRING - NCR_DERIVE_* */ NCR_ATTR_SIGNATURE_HASH_ALGORITHM, /* NLA_NUL_STRING */ NCR_ATTR_WRAPPING_ALGORITHM, /* NLA_U32 - ncr_wrap_algorithm_t */ NCR_ATTR_UPDATE_INPUT_DATA, /* NLA_BINARY - ncr_session_input_data */ @@ -120,9 +120,7 @@ typedef enum { RSA_PKCS1_PSS, /* for signatures only */ } ncr_rsa_type_t; -typedef enum { - NCR_DERIVE_DH=1, -} ncr_derive_t; +#define NCR_DERIVE_DH "dh" struct ncr_key_derive { diff --git a/utils.c b/utils.c index 23d75f126d5..113a1ee2e06 100644 --- a/utils.c +++ b/utils.c @@ -49,7 +49,7 @@ static const struct nla_policy ncr_attr_policy[NCR_ATTR_MAX + 1] = { [NCR_ATTR_ALGORITHM] = { NLA_NUL_STRING, 0 }, - [NCR_ATTR_DERIVATION_ALGORITHM] = { NLA_U32, 0 }, + [NCR_ATTR_DERIVATION_ALGORITHM] = { NLA_NUL_STRING, 0 }, [NCR_ATTR_SIGNATURE_HASH_ALGORITHM] = { NLA_NUL_STRING, 0 }, [NCR_ATTR_WRAPPING_ALGORITHM] = { NLA_U32, 0 }, [NCR_ATTR_UPDATE_INPUT_DATA] = { -- cgit From 718c0c3aa5cf871a7d69d5f440c9d668fac0ddf0 Mon Sep 17 00:00:00 2001 From: Miloslav Trmač Date: Wed, 18 Aug 2010 05:57:27 +0200 Subject: Replace ncr_wrap_algorithm_t by NLA_NUL_STRING --- examples/ncr.c | 12 ++++++------ examples/pk.c | 10 +++++----- ncr-key-wrap.c | 37 ++++++++++++++----------------------- ncr.h | 8 +++----- utils.c | 2 +- 5 files changed, 29 insertions(+), 40 deletions(-) diff --git a/examples/ncr.c b/examples/ncr.c index a9b0cea70d2..343208ec068 100644 --- a/examples/ncr.c +++ b/examples/ncr.c @@ -369,12 +369,12 @@ test_ncr_wrap_key(int cfd) struct __attribute__((packed)) { struct ncr_key_wrap f; struct nlattr algo_head ALIGN_NL; - uint32_t algo ALIGN_NL; + char algo[sizeof(NCR_WALG_AES_RFC3394)] ALIGN_NL; } kwrap; struct __attribute__((packed)) { struct ncr_key_unwrap f; struct nlattr wrap_algo_head ALIGN_NL; - uint32_t wrap_algo 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; } kunwrap; @@ -464,7 +464,7 @@ test_ncr_wrap_key(int cfd) kwrap.f.buffer_size = sizeof(data); kwrap.algo_head.nla_len = NLA_HDRLEN + sizeof(kwrap.algo); kwrap.algo_head.nla_type = NCR_ATTR_WRAPPING_ALGORITHM; - kwrap.algo = NCR_WALG_AES_RFC3394; + strcpy(kwrap.algo, NCR_WALG_AES_RFC3394); data_size = ioctl(cfd, NCRIO_KEY_WRAP, &kwrap); if (geteuid() == 0 && data_size < 0) { @@ -513,7 +513,7 @@ test_ncr_wrap_key(int cfd) kunwrap.f.data_size = data_size; kunwrap.wrap_algo_head.nla_len = NLA_HDRLEN + sizeof(kunwrap.wrap_algo); kunwrap.wrap_algo_head.nla_type = NCR_ATTR_WRAPPING_ALGORITHM; - kunwrap.wrap_algo = NCR_WALG_AES_RFC3394; + 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); @@ -579,7 +579,7 @@ test_ncr_wrap_key2(int cfd) struct __attribute__((packed)) { struct ncr_key_wrap f; struct nlattr algo_head ALIGN_NL; - uint32_t algo ALIGN_NL; + char algo[sizeof(NCR_WALG_AES_RFC3394)] ALIGN_NL; } kwrap; uint8_t data[WRAPPED_KEY_DATA_SIZE]; @@ -667,7 +667,7 @@ test_ncr_wrap_key2(int cfd) kwrap.f.buffer_size = sizeof(data); kwrap.algo_head.nla_len = NLA_HDRLEN + sizeof(kwrap.algo); kwrap.algo_head.nla_type = NCR_ATTR_WRAPPING_ALGORITHM; - kwrap.algo = NCR_WALG_AES_RFC3394; + strcpy(kwrap.algo, NCR_WALG_AES_RFC3394); ret = ioctl(cfd, NCRIO_KEY_WRAP, &kwrap); if (ret < 0) { diff --git a/examples/pk.c b/examples/pk.c index 599f396cf9a..1db7aaf2790 100644 --- a/examples/pk.c +++ b/examples/pk.c @@ -618,12 +618,12 @@ test_ncr_wrap_key3(int cfd) struct __attribute__((packed)) { struct ncr_key_wrap f; struct nlattr algo_head ALIGN_NL; - uint32_t algo ALIGN_NL; + char algo[sizeof(NCR_WALG_AES_RFC5649)] ALIGN_NL; } kwrap; struct __attribute__((packed)) { struct ncr_key_unwrap f; struct nlattr wrap_algo_head ALIGN_NL; - uint32_t wrap_algo 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; } kunwrap; @@ -731,7 +731,7 @@ test_ncr_wrap_key3(int cfd) kwrap.f.buffer_size = sizeof(data); kwrap.algo_head.nla_len = NLA_HDRLEN + sizeof(kwrap.algo); kwrap.algo_head.nla_type = NCR_ATTR_WRAPPING_ALGORITHM; - kwrap.algo = NCR_WALG_AES_RFC5649; + strcpy(kwrap.algo, NCR_WALG_AES_RFC5649); ret = ioctl(cfd, NCRIO_KEY_WRAP, &kwrap); if (ret < 0) { @@ -749,7 +749,7 @@ test_ncr_wrap_key3(int cfd) kwrap.f.buffer_size = sizeof(data); kwrap.algo_head.nla_len = NLA_HDRLEN + sizeof(kwrap.algo); kwrap.algo_head.nla_type = NCR_ATTR_WRAPPING_ALGORITHM; - kwrap.algo = NCR_WALG_AES_RFC5649; + strcpy(kwrap.algo, NCR_WALG_AES_RFC5649); ret = ioctl(cfd, NCRIO_KEY_WRAP, &kwrap); if (ret < 0 && i != 2) { @@ -776,7 +776,7 @@ test_ncr_wrap_key3(int cfd) = NLA_HDRLEN + sizeof(kunwrap.wrap_algo); kunwrap.wrap_algo_head.nla_type = NCR_ATTR_WRAPPING_ALGORITHM; - kunwrap.wrap_algo = NCR_WALG_AES_RFC5649; + 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; diff --git a/ncr-key-wrap.c b/ncr-key-wrap.c index de4bcdd5ff4..4111ab151f1 100644 --- a/ncr-key-wrap.c +++ b/ncr-key-wrap.c @@ -590,18 +590,14 @@ int ret; ret = -EINVAL; goto fail; } - switch (nla_get_u32(nla)) { - case NCR_WALG_AES_RFC3394: - ret = wrap_aes(wkey, key, data, &data_size, iv, + if (nla_strcmp(nla, NCR_WALG_AES_RFC3394) == 0) + ret = wrap_aes(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); - break; - case NCR_WALG_AES_RFC5649: - ret = wrap_aes_rfc5649(wkey, key, data, &data_size, iv, - iv_size); - break; - default: - err(); - ret = -EINVAL; + else { + err(); + ret = -EINVAL; } if (ret < 0) { @@ -678,18 +674,13 @@ int ret; ret = -EINVAL; goto fail; } - switch (nla_get_u32(nla)) { - case NCR_WALG_AES_RFC3394: - ret = unwrap_aes_rfc3394(wkey, key, data, data_size, - tb); - break; - case NCR_WALG_AES_RFC5649: - ret = unwrap_aes_rfc5649(wkey, key, data, data_size, - tb); - break; - default: - err(); - ret = -EINVAL; + if (nla_strcmp(nla, NCR_WALG_AES_RFC3394) == 0) + ret = unwrap_aes_rfc3394(wkey, key, data, data_size, tb); + else if (nla_strcmp(nla, NCR_WALG_AES_RFC5649) == 0) + ret = unwrap_aes_rfc5649(wkey, key, data, data_size, tb); + else { + err(); + ret = -EINVAL; } fail: diff --git a/ncr.h b/ncr.h index 7f8fba40740..180aa3a9007 100644 --- a/ncr.h +++ b/ncr.h @@ -33,7 +33,7 @@ enum { NCR_ATTR_ALGORITHM, /* NLA_NUL_STRING */ NCR_ATTR_DERIVATION_ALGORITHM, /* NLA_NUL_STRING - NCR_DERIVE_* */ NCR_ATTR_SIGNATURE_HASH_ALGORITHM, /* NLA_NUL_STRING */ - NCR_ATTR_WRAPPING_ALGORITHM, /* NLA_U32 - ncr_wrap_algorithm_t */ + NCR_ATTR_WRAPPING_ALGORITHM, /* NLA_NUL_STRING - NCR_WALG_* */ NCR_ATTR_UPDATE_INPUT_DATA, /* NLA_BINARY - ncr_session_input_data */ /* NLA_BINARY - ncr_session_output_buffer */ NCR_ATTR_UPDATE_OUTPUT_BUFFER, @@ -68,10 +68,8 @@ enum { #define NCR_CIPHER_MAX_BLOCK_LEN 32 #define NCR_HASH_MAX_OUTPUT_SIZE 64 -typedef enum { - NCR_WALG_AES_RFC3394, /* for secret keys only */ - NCR_WALG_AES_RFC5649, /* can wrap arbitrary key */ -} ncr_wrap_algorithm_t; +#define NCR_WALG_AES_RFC3394 "walg-aes-rfc3394" /* for secret keys only */ +#define NCR_WALG_AES_RFC5649 "walg-aes-rfc5649" /* can wrap arbitrary key */ typedef enum { NCR_KEY_TYPE_INVALID, diff --git a/utils.c b/utils.c index 113a1ee2e06..514833cc65c 100644 --- a/utils.c +++ b/utils.c @@ -51,7 +51,7 @@ static const struct nla_policy ncr_attr_policy[NCR_ATTR_MAX + 1] = { [NCR_ATTR_ALGORITHM] = { NLA_NUL_STRING, 0 }, [NCR_ATTR_DERIVATION_ALGORITHM] = { NLA_NUL_STRING, 0 }, [NCR_ATTR_SIGNATURE_HASH_ALGORITHM] = { NLA_NUL_STRING, 0 }, - [NCR_ATTR_WRAPPING_ALGORITHM] = { NLA_U32, 0 }, + [NCR_ATTR_WRAPPING_ALGORITHM] = { NLA_NUL_STRING, 0 }, [NCR_ATTR_UPDATE_INPUT_DATA] = { NLA_BINARY, MAX_SESSION_INPUT_DATA_SIZE }, -- cgit From e98198b8db7216f2fb0cca5614a51a617d5401cc Mon Sep 17 00:00:00 2001 From: Miloslav Trmač Date: Fri, 20 Aug 2010 03:05:39 +0200 Subject: Update ioctl interface documentation. --- crypto.4 | 677 ++++++++++++++++++++++++++++++++++++++++----------------------- 1 file changed, 430 insertions(+), 247 deletions(-) diff --git a/crypto.4 b/crypto.4 index e907e2f7742..7ba8d9be704 100644 --- a/crypto.4 +++ b/crypto.4 @@ -16,7 +16,7 @@ .\" 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. .\" .\" Author: Miloslav Trmač -.TH CRYPTO 4 2010-08-02 Linux "Linux Programmer's Manual" +.TH CRYPTO 4 2010-08-20 Linux "Linux Programmer's Manual" .SH NAME /dev/crypto \- kernel cryptographic module interface @@ -54,18 +54,125 @@ and passes a pointer to the data structure as the third parameter to .BR ioctl (2). On success, output data is available in the same structure. +.SH OPERATION ATTRIBUTES + +In addition to the fixed members of data structures, +a process can pass additional attributes on input of most operations, +and receive additional attributes back from the kernel. +If this is supported by a specific operation, +the fixed data structure members for this operation include +.B input_size +and \fBoutput_size\fR. + +The input attributes immediately follow the fixed data structure as a sequence +of correctly aligned (\fBstruct nlattr\fP, attribute data) pairs, +using the same data layout and formatting rules as +.BR netlink (7) +messages. +The +.B input_size +member must be initialized to the total length of input (including both the +fixed data structure and the attributes). + +There is an (unspecified) upper limit on the total size of all attributes, +which should be large enough to accommodate any reasonable application. +If a larger input is provided nevertheless, +the operation will fail with \fBEOVERFLOW\fP. + +Output attributes, if any, are written by the kernel in the same format +following the fixed data structure (overwriting input attributes, if any). +The +.B output_size +member must be initialized to the total space available for output +(including the fixed data structure and space for attributes), +and is updated by the kernel with the total space actually used for attributes. + +If the space available for output attributes is too small, +the operation will fail with \fBERANGE\fP. + +As a special case, +.B input_size +may be zero to indicate no input attributes are supplied. +Similarly, +.B output_size +may be zero to indicate no space for output attributes is provided; +in such case +.B output_size +is not overwritten by the kernel with the total space actually used +(which is equal to size of the fixed data structure) +and remains zero when the operation finishes. + +The kernel accepts and silently ignores unknown attributes. + +The kernel will not add new output attributes to existing operations +in future releases +unless the new output attribute was explicitly requested by the application. +(Therefore, the application does not have to allocate any extra space for +output attributes it does not expect.) + +The following attributes are used in more than one operation: + +.TP +.B NCR_ATTR_ALGORITHM +A NUL-terminated string specifying an algorithm +(to be used in an operation, or as a property of a key), +using the Linux crypto API algorithm names. + +Three additional algorithm names are recognized: \fBrsa\fP, \fBdsa\fP, \fBdh\fP. + +.TP +.B NCR_ATTR_IV +Unformatted binary data specifying an initialization vector, + +.TP +.B NCR_ATTR_KEY_FLAGS +An 32-bit unsigned integer in native byte order specifying key flags, +a combination of +.B NCR_KEY_FLAG_EXPORTABLE +(the key material can be exported in plaintext to user space) +and +.B NCR_KEY_FLAG_WRAPPABLE +(the key material can be wrapped and the result made available to user space). + +.TP +.B NCR_ATTR_KEY_ID +Arbitrary binary data +which can be used by the application for key identification. + +.TP +.B NCR_ATTR_KEY_TYPE +An 32-bit unsigned integer in native byte order specifying key type, +one of \fBNCR_KEY_TYPE_SECRET\fP, \fBNCR_KEY_TYPE_PUBLIC\fP and +\fBNCR_KEY_TYPE_PRIVATE\fP. + +.TP +.B NCR_ATTR_WRAPPING_ALGORITHM +A NUL-terminated string specifying a key wrapping algorithm. +The values +.B walg-aes-rfc3394 +and +.B walg-aes-rfc5649 +are currently supported. +.RE + +.SH OPERATIONS + The following operations are defined: .TP .B NCRIO_KEY_INIT Allocate a kernel-space key object. -The parameter is not used on input +The third +.BR ioctl (s) +parameter is ignored (key attributes are set later, when the key material is initialized). -On success, an integer descriptor for the key object +Returns an +.B ncr_key_t +descriptor for the key object (valid within the current .I /dev/crypto namespace) -is stored in the provided area. +on success. There is a per-process and per-user (not per-namespace) limit on the number key objects that can be allocated. @@ -73,7 +180,9 @@ on the number key objects that can be allocated. .TP .B NCRIO_KEY_DEINIT Deallocate a kernel-space key object. -The parameter specifies the integer descriptor of the key object. +The parameter points to a +.B ncr_key_t +descriptor of the key object. After all other operations using this key object (if any) terminate, the key material will be cleared and the object will be freed. Note that this may happen both before this operation returns, @@ -84,34 +193,25 @@ and after it returns, depending on other references to this key object. Clear existing key material in the specified key object, and generate new key material. -The parameter points to \fBstruct ncr_key_generate_st\fP, which specifies: +The parameter points to \fBstruct ncr_key_generate\fP, +which specifies the destination key object in its +.B key +member. + +The following input attributes are recognized: .RS -.IP \fBdesc\fP -The key descriptor -.IP \fBparams.algorithm\fP -The crypto algorithm with which the key will be used -.IP \fBparams.keyflags\fP -Key flags, a combination of -.B NCR_KEY_FLAG_EXPORTABLE -(the key material can be exported in plaintext to user space) -and -.B NCR_KEY_FLAG_WRAPPABLE -(the key material can be wrapped and the result made available to user space). -.IP \fBparams.params\fP -Algorithm-specific key parameters: -For symmetric keys, key length in bits. -For RSA keys, the public exponent and modulus length in bits. -For DSA keys, -.I p -and -.I q -length in bits. -For DH keys, the prime and group generator. +.IP \fBNCR_ATTR_ALGORITHM\fP +Mandatory. +.IP \fBNCR_ATTR_KEY_FLAGS\fP +Optional, flags are unchanged if not present. +.IP \fBNCR_ATTR_SECRET_KEY_BITS\fP +Mandatory for symmetric keys. +An 32-bit unsigned integer in native byte order specifying key length in bits. .RE .IP -Currently only symmetric keys can be generated using this operation. +Only symmetric keys can be currently generated using this operation. In addition to generating the key material, the "persistent" key ID is reset to a random value. @@ -121,98 +221,129 @@ the "persistent" key ID is reset to a random value. Similar to \fBNCRIO_KEY_GENERATE\fP, except that a pair of public/private keys is generated. -The parameter points to \fBstruct ncr_key_generate_st\fP as specified above, -with the additional member -.B desc2 -used to specify the key descriptor for the public key. +The parameter points to \fBstruct ncr_key_generate_pair\fP, +which specifies the destination key objects in its +.B private_key +and +.B public_key +members. + +The following input attributes are recognized: +.RS +.IP \fBNCR_ATTR_KEY_FLAGS\fP +Optional, flags are unchanged if not present. +.IP \fBNCR_ATTR_RSA_E\fP +For RSA keys, +the public exponent as a big-endian multiple-precision integer. +Optional, defaults to 65537. +.IP \fBNCR_ATTR_RSA_MODULUS_BITS\fP +Mandatory for RSA keys. +An 32-bit unsigned integer in native byte order +specifying modulus length in bits. +.IP \fBNCR_ATTR_DSA_P_BITS\fP +For DSA keys, length of the "p" key parameter in bits +as an 32-bit unsigned integer in native byte order. +Optional, defaults to 1024. +.IP \fBNCR_ATTR_DSA_Q_BITS\fP +For DSA keys, length of the "q" key parameter in bits +as an 32-bit unsigned integer in native byte order. +Optional, defaults to 160. +.IP \fBNCR_ATTR_DH_BASE\fP +Mandatory for D-H keys. +The prime modulus of a D-H group as a big-endian multiple-precision integer. +.IP \fBNCR_ATTR_DH_PRIME\fP +Mandatory for D-H keys. +The generator of a D-H group as a big-endian multiple-precision integer. +.RE + +.IP The .B NCR_KEY_FLAG_EXPORTABLE and .B NCR_KEY_FLAG_WRAPPABLE flags are automatically set on the public key. +In addition to generating the key material, +the "persistent" key ID of both keys is set to a same value +derived from the public key. + .TP .B NCRIO_KEY_DERIVE Derive a new key using one key and additional data. -The parameter points to \fBstruct ncr_key_derivation_params_st\fP, -which specifies: +The parameter points to \fBstruct ncr_key_derive\fP, +which specifies the source and destination keys in the +.B input_key +and +.B new_key +members. + +The following input attributes are recognized: .RS -.IP \fBderive\fP -The derivation algorithm. -Currently only -.B NCR_DERIVE_DH -is supported. -.IP \fBnewkey\fP -The descriptor of the resulting key -.IP \fBkeyflags\fP -Flags to use for the resulting key -.IP \fBkey\fP -The source key descriptor -.IP \fBparams\fP -Key type-specific parameters. -For \fBNCR_DERIVE_DH\fP, -.B params.params.dh.pub -and -.B params.params.dh.pub_size -specify the peer's public key. +.IP \fBNCR_ATTR_KEY_FLAGS\fP +Optional, flags are unchanged if not present. +.IP \fBNCR_ATTR_DERIVATION_ALGORITHM\fP +Mandatory. +A NUL-terminated string specifying a key derivation algorithm. +Only +.B dh +is currently supported. +.IP \fBNCR_ATTR_DH_PUBLIC\fP +Mandatory for D-H derivation. +The peer's public D-H value as a big-endian multiple-precision integer. .RE .TP .B NCRIO_KEY_EXPORT - Export key material in the specified key object to user space. Only keys with the .B NCR_KEY_FLAG_EXPORTABLE flag can be exported using this operation. -The parameter points to \fBstruct ncr_key_data_st\fP, which specifies: +The parameter points to \fBstruct ncr_key_export\fP, +which specifies the key to export in the +.B key +member, +and a buffer for the exported data in the +.B buffer +and +.B buffer_size +members. -.RS -.IP \fBkey\fP -The key descriptor -.IP \fBidata\fP -Destination buffer -.IP \fBidata_size\fP -Buffer size -.RE +On success, size of the exported key is returned. -.IP Symmetric keys are written directly into the destination buffer. Public and private keys are formatted using ASN.1, except for DH public keys, which are written a raw binary number. -On success, the -.B idata_size -member is set to the size of the exported key. - .TP .B NCRIO_KEY_IMPORT Clear existing key material in the specified key object, and import key material from user space. -The parameter points to \fBstruct ncr_key_data_st\fP, which specifies: +The parameter points to \fBstruct ncr_key_import\fP, +which specifies the destination key in the +.B key +member, +and the input data in the +.B data +and +.B data_size +members. + +The following input attributes are recognized: .RS -.IP \fBkey\fP -The key descriptor -.IP \fBidata\fP -Source data -.IP \fBidata_size\fP -Source data size -.IP \fBkey_id\fP -New "persistent" key ID. -.IP \fBkey_id_size\fP -Size of data in \fBkey_id\fP. -.IP \fBtype\fP -Key type, one of \fBNCR_KEY_TYPE_SECRET\fP, \fBNCR_KEY_TYPE_PUBLIC\fP and -\fBNCR_KEY_TYPE_PRIVATE\fP. -.IP \fBalgorithm\fP -The crypto algorithm with which the key will be used -.IP \fBflags\fP -Key flags +.IP \fBNCR_ATTR_ALGORITHM\fP +Mandatory. +.IP \fBNCR_ATTR_KEY_FLAGS\fP +Optional, flags are unchanged if not present. +.IP \fBNCR_ATTR_KEY_ID\fP +Optional, the "persistent" key ID is unchanged if not present. +.IP \fBNCR_ATTR_KEY_TYPE\fP +Mandatory. .RE .IP @@ -224,19 +355,28 @@ operation. .B NCRIO_KEY_GET_INFO Get metadata of an existing key. -The parameter points to \fBstruct ncr_key_info_st\fP, +The parameter points to \fBstruct ncr_key_get_info\fP, which specifies \fBkey\fP, the key descriptor. -On success, the following members are set: + +The following input attributes are recognized: .RS -.IP \fBflags\fP -Key flags -.IP \fBtype\fP -Key type -.IP \fBalgorithm\fP -Key algorithm +.IP \fBNCR_ATTR_WANTED_ATTRS\fP +An array of unsigned 16-bit integers in native byte order, +specifying the set of output attributes that should be returned. +\fBNCR_ATTR_ALGORITHM\fP, +.B NCR_ATTR_KEY_FLAGS +and +.B NCR_ATTR_KEY_TYPE +are currently supported. +Unsupported attribute requests are silently ignored .RE +.IP +The output attributes explicitly requested in \fBNCR_ATTR_WANTED_ATTRS\fP, +and no other output attributes, +are returned. + .TP .B NCRIO_KEY_WRAP Wrap one key using another, and write the result to user space. @@ -244,62 +384,61 @@ Only keys with the .B NCR_KEY_FLAG_WRAPPABLE flag can be wrapped using this operation. -The parameter points to \fBstruct ncr_key_wrap_st\fP, which specifies: +The parameter points to \fBstruct ncr_key_wrap\fP, +which specifies the key to wrap in the +.B source_key +member, +the wrapping key in the +.B wrapping_key +member, +and a buffer for the wrapped data in the +.B buffer +and +.B buffer_size +members. + +The following input attributes are recognized: .RS -.IP \fBalgorithm\fP -The wrapping algorithm to use, one of -.B NCR_WALG_AES_RFC3394 -and \fBNCR_WALG_AES_RFC5649\fP. -.IP \fBkeytowrap\fP -The descriptor of the key to wrap -.IP \fBkey\fP -The descriptor of the key used for wrapping -.IP \fBparams\fP -Key type-specific parameters. -For the currently supported wrapping algorithms, -.B params.params.cipher.iv -and -.B params.params.cipher.iv_size -specify the IV. -.IP \fBio\fP -Destination buffer -.IP \fBio_size\fP -Size of the destination buffer +.IP \fBNCR_ATTR_IV\fP +Optional, an empty IV is used if not present. +.IP \fBNCR_ATTR_WRAPPING_ALGORITHM\fP +Mandatory. .RE .IP -Currently only secret keys can be wrapped, -using one of the above-mentioned AES-based algorithms. +Only secret keys can be currently wrapped. -On success, the -.B io_size -member is set to the size of the wrapped key. +On success, size of the wrapped key is returned. .TP .B NCRIO_KEY_UNWRAP Unwrap user-space data into a kernel-space key using another key. -The parameter points to \fBstruct ncr_key_wrap_st\fP, which specifies: +The parameter points to \fBstruct ncr_key_unwrap\fP, +which specifies the destination key in the +.B dest_key +member, +the wrapping key in the +.B wrapping_key +member, +and the wrapped data in the +.B data +and +.B data_size +members. + +The following input attributes are recognized: .RS -.IP \fBalgorithm\fP -The wrapping algorithm to use. -.IP \fBkeytowrap\fP -The descriptor of the target key object -.IP \fBkey\fP -The descriptor of the key used for wrapping -.IP \fBparams\fP -Key type-specific parameters. -For the currently supported wrapping algorithms, -.B params.params.cipher.iv -and -.B params.params.cipher.iv_size -specify the IV. -.IP \fBio\fP -Pointer to the wrapped key -.IP \fBio_size\fP -Size of the wrapped key +.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_WRAPPING_ALGORITHM\fP +Mandatory. .RE .IP @@ -319,54 +458,42 @@ Only keys with the .B NCR_KEY_FLAG_WRAPPABLE flag can be wrapped using this operation. -The parameter points to \fBstruct ncr_key_storage_wrap_st\fP, which specifies: - -.RS -.IP \fBkeytowrap\fP -The descriptor of the key to wrap -.IP \fBio\fP -Destination buffer -.IP \fBio_size\fP -Size of the destination buffer -.RE +The parameter points to \fBstruct ncr_key_storage_wrap\fP, +which specifies the key to wrap in the +.B key +member, +and a buffer for the wrapped data in the +.B buffer +and +.B buffer_size +members. -.IP -On success, the -.B io_size -member is set to the size of the wrapped key. +On success, size of the wrapped key is returned. Both symmetric and asymmetric keys can be wrapped using this operation. -The wrapped data includes the following information in addition to the raw key -material: - -.RS -.IP \(bu -Key type -.IP \(bu -Key flags -.IP \(bu -Key algorithm -.IP \(bu -"Persistent" key ID. -.RE +The wrapped data includes data corresponding the +\fBNCR_ATTR_ALGORITHM\fP, \fBNCR_ATTR_KEY_FLAGS\fP, +.B NCR_ATTR_KEY_TYPE +and +.B NCR_ATTR_KEY_ID +attributes +in addition to the raw key material: .TP .B NCRIO_KEY_STORAGE_UNWRAP Unwrap key and associated metadata created using \fBNCRIO_KEY_STORAGE_WRAP\fP, and restore the information into a specified key object. -The parameter points to \fBstruct ncr_key_storage_wrap_st\fP, which specifies: - -.RS -.IP \fBkeytowrap\fP -The target key descriptor -.IP \fBio\fP -Wrapped data -.IP \fBio_size\fP -Size of the wrapped data -.RE +The parameter points to \fBstruct ncr_key_storage_unwrap\fP, +which specifies the destination key in the +.B key +member +and the wrapped data in the +.B data +and +.B data_size +members. -.IP See .B NCRIO_KEY_STORAGE_WRAP above for the list of attributes that will be restored. @@ -375,23 +502,49 @@ above for the list of attributes that will be restored. .B NCRIO_SESSION_INIT Allocate a session for performing crypto operations. -The parameter points to \fBstruct ncr_session_st\fP, which specifies: - -.RS -.IP \fBalgorithm\fP -The crypto algorithm to use. -.IP \fBkey\fP -The key to use for the operation, if required. -.IP \fBparams\fP -Parameters for the operation. -For symmetric ciphers, the IV. -For RSA operations, the format, used hash algorithms and PSS salt length. -for DSA, the signature hash algorithm. -.IP \fBop\fP -The operation to perform, one of \fBNCR_OP_ENCRYPT\fP, \fBNCR_OP_DECRYPT\fP, -\fBNCR_OP_SIGN\fP and \fBNCR_OP_VERIFY\FP. Use +The parameter points to \fBstruct ncr_session_init\fP, +which specifies the operation to perform, +one of \fBNCR_OP_ENCRYPT\fP, \fBNCR_OP_DECRYPT\fP, +.B NCR_OP_SIGN +and \fBNCR_OP_VERIFY\fP, +in the +.B op +member. +Use .B NCR_OP_SIGN for computing an unkeyed hash as well as keyed hashes and signatures. + +The following input attributes are recognized: + +.RS +.IP \fBNCR_ATTR_ALGORITHM\fP +Mandatory. +.IP \fBNCR_ATTR_IV\fP +Mandatory for some operations and algorithms. +.IP \fBNCR_ATTR_KEY\fP +Mandatory for some operations and algorithms. +An 32-bit unsigned integer in native byte order +specifying the key to use for the operation. +.IP \fBNCR_ATTR_RSA_ENCODING_METHOD\fP +Mandatory for RSA. +An 32-bit unsigned integer in native byte order +specifying a RSA encoding method, +one of \fBRSA_PKCS1_V1_5\fP, +.B RSA_PKCS1_OAEP +and \fBRSA_PKCS1_PSS\fP. +.IP \fBNCR_ATTR_RSA_OAEP_HASH_ALGORITHM\fP +Mandatory for RSA with \fBRSA_PKCS1_OAEP\fP. +A NUL-terminated string specifying a hash algorithm used in the +OAEP encoding method. +.IP \fBNCR_ATTR_RSA_PSS_SALT_LENGTH\fP +For RSA with \fBRSA_PKCS1_PSS\fP. +An 32-bit unsigned integer in native byte order +specifying the PSS salt length. +Optional, defaults to 0. +.IP \fBNCR_ATTR_SIGNATURE_HASH_ALGORITHM\fP +Mandatory for some operations and algorithms. +A NUL-terminated string specifying a hash algorithm underlying a signature, +using the same formats as \fBNCR_ATTR_ALGORITHM\fP. .RE .IP @@ -399,9 +552,7 @@ On success, an integer descriptor for the created session (valid within the current .I /dev/crypto namespace) -is stored into the -.B ses -member. +is returned. .TP .B NCRIO_SESSION_UPDATE @@ -410,31 +561,49 @@ Update an existing crypto session with new data or perform a single operation using the session context (for operations, such as public key encryption, that work on separate units of data). -The parameter points to \fBstruct ncr_session_op_st\fP, which specifies: +The parameter points to \fBstruct ncr_session_update\fP, +which specifies the descriptor of the session in the +.B ses +member. + +The following input attributes are recognized: .RS -.IP \fBses\fP -The integer descriptor of the session. -.IP \fBtype\fP -Type of the data references used for this operation, either -.B NCR_KEY_DATA -or -.B NCR_DIRECT_DATA. -.IP "\fBdata.udata.input\fP, \fBdata.udata.input_size\fP" -If \fBtype == NCR_DIRECT_DATA\fP, input data for the operation. -.IP \fBdata.kdata.input\fP -If \fBtype == NCR_KEY_DATA\fP, integer key descriptor serving as input for -the operation. +.IP \fBNCR_ATTR_UPDATE_INPUT_DATA\fP +A +.B struct ncr_session_input_data +specifying input for the operation in its +.B data +and +.B data_size +members. +.IP \fBNCR_ATTR_UPDATE_INPUT_KEY_AS_DATA\fP +An 32-bit unsigned integer in native byte order +specifying the key descriptor serving as input for the operation. This can be currently used only to compute or verify a signature or hash of a symmetric key: the keying material is directly used as input data for the underlying hash. -.IP "\fBdata.udata.output\fP, \fBdata,udata.output_size\fP" -If \fBtype == NCR_DIRECT_DATA\fP, output buffer for the operation. -.IP "\fBdata.kdata.output\fP, \fBdata,kdata.output_size\fP" -If \fBtype == NCR_KEY_DATA\fP, output buffer for the operation. +.IP \fBNCR_ATTR_UPDATE_OUTPUT_BUFFER\fP +Mandatory for some operations and algorithms. +A +.B struct ncr_session_output_buffer +specifying buffer for operation output in its +.B buffer +and +.B buffer_size +members. +On success the size of output is written to the variable pointed to by the +.B result_size_ptr +member. .RE .IP +It is mandatory to include one of the +.B NCR_ATTR_UPDATE_INPUT_DATA +and +.B NCR_ATTR_UPDATE_INPUT_KEY_AS_DATA +attributes. + For the .B NCR_OP_ENCRYPT and @@ -445,10 +614,6 @@ resulting in an output data block of the same size; for operations using public-key cryptography, a single operation is performed on the input data, resulting in output data. -In both cases, -the relevant -.B output_data -member is set to the size of valid output data on success. For the .B NCR_OP_SIGN @@ -462,14 +627,36 @@ no output data is produced. .B NCRIO_SESSION_FINAL Finalize an existing crypto session and deallocate it. -The parameter points to \fBstruct ncr_session_op_st\fP, as described in the -.B NCRIO_SESSION_UPDATE -section above. -If the parameter specifies valid input data, -it is processed as if using \fBNCRIO_SESSION_UPDATE\fP; +The parameter points to \fBstruct ncr_session_final\fP, +which specifies the descriptor of the session in the +.B ses +member. + +If one of the +.B NCR_ATTR_UPDATE_INPUT_DATA +and +.B NCR_ATTR_UPDATE_INPUT_KEY_AS_DATA +attributes is present, +all attributes are first processed as if using \fBNCRIO_SESSION_UPDATE\fP; thus, the last update operation can be performed together with the finalization in one step. +The following input attributes are recognized: + +.RS +.IP \fBNCR_ATTR_FINAL_INPUT_DATA\fP +Mandatory for some operations and algorithms. +A +.B struct ncr_session_input_data +as described above, specifying input for the operation. +.IP \fBNCR_ATTR_FINAL_OUTPUT_BUFFER\fP +Mandatory for some operations and algorithms. +A +.B struct ncr_session_output_buffer +as described above, specifying buffer for operation output. +.RE + +.IP There is no specific finalization operation performed for .B NCR_OP_ENCRYPT and \fBNCR_OP_DECRYPT\fP. @@ -482,23 +669,19 @@ the signature is created and written as output data. For the .B NCR_OP_VERIFY operation, -a signature specified as input using the -.I output data -fields is verified; -the result of this operation -(\fBNCR_SUCCESS\fP or \fBNCR_VERIFICATION_FAILED\fP) -will be stored into the -.B err -member. -(Note that the +a signature specified as input is verified and +the result of this operation is returned: +non-zero for a valid signature, zero for an invalid signature. +Note that the .BR ioctl (2) -operation will indicate success even if the signature verification fails, -as long all inputs were specified correctly.) +operation return value will be non-negative, i.e. "success", +even if the signature verification fails, +as long all inputs were specified correctly. The session will be deallocated even if the .B NCRIO_SESSION_FINAL operation reports an error, -as long as valid session descriptor was specified. +as long as a valid session descriptor was specified. .TP .B NCRIO_SESSION_ONCE @@ -507,18 +690,19 @@ allocating a temporary session, supplying a single instance of data, and finalizing the session in one operation. -The parameter points to \fBstruct ncr_session_once_op_st\fP, -which includes arguments for one +The parameter points to \fBstruct ncr_session_once\fP, +which specifies the operation to perform in the +.B op +member. + +The attributes handled as if by passing to a .B NCRIO_SESSION_INIT -and one +operation followed by a .B NCRIO_SESSION_FINAL -operation. -The -.B ses -member for the +operation, +and the return value of the .B NCRIO_SESSION_FINAL -sub-operation is ignored, -the sub-operation automatically uses the temporary session. +is returned on success. .TP .B NCRIO_MASTER_KEY_SET @@ -530,15 +714,14 @@ Once a master key is set, it can be changed only by rebooting the system and setting a different key. -The parameter points to \fBstruct ncr_master_key_st\fP, which specifies: -.RS -.IP \fBkey\fP -Pointer to the key material in user space. -.IP \fBkey_size\fP -Size of the key material in bytes. -.RE +The parameter points to \fBstruct ncr_master_key_set\fP, +which specifies the key material in user space using the +.B key +and +.B key_size +members. -Currently only an AES key with size 16, 24, or 32 bytes is acceptable. +Only an AES key with size 16, 24, or 32 bytes is currently acceptable. .SH CONFIGURATION The -- cgit From aad8b544d56557730e5a585896ccaa60a7662a45 Mon Sep 17 00:00:00 2001 From: Miloslav Trmač Date: Mon, 23 Aug 2010 20:50:16 +0200 Subject: Fix ioctl direction --- ncr.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ncr.h b/ncr.h index 180aa3a9007..e6c11360412 100644 --- a/ncr.h +++ b/ncr.h @@ -167,7 +167,7 @@ struct ncr_key_export { /* import a secret key */ #define NCRIO_KEY_IMPORT _IOWR('c', 210, struct ncr_key_import) -#define NCRIO_KEY_DEINIT _IOR ('c', 215, ncr_key_t) +#define NCRIO_KEY_DEINIT _IOW('c', 215, ncr_key_t) /* Key wrap ioctls */ -- cgit From cc60983067194a6e7bdc12c7771aeaff6762a253 Mon Sep 17 00:00:00 2001 From: Miloslav Trmač Date: Mon, 23 Aug 2010 20:56:11 +0200 Subject: Renumber ioctls - The ranges in Documentation/ioctl/ioctl-number.txt are allocated in hexadecimal digits - The operation identifer must be <= 255 - Leave smaller spaces to give other drivers a chance --- ncr.h | 35 +++++++++++++++++------------------ 1 file changed, 17 insertions(+), 18 deletions(-) diff --git a/ncr.h b/ncr.h index e6c11360412..47981d1ffd6 100644 --- a/ncr.h +++ b/ncr.h @@ -152,22 +152,21 @@ struct ncr_key_export { __NL_ATTRIBUTES; }; -#define NCRIO_KEY_INIT _IO('c', 204) +#define NCRIO_KEY_INIT _IO('c', 0xC0) /* generate a secret key */ -#define NCRIO_KEY_GENERATE _IOWR('c', 205, struct ncr_key_generate) +#define NCRIO_KEY_GENERATE _IOWR('c', 0xC1, struct ncr_key_generate) /* generate a public key pair */ -#define NCRIO_KEY_GENERATE_PAIR _IOWR('c', 206, struct ncr_key_generate_pair) +#define NCRIO_KEY_GENERATE_PAIR _IOWR('c', 0xC2, struct ncr_key_generate_pair) /* derive a new key from an old one */ -#define NCRIO_KEY_DERIVE _IOWR('c', 207, struct ncr_key_derive) +#define NCRIO_KEY_DERIVE _IOWR('c', 0xC3, struct ncr_key_derive) /* return information on a key */ -#define NCRIO_KEY_GET_INFO _IOWR('c', 208, struct ncr_key_get_info) - +#define NCRIO_KEY_GET_INFO _IOWR('c', 0xC4, struct ncr_key_get_info) /* export a secret key */ -#define NCRIO_KEY_EXPORT _IOWR('c', 209, struct ncr_key_export) +#define NCRIO_KEY_EXPORT _IOWR('c', 0xC5, struct ncr_key_export) /* import a secret key */ -#define NCRIO_KEY_IMPORT _IOWR('c', 210, struct ncr_key_import) +#define NCRIO_KEY_IMPORT _IOWR('c', 0xC6, struct ncr_key_import) -#define NCRIO_KEY_DEINIT _IOW('c', 215, ncr_key_t) +#define NCRIO_KEY_DEINIT _IOW('c', 0xC7, ncr_key_t) /* Key wrap ioctls */ @@ -189,8 +188,8 @@ struct ncr_key_unwrap { __NL_ATTRIBUTES; }; -#define NCRIO_KEY_WRAP _IOWR('c', 250, struct ncr_key_wrap) -#define NCRIO_KEY_UNWRAP _IOWR('c', 251, struct ncr_key_unwrap) +#define NCRIO_KEY_WRAP _IOWR('c', 0xC8, struct ncr_key_wrap) +#define NCRIO_KEY_UNWRAP _IOWR('c', 0xC9, struct ncr_key_unwrap) /* Internal ops */ struct ncr_master_key_set { @@ -200,7 +199,7 @@ struct ncr_master_key_set { __NL_ATTRIBUTES; }; -#define NCRIO_MASTER_KEY_SET _IOWR('c', 260, struct ncr_master_key_set) +#define NCRIO_MASTER_KEY_SET _IOWR('c', 0xCA, struct ncr_master_key_set) /* These are similar to key_wrap and unwrap except that will store some extra * fields to be able to recover a key */ @@ -220,8 +219,8 @@ struct ncr_key_storage_unwrap { __NL_ATTRIBUTES; }; -#define NCRIO_KEY_STORAGE_WRAP _IOWR('c', 261, struct ncr_key_storage_wrap) -#define NCRIO_KEY_STORAGE_UNWRAP _IOWR('c', 262, struct ncr_key_storage_wrap) +#define NCRIO_KEY_STORAGE_WRAP _IOWR('c', 0xCB, struct ncr_key_storage_wrap) +#define NCRIO_KEY_STORAGE_UNWRAP _IOWR('c', 0xCC, struct ncr_key_storage_wrap) /* Crypto Operations ioctls */ @@ -271,11 +270,11 @@ struct ncr_session_once { __NL_ATTRIBUTES; }; -#define NCRIO_SESSION_INIT _IOWR('c', 300, struct ncr_session_init) -#define NCRIO_SESSION_UPDATE _IOWR('c', 301, struct ncr_session_update) -#define NCRIO_SESSION_FINAL _IOWR('c', 302, struct ncr_session_final) +#define NCRIO_SESSION_INIT _IOWR('c', 0xD0, struct ncr_session_init) +#define NCRIO_SESSION_UPDATE _IOWR('c', 0xD1, struct ncr_session_update) +#define NCRIO_SESSION_FINAL _IOWR('c', 0xD2, struct ncr_session_final) /* everything in one call */ -#define NCRIO_SESSION_ONCE _IOWR('c', 303, struct ncr_session_once) +#define NCRIO_SESSION_ONCE _IOWR('c', 0xD3, struct ncr_session_once) #endif -- cgit From 5ec167e240a8002bba3cc37e22553c888c7d4133 Mon Sep 17 00:00:00 2001 From: Miloslav Trmač Date: Wed, 25 Aug 2010 00:35:48 +0200 Subject: Fix wrapping test conversions --- examples/ncr.c | 8 +++++--- examples/pk.c | 9 ++++++--- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/examples/ncr.c b/examples/ncr.c index 9112873c5aa..a7d34f0e881 100644 --- a/examples/ncr.c +++ b/examples/ncr.c @@ -606,7 +606,8 @@ test_ncr_wrap_key2(int cfd) } /* convert it to key */ - if (ioctl(cfd, NCRIO_KEY_INIT, &key)) { + key = ioctl(cfd, NCRIO_KEY_INIT); + if (key == -1) { perror("ioctl(NCRIO_KEY_INIT)"); return 1; } @@ -638,7 +639,8 @@ test_ncr_wrap_key2(int cfd) /* convert it to key */ - if (ioctl(cfd, NCRIO_KEY_INIT, &key2)) { + key2 = ioctl(cfd, NCRIO_KEY_INIT); + if (key2 == -1) { perror("ioctl(NCRIO_KEY_INIT)"); return 1; } @@ -680,7 +682,7 @@ test_ncr_wrap_key2(int cfd) strcpy(kwrap.algo, NCR_WALG_AES_RFC3394); ret = ioctl(cfd, NCRIO_KEY_WRAP, &kwrap); - if (ret < 0) { + if (ret >= 0) { fprintf(stderr, "Error: %s:%d\n", __func__, __LINE__); /* wrapping shouldn't have been allowed */ return 1; diff --git a/examples/pk.c b/examples/pk.c index 1ad5873f17d..6acbadf12b0 100644 --- a/examples/pk.c +++ b/examples/pk.c @@ -650,13 +650,15 @@ test_ncr_wrap_key3(int cfd) fflush(stdout); /* convert it to key */ - if (ioctl(cfd, NCRIO_KEY_INIT, &privkey)) { + privkey = ioctl(cfd, NCRIO_KEY_INIT); + if (privkey == -1) { fprintf(stderr, "Error: %s:%d\n", __func__, __LINE__); perror("ioctl(NCRIO_KEY_INIT)"); return 1; } - if (ioctl(cfd, NCRIO_KEY_INIT, &pubkey)) { + pubkey = ioctl(cfd, NCRIO_KEY_INIT); + if (pubkey == -1) { fprintf(stderr, "Error: %s:%d\n", __func__, __LINE__); perror("ioctl(NCRIO_KEY_INIT)"); return 1; @@ -669,7 +671,8 @@ test_ncr_wrap_key3(int cfd) } /* make a wrapping key */ - if (ioctl(cfd, NCRIO_KEY_INIT, &key)) { + key = ioctl(cfd, NCRIO_KEY_INIT); + if (key == -1) { perror("ioctl(NCRIO_KEY_INIT)"); return 1; } -- cgit From 6db12e213dfd6793203c9875e6765c7d27f3dd1f Mon Sep 17 00:00:00 2001 From: Miloslav Trmač Date: Wed, 25 Aug 2010 00:53:56 +0200 Subject: Simplify key flag updates --- ncr-int.h | 2 +- ncr-key-wrap.c | 22 ++++++++------------ ncr-key.c | 63 +++++++++++++++++++++++++--------------------------------- 3 files changed, 36 insertions(+), 51 deletions(-) diff --git a/ncr-int.h b/ncr-int.h index 5e86aff5641..2baea659f4a 100644 --- a/ncr-int.h +++ b/ncr-int.h @@ -137,7 +137,7 @@ int ncr_key_derive(struct ncr_lists *lst, const struct ncr_key_derive *data, struct nlattr *tb[]); void ncr_key_clear(struct key_item_st* item); -int ncr_key_assign_flags(struct key_item_st *item, unsigned int flags); +int ncr_key_update_flags(struct key_item_st *item, const struct nlattr *nla); /* key handling */ int ncr_key_init(struct ncr_lists *lst); diff --git a/ncr-key-wrap.c b/ncr-key-wrap.c index c409bb93fda..8ca23b8b20f 100644 --- a/ncr-key-wrap.c +++ b/ncr-key-wrap.c @@ -471,13 +471,10 @@ const uint8_t *iv; goto cleanup; } - nla = tb[NCR_ATTR_KEY_FLAGS]; - if (nla != NULL) { - ret = ncr_key_assign_flags(output, nla_get_u32(nla)); - if (ret != 0) { - err(); - goto cleanup; - } + ret = ncr_key_update_flags(output, tb[NCR_ATTR_KEY_FLAGS]); + if (ret != 0) { + err(); + goto cleanup; } memset(&output->key, 0, sizeof(output->key)); @@ -889,13 +886,10 @@ static int key_from_packed_data(struct nlattr *tb[], struct key_item_st *key, } key->type = nla_get_u32(nla); - nla = tb[NCR_ATTR_KEY_FLAGS]; - if (nla != NULL) { - ret = ncr_key_assign_flags(key, nla_get_u32(nla)); - if (ret != 0) { - err(); - return ret; - } + ret = ncr_key_update_flags(key, tb[NCR_ATTR_KEY_FLAGS]); + if (ret != 0) { + err(); + return ret; } if (key->type == NCR_KEY_TYPE_SECRET) { diff --git a/ncr-key.c b/ncr-key.c index 4942bc451d0..a82c907eb5e 100644 --- a/ncr-key.c +++ b/ncr-key.c @@ -287,8 +287,13 @@ fail: } -int ncr_key_assign_flags(struct key_item_st* item, unsigned int flags) +int ncr_key_update_flags(struct key_item_st* item, const struct nlattr *nla) { + uint32_t flags; + + if (nla == NULL) + return 0; + flags = nla_get_u32(nla); if (!capable(CAP_SYS_ADMIN) && (flags & NCR_KEY_FLAG_WRAPPING) != 0) return -EPERM; item->flags = flags; @@ -341,13 +346,10 @@ size_t tmp_size; goto fail; } - nla = tb[NCR_ATTR_KEY_FLAGS]; - if (nla != NULL) { - ret = ncr_key_assign_flags(item, nla_get_u32(nla)); - if (ret < 0) { - err(); - goto fail; - } + ret = ncr_key_update_flags(item, tb[NCR_ATTR_KEY_FLAGS]); + if (ret < 0) { + err(); + goto fail; } nla = tb[NCR_ATTR_KEY_ID]; @@ -434,13 +436,10 @@ size_t size; ncr_key_clear(item); /* we generate only secret keys */ - nla = tb[NCR_ATTR_KEY_FLAGS]; - if (nla != NULL) { - ret = ncr_key_assign_flags(item, nla_get_u32(nla)); - if (ret < 0) { - err(); - goto fail; - } + ret = ncr_key_update_flags(item, tb[NCR_ATTR_KEY_FLAGS]); + if (ret < 0) { + err(); + goto fail; } algo = _ncr_nla_to_properties(tb[NCR_ATTR_ALGORITHM]); @@ -662,7 +661,6 @@ int ncr_key_generate_pair(struct ncr_lists *lst, const struct ncr_key_generate_pair *gen, struct nlattr *tb[]) { -const struct nlattr *nla; struct key_item_st* private = NULL; struct key_item_st* public = NULL; int ret; @@ -692,18 +690,15 @@ int ret; } public->type = public->algorithm->key_type; private->type = NCR_KEY_TYPE_PRIVATE; - nla = tb[NCR_ATTR_KEY_FLAGS]; - if (nla != NULL) { - ret = ncr_key_assign_flags(private, nla_get_u32(nla)); - if (ret < 0) { - err(); - goto fail; - } - ret = ncr_key_assign_flags(public, nla_get_u32(nla)); - if (ret < 0) { - err(); - goto fail; - } + ret = ncr_key_update_flags(private, tb[NCR_ATTR_KEY_FLAGS]); + if (ret < 0) { + err(); + goto fail; + } + ret = ncr_key_update_flags(public, tb[NCR_ATTR_KEY_FLAGS]); + if (ret < 0) { + err(); + goto fail; } public->flags |= (NCR_KEY_FLAG_EXPORTABLE|NCR_KEY_FLAG_WRAPPABLE); @@ -736,7 +731,6 @@ fail: int ncr_key_derive(struct ncr_lists *lst, const struct ncr_key_derive *data, struct nlattr *tb[]) { -const struct nlattr *nla; int ret; struct key_item_st* key = NULL; struct key_item_st* newkey = NULL; @@ -763,13 +757,10 @@ struct key_item_st* newkey = NULL; ncr_key_clear(newkey); - nla = tb[NCR_ATTR_KEY_FLAGS]; - if (nla != NULL) { - ret = ncr_key_assign_flags(newkey, nla_get_u32(nla)); - if (ret < 0) { - err(); - goto fail; - } + ret = ncr_key_update_flags(newkey, tb[NCR_ATTR_KEY_FLAGS]); + if (ret < 0) { + err(); + goto fail; } switch (key->type) { -- cgit From a3e8fa0499ea7d779dfeb36fe916445aebac0ceb Mon Sep 17 00:00:00 2001 From: Miloslav Trmač Date: Wed, 25 Aug 2010 01:41:13 +0200 Subject: Make some session functions static --- ncr-int.h | 3 --- ncr-sessions.c | 8 +++++--- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/ncr-int.h b/ncr-int.h index 5e86aff5641..9ae0ea120b3 100644 --- a/ncr-int.h +++ b/ncr-int.h @@ -186,9 +186,6 @@ int ncr_key_storage_unwrap(struct ncr_lists *lst, struct nlattr *tb[]); /* sessions */ -struct session_item_st* ncr_session_new(struct ncr_lists *lst); -void _ncr_sessions_item_put( struct session_item_st* item); -struct session_item_st* ncr_sessions_item_get(struct ncr_lists *lst, ncr_session_t desc); void ncr_sessions_list_deinit(struct ncr_lists *lst); int ncr_session_init(struct ncr_lists *lists, diff --git a/ncr-sessions.c b/ncr-sessions.c index 41f8a4c9000..ee32e691ead 100644 --- a/ncr-sessions.c +++ b/ncr-sessions.c @@ -31,6 +31,7 @@ #include #include +static void _ncr_sessions_item_put(struct session_item_st *item); static int _ncr_session_update_key(struct ncr_lists *lists, ncr_session_t ses, struct nlattr *tb[]); static void _ncr_session_remove(struct ncr_lists *lst, ncr_session_t desc); @@ -54,7 +55,8 @@ void ncr_sessions_list_deinit(struct ncr_lists *lst) } /* returns the data item corresponding to desc */ -struct session_item_st* ncr_sessions_item_get(struct ncr_lists *lst, ncr_session_t desc) +static struct session_item_st *ncr_sessions_item_get(struct ncr_lists *lst, + ncr_session_t desc) { struct session_item_st* item; @@ -71,7 +73,7 @@ struct session_item_st* item; return NULL; } -void _ncr_sessions_item_put( struct session_item_st* item) +static void _ncr_sessions_item_put(struct session_item_st *item) { if (atomic_dec_and_test(&item->refcnt)) { cryptodev_cipher_deinit(&item->cipher); @@ -85,7 +87,7 @@ void _ncr_sessions_item_put( struct session_item_st* item) } } -struct session_item_st* ncr_session_new(struct ncr_lists *lst) +static struct session_item_st *ncr_session_new(struct ncr_lists *lst) { struct session_item_st* sess; -- cgit From 0916e9e52d02e31582ff326dd5327652515c839a Mon Sep 17 00:00:00 2001 From: Miloslav Trmač Date: Wed, 25 Aug 2010 01:41:13 +0200 Subject: Make some session functions static --- ncr-int.h | 3 --- ncr-sessions.c | 8 +++++--- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/ncr-int.h b/ncr-int.h index 2baea659f4a..0b28be5ddfb 100644 --- a/ncr-int.h +++ b/ncr-int.h @@ -186,9 +186,6 @@ int ncr_key_storage_unwrap(struct ncr_lists *lst, struct nlattr *tb[]); /* sessions */ -struct session_item_st* ncr_session_new(struct ncr_lists *lst); -void _ncr_sessions_item_put( struct session_item_st* item); -struct session_item_st* ncr_sessions_item_get(struct ncr_lists *lst, ncr_session_t desc); void ncr_sessions_list_deinit(struct ncr_lists *lst); int ncr_session_init(struct ncr_lists *lists, diff --git a/ncr-sessions.c b/ncr-sessions.c index 41f8a4c9000..ee32e691ead 100644 --- a/ncr-sessions.c +++ b/ncr-sessions.c @@ -31,6 +31,7 @@ #include #include +static void _ncr_sessions_item_put(struct session_item_st *item); static int _ncr_session_update_key(struct ncr_lists *lists, ncr_session_t ses, struct nlattr *tb[]); static void _ncr_session_remove(struct ncr_lists *lst, ncr_session_t desc); @@ -54,7 +55,8 @@ void ncr_sessions_list_deinit(struct ncr_lists *lst) } /* returns the data item corresponding to desc */ -struct session_item_st* ncr_sessions_item_get(struct ncr_lists *lst, ncr_session_t desc) +static struct session_item_st *ncr_sessions_item_get(struct ncr_lists *lst, + ncr_session_t desc) { struct session_item_st* item; @@ -71,7 +73,7 @@ struct session_item_st* item; return NULL; } -void _ncr_sessions_item_put( struct session_item_st* item) +static void _ncr_sessions_item_put(struct session_item_st *item) { if (atomic_dec_and_test(&item->refcnt)) { cryptodev_cipher_deinit(&item->cipher); @@ -85,7 +87,7 @@ void _ncr_sessions_item_put( struct session_item_st* item) } } -struct session_item_st* ncr_session_new(struct ncr_lists *lst) +static struct session_item_st *ncr_session_new(struct ncr_lists *lst) { struct session_item_st* sess; -- cgit From a3198b9448140afd15169745c5260cf828e1a82f Mon Sep 17 00:00:00 2001 From: Miloslav Trmač Date: Wed, 25 Aug 2010 02:00:12 +0200 Subject: Separate session ID allocation from object creation --- ncr-sessions.c | 72 ++++++++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 57 insertions(+), 15 deletions(-) diff --git a/ncr-sessions.c b/ncr-sessions.c index ee32e691ead..7230c34a652 100644 --- a/ncr-sessions.c +++ b/ncr-sessions.c @@ -54,6 +54,49 @@ void ncr_sessions_list_deinit(struct ncr_lists *lst) mutex_unlock(&lst->session_idr_mutex); } +/* Allocate a descriptor without making a sesssion available to userspace. */ +static ncr_session_t session_alloc_desc(struct ncr_lists *lst) +{ + int ret, desc; + + mutex_lock(&lst->session_idr_mutex); + if (idr_pre_get(&lst->session_idr, GFP_KERNEL) == 0) { + ret = -ENOMEM; + goto end; + } + /* idr_pre_get() should preallocate enough, and, due to + session_idr_mutex, nobody else can use the preallocated data. + Therefore the loop recommended in idr_get_new() documentation is not + necessary. */ + ret = idr_get_new(&lst->session_idr, NULL, &desc); + if (ret != 0) + goto end; + ret = desc; +end: + mutex_unlock(&lst->session_idr_mutex); + return ret; +} + +/* Drop a pre-allocated, unpublished session descriptor */ +static void session_drop_desc(struct ncr_lists *lst, ncr_session_t desc) +{ + mutex_lock(&lst->session_idr_mutex); + idr_remove(&lst->session_idr, desc); + mutex_unlock(&lst->session_idr_mutex); +} + +/* Make a session descriptor visible in user-space */ +static void session_publish(struct ncr_lists *lst, struct session_item_st *sess) +{ + void *old; + + atomic_inc(&sess->refcnt); + mutex_lock(&lst->session_idr_mutex); + old = idr_replace(&lst->session_idr, sess, sess->desc); + mutex_unlock(&lst->session_idr_mutex); + BUG_ON(old != NULL); +} + /* returns the data item corresponding to desc */ static struct session_item_st *ncr_sessions_item_get(struct ncr_lists *lst, ncr_session_t desc) @@ -61,6 +104,7 @@ static struct session_item_st *ncr_sessions_item_get(struct ncr_lists *lst, struct session_item_st* item; mutex_lock(&lst->session_idr_mutex); + /* item may be NULL for pre-allocated session IDs. */ item = idr_find(&lst->session_idr, desc); if (item != NULL) { atomic_inc(&item->refcnt); @@ -87,7 +131,7 @@ static void _ncr_sessions_item_put(struct session_item_st *item) } } -static struct session_item_st *ncr_session_new(struct ncr_lists *lst) +static struct session_item_st *ncr_session_new(ncr_session_t desc) { struct session_item_st* sess; @@ -108,19 +152,8 @@ static struct session_item_st *ncr_session_new(struct ncr_lists *lst) } mutex_init(&sess->mem_mutex); - atomic_set(&sess->refcnt, 2); /* One for lst->list, one for "sess" */ - - mutex_lock(&lst->session_idr_mutex); - /* idr_pre_get() should preallocate enough, and, due to - session_idr_mutex, nobody else can use the preallocated data. - Therefore the loop recommended in idr_get_new() documentation is not - necessary. */ - if (idr_pre_get(&lst->session_idr, GFP_KERNEL) == 0 || - idr_get_new(&lst->session_idr, sess, &sess->desc) != 0) { - mutex_unlock(&lst->session_idr_mutex); - goto err_sess; - } - mutex_unlock(&lst->session_idr_mutex); + atomic_set(&sess->refcnt, 1); + sess->desc = desc; return sess; @@ -263,15 +296,23 @@ static int _ncr_session_init(struct ncr_lists *lists, ncr_crypto_op_t op, struct nlattr *tb[]) { const struct nlattr *nla; + ncr_session_t desc; struct session_item_st* ns = NULL; int ret; const struct algo_properties_st *sign_hash; - ns = ncr_session_new(lists); + desc = session_alloc_desc(lists); + if (desc < 0) { + err(); + return desc; + } + ns = ncr_session_new(desc); if (ns == NULL) { err(); + session_drop_desc(lists, desc); return -ENOMEM; } + session_publish(lists, ns); ns->op = op; ns->algorithm = _ncr_nla_to_properties(tb[NCR_ATTR_ALGORITHM]); @@ -529,6 +570,7 @@ static void _ncr_session_remove(struct ncr_lists *lst, ncr_session_t desc) struct session_item_st * item; mutex_lock(&lst->session_idr_mutex); + /* item may be NULL for pre-allocated session IDs. */ item = idr_find(&lst->session_idr, desc); if (item != NULL) idr_remove(&lst->session_idr, desc); /* Steal the reference */ -- cgit From d50cc4f8c117aa971960e498536335b6d6194787 Mon Sep 17 00:00:00 2001 From: Miloslav Trmač Date: Wed, 25 Aug 2010 02:05:33 +0200 Subject: Publish sessions only after initialization --- ncr-sessions.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ncr-sessions.c b/ncr-sessions.c index 7230c34a652..885b63052b5 100644 --- a/ncr-sessions.c +++ b/ncr-sessions.c @@ -312,7 +312,6 @@ static int _ncr_session_init(struct ncr_lists *lists, ncr_crypto_op_t op, session_drop_desc(lists, desc); return -ENOMEM; } - session_publish(lists, ns); ns->op = op; ns->algorithm = _ncr_nla_to_properties(tb[NCR_ATTR_ALGORITHM]); @@ -490,11 +489,12 @@ static int _ncr_session_init(struct ncr_lists *lists, ncr_crypto_op_t op, goto fail; } + session_publish(lists, ns); ret = ns->desc; fail: if (ret < 0) { - _ncr_session_remove(lists, ns->desc); + session_drop_desc(lists, desc); } _ncr_sessions_item_put(ns); -- cgit From 24a20d546d227083a5304a3c82cba69d8334f80c Mon Sep 17 00:00:00 2001 From: Miloslav Trmač Date: Wed, 25 Aug 2010 02:27:16 +0200 Subject: Move session lookup and locking out of low-level functions While doing this, also lock mem_mutex during _ncr_session_update_key. --- ncr-sessions.c | 83 ++++++++++++++++++++++++++++++++++------------------------ 1 file changed, 49 insertions(+), 34 deletions(-) diff --git a/ncr-sessions.c b/ncr-sessions.c index 885b63052b5..d711ba76721 100644 --- a/ncr-sessions.c +++ b/ncr-sessions.c @@ -32,7 +32,8 @@ #include static void _ncr_sessions_item_put(struct session_item_st *item); -static int _ncr_session_update_key(struct ncr_lists *lists, ncr_session_t ses, +static int _ncr_session_update_key(struct ncr_lists *lists, + struct session_item_st *sess, struct nlattr *tb[]); static void _ncr_session_remove(struct ncr_lists *lst, ncr_session_t desc); @@ -702,34 +703,21 @@ static int get_userbuf2(struct session_item_st *ses, struct nlattr *tb[], } /* Called when userspace buffers are used */ -static int _ncr_session_update(struct ncr_lists *lists, ncr_session_t ses, +static int _ncr_session_update(struct session_item_st *sess, struct nlattr *tb[], int compat) { int ret; - struct session_item_st* sess; struct scatterlist *isg = NULL; struct scatterlist *osg = NULL; unsigned osg_cnt=0, isg_cnt=0; size_t isg_size = 0, osg_size; struct ncr_session_output_buffer out; - sess = ncr_sessions_item_get(lists, ses); - if (sess == NULL) { - err(); - return -EINVAL; - } - - if (mutex_lock_interruptible(&sess->mem_mutex)) { - err(); - _ncr_sessions_item_put(sess); - return -ERESTARTSYS; - } - ret = get_userbuf2(sess, tb, &isg, &isg_cnt, &isg_size, &out, &osg, &osg_cnt, compat); if (ret < 0) { err(); - goto fail; + return ret; } switch(sess->op) { @@ -811,8 +799,6 @@ fail: release_user_pages(sess->pages, sess->available_pages); sess->available_pages = 0; } - mutex_unlock(&sess->mem_mutex); - _ncr_sessions_item_put(sess); return ret; } @@ -820,12 +806,32 @@ fail: static int try_session_update(struct ncr_lists *lists, ncr_session_t ses, struct nlattr *tb[], int compat) { + struct session_item_st *sess; + int ret; + + sess = ncr_sessions_item_get(lists, ses); + if (sess == NULL) { + err(); + return -EINVAL; + } + + if (mutex_lock_interruptible(&sess->mem_mutex)) { + err(); + ret = -ERESTARTSYS; + goto end; + } if (tb[NCR_ATTR_UPDATE_INPUT_KEY_AS_DATA] != NULL) - return _ncr_session_update_key(lists, ses, tb); + ret = _ncr_session_update_key(lists, sess, tb); else if (tb[NCR_ATTR_UPDATE_INPUT_DATA] != NULL) - return _ncr_session_update(lists, ses, tb, compat); + ret = _ncr_session_update(sess, tb, compat); + else + ret = 0; + mutex_unlock(&sess->mem_mutex); - return 0; +end: + _ncr_sessions_item_put(sess); + + return ret; } static int _ncr_session_final(struct ncr_lists *lists, ncr_session_t ses, @@ -1003,25 +1009,19 @@ fail: } /* Direct with key: Allows to hash a key */ -static int _ncr_session_update_key(struct ncr_lists *lists, ncr_session_t ses, +static int _ncr_session_update_key(struct ncr_lists *lists, + struct session_item_st* sess, struct nlattr *tb[]) { int ret; - struct session_item_st* sess; struct key_item_st* key = NULL; - sess = ncr_sessions_item_get(lists, ses); - if (sess == NULL) { - err(); - return -EINVAL; - } - /* read key */ ret = key_item_get_nla_read(&key, lists, tb[NCR_ATTR_UPDATE_INPUT_KEY_AS_DATA]); if (ret < 0) { err(); - goto fail; + return ret; } if (key->type != NCR_KEY_TYPE_SECRET) { @@ -1054,8 +1054,7 @@ static int _ncr_session_update_key(struct ncr_lists *lists, ncr_session_t ses, ret = 0; fail: - if (key) _ncr_key_item_put(key); - _ncr_sessions_item_put(sess); + _ncr_key_item_put(key); return ret; } @@ -1064,14 +1063,30 @@ int ncr_session_update(struct ncr_lists *lists, const struct ncr_session_update *op, struct nlattr *tb[], int compat) { + struct session_item_st *sess; int ret; + sess = ncr_sessions_item_get(lists, op->ses); + if (sess == NULL) { + err(); + return -EINVAL; + } + + if (mutex_lock_interruptible(&sess->mem_mutex)) { + err(); + ret = -ERESTARTSYS; + goto end; + } if (tb[NCR_ATTR_UPDATE_INPUT_DATA] != NULL) - ret = _ncr_session_update(lists, op->ses, tb, compat); + ret = _ncr_session_update(sess, tb, compat); else if (tb[NCR_ATTR_UPDATE_INPUT_KEY_AS_DATA] != NULL) - ret = _ncr_session_update_key(lists, op->ses, tb); + ret = _ncr_session_update_key(lists, sess, tb); else ret = -EINVAL; + mutex_unlock(&sess->mem_mutex); + +end: + _ncr_sessions_item_put(sess); if (unlikely(ret)) { err(); -- cgit From b6ddae6aab4f799f0df64865079ffdc5f1f24b6f Mon Sep 17 00:00:00 2001 From: Miloslav Trmač Date: Wed, 25 Aug 2010 02:33:00 +0200 Subject: Avoid duplicit lookup and locking in _try_session_update --- ncr-sessions.c | 42 +++++++++++------------------------------- 1 file changed, 11 insertions(+), 31 deletions(-) diff --git a/ncr-sessions.c b/ncr-sessions.c index d711ba76721..d5ae1dd34c1 100644 --- a/ncr-sessions.c +++ b/ncr-sessions.c @@ -803,35 +803,16 @@ fail: return ret; } -static int try_session_update(struct ncr_lists *lists, ncr_session_t ses, - struct nlattr *tb[], int compat) +static int try_session_update(struct ncr_lists *lists, + struct session_item_st *sess, struct nlattr *tb[], + int compat) { - struct session_item_st *sess; - int ret; - - sess = ncr_sessions_item_get(lists, ses); - if (sess == NULL) { - err(); - return -EINVAL; - } - - if (mutex_lock_interruptible(&sess->mem_mutex)) { - err(); - ret = -ERESTARTSYS; - goto end; - } if (tb[NCR_ATTR_UPDATE_INPUT_KEY_AS_DATA] != NULL) - ret = _ncr_session_update_key(lists, sess, tb); + return _ncr_session_update_key(lists, sess, tb); else if (tb[NCR_ATTR_UPDATE_INPUT_DATA] != NULL) - ret = _ncr_session_update(sess, tb, compat); + return _ncr_session_update(sess, tb, compat); else - ret = 0; - mutex_unlock(&sess->mem_mutex); - -end: - _ncr_sessions_item_put(sess); - - return ret; + return 0; } static int _ncr_session_final(struct ncr_lists *lists, ncr_session_t ses, @@ -850,17 +831,16 @@ static int _ncr_session_final(struct ncr_lists *lists, ncr_session_t ses, return -EINVAL; } - ret = try_session_update(lists, ses, tb, compat); - if (ret < 0) { + if (mutex_lock_interruptible(&sess->mem_mutex)) { err(); _ncr_sessions_item_put(sess); - return ret; + return -ERESTARTSYS; } - if (mutex_lock_interruptible(&sess->mem_mutex)) { + ret = try_session_update(lists, sess, tb, compat); + if (ret < 0) { err(); - _ncr_sessions_item_put(sess); - return -ERESTARTSYS; + goto fail; } switch(sess->op) { -- cgit From 9cbe1a7c208e170cca07e735099842308bedc317 Mon Sep 17 00:00:00 2001 From: Miloslav Trmač Date: Wed, 25 Aug 2010 02:44:35 +0200 Subject: Remove redundant deinitializations. _ncr_sessions_item_put() clears this all on last put. --- ncr-sessions.c | 7 ------- 1 file changed, 7 deletions(-) diff --git a/ncr-sessions.c b/ncr-sessions.c index d5ae1dd34c1..7010cf7ef13 100644 --- a/ncr-sessions.c +++ b/ncr-sessions.c @@ -975,13 +975,6 @@ fail: mutex_unlock(&sess->mem_mutex); kfree(buffer); - cryptodev_hash_deinit(&sess->hash); - if (sess->algorithm->is_symmetric) { - cryptodev_cipher_deinit(&sess->cipher); - } else { - ncr_pk_cipher_deinit(&sess->pk); - } - _ncr_sessions_item_put(sess); _ncr_session_remove(lists, ses); -- cgit From d35dc8f2ba10288b5bb369278585cd12d68a3fb3 Mon Sep 17 00:00:00 2001 From: Miloslav Trmač Date: Wed, 25 Aug 2010 02:44:35 +0200 Subject: Remove redundant deinitializations. _ncr_sessions_item_put() clears this all on last put. --- ncr-sessions.c | 7 ------- 1 file changed, 7 deletions(-) diff --git a/ncr-sessions.c b/ncr-sessions.c index ee32e691ead..f2d9b3b9e79 100644 --- a/ncr-sessions.c +++ b/ncr-sessions.c @@ -947,13 +947,6 @@ fail: mutex_unlock(&sess->mem_mutex); kfree(buffer); - cryptodev_hash_deinit(&sess->hash); - if (sess->algorithm->is_symmetric) { - cryptodev_cipher_deinit(&sess->cipher); - } else { - ncr_pk_cipher_deinit(&sess->pk); - } - _ncr_sessions_item_put(sess); _ncr_session_remove(lists, ses); -- cgit From 6aca7d2bca9cab65aa5b84de3aa735667478c289 Mon Sep 17 00:00:00 2001 From: Miloslav Trmač Date: Wed, 25 Aug 2010 02:45:09 +0200 Subject: Move session lookup and locking out of _ncr_session_final --- ncr-sessions.c | 74 ++++++++++++++++++++++++++++++++++++---------------------- 1 file changed, 46 insertions(+), 28 deletions(-) diff --git a/ncr-sessions.c b/ncr-sessions.c index 7010cf7ef13..1c12d82d8bd 100644 --- a/ncr-sessions.c +++ b/ncr-sessions.c @@ -815,32 +815,20 @@ static int try_session_update(struct ncr_lists *lists, return 0; } -static int _ncr_session_final(struct ncr_lists *lists, ncr_session_t ses, - struct nlattr *tb[], int compat) +static int _ncr_session_final(struct ncr_lists *lists, + struct session_item_st *sess, struct nlattr *tb[], + int compat) { const struct nlattr *nla; int ret; - struct session_item_st* sess; int digest_size; uint8_t digest[NCR_HASH_MAX_OUTPUT_SIZE]; void *buffer = NULL; - sess = ncr_sessions_item_get(lists, ses); - if (sess == NULL) { - err(); - return -EINVAL; - } - - if (mutex_lock_interruptible(&sess->mem_mutex)) { - err(); - _ncr_sessions_item_put(sess); - return -ERESTARTSYS; - } - ret = try_session_update(lists, sess, tb, compat); if (ret < 0) { err(); - goto fail; + return ret; } switch(sess->op) { @@ -972,12 +960,8 @@ static int _ncr_session_final(struct ncr_lists *lists, ncr_session_t ses, } fail: - mutex_unlock(&sess->mem_mutex); kfree(buffer); - _ncr_sessions_item_put(sess); - _ncr_session_remove(lists, ses); - return ret; } @@ -1073,26 +1057,60 @@ int ncr_session_final(struct ncr_lists *lists, const struct ncr_session_final *op, struct nlattr *tb[], int compat) { - return _ncr_session_final(lists, op->ses, tb, compat); + struct session_item_st *sess; + int ret; + + sess = ncr_sessions_item_get(lists, op->ses); + if (sess == NULL) { + err(); + return -EINVAL; + } + + if (mutex_lock_interruptible(&sess->mem_mutex)) { + err(); + _ncr_sessions_item_put(sess); + return -ERESTARTSYS; + } + + ret = _ncr_session_final(lists, sess, tb, compat); + + mutex_unlock(&sess->mem_mutex); + _ncr_sessions_item_put(sess); + _ncr_session_remove(lists, op->ses); + + return ret; } int ncr_session_once(struct ncr_lists *lists, const struct ncr_session_once *once, struct nlattr *tb[], int compat) { - int ret; + struct session_item_st *sess; + int ret, desc; - ret = _ncr_session_init(lists, once->op, tb); - if (ret < 0) { + desc = _ncr_session_init(lists, once->op, tb); + if (desc < 0) { err(); - return ret; + return desc; } - ret = _ncr_session_final(lists, ret, tb, compat); - if (ret < 0) { + sess = ncr_sessions_item_get(lists, desc); + if (sess == NULL) { err(); - return ret; + return -EINVAL; } + if (mutex_lock_interruptible(&sess->mem_mutex)) { + err(); + _ncr_sessions_item_put(sess); + return -ERESTARTSYS; + } + + ret = _ncr_session_final(lists, sess, tb, compat); + + mutex_unlock(&sess->mem_mutex); + _ncr_sessions_item_put(sess); + _ncr_session_remove(lists, desc); + return ret; } -- cgit From daa80bfb63be6fcab80f2d7f526976b3000572f2 Mon Sep 17 00:00:00 2001 From: Miloslav Trmač Date: Wed, 25 Aug 2010 02:56:52 +0200 Subject: Move ID handling out of _ncr_session_init --- ncr-sessions.c | 57 +++++++++++++++++++++++++++++++++++---------------------- 1 file changed, 35 insertions(+), 22 deletions(-) diff --git a/ncr-sessions.c b/ncr-sessions.c index 1c12d82d8bd..ab4c9971719 100644 --- a/ncr-sessions.c +++ b/ncr-sessions.c @@ -293,25 +293,20 @@ static int key_item_get_nla_read(struct key_item_st **st, return ret; } -static int _ncr_session_init(struct ncr_lists *lists, ncr_crypto_op_t op, - struct nlattr *tb[]) +static struct session_item_st *_ncr_session_init(struct ncr_lists *lists, + ncr_session_t desc, + ncr_crypto_op_t op, + struct nlattr *tb[]) { const struct nlattr *nla; - ncr_session_t desc; - struct session_item_st* ns = NULL; + struct session_item_st *ns; int ret; const struct algo_properties_st *sign_hash; - desc = session_alloc_desc(lists); - if (desc < 0) { - err(); - return desc; - } ns = ncr_session_new(desc); if (ns == NULL) { err(); - session_drop_desc(lists, desc); - return -ENOMEM; + return ERR_PTR(-ENOMEM); } ns->op = op; @@ -490,23 +485,38 @@ static int _ncr_session_init(struct ncr_lists *lists, ncr_crypto_op_t op, goto fail; } - session_publish(lists, ns); - ret = ns->desc; + return ns; fail: - if (ret < 0) { - session_drop_desc(lists, desc); - } _ncr_sessions_item_put(ns); - return ret; + return ERR_PTR(ret); } int ncr_session_init(struct ncr_lists *lists, const struct ncr_session_init *session, struct nlattr *tb[]) { - return _ncr_session_init(lists, session->op, tb); + ncr_session_t desc; + struct session_item_st *sess; + + desc = session_alloc_desc(lists); + if (desc < 0) { + err(); + return desc; + } + + sess = _ncr_session_init(lists, desc, session->op, tb); + if (IS_ERR(sess)) { + err(); + session_drop_desc(lists, desc); + return PTR_ERR(sess); + } + + session_publish(lists, sess); + _ncr_sessions_item_put(sess); + + return desc; } static int _ncr_session_encrypt(struct session_item_st* sess, const struct scatterlist* input, unsigned input_cnt, @@ -1088,18 +1098,21 @@ int ncr_session_once(struct ncr_lists *lists, struct session_item_st *sess; int ret, desc; - desc = _ncr_session_init(lists, once->op, tb); + desc = session_alloc_desc(lists); if (desc < 0) { err(); return desc; } - sess = ncr_sessions_item_get(lists, desc); - if (sess == NULL) { + sess = _ncr_session_init(lists, desc, once->op, tb); + if (IS_ERR(sess)) { err(); - return -EINVAL; + session_drop_desc(lists, desc); + return PTR_ERR(sess); } + session_publish(lists, sess); + if (mutex_lock_interruptible(&sess->mem_mutex)) { err(); _ncr_sessions_item_put(sess); -- cgit From 638b47ddcec13d384c6122f56f8e336019382e2b Mon Sep 17 00:00:00 2001 From: Miloslav Trmač Date: Wed, 25 Aug 2010 03:08:13 +0200 Subject: Don't allocate session IDs for *_ONCE. Also skip locking the mutex - the session is private to the calling thread, nothing else can access it. --- ncr-sessions.c | 21 ++------------------- 1 file changed, 2 insertions(+), 19 deletions(-) diff --git a/ncr-sessions.c b/ncr-sessions.c index ab4c9971719..c0ef7e01f51 100644 --- a/ncr-sessions.c +++ b/ncr-sessions.c @@ -1096,34 +1096,17 @@ int ncr_session_once(struct ncr_lists *lists, int compat) { struct session_item_st *sess; - int ret, desc; - - desc = session_alloc_desc(lists); - if (desc < 0) { - err(); - return desc; - } + int ret; - sess = _ncr_session_init(lists, desc, once->op, tb); + sess = _ncr_session_init(lists, -1, once->op, tb); if (IS_ERR(sess)) { err(); - session_drop_desc(lists, desc); return PTR_ERR(sess); } - session_publish(lists, sess); - - if (mutex_lock_interruptible(&sess->mem_mutex)) { - err(); - _ncr_sessions_item_put(sess); - return -ERESTARTSYS; - } - ret = _ncr_session_final(lists, sess, tb, compat); - mutex_unlock(&sess->mem_mutex); _ncr_sessions_item_put(sess); - _ncr_session_remove(lists, desc); return ret; } -- cgit From 3959e5b137db6e81820a9d729ba3c61fc269b3f0 Mon Sep 17 00:00:00 2001 From: Miloslav Trmač Date: Wed, 25 Aug 2010 03:14:05 +0200 Subject: Simplify refcount handling in session_init --- ncr-sessions.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/ncr-sessions.c b/ncr-sessions.c index c0ef7e01f51..098b35ffcc1 100644 --- a/ncr-sessions.c +++ b/ncr-sessions.c @@ -86,12 +86,12 @@ static void session_drop_desc(struct ncr_lists *lst, ncr_session_t desc) mutex_unlock(&lst->session_idr_mutex); } -/* Make a session descriptor visible in user-space */ -static void session_publish(struct ncr_lists *lst, struct session_item_st *sess) +/* Make a session descriptor visible in user-space, stealing the reference */ +static void session_publish_ref(struct ncr_lists *lst, + struct session_item_st *sess) { void *old; - atomic_inc(&sess->refcnt); mutex_lock(&lst->session_idr_mutex); old = idr_replace(&lst->session_idr, sess, sess->desc); mutex_unlock(&lst->session_idr_mutex); @@ -513,8 +513,7 @@ int ncr_session_init(struct ncr_lists *lists, return PTR_ERR(sess); } - session_publish(lists, sess); - _ncr_sessions_item_put(sess); + session_publish_ref(lists, sess); return desc; } -- cgit From 4bc7ded8cb7e7e77c28a2b476ca1f3e0391b646b Mon Sep 17 00:00:00 2001 From: Miloslav Trmač Date: Wed, 25 Aug 2010 03:15:15 +0200 Subject: Rename ncr_sessions_item_get() to session_get_ref() ... for consistency with the other session ID handlers. --- ncr-sessions.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/ncr-sessions.c b/ncr-sessions.c index 098b35ffcc1..beb52714bb0 100644 --- a/ncr-sessions.c +++ b/ncr-sessions.c @@ -99,8 +99,8 @@ static void session_publish_ref(struct ncr_lists *lst, } /* returns the data item corresponding to desc */ -static struct session_item_st *ncr_sessions_item_get(struct ncr_lists *lst, - ncr_session_t desc) +static struct session_item_st *session_get_ref(struct ncr_lists *lst, + ncr_session_t desc) { struct session_item_st* item; @@ -1032,7 +1032,7 @@ int ncr_session_update(struct ncr_lists *lists, struct session_item_st *sess; int ret; - sess = ncr_sessions_item_get(lists, op->ses); + sess = session_get_ref(lists, op->ses); if (sess == NULL) { err(); return -EINVAL; @@ -1069,7 +1069,7 @@ int ncr_session_final(struct ncr_lists *lists, struct session_item_st *sess; int ret; - sess = ncr_sessions_item_get(lists, op->ses); + sess = session_get_ref(lists, op->ses); if (sess == NULL) { err(); return -EINVAL; -- cgit From b89b8e504e89d8d3cbad36d6d1abea2b7c285c22 Mon Sep 17 00:00:00 2001 From: Miloslav Trmač Date: Wed, 25 Aug 2010 03:30:45 +0200 Subject: Unpublish session ID at start of ncr_session_final. This means that ncr_session_final() can't be called on one ID twice, ensuring that the ID is still unique throughout the runtime of ncr_session_final(). (Note that this is not guaranteed for ncr_session_update(): a concurrent thread can call ncr_session_final() on the ID and reuse it before ncr_session_update() finishes.) --- ncr-sessions.c | 49 ++++++++++++++++++++++++++++--------------------- 1 file changed, 28 insertions(+), 21 deletions(-) diff --git a/ncr-sessions.c b/ncr-sessions.c index beb52714bb0..ae1aa69e48f 100644 --- a/ncr-sessions.c +++ b/ncr-sessions.c @@ -35,7 +35,6 @@ static void _ncr_sessions_item_put(struct session_item_st *item); static int _ncr_session_update_key(struct ncr_lists *lists, struct session_item_st *sess, struct nlattr *tb[]); -static void _ncr_session_remove(struct ncr_lists *lst, ncr_session_t desc); static int session_list_deinit_fn(int id, void *item, void *unused) { @@ -118,6 +117,23 @@ struct session_item_st* item; return NULL; } +/* Find a session, stealing the reference, but keep the descriptor allocated. */ +static struct session_item_st *session_unpublish_ref(struct ncr_lists *lst, + ncr_session_t desc) +{ + struct session_item_st *sess; + + mutex_lock(&lst->session_idr_mutex); + /* sess may be NULL for pre-allocated session IDs. */ + sess = idr_replace(&lst->session_idr, NULL, desc); + mutex_unlock(&lst->session_idr_mutex); + if (sess != NULL && !IS_ERR(sess)) + return sess; + + err(); + return NULL; +} + static void _ncr_sessions_item_put(struct session_item_st *item) { if (atomic_dec_and_test(&item->refcnt)) { @@ -575,21 +591,6 @@ int ret; return 0; } -static void _ncr_session_remove(struct ncr_lists *lst, ncr_session_t desc) -{ - struct session_item_st * item; - - mutex_lock(&lst->session_idr_mutex); - /* item may be NULL for pre-allocated session IDs. */ - item = idr_find(&lst->session_idr, desc); - if (item != NULL) - idr_remove(&lst->session_idr, desc); /* Steal the reference */ - mutex_unlock(&lst->session_idr_mutex); - - if (item != NULL) - _ncr_sessions_item_put(item); -} - static int _ncr_session_grow_pages(struct session_item_st *ses, int pagecount) { struct scatterlist *sg; @@ -1069,7 +1070,10 @@ int ncr_session_final(struct ncr_lists *lists, struct session_item_st *sess; int ret; - sess = session_get_ref(lists, op->ses); + /* Make the session inaccessible atomically to avoid concurrent + session_final() callers, but keep the ID allocated to keep audit + information unambiguous. */ + sess = session_unpublish_ref(lists, op->ses); if (sess == NULL) { err(); return -EINVAL; @@ -1077,15 +1081,18 @@ int ncr_session_final(struct ncr_lists *lists, if (mutex_lock_interruptible(&sess->mem_mutex)) { err(); - _ncr_sessions_item_put(sess); + /* Other threads may observe the session descriptor + disappearing and reappearing - but then they should not be + accessing it anyway if it is being freed. + session_unpublish_ref keeps the ID allocated for us. */ + session_publish_ref(lists, sess); return -ERESTARTSYS; } - ret = _ncr_session_final(lists, sess, tb, compat); - mutex_unlock(&sess->mem_mutex); + _ncr_sessions_item_put(sess); - _ncr_session_remove(lists, op->ses); + session_drop_desc(lists, op->ses); return ret; } -- cgit From ddd535966fc356f99b72af5eda678575f6fabebb Mon Sep 17 00:00:00 2001 From: Miloslav Trmač Date: Wed, 25 Aug 2010 03:35:07 +0200 Subject: Move session_item_st definition to ncr-sessions.c It is not used anywhere else. --- ncr-int.h | 26 -------------------------- ncr-sessions.c | 26 ++++++++++++++++++++++++++ 2 files changed, 26 insertions(+), 26 deletions(-) diff --git a/ncr-int.h b/ncr-int.h index 9ae0ea120b3..6bada329475 100644 --- a/ncr-int.h +++ b/ncr-int.h @@ -56,32 +56,6 @@ struct algo_properties_st { ncr_key_type_t key_type; }; -struct session_item_st { - const struct algo_properties_st *algorithm; - ncr_crypto_op_t op; - - /* contexts for various options. - * simpler to have them like that than - * in a union. - */ - struct cipher_data cipher; - struct ncr_pk_ctx pk; - struct hash_data hash; - - struct scatterlist *sg; - struct page **pages; - unsigned array_size; - unsigned available_pages; - struct mutex mem_mutex; /* down when the - * values above are changed. - */ - - struct key_item_st* key; - - atomic_t refcnt; - ncr_session_t desc; -}; - struct key_item_st { /* This object is also not protected from concurrent access. */ diff --git a/ncr-sessions.c b/ncr-sessions.c index ae1aa69e48f..2db972efdab 100644 --- a/ncr-sessions.c +++ b/ncr-sessions.c @@ -31,6 +31,32 @@ #include #include +struct session_item_st { + const struct algo_properties_st *algorithm; + ncr_crypto_op_t op; + + /* contexts for various options. + * simpler to have them like that than + * in a union. + */ + struct cipher_data cipher; + struct ncr_pk_ctx pk; + struct hash_data hash; + + struct scatterlist *sg; + struct page **pages; + unsigned array_size; + unsigned available_pages; + struct mutex mem_mutex; /* down when the + * values above are changed. + */ + + struct key_item_st* key; + + atomic_t refcnt; + ncr_session_t desc; +}; + static void _ncr_sessions_item_put(struct session_item_st *item); static int _ncr_session_update_key(struct ncr_lists *lists, struct session_item_st *sess, -- cgit From 6cf55ca05f1e6277dd6d4a5e90ad344988b77d0d Mon Sep 17 00:00:00 2001 From: Miloslav Trmač Date: Wed, 25 Aug 2010 03:35:07 +0200 Subject: Move session_item_st definition to ncr-sessions.c It is not used anywhere else. --- ncr-int.h | 26 -------------------------- ncr-sessions.c | 26 ++++++++++++++++++++++++++ 2 files changed, 26 insertions(+), 26 deletions(-) diff --git a/ncr-int.h b/ncr-int.h index 0b28be5ddfb..a6b37397c5f 100644 --- a/ncr-int.h +++ b/ncr-int.h @@ -56,32 +56,6 @@ struct algo_properties_st { ncr_key_type_t key_type; }; -struct session_item_st { - const struct algo_properties_st *algorithm; - ncr_crypto_op_t op; - - /* contexts for various options. - * simpler to have them like that than - * in a union. - */ - struct cipher_data cipher; - struct ncr_pk_ctx pk; - struct hash_data hash; - - struct scatterlist *sg; - struct page **pages; - unsigned array_size; - unsigned available_pages; - struct mutex mem_mutex; /* down when the - * values above are changed. - */ - - struct key_item_st* key; - - atomic_t refcnt; - ncr_session_t desc; -}; - struct key_item_st { /* This object is also not protected from concurrent access. */ diff --git a/ncr-sessions.c b/ncr-sessions.c index f2d9b3b9e79..e5e49ad5083 100644 --- a/ncr-sessions.c +++ b/ncr-sessions.c @@ -31,6 +31,32 @@ #include #include +struct session_item_st { + const struct algo_properties_st *algorithm; + ncr_crypto_op_t op; + + /* contexts for various options. + * simpler to have them like that than + * in a union. + */ + struct cipher_data cipher; + struct ncr_pk_ctx pk; + struct hash_data hash; + + struct scatterlist *sg; + struct page **pages; + unsigned array_size; + unsigned available_pages; + struct mutex mem_mutex; /* down when the + * values above are changed. + */ + + struct key_item_st* key; + + atomic_t refcnt; + ncr_session_t desc; +}; + static void _ncr_sessions_item_put(struct session_item_st *item); static int _ncr_session_update_key(struct ncr_lists *lists, ncr_session_t ses, struct nlattr *tb[]); -- cgit From 371746ebd171a83172b328375992f03f6c336bd4 Mon Sep 17 00:00:00 2001 From: Miloslav Trmač Date: Wed, 25 Aug 2010 03:51:36 +0200 Subject: Document locking. Document how members of session_item_st are protected, and what assumptions are made by internal functions. --- ncr-sessions.c | 47 +++++++++++++++++++++++++++++++---------------- 1 file changed, 31 insertions(+), 16 deletions(-) diff --git a/ncr-sessions.c b/ncr-sessions.c index 2db972efdab..2521f2e9920 100644 --- a/ncr-sessions.c +++ b/ncr-sessions.c @@ -32,8 +32,15 @@ #include struct session_item_st { + atomic_t refcnt; + /* Constant values throughout the life of this object follow. */ + ncr_session_t desc; const struct algo_properties_st *algorithm; ncr_crypto_op_t op; + struct key_item_st *key; + + /* Variable values, protected usually by mutex, follow. */ + struct mutex mutex; /* contexts for various options. * simpler to have them like that than @@ -47,14 +54,6 @@ struct session_item_st { struct page **pages; unsigned array_size; unsigned available_pages; - struct mutex mem_mutex; /* down when the - * values above are changed. - */ - - struct key_item_st* key; - - atomic_t refcnt; - ncr_session_t desc; }; static void _ncr_sessions_item_put(struct session_item_st *item); @@ -193,7 +192,7 @@ static struct session_item_st *ncr_session_new(ncr_session_t desc) err(); goto err_sess; } - mutex_init(&sess->mem_mutex); + mutex_init(&sess->mutex); atomic_set(&sess->refcnt, 1); sess->desc = desc; @@ -350,6 +349,8 @@ static struct session_item_st *_ncr_session_init(struct ncr_lists *lists, err(); return ERR_PTR(-ENOMEM); } + /* ns is the only reference throughout this function, so no locking + is necessary. */ ns->op = op; ns->algorithm = _ncr_nla_to_properties(tb[NCR_ATTR_ALGORITHM]); @@ -560,6 +561,7 @@ int ncr_session_init(struct ncr_lists *lists, return desc; } +/* The caller is responsible for locking of the session. */ static int _ncr_session_encrypt(struct session_item_st* sess, const struct scatterlist* input, unsigned input_cnt, size_t input_size, void *output, unsigned output_cnt, size_t *output_size) { @@ -588,6 +590,7 @@ int ret; return 0; } +/* The caller is responsible for locking of the session. */ static int _ncr_session_decrypt(struct session_item_st* sess, const struct scatterlist* input, unsigned input_cnt, size_t input_size, struct scatterlist *output, unsigned output_cnt, size_t *output_size) @@ -617,6 +620,7 @@ int ret; return 0; } +/* The caller is responsible for locking of the session. */ static int _ncr_session_grow_pages(struct session_item_st *ses, int pagecount) { struct scatterlist *sg; @@ -648,7 +652,8 @@ static int _ncr_session_grow_pages(struct session_item_st *ses, int pagecount) } /* Make NCR_ATTR_UPDATE_INPUT_DATA and NCR_ATTR_UPDATE_OUTPUT_BUFFER available - in scatterlists */ + in scatterlists. + The caller is responsible for locking of the session. */ static int get_userbuf2(struct session_item_st *ses, struct nlattr *tb[], struct scatterlist **src_sg, unsigned *src_cnt, size_t *src_size, struct ncr_session_output_buffer *dst, @@ -738,7 +743,8 @@ static int get_userbuf2(struct session_item_st *ses, struct nlattr *tb[], return 0; } -/* Called when userspace buffers are used */ +/* Called when userspace buffers are used. + The caller is responsible for locking of the session. */ static int _ncr_session_update(struct session_item_st *sess, struct nlattr *tb[], int compat) { @@ -839,6 +845,7 @@ fail: return ret; } +/* The caller is responsible for locking of the session. */ static int try_session_update(struct ncr_lists *lists, struct session_item_st *sess, struct nlattr *tb[], int compat) @@ -851,6 +858,9 @@ static int try_session_update(struct ncr_lists *lists, return 0; } +/* The caller is responsible for locking of the session. + Note that one or more _ncr_session_update()s may still be blocked on + sess->mutex and will execute after this function! */ static int _ncr_session_final(struct ncr_lists *lists, struct session_item_st *sess, struct nlattr *tb[], int compat) @@ -1001,7 +1011,8 @@ fail: return ret; } -/* Direct with key: Allows to hash a key */ +/* Direct with key: Allows to hash a key. + The caller is responsible for locking of the session. */ static int _ncr_session_update_key(struct ncr_lists *lists, struct session_item_st* sess, struct nlattr *tb[]) @@ -1065,7 +1076,10 @@ int ncr_session_update(struct ncr_lists *lists, return -EINVAL; } - if (mutex_lock_interruptible(&sess->mem_mutex)) { + /* Note that op->ses may be reallocated from now on, making the audit + information confusing. */ + + if (mutex_lock_interruptible(&sess->mutex)) { err(); ret = -ERESTARTSYS; goto end; @@ -1076,7 +1090,7 @@ int ncr_session_update(struct ncr_lists *lists, ret = _ncr_session_update_key(lists, sess, tb); else ret = -EINVAL; - mutex_unlock(&sess->mem_mutex); + mutex_unlock(&sess->mutex); end: _ncr_sessions_item_put(sess); @@ -1105,7 +1119,7 @@ int ncr_session_final(struct ncr_lists *lists, return -EINVAL; } - if (mutex_lock_interruptible(&sess->mem_mutex)) { + if (mutex_lock_interruptible(&sess->mutex)) { err(); /* Other threads may observe the session descriptor disappearing and reappearing - but then they should not be @@ -1115,7 +1129,7 @@ int ncr_session_final(struct ncr_lists *lists, return -ERESTARTSYS; } ret = _ncr_session_final(lists, sess, tb, compat); - mutex_unlock(&sess->mem_mutex); + mutex_unlock(&sess->mutex); _ncr_sessions_item_put(sess); session_drop_desc(lists, op->ses); @@ -1136,6 +1150,7 @@ int ncr_session_once(struct ncr_lists *lists, return PTR_ERR(sess); } + /* No locking of sess necessary, "sess" is the only reference. */ ret = _ncr_session_final(lists, sess, tb, compat); _ncr_sessions_item_put(sess); -- cgit From 823e0b899b1396a04585a3b4d555d5c4b626a94f Mon Sep 17 00:00:00 2001 From: Miloslav Trmač Date: Wed, 25 Aug 2010 04:03:19 +0200 Subject: Don't duplicate the list of example programs --- examples/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/Makefile b/examples/Makefile index d14908866bb..9911100263e 100644 --- a/examples/Makefile +++ b/examples/Makefile @@ -20,4 +20,4 @@ check: $(progs) ./speed clean: - rm -f *.o *~ ncr pk speed + rm -f *.o *~ $(progs) -- cgit From 9de348f24de5ab4f6eafba7a20f3fa64912b917b Mon Sep 17 00:00:00 2001 From: Miloslav Trmač Date: Wed, 25 Aug 2010 01:05:43 +0200 Subject: Define session cloning interface --- crypto.4 | 5 +++++ ncr.h | 1 + utils.c | 1 + 3 files changed, 7 insertions(+) diff --git a/crypto.4 b/crypto.4 index 0dc21e9431f..04d952e8a38 100644 --- a/crypto.4 +++ b/crypto.4 @@ -543,6 +543,11 @@ For RSA with \fBRSA_PKCS1_PSS\fP. An 32-bit unsigned integer in native byte order specifying the PSS salt length. Optional, defaults to 0. +.IP \fBNCR_ATTR_SESSION_CLONE_FROM\fP +Optional, a 32-bit unsigned integer in native byte order +specifying session state to clone. +Only supported for some operations and algorithms; +specifically intended for cloning hashing sessions. .IP \fBNCR_ATTR_SIGNATURE_HASH_ALGORITHM\fP Mandatory for some operations and algorithms. A NUL-terminated string specifying a hash algorithm underlying a signature, diff --git a/ncr.h b/ncr.h index 47981d1ffd6..3c416ebe1a6 100644 --- a/ncr.h +++ b/ncr.h @@ -58,6 +58,7 @@ enum { NCR_ATTR_DH_BASE, /* NLA_BINARY */ NCR_ATTR_DH_PUBLIC, /* NLA_BINARY */ NCR_ATTR_WANTED_ATTRS, /* NLA_BINARY - array of u16 IDs */ + NCR_ATTR_SESSION_CLONE_FROM, /* NLA_U32 - ncr_session_t */ /* Add new attributes here */ diff --git a/utils.c b/utils.c index 514833cc65c..a427833fdad 100644 --- a/utils.c +++ b/utils.c @@ -82,6 +82,7 @@ static const struct nla_policy ncr_attr_policy[NCR_ATTR_MAX + 1] = { [NCR_ATTR_DH_BASE] = { NLA_BINARY, 0 }, [NCR_ATTR_DH_PUBLIC] = { NLA_BINARY, 0 }, [NCR_ATTR_WANTED_ATTRS] = { NLA_BINARY, 0 }, + [NCR_ATTR_SESSION_CLONE_FROM] = { NLA_U32, 0 }, }; void *__ncr_get_input_args(void *fixed, struct nlattr *tb[], size_t fixed_size, -- cgit From db7c441175942d3b3c3e6321a9a16dc7e83b747c Mon Sep 17 00:00:00 2001 From: Miloslav Trmač Date: Wed, 25 Aug 2010 04:31:52 +0200 Subject: Remove a redundant argument of cryptodev_hash_init --- cryptodev_cipher.c | 4 ++-- cryptodev_int.h | 2 +- libtomcrypt/hashes/hash_memory.c | 2 +- libtomcrypt/hashes/hash_memory_multi.c | 2 +- ncr-sessions.c | 6 +++--- 5 files changed, 8 insertions(+), 8 deletions(-) diff --git a/cryptodev_cipher.c b/cryptodev_cipher.c index 4e74fcc39d0..dae4a63a174 100644 --- a/cryptodev_cipher.c +++ b/cryptodev_cipher.c @@ -216,7 +216,7 @@ ssize_t cryptodev_cipher_decrypt( struct cipher_data* cdata, const struct scatte /* Hash functions */ -int cryptodev_hash_init( struct hash_data* hdata, const char* alg_name, int hmac_mode, void * mackey, size_t mackeylen) +int cryptodev_hash_init(struct hash_data *hdata, const char *alg_name, const void *mackey, size_t mackeylen) { int ret; @@ -228,7 +228,7 @@ int ret; } /* Copy the key from user and set to TFM. */ - if (hmac_mode != 0) { + if (mackey != NULL) { ret = crypto_ahash_setkey(hdata->async.s, mackey, mackeylen); if (unlikely(ret)) { diff --git a/cryptodev_int.h b/cryptodev_int.h index e38150545b0..573fcaaed16 100644 --- a/cryptodev_int.h +++ b/cryptodev_int.h @@ -77,6 +77,6 @@ ssize_t cryptodev_hash_update( struct hash_data* hdata, struct scatterlist *sg, ssize_t _cryptodev_hash_update( struct hash_data* hdata, const void* data, size_t len); int cryptodev_hash_reset( struct hash_data* hdata); void cryptodev_hash_deinit(struct hash_data* hdata); -int cryptodev_hash_init( struct hash_data* hdata, const char* alg_name, int hmac_mode, void* mackey, size_t mackeylen); +int cryptodev_hash_init(struct hash_data *hdata, const char *alg_name, const void *mackey, size_t mackeylen); #endif /* CRYPTODEV_INT_H */ diff --git a/libtomcrypt/hashes/hash_memory.c b/libtomcrypt/hashes/hash_memory.c index a416de9624e..c6f51881245 100644 --- a/libtomcrypt/hashes/hash_memory.c +++ b/libtomcrypt/hashes/hash_memory.c @@ -44,7 +44,7 @@ int hash_memory(const struct algo_properties_st *hash, const unsigned char *in, return CRYPT_BUFFER_OVERFLOW; } - err = cryptodev_hash_init( &hdata, hash->kstr, 0, NULL, 0); + err = cryptodev_hash_init(&hdata, hash->kstr, NULL, 0); if (err < 0) { err = CRYPT_INVALID_HASH; goto LBL_ERR; diff --git a/libtomcrypt/hashes/hash_memory_multi.c b/libtomcrypt/hashes/hash_memory_multi.c index a9149166700..74226767a72 100644 --- a/libtomcrypt/hashes/hash_memory_multi.c +++ b/libtomcrypt/hashes/hash_memory_multi.c @@ -50,7 +50,7 @@ int hash_memory_multi(const struct algo_properties_st *hash, unsigned char *out, return CRYPT_BUFFER_OVERFLOW; } - err = cryptodev_hash_init( &hdata, hash->kstr, 0, NULL, 0); + err = cryptodev_hash_init(&hdata, hash->kstr, NULL, 0); if (err < 0) { err = CRYPT_INVALID_HASH; goto LBL_ERR; diff --git a/ncr-sessions.c b/ncr-sessions.c index 2521f2e9920..a08f2371495 100644 --- a/ncr-sessions.c +++ b/ncr-sessions.c @@ -444,7 +444,7 @@ static struct session_item_st *_ncr_session_init(struct ncr_lists *lists, goto fail; } - ret = cryptodev_hash_init(&ns->hash, ns->algorithm->kstr, 0, NULL, 0); + ret = cryptodev_hash_init(&ns->hash, ns->algorithm->kstr, NULL, 0); if (ret < 0) { err(); goto fail; @@ -474,7 +474,7 @@ static struct session_item_st *_ncr_session_init(struct ncr_lists *lists, goto fail; } - ret = cryptodev_hash_init(&ns->hash, ns->algorithm->kstr, 1, + ret = cryptodev_hash_init(&ns->hash, ns->algorithm->kstr, ns->key->key.secret.data, ns->key->key.secret.size); if (ret < 0) { err(); @@ -509,7 +509,7 @@ static struct session_item_st *_ncr_session_init(struct ncr_lists *lists, goto fail; } - ret = cryptodev_hash_init(&ns->hash, sign_hash->kstr, 0, NULL, 0); + ret = cryptodev_hash_init(&ns->hash, sign_hash->kstr, NULL, 0); if (ret < 0) { err(); goto fail; -- cgit From d2e5c1885639377eb06a03a852d05faf06b4a3c1 Mon Sep 17 00:00:00 2001 From: Miloslav Trmač Date: Wed, 25 Aug 2010 04:31:52 +0200 Subject: Remove a redundant argument of cryptodev_hash_init --- cryptodev_cipher.c | 4 ++-- cryptodev_int.h | 2 +- libtomcrypt/hashes/hash_memory.c | 2 +- libtomcrypt/hashes/hash_memory_multi.c | 2 +- ncr-sessions.c | 6 +++--- 5 files changed, 8 insertions(+), 8 deletions(-) diff --git a/cryptodev_cipher.c b/cryptodev_cipher.c index 4e74fcc39d0..dae4a63a174 100644 --- a/cryptodev_cipher.c +++ b/cryptodev_cipher.c @@ -216,7 +216,7 @@ ssize_t cryptodev_cipher_decrypt( struct cipher_data* cdata, const struct scatte /* Hash functions */ -int cryptodev_hash_init( struct hash_data* hdata, const char* alg_name, int hmac_mode, void * mackey, size_t mackeylen) +int cryptodev_hash_init(struct hash_data *hdata, const char *alg_name, const void *mackey, size_t mackeylen) { int ret; @@ -228,7 +228,7 @@ int ret; } /* Copy the key from user and set to TFM. */ - if (hmac_mode != 0) { + if (mackey != NULL) { ret = crypto_ahash_setkey(hdata->async.s, mackey, mackeylen); if (unlikely(ret)) { diff --git a/cryptodev_int.h b/cryptodev_int.h index e38150545b0..573fcaaed16 100644 --- a/cryptodev_int.h +++ b/cryptodev_int.h @@ -77,6 +77,6 @@ ssize_t cryptodev_hash_update( struct hash_data* hdata, struct scatterlist *sg, ssize_t _cryptodev_hash_update( struct hash_data* hdata, const void* data, size_t len); int cryptodev_hash_reset( struct hash_data* hdata); void cryptodev_hash_deinit(struct hash_data* hdata); -int cryptodev_hash_init( struct hash_data* hdata, const char* alg_name, int hmac_mode, void* mackey, size_t mackeylen); +int cryptodev_hash_init(struct hash_data *hdata, const char *alg_name, const void *mackey, size_t mackeylen); #endif /* CRYPTODEV_INT_H */ diff --git a/libtomcrypt/hashes/hash_memory.c b/libtomcrypt/hashes/hash_memory.c index a416de9624e..c6f51881245 100644 --- a/libtomcrypt/hashes/hash_memory.c +++ b/libtomcrypt/hashes/hash_memory.c @@ -44,7 +44,7 @@ int hash_memory(const struct algo_properties_st *hash, const unsigned char *in, return CRYPT_BUFFER_OVERFLOW; } - err = cryptodev_hash_init( &hdata, hash->kstr, 0, NULL, 0); + err = cryptodev_hash_init(&hdata, hash->kstr, NULL, 0); if (err < 0) { err = CRYPT_INVALID_HASH; goto LBL_ERR; diff --git a/libtomcrypt/hashes/hash_memory_multi.c b/libtomcrypt/hashes/hash_memory_multi.c index a9149166700..74226767a72 100644 --- a/libtomcrypt/hashes/hash_memory_multi.c +++ b/libtomcrypt/hashes/hash_memory_multi.c @@ -50,7 +50,7 @@ int hash_memory_multi(const struct algo_properties_st *hash, unsigned char *out, return CRYPT_BUFFER_OVERFLOW; } - err = cryptodev_hash_init( &hdata, hash->kstr, 0, NULL, 0); + err = cryptodev_hash_init(&hdata, hash->kstr, NULL, 0); if (err < 0) { err = CRYPT_INVALID_HASH; goto LBL_ERR; diff --git a/ncr-sessions.c b/ncr-sessions.c index e5e49ad5083..5a4ba727663 100644 --- a/ncr-sessions.c +++ b/ncr-sessions.c @@ -391,7 +391,7 @@ static int _ncr_session_init(struct ncr_lists *lists, ncr_crypto_op_t op, goto fail; } - ret = cryptodev_hash_init(&ns->hash, ns->algorithm->kstr, 0, NULL, 0); + ret = cryptodev_hash_init(&ns->hash, ns->algorithm->kstr, NULL, 0); if (ret < 0) { err(); goto fail; @@ -421,7 +421,7 @@ static int _ncr_session_init(struct ncr_lists *lists, ncr_crypto_op_t op, goto fail; } - ret = cryptodev_hash_init(&ns->hash, ns->algorithm->kstr, 1, + ret = cryptodev_hash_init(&ns->hash, ns->algorithm->kstr, ns->key->key.secret.data, ns->key->key.secret.size); if (ret < 0) { err(); @@ -456,7 +456,7 @@ static int _ncr_session_init(struct ncr_lists *lists, ncr_crypto_op_t op, goto fail; } - ret = cryptodev_hash_init(&ns->hash, sign_hash->kstr, 0, NULL, 0); + ret = cryptodev_hash_init(&ns->hash, sign_hash->kstr, NULL, 0); if (ret < 0) { err(); goto fail; -- cgit From 56895fcb6ada286ee95df0e49076f2785c45a0db Mon Sep 17 00:00:00 2001 From: Miloslav Trmač Date: Wed, 25 Aug 2010 05:20:11 +0200 Subject: Implement cloning hash sessions --- crypto.4 | 10 ++++-- cryptodev_cipher.c | 42 +++++++++++++++++++++++ cryptodev_int.h | 2 ++ ncr-sessions.c | 97 ++++++++++++++++++++++++++++++++++++++++++++++-------- 4 files changed, 134 insertions(+), 17 deletions(-) diff --git a/crypto.4 b/crypto.4 index 04d952e8a38..c1b39e11221 100644 --- a/crypto.4 +++ b/crypto.4 @@ -520,13 +520,18 @@ The following input attributes are recognized: .RS .IP \fBNCR_ATTR_ALGORITHM\fP -Mandatory. +Mandatory unless +.B NCR_ATTR_SESSION_CLONE_FROM +is provided. .IP \fBNCR_ATTR_IV\fP Mandatory for some operations and algorithms. .IP \fBNCR_ATTR_KEY\fP Mandatory for some operations and algorithms. An 32-bit unsigned integer in native byte order specifying the key to use for the operation. +If +.B NCR_ATTR_SESSION_CLONE_FROM +is provided, the key from the original session is used. .IP \fBNCR_ATTR_RSA_ENCODING_METHOD\fP Mandatory for RSA. An 32-bit unsigned integer in native byte order @@ -546,8 +551,7 @@ Optional, defaults to 0. .IP \fBNCR_ATTR_SESSION_CLONE_FROM\fP Optional, a 32-bit unsigned integer in native byte order specifying session state to clone. -Only supported for some operations and algorithms; -specifically intended for cloning hashing sessions. +Only supported for some operations and algorithms. .IP \fBNCR_ATTR_SIGNATURE_HASH_ALGORITHM\fP Mandatory for some operations and algorithms. A NUL-terminated string specifying a hash algorithm underlying a signature, diff --git a/cryptodev_cipher.c b/cryptodev_cipher.c index dae4a63a174..1fb11473715 100644 --- a/cryptodev_cipher.c +++ b/cryptodev_cipher.c @@ -278,6 +278,48 @@ error: return ret; } +int cryptodev_hash_clone(struct hash_data *hdata, struct hash_data *old_data, + const void *mackey, size_t mackeylen) +{ + const char *algo; + void *state; + int ret; + + /* We want exactly the same driver. */ + algo = crypto_tfm_alg_driver_name(crypto_ahash_tfm(old_data->async.s)); + ret = cryptodev_hash_init(hdata, algo, mackey, mackeylen); + if (unlikely(ret != 0)) + return ret; + + state = kmalloc(crypto_ahash_statesize(hdata->async.s), GFP_KERNEL); + if (unlikely(state == NULL)) { + ret = -ENOMEM; + goto err; + } + + ret = crypto_ahash_export(old_data->async.request, state); + if (unlikely(ret != 0)) { + dprintk(0, KERN_ERR, "error exporting hash state\n"); + goto err; + } + ret = crypto_ahash_import(hdata->async.request, state); + if (unlikely(ret != 0)) { + dprintk(0,KERN_ERR, + "error in crypto_hash_init()\n"); + goto err; + } + + kfree(state); + + hdata->init = 1; + return 0; + +err: + kfree(state); + cryptodev_hash_deinit(hdata); + return ret; +} + void cryptodev_hash_deinit(struct hash_data* hdata) { if (hdata->init) { diff --git a/cryptodev_int.h b/cryptodev_int.h index 573fcaaed16..4b140ba9820 100644 --- a/cryptodev_int.h +++ b/cryptodev_int.h @@ -78,5 +78,7 @@ ssize_t _cryptodev_hash_update( struct hash_data* hdata, const void* data, size_ int cryptodev_hash_reset( struct hash_data* hdata); void cryptodev_hash_deinit(struct hash_data* hdata); int cryptodev_hash_init(struct hash_data *hdata, const char *alg_name, const void *mackey, size_t mackeylen); +int cryptodev_hash_clone(struct hash_data *hdata, struct hash_data *old_data, + const void *mackey, size_t mackeylen); #endif /* CRYPTODEV_INT_H */ diff --git a/ncr-sessions.c b/ncr-sessions.c index a08f2371495..aa9026d32e9 100644 --- a/ncr-sessions.c +++ b/ncr-sessions.c @@ -334,13 +334,38 @@ static int key_item_get_nla_read(struct key_item_st **st, return ret; } +/* The caller is responsible for locking of "session". old_session must not be + locked on entry. */ +static int +init_or_clone_hash(struct session_item_st *session, + struct session_item_st *old_session, + const struct algo_properties_st *algo, + const void *mac_key, size_t mac_key_size) +{ + int ret; + + if (old_session == NULL) + return cryptodev_hash_init(&session->hash, algo->kstr, + mac_key, mac_key_size); + + if (mutex_lock_interruptible(&old_session->mutex)) { + err(); + return -ERESTARTSYS; + } + ret = cryptodev_hash_clone(&session->hash, &old_session->hash, mac_key, + mac_key_size); + mutex_unlock(&old_session->mutex); + + return ret; +} + static struct session_item_st *_ncr_session_init(struct ncr_lists *lists, ncr_session_t desc, ncr_crypto_op_t op, struct nlattr *tb[]) { const struct nlattr *nla; - struct session_item_st *ns; + struct session_item_st *ns, *old_session = NULL; int ret; const struct algo_properties_st *sign_hash; @@ -353,12 +378,31 @@ static struct session_item_st *_ncr_session_init(struct ncr_lists *lists, is necessary. */ ns->op = op; - ns->algorithm = _ncr_nla_to_properties(tb[NCR_ATTR_ALGORITHM]); - if (ns->algorithm == NULL) { - err(); - ret = -EINVAL; - goto fail; + nla = tb[NCR_ATTR_SESSION_CLONE_FROM]; + if (nla != NULL) { + /* "ns" is not visible to userspace, so this is safe. */ + old_session = session_get_ref(lists, nla_get_u32(nla)); + if (old_session == NULL) { + err(); + ret = -EINVAL; + goto fail; + } + if (ns->op != old_session->op) { + err(); + ret = -EINVAL; + goto fail; + } } + + if (old_session == NULL) { + ns->algorithm = _ncr_nla_to_properties(tb[NCR_ATTR_ALGORITHM]); + if (ns->algorithm == NULL) { + err(); + ret = -EINVAL; + goto fail; + } + } else + ns->algorithm = old_session->algorithm; switch(op) { case NCR_OP_ENCRYPT: @@ -369,6 +413,12 @@ static struct session_item_st *_ncr_session_init(struct ncr_lists *lists, goto fail; } + if (old_session != NULL) { + err(); + ret = -EOPNOTSUPP; + goto fail; + } + /* read key */ ret = key_item_get_nla_read(&ns->key, lists, tb[NCR_ATTR_KEY]); @@ -444,19 +494,27 @@ static struct session_item_st *_ncr_session_init(struct ncr_lists *lists, goto fail; } - ret = cryptodev_hash_init(&ns->hash, ns->algorithm->kstr, NULL, 0); + ret = init_or_clone_hash(ns, old_session, + ns->algorithm, NULL, + 0); if (ret < 0) { err(); goto fail; } } else { - /* read key */ - ret = key_item_get_nla_read(&ns->key, lists, - tb[NCR_ATTR_KEY]); - if (ret < 0) { - err(); - goto fail; + /* Get key */ + if (old_session == NULL) { + ret = key_item_get_nla_read(&ns->key, + lists, + tb[NCR_ATTR_KEY]); + if (ret < 0) { + err(); + goto fail; + } + } else { + atomic_inc(&old_session->key->refcnt); + ns->key = old_session->key; } /* wrapping keys cannot be used for anything except wrapping. @@ -474,7 +532,7 @@ static struct session_item_st *_ncr_session_init(struct ncr_lists *lists, goto fail; } - ret = cryptodev_hash_init(&ns->hash, ns->algorithm->kstr, + ret = init_or_clone_hash(ns, old_session, ns->algorithm, ns->key->key.secret.data, ns->key->key.secret.size); if (ret < 0) { err(); @@ -482,6 +540,12 @@ static struct session_item_st *_ncr_session_init(struct ncr_lists *lists, } } else if (ns->algorithm->is_pk && (ns->key->type == NCR_KEY_TYPE_PRIVATE || ns->key->type == NCR_KEY_TYPE_PUBLIC)) { + if (old_session != NULL) { + err(); + ret = -EOPNOTSUPP; + goto fail; + } + nla = tb[NCR_ATTR_SIGNATURE_HASH_ALGORITHM]; sign_hash = _ncr_nla_to_properties(nla); if (sign_hash == NULL) { @@ -527,10 +591,15 @@ static struct session_item_st *_ncr_session_init(struct ncr_lists *lists, ret = -EINVAL; goto fail; } + + if (old_session != NULL) + _ncr_sessions_item_put(old_session); return ns; fail: + if (old_session != NULL) + _ncr_sessions_item_put(old_session); _ncr_sessions_item_put(ns); return ERR_PTR(ret); -- cgit From 5d586cad2979ad279e9a7f0985d008e5d649bbc5 Mon Sep 17 00:00:00 2001 From: Miloslav Trmač Date: Wed, 25 Aug 2010 05:46:06 +0200 Subject: Add hash cloning example. --- examples/ncr.c | 218 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 218 insertions(+) diff --git a/examples/ncr.c b/examples/ncr.c index a7d34f0e881..203951646fa 100644 --- a/examples/ncr.c +++ b/examples/ncr.c @@ -1236,6 +1236,221 @@ test_ncr_hash(int cfd) } +static int +test_ncr_hash_clone(int cfd) +{ + ncr_key_t key; + struct __attribute__((packed)) { + struct ncr_key_import f; + struct nlattr id_head ALIGN_NL; + uint8_t id[2] ALIGN_NL; + struct nlattr type_head ALIGN_NL; + uint32_t type ALIGN_NL; + struct nlattr flags_head ALIGN_NL; + uint32_t flags ALIGN_NL; + struct nlattr algo_head ALIGN_NL; + char algo[128] ALIGN_NL; + } kimport; + uint8_t data[HASH_DATA_SIZE]; + const struct hash_vectors_st *hv; + int j; + size_t data_size; + struct __attribute__((packed)) { + struct ncr_session_init f; + struct nlattr key_head ALIGN_NL; + uint32_t key ALIGN_NL; + struct nlattr algo_head ALIGN_NL; + char algo[128] ALIGN_NL; + } kinit; + struct __attribute__((packed)) { + struct ncr_session_update f; + struct nlattr input_head ALIGN_NL; + struct ncr_session_input_data input ALIGN_NL; + } kupdate; + struct __attribute__((packed)) { + struct ncr_session_final f; + struct nlattr input_head ALIGN_NL; + struct ncr_session_input_data input ALIGN_NL; + struct nlattr output_head ALIGN_NL; + struct ncr_session_output_buffer output ALIGN_NL; + } kfinal; + struct __attribute__((packed)) { + struct ncr_session_once f; + struct nlattr clone_head ALIGN_NL; + uint32_t clone ALIGN_NL; + struct nlattr input_head ALIGN_NL; + struct ncr_session_input_data input ALIGN_NL; + struct nlattr output_head ALIGN_NL; + struct ncr_session_output_buffer output ALIGN_NL; + } kclone; + ncr_session_t ses; + + /* convert it to key */ + key = ioctl(cfd, NCRIO_KEY_INIT); + if (key == -1) { + perror("ioctl(NCRIO_KEY_INIT)"); + return 1; + } + + fprintf(stdout, "Tests of hash cloning\n"); + for (hv = hash_vectors; + hv < hash_vectors + sizeof(hash_vectors) / sizeof(hash_vectors[0]); + hv++) { + size_t algo_size; + + algo_size = strlen(hv->algorithm) + 1; + fprintf(stdout, "\t%s:\n", hv->algorithm); + /* import key */ + if (hv->key != NULL) { + + memset(&kimport.f, 0, sizeof(kimport.f)); + kimport.f.key = key; + kimport.f.data = hv->key; + kimport.f.data_size = hv->key_size; + kimport.id_head.nla_len + = NLA_HDRLEN + sizeof(kimport.id); + kimport.id_head.nla_type = NCR_ATTR_KEY_ID; + kimport.id[0] = 'a'; + kimport.id[1] = 'b'; + kimport.type_head.nla_len + = NLA_HDRLEN + sizeof(kimport.type); + kimport.type_head.nla_type = NCR_ATTR_KEY_TYPE; + kimport.type = NCR_KEY_TYPE_SECRET; + 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; + kimport.algo_head.nla_len = NLA_HDRLEN + algo_size; + kimport.algo_head.nla_type = NCR_ATTR_ALGORITHM; + memcpy(kimport.algo, hv->algorithm, algo_size); + kimport.f.input_size + = kimport.algo + algo_size - (char *)&kimport; + if (ioctl(cfd, NCRIO_KEY_IMPORT, &kimport)) { + fprintf(stderr, "Error: %s:%d\n", __func__, __LINE__); + perror("ioctl(NCRIO_KEY_IMPORT)"); + return 1; + } + } + + /* Initialize a session */ + memset(&kinit.f, 0, sizeof(kinit.f)); + kinit.f.op = hv->op; + kinit.key_head.nla_len = NLA_HDRLEN + sizeof(kinit.key); + kinit.key_head.nla_type = NCR_ATTR_KEY; + kinit.key = hv->key != NULL ? key : NCR_KEY_INVALID; + kinit.algo_head.nla_len = NLA_HDRLEN + algo_size; + kinit.algo_head.nla_type = NCR_ATTR_ALGORITHM; + memcpy(kinit.algo, hv->algorithm, algo_size); + kinit.f.input_size = kinit.algo + algo_size - (char *)&kinit; + + ses = ioctl(cfd, NCRIO_SESSION_INIT, &kinit); + if (ses < 0) { + fprintf(stderr, "Error: %s:%d\n", __func__, __LINE__); + perror("ioctl(NCRIO_SESSION_INIT)"); + return 1; + } + + /* Submit half of the data */ + memset(&kupdate.f, 0, sizeof(kupdate.f)); + kupdate.f.input_size = sizeof(kupdate); + kupdate.f.ses = ses; + kupdate.input_head.nla_len = NLA_HDRLEN + sizeof(kupdate.input); + kupdate.input_head.nla_type = NCR_ATTR_UPDATE_INPUT_DATA; + kupdate.input.data = hv->plaintext; + kupdate.input.data_size = hv->plaintext_size / 2; + + if (ioctl(cfd, NCRIO_SESSION_UPDATE, &kupdate)) { + fprintf(stderr, "Error: %s:%d\n", __func__, __LINE__); + perror("ioctl(NCRIO_SESSION_UPDATE)"); + return 1; + } + + /* Clone a session, submit the other half, verify. */ + memset(&kclone.f, 0, sizeof(kclone.f)); + kclone.f.input_size = sizeof(kclone); + kclone.f.op = hv->op; + kclone.clone_head.nla_len = NLA_HDRLEN + sizeof(kclone.clone); + kclone.clone_head.nla_type = NCR_ATTR_SESSION_CLONE_FROM; + kclone.clone = ses; + kclone.input_head.nla_len = NLA_HDRLEN + sizeof(kclone.input); + kclone.input_head.nla_type = NCR_ATTR_UPDATE_INPUT_DATA; + kclone.input.data = hv->plaintext + hv->plaintext_size / 2; + kclone.input.data_size + = hv->plaintext_size - hv->plaintext_size / 2; + kclone.output_head.nla_len = NLA_HDRLEN + sizeof(kclone.output); + kclone.output_head.nla_type = NCR_ATTR_FINAL_OUTPUT_BUFFER; + kclone.output.buffer = data; + kclone.output.buffer_size = sizeof(data); + kclone.output.result_size_ptr = &data_size; + + if (ioctl(cfd, NCRIO_SESSION_ONCE, &kclone)) { + fprintf(stderr, "Error: %s:%d\n", __func__, __LINE__); + perror("ioctl(NCRIO_SESSION_ONCE)"); + return 1; + } + + if (data_size != hv->output_size + || memcmp(data, hv->output, hv->output_size) != 0) { + fprintf(stderr, "HASH test vector %td failed!\n", + hv - hash_vectors); + + fprintf(stderr, "Output[%zu]: ", data_size); + for(j = 0; j < data_size; j++) + fprintf(stderr, "%.2x:", (int)data[j]); + fprintf(stderr, "\n"); + + fprintf(stderr, "Expected[%d]: ", hv->output_size); + for (j = 0; j < hv->output_size; j++) + fprintf(stderr, "%.2x:", (int)hv->output[j]); + fprintf(stderr, "\n"); + return 1; + } + + /* Submit the other half to the original session, verify. */ + memset(&kfinal.f, 0, sizeof(kfinal.f)); + kfinal.f.input_size = sizeof(kfinal); + kfinal.f.ses = ses; + kfinal.input_head.nla_len = NLA_HDRLEN + sizeof(kfinal.input); + kfinal.input_head.nla_type = NCR_ATTR_UPDATE_INPUT_DATA; + kfinal.input.data = hv->plaintext + hv->plaintext_size / 2; + kfinal.input.data_size + = hv->plaintext_size - hv->plaintext_size / 2; + kfinal.output_head.nla_len = NLA_HDRLEN + sizeof(kfinal.output); + kfinal.output_head.nla_type = NCR_ATTR_FINAL_OUTPUT_BUFFER; + kfinal.output.buffer = data; + kfinal.output.buffer_size = sizeof(data); + kfinal.output.result_size_ptr = &data_size; + + if (ioctl(cfd, NCRIO_SESSION_FINAL, &kfinal)) { + fprintf(stderr, "Error: %s:%d\n", __func__, __LINE__); + perror("ioctl(NCRIO_SESSION_FINAL)"); + return 1; + } + + if (data_size != hv->output_size + || memcmp(data, hv->output, hv->output_size) != 0) { + fprintf(stderr, "HASH test vector %td failed!\n", + hv - hash_vectors); + + fprintf(stderr, "Output[%zu]: ", data_size); + for(j = 0; j < data_size; j++) + fprintf(stderr, "%.2x:", (int)data[j]); + fprintf(stderr, "\n"); + + fprintf(stderr, "Expected[%d]: ", hv->output_size); + for (j = 0; j < hv->output_size; j++) + fprintf(stderr, "%.2x:", (int)hv->output[j]); + fprintf(stderr, "\n"); + return 1; + } + } + + fprintf(stdout, "\n"); + + return 0; + +} + static int test_ncr_hash_key(int cfd) { @@ -1415,6 +1630,9 @@ main() if (test_ncr_hash(fd)) return 1; + if (test_ncr_hash_clone(fd)) + return 1; + if (test_ncr_hash_key(fd)) return 1; -- cgit From 6bb729e4da0d4f280845f14196c2e9cef0cd1480 Mon Sep 17 00:00:00 2001 From: Miloslav Trmač Date: Wed, 25 Aug 2010 06:11:22 +0200 Subject: Make some objects static --- ncr-key-wrap.c | 2 +- ncr-key.c | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/ncr-key-wrap.c b/ncr-key-wrap.c index 0f9f0fe1831..7a449ed29ee 100644 --- a/ncr-key-wrap.c +++ b/ncr-key-wrap.c @@ -484,7 +484,7 @@ cleanup: /* will check if the kek is of equal or higher security level than * wkey. To prevent encrypting a 256 bit key with an 128 bit one. */ -int check_key_level(struct key_item_st* kek, struct key_item_st* wkey) +static int check_key_level(struct key_item_st* kek, struct key_item_st* wkey) { int kek_level, wkey_level; diff --git a/ncr-key.c b/ncr-key.c index a7019f5cfba..35e68715964 100644 --- a/ncr-key.c +++ b/ncr-key.c @@ -504,7 +504,7 @@ fail: * Keysizes (2009-2010)". It maps the strength of public key algorithms to * symmetric ones. Should be kept up to date. */ -struct { +static const struct { unsigned int bits; /* sec level */ unsigned int rsa_bits; unsigned int dlog_bits; @@ -519,7 +519,7 @@ struct { {0,0,0} }; -unsigned int rsa_to_bits(unsigned int rsa_bits) +static unsigned int rsa_to_bits(unsigned int rsa_bits) { int i = 1; @@ -538,7 +538,7 @@ int i = 1; return ecrypt_vals[i-1].bits; } -unsigned int dlog_to_bits(unsigned int dlog_bits) +static unsigned int dlog_to_bits(unsigned int dlog_bits) { int i = 1; -- cgit 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 From 387d5847ee502cdb03bbf5771575438ddebf2624 Mon Sep 17 00:00:00 2001 From: Miloslav Trmač Date: Fri, 27 Aug 2010 08:31:36 +0200 Subject: Implement PK signatures with transparent hashes --- ncr-int.h | 9 +++++++- ncr-sessions.c | 70 ++++++++++++++++++++++++++++++++++++++++++++++++---------- ncr.h | 4 ++++ 3 files changed, 70 insertions(+), 13 deletions(-) diff --git a/ncr-int.h b/ncr-int.h index 5e86aff5641..764abdbb96e 100644 --- a/ncr-int.h +++ b/ncr-int.h @@ -18,7 +18,8 @@ struct nlattr; struct ncr_out; -// Not all known algorithms - only for quick internal identification +// Not all known algorithms - only for quick internal identification. Note +// that more than one struct algo_properties_st may share the same enum value! enum ncr_algorithm { NCR_ALG_NONE__, NCR_ALG_NULL, @@ -49,6 +50,7 @@ struct algo_properties_st { unsigned can_kx:1; /* key exchange */ unsigned is_symmetric:1; unsigned is_pk:1; + unsigned has_transparent_hash:1; int digest_size; /* NCR_KEY_TYPE_SECRET if for a secret key algorithm or MAC, * NCR_KEY_TYPE_PUBLIC for a public key algorithm. @@ -67,6 +69,11 @@ struct session_item_st { struct cipher_data cipher; struct ncr_pk_ctx pk; struct hash_data hash; + /* This is a hack, ideally we'd have a hash algorithm that simply + outputs its input as a digest. We'd still need to distinguish + between the hash to identify in the signature and the hash to + actually use, though. */ + void *transparent_hash; struct scatterlist *sg; struct page **pages; diff --git a/ncr-sessions.c b/ncr-sessions.c index 41f8a4c9000..84433cca3fe 100644 --- a/ncr-sessions.c +++ b/ncr-sessions.c @@ -77,6 +77,7 @@ void _ncr_sessions_item_put( struct session_item_st* item) cryptodev_cipher_deinit(&item->cipher); ncr_pk_cipher_deinit(&item->pk); cryptodev_hash_deinit(&item->hash); + kfree(item->transparent_hash); if (item->key) _ncr_key_item_put(item->key); kfree(item->sg); @@ -195,8 +196,14 @@ static const struct algo_properties_st algo_properties[] = { (yet). */ { .algo = NCR_ALG_RSA, KSTR("rsa"), .is_pk = 1, .can_encrypt=1, .can_sign=1, .key_type = NCR_KEY_TYPE_PUBLIC }, + { .algo = NCR_ALG_RSA, KSTR(NCR_ALG_RSA_TRANSPARENT_HASH), .is_pk = 1, + .can_encrypt=1, .can_sign=1, .has_transparent_hash = 1, + .key_type = NCR_KEY_TYPE_PUBLIC }, { .algo = NCR_ALG_DSA, KSTR("dsa"), .is_pk = 1, .can_sign=1, .key_type = NCR_KEY_TYPE_PUBLIC }, + { .algo = NCR_ALG_DSA, KSTR(NCR_ALG_DSA_TRANSPARENT_HASH), .is_pk = 1, + .can_sign=1, .has_transparent_hash = 1, + .key_type = NCR_KEY_TYPE_PUBLIC }, { .algo = NCR_ALG_DH, KSTR("dh"), .is_pk = 1, .can_kx=1, .key_type = NCR_KEY_TYPE_PUBLIC }, #undef KSTR @@ -433,6 +440,15 @@ static int _ncr_session_init(struct ncr_lists *lists, ncr_crypto_op_t op, err(); goto fail; } + + if (ns->algorithm->has_transparent_hash) { + ns->transparent_hash = kzalloc(ns->hash.digestsize, GFP_KERNEL); + if (ns->transparent_hash == NULL) { + err(); + ret = -ENOMEM; + goto fail; + } + } } else { err(); ret = -EINVAL; @@ -748,10 +764,27 @@ static int _ncr_session_update(struct ncr_lists *lists, ncr_session_t ses, case NCR_OP_SIGN: case NCR_OP_VERIFY: - ret = cryptodev_hash_update(&sess->hash, isg, isg_size); - if (ret < 0) { - err(); - goto fail; + if (sess->algorithm->has_transparent_hash) { + if (isg_size != sess->hash.digestsize) { + err(); + ret = -EINVAL; + goto fail; + } + ret = sg_copy_to_buffer(isg, isg_cnt, + sess->transparent_hash, + isg_size); + if (ret != isg_size) { + err(); + ret = -EINVAL; + goto fail; + } + } else { + ret = cryptodev_hash_update(&sess->hash, isg, + isg_size); + if (ret < 0) { + err(); + goto fail; + } } break; default: @@ -845,10 +878,14 @@ static int _ncr_session_final(struct ncr_lists *lists, ncr_session_t ses, ret = -EINVAL; goto fail; } - ret = cryptodev_hash_final(&sess->hash, digest); - if (ret < 0) { - err(); - goto fail; + if (sess->algorithm->has_transparent_hash) + memcpy(digest, sess->transparent_hash, digest_size); + else { + ret = cryptodev_hash_final(&sess->hash, digest); + if (ret < 0) { + err(); + goto fail; + } } if (!sess->algorithm->is_pk) @@ -884,10 +921,14 @@ static int _ncr_session_final(struct ncr_lists *lists, ncr_session_t ses, goto fail; } - ret = cryptodev_hash_final(&sess->hash, digest); - if (ret < 0) { - err(); - goto fail; + if (sess->algorithm->has_transparent_hash) + memcpy(digest, sess->transparent_hash, digest_size); + else { + ret = cryptodev_hash_final(&sess->hash, digest); + if (ret < 0) { + err(); + goto fail; + } } cryptodev_hash_deinit(&sess->hash); @@ -994,6 +1035,11 @@ static int _ncr_session_update_key(struct ncr_lists *lists, ncr_session_t ses, goto fail; case NCR_OP_SIGN: case NCR_OP_VERIFY: + if (sess->algorithm->has_transparent_hash) { + err(); + ret = -EINVAL; + goto fail; + } ret = _cryptodev_hash_update(&sess->hash, key->key.secret.data, key->key.secret.size); if (ret < 0) { diff --git a/ncr.h b/ncr.h index 47981d1ffd6..e4863564694 100644 --- a/ncr.h +++ b/ncr.h @@ -68,6 +68,10 @@ enum { #define NCR_CIPHER_MAX_BLOCK_LEN 32 #define NCR_HASH_MAX_OUTPUT_SIZE 64 +/* Better names wanted */ +#define NCR_ALG_DSA_TRANSPARENT_HASH "__dsa_transparent_hash" +#define NCR_ALG_RSA_TRANSPARENT_HASH "__rsa_transparent_hash" + #define NCR_WALG_AES_RFC3394 "walg-aes-rfc3394" /* for secret keys only */ #define NCR_WALG_AES_RFC5649 "walg-aes-rfc5649" /* can wrap arbitrary key */ -- cgit From 114f42fe23152f6726144fe82eb62f400cfe1dba Mon Sep 17 00:00:00 2001 From: Miloslav Trmač Date: Fri, 27 Aug 2010 07:59:04 +0200 Subject: Add support for changing IVs in sessions --- crypto.4 | 4 ++++ ncr-sessions.c | 19 +++++++++++++++++++ 2 files changed, 23 insertions(+) diff --git a/crypto.4 b/crypto.4 index 0dc21e9431f..c2d1102b538 100644 --- a/crypto.4 +++ b/crypto.4 @@ -571,6 +571,10 @@ member. The following input attributes are recognized: .RS +.IP \fBNCR_ATTR_IV\fP +Only used for some operations and algorithms. +Optional, +IV from session initialization or left from last update is used if not present. .IP \fBNCR_ATTR_UPDATE_INPUT_DATA\fP A .B struct ncr_session_input_data diff --git a/ncr-sessions.c b/ncr-sessions.c index 41f8a4c9000..460df6f637c 100644 --- a/ncr-sessions.c +++ b/ncr-sessions.c @@ -661,6 +661,7 @@ static int get_userbuf2(struct session_item_st *ses, struct nlattr *tb[], static int _ncr_session_update(struct ncr_lists *lists, ncr_session_t ses, struct nlattr *tb[], int compat) { + const struct nlattr *nla; int ret; struct session_item_st* sess; struct scatterlist *isg = NULL; @@ -703,6 +704,15 @@ static int _ncr_session_update(struct ncr_lists *lists, ncr_session_t ses, goto fail; } + if (sess->algorithm->is_symmetric + && sess->algorithm->needs_iv) { + nla = tb[NCR_ATTR_IV]; + if (nla != NULL) + cryptodev_cipher_set_iv(&sess->cipher, + nla_data(nla), + nla_len(nla)); + } + ret = _ncr_session_encrypt(sess, isg, isg_cnt, isg_size, osg, osg_cnt, &osg_size); if (ret < 0) { @@ -731,6 +741,15 @@ static int _ncr_session_update(struct ncr_lists *lists, ncr_session_t ses, goto fail; } + if (sess->algorithm->is_symmetric + && sess->algorithm->needs_iv) { + nla = tb[NCR_ATTR_IV]; + if (nla != NULL) + cryptodev_cipher_set_iv(&sess->cipher, + nla_data(nla), + nla_len(nla)); + } + ret = _ncr_session_decrypt(sess, isg, isg_cnt, isg_size, osg, osg_cnt, &osg_size); if (ret < 0) { -- cgit From 4d969f0e12517e49a60c2a2b146ba2f650e7f61b Mon Sep 17 00:00:00 2001 From: Miloslav Trmač Date: Fri, 27 Aug 2010 09:01:21 +0200 Subject: Allow sharing keys for "regular" and "transparent" algorithms --- ncr-pk.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/ncr-pk.c b/ncr-pk.c index c6055dba1d5..9b9078efe38 100644 --- a/ncr-pk.c +++ b/ncr-pk.c @@ -358,7 +358,9 @@ int ncr_pk_cipher_init(const struct algo_properties_st *algo, memset(ctx, 0, sizeof(*ctx)); - if (key->algorithm != algo) { + /* Allow using the same key for transparent and non-transparent + hashing. */ + if (key->algorithm->algo != algo->algo) { err(); return -EINVAL; } -- cgit From bf6a75c801ece98f608df29df3846033d22f28d7 Mon Sep 17 00:00:00 2001 From: Miloslav Trmač Date: Fri, 27 Aug 2010 08:51:14 +0200 Subject: Add transparent hash signature examples --- examples/pk.c | 245 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 245 insertions(+) diff --git a/examples/pk.c b/examples/pk.c index 6acbadf12b0..2014010f417 100644 --- a/examples/pk.c +++ b/examples/pk.c @@ -29,6 +29,7 @@ #define ALIGN_NL __attribute__((aligned(NLA_ALIGNTO))) #define SIGNATURE_HASH "sha1" +#define SIGNATURE_HASH_SIZE 20 #define ALG_AES_CBC "cbc(aes)" #define ALG_DH "dh" @@ -1041,6 +1042,126 @@ static int rsa_key_sign_verify(int cfd, ncr_key_t privkey, ncr_key_t pubkey, int } +static int rsa_key_sign_verify_transparent(int cfd, ncr_key_t privkey, + ncr_key_t pubkey, int pss) +{ + struct __attribute__((packed)) { + struct ncr_session_once f; + struct nlattr algo_head ALIGN_NL; + char algo[sizeof(NCR_ALG_RSA_TRANSPARENT_HASH)] ALIGN_NL; + struct nlattr key_head ALIGN_NL; + uint32_t key ALIGN_NL; + struct nlattr rsa_head ALIGN_NL; + uint32_t rsa ALIGN_NL; + struct nlattr sign_hash_head ALIGN_NL; + char sign_hash[sizeof(SIGNATURE_HASH)] ALIGN_NL; + struct nlattr input_head ALIGN_NL; + struct ncr_session_input_data input ALIGN_NL; + struct nlattr signature_head ALIGN_NL; + struct ncr_session_output_buffer signature ALIGN_NL; + } ksign; + struct __attribute__((packed)) { + struct ncr_session_once f; + struct nlattr algo_head ALIGN_NL; + char algo[sizeof(NCR_ALG_RSA_TRANSPARENT_HASH)] ALIGN_NL; + struct nlattr key_head ALIGN_NL; + uint32_t key ALIGN_NL; + struct nlattr rsa_head ALIGN_NL; + uint32_t rsa ALIGN_NL; + struct nlattr sign_hash_head ALIGN_NL; + char sign_hash[sizeof(SIGNATURE_HASH)] ALIGN_NL; + struct nlattr input_head ALIGN_NL; + struct ncr_session_input_data input ALIGN_NL; + struct nlattr signature_head ALIGN_NL; + struct ncr_session_input_data signature ALIGN_NL; + } kverify; + uint8_t data[SIGNATURE_HASH_SIZE]; + uint8_t sig[DATA_SIZE]; + size_t sig_size; + int ret; + + fprintf(stdout, "Tests on transparent RSA (%s) key signature:", + (pss != 0) ? "PSS" : "PKCS V1.5"); + fflush(stdout); + + memset(data, 0x3, sizeof(data)); + + /* sign data */ + memset(&ksign.f, 0, sizeof(ksign.f)); + ksign.f.input_size = sizeof(ksign); + ksign.f.op = NCR_OP_SIGN; + ksign.algo_head.nla_len = NLA_HDRLEN + sizeof(ksign.algo); + ksign.algo_head.nla_type = NCR_ATTR_ALGORITHM; + strcpy(ksign.algo, NCR_ALG_RSA_TRANSPARENT_HASH); + ksign.key_head.nla_len = NLA_HDRLEN + sizeof(ksign.key); + ksign.key_head.nla_type = NCR_ATTR_KEY; + ksign.key = privkey; + ksign.rsa_head.nla_len = NLA_HDRLEN + sizeof(ksign.rsa); + ksign.rsa_head.nla_type = NCR_ATTR_RSA_ENCODING_METHOD; + ksign.rsa = (pss != 0) ? RSA_PKCS1_PSS : RSA_PKCS1_V1_5; + ksign.sign_hash_head.nla_len = NLA_HDRLEN + sizeof(ksign.sign_hash); + ksign.sign_hash_head.nla_type = NCR_ATTR_SIGNATURE_HASH_ALGORITHM; + strcpy(ksign.sign_hash, SIGNATURE_HASH); + ksign.input_head.nla_len = NLA_HDRLEN + sizeof(ksign.input); + ksign.input_head.nla_type = NCR_ATTR_UPDATE_INPUT_DATA; + ksign.input.data = data; + ksign.input.data_size = SIGNATURE_HASH_SIZE; + ksign.signature_head.nla_len = NLA_HDRLEN + sizeof(ksign.signature); + ksign.signature_head.nla_type = NCR_ATTR_FINAL_OUTPUT_BUFFER; + ksign.signature.buffer = sig; + ksign.signature.buffer_size = sizeof(sig); + ksign.signature.result_size_ptr = &sig_size; + + if (ioctl(cfd, NCRIO_SESSION_ONCE, &ksign)) { + fprintf(stderr, "Error: %s:%d\n", __func__, __LINE__); + perror("ioctl(NCRIO_SESSION_ONCE)"); + return 1; + } + + /* verify signature */ + memset(data, 0x3, sizeof(data)); + + memset(&kverify.f, 0, sizeof(kverify.f)); + kverify.f.input_size = sizeof(kverify); + kverify.f.op = NCR_OP_VERIFY; + kverify.algo_head.nla_len = NLA_HDRLEN + sizeof(kverify.algo); + kverify.algo_head.nla_type = NCR_ATTR_ALGORITHM; + strcpy(kverify.algo, NCR_ALG_RSA_TRANSPARENT_HASH); + kverify.key_head.nla_len = NLA_HDRLEN + sizeof(kverify.key); + kverify.key_head.nla_type = NCR_ATTR_KEY; + kverify.key = pubkey; + kverify.rsa_head.nla_len = NLA_HDRLEN + sizeof(kverify.rsa); + kverify.rsa_head.nla_type = NCR_ATTR_RSA_ENCODING_METHOD; + kverify.rsa = (pss != 0) ? RSA_PKCS1_PSS : RSA_PKCS1_V1_5; + kverify.sign_hash_head.nla_len = NLA_HDRLEN + sizeof(kverify.sign_hash); + kverify.sign_hash_head.nla_type = NCR_ATTR_SIGNATURE_HASH_ALGORITHM; + strcpy(kverify.sign_hash, SIGNATURE_HASH); + kverify.input_head.nla_len = NLA_HDRLEN + sizeof(kverify.input); + kverify.input_head.nla_type = NCR_ATTR_UPDATE_INPUT_DATA; + kverify.input.data = data; + kverify.input.data_size = SIGNATURE_HASH_SIZE; + kverify.signature_head.nla_len = NLA_HDRLEN + sizeof(kverify.signature); + kverify.signature_head.nla_type = NCR_ATTR_FINAL_INPUT_DATA; + kverify.signature.data = sig; + kverify.signature.data_size = sig_size; + + ret = ioctl(cfd, NCRIO_SESSION_ONCE, &kverify); + if (ret < 0) { + fprintf(stderr, "Error: %s:%d\n", __func__, __LINE__); + perror("ioctl(NCRIO_SESSION_ONCE)"); + return 1; + } + + if (ret) + fprintf(stdout, " Success\n"); + else { + fprintf(stdout, " Verification Failed!\n"); + return 1; + } + + return 0; +} + static int dsa_key_sign_verify(int cfd, ncr_key_t privkey, ncr_key_t pubkey) { struct __attribute__((packed)) { @@ -1148,6 +1269,112 @@ static int dsa_key_sign_verify(int cfd, ncr_key_t privkey, ncr_key_t pubkey) } +static int dsa_key_sign_verify_transparent(int cfd, ncr_key_t privkey, + ncr_key_t pubkey) +{ + struct __attribute__((packed)) { + struct ncr_session_once f; + struct nlattr algo_head ALIGN_NL; + char algo[sizeof(NCR_ALG_DSA_TRANSPARENT_HASH)] ALIGN_NL; + struct nlattr key_head ALIGN_NL; + uint32_t key ALIGN_NL; + struct nlattr sign_hash_head ALIGN_NL; + char sign_hash[sizeof(SIGNATURE_HASH)] ALIGN_NL; + struct nlattr input_head ALIGN_NL; + struct ncr_session_input_data input ALIGN_NL; + struct nlattr signature_head ALIGN_NL; + struct ncr_session_output_buffer signature ALIGN_NL; + } ksign; + struct __attribute__((packed)) { + struct ncr_session_once f; + struct nlattr algo_head ALIGN_NL; + char algo[sizeof(NCR_ALG_DSA_TRANSPARENT_HASH)] ALIGN_NL; + struct nlattr key_head ALIGN_NL; + uint32_t key ALIGN_NL; + struct nlattr sign_hash_head ALIGN_NL; + char sign_hash[sizeof(SIGNATURE_HASH)] ALIGN_NL; + struct nlattr input_head ALIGN_NL; + struct ncr_session_input_data input ALIGN_NL; + struct nlattr signature_head ALIGN_NL; + struct ncr_session_input_data signature ALIGN_NL; + } kverify; + uint8_t data[SIGNATURE_HASH_SIZE]; + uint8_t sig[DATA_SIZE]; + size_t sig_size; + int ret; + + fprintf(stdout, "Tests on transparent DSA key signature:"); + fflush(stdout); + + memset(data, 0x3, sizeof(data)); + + /* sign data */ + memset(&ksign.f, 0, sizeof(ksign.f)); + ksign.f.input_size = sizeof(ksign); + ksign.f.op = NCR_OP_SIGN; + ksign.algo_head.nla_len = NLA_HDRLEN + sizeof(ksign.algo); + ksign.algo_head.nla_type = NCR_ATTR_ALGORITHM; + strcpy(ksign.algo, NCR_ALG_DSA_TRANSPARENT_HASH); + ksign.key_head.nla_len = NLA_HDRLEN + sizeof(ksign.key); + ksign.key_head.nla_type = NCR_ATTR_KEY; + ksign.key = privkey; + ksign.sign_hash_head.nla_len = NLA_HDRLEN + sizeof(ksign.sign_hash); + ksign.sign_hash_head.nla_type = NCR_ATTR_SIGNATURE_HASH_ALGORITHM; + strcpy(ksign.sign_hash, SIGNATURE_HASH); + ksign.input_head.nla_len = NLA_HDRLEN + sizeof(ksign.input); + ksign.input_head.nla_type = NCR_ATTR_UPDATE_INPUT_DATA; + ksign.input.data = data; + ksign.input.data_size = SIGNATURE_HASH_SIZE; + ksign.signature_head.nla_len = NLA_HDRLEN + sizeof(ksign.signature); + ksign.signature_head.nla_type = NCR_ATTR_FINAL_OUTPUT_BUFFER; + ksign.signature.buffer = sig; + ksign.signature.buffer_size = sizeof(sig); + ksign.signature.result_size_ptr = &sig_size; + + if (ioctl(cfd, NCRIO_SESSION_ONCE, &ksign)) { + fprintf(stderr, "Error: %s:%d\n", __func__, __LINE__); + perror("ioctl(NCRIO_SESSION_ONCE)"); + return 1; + } + + /* verify signature */ + memset(&kverify.f, 0, sizeof(kverify.f)); + kverify.f.input_size = sizeof(kverify); + kverify.f.op = NCR_OP_VERIFY; + kverify.algo_head.nla_len = NLA_HDRLEN + sizeof(kverify.algo); + kverify.algo_head.nla_type = NCR_ATTR_ALGORITHM; + strcpy(kverify.algo, NCR_ALG_DSA_TRANSPARENT_HASH); + kverify.key_head.nla_len = NLA_HDRLEN + sizeof(kverify.key); + kverify.key_head.nla_type = NCR_ATTR_KEY; + kverify.key = pubkey; + kverify.sign_hash_head.nla_len = NLA_HDRLEN + sizeof(kverify.sign_hash); + kverify.sign_hash_head.nla_type = NCR_ATTR_SIGNATURE_HASH_ALGORITHM; + strcpy(kverify.sign_hash, SIGNATURE_HASH); + kverify.input_head.nla_len = NLA_HDRLEN + sizeof(kverify.input); + kverify.input_head.nla_type = NCR_ATTR_UPDATE_INPUT_DATA; + kverify.input.data = data; + kverify.input.data_size = SIGNATURE_HASH_SIZE; + kverify.signature_head.nla_len = NLA_HDRLEN + sizeof(kverify.signature); + kverify.signature_head.nla_type = NCR_ATTR_FINAL_INPUT_DATA; + kverify.signature.data = sig; + kverify.signature.data_size = sizeof(sig); + + ret = ioctl(cfd, NCRIO_SESSION_ONCE, &kverify); + if (ret < 0) { + fprintf(stderr, "Error: %s:%d\n", __func__, __LINE__); + perror("ioctl(NCRIO_SESSION_ONCE)"); + return 1; + } + + if (ret) + fprintf(stdout, " Success\n"); + else { + fprintf(stdout, " Verification Failed!\n"); + return 1; + } + + return 0; +} static int test_ncr_rsa(int cfd) { @@ -1259,6 +1486,18 @@ static int test_ncr_rsa(int cfd) return 1; } + ret = rsa_key_sign_verify_transparent(cfd, privkey, pubkey, 1); + if (ret != 0) { + fprintf(stderr, "Error: %s:%d\n", __func__, __LINE__); + return 1; + } + + ret = rsa_key_sign_verify_transparent(cfd, privkey, pubkey, 0); + if (ret != 0) { + fprintf(stderr, "Error: %s:%d\n", __func__, __LINE__); + return 1; + } + ret = rsa_key_encrypt(cfd, privkey, pubkey, 0); if (ret != 0) { fprintf(stderr, "Error: %s:%d\n", __func__, __LINE__); @@ -1383,6 +1622,12 @@ static int test_ncr_dsa(int cfd) return 1; } + ret = dsa_key_sign_verify_transparent(cfd, privkey, pubkey); + if (ret != 0) { + fprintf(stderr, "Error: %s:%d\n", __func__, __LINE__); + return 1; + } + return 0; } -- cgit