diff options
author | Miloslav Trmač <mitr@redhat.com> | 2010-08-27 09:02:55 +0200 |
---|---|---|
committer | Miloslav Trmač <mitr@redhat.com> | 2010-08-27 09:02:55 +0200 |
commit | dd5317620d70e6b438e40370163257e47ca385a3 (patch) | |
tree | f195a8cb4aa2ff6fbb5a51e0e6c13df1968401b6 | |
parent | c9c3bf34c8f7c12c0d961bf7c0beb13ad5b24950 (diff) | |
parent | bf6a75c801ece98f608df29df3846033d22f28d7 (diff) | |
download | kernel-crypto-dd5317620d70e6b438e40370163257e47ca385a3.tar.gz kernel-crypto-dd5317620d70e6b438e40370163257e47ca385a3.tar.xz kernel-crypto-dd5317620d70e6b438e40370163257e47ca385a3.zip |
Merge branch 'pk-transparent-hash'
Conflicts:
ncr-int.h
-rw-r--r-- | examples/pk.c | 245 | ||||
-rw-r--r-- | ncr-int.h | 4 | ||||
-rw-r--r-- | ncr-pk.c | 4 | ||||
-rw-r--r-- | ncr-sessions.c | 75 | ||||
-rw-r--r-- | ncr.h | 4 |
5 files changed, 318 insertions, 14 deletions
diff --git a/examples/pk.c b/examples/pk.c index 81c5b49263d..5ccb73e5205 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" @@ -1035,6 +1036,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)) { @@ -1142,6 +1263,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) { @@ -1253,6 +1480,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__); @@ -1377,6 +1616,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; } diff --git a/ncr-int.h b/ncr-int.h index a6b37397c5f..87964b08065 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. @@ -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; } diff --git a/ncr-sessions.c b/ncr-sessions.c index 3691127a757..c65db2f751e 100644 --- a/ncr-sessions.c +++ b/ncr-sessions.c @@ -49,6 +49,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; @@ -165,6 +170,7 @@ static 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); @@ -272,8 +278,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 @@ -578,6 +590,15 @@ static struct session_item_st *_ncr_session_init(struct ncr_lists *lists, 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; @@ -910,10 +931,27 @@ static int _ncr_session_update(struct session_item_st *sess, 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: @@ -997,10 +1035,14 @@ static int _ncr_session_final(struct ncr_lists *lists, 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) @@ -1036,10 +1078,14 @@ static int _ncr_session_final(struct ncr_lists *lists, 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); @@ -1130,6 +1176,11 @@ static int _ncr_session_update_key(struct ncr_lists *lists, 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) { @@ -69,6 +69,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 */ |