summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMiloslav Trmač <mitr@redhat.com>2010-08-27 08:31:36 +0200
committerMiloslav Trmač <mitr@redhat.com>2010-08-27 08:38:20 +0200
commit387d5847ee502cdb03bbf5771575438ddebf2624 (patch)
tree3d2b90305d35ece095d7c9567c0ea30c1e853fbc
parent5ec167e240a8002bba3cc37e22553c888c7d4133 (diff)
downloadcryptodev-linux-387d5847ee502cdb03bbf5771575438ddebf2624.tar.gz
cryptodev-linux-387d5847ee502cdb03bbf5771575438ddebf2624.tar.xz
cryptodev-linux-387d5847ee502cdb03bbf5771575438ddebf2624.zip
Implement PK signatures with transparent hashes
-rw-r--r--ncr-int.h9
-rw-r--r--ncr-sessions.c70
-rw-r--r--ncr.h4
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 */