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 5e86aff..764abdb 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 41f8a4c..84433cc 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 47981d1..e486356 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