diff options
author | Miloslav Trmač <mitr@redhat.com> | 2010-08-27 08:31:36 +0200 |
---|---|---|
committer | Miloslav Trmač <mitr@redhat.com> | 2010-08-27 08:38:20 +0200 |
commit | 387d5847ee502cdb03bbf5771575438ddebf2624 (patch) | |
tree | 3d2b90305d35ece095d7c9567c0ea30c1e853fbc | |
parent | 5ec167e240a8002bba3cc37e22553c888c7d4133 (diff) | |
download | cryptodev-linux-387d5847ee502cdb03bbf5771575438ddebf2624.tar.gz cryptodev-linux-387d5847ee502cdb03bbf5771575438ddebf2624.tar.xz cryptodev-linux-387d5847ee502cdb03bbf5771575438ddebf2624.zip |
Implement PK signatures with transparent hashes
-rw-r--r-- | ncr-int.h | 9 | ||||
-rw-r--r-- | ncr-sessions.c | 70 | ||||
-rw-r--r-- | ncr.h | 4 |
3 files changed, 70 insertions, 13 deletions
@@ -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) { @@ -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 */ |