diff options
-rw-r--r-- | README | 5 | ||||
-rw-r--r-- | examples/ncr.c | 68 | ||||
-rw-r--r-- | ncr-key-wrap.c | 34 | ||||
-rw-r--r-- | ncr-key.c | 109 | ||||
-rw-r--r-- | ncr-pk.c | 105 | ||||
-rw-r--r-- | ncr-sessions.c | 84 | ||||
-rw-r--r-- | ncr.h | 12 | ||||
-rw-r--r-- | ncr_int.h | 36 | ||||
-rw-r--r-- | userspace/Makefile | 13 | ||||
-rw-r--r-- | userspace/setkey.c | 5 |
10 files changed, 343 insertions, 128 deletions
@@ -3,7 +3,10 @@ designed. The ioctl() API is in ncr.h and the userspace in ncrypto.h. For the new API to fully operate, root must load a system key (constant per system) using the setkey program. After this stage the new API should -be fully operational. +be fully operational. Example: +$ dd if=/dev/urandom of=/boot/key count=1 bs=16 +$ chmod 600 /boot/key +$ userspace/ncr-setkey /boot/key The main concept of the new API is disallow userspace applications access to cryptographic keys. Operations should be possible (such diff --git a/examples/ncr.c b/examples/ncr.c index 3cfc206..cc7b463 100644 --- a/examples/ncr.c +++ b/examples/ncr.c @@ -385,7 +385,6 @@ test_ncr_wrap_key(int cfd) { int i; struct ncr_data_init_st dinit; - struct ncr_key_generate_st kgen; ncr_key_t key, key2; struct ncr_key_data_st keydata; struct ncr_data_st kdata; @@ -572,7 +571,6 @@ test_ncr_store_wrap_key(int cfd) { int i; struct ncr_data_init_st dinit; - struct ncr_key_generate_st kgen; ncr_key_t key2; struct ncr_key_data_st keydata; struct ncr_data_st kdata; @@ -709,29 +707,29 @@ struct aes_vectors_st { const uint8_t* ciphertext; } aes_vectors[] = { { - .key = "\xc0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", - .plaintext = "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", - .ciphertext = "\x4b\xc3\xf8\x83\x45\x0c\x11\x3c\x64\xca\x42\xe1\x11\x2a\x9e\x87", + .key = (uint8_t*)"\xc0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", + .plaintext = (uint8_t*)"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", + .ciphertext = (uint8_t*)"\x4b\xc3\xf8\x83\x45\x0c\x11\x3c\x64\xca\x42\xe1\x11\x2a\x9e\x87", }, { - .key = "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", - .plaintext = "\xf3\x44\x81\xec\x3c\xc6\x27\xba\xcd\x5d\xc3\xfb\x08\xf2\x73\xe6", - .ciphertext = "\x03\x36\x76\x3e\x96\x6d\x92\x59\x5a\x56\x7c\xc9\xce\x53\x7f\x5e", + .key = (uint8_t*)"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", + .plaintext = (uint8_t*)"\xf3\x44\x81\xec\x3c\xc6\x27\xba\xcd\x5d\xc3\xfb\x08\xf2\x73\xe6", + .ciphertext = (uint8_t*)"\x03\x36\x76\x3e\x96\x6d\x92\x59\x5a\x56\x7c\xc9\xce\x53\x7f\x5e", }, { - .key = "\x10\xa5\x88\x69\xd7\x4b\xe5\xa3\x74\xcf\x86\x7c\xfb\x47\x38\x59", - .plaintext = "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", - .ciphertext = "\x6d\x25\x1e\x69\x44\xb0\x51\xe0\x4e\xaa\x6f\xb4\xdb\xf7\x84\x65", + .key = (uint8_t*)"\x10\xa5\x88\x69\xd7\x4b\xe5\xa3\x74\xcf\x86\x7c\xfb\x47\x38\x59", + .plaintext = (uint8_t*)"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", + .ciphertext = (uint8_t*)"\x6d\x25\x1e\x69\x44\xb0\x51\xe0\x4e\xaa\x6f\xb4\xdb\xf7\x84\x65", }, { - .key = "\xca\xea\x65\xcd\xbb\x75\xe9\x16\x9e\xcd\x22\xeb\xe6\xe5\x46\x75", - .plaintext = "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", - .ciphertext = "\x6e\x29\x20\x11\x90\x15\x2d\xf4\xee\x05\x81\x39\xde\xf6\x10\xbb", + .key = (uint8_t*)"\xca\xea\x65\xcd\xbb\x75\xe9\x16\x9e\xcd\x22\xeb\xe6\xe5\x46\x75", + .plaintext = (uint8_t*)"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", + .ciphertext = (uint8_t*)"\x6e\x29\x20\x11\x90\x15\x2d\xf4\xee\x05\x81\x39\xde\xf6\x10\xbb", }, { - .key = "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe", - .plaintext = "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", - .ciphertext = "\x9b\xa4\xa9\x14\x3f\x4e\x5d\x40\x48\x52\x1c\x4f\x88\x77\xd8\x8e", + .key = (uint8_t*)"\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfe", + .plaintext = (uint8_t*)"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", + .ciphertext = (uint8_t*)"\x9b\xa4\xa9\x14\x3f\x4e\x5d\x40\x48\x52\x1c\x4f\x88\x77\xd8\x8e", }, }; @@ -740,7 +738,6 @@ static int test_ncr_aes(int cfd) { struct ncr_data_init_st dinit; - struct ncr_key_generate_st kgen; ncr_key_t key; struct ncr_key_data_st keydata; struct ncr_data_st kdata; @@ -961,20 +958,20 @@ struct hash_vectors_st { .name = "SHA1", .algorithm = NCR_ALG_SHA1, .key = NULL, - .plaintext = "what do ya want for nothing?", + .plaintext = (uint8_t*)"what do ya want for nothing?", .plaintext_size = sizeof("what do ya want for nothing?")-1, - .output = "\x8f\x82\x03\x94\xf9\x53\x35\x18\x20\x45\xda\x24\xf3\x4d\xe5\x2b\xf8\xbc\x34\x32", + .output = (uint8_t*)"\x8f\x82\x03\x94\xf9\x53\x35\x18\x20\x45\xda\x24\xf3\x4d\xe5\x2b\xf8\xbc\x34\x32", .output_size = 20, .op = NCR_OP_DIGEST, }, { .name = "HMAC-MD5", .algorithm = NCR_ALG_HMAC_MD5, - .key = "Jefe", + .key = (uint8_t*)"Jefe", .key_size = 4, - .plaintext = "what do ya want for nothing?", + .plaintext = (uint8_t*)"what do ya want for nothing?", .plaintext_size = sizeof("what do ya want for nothing?")-1, - .output = "\x75\x0c\x78\x3e\x6a\xb0\xb5\x03\xea\xa8\x6e\x31\x0a\x5d\xb7\x38", + .output = (uint8_t*)"\x75\x0c\x78\x3e\x6a\xb0\xb5\x03\xea\xa8\x6e\x31\x0a\x5d\xb7\x38", .output_size = 16, .op = NCR_OP_MAC, }, @@ -982,44 +979,44 @@ struct hash_vectors_st { { .name = "HMAC-SHA224", .algorithm = NCR_ALG_HMAC_SHA2_224, - .key = "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b", + .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 = "Hi There", + .plaintext = (uint8_t*)"Hi There", .plaintext_size = sizeof("Hi There")-1, - .output = "\x89\x6f\xb1\x12\x8a\xbb\xdf\x19\x68\x32\x10\x7c\xd4\x9d\xf3\x3f\x47\xb4\xb1\x16\x99\x12\xba\x4f\x53\x68\x4b\x22", + .output = (uint8_t*)"\x89\x6f\xb1\x12\x8a\xbb\xdf\x19\x68\x32\x10\x7c\xd4\x9d\xf3\x3f\x47\xb4\xb1\x16\x99\x12\xba\x4f\x53\x68\x4b\x22", .output_size = 28, .op = NCR_OP_MAC, }, { .name = "HMAC-SHA256", .algorithm = NCR_ALG_HMAC_SHA2_256, - .key = "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b", + .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 = "Hi There", + .plaintext = (uint8_t*)"Hi There", .plaintext_size = sizeof("Hi There")-1, - .output = "\xb0\x34\x4c\x61\xd8\xdb\x38\x53\x5c\xa8\xaf\xce\xaf\x0b\xf1\x2b\x88\x1d\xc2\x00\xc9\x83\x3d\xa7\x26\xe9\x37\x6c\x2e\x32\xcf\xf7", + .output = (uint8_t*)"\xb0\x34\x4c\x61\xd8\xdb\x38\x53\x5c\xa8\xaf\xce\xaf\x0b\xf1\x2b\x88\x1d\xc2\x00\xc9\x83\x3d\xa7\x26\xe9\x37\x6c\x2e\x32\xcf\xf7", .output_size = 32, .op = NCR_OP_MAC, }, { .name = "HMAC-SHA384", .algorithm = NCR_ALG_HMAC_SHA2_384, - .key = "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b", + .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 = "Hi There", + .plaintext = (uint8_t*)"Hi There", .plaintext_size = sizeof("Hi There")-1, - .output = "\xaf\xd0\x39\x44\xd8\x48\x95\x62\x6b\x08\x25\xf4\xab\x46\x90\x7f\x15\xf9\xda\xdb\xe4\x10\x1e\xc6\x82\xaa\x03\x4c\x7c\xeb\xc5\x9c\xfa\xea\x9e\xa9\x07\x6e\xde\x7f\x4a\xf1\x52\xe8\xb2\xfa\x9c\xb6", + .output = (uint8_t*)"\xaf\xd0\x39\x44\xd8\x48\x95\x62\x6b\x08\x25\xf4\xab\x46\x90\x7f\x15\xf9\xda\xdb\xe4\x10\x1e\xc6\x82\xaa\x03\x4c\x7c\xeb\xc5\x9c\xfa\xea\x9e\xa9\x07\x6e\xde\x7f\x4a\xf1\x52\xe8\xb2\xfa\x9c\xb6", .output_size = 48, .op = NCR_OP_MAC, }, { .name = "HMAC-SHA512", .algorithm = NCR_ALG_HMAC_SHA2_512, - .key = "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b", + .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 = "Hi There", + .plaintext = (uint8_t*)"Hi There", .plaintext_size = sizeof("Hi There")-1, - .output = "\x87\xaa\x7c\xde\xa5\xef\x61\x9d\x4f\xf0\xb4\x24\x1a\x1d\x6c\xb0\x23\x79\xf4\xe2\xce\x4e\xc2\x78\x7a\xd0\xb3\x05\x45\xe1\x7c\xde\xda\xa8\x33\xb7\xd6\xb8\xa7\x02\x03\x8b\x27\x4e\xae\xa3\xf4\xe4\xbe\x9d\x91\x4e\xeb\x61\xf1\x70\x2e\x69\x6c\x20\x3a\x12\x68\x54", + .output = (uint8_t*)"\x87\xaa\x7c\xde\xa5\xef\x61\x9d\x4f\xf0\xb4\x24\x1a\x1d\x6c\xb0\x23\x79\xf4\xe2\xce\x4e\xc2\x78\x7a\xd0\xb3\x05\x45\xe1\x7c\xde\xda\xa8\x33\xb7\xd6\xb8\xa7\x02\x03\x8b\x27\x4e\xae\xa3\xf4\xe4\xbe\x9d\x91\x4e\xeb\x61\xf1\x70\x2e\x69\x6c\x20\x3a\x12\x68\x54", .output_size = 64, .op = NCR_OP_MAC, }, @@ -1032,7 +1029,6 @@ static int test_ncr_hash(int cfd) { struct ncr_data_init_st dinit; - struct ncr_key_generate_st kgen; ncr_key_t key; struct ncr_key_data_st keydata; struct ncr_data_st kdata; diff --git a/ncr-key-wrap.c b/ncr-key-wrap.c index 5fda82c..5510436 100644 --- a/ncr-key-wrap.c +++ b/ncr-key-wrap.c @@ -428,10 +428,10 @@ int ret; return ret; } - wkey = ncr_key_item_get( key_lst, wrap.keytowrap); - if (wkey == NULL) { + ret = ncr_key_item_get_read( &wkey, key_lst, wrap.keytowrap); + if (ret < 0) { err(); - return -EINVAL; + return ret; } if (!(wkey->flags & NCR_KEY_FLAG_WRAPPABLE)) { @@ -439,10 +439,9 @@ int ret; return -EPERM; } - key = ncr_key_item_get( key_lst, wrap.key.key); - if (key == NULL) { + ret = ncr_key_item_get_read( &key, key_lst, wrap.key.key); + if (ret < 0) { err(); - ret = -EINVAL; goto fail; } @@ -492,16 +491,15 @@ int ret; return ret; } - wkey = ncr_key_item_get( key_lst, wrap.keytowrap); - if (wkey == NULL) { + ret = ncr_key_item_get_write( &wkey, key_lst, wrap.keytowrap); + if (ret < 0) { err(); - return -EINVAL; + return ret; } - key = ncr_key_item_get( key_lst, wrap.key.key); - if (key == NULL) { + ret = ncr_key_item_get_read( &key, key_lst, wrap.key.key); + if (ret < 0) { err(); - ret = -EINVAL; goto fail; } @@ -554,10 +552,10 @@ int ret; return ret; } - wkey = ncr_key_item_get( key_lst, wrap.keytowrap); - if (wkey == NULL) { + ret = ncr_key_item_get_read( &wkey, key_lst, wrap.keytowrap); + if (ret < 0) { err(); - return -EINVAL; + return ret; } if (!(wkey->flags & NCR_KEY_FLAG_WRAPPABLE)) { @@ -613,10 +611,10 @@ int ret; return ret; } - wkey = ncr_key_item_get( key_lst, wrap.keytowrap); - if (wkey == NULL) { + ret = ncr_key_item_get_write( &wkey, key_lst, wrap.keytowrap); + if (ret < 0) { err(); - return -EINVAL; + return ret; } data = ncr_data_item_get(data_lst, wrap.data); @@ -61,21 +61,80 @@ int mx = 1; } /* returns the data item corresponding to desc */ -struct key_item_st* ncr_key_item_get( struct list_sem_st* lst, ncr_key_t desc) +int ncr_key_item_get_read(struct key_item_st**st, struct list_sem_st* lst, + ncr_key_t desc) { struct key_item_st* item; +int ret; + + *st = NULL; + down(&lst->sem); list_for_each_entry(item, &lst->list, list) { if (item->desc == desc) { atomic_inc(&item->refcnt); - up(&lst->sem); - return item; + + if (atomic_read(&item->writer) != 0) { + /* writer in place busy */ + atomic_dec(&item->refcnt); + ret = -EBUSY; + goto exit; + } + + *st = item; + ret = 0; + goto exit; } } + + err(); + ret = -EINVAL; +exit: up(&lst->sem); + return ret; +} + +/* as above but will never return anything that + * is in use. + */ +int ncr_key_item_get_write( struct key_item_st** st, + struct list_sem_st* lst, ncr_key_t desc) +{ +struct key_item_st* item; +int ret; + + *st = NULL; + + down(&lst->sem); + list_for_each_entry(item, &lst->list, list) { + if (item->desc == desc) { + /* do not return items that are in use already */ + + if (atomic_add_unless(&item->writer, 1, 1)==0) { + /* another writer so busy */ + ret = -EBUSY; + goto exit; + } + + if (atomic_add_unless(&item->refcnt, 1, 2)==0) { + /* some reader is active so busy */ + atomic_dec(&item->writer); + ret = -EBUSY; + goto exit; + } + + *st = item; + ret = 0; + goto exit; + } + } err(); - return NULL; + ret = -EINVAL; + +exit: + up(&lst->sem); + return ret; } void _ncr_key_item_put( struct key_item_st* item) @@ -85,6 +144,8 @@ void _ncr_key_item_put( struct key_item_st* item) ncr_key_clear(item); kfree(item); } + if (atomic_read(&item->writer) > 0) + atomic_dec(&item->writer); } int ncr_key_init(struct list_sem_st* lst, void __user* arg) @@ -108,6 +169,7 @@ int ncr_key_init(struct list_sem_st* lst, void __user* arg) memset(key, 0, sizeof(*key)); atomic_set(&key->refcnt, 1); + atomic_set(&key->writer, 0); down(&lst->sem); @@ -169,10 +231,10 @@ int ret; return ret; } - item = ncr_key_item_get( key_lst, data.key); - if (item == NULL) { + ret = ncr_key_item_get_read( &item, key_lst, data.key); + if (ret < 0) { err(); - return -EINVAL; + return ret; } ditem = ncr_data_item_get( data_lst, data.data); @@ -250,12 +312,12 @@ int ret; return ret; } - item = ncr_key_item_get( key_lst, data.key); - if (item == NULL) { + ret = ncr_key_item_get_write( &item, key_lst, data.key); + if (ret < 0) { err(); - return -EINVAL; + return ret; } - + ditem = ncr_data_item_get( data_lst, data.data); if (ditem == NULL) { err(); @@ -331,6 +393,8 @@ static void ncr_key_clear(struct key_item_st* item) ncr_pk_clear(item); } memset(&item->key, 0, sizeof(item->key)); + + return; } /* Generate a secret key @@ -348,10 +412,10 @@ size_t size; return ret; } - item = ncr_key_item_get( lst, gen.desc); - if (item == NULL) { + ret = ncr_key_item_get_write( &item, lst, gen.desc); + if (ret < 0) { err(); - return -EINVAL; + return ret; } ncr_key_clear(item); @@ -404,10 +468,10 @@ int ret; return ret; } - item = ncr_key_item_get( lst, info.key); - if (item == NULL) { + ret = ncr_key_item_get_read(&item, lst, info.key); + if (ret < 0) { err(); - return -EINVAL; + return ret; } info.flags = item->flags; @@ -432,16 +496,15 @@ int ret; return ret; } - private = ncr_key_item_get( lst, gen.desc); - if (private == NULL) { + ret = ncr_key_item_get_write( &private, lst, gen.desc); + if (ret < 0) { err(); - return -EINVAL; + goto fail; } - public = ncr_key_item_get( lst, gen.desc2); - if (public == NULL) { + ret = ncr_key_item_get_write( &public, lst, gen.desc2); + if (ret < 0) { err(); - ret = -EINVAL; goto fail; } @@ -283,7 +283,6 @@ struct keygen_st st; return 0; } - int ncr_pk_queue_init(void) { pk_wq = @@ -301,3 +300,107 @@ void ncr_pk_queue_deinit(void) flush_workqueue(pk_wq); destroy_workqueue(pk_wq); } + +/* Encryption/Decryption + */ + +void ncr_pk_cipher_deinit(struct ncr_pk_ctx* ctx) +{ + ctx->key = NULL; +} + +int ncr_pk_cipher_init(ncr_algorithm_t algo, + struct ncr_pk_ctx* ctx, struct ncr_key_params_st* params, + struct key_item_st *key) +{ + memset(ctx, 0, sizeof(*ctx)); + + if (key->algorithm != algo) { + err(); + return -EINVAL; + } + + ctx->algorithm = algo; + ctx->key = key; + + switch(algo) { + case NCR_ALG_RSA: + if (params->params.rsa.type == RSA_PKCS1_V1_5) + ctx->type = LTC_LTC_PKCS_1_V1_5; + else + ctx->type = LTC_LTC_PKCS_1_OAEP; + + ctx->hash = params->params.rsa.hash; + break; + case NCR_ALG_DSA: + break; + default: + err(); + return -EINVAL; + } + + return 0; +} + +int ncr_pk_cipher_encrypt(const struct ncr_pk_ctx* ctx, + const void* input, size_t input_size, + void* output, size_t *output_size) +{ +int cret; +unsigned long osize = *output_size; + + switch(ctx->algorithm) { + case NCR_ALG_RSA: + cret = rsa_encrypt_key_ex( input, input_size, output, &osize, + NULL, 0, ctx->hash, ctx->type, &ctx->key->key.pk.rsa); + + if (cret != CRYPT_OK) { + err(); + return tomerr(cret); + } + *output_size = osize; + break; + case NCR_ALG_DSA: + return -EINVAL; + break; + default: + err(); + return -EINVAL; + } + + return 0; +} + +int ncr_pk_cipher_decrypt(const struct ncr_pk_ctx* ctx, const void* input, size_t input_size, + void* output, size_t *output_size) +{ +int cret; +unsigned long osize = *output_size; +int stat; + + switch(ctx->algorithm) { + case NCR_ALG_RSA: + cret = rsa_decrypt_key_ex( input, input_size, output, &osize, + NULL, 0, ctx->hash, ctx->type, &stat, &ctx->key->key.pk.rsa); + + if (cret != CRYPT_OK) { + err(); + return tomerr(cret); + } + + if (stat==0) { + err(); + return -EINVAL; + } + *output_size = osize; + break; + case NCR_ALG_DSA: + return -EINVAL; + break; + default: + err(); + return -EINVAL; + } + + return 0; +} diff --git a/ncr-sessions.c b/ncr-sessions.c index f8157fb..a461bf1 100644 --- a/ncr-sessions.c +++ b/ncr-sessions.c @@ -180,7 +180,6 @@ int i = 0; static int _ncr_session_init(struct ncr_lists* lists, struct ncr_session_st* session) { struct session_item_st* ns = NULL; - struct key_item_st *key = NULL; int ret; const char* str; @@ -202,57 +201,63 @@ static int _ncr_session_init(struct ncr_lists* lists, struct ncr_session_st* ses case NCR_OP_ENCRYPT: case NCR_OP_DECRYPT: /* read key */ - key = ncr_key_item_get( &lists->key, session->params.key); - if (key == NULL) { - err(); - ret = -EINVAL; - goto fail; - } - - if (key->type != NCR_KEY_TYPE_SECRET) { - err(); - ret = -EINVAL; - goto fail; - } - - ret = cryptodev_cipher_init(&ns->ctx, str, key->key.secret.data, key->key.secret.size); + ret = ncr_key_item_get_read( &ns->key, &lists->key, session->params.key); if (ret < 0) { err(); goto fail; } - if (algo_needs_iv(session->algorithm)) { - if (session->params.params.cipher.iv_size > sizeof(session->params.params.cipher.iv)) { + if (ns->key->type == NCR_KEY_TYPE_SECRET) { + ret = cryptodev_cipher_init(&ns->ctx.cipher, str, + ns->key->key.secret.data, ns->key->key.secret.size); + if (ret < 0) { + err(); + goto fail; + } + + if (algo_needs_iv(session->algorithm)) { + if (session->params.params.cipher.iv_size > sizeof(session->params.params.cipher.iv)) { + err(); + ret = -EINVAL; + goto fail; + } + cryptodev_cipher_set_iv(&ns->ctx.cipher, session->params.params.cipher.iv, session->params.params.cipher.iv_size); + } + } else if (ns->key->type == NCR_KEY_TYPE_PRIVATE || ns->key->type == NCR_KEY_TYPE_PUBLIC) { + ret = ncr_pk_cipher_init(ns->algo, &ns->ctx.pk, + &session->params, ns->key); + if (ret < 0) { err(); - ret = -EINVAL; goto fail; } - cryptodev_cipher_set_iv(&ns->ctx, session->params.params.cipher.iv, session->params.params.cipher.iv_size); + } else { + err(); + ret = -EINVAL; + goto fail; } break; case NCR_OP_MAC: /* read key */ - key = ncr_key_item_get( &lists->key, session->params.key); - if (key == NULL) { + ret = ncr_key_item_get_read( &ns->key, &lists->key, session->params.key); + if (ret < 0) { err(); - ret = -EINVAL; goto fail; } - if (key->type != NCR_KEY_TYPE_SECRET) { + if (ns->key->type != NCR_KEY_TYPE_SECRET) { err(); ret = -EINVAL; goto fail; } - ret = cryptodev_hash_init(&ns->hctx, str, 1, key->key.secret.data, key->key.secret.size); + ret = cryptodev_hash_init(&ns->ctx.hash, str, 1, ns->key->key.secret.data, ns->key->key.secret.size); if (ret < 0) { err(); goto fail; } - ret = cryptodev_hash_reset(&ns->hctx); + ret = cryptodev_hash_reset(&ns->ctx.hash); if (ret < 0) { err(); goto fail; @@ -260,13 +265,13 @@ static int _ncr_session_init(struct ncr_lists* lists, struct ncr_session_st* ses break; case NCR_OP_DIGEST: - ret = cryptodev_hash_init(&ns->hctx, str, 0, NULL, 0); + ret = cryptodev_hash_init(&ns->ctx.hash, str, 0, NULL, 0); if (ret < 0) { err(); goto fail; } - ret = cryptodev_hash_reset(&ns->hctx); + ret = cryptodev_hash_reset(&ns->ctx.hash); if (ret < 0) { err(); goto fail; @@ -283,12 +288,12 @@ static int _ncr_session_init(struct ncr_lists* lists, struct ncr_session_st* ses session->ses = ns->desc; fail: - if (key) _ncr_key_item_put(key); if (ret < 0) { - if (ns->ctx.init) - cryptodev_cipher_deinit(&ns->ctx); - if (ns->hctx.init) - cryptodev_hash_deinit(&ns->hctx); + if (ns->key) _ncr_key_item_put(ns->key); + if (ns->ctx.cipher.init) + cryptodev_cipher_deinit(&ns->ctx.cipher); + if (ns->ctx.hash.init) + cryptodev_hash_deinit(&ns->ctx.hash); _ncr_session_remove(&lists->sessions, ns->desc); } @@ -353,7 +358,7 @@ static int _ncr_session_update(struct ncr_lists* lists, struct ncr_session_op_st } /* read key */ - ret = _cryptodev_cipher_encrypt(&sess->ctx, data->data, data->data_size, odata->data, data->data_size); + ret = _cryptodev_cipher_encrypt(&sess->ctx.cipher, data->data, data->data_size, odata->data, data->data_size); if (ret < 0) { err(); goto fail; @@ -385,7 +390,7 @@ static int _ncr_session_update(struct ncr_lists* lists, struct ncr_session_op_st } /* read key */ - ret = _cryptodev_cipher_decrypt(&sess->ctx, data->data, data->data_size, odata->data, data->data_size); + ret = _cryptodev_cipher_decrypt(&sess->ctx.cipher, data->data, data->data_size, odata->data, data->data_size); if (ret < 0) { err(); goto fail; @@ -405,7 +410,7 @@ static int _ncr_session_update(struct ncr_lists* lists, struct ncr_session_op_st goto fail; } - ret = _cryptodev_hash_update(&sess->hctx, data->data, data->data_size); + ret = _cryptodev_hash_update(&sess->ctx.hash, data->data, data->data_size); if (ret < 0) { err(); goto fail; @@ -451,6 +456,7 @@ static void _ncr_session_remove(struct list_sem_st* lst, ncr_session_t desc) list_for_each_entry_safe(item, tmp, &lst->list, list) { if(item->desc == desc) { list_del(&item->list); + if (item->key) _ncr_key_item_put(item->key); _ncr_sessions_item_put( item); /* decrement ref count */ break; } @@ -463,7 +469,6 @@ static void _ncr_session_remove(struct list_sem_st* lst, ncr_session_t desc) static int _ncr_session_final(struct ncr_lists* lists, struct ncr_session_op_st* op) { - struct key_item_st *key = NULL; int ret; struct session_item_st* sess; struct data_item_st* data = NULL; @@ -484,7 +489,7 @@ static int _ncr_session_final(struct ncr_lists* lists, struct ncr_session_op_st* op->data.cipher.ciphertext != NCR_DATA_INVALID) { _ncr_session_update(lists, op); } - cryptodev_cipher_deinit(&sess->ctx); + cryptodev_cipher_deinit(&sess->ctx.cipher); break; case NCR_OP_MAC: case NCR_OP_DIGEST: @@ -505,10 +510,10 @@ static int _ncr_session_final(struct ncr_lists* lists, struct ncr_session_op_st* ret = -EINVAL; goto fail; } - ret = cryptodev_hash_final(&sess->hctx, odata->data); + ret = cryptodev_hash_final(&sess->ctx.hash, odata->data); odata->data_size = digest_size; - cryptodev_hash_deinit(&sess->hctx); + cryptodev_hash_deinit(&sess->ctx.hash); break; default: err(); @@ -519,7 +524,6 @@ static int _ncr_session_final(struct ncr_lists* lists, struct ncr_session_op_st* ret = 0; fail: - if (key) _ncr_key_item_put(key); if (odata) _ncr_data_item_put(odata); if (data) _ncr_data_item_put(data); _ncr_sessions_item_put(sess); @@ -8,6 +8,7 @@ #define NCR_CIPHER_MAX_BLOCK_LEN 32 #define NCR_CIPHER_MAX_KEY_LEN 64 #define NCR_HASH_MAX_OUTPUT_SIZE 64 +#define NCR_PK_MAX_OBJECT 640 typedef enum { NCR_ALG_NONE, @@ -126,6 +127,11 @@ struct ncr_key_generate_st { struct ncr_key_generate_params_st params; }; +typedef enum { + RSA_PKCS1_V1_5, + RSA_PKCS1_OAEP, +} ncr_rsa_type_t; + /* used in derivation/encryption */ struct ncr_key_params_st { @@ -137,9 +143,13 @@ struct ncr_key_params_st { size_t iv_size; } cipher; struct { - void * peer_public; + uint8_t peer_public[NCR_PK_MAX_OBJECT]; size_t peer_public_size; } dh; + struct { + ncr_rsa_type_t type; + ncr_algorithm_t hash; /* for OAEP */ + } rsa; } params; }; @@ -10,13 +10,26 @@ #define err() printk(KERN_DEBUG"ncr: %s: %s: %d\n", __FILE__, __func__, __LINE__) +struct ncr_pk_ctx { + ncr_algorithm_t algorithm; /* algorithm */ + ncr_algorithm_t hash; /* if hash is required is of this type */ + int type; /* libtomcrypt type */ + + struct key_item_st * key; +}; + struct session_item_st { struct list_head list; ncr_algorithm_t algo; ncr_crypto_op_t op; - struct cipher_data ctx; - struct hash_data hctx; + union { + struct cipher_data cipher; + struct hash_data hash; + struct ncr_pk_ctx pk; + } ctx; + + struct key_item_st* key; atomic_t refcnt; ncr_session_t desc; @@ -64,6 +77,7 @@ struct key_item_st { } key; atomic_t refcnt; + atomic_t writer; /* owner. The one charged with this */ uid_t uid; @@ -116,7 +130,11 @@ int ncr_key_generate_pair(struct list_sem_st* lst, void __user* arg); int ncr_key_derive(struct list_sem_st*, void __user* arg); int ncr_key_get_public(struct list_sem_st* lst, void __user* arg); -struct key_item_st* ncr_key_item_get( struct list_sem_st* lst, ncr_key_t desc); +int ncr_key_item_get_read(struct key_item_st**st, struct list_sem_st* lst, + ncr_key_t desc); +/* get key item for writing */ +int ncr_key_item_get_write( struct key_item_st** st, + struct list_sem_st* lst, ncr_key_t desc); void _ncr_key_item_put( struct key_item_st* item); typedef enum { @@ -193,4 +211,16 @@ int ncr_pk_unpack( struct key_item_st * key, const void * packed, size_t packed_ int ncr_pk_queue_init(void); void ncr_pk_queue_deinit(void); +/* encryption/decryption */ +int ncr_pk_cipher_init(ncr_algorithm_t algo, + struct ncr_pk_ctx* ctx, struct ncr_key_params_st* params, + struct key_item_st *key); +void ncr_pk_cipher_deinit(struct ncr_pk_ctx* ctx); +int ncr_pk_cipher_encrypt(const struct ncr_pk_ctx* ctx, const void* input, + size_t input_size, void* output, size_t *output_size); +int ncr_pk_cipher_decrypt(const struct ncr_pk_ctx* ctx, const void* input, + size_t input_size, void* output, size_t *output_size); + + + #endif diff --git a/userspace/Makefile b/userspace/Makefile index 1a95ac7..fddefb3 100644 --- a/userspace/Makefile +++ b/userspace/Makefile @@ -1,9 +1,12 @@ -KERNEL_DIR ?= /lib/modules/$(shell uname -r)/build +CC = gcc +CFLAGS = -Wall -g -O2 -hostprogs := setkey -setkey-objs := setkey.o +progs := ncr-setkey -all: $(hostprogs) +all: $(progs) + +ncr-setkey: setkey.c + $(CC) $(CFLAGS) $< -o $@ clean: - rm -f *.o *~ setkey + rm -f *.o *~ ncr-setkey diff --git a/userspace/setkey.c b/userspace/setkey.c index 535773d..d0a2b62 100644 --- a/userspace/setkey.c +++ b/userspace/setkey.c @@ -47,6 +47,11 @@ int main(int argc, char** argv) memset(&key, 0, sizeof(key)); fp = fopen(argv[1], "r"); + if (fp == NULL) { + fprintf(stderr, "Cannot read %s\n", argv[1]); + exit(1); + } + size = fread(key.key, 1, sizeof(key.key), fp); if (size < 16) { fprintf(stderr, "Illegal key!\n"); |