From 707ae74fc7aae4f9aaef480c11289b69356bbe51 Mon Sep 17 00:00:00 2001 From: Miloslav Trmač Date: Sat, 24 Jul 2010 03:31:39 +0200 Subject: Allow parrallel build (make -j$$$$N) Using "$(MAKE)" instead of "make" allows make to recognize the subprocesses and manage the parallel build. --- Makefile | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Makefile b/Makefile index 0b031d4..04f4984 100644 --- a/Makefile +++ b/Makefile @@ -75,22 +75,22 @@ cryptodev-objs = cryptodev_main.o cryptodev_cipher.o ncr.o \ obj-m += cryptodev.o build: - @make version.h - make -C $(KERNEL_DIR) SUBDIRS=`pwd` modules + @$(MAKE) version.h + $(MAKE) -C $(KERNEL_DIR) SUBDIRS=`pwd` modules install: - make -C $(KERNEL_DIR) SUBDIRS=`pwd` modules_install + $(MAKE) -C $(KERNEL_DIR) SUBDIRS=`pwd` modules_install @echo "Installing cryptodev.h in /usr/include/crypto ..." @install -D cryptodev.h /usr/include/crypto/cryptodev.h @install -D ncr.h /usr/include/crypto/ncr.h clean: - make -C $(KERNEL_DIR) SUBDIRS=`pwd` clean + $(MAKE) -C $(KERNEL_DIR) SUBDIRS=`pwd` clean rm -f $(hostprogs) - KERNEL_DIR=$(KERNEL_DIR) make -C examples clean + KERNEL_DIR=$(KERNEL_DIR) $(MAKE) -C examples clean check: - KERNEL_DIR=$(KERNEL_DIR) make -C examples check + KERNEL_DIR=$(KERNEL_DIR) $(MAKE) -C examples check FILEBASE = cryptodev-linux-$(VERSION) TMPDIR ?= /tmp -- cgit From c13723d4a2a9627f4cd85d47954ab1fd3a115dbd Mon Sep 17 00:00:00 2001 From: Miloslav Trmač Date: Fri, 23 Jul 2010 21:51:52 +0200 Subject: Reformat for kernel's (make headers_install) (make headers_install) automatically removes the __user annotations, but it doesn't recognize "__user*". --- ncr.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ncr.h b/ncr.h index f6c8f9f..cd82a62 100644 --- a/ncr.h +++ b/ncr.h @@ -73,7 +73,7 @@ struct ncr_data_init_st { struct ncr_data_st { ncr_data_t desc; - void __user* data; + void __user *data; size_t data_size; /* rw in get */ unsigned int append_flag; /* only when used with NCRIO_DATA_SET */ }; -- cgit From 951eda087f418c2a5ced189fa9d64c8616634dd0 Mon Sep 17 00:00:00 2001 From: Miloslav Trmač Date: Sat, 24 Jul 2010 11:54:02 +0200 Subject: Use of algo_properties to avoid linear search on a table for each property. --- libtomcrypt/hashes/crypt_hash_is_valid.c | 4 +- libtomcrypt/hashes/hash_get_oid.c | 4 +- libtomcrypt/hashes/hash_memory.c | 14 +- libtomcrypt/hashes/hash_memory_multi.c | 14 +- libtomcrypt/headers/tomcrypt_hash.h | 10 +- libtomcrypt/headers/tomcrypt_pk.h | 26 +-- libtomcrypt/headers/tomcrypt_pkcs.h | 12 +- libtomcrypt/pk/pkcs1/pkcs_1_mgf1.c | 10 +- libtomcrypt/pk/pkcs1/pkcs_1_oaep_decode.c | 16 +- libtomcrypt/pk/pkcs1/pkcs_1_oaep_encode.c | 16 +- libtomcrypt/pk/pkcs1/pkcs_1_pss_decode.c | 12 +- libtomcrypt/pk/pkcs1/pkcs_1_pss_encode.c | 12 +- libtomcrypt/pk/rsa/rsa_decrypt_key.c | 9 +- libtomcrypt/pk/rsa/rsa_encrypt_key.c | 11 +- libtomcrypt/pk/rsa/rsa_sign_hash.c | 11 +- libtomcrypt/pk/rsa/rsa_verify_hash.c | 11 +- ncr-key-storage.c | 8 +- ncr-key.c | 31 +++- ncr-pk.c | 74 +++++---- ncr-pk.h | 12 +- ncr-sessions.c | 262 ++++++++++-------------------- ncr.c | 28 ---- ncr_int.h | 27 ++- 23 files changed, 284 insertions(+), 350 deletions(-) diff --git a/libtomcrypt/hashes/crypt_hash_is_valid.c b/libtomcrypt/hashes/crypt_hash_is_valid.c index 32e8699..d01d418 100644 --- a/libtomcrypt/hashes/crypt_hash_is_valid.c +++ b/libtomcrypt/hashes/crypt_hash_is_valid.c @@ -17,10 +17,10 @@ /* Test if a hash index is valid - @param idx The index of the hash to search for + @param idx The hash to search for @return CRYPT_OK if valid */ -int hash_is_valid(int idx) +int hash_is_valid(const struct algo_properties_st *hash) { return CRYPT_OK; } diff --git a/libtomcrypt/hashes/hash_get_oid.c b/libtomcrypt/hashes/hash_get_oid.c index 32e4390..c6469ba 100644 --- a/libtomcrypt/hashes/hash_get_oid.c +++ b/libtomcrypt/hashes/hash_get_oid.c @@ -46,9 +46,9 @@ static const oid_st sha512_oid = { .OID = { 2, 16, 840, 1, 101, 3, 4, 2, 3, }, }; -int hash_get_oid(int hash, oid_st *st) +int hash_get_oid(const struct algo_properties_st *hash, oid_st *st) { - switch (hash) { + switch (hash->algo) { case NCR_ALG_SHA1: memcpy(st, &sha1_oid, sizeof(*st)); break; diff --git a/libtomcrypt/hashes/hash_memory.c b/libtomcrypt/hashes/hash_memory.c index 274c208..5ba3bc6 100644 --- a/libtomcrypt/hashes/hash_memory.c +++ b/libtomcrypt/hashes/hash_memory.c @@ -19,18 +19,17 @@ /** Hash a block of memory and store the digest. - @param hash The index of the hash you wish to use + @param hash The hash you wish to use @param in The data you wish to hash @param inlen The length of the data to hash (octets) @param out [out] Where to store the digest @param outlen [in/out] Max size and resulting size of the digest @return CRYPT_OK if successful */ -int hash_memory(int hash, const unsigned char *in, unsigned long inlen, unsigned char *out, unsigned long *outlen) +int hash_memory(const struct algo_properties_st *hash, const unsigned char *in, unsigned long inlen, unsigned char *out, unsigned long *outlen) { int err; struct hash_data hdata; - int digest_size; LTC_ARGCHK(in != NULL); LTC_ARGCHK(out != NULL); @@ -40,13 +39,12 @@ int hash_memory(int hash, const unsigned char *in, unsigned long inlen, unsigned return err; } - digest_size = _ncr_algo_digest_size(hash); - if (*outlen < digest_size) { - *outlen = digest_size; + if (*outlen < hash->digest_size) { + *outlen = hash->digest_size; return CRYPT_BUFFER_OVERFLOW; } - err = cryptodev_hash_init( &hdata, _ncr_algo_to_str(hash), 0, NULL, 0); + err = cryptodev_hash_init( &hdata, hash->kstr, 0, NULL, 0); if (err < 0) { err = CRYPT_INVALID_HASH; goto LBL_ERR; @@ -59,7 +57,7 @@ int hash_memory(int hash, const unsigned char *in, unsigned long inlen, unsigned err = cryptodev_hash_final(&hdata, out); - *outlen = digest_size; + *outlen = hash->digest_size; LBL_ERR: cryptodev_hash_deinit(&hdata); diff --git a/libtomcrypt/hashes/hash_memory_multi.c b/libtomcrypt/hashes/hash_memory_multi.c index 6a85f65..d772492 100644 --- a/libtomcrypt/hashes/hash_memory_multi.c +++ b/libtomcrypt/hashes/hash_memory_multi.c @@ -20,7 +20,7 @@ /** Hash multiple (non-adjacent) blocks of memory at once. - @param hash The index of the hash you wish to use + @param hash The hash you wish to use @param out [out] Where to store the digest @param outlen [in/out] Max size and resulting size of the digest @param in The data you wish to hash @@ -28,11 +28,10 @@ @param ... tuples of (data,len) pairs to hash, terminated with a (NULL,x) (x=don't care) @return CRYPT_OK if successful */ -int hash_memory_multi(int hash, unsigned char *out, unsigned long *outlen, +int hash_memory_multi(const struct algo_properties_st *hash, unsigned char *out, unsigned long *outlen, const unsigned char *in, unsigned long inlen, ...) { struct hash_data hdata; - int digest_size; int err; va_list args; const unsigned char *curptr; @@ -46,13 +45,12 @@ int hash_memory_multi(int hash, unsigned char *out, unsigned long *outlen, return err; } - digest_size = _ncr_algo_digest_size(hash); - if (*outlen < digest_size) { - *outlen = digest_size; + if (*outlen < hash->digest_size) { + *outlen = hash->digest_size; return CRYPT_BUFFER_OVERFLOW; } - err = cryptodev_hash_init( &hdata, _ncr_algo_to_str(hash), 0, NULL, 0); + err = cryptodev_hash_init( &hdata, hash->kstr, 0, NULL, 0); if (err < 0) { err = CRYPT_INVALID_HASH; goto LBL_ERR; @@ -77,7 +75,7 @@ int hash_memory_multi(int hash, unsigned char *out, unsigned long *outlen, err = cryptodev_hash_final(&hdata, out); - *outlen = digest_size; + *outlen = hash->digest_size; LBL_ERR: cryptodev_hash_deinit(&hdata); va_end(args); diff --git a/libtomcrypt/headers/tomcrypt_hash.h b/libtomcrypt/headers/tomcrypt_hash.h index 417e481..e4e84e4 100644 --- a/libtomcrypt/headers/tomcrypt_hash.h +++ b/libtomcrypt/headers/tomcrypt_hash.h @@ -1,12 +1,14 @@ /* ---- HASH FUNCTIONS ---- */ -int hash_is_valid(int idx); +struct algo_properties_st; -int hash_memory(int hash, +int hash_is_valid(const struct algo_properties_st *hash); + +int hash_memory(const struct algo_properties_st *hash, const unsigned char *in, unsigned long inlen, unsigned char *out, unsigned long *outlen); -int hash_memory_multi(int hash, unsigned char *out, unsigned long *outlen, +int hash_memory_multi(const struct algo_properties_st *hash, unsigned char *out, unsigned long *outlen, const unsigned char *in, unsigned long inlen, ...); -int hash_get_oid(int hash, oid_st* st); +int hash_get_oid(const struct algo_properties_st *hash, oid_st* st); diff --git a/libtomcrypt/headers/tomcrypt_pk.h b/libtomcrypt/headers/tomcrypt_pk.h index fa6030e..145165e 100644 --- a/libtomcrypt/headers/tomcrypt_pk.h +++ b/libtomcrypt/headers/tomcrypt_pk.h @@ -1,5 +1,7 @@ /* ---- NUMBER THEORY ---- */ +struct algo_properties_st; + enum { PK_PUBLIC=0, PK_PRIVATE=1 @@ -57,40 +59,40 @@ int rsa_exptmod(const unsigned char *in, unsigned long inlen, void rsa_free(rsa_key *key); /* These use LTC_PKCS #1 v2.0 padding */ -#define rsa_encrypt_key(_in, _inlen, _out, _outlen, _lparam, _lparamlen, _hash_idx, _key) \ - rsa_encrypt_key_ex(_in, _inlen, _out, _outlen, _lparam, _lparamlen, _hash_idx, LTC_LTC_PKCS_1_OAEP, _key) +#define rsa_encrypt_key(_in, _inlen, _out, _outlen, _lparam, _lparamlen, _hash, _key) \ + rsa_encrypt_key_ex(_in, _inlen, _out, _outlen, _lparam, _lparamlen, _hash, LTC_LTC_PKCS_1_OAEP, _key) -#define rsa_decrypt_key(_in, _inlen, _out, _outlen, _lparam, _lparamlen, _hash_idx, _stat, _key) \ - rsa_decrypt_key_ex(_in, _inlen, _out, _outlen, _lparam, _lparamlen, _hash_idx, LTC_LTC_PKCS_1_OAEP, _stat, _key) +#define rsa_decrypt_key(_in, _inlen, _out, _outlen, _lparam, _lparamlen, _hash, _stat, _key) \ + rsa_decrypt_key_ex(_in, _inlen, _out, _outlen, _lparam, _lparamlen, _hash, LTC_LTC_PKCS_1_OAEP, _stat, _key) -#define rsa_sign_hash(_in, _inlen, _out, _outlen, _hash_idx, _saltlen, _key) \ - rsa_sign_hash_ex(_in, _inlen, _out, _outlen, LTC_LTC_PKCS_1_PSS, _hash_idx, _saltlen, _key) +#define rsa_sign_hash(_in, _inlen, _out, _outlen, _hash, _saltlen, _key) \ + rsa_sign_hash_ex(_in, _inlen, _out, _outlen, LTC_LTC_PKCS_1_PSS, _hash, _saltlen, _key) -#define rsa_verify_hash(_sig, _siglen, _hash, _hashlen, _hash_idx, _saltlen, _stat, _key) \ - rsa_verify_hash_ex(_sig, _siglen, _hash, _hashlen, LTC_LTC_PKCS_1_PSS, _hash_idx, _saltlen, _stat, _key) +#define rsa_verify_hash(_sig, _siglen, _hash, _hashlen, _hash_algo, _saltlen, _stat, _key) \ + rsa_verify_hash_ex(_sig, _siglen, _hash, _hashlen, LTC_LTC_PKCS_1_PSS, _hash_algo, _saltlen, _stat, _key) /* These can be switched between LTC_PKCS #1 v2.x and LTC_PKCS #1 v1.5 paddings */ int rsa_encrypt_key_ex(const unsigned char *in, unsigned long inlen, unsigned char *out, unsigned long *outlen, const unsigned char *lparam, unsigned long lparamlen, - int hash_idx, int padding, rsa_key *key); + const struct algo_properties_st *hash, int padding, rsa_key *key); int rsa_decrypt_key_ex(const unsigned char *in, unsigned long inlen, unsigned char *out, unsigned long *outlen, const unsigned char *lparam, unsigned long lparamlen, - int hash_idx, int padding, + const struct algo_properties_st *hash, int padding, int *stat, rsa_key *key); int rsa_sign_hash_ex(const unsigned char *in, unsigned long inlen, unsigned char *out, unsigned long *outlen, int padding, - int hash_idx, unsigned long saltlen, + const struct algo_properties_st *hash, unsigned long saltlen, rsa_key *key); int rsa_verify_hash_ex(const unsigned char *sig, unsigned long siglen, const unsigned char *hash, unsigned long hashlen, int padding, - int hash_idx, unsigned long saltlen, + const struct algo_properties_st *hash_algo, unsigned long saltlen, int *stat, rsa_key *key); /* LTC_PKCS #1 import/export */ diff --git a/libtomcrypt/headers/tomcrypt_pkcs.h b/libtomcrypt/headers/tomcrypt_pkcs.h index 8e43942..be0d7f6 100644 --- a/libtomcrypt/headers/tomcrypt_pkcs.h +++ b/libtomcrypt/headers/tomcrypt_pkcs.h @@ -3,6 +3,8 @@ /* ===> LTC_PKCS #1 -- RSA Cryptography <=== */ #ifdef LTC_PKCS_1 +struct algo_properties_st; + enum ltc_pkcs_1_v1_5_blocks { LTC_LTC_PKCS_1_EMSA = 1, /* Block type 1 (LTC_PKCS #1 v1.5 signature padding) */ @@ -16,7 +18,7 @@ enum ltc_pkcs_1_paddings LTC_LTC_PKCS_1_PSS = 3 /* LTC_PKCS #1 v2.1 signature padding */ }; -int pkcs_1_mgf1( int hash_idx, +int pkcs_1_mgf1(const struct algo_properties_st *hash, const unsigned char *seed, unsigned long seedlen, unsigned char *mask, unsigned long masklen); @@ -42,23 +44,23 @@ int pkcs_1_v1_5_decode(const unsigned char *msg, /* *** v2.1 padding */ int pkcs_1_oaep_encode(const unsigned char *msg, unsigned long msglen, const unsigned char *lparam, unsigned long lparamlen, - unsigned long modulus_bitlen, int hash_idx, + unsigned long modulus_bitlen, const struct algo_properties_st *hash, unsigned char *out, unsigned long *outlen); int pkcs_1_oaep_decode(const unsigned char *msg, unsigned long msglen, const unsigned char *lparam, unsigned long lparamlen, - unsigned long modulus_bitlen, int hash_idx, + unsigned long modulus_bitlen, const struct algo_properties_st *hash, unsigned char *out, unsigned long *outlen, int *res); int pkcs_1_pss_encode(const unsigned char *msghash, unsigned long msghashlen, - unsigned long saltlen, int hash_idx, + unsigned long saltlen, const struct algo_properties_st *hash, unsigned long modulus_bitlen, unsigned char *out, unsigned long *outlen); int pkcs_1_pss_decode(const unsigned char *msghash, unsigned long msghashlen, const unsigned char *sig, unsigned long siglen, - unsigned long saltlen, int hash_idx, + unsigned long saltlen, const struct algo_properties_st *hash, unsigned long modulus_bitlen, int *res); #endif /* LTC_PKCS_1 */ diff --git a/libtomcrypt/pk/pkcs1/pkcs_1_mgf1.c b/libtomcrypt/pk/pkcs1/pkcs_1_mgf1.c index 01fe231..b09dd11 100644 --- a/libtomcrypt/pk/pkcs1/pkcs_1_mgf1.c +++ b/libtomcrypt/pk/pkcs1/pkcs_1_mgf1.c @@ -22,12 +22,12 @@ Perform LTC_PKCS #1 MGF1 (internal) @param seed The seed for MGF1 @param seedlen The length of the seed - @param hash_idx The index of the hash desired + @param hash The desired hash @param mask [out] The destination @param masklen The length of the mask desired @return CRYPT_OK if successful */ -int pkcs_1_mgf1(int hash_idx, +int pkcs_1_mgf1(const struct algo_properties_st *hash, const unsigned char *seed, unsigned long seedlen, unsigned char *mask, unsigned long masklen) { @@ -40,12 +40,12 @@ int pkcs_1_mgf1(int hash_idx, LTC_ARGCHK(mask != NULL); /* ensure valid hash */ - if ((err = hash_is_valid(hash_idx)) != CRYPT_OK) { + if ((err = hash_is_valid(hash)) != CRYPT_OK) { return err; } /* get hash output size */ - hLen = _ncr_algo_digest_size(hash_idx); + hLen = hash->digest_size; /* allocate memory */ buf = XMALLOC(hLen); @@ -61,7 +61,7 @@ int pkcs_1_mgf1(int hash_idx, STORE32H(counter, buf); ++counter; - err = hash_memory_multi(hash_idx, buf, &hLen, seed, seedlen, buf, (unsigned long) 4, NULL, 0); + err = hash_memory_multi(hash, buf, &hLen, seed, seedlen, buf, (unsigned long) 4, NULL, 0); if (err != CRYPT_OK) { goto LBL_ERR; } diff --git a/libtomcrypt/pk/pkcs1/pkcs_1_oaep_decode.c b/libtomcrypt/pk/pkcs1/pkcs_1_oaep_decode.c index 4114c56..60f76a0 100644 --- a/libtomcrypt/pk/pkcs1/pkcs_1_oaep_decode.c +++ b/libtomcrypt/pk/pkcs1/pkcs_1_oaep_decode.c @@ -25,7 +25,7 @@ @param lparam The session or system data (can be NULL) @param lparamlen The length of the lparam @param modulus_bitlen The bit length of the RSA modulus - @param hash_idx The index of the hash desired + @param hash The desired hash @param out [out] Destination of decoding @param outlen [in/out] The max size and resulting size of the decoding @param res [out] Result of decoding, 1==valid, 0==invalid @@ -33,7 +33,7 @@ */ int pkcs_1_oaep_decode(const unsigned char *msg, unsigned long msglen, const unsigned char *lparam, unsigned long lparamlen, - unsigned long modulus_bitlen, int hash_idx, + unsigned long modulus_bitlen, const struct algo_properties_st *hash, unsigned char *out, unsigned long *outlen, int *res) { @@ -50,11 +50,11 @@ int pkcs_1_oaep_decode(const unsigned char *msg, unsigned long msglen, *res = 0; /* test valid hash */ - if ((err = hash_is_valid(hash_idx)) != CRYPT_OK) { + if ((err = hash_is_valid(hash)) != CRYPT_OK) { return err; } - hLen = _ncr_algo_digest_size(hash_idx); + hLen = hash->digest_size; modulus_len = (modulus_bitlen >> 3) + (modulus_bitlen & 7 ? 1 : 0); /* test hash/message size */ @@ -103,7 +103,7 @@ int pkcs_1_oaep_decode(const unsigned char *msg, unsigned long msglen, x += modulus_len - hLen - 1; /* compute MGF1 of maskedDB (hLen) */ - if ((err = pkcs_1_mgf1(hash_idx, DB, modulus_len - hLen - 1, mask, hLen)) != CRYPT_OK) { + if ((err = pkcs_1_mgf1(hash, DB, modulus_len - hLen - 1, mask, hLen)) != CRYPT_OK) { goto LBL_ERR; } @@ -113,7 +113,7 @@ int pkcs_1_oaep_decode(const unsigned char *msg, unsigned long msglen, } /* compute MGF1 of seed (k - hlen - 1) */ - if ((err = pkcs_1_mgf1(hash_idx, seed, hLen, mask, modulus_len - hLen - 1)) != CRYPT_OK) { + if ((err = pkcs_1_mgf1(hash, seed, hLen, mask, modulus_len - hLen - 1)) != CRYPT_OK) { goto LBL_ERR; } @@ -127,12 +127,12 @@ int pkcs_1_oaep_decode(const unsigned char *msg, unsigned long msglen, /* compute lhash and store it in seed [reuse temps!] */ x = modulus_len; if (lparam != NULL) { - if ((err = hash_memory(hash_idx, lparam, lparamlen, seed, &x)) != CRYPT_OK) { + if ((err = hash_memory(hash, lparam, lparamlen, seed, &x)) != CRYPT_OK) { goto LBL_ERR; } } else { /* can't pass hash_memory a NULL so use DB with zero length */ - if ((err = hash_memory(hash_idx, DB, 0, seed, &x)) != CRYPT_OK) { + if ((err = hash_memory(hash, DB, 0, seed, &x)) != CRYPT_OK) { goto LBL_ERR; } } diff --git a/libtomcrypt/pk/pkcs1/pkcs_1_oaep_encode.c b/libtomcrypt/pk/pkcs1/pkcs_1_oaep_encode.c index ccee5cf..c56e3b1 100644 --- a/libtomcrypt/pk/pkcs1/pkcs_1_oaep_encode.c +++ b/libtomcrypt/pk/pkcs1/pkcs_1_oaep_encode.c @@ -25,14 +25,14 @@ @param lparam A session or system parameter (can be NULL) @param lparamlen The length of the lparam data @param modulus_bitlen The bit length of the RSA modulus - @param hash_idx The index of the hash desired + @param hash The desired hash @param out [out] The destination for the encoded data @param outlen [in/out] The max size and resulting size of the encoded data @return CRYPT_OK if successful */ int pkcs_1_oaep_encode(const unsigned char *msg, unsigned long msglen, const unsigned char *lparam, unsigned long lparamlen, - unsigned long modulus_bitlen, int hash_idx, + unsigned long modulus_bitlen, const struct algo_properties_st *hash, unsigned char *out, unsigned long *outlen) { unsigned char *DB, *seed, *mask; @@ -44,11 +44,11 @@ int pkcs_1_oaep_encode(const unsigned char *msg, unsigned long msglen, LTC_ARGCHK(outlen != NULL); /* test valid hash */ - if ((err = hash_is_valid(hash_idx)) != CRYPT_OK) { + if ((err = hash_is_valid(hash)) != CRYPT_OK) { return err; } - hLen = _ncr_algo_digest_size(hash_idx); + hLen = hash->digest_size; modulus_len = (modulus_bitlen >> 3) + (modulus_bitlen & 7 ? 1 : 0); /* test message size */ @@ -77,12 +77,12 @@ int pkcs_1_oaep_encode(const unsigned char *msg, unsigned long msglen, /* DB == lhash || PS || 0x01 || M, PS == k - mlen - 2hlen - 2 zeroes */ x = modulus_len; if (lparam != NULL) { - if ((err = hash_memory(hash_idx, lparam, lparamlen, DB, &x)) != CRYPT_OK) { + if ((err = hash_memory(hash, lparam, lparamlen, DB, &x)) != CRYPT_OK) { goto LBL_ERR; } } else { /* can't pass hash_memory a NULL so use DB with zero length */ - if ((err = hash_memory(hash_idx, DB, 0, DB, &x)) != CRYPT_OK) { + if ((err = hash_memory(hash, DB, 0, DB, &x)) != CRYPT_OK) { goto LBL_ERR; } } @@ -104,7 +104,7 @@ int pkcs_1_oaep_encode(const unsigned char *msg, unsigned long msglen, get_random_bytes(seed, hLen); /* compute MGF1 of seed (k - hlen - 1) */ - if ((err = pkcs_1_mgf1(hash_idx, seed, hLen, mask, modulus_len - hLen - 1)) != CRYPT_OK) { + if ((err = pkcs_1_mgf1(hash, seed, hLen, mask, modulus_len - hLen - 1)) != CRYPT_OK) { goto LBL_ERR; } @@ -114,7 +114,7 @@ int pkcs_1_oaep_encode(const unsigned char *msg, unsigned long msglen, } /* compute MGF1 of maskedDB (hLen) */ - if ((err = pkcs_1_mgf1(hash_idx, DB, modulus_len - hLen - 1, mask, hLen)) != CRYPT_OK) { + if ((err = pkcs_1_mgf1(hash, DB, modulus_len - hLen - 1, mask, hLen)) != CRYPT_OK) { goto LBL_ERR; } diff --git a/libtomcrypt/pk/pkcs1/pkcs_1_pss_decode.c b/libtomcrypt/pk/pkcs1/pkcs_1_pss_decode.c index 5a26654..293d84f 100644 --- a/libtomcrypt/pk/pkcs1/pkcs_1_pss_decode.c +++ b/libtomcrypt/pk/pkcs1/pkcs_1_pss_decode.c @@ -25,14 +25,14 @@ @param sig The signature data (encoded data) @param siglen The length of the signature data (octets) @param saltlen The length of the salt used (octets) - @param hash_idx The index of the hash desired + @param hash_algo The desired hash @param modulus_bitlen The bit length of the RSA modulus @param res [out] The result of the comparison, 1==valid, 0==invalid @return CRYPT_OK if successful (even if the comparison failed) */ int pkcs_1_pss_decode(const unsigned char *msghash, unsigned long msghashlen, const unsigned char *sig, unsigned long siglen, - unsigned long saltlen, int hash_idx, + unsigned long saltlen, const struct algo_properties_st *hash_algo, unsigned long modulus_bitlen, int *res) { unsigned char *DB, *mask, *salt, *hash; @@ -46,11 +46,11 @@ int pkcs_1_pss_decode(const unsigned char *msghash, unsigned long msghashlen, *res = 0; /* ensure hash is valid */ - if ((err = hash_is_valid(hash_idx)) != CRYPT_OK) { + if ((err = hash_is_valid(hash_algo)) != CRYPT_OK) { return err; } - hLen = _ncr_algo_digest_size(hash_idx); + hLen = hash_algo->digest_size; modulus_len = (modulus_bitlen>>3) + (modulus_bitlen & 7 ? 1 : 0); /* check sizes */ @@ -102,7 +102,7 @@ int pkcs_1_pss_decode(const unsigned char *msghash, unsigned long msghashlen, } /* generate mask of length modulus_len - hLen - 1 from hash */ - if ((err = pkcs_1_mgf1(hash_idx, hash, hLen, mask, modulus_len - hLen - 1)) != CRYPT_OK) { + if ((err = pkcs_1_mgf1(hash_algo, hash, hLen, mask, modulus_len - hLen - 1)) != CRYPT_OK) { goto LBL_ERR; } @@ -131,7 +131,7 @@ int pkcs_1_pss_decode(const unsigned char *msghash, unsigned long msghashlen, } /* M = (eight) 0x00 || msghash || salt, mask = H(M) */ - err = hash_memory_multi(hash_idx, mask, &hLen, mask, 8, msghash, (unsigned long)msghashlen, DB+x, (unsigned long)saltlen, NULL, 0); + err = hash_memory_multi(hash_algo, mask, &hLen, mask, 8, msghash, (unsigned long)msghashlen, DB+x, (unsigned long)saltlen, NULL, 0); if (err != CRYPT_OK) { goto LBL_ERR; } diff --git a/libtomcrypt/pk/pkcs1/pkcs_1_pss_encode.c b/libtomcrypt/pk/pkcs1/pkcs_1_pss_encode.c index 382820d..d747b49 100644 --- a/libtomcrypt/pk/pkcs1/pkcs_1_pss_encode.c +++ b/libtomcrypt/pk/pkcs1/pkcs_1_pss_encode.c @@ -23,14 +23,14 @@ @param msghash The hash to encode @param msghashlen The length of the hash (octets) @param saltlen The length of the salt desired (octets) - @param hash_idx The index of the hash desired + @param hash_algo The desired hash @param modulus_bitlen The bit length of the RSA modulus @param out [out] The destination of the encoding @param outlen [in/out] The max size and resulting size of the encoded data @return CRYPT_OK if successful */ int pkcs_1_pss_encode(const unsigned char *msghash, unsigned long msghashlen, - unsigned long saltlen, int hash_idx, + unsigned long saltlen, const struct algo_properties_st *hash_algo, unsigned long modulus_bitlen, unsigned char *out, unsigned long *outlen) { @@ -43,11 +43,11 @@ int pkcs_1_pss_encode(const unsigned char *msghash, unsigned long msghashlen, LTC_ARGCHK(outlen != NULL); /* ensure hash and PRNG are valid */ - if ((err = hash_is_valid(hash_idx)) != CRYPT_OK) { + if ((err = hash_is_valid(hash_algo)) != CRYPT_OK) { return err; } - hLen = _ncr_algo_digest_size(hash_idx); + hLen = hash_algo->digest_size; modulus_len = (modulus_bitlen>>3) + (modulus_bitlen & 7 ? 1 : 0); /* check sizes */ @@ -83,7 +83,7 @@ int pkcs_1_pss_encode(const unsigned char *msghash, unsigned long msghashlen, } /* M = (eight) 0x00 || msghash || salt, hash = H(M) */ - err = hash_memory_multi(hash_idx, hash, &hLen, DB, 8, msghash, (unsigned long)msghashlen, salt, (unsigned long)saltlen, NULL, 0); + err = hash_memory_multi(hash_algo, hash, &hLen, DB, 8, msghash, (unsigned long)msghashlen, salt, (unsigned long)saltlen, NULL, 0); if (err != CRYPT_OK) { goto LBL_ERR; } @@ -97,7 +97,7 @@ int pkcs_1_pss_encode(const unsigned char *msghash, unsigned long msghashlen, x += saltlen; /* generate mask of length modulus_len - hLen - 1 from hash */ - if ((err = pkcs_1_mgf1(hash_idx, hash, hLen, mask, modulus_len - hLen - 1)) != CRYPT_OK) { + if ((err = pkcs_1_mgf1(hash_algo, hash, hLen, mask, modulus_len - hLen - 1)) != CRYPT_OK) { goto LBL_ERR; } diff --git a/libtomcrypt/pk/rsa/rsa_decrypt_key.c b/libtomcrypt/pk/rsa/rsa_decrypt_key.c index 52885e8..989c935 100644 --- a/libtomcrypt/pk/rsa/rsa_decrypt_key.c +++ b/libtomcrypt/pk/rsa/rsa_decrypt_key.c @@ -9,6 +9,7 @@ * Tom St Denis, tomstdenis@gmail.com, http://libtom.org */ #include "tomcrypt.h" +#include "ncr_int.h" /** @file rsa_decrypt_key.c @@ -25,7 +26,7 @@ @param outlen [in/out] The max size and resulting size of the plaintext (octets) @param lparam The system "lparam" value @param lparamlen The length of the lparam value (octets) - @param hash_idx The index of the hash desired + @param hash The desired hash @param padding Type of padding (LTC_LTC_PKCS_1_OAEP or LTC_LTC_PKCS_1_V1_5) @param stat [out] Result of the decryption, 1==valid, 0==invalid @param key The corresponding private RSA key @@ -34,7 +35,7 @@ int rsa_decrypt_key_ex(const unsigned char *in, unsigned long inlen, unsigned char *out, unsigned long *outlen, const unsigned char *lparam, unsigned long lparamlen, - int hash_idx, int padding, + const struct algo_properties_st *hash, int padding, int *stat, rsa_key *key) { unsigned long modulus_bitlen, modulus_bytelen, x; @@ -58,7 +59,7 @@ int rsa_decrypt_key_ex(const unsigned char *in, unsigned long inlen, if (padding == LTC_LTC_PKCS_1_OAEP) { /* valid hash ? */ - if ((err = hash_is_valid(hash_idx)) != CRYPT_OK) { + if ((err = hash_is_valid(hash)) != CRYPT_OK) { return err; } } @@ -87,7 +88,7 @@ int rsa_decrypt_key_ex(const unsigned char *in, unsigned long inlen, if (padding == LTC_LTC_PKCS_1_OAEP) { /* now OAEP decode the packet */ - err = pkcs_1_oaep_decode(tmp, x, lparam, lparamlen, modulus_bitlen, hash_idx, + err = pkcs_1_oaep_decode(tmp, x, lparam, lparamlen, modulus_bitlen, hash, out, outlen, stat); } else { /* now LTC_PKCS #1 v1.5 depad the packet */ diff --git a/libtomcrypt/pk/rsa/rsa_encrypt_key.c b/libtomcrypt/pk/rsa/rsa_encrypt_key.c index d59699c..4ce51a4 100644 --- a/libtomcrypt/pk/rsa/rsa_encrypt_key.c +++ b/libtomcrypt/pk/rsa/rsa_encrypt_key.c @@ -9,6 +9,7 @@ * Tom St Denis, tomstdenis@gmail.com, http://libtom.org */ #include "tomcrypt.h" +#include "ncr_int.h" /** @file rsa_encrypt_key.c @@ -25,7 +26,7 @@ @param outlen [in/out] The max size and resulting size of the ciphertext @param lparam The system "lparam" for the encryption @param lparamlen The length of lparam (octets) - @param hash_idx The index of the desired hash + @param hash The desired hash @param padding Type of padding (LTC_LTC_PKCS_1_OAEP or LTC_LTC_PKCS_1_V1_5) @param key The RSA key to encrypt to @return CRYPT_OK if successful @@ -33,7 +34,7 @@ int rsa_encrypt_key_ex(const unsigned char *in, unsigned long inlen, unsigned char *out, unsigned long *outlen, const unsigned char *lparam, unsigned long lparamlen, - int hash_idx, int padding, rsa_key *key) + const struct algo_properties_st *hash, int padding, rsa_key *key) { unsigned long modulus_bitlen, modulus_bytelen, x; int err; @@ -51,7 +52,7 @@ int rsa_encrypt_key_ex(const unsigned char *in, unsigned long inlen, if (padding == LTC_LTC_PKCS_1_OAEP) { /* valid hash? */ - if ((err = hash_is_valid(hash_idx)) != CRYPT_OK) { + if ((err = hash_is_valid(hash)) != CRYPT_OK) { return err; } } @@ -70,8 +71,8 @@ int rsa_encrypt_key_ex(const unsigned char *in, unsigned long inlen, /* OAEP pad the key */ x = *outlen; if ((err = pkcs_1_oaep_encode(in, inlen, lparam, - lparamlen, modulus_bitlen, hash_idx, - out, &x)) != CRYPT_OK) { + lparamlen, modulus_bitlen, hash, + out, &x)) != CRYPT_OK) { return err; } } else { diff --git a/libtomcrypt/pk/rsa/rsa_sign_hash.c b/libtomcrypt/pk/rsa/rsa_sign_hash.c index 1298d46..5a32d33 100644 --- a/libtomcrypt/pk/rsa/rsa_sign_hash.c +++ b/libtomcrypt/pk/rsa/rsa_sign_hash.c @@ -9,6 +9,7 @@ * Tom St Denis, tomstdenis@gmail.com, http://libtom.org */ #include "tomcrypt.h" +#include "ncr_int.h" /** @file rsa_sign_hash.c @@ -24,7 +25,7 @@ @param out [out] The signature @param outlen [in/out] The max size and resulting size of the signature @param padding Type of padding (LTC_LTC_PKCS_1_PSS or LTC_LTC_PKCS_1_V1_5) - @param hash_idx The index of the hash desired + @param hash The desired hash @param saltlen The length of the salt desired (octets) @param key The private RSA key to use @return CRYPT_OK if successful @@ -32,7 +33,7 @@ int rsa_sign_hash_ex(const unsigned char *in, unsigned long inlen, unsigned char *out, unsigned long *outlen, int padding, - int hash_idx, unsigned long saltlen, + const struct algo_properties_st *hash, unsigned long saltlen, rsa_key *key) { unsigned long modulus_bitlen, modulus_bytelen, x, y; @@ -49,7 +50,7 @@ int rsa_sign_hash_ex(const unsigned char *in, unsigned long inlen, } if (padding == LTC_LTC_PKCS_1_PSS) { - if ((err = hash_is_valid(hash_idx)) != CRYPT_OK) { + if ((err = hash_is_valid(hash)) != CRYPT_OK) { return err; } } @@ -68,7 +69,7 @@ int rsa_sign_hash_ex(const unsigned char *in, unsigned long inlen, /* PSS pad the key */ x = *outlen; if ((err = pkcs_1_pss_encode(in, inlen, saltlen, - hash_idx, modulus_bitlen, out, &x)) != CRYPT_OK) { + hash, modulus_bitlen, out, &x)) != CRYPT_OK) { return err; } } else { @@ -78,7 +79,7 @@ int rsa_sign_hash_ex(const unsigned char *in, unsigned long inlen, oid_st st; /* not all hashes have OIDs... so sad */ - if (hash_get_oid(hash_idx, &st) != CRYPT_OK) { + if (hash_get_oid(hash, &st) != CRYPT_OK) { return CRYPT_INVALID_ARG; } diff --git a/libtomcrypt/pk/rsa/rsa_verify_hash.c b/libtomcrypt/pk/rsa/rsa_verify_hash.c index 773ea7d..20f852e 100644 --- a/libtomcrypt/pk/rsa/rsa_verify_hash.c +++ b/libtomcrypt/pk/rsa/rsa_verify_hash.c @@ -9,6 +9,7 @@ * Tom St Denis, tomstdenis@gmail.com, http://libtom.org */ #include "tomcrypt.h" +#include "ncr_int.h" /** @file rsa_verify_hash.c @@ -24,7 +25,7 @@ @param hash The hash of the message that was signed @param hashlen The length of the hash of the message that was signed (octets) @param padding Type of padding (LTC_LTC_PKCS_1_PSS or LTC_LTC_PKCS_1_V1_5) - @param hash_idx The index of the desired hash + @param hash_algo The desired hash @param saltlen The length of the salt used during signature @param stat [out] The result of the signature comparison, 1==valid, 0==invalid @param key The public RSA key corresponding to the key that performed the signature @@ -33,7 +34,7 @@ int rsa_verify_hash_ex(const unsigned char *sig, unsigned long siglen, const unsigned char *hash, unsigned long hashlen, int padding, - int hash_idx, unsigned long saltlen, + const struct algo_properties_st *hash_algo, unsigned long saltlen, int *stat, rsa_key *key) { unsigned long modulus_bitlen, modulus_bytelen, x; @@ -57,7 +58,7 @@ int rsa_verify_hash_ex(const unsigned char *sig, unsigned long siglen, if (padding == LTC_LTC_PKCS_1_PSS) { /* valid hash ? */ - if ((err = hash_is_valid(hash_idx)) != CRYPT_OK) { + if ((err = hash_is_valid(hash_algo)) != CRYPT_OK) { return err; } } @@ -92,7 +93,7 @@ int rsa_verify_hash_ex(const unsigned char *sig, unsigned long siglen, if (padding == LTC_LTC_PKCS_1_PSS) { /* PSS decode and verify it */ - err = pkcs_1_pss_decode(hash, hashlen, tmpbuf, x, saltlen, hash_idx, modulus_bitlen, stat); + err = pkcs_1_pss_decode(hash, hashlen, tmpbuf, x, saltlen, hash_algo, modulus_bitlen, stat); } else { /* LTC_PKCS #1 v1.5 decode it */ unsigned char *out; @@ -102,7 +103,7 @@ int rsa_verify_hash_ex(const unsigned char *sig, unsigned long siglen, oid_st st; /* not all hashes have OIDs... so sad */ - if (hash_get_oid(hash_idx, &st) != CRYPT_OK) { + if (hash_get_oid(hash_algo, &st) != CRYPT_OK) { err = CRYPT_INVALID_ARG; goto bail_2; } diff --git a/ncr-key-storage.c b/ncr-key-storage.c index 69e1c50..90d3f74 100644 --- a/ncr-key-storage.c +++ b/ncr-key-storage.c @@ -52,7 +52,7 @@ int key_to_storage_data( uint8_t** sdata, size_t * sdata_size, const struct key_ pkey->type = key->type; pkey->flags = key->flags; - pkey->algorithm = key->algorithm; + pkey->algorithm = key->algorithm->algo; pkey->key_id_size = key->key_id_size; memcpy(pkey->key_id, key->key_id, key->key_id_size); @@ -95,7 +95,11 @@ int key_from_storage_data(struct key_item_st* key, const void* data, size_t data key->type = pkey->type; key->flags = pkey->flags; - key->algorithm = pkey->algorithm; + key->algorithm = _ncr_algo_to_properties(pkey->algorithm); + if (key->algorithm == NULL) { + err(); + return -EINVAL; + } key->key_id_size = pkey->key_id_size; memcpy(key->key_id, pkey->key_id, pkey->key_id_size); diff --git a/ncr-key.c b/ncr-key.c index 134831e..db5d458 100644 --- a/ncr-key.c +++ b/ncr-key.c @@ -337,7 +337,12 @@ int ret; } item->type = data.type; - item->algorithm = data.algorithm; + item->algorithm = _ncr_algo_to_properties(data.algorithm); + if (item->algorithm == NULL) { + err(); + ret = -EINVAL; + goto fail; + } item->flags = data.flags; /* if data cannot be exported then the flags above * should be overriden */ @@ -414,6 +419,7 @@ int ncr_key_generate(struct list_sem_st* lst, void __user* arg) { struct ncr_key_generate_st gen; struct key_item_st* item = NULL; +const struct algo_properties_st *algo; int ret; size_t size; @@ -432,9 +438,15 @@ size_t size; /* we generate only secret keys */ item->flags = gen.params.keyflags; - item->type = ncr_algorithm_to_key_type(gen.params.algorithm); + algo = _ncr_algo_to_properties(gen.params.algorithm); + if (algo == NULL) { + err(); + return ret; + } + item->type = algo->key_type; if (item->type == NCR_KEY_TYPE_SECRET) { - item->algorithm = /* arbitrary */ NCR_ALG_AES_CBC; + /* arbitrary */ + item->algorithm = _ncr_algo_to_properties(NCR_ALG_AES_CBC); size = gen.params.params.secret.bits/8; if ((gen.params.params.secret.bits % 8 != 0) || @@ -485,7 +497,7 @@ int ret; info.flags = item->flags; info.type = item->type; - info.algorithm = item->algorithm; + info.algorithm = item->algorithm->algo; _ncr_key_item_put( item); @@ -521,13 +533,18 @@ int ret; /* we generate only secret keys */ private->flags = public->flags = gen.params.keyflags; - public->type = ncr_algorithm_to_key_type(gen.params.algorithm); + private->algorithm = public->algorithm = _ncr_algo_to_properties(gen.params.algorithm); + if (private->algorithm == NULL) { + err(); + ret = -EINVAL; + goto fail; + } + public->type = public->algorithm->key_type; private->type = NCR_KEY_TYPE_PRIVATE; - private->algorithm = public->algorithm = gen.params.algorithm; public->flags |= (NCR_KEY_FLAG_EXPORTABLE|NCR_KEY_FLAG_WRAPPABLE); if (public->type == NCR_KEY_TYPE_PUBLIC) { - ret = ncr_pk_generate(gen.params.algorithm, &gen.params, private, public); + ret = ncr_pk_generate(public->algorithm, &gen.params, private, public); if (ret < 0) { err(); goto fail; diff --git a/ncr-pk.c b/ncr-pk.c index b95256d..bfe575d 100644 --- a/ncr-pk.c +++ b/ncr-pk.c @@ -45,7 +45,9 @@ static int tomerr(int err) void ncr_pk_clear(struct key_item_st* key) { - switch(key->algorithm) { + if (key->algorithm == NULL) + return; + switch(key->algorithm->algo) { case NCR_ALG_RSA: rsa_free(&key->key.pk.rsa); break; @@ -71,7 +73,7 @@ static int ncr_pk_make_public_and_id( struct key_item_st * private, struct key_i return -ENOMEM; } - switch(private->algorithm) { + switch(private->algorithm->algo) { case NCR_ALG_RSA: cret = rsa_export(tmp, &max_size, PK_PUBLIC, &private->key.pk.rsa); if (cret != CRYPT_OK) { @@ -109,7 +111,7 @@ static int ncr_pk_make_public_and_id( struct key_item_st * private, struct key_i } key_id_size = MAX_KEY_ID_SIZE; - cret = hash_memory(NCR_ALG_SHA1, tmp, max_size, private->key_id, &key_id_size); + cret = hash_memory(_ncr_algo_to_properties(NCR_ALG_SHA1), tmp, max_size, private->key_id, &key_id_size); if (cret != CRYPT_OK) { err(); ret = tomerr(cret); @@ -135,7 +137,7 @@ int ncr_pk_pack( const struct key_item_st * key, uint8_t * packed, uint32_t * pa return -EINVAL; } - switch(key->algorithm) { + switch(key->algorithm->algo) { case NCR_ALG_RSA: cret = rsa_export(packed, &max_size, key->key.pk.rsa.type, (void*)&key->key.pk.rsa); if (cret != CRYPT_OK) { @@ -170,7 +172,7 @@ int ncr_pk_unpack( struct key_item_st * key, const void * packed, size_t packed_ return -EINVAL; } - switch(key->algorithm) { + switch(key->algorithm->algo) { case NCR_ALG_RSA: cret = rsa_import(packed, packed_size, (void*)&key->key.pk.rsa); if (cret != CRYPT_OK) { @@ -197,7 +199,7 @@ struct keygen_st { struct work_struct pk_gen; struct completion completed; int ret; - ncr_algorithm_t algo; + const struct algo_properties_st *algo; struct key_item_st* private; struct key_item_st* public; struct ncr_key_generate_params_st * params; @@ -210,7 +212,7 @@ static void keygen_handler(struct work_struct *instance) struct keygen_st *st = container_of(instance, struct keygen_st, pk_gen); - switch(st->algo) { + switch(st->algo->algo) { case NCR_ALG_RSA: e = st->params->params.rsa.e; @@ -246,7 +248,7 @@ static void keygen_handler(struct work_struct *instance) } -int ncr_pk_generate(ncr_algorithm_t algo, +int ncr_pk_generate(const struct algo_properties_st *algo, struct ncr_key_generate_params_st * params, struct key_item_st* private, struct key_item_st* public) { @@ -303,16 +305,21 @@ void ncr_pk_queue_deinit(void) destroy_workqueue(pk_wq); } -int ncr_key_params_get_sign_hash(ncr_algorithm_t algo, struct ncr_key_params_st * params) +const struct algo_properties_st *ncr_key_params_get_sign_hash(const struct algo_properties_st *algo, struct ncr_key_params_st * params) { - switch(algo) { + ncr_algorithm_t id; + + switch(algo->algo) { case NCR_ALG_RSA: - return params->params.rsa.sign_hash; + id = params->params.rsa.sign_hash; + break; case NCR_ALG_DSA: - return params->params.dsa.sign_hash; + id = params->params.dsa.sign_hash; + break; default: - return -EINVAL; + return ERR_PTR(-EINVAL); } + return _ncr_algo_to_properties(id); } /* Encryption/Decryption @@ -326,12 +333,10 @@ void ncr_pk_cipher_deinit(struct ncr_pk_ctx* ctx) } } -int ncr_pk_cipher_init(ncr_algorithm_t algo, +int ncr_pk_cipher_init(const struct algo_properties_st *algo, struct ncr_pk_ctx* ctx, struct ncr_key_params_st* params, - struct key_item_st *key) + struct key_item_st *key, const struct algo_properties_st *sign_hash) { -int ret; - memset(ctx, 0, sizeof(*ctx)); if (key->algorithm != algo) { @@ -341,23 +346,22 @@ int ret; ctx->algorithm = algo; ctx->key = key; - ret = ncr_key_params_get_sign_hash(algo, params); - if (ret < 0) { - err(); - return ret; - } - ctx->sign_hash = ret; + ctx->sign_hash = sign_hash; - switch(algo) { + switch(algo->algo) { case NCR_ALG_RSA: if (params->params.rsa.type == RSA_PKCS1_V1_5) ctx->type = LTC_LTC_PKCS_1_V1_5; - else if (params->params.rsa.type == RSA_PKCS1_OAEP) + else if (params->params.rsa.type == RSA_PKCS1_OAEP) { ctx->type = LTC_LTC_PKCS_1_OAEP; - else if (params->params.rsa.type == RSA_PKCS1_PSS) + ctx->oaep_hash = _ncr_algo_to_properties(params->params.rsa.oaep_hash); + if (ctx->oaep_hash == NULL) { + err(); + return -EINVAL; + } + } else if (params->params.rsa.type == RSA_PKCS1_PSS) ctx->type = LTC_LTC_PKCS_1_PSS; - ctx->oaep_hash = params->params.rsa.oaep_hash; ctx->salt_len = params->params.rsa.pss_salt; break; case NCR_ALG_DSA: @@ -379,7 +383,7 @@ int ncr_pk_cipher_encrypt(const struct ncr_pk_ctx* ctx, int cret; unsigned long osize = *output_size; - switch(ctx->algorithm) { + switch(ctx->algorithm->algo) { case NCR_ALG_RSA: cret = rsa_encrypt_key_ex( input, input_size, output, &osize, NULL, 0, ctx->oaep_hash, ctx->type, &ctx->key->key.pk.rsa); @@ -409,7 +413,7 @@ int cret; unsigned long osize = *output_size; int stat; - switch(ctx->algorithm) { + switch(ctx->algorithm->algo) { case NCR_ALG_RSA: cret = rsa_decrypt_key_ex( input, input_size, output, &osize, NULL, 0, ctx->oaep_hash, ctx->type, &stat, &ctx->key->key.pk.rsa); @@ -443,8 +447,12 @@ int ncr_pk_cipher_sign(const struct ncr_pk_ctx* ctx, int cret; unsigned long osize = *output_size; - switch(ctx->algorithm) { + switch(ctx->algorithm->algo) { case NCR_ALG_RSA: + if (ctx->sign_hash == NULL) { + err(); + return -EINVAL; + } cret = rsa_sign_hash_ex( input, input_size, output, &osize, ctx->type, ctx->sign_hash, ctx->salt_len, &ctx->key->key.pk.rsa); @@ -479,8 +487,12 @@ int ncr_pk_cipher_verify(const struct ncr_pk_ctx* ctx, int cret; int stat; - switch(ctx->algorithm) { + switch(ctx->algorithm->algo) { case NCR_ALG_RSA: + if (ctx->sign_hash == NULL) { + err(); + return -EINVAL; + } cret = rsa_verify_hash_ex( signature, signature_size, hash, hash_size, ctx->type, ctx->sign_hash, ctx->salt_len, &stat, &ctx->key->key.pk.rsa); diff --git a/ncr-pk.h b/ncr-pk.h index 1180017..873ee83 100644 --- a/ncr-pk.h +++ b/ncr-pk.h @@ -4,11 +4,11 @@ #include struct ncr_pk_ctx { - ncr_algorithm_t algorithm; /* algorithm */ + const struct algo_properties_st *algorithm; /* algorithm */ - ncr_algorithm_t sign_hash; /* for verification */ + const struct algo_properties_st *sign_hash; /* for verification */ - ncr_algorithm_t oaep_hash; + const struct algo_properties_st *oaep_hash; int salt_len; /* for RSA-PSS signatures */ int type; /* libtomcrypt type */ @@ -19,7 +19,7 @@ struct ncr_pk_ctx { /* PK */ void ncr_pk_clear(struct key_item_st* key); -int ncr_pk_generate(ncr_algorithm_t algo, +int ncr_pk_generate(const struct algo_properties_st *algo, struct ncr_key_generate_params_st * params, struct key_item_st* private, struct key_item_st* public); int ncr_pk_pack( const struct key_item_st * key, uint8_t * packed, uint32_t * packed_size); @@ -30,9 +30,9 @@ int ncr_pk_queue_init(void); void ncr_pk_queue_deinit(void); /* encryption/decryption */ -int ncr_pk_cipher_init(ncr_algorithm_t algo, +int ncr_pk_cipher_init(const struct algo_properties_st *algo, struct ncr_pk_ctx* ctx, struct ncr_key_params_st* params, - struct key_item_st *key); + struct key_item_st *key, const struct algo_properties_st *sign_hash); 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); diff --git a/ncr-sessions.c b/ncr-sessions.c index 6856310..f768cb3 100644 --- a/ncr-sessions.c +++ b/ncr-sessions.c @@ -112,186 +112,96 @@ struct session_item_st* ncr_session_new(struct list_sem_st* lst) return sess; } -static const struct algo_properties_st { - ncr_algorithm_t algo; - const char* kstr; - unsigned needs_iv:1; - unsigned hmac:1; - unsigned can_sign:1; - unsigned can_digest:1; - unsigned can_encrypt:1; - unsigned symmetric:1; - int digest_size; -} algo_properties[] = { +static const struct algo_properties_st algo_properties[] = { { .algo = NCR_ALG_NULL, .kstr = "ecb(cipher_null)", - .needs_iv = 0, .symmetric=1, .can_encrypt=1 }, + .needs_iv = 0, .is_symmetric=1, .can_encrypt=1, + .key_type = NCR_KEY_TYPE_INVALID }, { .algo = NCR_ALG_3DES_CBC, .kstr = "cbc(des3_ede)", - .needs_iv = 1, .symmetric=1, .can_encrypt=1 }, + .needs_iv = 1, .is_symmetric=1, .can_encrypt=1, + .key_type = NCR_KEY_TYPE_SECRET }, { .algo = NCR_ALG_AES_CBC, .kstr = "cbc(aes)", - .needs_iv = 1, .symmetric=1, .can_encrypt=1 }, + .needs_iv = 1, .is_symmetric=1, .can_encrypt=1, + .key_type = NCR_KEY_TYPE_SECRET }, { .algo = NCR_ALG_CAMELLIA_CBC, .kstr = "cbc(camelia)", - .needs_iv = 1, .symmetric=1, .can_encrypt=1 }, + .needs_iv = 1, .is_symmetric=1, .can_encrypt=1, + .key_type = NCR_KEY_TYPE_SECRET }, { .algo = NCR_ALG_AES_CTR, .kstr = "ctr(aes)", - .needs_iv = 1, .symmetric=1, .can_encrypt=1 }, + .needs_iv = 1, .is_symmetric=1, .can_encrypt=1, + .key_type = NCR_KEY_TYPE_SECRET }, { .algo = NCR_ALG_CAMELLIA_CTR, .kstr = "ctr(camelia)", - .needs_iv = 1, .symmetric=1, .can_encrypt=1 }, + .needs_iv = 1, .is_symmetric=1, .can_encrypt=1, + .key_type = NCR_KEY_TYPE_SECRET }, { .algo = NCR_ALG_ARCFOUR, .kstr = NULL, - .needs_iv = 0, .symmetric=1, .can_encrypt=1 }, + .needs_iv = 0, .is_symmetric=1, .can_encrypt=1, + .key_type = NCR_KEY_TYPE_SECRET }, { .algo = NCR_ALG_AES_ECB, .kstr = "ecb(aes)", - .needs_iv = 0, .symmetric=1, .can_encrypt=1 }, + .needs_iv = 0, .is_symmetric=1, .can_encrypt=1, + .key_type = NCR_KEY_TYPE_SECRET }, { .algo = NCR_ALG_CAMELLIA_ECB, .kstr = "ecb(camelia)", - .needs_iv = 0, .symmetric=1, .can_encrypt=1 }, + .needs_iv = 0, .is_symmetric=1, .can_encrypt=1, + .key_type = NCR_KEY_TYPE_SECRET }, { .algo = NCR_ALG_SHA1, .kstr = "sha1", - .digest_size = 20, .can_digest=1 }, + .digest_size = 20, .can_digest=1, + .key_type = NCR_KEY_TYPE_INVALID }, { .algo = NCR_ALG_MD5, .kstr = "md5", - .digest_size = 16, .can_digest=1 }, + .digest_size = 16, .can_digest=1, + .key_type = NCR_KEY_TYPE_INVALID }, { .algo = NCR_ALG_SHA2_224, .kstr = "sha224", - .digest_size = 28, .can_digest=1 }, + .digest_size = 28, .can_digest=1, + .key_type = NCR_KEY_TYPE_INVALID }, { .algo = NCR_ALG_SHA2_256, .kstr = "sha256", - .digest_size = 32, .can_digest=1 }, + .digest_size = 32, .can_digest=1, + .key_type = NCR_KEY_TYPE_INVALID }, { .algo = NCR_ALG_SHA2_384, .kstr = "sha384", - .digest_size = 48, .can_digest=1 }, + .digest_size = 48, .can_digest=1, + .key_type = NCR_KEY_TYPE_INVALID }, { .algo = NCR_ALG_SHA2_512, .kstr = "sha512", - .digest_size = 64, .can_digest=1 }, - { .algo = NCR_ALG_HMAC_SHA1, .hmac = 1, .kstr = "hmac(sha1)", - .digest_size = 20, .can_sign=1 }, - { .algo = NCR_ALG_HMAC_MD5, .hmac = 1, .kstr = "hmac(md5)", - .digest_size = 16, .can_sign=1 }, - { .algo = NCR_ALG_HMAC_SHA2_224, .hmac = 1, .kstr = "hmac(sha224)", - .digest_size = 28, .can_sign=1 }, - { .algo = NCR_ALG_HMAC_SHA2_256, .hmac = 1, .kstr = "hmac(sha256)", - .digest_size = 32, .can_sign=1 }, - { .algo = NCR_ALG_HMAC_SHA2_384, .hmac = 1, .kstr = "hmac(sha384)", - .digest_size = 48, .can_sign=1 }, - { .algo = NCR_ALG_HMAC_SHA2_512, .hmac = 1, .kstr = "hmac(sha512)", - .digest_size = 64, .can_sign=1 }, + .digest_size = 64, .can_digest=1, + .key_type = NCR_KEY_TYPE_INVALID }, + { .algo = NCR_ALG_HMAC_SHA1, .is_hmac = 1, .kstr = "hmac(sha1)", + .digest_size = 20, .can_sign=1, + .key_type = NCR_KEY_TYPE_SECRET }, + { .algo = NCR_ALG_HMAC_MD5, .is_hmac = 1, .kstr = "hmac(md5)", + .digest_size = 16, .can_sign=1, + .key_type = NCR_KEY_TYPE_SECRET }, + { .algo = NCR_ALG_HMAC_SHA2_224, .is_hmac = 1, .kstr = "hmac(sha224)", + .digest_size = 28, .can_sign=1, + .key_type = NCR_KEY_TYPE_SECRET }, + { .algo = NCR_ALG_HMAC_SHA2_256, .is_hmac = 1, .kstr = "hmac(sha256)", + .digest_size = 32, .can_sign=1, + .key_type = NCR_KEY_TYPE_SECRET }, + { .algo = NCR_ALG_HMAC_SHA2_384, .is_hmac = 1, .kstr = "hmac(sha384)", + .digest_size = 48, .can_sign=1, + .key_type = NCR_KEY_TYPE_SECRET }, + { .algo = NCR_ALG_HMAC_SHA2_512, .is_hmac = 1, .kstr = "hmac(sha512)", + .digest_size = 64, .can_sign=1, + .key_type = NCR_KEY_TYPE_SECRET }, { .algo = NCR_ALG_RSA, .kstr = NULL, - .can_encrypt=1, .can_sign=1}, + .can_encrypt=1, .can_sign=1, .key_type = NCR_KEY_TYPE_PUBLIC }, { .algo = NCR_ALG_DSA, .kstr = NULL, - .can_sign=1 }, + .can_sign=1, .key_type = NCR_KEY_TYPE_PUBLIC }, { .algo = NCR_ALG_NONE } }; -const char* _ncr_algo_to_str(ncr_algorithm_t algo) +const struct algo_properties_st *_ncr_algo_to_properties(ncr_algorithm_t algo) { -ncr_algorithm_t a; -int i = 0; + ncr_algorithm_t a; + int i = 0; - while((a=algo_properties[i].algo)!=NCR_ALG_NONE) { + for (i = 0; (a = algo_properties[i].algo) != NCR_ALG_NONE; i++) { if (a == algo) - return algo_properties[i].kstr; - i++; + return &algo_properties[i]; } return NULL; } -static int algo_needs_iv(ncr_algorithm_t algo) -{ -ncr_algorithm_t a; -int i = 0; - - while((a=algo_properties[i].algo)!=NCR_ALG_NONE) { - if (a == algo) - return algo_properties[i].needs_iv; - i++; - } - - return 0; -} - -static int algo_can_sign(ncr_algorithm_t algo) -{ -ncr_algorithm_t a; -int i = 0; - - while((a=algo_properties[i].algo)!=NCR_ALG_NONE) { - if (a == algo) - return algo_properties[i].can_sign; - i++; - } - - return 0; -} - -static int algo_can_encrypt(ncr_algorithm_t algo) -{ -ncr_algorithm_t a; -int i = 0; - - while((a=algo_properties[i].algo)!=NCR_ALG_NONE) { - if (a == algo) - return algo_properties[i].can_encrypt; - i++; - } - - return 0; -} - -static int algo_can_digest(ncr_algorithm_t algo) -{ -ncr_algorithm_t a; -int i = 0; - - while((a=algo_properties[i].algo)!=NCR_ALG_NONE) { - if (a == algo) - return algo_properties[i].can_digest; - i++; - } - - return 0; -} - - -static int algo_is_hmac(ncr_algorithm_t algo) -{ -ncr_algorithm_t a; -int i = 0; - - while((a=algo_properties[i].algo)!=NCR_ALG_NONE) { - if (a == algo) - return algo_properties[i].hmac; - i++; - } - - return 0; -} - -static int algo_is_symmetric(ncr_algorithm_t algo) -{ -ncr_algorithm_t a; -int i = 0; - - while((a=algo_properties[i].algo)!=NCR_ALG_NONE) { - if (a == algo) - return algo_properties[i].symmetric; - i++; - } - - return 0; -} - -int _ncr_algo_digest_size(ncr_algorithm_t algo) -{ -ncr_algorithm_t a; -int i = 0; - - while((a=algo_properties[i].algo)!=NCR_ALG_NONE) { - if (a == algo) - return algo_properties[i].digest_size; - i++; - } - - return 0; -} - static int _ncr_session_init(struct ncr_lists* lists, struct ncr_session_st* session) { struct session_item_st* ns = NULL; int ret; - ncr_algorithm_t sign_hash; - const char* str = NULL; + const struct algo_properties_st *sign_hash; ns = ncr_session_new(&lists->sessions); if (ns == NULL) { @@ -300,11 +210,16 @@ static int _ncr_session_init(struct ncr_lists* lists, struct ncr_session_st* ses } ns->op = session->op; - ns->algorithm = session->algorithm; + ns->algorithm = _ncr_algo_to_properties(session->algorithm); + if (ns->algorithm == NULL) { + err(); + ret = -EINVAL; + goto fail; + } switch(session->op) { case NCR_OP_ENCRYPT: case NCR_OP_DECRYPT: - if (algo_can_encrypt(session->algorithm)==0) { + if (!ns->algorithm->can_encrypt) { err(); ret = -EINVAL; goto fail; @@ -322,20 +237,19 @@ static int _ncr_session_init(struct ncr_lists* lists, struct ncr_session_st* ses if (session->algorithm == NCR_ALG_NULL) keysize = 0; - str = _ncr_algo_to_str(session->algorithm); - if (str == NULL) { + if (ns->algorithm->kstr == NULL) { err(); return -EINVAL; } - ret = cryptodev_cipher_init(&ns->cipher, str, + ret = cryptodev_cipher_init(&ns->cipher, ns->algorithm->kstr, ns->key->key.secret.data, keysize); if (ret < 0) { err(); goto fail; } - if (algo_needs_iv(session->algorithm)) { + if (ns->algorithm->needs_iv) { if (session->params.params.cipher.iv_size > sizeof(session->params.params.cipher.iv)) { err(); ret = -EINVAL; @@ -345,7 +259,7 @@ static int _ncr_session_init(struct ncr_lists* lists, struct ncr_session_st* ses } } else if (ns->key->type == NCR_KEY_TYPE_PRIVATE || ns->key->type == NCR_KEY_TYPE_PUBLIC) { ret = ncr_pk_cipher_init(ns->algorithm, &ns->pk, - &session->params, ns->key); + &session->params, ns->key, NULL); if (ret < 0) { err(); goto fail; @@ -359,7 +273,7 @@ static int _ncr_session_init(struct ncr_lists* lists, struct ncr_session_st* ses case NCR_OP_SIGN: case NCR_OP_VERIFY: - if (algo_can_sign(session->algorithm)==0) { + if (!ns->algorithm->can_sign) { err(); ret = -EINVAL; goto fail; @@ -373,13 +287,12 @@ static int _ncr_session_init(struct ncr_lists* lists, struct ncr_session_st* ses } if (ns->key->type == NCR_KEY_TYPE_SECRET) { - str = _ncr_algo_to_str(session->algorithm); - if (str == NULL) { + if (ns->algorithm->kstr == NULL) { err(); return -EINVAL; } - ret = cryptodev_hash_init(&ns->hash, str, 1, + ret = cryptodev_hash_init(&ns->hash, ns->algorithm->kstr, 1, ns->key->key.secret.data, ns->key->key.secret.size); if (ret < 0) { err(); @@ -387,33 +300,31 @@ static int _ncr_session_init(struct ncr_lists* lists, struct ncr_session_st* ses } } else if (ns->key->type == NCR_KEY_TYPE_PRIVATE || ns->key->type == NCR_KEY_TYPE_PUBLIC) { - ret = ncr_key_params_get_sign_hash(ns->key->algorithm, &session->params); - if (ret < 0) { + sign_hash = ncr_key_params_get_sign_hash(ns->key->algorithm, &session->params); + if (IS_ERR(sign_hash)) { err(); - return ret; + return PTR_ERR(sign_hash); } - sign_hash = ret; - if (algo_can_digest(sign_hash) == 0) { + if (!sign_hash->can_digest) { err(); ret = -EINVAL; goto fail; } - str = _ncr_algo_to_str(sign_hash); - if (str == NULL) { + if (sign_hash->kstr == NULL) { err(); ret = -EINVAL; goto fail; } ret = ncr_pk_cipher_init(ns->algorithm, &ns->pk, - &session->params, ns->key); + &session->params, ns->key, sign_hash); if (ret < 0) { err(); goto fail; } - ret = cryptodev_hash_init(&ns->hash, str, 0, NULL, 0); + ret = cryptodev_hash_init(&ns->hash, sign_hash->kstr, 0, NULL, 0); if (ret < 0) { err(); goto fail; @@ -426,19 +337,18 @@ static int _ncr_session_init(struct ncr_lists* lists, struct ncr_session_st* ses break; case NCR_OP_DIGEST: - if (algo_can_digest(session->algorithm)==0) { + if (!ns->algorithm->can_digest) { err(); ret = -EINVAL; goto fail; } - str = _ncr_algo_to_str(session->algorithm); - if (str == NULL) { + if (ns->algorithm->kstr == NULL) { err(); ret = -EINVAL; goto fail; } - ret = cryptodev_hash_init(&ns->hash, str, 0, NULL, 0); + ret = cryptodev_hash_init(&ns->hash, ns->algorithm->kstr, 0, NULL, 0); if (ret < 0) { err(); goto fail; @@ -525,7 +435,7 @@ static int _ncr_session_update(struct ncr_lists* lists, struct ncr_session_op_st goto fail; } - if (algo_is_symmetric(sess->algorithm)) { + if (sess->algorithm->is_symmetric) { /* read key */ ret = _cryptodev_cipher_encrypt(&sess->cipher, data->data, data->data_size, odata->data, data->data_size); @@ -571,7 +481,7 @@ static int _ncr_session_update(struct ncr_lists* lists, struct ncr_session_op_st } /* read key */ - if (algo_is_symmetric(sess->algorithm)) { + if (sess->algorithm->is_symmetric) { ret = _cryptodev_cipher_decrypt(&sess->cipher, data->data, data->data_size, odata->data, data->data_size); if (ret < 0) { err(); @@ -728,7 +638,7 @@ static int _ncr_session_final(struct ncr_lists* lists, struct ncr_session_op_st* } - if (algo_is_hmac(sess->algorithm)) { + if (sess->algorithm->is_hmac) { if (digest_size != odata->data_size || memcmp(odata->data, digest, digest_size) != 0) { @@ -773,7 +683,7 @@ static int _ncr_session_final(struct ncr_lists* lists, struct ncr_session_op_st* cryptodev_hash_deinit(&sess->hash); - if (sess->op != NCR_OP_DIGEST && !algo_is_hmac(sess->algorithm)) { + if (sess->op != NCR_OP_DIGEST && !sess->algorithm->is_hmac) { /* PK signature */ size_t new_size = odata->max_data_size; ret = ncr_pk_cipher_sign(&sess->pk, odata->data, odata->data_size, @@ -796,7 +706,7 @@ static int _ncr_session_final(struct ncr_lists* lists, struct ncr_session_op_st* fail: if (odata) _ncr_data_item_put(odata); cryptodev_hash_deinit(&sess->hash); - if (algo_is_symmetric(sess->algorithm)) { + if (sess->algorithm->is_symmetric) { cryptodev_cipher_deinit(&sess->cipher); } else { ncr_pk_cipher_deinit(&sess->pk); diff --git a/ncr.c b/ncr.c index 5740580..7014a30 100644 --- a/ncr.c +++ b/ncr.c @@ -173,31 +173,3 @@ ncr_ioctl(struct ncr_lists* lst, struct file *filp, return -EINVAL; } } - -/* Returns NCR_KEY_TYPE_SECRET if a secret key algorithm or MAC is given, - * and NCR_KEY_TYPE_PUBLIC if a public key algorithm is given. - */ -ncr_key_type_t ncr_algorithm_to_key_type(ncr_algorithm_t algo) -{ - switch(algo) { - case NCR_ALG_3DES_CBC: - case NCR_ALG_AES_CBC: - case NCR_ALG_CAMELLIA_CBC: - case NCR_ALG_ARCFOUR: - case NCR_ALG_HMAC_SHA1: - case NCR_ALG_HMAC_MD5: - case NCR_ALG_HMAC_SHA2_224: - case NCR_ALG_HMAC_SHA2_256: - case NCR_ALG_HMAC_SHA2_384: - case NCR_ALG_HMAC_SHA2_512: - return NCR_KEY_TYPE_SECRET; - case NCR_ALG_RSA: - case NCR_ALG_DSA: - return NCR_KEY_TYPE_PUBLIC; - default: - return NCR_KEY_TYPE_INVALID; - } - -} - - diff --git a/ncr_int.h b/ncr_int.h index 12c053a..506dfa3 100644 --- a/ncr_int.h +++ b/ncr_int.h @@ -10,10 +10,26 @@ #define err() printk(KERN_DEBUG"ncr: %s: %s: %d\n", __FILE__, __func__, __LINE__) +struct algo_properties_st { + ncr_algorithm_t algo; + const char *kstr; + unsigned needs_iv:1; + unsigned is_hmac:1; + unsigned can_sign:1; + unsigned can_digest:1; + unsigned can_encrypt:1; + unsigned is_symmetric: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. + */ + ncr_key_type_t key_type; +}; + struct session_item_st { struct list_head list; - ncr_algorithm_t algorithm; + const struct algo_properties_st *algorithm; ncr_crypto_op_t op; /* contexts for various options. @@ -56,7 +72,7 @@ struct key_item_st { */ ncr_key_type_t type; unsigned int flags; - ncr_algorithm_t algorithm; /* valid for public/private keys */ + const struct algo_properties_st *algorithm; /* non-NULL for public/private keys */ uint8_t key_id[MAX_KEY_ID_SIZE]; size_t key_id_size; @@ -142,8 +158,6 @@ int ncr_limits_add_and_check(uid_t uid, pid_t pid, limits_type_t type); void ncr_limits_init(void); void ncr_limits_deinit(void); -ncr_key_type_t ncr_algorithm_to_key_type(ncr_algorithm_t algo); - int ncr_key_wrap(struct list_sem_st* keys, struct list_sem_st* data, void __user* arg); int ncr_key_unwrap(struct list_sem_st*, struct list_sem_st* data, void __user* arg); int ncr_key_storage_wrap(struct list_sem_st* key_lst, struct list_sem_st* data_lst, void __user* arg); @@ -191,8 +205,7 @@ inline static unsigned int data_flags_to_key(unsigned int data_flags) return flags; } -const char* _ncr_algo_to_str(ncr_algorithm_t algo); -int _ncr_algo_digest_size(ncr_algorithm_t algo); -int ncr_key_params_get_sign_hash(ncr_algorithm_t algo, struct ncr_key_params_st * params); +const struct algo_properties_st *_ncr_algo_to_properties(ncr_algorithm_t algo); +const struct algo_properties_st *ncr_key_params_get_sign_hash(const struct algo_properties_st *algo, struct ncr_key_params_st * params); #endif -- cgit From 4b45720ea1dffc3514c81439c7f93928d05c5521 Mon Sep 17 00:00:00 2001 From: Nikos Mavrogiannopoulos Date: Sat, 24 Jul 2010 12:14:00 +0200 Subject: Simplified the session_op structure and combined the OP_SIGN with the OP_DIGEST for digest algorithms. --- examples/ncr.c | 14 +++--- examples/pk.c | 24 ++++----- examples/speed.c | 4 +- ncr-sessions.c | 146 +++++++++++++++++++++++++++---------------------------- ncr.h | 19 ++------ ncr_int.h | 1 + 6 files changed, 97 insertions(+), 111 deletions(-) diff --git a/examples/ncr.c b/examples/ncr.c index 234e8bd..d9870e0 100644 --- a/examples/ncr.c +++ b/examples/ncr.c @@ -809,8 +809,8 @@ test_ncr_aes(int cfd) nop.init.algorithm = NCR_ALG_AES_ECB; nop.init.key = key; nop.init.op = NCR_OP_ENCRYPT; - nop.op.data.cipher.plaintext = dd; - nop.op.data.cipher.ciphertext = dd2; + nop.op.input = dd; + nop.op.output = dd2; if (ioctl(cfd, NCRIO_SESSION_ONCE, &nop)) { fprintf(stderr, "Error: %s:%d\n", __func__, __LINE__); @@ -884,8 +884,8 @@ test_ncr_aes(int cfd) nop.init.algorithm = NCR_ALG_AES_ECB; nop.init.key = key; nop.init.op = NCR_OP_DECRYPT; - nop.op.data.cipher.ciphertext = dd; - nop.op.data.cipher.plaintext = dd2; + nop.op.input = dd; + nop.op.output = dd2; if (ioctl(cfd, NCRIO_SESSION_ONCE, &nop)) { fprintf(stderr, "Error: %s:%d\n", __func__, __LINE__); @@ -946,7 +946,7 @@ struct hash_vectors_st { .plaintext_size = sizeof("what do ya want for nothing?")-1, .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, + .op = NCR_OP_SIGN, }, { .name = "HMAC-MD5", @@ -1098,8 +1098,8 @@ test_ncr_hash(int cfd) if (hash_vectors[i].key != NULL) nop.init.key = key; nop.init.op = hash_vectors[i].op; - nop.op.data.sign.text = dd; - nop.op.data.sign.output = dd2; + nop.op.input = dd; + nop.op.output = dd2; if (ioctl(cfd, NCRIO_SESSION_ONCE, &nop)) { fprintf(stderr, "Error: %s:%d\n", __func__, __LINE__); diff --git a/examples/pk.c b/examples/pk.c index fef695c..ce9dff8 100644 --- a/examples/pk.c +++ b/examples/pk.c @@ -371,8 +371,8 @@ static int rsa_key_encrypt(int cfd, ncr_key_t privkey, ncr_key_t pubkey, int oae nop.init.params.params.rsa.type = RSA_PKCS1_V1_5; } nop.init.op = NCR_OP_ENCRYPT; - nop.op.data.cipher.plaintext = datad; - nop.op.data.cipher.ciphertext = encd; + nop.op.input = datad; + nop.op.output = encd; if (ioctl(cfd, NCRIO_SESSION_ONCE, &nop)) { fprintf(stderr, "Error: %s:%d\n", __func__, __LINE__); @@ -391,8 +391,8 @@ static int rsa_key_encrypt(int cfd, ncr_key_t privkey, ncr_key_t pubkey, int oae } else { nop.init.params.params.rsa.type = RSA_PKCS1_V1_5; } - nop.op.data.cipher.plaintext = encd; - nop.op.data.cipher.ciphertext = encd; + nop.op.input = encd; + nop.op.output = encd; if (ioctl(cfd, NCRIO_SESSION_ONCE, &nop)) { fprintf(stderr, "Error: %s:%d\n", __func__, __LINE__); @@ -466,8 +466,8 @@ static int rsa_key_sign_verify(int cfd, ncr_key_t privkey, ncr_key_t pubkey, int nop.init.params.params.rsa.sign_hash = NCR_ALG_SHA1; nop.init.op = NCR_OP_SIGN; - nop.op.data.sign.text = datad; - nop.op.data.sign.output = signd; + nop.op.input = datad; + nop.op.output = signd; if (ioctl(cfd, NCRIO_SESSION_ONCE, &nop)) { fprintf(stderr, "Error: %s:%d\n", __func__, __LINE__); @@ -483,8 +483,8 @@ static int rsa_key_sign_verify(int cfd, ncr_key_t privkey, ncr_key_t pubkey, int nop.init.params.params.rsa.sign_hash = NCR_ALG_SHA1; nop.init.op = NCR_OP_VERIFY; - nop.op.data.verify.text = datad; - nop.op.data.verify.signature = signd; + nop.op.input = datad; + nop.op.output = signd; if (ioctl(cfd, NCRIO_SESSION_ONCE, &nop)) { fprintf(stderr, "Error: %s:%d\n", __func__, __LINE__); @@ -545,8 +545,8 @@ static int dsa_key_sign_verify(int cfd, ncr_key_t privkey, ncr_key_t pubkey) nop.init.params.params.dsa.sign_hash = NCR_ALG_SHA1; nop.init.op = NCR_OP_SIGN; - nop.op.data.sign.text = datad; - nop.op.data.sign.output = signd; + nop.op.input = datad; + nop.op.output = signd; if (ioctl(cfd, NCRIO_SESSION_ONCE, &nop)) { fprintf(stderr, "Error: %s:%d\n", __func__, __LINE__); @@ -561,8 +561,8 @@ static int dsa_key_sign_verify(int cfd, ncr_key_t privkey, ncr_key_t pubkey) nop.init.params.params.dsa.sign_hash = NCR_ALG_SHA1; nop.init.op = NCR_OP_VERIFY; - nop.op.data.verify.text = datad; - nop.op.data.verify.signature = signd; + nop.op.input = datad; + nop.op.output = signd; if (ioctl(cfd, NCRIO_SESSION_ONCE, &nop)) { fprintf(stderr, "Error: %s:%d\n", __func__, __LINE__); diff --git a/examples/speed.c b/examples/speed.c index 1c76eb6..d3cf04a 100644 --- a/examples/speed.c +++ b/examples/speed.c @@ -189,8 +189,8 @@ int encrypt_data_ncr(int cfd, int algo, int chunksize) nop.init.algorithm = algo; nop.init.key = key; nop.init.op = NCR_OP_ENCRYPT; - nop.op.data.cipher.plaintext = dd; - nop.op.data.cipher.ciphertext = dd; + nop.op.input = dd; + nop.op.output = dd; if (ioctl(cfd, NCRIO_SESSION_ONCE, &nop)) { fprintf(stderr, "Error: %s:%d\n", __func__, __LINE__); diff --git a/ncr-sessions.c b/ncr-sessions.c index f768cb3..b8eabdd 100644 --- a/ncr-sessions.c +++ b/ncr-sessions.c @@ -176,9 +176,9 @@ static const struct algo_properties_st algo_properties[] = { { .algo = NCR_ALG_HMAC_SHA2_512, .is_hmac = 1, .kstr = "hmac(sha512)", .digest_size = 64, .can_sign=1, .key_type = NCR_KEY_TYPE_SECRET }, - { .algo = NCR_ALG_RSA, .kstr = NULL, + { .algo = NCR_ALG_RSA, .kstr = NULL, .is_pk = 1, .can_encrypt=1, .can_sign=1, .key_type = NCR_KEY_TYPE_PUBLIC }, - { .algo = NCR_ALG_DSA, .kstr = NULL, + { .algo = NCR_ALG_DSA, .kstr = NULL, .is_pk = 1, .can_sign=1, .key_type = NCR_KEY_TYPE_PUBLIC }, { .algo = NCR_ALG_NONE } @@ -273,85 +273,83 @@ static int _ncr_session_init(struct ncr_lists* lists, struct ncr_session_st* ses case NCR_OP_SIGN: case NCR_OP_VERIFY: - if (!ns->algorithm->can_sign) { + if (!ns->algorithm->can_sign && !ns->algorithm->can_digest) { err(); ret = -EINVAL; goto fail; } - /* read key */ - ret = ncr_key_item_get_read( &ns->key, &lists->key, session->key); - if (ret < 0) { - err(); - goto fail; - } - - if (ns->key->type == NCR_KEY_TYPE_SECRET) { + if (ns->algorithm->can_digest) { if (ns->algorithm->kstr == NULL) { - err(); - return -EINVAL; - } - - ret = cryptodev_hash_init(&ns->hash, ns->algorithm->kstr, 1, - ns->key->key.secret.data, ns->key->key.secret.size); - if (ret < 0) { - err(); - goto fail; - } - - } else if (ns->key->type == NCR_KEY_TYPE_PRIVATE || ns->key->type == NCR_KEY_TYPE_PUBLIC) { - sign_hash = ncr_key_params_get_sign_hash(ns->key->algorithm, &session->params); - if (IS_ERR(sign_hash)) { - err(); - return PTR_ERR(sign_hash); - } - - if (!sign_hash->can_digest) { - err(); - ret = -EINVAL; - goto fail; - } - if (sign_hash->kstr == NULL) { err(); ret = -EINVAL; goto fail; } - ret = ncr_pk_cipher_init(ns->algorithm, &ns->pk, - &session->params, ns->key, sign_hash); + ret = cryptodev_hash_init(&ns->hash, ns->algorithm->kstr, 0, NULL, 0); if (ret < 0) { err(); goto fail; } - - ret = cryptodev_hash_init(&ns->hash, sign_hash->kstr, 0, NULL, 0); + + } else { + /* read key */ + ret = ncr_key_item_get_read( &ns->key, &lists->key, session->key); if (ret < 0) { err(); goto fail; } - } else { - err(); - ret = -EINVAL; - goto fail; - } - break; - case NCR_OP_DIGEST: - if (!ns->algorithm->can_digest) { - err(); - ret = -EINVAL; - goto fail; - } - if (ns->algorithm->kstr == NULL) { - err(); - ret = -EINVAL; - goto fail; - } + if (ns->algorithm->is_hmac && ns->key->type == NCR_KEY_TYPE_SECRET) { + if (ns->algorithm->kstr == NULL) { + err(); + ret = -EINVAL; + goto fail; + } - ret = cryptodev_hash_init(&ns->hash, ns->algorithm->kstr, 0, NULL, 0); - if (ret < 0) { - err(); - goto fail; + ret = cryptodev_hash_init(&ns->hash, ns->algorithm->kstr, 1, + ns->key->key.secret.data, ns->key->key.secret.size); + if (ret < 0) { + err(); + goto fail; + } + + } else if (ns->algorithm->is_pk && (ns->key->type == NCR_KEY_TYPE_PRIVATE || ns->key->type == NCR_KEY_TYPE_PUBLIC)) { + sign_hash = ncr_key_params_get_sign_hash(ns->key->algorithm, &session->params); + if (IS_ERR(sign_hash)) { + err(); + return PTR_ERR(sign_hash); + } + + if (!sign_hash->can_digest) { + err(); + ret = -EINVAL; + goto fail; + } + + if (sign_hash->kstr == NULL) { + err(); + ret = -EINVAL; + goto fail; + } + + ret = ncr_pk_cipher_init(ns->algorithm, &ns->pk, + &session->params, ns->key, sign_hash); + if (ret < 0) { + err(); + goto fail; + } + + ret = cryptodev_hash_init(&ns->hash, sign_hash->kstr, 0, NULL, 0); + if (ret < 0) { + err(); + goto fail; + } + } else { + err(); + ret = -EINVAL; + goto fail; + } } break; @@ -415,14 +413,14 @@ static int _ncr_session_update(struct ncr_lists* lists, struct ncr_session_op_st switch(sess->op) { case NCR_OP_ENCRYPT: /* obtain data item */ - data = ncr_data_item_get( &lists->data, op->data.cipher.plaintext); + data = ncr_data_item_get( &lists->data, op->input); if (data == NULL) { err(); ret = -EINVAL; goto fail; } - odata = ncr_data_item_get( &lists->data, op->data.cipher.ciphertext); + odata = ncr_data_item_get( &lists->data, op->output); if (odata == NULL) { err(); ret = -EINVAL; @@ -460,14 +458,14 @@ static int _ncr_session_update(struct ncr_lists* lists, struct ncr_session_op_st break; case NCR_OP_DECRYPT: /* obtain data item */ - data = ncr_data_item_get( &lists->data, op->data.cipher.ciphertext); + data = ncr_data_item_get( &lists->data, op->input); if (data == NULL) { err(); ret = -EINVAL; goto fail; } - odata = ncr_data_item_get( &lists->data, op->data.cipher.plaintext); + odata = ncr_data_item_get( &lists->data, op->output); if (odata == NULL) { err(); ret = -EINVAL; @@ -505,9 +503,8 @@ static int _ncr_session_update(struct ncr_lists* lists, struct ncr_session_op_st break; case NCR_OP_SIGN: - case NCR_OP_DIGEST: /* obtain data item */ - data = ncr_data_item_get( &lists->data, op->data.sign.text); + data = ncr_data_item_get( &lists->data, op->input); if (data == NULL) { err(); ret = -EINVAL; @@ -523,7 +520,7 @@ static int _ncr_session_update(struct ncr_lists* lists, struct ncr_session_op_st case NCR_OP_VERIFY: /* obtain data item */ - data = ncr_data_item_get( &lists->data, op->data.verify.text); + data = ncr_data_item_get( &lists->data, op->input); if (data == NULL) { err(); ret = -EINVAL; @@ -602,8 +599,8 @@ static int _ncr_session_final(struct ncr_lists* lists, struct ncr_session_op_st* case NCR_OP_ENCRYPT: case NCR_OP_DECRYPT: /* obtain data item */ - if (op->data.cipher.plaintext != NCR_DATA_INVALID && - op->data.cipher.ciphertext != NCR_DATA_INVALID) { + if (op->input != NCR_DATA_INVALID && + op->output != NCR_DATA_INVALID) { ret = _ncr_session_update(lists, op); if (ret < 0) goto fail; @@ -612,13 +609,13 @@ static int _ncr_session_final(struct ncr_lists* lists, struct ncr_session_op_st* case NCR_OP_VERIFY: /* obtain data item */ - if (op->data.sign.text != NCR_DATA_INVALID) { + if (op->input != NCR_DATA_INVALID) { ret = _ncr_session_update(lists, op); if (ret < 0) goto fail; } - odata = ncr_data_item_get( &lists->data, op->data.verify.signature); + odata = ncr_data_item_get( &lists->data, op->output); if (odata == NULL) { err(); ret = -EINVAL; @@ -658,14 +655,13 @@ static int _ncr_session_final(struct ncr_lists* lists, struct ncr_session_op_st* break; case NCR_OP_SIGN: - case NCR_OP_DIGEST: /* obtain data item */ - if (op->data.sign.text != NCR_DATA_INVALID) { + if (op->input != NCR_DATA_INVALID) { ret = _ncr_session_update(lists, op); if (ret < 0) goto fail; } - odata = ncr_data_item_get( &lists->data, op->data.sign.output); + odata = ncr_data_item_get( &lists->data, op->output); if (odata == NULL) { err(); ret = -EINVAL; @@ -683,7 +679,7 @@ static int _ncr_session_final(struct ncr_lists* lists, struct ncr_session_op_st* cryptodev_hash_deinit(&sess->hash); - if (sess->op != NCR_OP_DIGEST && !sess->algorithm->is_hmac) { + if (sess->algorithm->is_pk) { /* PK signature */ size_t new_size = odata->max_data_size; ret = ncr_pk_cipher_sign(&sess->pk, odata->data, odata->data_size, diff --git a/ncr.h b/ncr.h index cd82a62..d3f4813 100644 --- a/ncr.h +++ b/ncr.h @@ -250,7 +250,6 @@ struct ncr_key_storage_wrap_st { typedef enum { NCR_OP_ENCRYPT=1, NCR_OP_DECRYPT, - NCR_OP_DIGEST, NCR_OP_SIGN, NCR_OP_VERIFY, } ncr_crypto_op_t; @@ -281,20 +280,10 @@ struct ncr_session_op_st { /* input */ ncr_session_t ses; - union { - struct { - ncr_data_t plaintext; - ncr_data_t ciphertext; - } cipher; - struct { - ncr_data_t text; - ncr_data_t output; - } sign; /* mac/hash/sign */ - struct { - ncr_data_t text; - ncr_data_t signature; - } verify; /* mac/sign */ - } data; + ncr_data_t input; + ncr_data_t output; /* when verifying signature this is + * the place of the signature. + */ /* output of verification */ ncr_error_t err; diff --git a/ncr_int.h b/ncr_int.h index 506dfa3..fadb46e 100644 --- a/ncr_int.h +++ b/ncr_int.h @@ -19,6 +19,7 @@ struct algo_properties_st { unsigned can_digest:1; unsigned can_encrypt:1; unsigned is_symmetric:1; + unsigned is_pk: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. -- cgit From ffb3e747f8b50ca18701530d1729a4ee3aa4ae69 Mon Sep 17 00:00:00 2001 From: Nikos Mavrogiannopoulos Date: Sat, 24 Jul 2010 13:43:43 +0200 Subject: Added a support for reading session data directly from userspace. --- .gitignore | 1 + cryptodev_cipher.c | 8 +- cryptodev_int.h | 16 +- cryptodev_main.c | 11 +- examples/Makefile | 8 +- examples/ncr-direct.c | 443 +++++++++++++++++++++++++++++++++ examples/ncr.c | 15 +- examples/pk.c | 30 ++- examples/speed.c | 5 +- ncr-data.c | 2 + ncr-pk.c | 210 ++++++++++++---- ncr-pk.h | 22 +- ncr-sessions.c | 667 ++++++++++++++++++++++++++++++++++++++++---------- ncr.c | 1 + ncr.h | 26 +- ncr_int.h | 9 + 16 files changed, 1246 insertions(+), 228 deletions(-) create mode 100644 examples/ncr-direct.c diff --git a/.gitignore b/.gitignore index 4379d92..e3f0923 100644 --- a/.gitignore +++ b/.gitignore @@ -10,6 +10,7 @@ modules.order examples/cipher examples/hmac examples/ncr +examples/ncr-direct examples/pk examples/speed releases diff --git a/cryptodev_cipher.c b/cryptodev_cipher.c index fa5aab2..0dd0db7 100644 --- a/cryptodev_cipher.c +++ b/cryptodev_cipher.c @@ -188,24 +188,24 @@ struct scatterlist sg, sg2; } -ssize_t cryptodev_cipher_encrypt( struct cipher_data* cdata, struct scatterlist *sg1, struct scatterlist *sg2, size_t len) +ssize_t cryptodev_cipher_encrypt( struct cipher_data* cdata, const struct scatterlist *sg1, struct scatterlist *sg2, size_t len) { int ret; INIT_COMPLETION(cdata->async.result->completion); - ablkcipher_request_set_crypt(cdata->async.request, sg1, sg2, + ablkcipher_request_set_crypt(cdata->async.request, (struct scatterlist*)sg1, sg2, len, cdata->async.iv); ret = crypto_ablkcipher_encrypt(cdata->async.request); return waitfor(cdata->async.result,ret); } -ssize_t cryptodev_cipher_decrypt( struct cipher_data* cdata, struct scatterlist *sg1, struct scatterlist *sg2, size_t len) +ssize_t cryptodev_cipher_decrypt( struct cipher_data* cdata, const struct scatterlist *sg1, struct scatterlist *sg2, size_t len) { int ret; INIT_COMPLETION(cdata->async.result->completion); - ablkcipher_request_set_crypt(cdata->async.request, sg1, sg2, + ablkcipher_request_set_crypt(cdata->async.request, (struct scatterlist*)sg1, sg2, len, cdata->async.iv); ret = crypto_ablkcipher_decrypt(cdata->async.request); diff --git a/cryptodev_int.h b/cryptodev_int.h index a0d3073..3c6eca4 100644 --- a/cryptodev_int.h +++ b/cryptodev_int.h @@ -24,6 +24,18 @@ extern int cryptodev_verbosity; +/* For zero copy */ +int __get_userbuf(uint8_t *addr, uint32_t len, int write, + int pgcount, struct page **pg, struct scatterlist *sg); +void release_user_pages(struct page **pg, int pagecount); + +/* last page - first page + 1 */ +#define PAGECOUNT(buf, buflen) \ + ((((unsigned long)(buf + buflen - 1) & PAGE_MASK) >> PAGE_SHIFT) - \ + (((unsigned long) buf & PAGE_MASK) >> PAGE_SHIFT) + 1) + +#define DEFAULT_PREALLOC_PAGES 32 + struct cipher_data { int init; /* 0 uninitialized */ @@ -39,8 +51,8 @@ struct cipher_data int cryptodev_cipher_init(struct cipher_data* out, const char* alg_name, uint8_t * key, size_t keylen); void cryptodev_cipher_deinit(struct cipher_data* cdata); -ssize_t cryptodev_cipher_decrypt( struct cipher_data* cdata, struct scatterlist *sg1, struct scatterlist *sg2, size_t len); -ssize_t cryptodev_cipher_encrypt( struct cipher_data* cdata, struct scatterlist *sg1, struct scatterlist *sg2, size_t len); +ssize_t cryptodev_cipher_decrypt( struct cipher_data* cdata, const struct scatterlist *sg1, struct scatterlist *sg2, size_t len); +ssize_t cryptodev_cipher_encrypt( struct cipher_data* cdata, const struct scatterlist *sg1, struct scatterlist *sg2, size_t len); void cryptodev_cipher_set_iv(struct cipher_data* cdata, void* iv, size_t iv_size); int _cryptodev_cipher_decrypt(struct cipher_data* cdata, const void* ciphertext, diff --git a/cryptodev_main.c b/cryptodev_main.c index 0316a74..89b9a02 100644 --- a/cryptodev_main.c +++ b/cryptodev_main.c @@ -65,8 +65,6 @@ module_param(enable_stats, int, 0644); MODULE_PARM_DESC(enable_stats, "collect statictics about cryptodev usage"); #endif -#define DEFAULT_PREALLOC_PAGES 16 - /* ====== CryptoAPI ====== */ struct fcrypt { struct list_head list; @@ -495,7 +493,7 @@ __crypto_run_std(struct csession *ses_ptr, struct crypt_op *cop) #ifndef DISABLE_ZCOPY -static void release_user_pages(struct page **pg, int pagecount) +void release_user_pages(struct page **pg, int pagecount) { while (pagecount--) { if (!PageReserved(pg[pagecount])) @@ -504,16 +502,11 @@ static void release_user_pages(struct page **pg, int pagecount) } } -/* last page - first page + 1 */ -#define PAGECOUNT(buf, buflen) \ - ((((unsigned long)(buf + buflen - 1) & PAGE_MASK) >> PAGE_SHIFT) - \ - (((unsigned long) buf & PAGE_MASK) >> PAGE_SHIFT) + 1) - /* offset of buf in it's first page */ #define PAGEOFFSET(buf) ((unsigned long)buf & ~PAGE_MASK) /* fetch the pages addr resides in into pg and initialise sg with them */ -static int __get_userbuf(uint8_t *addr, uint32_t len, int write, +int __get_userbuf(uint8_t *addr, uint32_t len, int write, int pgcount, struct page **pg, struct scatterlist *sg) { int ret, pglen, i = 0; diff --git a/examples/Makefile b/examples/Makefile index c65297f..f482649 100644 --- a/examples/Makefile +++ b/examples/Makefile @@ -1,7 +1,7 @@ CC = gcc CFLAGS = -Wall -g -O2 -progs := cipher hmac ncr pk speed +progs := cipher hmac ncr pk speed ncr-direct all: $(progs) @@ -17,15 +17,19 @@ hmac: hmac.c ncr: ncr.c $(CC) $(CFLAGS) $< -o $@ +ncr-direct: ncr-direct.c + $(CC) $(CFLAGS) $< -o $@ + pk: pk.c $(CC) $(CFLAGS) $< -o $@ -L/usr/local/lib -lgnutls check: $(progs) ./ncr + ./ncr-direct ./pk ./cipher ./hmac ./speed clean: - rm -f *.o *~ hmac cipher ncr pk speed + rm -f *.o *~ hmac cipher ncr pk speed ncr-direct diff --git a/examples/ncr-direct.c b/examples/ncr-direct.c new file mode 100644 index 0000000..0908e2c --- /dev/null +++ b/examples/ncr-direct.c @@ -0,0 +1,443 @@ +/* + * Demo on how to use /dev/crypto device for HMAC. + * + * Placed under public domain. + * + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include "../ncr.h" +#include + +#define DATA_SIZE 4096 +#define KEY_DATA_SIZE 16 + + +struct aes_vectors_st { + const uint8_t* key; + const uint8_t* plaintext; + const uint8_t* ciphertext; +} aes_vectors[] = { + { + .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 = (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 = (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 = (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 = (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", + }, +}; + +/* AES cipher */ +static int +test_ncr_aes(int cfd) +{ + struct ncr_data_init_st dinit; + ncr_key_t key; + struct ncr_key_data_st keydata; + struct ncr_data_st kdata; + ncr_data_t dd, dd2; + uint8_t data[KEY_DATA_SIZE]; + int i, j; + struct ncr_session_once_op_st nop; + + dinit.max_object_size = KEY_DATA_SIZE; + dinit.flags = NCR_DATA_FLAG_EXPORTABLE; + dinit.initial_data = NULL; + dinit.initial_data_size = 0; + + if (ioctl(cfd, NCRIO_DATA_INIT, &dinit)) { + fprintf(stderr, "Error: %s:%d\n", __func__, __LINE__); + perror("ioctl(NCRIO_DATA_INIT)"); + return 1; + } + + dd = dinit.desc; + + if (ioctl(cfd, NCRIO_DATA_INIT, &dinit)) { + fprintf(stderr, "Error: %s:%d\n", __func__, __LINE__); + perror("ioctl(NCRIO_DATA_INIT)"); + return 1; + } + + dd2 = dinit.desc; + + /* convert it to key */ + if (ioctl(cfd, NCRIO_KEY_INIT, &key)) { + perror("ioctl(NCRIO_KEY_INIT)"); + return 1; + } + + keydata.key_id[0] = 'a'; + keydata.key_id[2] = 'b'; + keydata.key_id_size = 2; + keydata.type = NCR_KEY_TYPE_SECRET; + keydata.algorithm = NCR_ALG_AES_CBC; + keydata.flags = NCR_KEY_FLAG_EXPORTABLE; + + + fprintf(stdout, "Tests on AES Encryption\n"); + for (i=0;imax_data_size = init.max_object_size; + + sg_init_one(&data->sg, data->data, data->max_data_size); if (init.initial_data != NULL) { if (unlikely(copy_from_user(data->data, init.initial_data, diff --git a/ncr-pk.c b/ncr-pk.c index bfe575d..8d85a92 100644 --- a/ncr-pk.c +++ b/ncr-pk.c @@ -377,129 +377,230 @@ int ncr_pk_cipher_init(const struct algo_properties_st *algo, } int ncr_pk_cipher_encrypt(const struct ncr_pk_ctx* ctx, - const void* input, size_t input_size, - void* output, size_t *output_size) + const struct scatterlist* isg, unsigned int isg_cnt, size_t isg_size, + struct scatterlist *osg, unsigned int osg_cnt, size_t* osg_size) { -int cret; -unsigned long osize = *output_size; +int cret, ret; +unsigned long osize = *osg_size; +uint8_t* tmp; +void * input, *output; + + tmp = kmalloc(isg_size + *osg_size, GFP_KERNEL); + if (tmp == NULL) { + err(); + return -ENOMEM; + } + + ret = sg_copy_to_buffer((struct scatterlist*)isg, isg_cnt, tmp, isg_size); + if (ret != isg_size) { + err(); + ret = -EINVAL; + goto fail; + } + + input = tmp; + output = &tmp[isg_size]; + switch(ctx->algorithm->algo) { case NCR_ALG_RSA: - cret = rsa_encrypt_key_ex( input, input_size, output, &osize, + cret = rsa_encrypt_key_ex( input, isg_size, output, &osize, NULL, 0, ctx->oaep_hash, ctx->type, &ctx->key->key.pk.rsa); if (cret != CRYPT_OK) { - printk("cret: %d type: %d\n", cret, ctx->type); err(); - return tomerr(cret); + ret = tomerr(cret); + goto fail; } - *output_size = osize; + *osg_size = osize; + break; case NCR_ALG_DSA: - return -EINVAL; - break; + ret = -EINVAL; + goto fail; default: err(); - return -EINVAL; + ret = -EINVAL; + goto fail; } - - return 0; + + ret = sg_copy_from_buffer(osg, osg_cnt, output, *osg_size); + if (ret != *osg_size) { + err(); + ret = -EINVAL; + goto fail; + } + + ret = 0; + +fail: + kfree(tmp); + return ret; } -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 ncr_pk_cipher_decrypt(const struct ncr_pk_ctx* ctx, + const struct scatterlist* isg, unsigned int isg_cnt, size_t isg_size, + struct scatterlist *osg, unsigned int osg_cnt, size_t* osg_size) { -int cret; -unsigned long osize = *output_size; +int cret, ret; int stat; +unsigned long osize = *osg_size; +uint8_t* tmp; +void * input, *output; + + tmp = kmalloc(isg_size + *osg_size, GFP_KERNEL); + if (tmp == NULL) { + err(); + return -ENOMEM; + } + + input = tmp; + output = &tmp[isg_size]; + + ret = sg_copy_to_buffer((struct scatterlist*)isg, isg_cnt, input, isg_size); + if (ret != isg_size) { + err(); + ret = -EINVAL; + goto fail; + } switch(ctx->algorithm->algo) { case NCR_ALG_RSA: - cret = rsa_decrypt_key_ex( input, input_size, output, &osize, + cret = rsa_decrypt_key_ex( input, isg_size, output, &osize, NULL, 0, ctx->oaep_hash, ctx->type, &stat, &ctx->key->key.pk.rsa); if (cret != CRYPT_OK) { err(); - return tomerr(cret); + ret = tomerr(cret); + goto fail; } if (stat==0) { err(); - return -EINVAL; + ret = -EINVAL; + goto fail; } - *output_size = osize; + *osg_size = osize; break; case NCR_ALG_DSA: - return -EINVAL; - break; + ret = -EINVAL; + goto fail; default: err(); - return -EINVAL; + ret = -EINVAL; + goto fail; } + + ret = sg_copy_from_buffer(osg, osg_cnt, output, *osg_size); + if (ret != *osg_size) { + err(); + ret = -EINVAL; + goto fail; + } + + ret = 0; +fail: + kfree(tmp); - return 0; + return ret; } int ncr_pk_cipher_sign(const struct ncr_pk_ctx* ctx, - const void* input, size_t input_size, - void* output, size_t *output_size) + const struct scatterlist* isg, unsigned int isg_cnt, size_t isg_size, + struct scatterlist *osg, unsigned int osg_cnt, size_t* osg_size) { -int cret; -unsigned long osize = *output_size; +int cret, ret; +unsigned long osize = *osg_size; +uint8_t* tmp; +void * input, *output; + + tmp = kmalloc(isg_size + *osg_size, GFP_KERNEL); + if (tmp == NULL) { + err(); + return -ENOMEM; + } + + input = tmp; + output = &tmp[isg_size]; + + ret = sg_copy_to_buffer((struct scatterlist*)isg, isg_cnt, input, isg_size); + if (ret != isg_size) { + err(); + ret = -EINVAL; + goto fail; + } switch(ctx->algorithm->algo) { case NCR_ALG_RSA: - if (ctx->sign_hash == NULL) { - err(); - return -EINVAL; - } - cret = rsa_sign_hash_ex( input, input_size, output, &osize, + cret = rsa_sign_hash_ex( input, isg_size, output, &osize, ctx->type, ctx->sign_hash, ctx->salt_len, &ctx->key->key.pk.rsa); if (cret != CRYPT_OK) { err(); return tomerr(cret); } - *output_size = osize; + *osg_size = osize; break; case NCR_ALG_DSA: - cret = dsa_sign_hash( input, input_size, output, &osize, + cret = dsa_sign_hash( input, isg_size, output, &osize, &ctx->key->key.pk.dsa); if (cret != CRYPT_OK) { err(); return tomerr(cret); } - *output_size = osize; + *osg_size = osize; break; default: err(); - return -EINVAL; + ret = -EINVAL; + goto fail; + } + + ret = sg_copy_from_buffer(osg, osg_cnt, output, *osg_size); + if (ret != *osg_size) { + err(); + ret = -EINVAL; + goto fail; } + ret = 0; +fail: + kfree(tmp); - return 0; + return ret; } int ncr_pk_cipher_verify(const struct ncr_pk_ctx* ctx, - const void* signature, size_t signature_size, + const struct scatterlist* sign_sg, unsigned int sign_sg_cnt, size_t sign_sg_size, const void* hash, size_t hash_size, ncr_error_t* err) { -int cret; +int cret, ret; int stat; +uint8_t* sig; + + sig = kmalloc(sign_sg_size, GFP_KERNEL); + if (sig == NULL) { + err(); + return -ENOMEM; + } + + ret = sg_copy_to_buffer((struct scatterlist*)sign_sg, sign_sg_cnt, sig, sign_sg_size); + if (ret != sign_sg_size) { + err(); + ret = -EINVAL; + goto fail; + } switch(ctx->algorithm->algo) { case NCR_ALG_RSA: - if (ctx->sign_hash == NULL) { - err(); - return -EINVAL; - } - cret = rsa_verify_hash_ex( signature, signature_size, + cret = rsa_verify_hash_ex( sig, sign_sg_size, hash, hash_size, ctx->type, ctx->sign_hash, ctx->salt_len, &stat, &ctx->key->key.pk.rsa); if (cret != CRYPT_OK) { err(); - return tomerr(cret); + ret = tomerr(cret); + goto fail; } if (stat == 1) @@ -509,11 +610,12 @@ int stat; break; case NCR_ALG_DSA: - cret = dsa_verify_hash( signature, signature_size, + cret = dsa_verify_hash( sig, sign_sg_size, hash, hash_size, &stat, &ctx->key->key.pk.dsa); if (cret != CRYPT_OK) { err(); - return tomerr(cret); + ret = tomerr(cret); + goto fail; } if (stat == 1) @@ -524,8 +626,12 @@ int stat; break; default: err(); - return -EINVAL; + ret = -EINVAL; + goto fail; } - - return 0; + + ret = 0; +fail: + kfree(sig); + return ret; } diff --git a/ncr-pk.h b/ncr-pk.h index 873ee83..fdc5e1c 100644 --- a/ncr-pk.h +++ b/ncr-pk.h @@ -34,15 +34,21 @@ int ncr_pk_cipher_init(const struct algo_properties_st *algo, struct ncr_pk_ctx* ctx, struct ncr_key_params_st* params, struct key_item_st *key, const struct algo_properties_st *sign_hash); 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); -int ncr_pk_cipher_sign(const struct ncr_pk_ctx* ctx, const void* input, - size_t input_size, void* output, size_t *output_size); +int ncr_pk_cipher_encrypt(const struct ncr_pk_ctx* ctx, + const struct scatterlist* isg, unsigned int isg_cnt, size_t isg_size, + struct scatterlist *osg, unsigned int osg_cnt, size_t* osg_size); + +int ncr_pk_cipher_decrypt(const struct ncr_pk_ctx* ctx, + const struct scatterlist* isg, unsigned int isg_cnt, size_t isg_size, + struct scatterlist *osg, unsigned int osg_cnt, size_t* osg_size); + +int ncr_pk_cipher_sign(const struct ncr_pk_ctx* ctx, + const struct scatterlist* isg, unsigned int isg_cnt, size_t isg_size, + struct scatterlist *osg, unsigned int osg_cnt, size_t* osg_size); + int ncr_pk_cipher_verify(const struct ncr_pk_ctx* ctx, - const void* signature, size_t signature_size, - const void* hash, size_t hash_size, ncr_error_t*); + const struct scatterlist* sign_sg, unsigned int sign_sg_cnt, size_t sign_sg_size, + const void* hash, size_t hash_size, ncr_error_t* err); #endif diff --git a/ncr-sessions.c b/ncr-sessions.c index b8eabdd..fb9fe4f 100644 --- a/ncr-sessions.c +++ b/ncr-sessions.c @@ -23,6 +23,8 @@ #include "cryptodev.h" #include "ncr.h" #include "ncr_int.h" +#include +#include static void _ncr_session_remove(struct list_sem_st* lst, ncr_session_t desc); @@ -84,6 +86,8 @@ void _ncr_sessions_item_put( struct session_item_st* item) cryptodev_hash_deinit(&item->hash); if (item->key) _ncr_key_item_put(item->key); + kfree(item->sg); + kfree(item->pages); kfree(item); } } @@ -92,13 +96,25 @@ struct session_item_st* ncr_session_new(struct list_sem_st* lst) { struct session_item_st* sess; - sess = kmalloc(sizeof(*sess), GFP_KERNEL); + sess = kzalloc(sizeof(*sess), GFP_KERNEL); if (sess == NULL) { err(); return NULL; } - memset(sess, 0, sizeof(*sess)); + sess->array_size = DEFAULT_PREALLOC_PAGES; + sess->pages = kzalloc(sess->array_size * + sizeof(struct page *), GFP_KERNEL); + sess->sg = kzalloc(sess->array_size * + sizeof(struct scatterlist), GFP_KERNEL); + if (sess->sg == NULL || sess->pages == NULL) { + err(); + kfree(sess->sg); + kfree(sess->pages); + kfree(sess); + return NULL; + } + init_MUTEX(&sess->mem_mutex); atomic_set(&sess->refcnt, 1); @@ -216,6 +232,7 @@ static int _ncr_session_init(struct ncr_lists* lists, struct ncr_session_st* ses ret = -EINVAL; goto fail; } + switch(session->op) { case NCR_OP_ENCRYPT: case NCR_OP_DECRYPT: @@ -395,6 +412,63 @@ int ncr_session_init(struct ncr_lists* lists, void __user* arg) return ret; } +int _ncr_session_encrypt(struct session_item_st* sess, const struct scatterlist* input, unsigned input_cnt, + size_t input_size, void *output, unsigned output_cnt, size_t *output_size) +{ +int ret; + + if (sess->algorithm->is_symmetric) { + /* read key */ + ret = cryptodev_cipher_encrypt(&sess->cipher, input, + output, input_size); + if (ret < 0) { + err(); + return ret; + } + /* FIXME: handle ciphers that do not require that */ + + } else { /* public key */ + ret = ncr_pk_cipher_encrypt(&sess->pk, input, input_cnt, input_size, + output, output_cnt, output_size); + + if (ret < 0) { + err(); + return ret; + } + } + + return 0; +} + +int _ncr_session_decrypt(struct session_item_st* sess, const struct scatterlist* input, + unsigned input_cnt, size_t input_size, + struct scatterlist *output, unsigned output_cnt, size_t *output_size) +{ +int ret; + + if (sess->algorithm->is_symmetric) { + /* read key */ + ret = cryptodev_cipher_decrypt(&sess->cipher, input, + output, input_size); + if (ret < 0) { + err(); + return ret; + } + /* FIXME: handle ciphers that do not require equality */ + + } else { /* public key */ + ret = ncr_pk_cipher_decrypt(&sess->pk, input, input_cnt, input_size, + output, output_cnt, output_size); + + if (ret < 0) { + err(); + return ret; + } + } + + return 0; +} + /* Main update function */ static int _ncr_session_update(struct ncr_lists* lists, struct ncr_session_op_st* op) @@ -403,6 +477,7 @@ static int _ncr_session_update(struct ncr_lists* lists, struct ncr_session_op_st struct session_item_st* sess; struct data_item_st* data = NULL; struct data_item_st* odata = NULL; + size_t new_size; sess = ncr_sessions_item_get( &lists->sessions, op->ses); if (sess == NULL) { @@ -410,17 +485,17 @@ static int _ncr_session_update(struct ncr_lists* lists, struct ncr_session_op_st return -EINVAL; } + /* obtain data item */ + data = ncr_data_item_get( &lists->data, op->data.ndata.input); + if (data == NULL) { + err(); + ret = -EINVAL; + goto fail; + } + switch(sess->op) { case NCR_OP_ENCRYPT: - /* obtain data item */ - data = ncr_data_item_get( &lists->data, op->input); - if (data == NULL) { - err(); - ret = -EINVAL; - goto fail; - } - - odata = ncr_data_item_get( &lists->data, op->output); + odata = ncr_data_item_get( &lists->data, op->data.ndata.output); if (odata == NULL) { err(); ret = -EINVAL; @@ -433,39 +508,16 @@ static int _ncr_session_update(struct ncr_lists* lists, struct ncr_session_op_st goto fail; } - if (sess->algorithm->is_symmetric) { - /* read key */ - ret = _cryptodev_cipher_encrypt(&sess->cipher, data->data, - data->data_size, odata->data, data->data_size); - if (ret < 0) { - err(); - goto fail; - } - /* FIXME: handle ciphers that do not require that */ - odata->data_size = data->data_size; - } else { /* public key */ - size_t new_size = odata->max_data_size; - ret = ncr_pk_cipher_encrypt(&sess->pk, data->data, data->data_size, - odata->data, &new_size); - - odata->data_size = new_size; - - if (ret < 0) { - err(); - goto fail; - } - } - break; - case NCR_OP_DECRYPT: - /* obtain data item */ - data = ncr_data_item_get( &lists->data, op->input); - if (data == NULL) { + odata->data_size = odata->max_data_size; + ret = _ncr_session_encrypt(sess, &data->sg, 1, data->data_size, + &odata->sg, 1, &odata->data_size); + if (ret < 0) { err(); - ret = -EINVAL; goto fail; } - - odata = ncr_data_item_get( &lists->data, op->output); + break; + case NCR_OP_DECRYPT: + odata = ncr_data_item_get( &lists->data, op->data.ndata.output); if (odata == NULL) { err(); ret = -EINVAL; @@ -477,63 +529,26 @@ static int _ncr_session_update(struct ncr_lists* lists, struct ncr_session_op_st ret = -EINVAL; goto fail; } - - /* read key */ - if (sess->algorithm->is_symmetric) { - ret = _cryptodev_cipher_decrypt(&sess->cipher, data->data, data->data_size, odata->data, data->data_size); - if (ret < 0) { - err(); - goto fail; - } - /* FIXME: handle ciphers that do not require that */ - odata->data_size = data->data_size; - } else { /* public key */ - size_t new_size = odata->max_data_size; - ret = ncr_pk_cipher_decrypt(&sess->pk, data->data, data->data_size, - odata->data, &new_size); - - odata->data_size = new_size; - - if (ret < 0) { - err(); - goto fail; - } - } - - break; - - case NCR_OP_SIGN: - /* obtain data item */ - data = ncr_data_item_get( &lists->data, op->input); - if (data == NULL) { - err(); - ret = -EINVAL; - goto fail; - } - ret = _cryptodev_hash_update(&sess->hash, data->data, data->data_size); + new_size = odata->max_data_size; + ret = _ncr_session_decrypt(sess, &data->sg, 1, data->data_size, + &odata->sg, 1, &new_size); if (ret < 0) { err(); goto fail; } + odata->data_size = new_size; + break; + case NCR_OP_SIGN: case NCR_OP_VERIFY: - /* obtain data item */ - data = ncr_data_item_get( &lists->data, op->input); - if (data == NULL) { - err(); - ret = -EINVAL; - goto fail; - } - - ret = _cryptodev_hash_update(&sess->hash, data->data, data->data_size); + ret = cryptodev_hash_update(&sess->hash, &data->sg, data->data_size); if (ret < 0) { err(); goto fail; } break; - default: err(); ret = -EINVAL; @@ -550,16 +565,117 @@ fail: return ret; } -int ncr_session_update(struct ncr_lists* lists, void __user* arg) +/* Only the output buffer is given as scatterlist */ +static int get_userbuf1(struct session_item_st* ses, + struct ncr_session_op_st* op, struct scatterlist **dst_sg, unsigned *dst_cnt) { - struct ncr_session_op_st op; + int pagecount = 0; - if (unlikely(copy_from_user( &op, arg, sizeof(op)))) { - err(); - return -EFAULT; + if (op->data.udata.output == NULL) { + return -EINVAL; } - - return _ncr_session_update(lists, &op); + + pagecount = PAGECOUNT(op->data.udata.output, op->data.udata.output_size); + + + ses->available_pages = pagecount; + + if (pagecount > ses->array_size) { + while (ses->array_size < pagecount) + ses->array_size *= 2; + + dprintk(2, KERN_DEBUG, "%s: reallocating to %d elements\n", + __func__, ses->array_size); + ses->pages = krealloc(ses->pages, ses->array_size * + sizeof(struct page *), GFP_KERNEL); + ses->sg = krealloc(ses->sg, ses->array_size * + sizeof(struct scatterlist), GFP_KERNEL); + + if (ses->sg == NULL || ses->pages == NULL) { + return -ENOMEM; + } + } + + if (__get_userbuf(op->data.udata.output, op->data.udata.output_size, 1, + pagecount, ses->pages, ses->sg)) { + dprintk(1, KERN_ERR, "failed to get user pages for data input\n"); + return -EINVAL; + } + (*dst_sg) = ses->sg; + *dst_cnt = pagecount; + + return 0; +} + +/* make op->data.udata.input and op->data.udata.output available in scatterlists */ +static int get_userbuf2(struct session_item_st* ses, + struct ncr_session_op_st* op, struct scatterlist **src_sg, + unsigned *src_cnt, struct scatterlist **dst_sg, unsigned *dst_cnt) +{ + int src_pagecount, dst_pagecount = 0, pagecount, write_src = 1; + + if (op->data.udata.input == NULL) { + return -EINVAL; + } + + src_pagecount = PAGECOUNT(op->data.udata.input, op->data.udata.input_size); + + if (op->data.udata.input != op->data.udata.output) { /* non-in-situ transformation */ + if (op->data.udata.output != NULL) { + dst_pagecount = PAGECOUNT(op->data.udata.output, op->data.udata.output_size); + write_src = 0; + } else { + dst_pagecount = 0; + } + } + + ses->available_pages = pagecount = src_pagecount + dst_pagecount; + + if (pagecount > ses->array_size) { + while (ses->array_size < pagecount) + ses->array_size *= 2; + + dprintk(2, KERN_DEBUG, "%s: reallocating to %d elements\n", + __func__, ses->array_size); + ses->pages = krealloc(ses->pages, ses->array_size * + sizeof(struct page *), GFP_KERNEL); + ses->sg = krealloc(ses->sg, ses->array_size * + sizeof(struct scatterlist), GFP_KERNEL); + + if (ses->sg == NULL || ses->pages == NULL) { + return -ENOMEM; + } + } + + if (__get_userbuf(op->data.udata.input, op->data.udata.input_size, write_src, + src_pagecount, ses->pages, ses->sg)) { + dprintk(1, KERN_ERR, "failed to get user pages for data input\n"); + return -EINVAL; + } + (*src_sg) = ses->sg; + *src_cnt = src_pagecount; + + if (dst_pagecount) { + *dst_cnt = dst_pagecount; + (*dst_sg) = ses->sg + src_pagecount; + + if (__get_userbuf(op->data.udata.output, op->data.udata.output_size, 1, dst_pagecount, + ses->pages + src_pagecount, *dst_sg)) { + dprintk(1, KERN_ERR, "failed to get user pages for data output\n"); + release_user_pages(ses->pages, src_pagecount); + return -EINVAL; + } + } else { + if (op->data.udata.output != NULL) { + *dst_cnt = src_pagecount; + (*dst_sg) = (*src_sg); + } else { + *dst_cnt = 0; + *dst_sg = NULL; + } + } + + return 0; } static void _ncr_session_remove(struct list_sem_st* lst, ncr_session_t desc) @@ -581,6 +697,15 @@ static void _ncr_session_remove(struct list_sem_st* lst, ncr_session_t desc) return; } +static int try_session_update(struct ncr_lists* lists, struct ncr_session_op_st* op) +{ + if (op->data.ndata.input != NCR_DATA_INVALID) { + return _ncr_session_update(lists, op); + } + + return 0; +} + static int _ncr_session_final(struct ncr_lists* lists, struct ncr_session_op_st* op) { int ret; @@ -595,33 +720,260 @@ static int _ncr_session_final(struct ncr_lists* lists, struct ncr_session_op_st* return -EINVAL; } + ret = try_session_update(lists, op); + if (ret < 0) { + err(); + goto fail; + } + switch(sess->op) { case NCR_OP_ENCRYPT: case NCR_OP_DECRYPT: - /* obtain data item */ - if (op->input != NCR_DATA_INVALID && - op->output != NCR_DATA_INVALID) { - ret = _ncr_session_update(lists, op); - if (ret < 0) + break; + + case NCR_OP_VERIFY: + digest_size = sess->hash.digestsize; + if (digest_size == 0 || sizeof(digest) < digest_size) { + err(); + ret = -EINVAL; + goto fail; + } + ret = cryptodev_hash_final(&sess->hash, digest); + if (ret < 0) { + err(); + goto fail; + } + + odata = ncr_data_item_get( &lists->data, op->data.ndata.output); + if (odata == NULL) { + err(); + ret = -EINVAL; + goto fail; + } + + if (sess->algorithm->is_hmac) { + if (digest_size != odata->data_size || + memcmp(odata->data, digest, digest_size) != 0) { + + op->err = NCR_VERIFICATION_FAILED; + } else { + op->err = NCR_SUCCESS; + } + } else { + /* PK signature */ + ret = ncr_pk_cipher_verify(&sess->pk, &odata->sg, 1, odata->data_size, + digest, digest_size, &op->err); + if (ret < 0) { + err(); goto fail; + } } break; - case NCR_OP_VERIFY: - /* obtain data item */ - if (op->input != NCR_DATA_INVALID) { - ret = _ncr_session_update(lists, op); - if (ret < 0) + case NCR_OP_SIGN: + odata = ncr_data_item_get( &lists->data, op->data.ndata.output); + if (odata == NULL) { + err(); + ret = -EINVAL; + goto fail; + } + + digest_size = sess->hash.digestsize; + if (digest_size == 0 || odata->max_data_size < digest_size) { + err(); + ret = -EINVAL; + goto fail; + } + ret = cryptodev_hash_final(&sess->hash, odata->data); + odata->data_size = digest_size; + + cryptodev_hash_deinit(&sess->hash); + + if (sess->algorithm->is_pk) { + /* PK signature */ + size_t new_size = odata->max_data_size; + ret = ncr_pk_cipher_sign(&sess->pk, &odata->sg, 1, odata->data_size, + &odata->sg, 1, &new_size); + if (ret < 0) { + err(); goto fail; + } + odata->data_size = new_size; + } + break; + default: + err(); + ret = -EINVAL; + goto fail; + } + + ret = 0; + +fail: + if (odata) _ncr_data_item_put(odata); + cryptodev_hash_deinit(&sess->hash); + if (sess->algorithm->is_symmetric) { + cryptodev_cipher_deinit(&sess->cipher); + } else { + ncr_pk_cipher_deinit(&sess->pk); + } + + _ncr_sessions_item_put(sess); + _ncr_session_remove(&lists->sessions, op->ses); + + return ret; +} + +/* Called when userspace buffers are used */ +static int _ncr_session_direct_update(struct ncr_lists* lists, struct ncr_session_op_st* op) +{ + int ret; + struct session_item_st* sess; + struct scatterlist *isg; + struct scatterlist *osg; + unsigned osg_cnt=0, isg_cnt=0; + size_t isg_size, osg_size; + + sess = ncr_sessions_item_get( &lists->sessions, op->ses); + if (sess == NULL) { + err(); + return -EINVAL; + } + + if (down_interruptible(&sess->mem_mutex)) { + err(); + _ncr_sessions_item_put(sess); + return -ERESTARTSYS; + } + + ret = get_userbuf2(sess, op, &isg, &isg_cnt, &osg, &osg_cnt); + if (ret < 0) { + err(); + goto fail; + } + isg_size = op->data.udata.input_size; + osg_size = op->data.udata.output_size; + + switch(sess->op) { + case NCR_OP_ENCRYPT: + if (osg == NULL) { + err(); + ret = -EINVAL; + goto fail; } - odata = ncr_data_item_get( &lists->data, op->output); - if (odata == NULL) { + ret = _ncr_session_encrypt(sess, isg, isg_cnt, isg_size, + osg, osg_cnt, &osg_size); + if (ret < 0) { + err(); + goto fail; + } + op->data.udata.output_size = osg_size; + + break; + case NCR_OP_DECRYPT: + if (osg == NULL) { + err(); + ret = -EINVAL; + goto fail; + } + + if (osg_size < isg_size) { err(); ret = -EINVAL; goto fail; } + ret = _ncr_session_decrypt(sess, isg, isg_cnt, isg_size, + osg, osg_cnt, &osg_size); + if (ret < 0) { + err(); + goto fail; + } + op->data.udata.output_size = osg_size; + + break; + + case NCR_OP_SIGN: + case NCR_OP_VERIFY: + ret = cryptodev_hash_update(&sess->hash, isg, isg_size); + if (ret < 0) { + err(); + goto fail; + } + break; + default: + err(); + ret = -EINVAL; + goto fail; + } + + ret = 0; + +fail: + if (sess->available_pages) { + release_user_pages(sess->pages, sess->available_pages); + sess->available_pages = 0; + } + up(&sess->mem_mutex); + _ncr_sessions_item_put(sess); + + return ret; +} + +static int try_session_direct_update(struct ncr_lists* lists, struct ncr_session_op_st* op) +{ + if (op->data.udata.input != NULL) { + return _ncr_session_direct_update(lists, op); + } + + return 0; +} + +static int _ncr_session_direct_final(struct ncr_lists* lists, struct ncr_session_op_st* op) +{ + int ret; + struct session_item_st* sess; + struct data_item_st* odata = NULL; + int digest_size; + uint8_t digest[NCR_HASH_MAX_OUTPUT_SIZE]; + uint8_t vdigest[NCR_HASH_MAX_OUTPUT_SIZE]; + struct scatterlist *osg; + unsigned osg_cnt=0; + size_t osg_size = 0; + size_t orig_osg_size; + + sess = ncr_sessions_item_get( &lists->sessions, op->ses); + if (sess == NULL) { + err(); + return -EINVAL; + } + + ret = try_session_direct_update(lists, op); + if (ret < 0) { + err(); + _ncr_sessions_item_put(sess); + return ret; + } + + if (down_interruptible(&sess->mem_mutex)) { + err(); + _ncr_sessions_item_put(sess); + return -ERESTARTSYS; + } + + switch(sess->op) { + case NCR_OP_ENCRYPT: + case NCR_OP_DECRYPT: + break; + case NCR_OP_VERIFY: + ret = get_userbuf1(sess, op, &osg, &osg_cnt); + if (ret < 0) { + err(); + goto fail; + } + orig_osg_size = osg_size = op->data.udata.output_size; + digest_size = sess->hash.digestsize; if (digest_size == 0 || sizeof(digest) < digest_size) { err(); @@ -633,11 +985,17 @@ static int _ncr_session_final(struct ncr_lists* lists, struct ncr_session_op_st* err(); goto fail; } - if (sess->algorithm->is_hmac) { + ret = sg_copy_to_buffer(osg, osg_cnt, vdigest, digest_size); + if (ret != digest_size) { + err(); + ret = -EINVAL; + goto fail; + } + if (digest_size != odata->data_size || - memcmp(odata->data, digest, digest_size) != 0) { + memcmp(vdigest, digest, digest_size) != 0) { op->err = NCR_VERIFICATION_FAILED; } else { @@ -645,7 +1003,7 @@ static int _ncr_session_final(struct ncr_lists* lists, struct ncr_session_op_st* } } else { /* PK signature */ - ret = ncr_pk_cipher_verify(&sess->pk, odata->data, odata->data_size, + ret = ncr_pk_cipher_verify(&sess->pk, osg, osg_cnt, osg_size, digest, digest_size, &op->err); if (ret < 0) { err(); @@ -655,40 +1013,46 @@ static int _ncr_session_final(struct ncr_lists* lists, struct ncr_session_op_st* break; case NCR_OP_SIGN: - /* obtain data item */ - if (op->input != NCR_DATA_INVALID) { - ret = _ncr_session_update(lists, op); - if (ret < 0) - goto fail; + ret = get_userbuf1(sess, op, &osg, &osg_cnt); + if (ret < 0) { + err(); + goto fail; } - odata = ncr_data_item_get( &lists->data, op->output); - if (odata == NULL) { + orig_osg_size = osg_size = op->data.udata.output_size; + + digest_size = sess->hash.digestsize; + if (digest_size == 0 || osg_size < digest_size) { err(); ret = -EINVAL; goto fail; } - digest_size = sess->hash.digestsize; - if (digest_size == 0 || odata->max_data_size < digest_size) { + ret = cryptodev_hash_final(&sess->hash, digest); + if (ret < 0) { + err(); + goto fail; + } + + ret = sg_copy_from_buffer(osg, osg_cnt, digest, digest_size); + if (ret != digest_size) { err(); ret = -EINVAL; goto fail; } - ret = cryptodev_hash_final(&sess->hash, odata->data); - odata->data_size = digest_size; + osg_size = digest_size; cryptodev_hash_deinit(&sess->hash); if (sess->algorithm->is_pk) { /* PK signature */ - size_t new_size = odata->max_data_size; - ret = ncr_pk_cipher_sign(&sess->pk, odata->data, odata->data_size, - odata->data, &new_size); + + ret = ncr_pk_cipher_sign(&sess->pk, osg, osg_cnt, osg_size, + osg, osg_cnt, &orig_osg_size); if (ret < 0) { err(); goto fail; } - odata->data_size = new_size; + osg_size = orig_osg_size; } break; default: @@ -697,10 +1061,18 @@ static int _ncr_session_final(struct ncr_lists* lists, struct ncr_session_op_st* goto fail; } + if (osg_size > 0) + op->data.udata.output_size = osg_size; + ret = 0; fail: - if (odata) _ncr_data_item_put(odata); + if (sess->available_pages) { + release_user_pages(sess->pages, sess->available_pages); + sess->available_pages = 0; + } + up(&sess->mem_mutex); + cryptodev_hash_deinit(&sess->hash); if (sess->algorithm->is_symmetric) { cryptodev_cipher_deinit(&sess->cipher); @@ -714,6 +1086,37 @@ fail: return ret; } + +int ncr_session_update(struct ncr_lists* lists, void __user* arg) +{ + struct ncr_session_op_st op; + int ret; + + if (unlikely(copy_from_user( &op, arg, sizeof(op)))) { + err(); + return -EFAULT; + } + + if (op.type == NCR_DIRECT_DATA) + ret = _ncr_session_direct_update(lists, &op); + else if (op.type == NCR_DATA) + ret = _ncr_session_update(lists, &op); + else + ret = -EINVAL; + + if (unlikely(ret)) { + err(); + return ret; + } + + if (unlikely(copy_to_user(arg, &op, sizeof(op)))) { + err(); + return -EFAULT; + } + + return 0; +} + int ncr_session_final(struct ncr_lists* lists, void __user* arg) { struct ncr_session_op_st op; @@ -724,7 +1127,14 @@ int ncr_session_final(struct ncr_lists* lists, void __user* arg) return -EFAULT; } - ret = _ncr_session_final(lists, &op); + if (op.type == NCR_DATA) { + ret = _ncr_session_final(lists, &op); + } else if (op.type == NCR_DIRECT_DATA) { + ret = _ncr_session_direct_final(lists, &op); + } else { + ret = -EINVAL; + } + if (unlikely(ret)) { err(); return ret; @@ -754,7 +1164,13 @@ int ncr_session_once(struct ncr_lists* lists, void __user* arg) } kop.op.ses = kop.init.ses; - ret = _ncr_session_final(lists, &kop.op); + if (kop.op.type == NCR_DIRECT_DATA) + ret = _ncr_session_direct_final(lists, &kop.op); + else if (kop.op.type == NCR_DATA) + ret = _ncr_session_final(lists, &kop.op); + else + ret = -EINVAL; + if (ret < 0) { err(); return ret; @@ -764,4 +1180,3 @@ int ncr_session_once(struct ncr_lists* lists, void __user* arg) return -EFAULT; return 0; } - diff --git a/ncr.c b/ncr.c index 7014a30..4cc7ef3 100644 --- a/ncr.c +++ b/ncr.c @@ -161,6 +161,7 @@ ncr_ioctl(struct ncr_lists* lst, struct file *filp, return ncr_session_final(lst, arg); case NCRIO_SESSION_ONCE: return ncr_session_once(lst, arg); + case NCRIO_MASTER_KEY_SET: return ncr_master_key_set(arg); case NCRIO_KEY_GENERATE_PAIR: diff --git a/ncr.h b/ncr.h index d3f4813..d666628 100644 --- a/ncr.h +++ b/ncr.h @@ -276,14 +276,30 @@ typedef enum { NCR_VERIFICATION_FAILED = -2, } ncr_error_t; +typedef enum { + NCR_DATA, + NCR_DIRECT_DATA, +} ncr_data_type_t; + struct ncr_session_op_st { /* input */ ncr_session_t ses; - ncr_data_t input; - ncr_data_t output; /* when verifying signature this is - * the place of the signature. - */ + union { + struct { + ncr_data_t input; + ncr_data_t output; /* when verifying signature this is + * the place of the signature. + */ + } ndata; + struct { + void* input; + size_t input_size; + void* output; + size_t output_size; + } udata; + } data; + ncr_data_type_t type; /* output of verification */ ncr_error_t err; @@ -296,7 +312,7 @@ struct ncr_session_once_op_st { #define NCRIO_SESSION_INIT _IOR ('c', 300, struct ncr_session_st) #define NCRIO_SESSION_UPDATE _IOWR ('c', 301, struct ncr_session_op_st) -#define NCRIO_SESSION_FINAL _IOR ('c', 302, struct ncr_session_op_st) +#define NCRIO_SESSION_FINAL _IOWR ('c', 302, struct ncr_session_op_st) /* everything in one call */ #define NCRIO_SESSION_ONCE _IOWR ('c', 303, struct ncr_session_once_op_st) diff --git a/ncr_int.h b/ncr_int.h index fadb46e..cbfe58a 100644 --- a/ncr_int.h +++ b/ncr_int.h @@ -41,6 +41,14 @@ struct session_item_st { struct ncr_pk_ctx pk; struct hash_data hash; + struct scatterlist *sg; + struct page **pages; + unsigned array_size; + unsigned available_pages; + struct semaphore mem_mutex; /* down when the + * values above are changed. + */ + struct key_item_st* key; atomic_t refcnt; @@ -53,6 +61,7 @@ struct data_item_st { * I see no reason to allow concurrent writes (reads are * not an issue). */ + struct scatterlist sg; /* points to data */ uint8_t* data; size_t data_size; -- cgit From 174add36f5b6592db7573145f5c59d0207856e07 Mon Sep 17 00:00:00 2001 From: Nikos Mavrogiannopoulos Date: Sat, 24 Jul 2010 18:46:50 +0200 Subject: Added the NCR-DIRECT to speed test. --- examples/speed.c | 93 +++++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 89 insertions(+), 4 deletions(-) diff --git a/examples/speed.c b/examples/speed.c index 1416411..d49faa9 100644 --- a/examples/speed.c +++ b/examples/speed.c @@ -218,6 +218,78 @@ int encrypt_data_ncr(int cfd, int algo, int chunksize) return 0; } +int encrypt_data_ncr_direct(int cfd, int algo, int chunksize) +{ + char *buffer, iv[32]; + static int val = 23; + struct timeval start, end; + double total = 0; + double secs, ddata, dspeed; + char metric[16]; + ncr_key_t key; + struct ncr_key_generate_st kgen; + struct ncr_session_once_op_st nop; + + if (ioctl(cfd, NCRIO_KEY_INIT, &key)) { + fprintf(stderr, "Error: %s:%d\n", __func__, __LINE__); + perror("ioctl(NCRIO_KEY_INIT)"); + return 1; + } + + kgen.desc = key; + kgen.params.algorithm = NCR_ALG_AES_CBC; + kgen.params.keyflags = NCR_KEY_FLAG_EXPORTABLE; + kgen.params.params.secret.bits = 128; /* 16 bytes */ + + if (ioctl(cfd, NCRIO_KEY_GENERATE, &kgen)) { + fprintf(stderr, "Error: %s:%d\n", __func__, __LINE__); + perror("ioctl(NCRIO_KEY_IMPORT)"); + return 1; + } + + + buffer = malloc(chunksize); + memset(iv, 0x23, 32); + + printf("\tEncrypting in chunks of %d bytes: ", chunksize); + fflush(stdout); + + memset(buffer, val++, chunksize); + + must_finish = 0; + alarm(5); + + gettimeofday(&start, NULL); + do { + memset(&nop, 0, sizeof(nop)); + nop.init.algorithm = algo; + nop.init.key = key; + nop.init.op = NCR_OP_ENCRYPT; + nop.op.data.udata.input = buffer; + nop.op.data.udata.input_size = chunksize; + nop.op.data.udata.output = buffer; + nop.op.data.udata.output_size = chunksize; + nop.op.type = NCR_DIRECT_DATA; + + if (ioctl(cfd, NCRIO_SESSION_ONCE, &nop)) { + fprintf(stderr, "Error: %s:%d\n", __func__, __LINE__); + perror("ioctl(NCRIO_SESSION_ONCE)"); + return 1; + } + + total+=chunksize; + } while(must_finish==0); + gettimeofday(&end, NULL); + + secs = udifftimeval(start, end)/ 1000000.0; + + value2human(total, secs, &ddata, &dspeed, metric); + printf ("done. %.2f %s in %.2f secs: ", ddata, metric, secs); + printf ("%.2f %s/sec\n", dspeed, metric); + + return 0; +} + int main(void) { int fd, i, fdc = -1; @@ -250,6 +322,19 @@ int main(void) break; } + fprintf(stderr, "\nTesting NCR with NULL cipher: \n"); + for (i = 256; i <= (64 * 1024); i *= 2) { + if (encrypt_data_ncr(fdc, NCR_ALG_NULL, i)) + break; + } + + fprintf(stderr, "\nTesting NCR-DIRECT with NULL cipher: \n"); + for (i = 256; i <= (64 * 1024); i *= 2) { + if (encrypt_data_ncr_direct(fdc, NCR_ALG_NULL, i)) + break; + } + + fprintf(stderr, "\nTesting AES-128-CBC cipher: \n"); memset(&sess, 0, sizeof(sess)); sess.cipher = CRYPTO_AES_CBC; @@ -266,15 +351,15 @@ int main(void) break; } - fprintf(stderr, "\nTesting NCR with NULL cipher: \n"); + fprintf(stderr, "\nTesting NCR with AES-128-CBC cipher: \n"); for (i = 256; i <= (64 * 1024); i *= 2) { - if (encrypt_data_ncr(fdc, NCR_ALG_NULL, i)) + if (encrypt_data_ncr(fdc, NCR_ALG_AES_CBC, i)) break; } - fprintf(stderr, "\nTesting NCR with AES-128-CBC cipher: \n"); + fprintf(stderr, "\nTesting NCR-DIRECT with AES-128-CBC cipher: \n"); for (i = 256; i <= (64 * 1024); i *= 2) { - if (encrypt_data_ncr(fdc, NCR_ALG_AES_CBC, i)) + if (encrypt_data_ncr_direct(fdc, NCR_ALG_AES_CBC, i)) break; } -- cgit From a9970bd8d7b690f03e770a16d8471924ea3ad126 Mon Sep 17 00:00:00 2001 From: Nikos Mavrogiannopoulos Date: Sun, 25 Jul 2010 20:48:26 +0200 Subject: Separated the direct session functions. --- Makefile | 1 + ncr-sessions-direct.c | 405 ++++++++++++++++++++++++++++++++++++++++++++++++++ ncr-sessions.c | 381 +---------------------------------------------- ncr-sessions.h | 16 ++ 4 files changed, 424 insertions(+), 379 deletions(-) create mode 100644 ncr-sessions-direct.c create mode 100644 ncr-sessions.h diff --git a/Makefile b/Makefile index 04f4984..2babafd 100644 --- a/Makefile +++ b/Makefile @@ -68,6 +68,7 @@ TOMCRYPT_OBJECTS = libtomcrypt/misc/zeromem.o libtomcrypt/misc/crypt/crypt_argch cryptodev-objs = cryptodev_main.o cryptodev_cipher.o ncr.o \ ncr-data.o ncr-key.o ncr-limits.o ncr-sessions.o ncr-pk.o \ + ncr-sessions-direct.o \ ncr-key-wrap.o ncr-key-storage.o $(TOMMATH_OBJECTS) \ $(TOMCRYPT_OBJECTS) diff --git a/ncr-sessions-direct.c b/ncr-sessions-direct.c new file mode 100644 index 0000000..aa4c756 --- /dev/null +++ b/ncr-sessions-direct.c @@ -0,0 +1,405 @@ +/* + * New driver for /dev/crypto device (aka CryptoDev) + + * Copyright (c) 2010 Nikos Mavrogiannopoulos + * + * This file is part of linux cryptodev. + * + * cryptodev is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * cryptodev is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include +#include "cryptodev.h" +#include "ncr.h" +#include "ncr_int.h" +#include +#include +#include + +/* Only the output buffer is given as scatterlist */ +static int get_userbuf1(struct session_item_st* ses, + struct ncr_session_op_st* op, struct scatterlist **dst_sg, unsigned *dst_cnt) +{ + int pagecount = 0; + + if (op->data.udata.output == NULL) { + return -EINVAL; + } + + pagecount = PAGECOUNT(op->data.udata.output, op->data.udata.output_size); + + + ses->available_pages = pagecount; + + if (pagecount > ses->array_size) { + while (ses->array_size < pagecount) + ses->array_size *= 2; + + dprintk(2, KERN_DEBUG, "%s: reallocating to %d elements\n", + __func__, ses->array_size); + ses->pages = krealloc(ses->pages, ses->array_size * + sizeof(struct page *), GFP_KERNEL); + ses->sg = krealloc(ses->sg, ses->array_size * + sizeof(struct scatterlist), GFP_KERNEL); + + if (ses->sg == NULL || ses->pages == NULL) { + return -ENOMEM; + } + } + + if (__get_userbuf(op->data.udata.output, op->data.udata.output_size, 1, + pagecount, ses->pages, ses->sg)) { + dprintk(1, KERN_ERR, "failed to get user pages for data input\n"); + return -EINVAL; + } + (*dst_sg) = ses->sg; + *dst_cnt = pagecount; + + return 0; +} + +/* make op->data.udata.input and op->data.udata.output available in scatterlists */ +static int get_userbuf2(struct session_item_st* ses, + struct ncr_session_op_st* op, struct scatterlist **src_sg, + unsigned *src_cnt, struct scatterlist **dst_sg, unsigned *dst_cnt) +{ + int src_pagecount, dst_pagecount = 0, pagecount, write_src = 1; + + if (op->data.udata.input == NULL) { + return -EINVAL; + } + + src_pagecount = PAGECOUNT(op->data.udata.input, op->data.udata.input_size); + + if (op->data.udata.input != op->data.udata.output) { /* non-in-situ transformation */ + if (op->data.udata.output != NULL) { + dst_pagecount = PAGECOUNT(op->data.udata.output, op->data.udata.output_size); + write_src = 0; + } else { + dst_pagecount = 0; + } + } + + ses->available_pages = pagecount = src_pagecount + dst_pagecount; + + if (pagecount > ses->array_size) { + while (ses->array_size < pagecount) + ses->array_size *= 2; + + dprintk(2, KERN_DEBUG, "%s: reallocating to %d elements\n", + __func__, ses->array_size); + ses->pages = krealloc(ses->pages, ses->array_size * + sizeof(struct page *), GFP_KERNEL); + ses->sg = krealloc(ses->sg, ses->array_size * + sizeof(struct scatterlist), GFP_KERNEL); + + if (ses->sg == NULL || ses->pages == NULL) { + return -ENOMEM; + } + } + + if (__get_userbuf(op->data.udata.input, op->data.udata.input_size, write_src, + src_pagecount, ses->pages, ses->sg)) { + dprintk(1, KERN_ERR, "failed to get user pages for data input\n"); + return -EINVAL; + } + (*src_sg) = ses->sg; + *src_cnt = src_pagecount; + + if (dst_pagecount) { + *dst_cnt = dst_pagecount; + (*dst_sg) = ses->sg + src_pagecount; + + if (__get_userbuf(op->data.udata.output, op->data.udata.output_size, 1, dst_pagecount, + ses->pages + src_pagecount, *dst_sg)) { + dprintk(1, KERN_ERR, "failed to get user pages for data output\n"); + release_user_pages(ses->pages, src_pagecount); + return -EINVAL; + } + } else { + if (op->data.udata.output != NULL) { + *dst_cnt = src_pagecount; + (*dst_sg) = (*src_sg); + } else { + *dst_cnt = 0; + *dst_sg = NULL; + } + } + + return 0; +} + +/* Called when userspace buffers are used */ +int _ncr_session_direct_update(struct ncr_lists* lists, struct ncr_session_op_st* op) +{ + int ret; + struct session_item_st* sess; + struct scatterlist *isg; + struct scatterlist *osg; + unsigned osg_cnt=0, isg_cnt=0; + size_t isg_size, osg_size; + + sess = ncr_sessions_item_get( &lists->sessions, op->ses); + if (sess == NULL) { + err(); + return -EINVAL; + } + + if (down_interruptible(&sess->mem_mutex)) { + err(); + _ncr_sessions_item_put(sess); + return -ERESTARTSYS; + } + + ret = get_userbuf2(sess, op, &isg, &isg_cnt, &osg, &osg_cnt); + if (ret < 0) { + err(); + goto fail; + } + isg_size = op->data.udata.input_size; + osg_size = op->data.udata.output_size; + + switch(sess->op) { + case NCR_OP_ENCRYPT: + if (osg == NULL) { + err(); + ret = -EINVAL; + goto fail; + } + + ret = _ncr_session_encrypt(sess, isg, isg_cnt, isg_size, + osg, osg_cnt, &osg_size); + if (ret < 0) { + err(); + goto fail; + } + op->data.udata.output_size = osg_size; + + break; + case NCR_OP_DECRYPT: + if (osg == NULL) { + err(); + ret = -EINVAL; + goto fail; + } + + if (osg_size < isg_size) { + err(); + ret = -EINVAL; + goto fail; + } + + ret = _ncr_session_decrypt(sess, isg, isg_cnt, isg_size, + osg, osg_cnt, &osg_size); + if (ret < 0) { + err(); + goto fail; + } + op->data.udata.output_size = osg_size; + + break; + + case NCR_OP_SIGN: + case NCR_OP_VERIFY: + ret = cryptodev_hash_update(&sess->hash, isg, isg_size); + if (ret < 0) { + err(); + goto fail; + } + break; + default: + err(); + ret = -EINVAL; + goto fail; + } + + ret = 0; + +fail: + if (sess->available_pages) { + release_user_pages(sess->pages, sess->available_pages); + sess->available_pages = 0; + } + up(&sess->mem_mutex); + _ncr_sessions_item_put(sess); + + return ret; +} + +static int try_session_direct_update(struct ncr_lists* lists, struct ncr_session_op_st* op) +{ + if (op->data.udata.input != NULL) { + return _ncr_session_direct_update(lists, op); + } + + return 0; +} + +int _ncr_session_direct_final(struct ncr_lists* lists, struct ncr_session_op_st* op) +{ + int ret; + struct session_item_st* sess; + struct data_item_st* odata = NULL; + int digest_size; + uint8_t digest[NCR_HASH_MAX_OUTPUT_SIZE]; + uint8_t vdigest[NCR_HASH_MAX_OUTPUT_SIZE]; + struct scatterlist *osg; + unsigned osg_cnt=0; + size_t osg_size = 0; + size_t orig_osg_size; + + sess = ncr_sessions_item_get( &lists->sessions, op->ses); + if (sess == NULL) { + err(); + return -EINVAL; + } + + ret = try_session_direct_update(lists, op); + if (ret < 0) { + err(); + _ncr_sessions_item_put(sess); + return ret; + } + + if (down_interruptible(&sess->mem_mutex)) { + err(); + _ncr_sessions_item_put(sess); + return -ERESTARTSYS; + } + + switch(sess->op) { + case NCR_OP_ENCRYPT: + case NCR_OP_DECRYPT: + break; + case NCR_OP_VERIFY: + ret = get_userbuf1(sess, op, &osg, &osg_cnt); + if (ret < 0) { + err(); + goto fail; + } + orig_osg_size = osg_size = op->data.udata.output_size; + + digest_size = sess->hash.digestsize; + if (digest_size == 0 || sizeof(digest) < digest_size) { + err(); + ret = -EINVAL; + goto fail; + } + ret = cryptodev_hash_final(&sess->hash, digest); + if (ret < 0) { + err(); + goto fail; + } + + if (sess->algorithm->is_hmac) { + ret = sg_copy_to_buffer(osg, osg_cnt, vdigest, digest_size); + if (ret != digest_size) { + err(); + ret = -EINVAL; + goto fail; + } + + if (digest_size != odata->data_size || + memcmp(vdigest, digest, digest_size) != 0) { + + op->err = NCR_VERIFICATION_FAILED; + } else { + op->err = NCR_SUCCESS; + } + } else { + /* PK signature */ + ret = ncr_pk_cipher_verify(&sess->pk, osg, osg_cnt, osg_size, + digest, digest_size, &op->err); + if (ret < 0) { + err(); + goto fail; + } + } + break; + + case NCR_OP_SIGN: + ret = get_userbuf1(sess, op, &osg, &osg_cnt); + if (ret < 0) { + err(); + goto fail; + } + orig_osg_size = osg_size = op->data.udata.output_size; + + digest_size = sess->hash.digestsize; + if (digest_size == 0 || osg_size < digest_size) { + err(); + ret = -EINVAL; + goto fail; + } + + ret = cryptodev_hash_final(&sess->hash, digest); + if (ret < 0) { + err(); + goto fail; + } + + ret = sg_copy_from_buffer(osg, osg_cnt, digest, digest_size); + if (ret != digest_size) { + err(); + ret = -EINVAL; + goto fail; + } + osg_size = digest_size; + + cryptodev_hash_deinit(&sess->hash); + + if (sess->algorithm->is_pk) { + /* PK signature */ + + ret = ncr_pk_cipher_sign(&sess->pk, osg, osg_cnt, osg_size, + osg, osg_cnt, &orig_osg_size); + if (ret < 0) { + err(); + goto fail; + } + osg_size = orig_osg_size; + } + break; + default: + err(); + ret = -EINVAL; + goto fail; + } + + if (osg_size > 0) + op->data.udata.output_size = osg_size; + + ret = 0; + +fail: + if (sess->available_pages) { + release_user_pages(sess->pages, sess->available_pages); + sess->available_pages = 0; + } + up(&sess->mem_mutex); + + cryptodev_hash_deinit(&sess->hash); + if (sess->algorithm->is_symmetric) { + cryptodev_cipher_deinit(&sess->cipher); + } else { + ncr_pk_cipher_deinit(&sess->pk); + } + + _ncr_sessions_item_put(sess); + _ncr_session_remove(&lists->sessions, op->ses); + + return ret; +} + + diff --git a/ncr-sessions.c b/ncr-sessions.c index fb9fe4f..8137276 100644 --- a/ncr-sessions.c +++ b/ncr-sessions.c @@ -25,8 +25,7 @@ #include "ncr_int.h" #include #include - -static void _ncr_session_remove(struct list_sem_st* lst, ncr_session_t desc); +#include void ncr_sessions_list_deinit(struct list_sem_st* lst) { @@ -565,120 +564,7 @@ fail: return ret; } -/* Only the output buffer is given as scatterlist */ -static int get_userbuf1(struct session_item_st* ses, - struct ncr_session_op_st* op, struct scatterlist **dst_sg, unsigned *dst_cnt) -{ - int pagecount = 0; - - if (op->data.udata.output == NULL) { - return -EINVAL; - } - - pagecount = PAGECOUNT(op->data.udata.output, op->data.udata.output_size); - - - ses->available_pages = pagecount; - - if (pagecount > ses->array_size) { - while (ses->array_size < pagecount) - ses->array_size *= 2; - - dprintk(2, KERN_DEBUG, "%s: reallocating to %d elements\n", - __func__, ses->array_size); - ses->pages = krealloc(ses->pages, ses->array_size * - sizeof(struct page *), GFP_KERNEL); - ses->sg = krealloc(ses->sg, ses->array_size * - sizeof(struct scatterlist), GFP_KERNEL); - - if (ses->sg == NULL || ses->pages == NULL) { - return -ENOMEM; - } - } - - if (__get_userbuf(op->data.udata.output, op->data.udata.output_size, 1, - pagecount, ses->pages, ses->sg)) { - dprintk(1, KERN_ERR, "failed to get user pages for data input\n"); - return -EINVAL; - } - (*dst_sg) = ses->sg; - *dst_cnt = pagecount; - - return 0; -} - -/* make op->data.udata.input and op->data.udata.output available in scatterlists */ -static int get_userbuf2(struct session_item_st* ses, - struct ncr_session_op_st* op, struct scatterlist **src_sg, - unsigned *src_cnt, struct scatterlist **dst_sg, unsigned *dst_cnt) -{ - int src_pagecount, dst_pagecount = 0, pagecount, write_src = 1; - - if (op->data.udata.input == NULL) { - return -EINVAL; - } - - src_pagecount = PAGECOUNT(op->data.udata.input, op->data.udata.input_size); - - if (op->data.udata.input != op->data.udata.output) { /* non-in-situ transformation */ - if (op->data.udata.output != NULL) { - dst_pagecount = PAGECOUNT(op->data.udata.output, op->data.udata.output_size); - write_src = 0; - } else { - dst_pagecount = 0; - } - } - - ses->available_pages = pagecount = src_pagecount + dst_pagecount; - - if (pagecount > ses->array_size) { - while (ses->array_size < pagecount) - ses->array_size *= 2; - - dprintk(2, KERN_DEBUG, "%s: reallocating to %d elements\n", - __func__, ses->array_size); - ses->pages = krealloc(ses->pages, ses->array_size * - sizeof(struct page *), GFP_KERNEL); - ses->sg = krealloc(ses->sg, ses->array_size * - sizeof(struct scatterlist), GFP_KERNEL); - - if (ses->sg == NULL || ses->pages == NULL) { - return -ENOMEM; - } - } - - if (__get_userbuf(op->data.udata.input, op->data.udata.input_size, write_src, - src_pagecount, ses->pages, ses->sg)) { - dprintk(1, KERN_ERR, "failed to get user pages for data input\n"); - return -EINVAL; - } - (*src_sg) = ses->sg; - *src_cnt = src_pagecount; - - if (dst_pagecount) { - *dst_cnt = dst_pagecount; - (*dst_sg) = ses->sg + src_pagecount; - - if (__get_userbuf(op->data.udata.output, op->data.udata.output_size, 1, dst_pagecount, - ses->pages + src_pagecount, *dst_sg)) { - dprintk(1, KERN_ERR, "failed to get user pages for data output\n"); - release_user_pages(ses->pages, src_pagecount); - return -EINVAL; - } - } else { - if (op->data.udata.output != NULL) { - *dst_cnt = src_pagecount; - (*dst_sg) = (*src_sg); - } else { - *dst_cnt = 0; - *dst_sg = NULL; - } - } - - return 0; -} - -static void _ncr_session_remove(struct list_sem_st* lst, ncr_session_t desc) +void _ncr_session_remove(struct list_sem_st* lst, ncr_session_t desc) { struct session_item_st * item, *tmp; @@ -824,269 +710,6 @@ fail: return ret; } -/* Called when userspace buffers are used */ -static int _ncr_session_direct_update(struct ncr_lists* lists, struct ncr_session_op_st* op) -{ - int ret; - struct session_item_st* sess; - struct scatterlist *isg; - struct scatterlist *osg; - unsigned osg_cnt=0, isg_cnt=0; - size_t isg_size, osg_size; - - sess = ncr_sessions_item_get( &lists->sessions, op->ses); - if (sess == NULL) { - err(); - return -EINVAL; - } - - if (down_interruptible(&sess->mem_mutex)) { - err(); - _ncr_sessions_item_put(sess); - return -ERESTARTSYS; - } - - ret = get_userbuf2(sess, op, &isg, &isg_cnt, &osg, &osg_cnt); - if (ret < 0) { - err(); - goto fail; - } - isg_size = op->data.udata.input_size; - osg_size = op->data.udata.output_size; - - switch(sess->op) { - case NCR_OP_ENCRYPT: - if (osg == NULL) { - err(); - ret = -EINVAL; - goto fail; - } - - ret = _ncr_session_encrypt(sess, isg, isg_cnt, isg_size, - osg, osg_cnt, &osg_size); - if (ret < 0) { - err(); - goto fail; - } - op->data.udata.output_size = osg_size; - - break; - case NCR_OP_DECRYPT: - if (osg == NULL) { - err(); - ret = -EINVAL; - goto fail; - } - - if (osg_size < isg_size) { - err(); - ret = -EINVAL; - goto fail; - } - - ret = _ncr_session_decrypt(sess, isg, isg_cnt, isg_size, - osg, osg_cnt, &osg_size); - if (ret < 0) { - err(); - goto fail; - } - op->data.udata.output_size = osg_size; - - break; - - case NCR_OP_SIGN: - case NCR_OP_VERIFY: - ret = cryptodev_hash_update(&sess->hash, isg, isg_size); - if (ret < 0) { - err(); - goto fail; - } - break; - default: - err(); - ret = -EINVAL; - goto fail; - } - - ret = 0; - -fail: - if (sess->available_pages) { - release_user_pages(sess->pages, sess->available_pages); - sess->available_pages = 0; - } - up(&sess->mem_mutex); - _ncr_sessions_item_put(sess); - - return ret; -} - -static int try_session_direct_update(struct ncr_lists* lists, struct ncr_session_op_st* op) -{ - if (op->data.udata.input != NULL) { - return _ncr_session_direct_update(lists, op); - } - - return 0; -} - -static int _ncr_session_direct_final(struct ncr_lists* lists, struct ncr_session_op_st* op) -{ - int ret; - struct session_item_st* sess; - struct data_item_st* odata = NULL; - int digest_size; - uint8_t digest[NCR_HASH_MAX_OUTPUT_SIZE]; - uint8_t vdigest[NCR_HASH_MAX_OUTPUT_SIZE]; - struct scatterlist *osg; - unsigned osg_cnt=0; - size_t osg_size = 0; - size_t orig_osg_size; - - sess = ncr_sessions_item_get( &lists->sessions, op->ses); - if (sess == NULL) { - err(); - return -EINVAL; - } - - ret = try_session_direct_update(lists, op); - if (ret < 0) { - err(); - _ncr_sessions_item_put(sess); - return ret; - } - - if (down_interruptible(&sess->mem_mutex)) { - err(); - _ncr_sessions_item_put(sess); - return -ERESTARTSYS; - } - - switch(sess->op) { - case NCR_OP_ENCRYPT: - case NCR_OP_DECRYPT: - break; - case NCR_OP_VERIFY: - ret = get_userbuf1(sess, op, &osg, &osg_cnt); - if (ret < 0) { - err(); - goto fail; - } - orig_osg_size = osg_size = op->data.udata.output_size; - - digest_size = sess->hash.digestsize; - if (digest_size == 0 || sizeof(digest) < digest_size) { - err(); - ret = -EINVAL; - goto fail; - } - ret = cryptodev_hash_final(&sess->hash, digest); - if (ret < 0) { - err(); - goto fail; - } - - if (sess->algorithm->is_hmac) { - ret = sg_copy_to_buffer(osg, osg_cnt, vdigest, digest_size); - if (ret != digest_size) { - err(); - ret = -EINVAL; - goto fail; - } - - if (digest_size != odata->data_size || - memcmp(vdigest, digest, digest_size) != 0) { - - op->err = NCR_VERIFICATION_FAILED; - } else { - op->err = NCR_SUCCESS; - } - } else { - /* PK signature */ - ret = ncr_pk_cipher_verify(&sess->pk, osg, osg_cnt, osg_size, - digest, digest_size, &op->err); - if (ret < 0) { - err(); - goto fail; - } - } - break; - - case NCR_OP_SIGN: - ret = get_userbuf1(sess, op, &osg, &osg_cnt); - if (ret < 0) { - err(); - goto fail; - } - orig_osg_size = osg_size = op->data.udata.output_size; - - digest_size = sess->hash.digestsize; - if (digest_size == 0 || osg_size < digest_size) { - err(); - ret = -EINVAL; - goto fail; - } - - ret = cryptodev_hash_final(&sess->hash, digest); - if (ret < 0) { - err(); - goto fail; - } - - ret = sg_copy_from_buffer(osg, osg_cnt, digest, digest_size); - if (ret != digest_size) { - err(); - ret = -EINVAL; - goto fail; - } - osg_size = digest_size; - - cryptodev_hash_deinit(&sess->hash); - - if (sess->algorithm->is_pk) { - /* PK signature */ - - ret = ncr_pk_cipher_sign(&sess->pk, osg, osg_cnt, osg_size, - osg, osg_cnt, &orig_osg_size); - if (ret < 0) { - err(); - goto fail; - } - osg_size = orig_osg_size; - } - break; - default: - err(); - ret = -EINVAL; - goto fail; - } - - if (osg_size > 0) - op->data.udata.output_size = osg_size; - - ret = 0; - -fail: - if (sess->available_pages) { - release_user_pages(sess->pages, sess->available_pages); - sess->available_pages = 0; - } - up(&sess->mem_mutex); - - cryptodev_hash_deinit(&sess->hash); - if (sess->algorithm->is_symmetric) { - cryptodev_cipher_deinit(&sess->cipher); - } else { - ncr_pk_cipher_deinit(&sess->pk); - } - - _ncr_sessions_item_put(sess); - _ncr_session_remove(&lists->sessions, op->ses); - - return ret; -} - - int ncr_session_update(struct ncr_lists* lists, void __user* arg) { struct ncr_session_op_st op; diff --git a/ncr-sessions.h b/ncr-sessions.h new file mode 100644 index 0000000..d6185aa --- /dev/null +++ b/ncr-sessions.h @@ -0,0 +1,16 @@ +#ifndef NCR_SESSIONS_H +# define NCR_SESSIONS_H + +int _ncr_session_direct_final(struct ncr_lists* lists, struct ncr_session_op_st* op); +int _ncr_session_direct_update(struct ncr_lists* lists, struct ncr_session_op_st* op); + +int _ncr_session_encrypt(struct session_item_st* sess, const struct scatterlist* input, unsigned input_cnt, + size_t input_size, void *output, unsigned output_cnt, size_t *output_size); + +int _ncr_session_decrypt(struct session_item_st* sess, const struct scatterlist* input, + unsigned input_cnt, size_t input_size, + struct scatterlist *output, unsigned output_cnt, size_t *output_size); + +void _ncr_session_remove(struct list_sem_st* lst, ncr_session_t desc); + +#endif -- cgit From 707f55b34377fd9f33ccbdd0b5ab61cb484396f0 Mon Sep 17 00:00:00 2001 From: Nikos Mavrogiannopoulos Date: Sun, 25 Jul 2010 21:34:55 +0200 Subject: Key wrapping operates directly to userspace data. No need to involve the data_t structures. --- examples/ncr.c | 33 ++++++----- ncr-key-wrap.c | 171 ++++++++++++++++++++++++++++++++++++--------------------- ncr.c | 8 +-- ncr.h | 14 +++-- ncr_int.h | 8 +-- 5 files changed, 141 insertions(+), 93 deletions(-) diff --git a/examples/ncr.c b/examples/ncr.c index bd5779c..be3dec9 100644 --- a/examples/ncr.c +++ b/examples/ncr.c @@ -383,7 +383,7 @@ test_ncr_wrap_key(int cfd) struct ncr_data_st kdata; struct ncr_key_wrap_st kwrap; uint8_t data[WRAPPED_KEY_DATA_SIZE]; - + int data_size; fprintf(stdout, "Tests on Keys:\n"); @@ -465,29 +465,23 @@ test_ncr_wrap_key(int cfd) kwrap.algorithm = NCR_WALG_AES_RFC3394; kwrap.keytowrap = key2; kwrap.key = key; - kwrap.data = kdata.desc; + kwrap.io = data; + kwrap.io_size = sizeof(data); if (ioctl(cfd, NCRIO_KEY_WRAP, &kwrap)) { fprintf(stderr, "Error: %s:%d\n", __func__, __LINE__); perror("ioctl(NCRIO_KEY_WRAP)"); return 1; } + + data_size = kwrap.io_size; - kdata.data = data; - kdata.data_size = sizeof(data); - - if (ioctl(cfd, NCRIO_DATA_GET, &kdata)) { - fprintf(stderr, "Error: %s:%d\n", __func__, __LINE__); - perror("ioctl(NCRIO_DATA_GET)"); - return 1; - } - - if (kdata.data_size != 24 || memcmp(kdata.data, + if (kwrap.io_size != 24 || memcmp(data, "\x1F\xA6\x8B\x0A\x81\x12\xB4\x47\xAE\xF3\x4B\xD8\xFB\x5A\x7B\x82\x9D\x3E\x86\x23\x71\xD2\xCF\xE5", 24) != 0) { fprintf(stderr, "Wrapped data do not match.\n"); - fprintf(stderr, "Data[%d]: ",(int) kdata.data_size); - for(i=0;imax_data_size < (n+1)*8) { + if (*output_size < (n+1)*8) { err(); return -EINVAL; } @@ -72,15 +72,15 @@ int i,j; memcpy(R[n-1], &aes_block[8], 8); /* R[n-1] = LSB64(AES(A^{t-1}|R_{1}^{t-1})) */ } - memcpy(output->data, A, sizeof(A)); + memcpy(output, A, sizeof(A)); for (j=0;jdata[(j+1)*8], R[j], 8); - output->data_size = (n+1)*8; + memcpy(&output[(j+1)*8], R[j], 8); + *output_size = (n+1)*8; return 0; } -static int rfc3394_unwrap(uint8_t *wrapped_key, val64_t R[], unsigned int n, val64_t A, struct cipher_data *ctx) +static int rfc3394_unwrap(const uint8_t *wrapped_key, val64_t R[], unsigned int n, val64_t A, struct cipher_data *ctx) { int i, j; uint8_t aes_block[16]; @@ -111,7 +111,7 @@ static int rfc3394_unwrap(uint8_t *wrapped_key, val64_t R[], unsigned int n, val #define RFC5649_IV "\xA6\x59\x59\xA6" static int _wrap_aes_rfc5649(void* kdata, size_t kdata_size, struct key_item_st* kek, - struct data_item_st* output, const void* _iv, size_t iv_size) + void* output, size_t* output_size, const void* _iv, size_t iv_size) { size_t n; int i, ret; @@ -157,7 +157,7 @@ uint8_t iv[8]; for (;idata; - wrapped_key_size = wrapped->data_size; - if (wrapped_key_size % 8 != 0) { err(); ret = -EINVAL; @@ -263,7 +259,7 @@ cleanup: static int wrap_aes_rfc5649(struct key_item_st* tobewrapped, struct key_item_st *kek, - struct data_item_st* output, const void* iv, size_t iv_size) + void* output, size_t* output_size, const void* iv, size_t iv_size) { if (tobewrapped->type != NCR_KEY_TYPE_SECRET) { err(); @@ -271,23 +267,24 @@ static int wrap_aes_rfc5649(struct key_item_st* tobewrapped, struct key_item_st } return _wrap_aes_rfc5649(tobewrapped->key.secret.data, tobewrapped->key.secret.size, - kek, output, iv, iv_size); + kek, output, output_size, iv, iv_size); } static int unwrap_aes_rfc5649(struct key_item_st* output, struct key_item_st *kek, - struct data_item_st* wrapped, const void* iv, size_t iv_size) + void* wrapped, size_t wrapped_size, const void* iv, size_t iv_size) { output->type = NCR_KEY_TYPE_SECRET; - return _unwrap_aes_rfc5649(output->key.secret.data, &output->key.secret.size, kek, wrapped, iv, iv_size); + return _unwrap_aes_rfc5649(output->key.secret.data, &output->key.secret.size, kek, + wrapped, wrapped_size, iv, iv_size); } /* Wraps using the RFC3394 way. */ static int wrap_aes(struct key_item_st* tobewrapped, struct key_item_st *kek, - struct data_item_st* output, const void* iv, size_t iv_size) + void* output, size_t *output_size, const void* iv, size_t iv_size) { size_t key_size, n; uint8_t *raw_key; @@ -330,7 +327,7 @@ struct cipher_data ctx; memcpy(R[i], &raw_key[i*8], 8); } - ret = rfc3394_wrap( R, n, &ctx, output, iv); + ret = rfc3394_wrap( R, n, &ctx, output, output_size, iv); if (ret < 0) { err(); goto cleanup; @@ -359,10 +356,9 @@ void print_val64(char* str, val64_t val) #endif static int unwrap_aes(struct key_item_st* output, struct key_item_st *kek, - struct data_item_st* wrapped, const void* iv, size_t iv_size) + void* wrapped_key, size_t wrapped_key_size, const void* iv, size_t iv_size) { -size_t wrapped_key_size, n; -uint8_t *wrapped_key; +size_t n; val64_t A; int i, ret; struct cipher_data ctx; @@ -380,9 +376,6 @@ struct cipher_data ctx; output->type = NCR_KEY_TYPE_SECRET; - wrapped_key = wrapped->data; - wrapped_key_size = wrapped->data_size; - if (wrapped_key_size % 8 != 0) { err(); ret = -EINVAL; @@ -431,12 +424,13 @@ cleanup: return ret; } -int ncr_key_wrap(struct list_sem_st* key_lst, struct list_sem_st* data_lst, void __user* arg) +int ncr_key_wrap(struct list_sem_st* key_lst, void __user* arg) { struct ncr_key_wrap_st wrap; struct key_item_st* wkey = NULL; struct key_item_st* key = NULL; -struct data_item_st * data = NULL; +void* data = NULL; +size_t data_size; int ret; if (unlikely(copy_from_user(&wrap, arg, sizeof(wrap)))) { @@ -462,31 +456,50 @@ int ret; goto fail; } - data = ncr_data_item_get(data_lst, wrap.data); + data_size = wrap.io_size; + data = kmalloc(data_size, GFP_KERNEL); if (data == NULL) { err(); - ret = -EINVAL; + ret = -ENOMEM; goto fail; } - - data->flags = key_flags_to_data(wkey->flags) | NCR_DATA_FLAG_EXPORTABLE; - + switch(wrap.algorithm) { case NCR_WALG_AES_RFC3394: - ret = wrap_aes(wkey, key, data, wrap.params.params.cipher.iv, wrap.params.params.cipher.iv_size); + ret = wrap_aes(wkey, key, data, &data_size, + wrap.params.params.cipher.iv, wrap.params.params.cipher.iv_size); break; case NCR_WALG_AES_RFC5649: - ret = wrap_aes_rfc5649(wkey, key, data, wrap.params.params.cipher.iv, wrap.params.params.cipher.iv_size); + ret = wrap_aes_rfc5649(wkey, key, data, &data_size, + wrap.params.params.cipher.iv, wrap.params.params.cipher.iv_size); break; default: err(); ret = -EINVAL; } + + if (ret < 0) { + err(); + goto fail; + } + + ret = copy_to_user(wrap.io, data, data_size); + if (unlikely(ret)) { + ret = -EFAULT; + goto fail; + } + + wrap.io_size = data_size; + + ret = copy_to_user(arg, &wrap, sizeof(wrap)); + if (unlikely(ret)) { + ret = -EFAULT; + } fail: if (wkey != NULL) _ncr_key_item_put(wkey); if (key != NULL) _ncr_key_item_put(key); - if (data != NULL) _ncr_data_item_put(data); + kfree(data); return ret; } @@ -494,12 +507,13 @@ fail: /* Unwraps keys. All keys unwrapped are not accessible by * userspace. */ -int ncr_key_unwrap(struct list_sem_st* key_lst, struct list_sem_st* data_lst, void __user* arg) +int ncr_key_unwrap(struct list_sem_st* key_lst, void __user* arg) { struct ncr_key_wrap_st wrap; struct key_item_st* wkey = NULL; struct key_item_st* key = NULL; -struct data_item_st * data = NULL; +void* data = NULL; +size_t data_size; int ret; if (unlikely(copy_from_user(&wrap, arg, sizeof(wrap)))) { @@ -519,40 +533,48 @@ int ret; goto fail; } - data = ncr_data_item_get(data_lst, wrap.data); + data_size = wrap.io_size; + data = kmalloc(data_size, GFP_KERNEL); if (data == NULL) { err(); - ret = -EINVAL; + ret = -ENOMEM; goto fail; } - wkey->flags = data_flags_to_key(data->flags) | NCR_KEY_FLAG_WRAPPABLE; + if (unlikely(copy_from_user(data, wrap.io, data_size))) { + err(); + ret = -EFAULT; + goto fail; + } switch(wrap.algorithm) { case NCR_WALG_AES_RFC3394: - ret = unwrap_aes(wkey, key, data, wrap.params.params.cipher.iv, wrap.params.params.cipher.iv_size); + ret = unwrap_aes(wkey, key, data, data_size, + wrap.params.params.cipher.iv, wrap.params.params.cipher.iv_size); break; case NCR_WALG_AES_RFC5649: - ret = unwrap_aes_rfc5649(wkey, key, data, wrap.params.params.cipher.iv, wrap.params.params.cipher.iv_size); + ret = unwrap_aes_rfc5649(wkey, key, data, data_size, + wrap.params.params.cipher.iv, wrap.params.params.cipher.iv_size); break; default: err(); ret = -EINVAL; } - + fail: if (wkey != NULL) _ncr_key_item_put(wkey); if (key != NULL) _ncr_key_item_put(key); - if (data != NULL) _ncr_data_item_put(data); + if (data != NULL) kfree(data); return ret; } -int ncr_key_storage_wrap(struct list_sem_st* key_lst, struct list_sem_st* data_lst, void __user* arg) +int ncr_key_storage_wrap(struct list_sem_st* key_lst, void __user* arg) { struct ncr_key_storage_wrap_st wrap; struct key_item_st* wkey = NULL; -struct data_item_st * data = NULL; +void* data = NULL; +size_t data_size; uint8_t * sdata = NULL; size_t sdata_size = 0; int ret; @@ -579,26 +601,42 @@ int ret; goto fail; } - data = ncr_data_item_get(data_lst, wrap.data); + data_size = wrap.io_size; + data = kmalloc(data_size, GFP_KERNEL); if (data == NULL) { err(); - ret = -EINVAL; + ret = -ENOMEM; goto fail; } - - data->flags = key_flags_to_data(wkey->flags) | NCR_DATA_FLAG_EXPORTABLE; - + ret = key_to_storage_data(&sdata, &sdata_size, wkey); if (ret < 0) { err(); goto fail; } - ret = _wrap_aes_rfc5649(sdata, sdata_size, &master_key, data, NULL, 0); + ret = _wrap_aes_rfc5649(sdata, sdata_size, &master_key, data, &data_size, NULL, 0); + if (ret < 0) { + err(); + goto fail; + } + + ret = copy_to_user(wrap.io, data, data_size); + if (unlikely(ret)) { + ret = -EFAULT; + goto fail; + } + + wrap.io_size = data_size; + + ret = copy_to_user(arg, &wrap, sizeof(wrap)); + if (unlikely(ret)) { + ret = -EFAULT; + } fail: if (wkey != NULL) _ncr_key_item_put(wkey); - if (data != NULL) _ncr_data_item_put(data); + if (data != NULL) kfree(data); if (sdata != NULL) kfree(sdata); return ret; @@ -607,13 +645,13 @@ fail: /* Unwraps keys. All keys unwrapped are not accessible by * userspace. */ -int ncr_key_storage_unwrap(struct list_sem_st* key_lst, struct list_sem_st* data_lst, void __user* arg) +int ncr_key_storage_unwrap(struct list_sem_st* key_lst, void __user* arg) { struct ncr_key_storage_wrap_st wrap; struct key_item_st* wkey = NULL; -struct data_item_st * data = NULL; +void* data = NULL; uint8_t * sdata = NULL; -size_t sdata_size = 0; +size_t sdata_size = 0, data_size; int ret; if (master_key.type != NCR_KEY_TYPE_SECRET) { @@ -632,14 +670,21 @@ int ret; return ret; } - data = ncr_data_item_get(data_lst, wrap.data); + data_size = wrap.io_size; + data = kmalloc(data_size, GFP_KERNEL); if (data == NULL) { err(); - ret = -EINVAL; + ret = -ENOMEM; + goto fail; + } + + if (unlikely(copy_from_user(data, wrap.io, data_size))) { + err(); + ret = -EFAULT; goto fail; } - sdata_size = data->data_size; + sdata_size = data_size; sdata = kmalloc(sdata_size, GFP_KERNEL); if (sdata == NULL) { err(); @@ -647,9 +692,9 @@ int ret; goto fail; } - wkey->flags = data_flags_to_key(data->flags) | NCR_KEY_FLAG_WRAPPABLE; + wkey->flags = NCR_KEY_FLAG_WRAPPABLE; - ret = _unwrap_aes_rfc5649(sdata, &sdata_size, &master_key, data, NULL, 0); + ret = _unwrap_aes_rfc5649(sdata, &sdata_size, &master_key, data, data_size, NULL, 0); if (ret < 0) { err(); goto fail; @@ -664,7 +709,7 @@ int ret; fail: if (wkey != NULL) _ncr_key_item_put(wkey); - if (data != NULL) _ncr_data_item_put(data); + if (data != NULL) kfree(data); if (sdata != NULL) kfree(sdata); return ret; diff --git a/ncr.c b/ncr.c index 4cc7ef3..928bf3e 100644 --- a/ncr.c +++ b/ncr.c @@ -146,13 +146,13 @@ ncr_ioctl(struct ncr_lists* lst, struct file *filp, case NCRIO_KEY_GET_INFO: return ncr_key_info(&lst->key, arg); case NCRIO_KEY_WRAP: - return ncr_key_wrap(&lst->key, &lst->data, arg); + return ncr_key_wrap(&lst->key, arg); case NCRIO_KEY_UNWRAP: - return ncr_key_unwrap(&lst->key, &lst->data, arg); + return ncr_key_unwrap(&lst->key, arg); case NCRIO_KEY_STORAGE_WRAP: - return ncr_key_storage_wrap(&lst->key, &lst->data, arg); + return ncr_key_storage_wrap(&lst->key, arg); case NCRIO_KEY_STORAGE_UNWRAP: - return ncr_key_storage_unwrap(&lst->key, &lst->data, arg); + return ncr_key_storage_unwrap(&lst->key, arg); case NCRIO_SESSION_INIT: return ncr_session_init(lst, arg); case NCRIO_SESSION_UPDATE: diff --git a/ncr.h b/ncr.h index d666628..37d1f5d 100644 --- a/ncr.h +++ b/ncr.h @@ -212,7 +212,7 @@ struct ncr_key_data_st { #define NCRIO_KEY_DEINIT _IOR ('c', 215, ncr_key_t) -/* FIXME key wrap ioctls +/* Key wrap ioctls */ struct ncr_key_wrap_st { ncr_wrap_algorithm_t algorithm; @@ -220,10 +220,12 @@ struct ncr_key_wrap_st { ncr_key_t key; struct ncr_key_params_st params; - ncr_data_t data; /* encrypted keytowrap */ + + void* io; /* encrypted keytowrap */ + size_t io_size; /* this will be updated by the actual size on wrap */ }; -#define NCRIO_KEY_WRAP _IOR ('c', 250, struct ncr_key_wrap_st) +#define NCRIO_KEY_WRAP _IOWR ('c', 250, struct ncr_key_wrap_st) #define NCRIO_KEY_UNWRAP _IOR ('c', 251, struct ncr_key_wrap_st) /* Internal ops */ @@ -238,10 +240,12 @@ struct ncr_master_key_st { * fields to be able to recover a key */ struct ncr_key_storage_wrap_st { ncr_key_t keytowrap; - ncr_data_t data; /* encrypted keytowrap */ + + void* io; /* encrypted keytowrap */ + size_t io_size; /* this will be updated by the actual size on wrap */ }; -#define NCRIO_KEY_STORAGE_WRAP _IOR ('c', 261, struct ncr_key_storage_wrap_st) +#define NCRIO_KEY_STORAGE_WRAP _IOWR ('c', 261, struct ncr_key_storage_wrap_st) #define NCRIO_KEY_STORAGE_UNWRAP _IOR ('c', 262, struct ncr_key_storage_wrap_st) /* Crypto Operations ioctls diff --git a/ncr_int.h b/ncr_int.h index cbfe58a..6ccbcd2 100644 --- a/ncr_int.h +++ b/ncr_int.h @@ -168,10 +168,10 @@ int ncr_limits_add_and_check(uid_t uid, pid_t pid, limits_type_t type); void ncr_limits_init(void); void ncr_limits_deinit(void); -int ncr_key_wrap(struct list_sem_st* keys, struct list_sem_st* data, void __user* arg); -int ncr_key_unwrap(struct list_sem_st*, struct list_sem_st* data, void __user* arg); -int ncr_key_storage_wrap(struct list_sem_st* key_lst, struct list_sem_st* data_lst, void __user* arg); -int ncr_key_storage_unwrap(struct list_sem_st*, struct list_sem_st* data, void __user* arg); +int ncr_key_wrap(struct list_sem_st* keys, void __user* arg); +int ncr_key_unwrap(struct list_sem_st*, void __user* arg); +int ncr_key_storage_wrap(struct list_sem_st* key_lst, void __user* arg); +int ncr_key_storage_unwrap(struct list_sem_st*, void __user* arg); /* sessions */ struct session_item_st* ncr_session_new(struct list_sem_st* lst); -- cgit From c2dda95767e03af277f4d7dab1334aa10e3ee10f Mon Sep 17 00:00:00 2001 From: Nikos Mavrogiannopoulos Date: Sun, 25 Jul 2010 21:38:28 +0200 Subject: ncr_int.h -> ncr-int.h --- cryptodev_main.c | 2 +- libtomcrypt/hashes/hash_get_oid.c | 2 +- libtomcrypt/hashes/hash_memory.c | 2 +- libtomcrypt/hashes/hash_memory_multi.c | 2 +- libtomcrypt/pk/pkcs1/pkcs_1_mgf1.c | 2 +- libtomcrypt/pk/pkcs1/pkcs_1_oaep_decode.c | 2 +- libtomcrypt/pk/pkcs1/pkcs_1_oaep_encode.c | 2 +- libtomcrypt/pk/pkcs1/pkcs_1_pss_decode.c | 2 +- libtomcrypt/pk/pkcs1/pkcs_1_pss_encode.c | 2 +- libtomcrypt/pk/rsa/rsa_decrypt_key.c | 2 +- libtomcrypt/pk/rsa/rsa_encrypt_key.c | 2 +- libtomcrypt/pk/rsa/rsa_export.c | 2 +- libtomcrypt/pk/rsa/rsa_sign_hash.c | 2 +- libtomcrypt/pk/rsa/rsa_verify_hash.c | 2 +- ncr-data.c | 2 +- ncr-int.h | 221 ++++++++++++++++++++++++++++++ ncr-key-storage.c | 2 +- ncr-key-wrap.c | 2 +- ncr-key.c | 2 +- ncr-limits.c | 2 +- ncr-pk.c | 2 +- ncr-sessions-direct.c | 2 +- ncr-sessions.c | 2 +- ncr.c | 2 +- ncr_int.h | 221 ------------------------------ 25 files changed, 244 insertions(+), 244 deletions(-) create mode 100644 ncr-int.h delete mode 100644 ncr_int.h diff --git a/cryptodev_main.c b/cryptodev_main.c index 89b9a02..3cb96fb 100644 --- a/cryptodev_main.c +++ b/cryptodev_main.c @@ -41,7 +41,7 @@ #include #include #include "cryptodev_int.h" -#include "ncr_int.h" +#include "ncr-int.h" #include #include "version.h" diff --git a/libtomcrypt/hashes/hash_get_oid.c b/libtomcrypt/hashes/hash_get_oid.c index c6469ba..39f4372 100644 --- a/libtomcrypt/hashes/hash_get_oid.c +++ b/libtomcrypt/hashes/hash_get_oid.c @@ -8,7 +8,7 @@ * */ #include "tomcrypt.h" -#include +#include /* Returns the OID of the hash. diff --git a/libtomcrypt/hashes/hash_memory.c b/libtomcrypt/hashes/hash_memory.c index 5ba3bc6..a416de9 100644 --- a/libtomcrypt/hashes/hash_memory.c +++ b/libtomcrypt/hashes/hash_memory.c @@ -9,7 +9,7 @@ * Tom St Denis, tomstdenis@gmail.com, http://libtom.org */ #include "tomcrypt.h" -#include +#include #include /** diff --git a/libtomcrypt/hashes/hash_memory_multi.c b/libtomcrypt/hashes/hash_memory_multi.c index d772492..a914916 100644 --- a/libtomcrypt/hashes/hash_memory_multi.c +++ b/libtomcrypt/hashes/hash_memory_multi.c @@ -10,7 +10,7 @@ */ #include "tomcrypt.h" #include -#include +#include #include /** diff --git a/libtomcrypt/pk/pkcs1/pkcs_1_mgf1.c b/libtomcrypt/pk/pkcs1/pkcs_1_mgf1.c index b09dd11..58052eb 100644 --- a/libtomcrypt/pk/pkcs1/pkcs_1_mgf1.c +++ b/libtomcrypt/pk/pkcs1/pkcs_1_mgf1.c @@ -9,7 +9,7 @@ * Tom St Denis, tomstdenis@gmail.com, http://libtom.org */ #include "tomcrypt.h" -#include +#include /** @file pkcs_1_mgf1.c diff --git a/libtomcrypt/pk/pkcs1/pkcs_1_oaep_decode.c b/libtomcrypt/pk/pkcs1/pkcs_1_oaep_decode.c index 60f76a0..5214a29 100644 --- a/libtomcrypt/pk/pkcs1/pkcs_1_oaep_decode.c +++ b/libtomcrypt/pk/pkcs1/pkcs_1_oaep_decode.c @@ -9,7 +9,7 @@ * Tom St Denis, tomstdenis@gmail.com, http://libtom.org */ #include "tomcrypt.h" -#include +#include /** @file pkcs_1_oaep_decode.c diff --git a/libtomcrypt/pk/pkcs1/pkcs_1_oaep_encode.c b/libtomcrypt/pk/pkcs1/pkcs_1_oaep_encode.c index c56e3b1..ef644f9 100644 --- a/libtomcrypt/pk/pkcs1/pkcs_1_oaep_encode.c +++ b/libtomcrypt/pk/pkcs1/pkcs_1_oaep_encode.c @@ -9,7 +9,7 @@ * Tom St Denis, tomstdenis@gmail.com, http://libtom.org */ #include "tomcrypt.h" -#include +#include /** @file pkcs_1_oaep_encode.c diff --git a/libtomcrypt/pk/pkcs1/pkcs_1_pss_decode.c b/libtomcrypt/pk/pkcs1/pkcs_1_pss_decode.c index 293d84f..4249743 100644 --- a/libtomcrypt/pk/pkcs1/pkcs_1_pss_decode.c +++ b/libtomcrypt/pk/pkcs1/pkcs_1_pss_decode.c @@ -9,7 +9,7 @@ * Tom St Denis, tomstdenis@gmail.com, http://libtom.org */ #include "tomcrypt.h" -#include +#include /** @file pkcs_1_pss_decode.c diff --git a/libtomcrypt/pk/pkcs1/pkcs_1_pss_encode.c b/libtomcrypt/pk/pkcs1/pkcs_1_pss_encode.c index d747b49..956c79e 100644 --- a/libtomcrypt/pk/pkcs1/pkcs_1_pss_encode.c +++ b/libtomcrypt/pk/pkcs1/pkcs_1_pss_encode.c @@ -9,7 +9,7 @@ * Tom St Denis, tomstdenis@gmail.com, http://libtom.org */ #include "tomcrypt.h" -#include +#include /** @file pkcs_1_pss_encode.c diff --git a/libtomcrypt/pk/rsa/rsa_decrypt_key.c b/libtomcrypt/pk/rsa/rsa_decrypt_key.c index 989c935..a8f3ac4 100644 --- a/libtomcrypt/pk/rsa/rsa_decrypt_key.c +++ b/libtomcrypt/pk/rsa/rsa_decrypt_key.c @@ -9,7 +9,7 @@ * Tom St Denis, tomstdenis@gmail.com, http://libtom.org */ #include "tomcrypt.h" -#include "ncr_int.h" +#include "ncr-int.h" /** @file rsa_decrypt_key.c diff --git a/libtomcrypt/pk/rsa/rsa_encrypt_key.c b/libtomcrypt/pk/rsa/rsa_encrypt_key.c index 4ce51a4..8d3f2db 100644 --- a/libtomcrypt/pk/rsa/rsa_encrypt_key.c +++ b/libtomcrypt/pk/rsa/rsa_encrypt_key.c @@ -9,7 +9,7 @@ * Tom St Denis, tomstdenis@gmail.com, http://libtom.org */ #include "tomcrypt.h" -#include "ncr_int.h" +#include "ncr-int.h" /** @file rsa_encrypt_key.c diff --git a/libtomcrypt/pk/rsa/rsa_export.c b/libtomcrypt/pk/rsa/rsa_export.c index 33c222d..905bb6f 100644 --- a/libtomcrypt/pk/rsa/rsa_export.c +++ b/libtomcrypt/pk/rsa/rsa_export.c @@ -9,7 +9,7 @@ * Tom St Denis, tomstdenis@gmail.com, http://libtom.org */ #include "tomcrypt.h" -#include +#include /** @file rsa_export.c Export RSA LTC_PKCS keys, Tom St Denis diff --git a/libtomcrypt/pk/rsa/rsa_sign_hash.c b/libtomcrypt/pk/rsa/rsa_sign_hash.c index 5a32d33..f27789d 100644 --- a/libtomcrypt/pk/rsa/rsa_sign_hash.c +++ b/libtomcrypt/pk/rsa/rsa_sign_hash.c @@ -9,7 +9,7 @@ * Tom St Denis, tomstdenis@gmail.com, http://libtom.org */ #include "tomcrypt.h" -#include "ncr_int.h" +#include "ncr-int.h" /** @file rsa_sign_hash.c diff --git a/libtomcrypt/pk/rsa/rsa_verify_hash.c b/libtomcrypt/pk/rsa/rsa_verify_hash.c index 20f852e..c8a113d 100644 --- a/libtomcrypt/pk/rsa/rsa_verify_hash.c +++ b/libtomcrypt/pk/rsa/rsa_verify_hash.c @@ -9,7 +9,7 @@ * Tom St Denis, tomstdenis@gmail.com, http://libtom.org */ #include "tomcrypt.h" -#include "ncr_int.h" +#include "ncr-int.h" /** @file rsa_verify_hash.c diff --git a/ncr-data.c b/ncr-data.c index 73c62c6..639637f 100644 --- a/ncr-data.c +++ b/ncr-data.c @@ -27,7 +27,7 @@ #include #include #include "ncr.h" -#include "ncr_int.h" +#include "ncr-int.h" /* must be called with data semaphore down */ static void _ncr_data_unlink_item(struct data_item_st *item) diff --git a/ncr-int.h b/ncr-int.h new file mode 100644 index 0000000..6ccbcd2 --- /dev/null +++ b/ncr-int.h @@ -0,0 +1,221 @@ +#ifndef NCR_INT_H +# define NCR_INT_H + +#include "ncr.h" +#include +#include "cryptodev_int.h" +#include + +#define KEY_DATA_MAX_SIZE 3*1024 + +#define err() printk(KERN_DEBUG"ncr: %s: %s: %d\n", __FILE__, __func__, __LINE__) + +struct algo_properties_st { + ncr_algorithm_t algo; + const char *kstr; + unsigned needs_iv:1; + unsigned is_hmac:1; + unsigned can_sign:1; + unsigned can_digest:1; + unsigned can_encrypt:1; + unsigned is_symmetric:1; + unsigned is_pk: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. + */ + ncr_key_type_t key_type; +}; + +struct session_item_st { + struct list_head list; + + const struct algo_properties_st *algorithm; + ncr_crypto_op_t op; + + /* contexts for various options. + * simpler to have them like that than + * in a union. + */ + struct cipher_data cipher; + struct ncr_pk_ctx pk; + struct hash_data hash; + + struct scatterlist *sg; + struct page **pages; + unsigned array_size; + unsigned available_pages; + struct semaphore mem_mutex; /* down when the + * values above are changed. + */ + + struct key_item_st* key; + + atomic_t refcnt; + ncr_session_t desc; +}; + +struct data_item_st { + struct list_head list; + /* This object is not protected from concurrent access. + * I see no reason to allow concurrent writes (reads are + * not an issue). + */ + struct scatterlist sg; /* points to data */ + + uint8_t* data; + size_t data_size; + size_t max_data_size; + unsigned int flags; + atomic_t refcnt; + + /* owner. The one charged with this */ + uid_t uid; + pid_t pid; + + ncr_data_t desc; +}; + +struct key_item_st { + struct list_head list; + /* This object is also not protected from concurrent access. + */ + ncr_key_type_t type; + unsigned int flags; + const struct algo_properties_st *algorithm; /* non-NULL for public/private keys */ + uint8_t key_id[MAX_KEY_ID_SIZE]; + size_t key_id_size; + + union { + struct { + uint8_t data[NCR_CIPHER_MAX_KEY_LEN]; + size_t size; + } secret; + union { + rsa_key rsa; + dsa_key dsa; + } pk; + } key; + + atomic_t refcnt; + atomic_t writer; + + /* owner. The one charged with this */ + uid_t uid; + pid_t pid; + + ncr_key_t desc; +}; + +struct list_sem_st { + struct list_head list; + struct semaphore sem; +}; + +/* all the data associated with the open descriptor + * are here. + */ +struct ncr_lists { + struct list_sem_st data; + struct list_sem_st key; + + /* sessions */ + struct list_sem_st sessions; +}; + +void* ncr_init_lists(void); +void ncr_deinit_lists(struct ncr_lists *lst); + +int ncr_ioctl(struct ncr_lists*, struct file *filp, + unsigned int cmd, unsigned long arg); + +int ncr_data_set(struct list_sem_st*, void __user* arg); +int ncr_data_get(struct list_sem_st*, void __user* arg); +int ncr_data_deinit(struct list_sem_st*, void __user* arg); +int ncr_data_init(struct list_sem_st*, void __user* arg); +void ncr_data_list_deinit(struct list_sem_st*); +struct data_item_st* ncr_data_item_get( struct list_sem_st* lst, ncr_data_t desc); +void _ncr_data_item_put( struct data_item_st* item); + +int ncr_key_init(struct list_sem_st*, void __user* arg); +int ncr_key_deinit(struct list_sem_st*, void __user* arg); +int ncr_key_export(struct list_sem_st* data_lst, + struct list_sem_st* key_lst,void __user* arg); +int ncr_key_import(struct list_sem_st* data_lst, + struct list_sem_st* key_lst,void __user* arg); +void ncr_key_list_deinit(struct list_sem_st* lst); +int ncr_key_generate(struct list_sem_st* data_lst, void __user* arg); +int ncr_key_info(struct list_sem_st*, void __user* arg); + +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); + +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 { + LIMIT_TYPE_KEY, + LIMIT_TYPE_DATA +} limits_type_t; + +void ncr_limits_remove(uid_t uid, pid_t pid, limits_type_t type); +int ncr_limits_add_and_check(uid_t uid, pid_t pid, limits_type_t type); +void ncr_limits_init(void); +void ncr_limits_deinit(void); + +int ncr_key_wrap(struct list_sem_st* keys, void __user* arg); +int ncr_key_unwrap(struct list_sem_st*, void __user* arg); +int ncr_key_storage_wrap(struct list_sem_st* key_lst, void __user* arg); +int ncr_key_storage_unwrap(struct list_sem_st*, void __user* arg); + +/* sessions */ +struct session_item_st* ncr_session_new(struct list_sem_st* lst); +void _ncr_sessions_item_put( struct session_item_st* item); +struct session_item_st* ncr_sessions_item_get( struct list_sem_st* lst, ncr_session_t desc); +void ncr_sessions_list_deinit(struct list_sem_st* lst); + +int ncr_session_init(struct ncr_lists* lists, void __user* arg); +int ncr_session_update(struct ncr_lists* lists, void __user* arg); +int ncr_session_final(struct ncr_lists* lists, void __user* arg); +int ncr_session_once(struct ncr_lists* lists, void __user* arg); + +/* master key */ +extern struct key_item_st master_key; + +void ncr_master_key_reset(void); + +/* storage */ +int key_from_storage_data(struct key_item_st* key, const void* data, size_t data_size); +int key_to_storage_data( uint8_t** data, size_t * data_size, const struct key_item_st *key); + + +/* misc helper macros */ +inline static unsigned int key_flags_to_data(unsigned int key_flags) +{ + unsigned int flags = 0; + + if (key_flags & NCR_KEY_FLAG_EXPORTABLE) + flags |= NCR_DATA_FLAG_EXPORTABLE; + + return flags; +} + +inline static unsigned int data_flags_to_key(unsigned int data_flags) +{ + unsigned int flags = 0; + + if (data_flags & NCR_DATA_FLAG_EXPORTABLE) + flags |= NCR_KEY_FLAG_EXPORTABLE; + + return flags; +} + +const struct algo_properties_st *_ncr_algo_to_properties(ncr_algorithm_t algo); +const struct algo_properties_st *ncr_key_params_get_sign_hash(const struct algo_properties_st *algo, struct ncr_key_params_st * params); + +#endif diff --git a/ncr-key-storage.c b/ncr-key-storage.c index 90d3f74..a1788dc 100644 --- a/ncr-key-storage.c +++ b/ncr-key-storage.c @@ -25,7 +25,7 @@ #include #include #include "ncr.h" -#include "ncr_int.h" +#include "ncr-int.h" #include "cryptodev_int.h" struct packed_key { diff --git a/ncr-key-wrap.c b/ncr-key-wrap.c index 149a8ff..2edcefb 100644 --- a/ncr-key-wrap.c +++ b/ncr-key-wrap.c @@ -27,7 +27,7 @@ #include #include #include "ncr.h" -#include "ncr_int.h" +#include "ncr-int.h" #include "cryptodev_int.h" typedef uint8_t val64_t[8]; diff --git a/ncr-key.c b/ncr-key.c index db5d458..126d1bf 100644 --- a/ncr-key.c +++ b/ncr-key.c @@ -26,7 +26,7 @@ #include #include #include "ncr.h" -#include "ncr_int.h" +#include "ncr-int.h" static void ncr_key_clear(struct key_item_st* item); diff --git a/ncr-limits.c b/ncr-limits.c index 746434c..5340954 100644 --- a/ncr-limits.c +++ b/ncr-limits.c @@ -29,7 +29,7 @@ #include #include #include "ncr.h" -#include "ncr_int.h" +#include "ncr-int.h" /* arbitrary now */ static unsigned int max_per_user[] = { diff --git a/ncr-pk.c b/ncr-pk.c index 8d85a92..cb217d7 100644 --- a/ncr-pk.c +++ b/ncr-pk.c @@ -26,7 +26,7 @@ #include #include #include "ncr.h" -#include "ncr_int.h" +#include "ncr-int.h" #include static struct workqueue_struct * pk_wq = NULL; diff --git a/ncr-sessions-direct.c b/ncr-sessions-direct.c index aa4c756..97d5ad7 100644 --- a/ncr-sessions-direct.c +++ b/ncr-sessions-direct.c @@ -22,7 +22,7 @@ #include #include "cryptodev.h" #include "ncr.h" -#include "ncr_int.h" +#include "ncr-int.h" #include #include #include diff --git a/ncr-sessions.c b/ncr-sessions.c index 8137276..3202e69 100644 --- a/ncr-sessions.c +++ b/ncr-sessions.c @@ -22,7 +22,7 @@ #include #include "cryptodev.h" #include "ncr.h" -#include "ncr_int.h" +#include "ncr-int.h" #include #include #include diff --git a/ncr.c b/ncr.c index 928bf3e..4813eef 100644 --- a/ncr.c +++ b/ncr.c @@ -30,7 +30,7 @@ #include #include #include "ncr.h" -#include "ncr_int.h" +#include "ncr-int.h" #include /* This is the master wrapping key for storage of keys diff --git a/ncr_int.h b/ncr_int.h deleted file mode 100644 index 6ccbcd2..0000000 --- a/ncr_int.h +++ /dev/null @@ -1,221 +0,0 @@ -#ifndef NCR_INT_H -# define NCR_INT_H - -#include "ncr.h" -#include -#include "cryptodev_int.h" -#include - -#define KEY_DATA_MAX_SIZE 3*1024 - -#define err() printk(KERN_DEBUG"ncr: %s: %s: %d\n", __FILE__, __func__, __LINE__) - -struct algo_properties_st { - ncr_algorithm_t algo; - const char *kstr; - unsigned needs_iv:1; - unsigned is_hmac:1; - unsigned can_sign:1; - unsigned can_digest:1; - unsigned can_encrypt:1; - unsigned is_symmetric:1; - unsigned is_pk: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. - */ - ncr_key_type_t key_type; -}; - -struct session_item_st { - struct list_head list; - - const struct algo_properties_st *algorithm; - ncr_crypto_op_t op; - - /* contexts for various options. - * simpler to have them like that than - * in a union. - */ - struct cipher_data cipher; - struct ncr_pk_ctx pk; - struct hash_data hash; - - struct scatterlist *sg; - struct page **pages; - unsigned array_size; - unsigned available_pages; - struct semaphore mem_mutex; /* down when the - * values above are changed. - */ - - struct key_item_st* key; - - atomic_t refcnt; - ncr_session_t desc; -}; - -struct data_item_st { - struct list_head list; - /* This object is not protected from concurrent access. - * I see no reason to allow concurrent writes (reads are - * not an issue). - */ - struct scatterlist sg; /* points to data */ - - uint8_t* data; - size_t data_size; - size_t max_data_size; - unsigned int flags; - atomic_t refcnt; - - /* owner. The one charged with this */ - uid_t uid; - pid_t pid; - - ncr_data_t desc; -}; - -struct key_item_st { - struct list_head list; - /* This object is also not protected from concurrent access. - */ - ncr_key_type_t type; - unsigned int flags; - const struct algo_properties_st *algorithm; /* non-NULL for public/private keys */ - uint8_t key_id[MAX_KEY_ID_SIZE]; - size_t key_id_size; - - union { - struct { - uint8_t data[NCR_CIPHER_MAX_KEY_LEN]; - size_t size; - } secret; - union { - rsa_key rsa; - dsa_key dsa; - } pk; - } key; - - atomic_t refcnt; - atomic_t writer; - - /* owner. The one charged with this */ - uid_t uid; - pid_t pid; - - ncr_key_t desc; -}; - -struct list_sem_st { - struct list_head list; - struct semaphore sem; -}; - -/* all the data associated with the open descriptor - * are here. - */ -struct ncr_lists { - struct list_sem_st data; - struct list_sem_st key; - - /* sessions */ - struct list_sem_st sessions; -}; - -void* ncr_init_lists(void); -void ncr_deinit_lists(struct ncr_lists *lst); - -int ncr_ioctl(struct ncr_lists*, struct file *filp, - unsigned int cmd, unsigned long arg); - -int ncr_data_set(struct list_sem_st*, void __user* arg); -int ncr_data_get(struct list_sem_st*, void __user* arg); -int ncr_data_deinit(struct list_sem_st*, void __user* arg); -int ncr_data_init(struct list_sem_st*, void __user* arg); -void ncr_data_list_deinit(struct list_sem_st*); -struct data_item_st* ncr_data_item_get( struct list_sem_st* lst, ncr_data_t desc); -void _ncr_data_item_put( struct data_item_st* item); - -int ncr_key_init(struct list_sem_st*, void __user* arg); -int ncr_key_deinit(struct list_sem_st*, void __user* arg); -int ncr_key_export(struct list_sem_st* data_lst, - struct list_sem_st* key_lst,void __user* arg); -int ncr_key_import(struct list_sem_st* data_lst, - struct list_sem_st* key_lst,void __user* arg); -void ncr_key_list_deinit(struct list_sem_st* lst); -int ncr_key_generate(struct list_sem_st* data_lst, void __user* arg); -int ncr_key_info(struct list_sem_st*, void __user* arg); - -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); - -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 { - LIMIT_TYPE_KEY, - LIMIT_TYPE_DATA -} limits_type_t; - -void ncr_limits_remove(uid_t uid, pid_t pid, limits_type_t type); -int ncr_limits_add_and_check(uid_t uid, pid_t pid, limits_type_t type); -void ncr_limits_init(void); -void ncr_limits_deinit(void); - -int ncr_key_wrap(struct list_sem_st* keys, void __user* arg); -int ncr_key_unwrap(struct list_sem_st*, void __user* arg); -int ncr_key_storage_wrap(struct list_sem_st* key_lst, void __user* arg); -int ncr_key_storage_unwrap(struct list_sem_st*, void __user* arg); - -/* sessions */ -struct session_item_st* ncr_session_new(struct list_sem_st* lst); -void _ncr_sessions_item_put( struct session_item_st* item); -struct session_item_st* ncr_sessions_item_get( struct list_sem_st* lst, ncr_session_t desc); -void ncr_sessions_list_deinit(struct list_sem_st* lst); - -int ncr_session_init(struct ncr_lists* lists, void __user* arg); -int ncr_session_update(struct ncr_lists* lists, void __user* arg); -int ncr_session_final(struct ncr_lists* lists, void __user* arg); -int ncr_session_once(struct ncr_lists* lists, void __user* arg); - -/* master key */ -extern struct key_item_st master_key; - -void ncr_master_key_reset(void); - -/* storage */ -int key_from_storage_data(struct key_item_st* key, const void* data, size_t data_size); -int key_to_storage_data( uint8_t** data, size_t * data_size, const struct key_item_st *key); - - -/* misc helper macros */ -inline static unsigned int key_flags_to_data(unsigned int key_flags) -{ - unsigned int flags = 0; - - if (key_flags & NCR_KEY_FLAG_EXPORTABLE) - flags |= NCR_DATA_FLAG_EXPORTABLE; - - return flags; -} - -inline static unsigned int data_flags_to_key(unsigned int data_flags) -{ - unsigned int flags = 0; - - if (data_flags & NCR_DATA_FLAG_EXPORTABLE) - flags |= NCR_KEY_FLAG_EXPORTABLE; - - return flags; -} - -const struct algo_properties_st *_ncr_algo_to_properties(ncr_algorithm_t algo); -const struct algo_properties_st *ncr_key_params_get_sign_hash(const struct algo_properties_st *algo, struct ncr_key_params_st * params); - -#endif -- cgit From 6a2560330da7bc05ccb9bc75e70ce745acba7d6c Mon Sep 17 00:00:00 2001 From: Nikos Mavrogiannopoulos Date: Sun, 25 Jul 2010 22:17:22 +0200 Subject: No need for ncr-direct. All session operations are being done on keys or on userspace data. --- .gitignore | 1 - Makefile | 4 +- examples/Makefile | 3 - examples/ncr-direct.c | 443 -------------------------------------------------- examples/ncr.c | 116 ++++--------- examples/pk.c | 185 ++++++--------------- ncr-sessions-direct.c | 375 ------------------------------------------ ncr-sessions.c | 412 +++++++++++++++++++++++++++++++++++----------- ncr.h | 9 +- 9 files changed, 407 insertions(+), 1141 deletions(-) delete mode 100644 examples/ncr-direct.c diff --git a/.gitignore b/.gitignore index e3f0923..4379d92 100644 --- a/.gitignore +++ b/.gitignore @@ -10,7 +10,6 @@ modules.order examples/cipher examples/hmac examples/ncr -examples/ncr-direct examples/pk examples/speed releases diff --git a/Makefile b/Makefile index 2babafd..f85e7bd 100644 --- a/Makefile +++ b/Makefile @@ -67,8 +67,8 @@ TOMCRYPT_OBJECTS = libtomcrypt/misc/zeromem.o libtomcrypt/misc/crypt/crypt_argch libtomcrypt/pk/asn1/der/x509/der_decode_subject_public_key_info.o cryptodev-objs = cryptodev_main.o cryptodev_cipher.o ncr.o \ - ncr-data.o ncr-key.o ncr-limits.o ncr-sessions.o ncr-pk.o \ - ncr-sessions-direct.o \ + ncr-data.o ncr-key.o ncr-limits.o ncr-pk.o \ + ncr-sessions-direct.o ncr-sessions.o \ ncr-key-wrap.o ncr-key-storage.o $(TOMMATH_OBJECTS) \ $(TOMCRYPT_OBJECTS) diff --git a/examples/Makefile b/examples/Makefile index f482649..ff5381d 100644 --- a/examples/Makefile +++ b/examples/Makefile @@ -17,9 +17,6 @@ hmac: hmac.c ncr: ncr.c $(CC) $(CFLAGS) $< -o $@ -ncr-direct: ncr-direct.c - $(CC) $(CFLAGS) $< -o $@ - pk: pk.c $(CC) $(CFLAGS) $< -o $@ -L/usr/local/lib -lgnutls diff --git a/examples/ncr-direct.c b/examples/ncr-direct.c deleted file mode 100644 index 0908e2c..0000000 --- a/examples/ncr-direct.c +++ /dev/null @@ -1,443 +0,0 @@ -/* - * Demo on how to use /dev/crypto device for HMAC. - * - * Placed under public domain. - * - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include "../ncr.h" -#include - -#define DATA_SIZE 4096 -#define KEY_DATA_SIZE 16 - - -struct aes_vectors_st { - const uint8_t* key; - const uint8_t* plaintext; - const uint8_t* ciphertext; -} aes_vectors[] = { - { - .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 = (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 = (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 = (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 = (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", - }, -}; - -/* AES cipher */ -static int -test_ncr_aes(int cfd) -{ - struct ncr_data_init_st dinit; - ncr_key_t key; - struct ncr_key_data_st keydata; - struct ncr_data_st kdata; - ncr_data_t dd, dd2; - uint8_t data[KEY_DATA_SIZE]; - int i, j; - struct ncr_session_once_op_st nop; - - dinit.max_object_size = KEY_DATA_SIZE; - dinit.flags = NCR_DATA_FLAG_EXPORTABLE; - dinit.initial_data = NULL; - dinit.initial_data_size = 0; - - if (ioctl(cfd, NCRIO_DATA_INIT, &dinit)) { - fprintf(stderr, "Error: %s:%d\n", __func__, __LINE__); - perror("ioctl(NCRIO_DATA_INIT)"); - return 1; - } - - dd = dinit.desc; - - if (ioctl(cfd, NCRIO_DATA_INIT, &dinit)) { - fprintf(stderr, "Error: %s:%d\n", __func__, __LINE__); - perror("ioctl(NCRIO_DATA_INIT)"); - return 1; - } - - dd2 = dinit.desc; - - /* convert it to key */ - if (ioctl(cfd, NCRIO_KEY_INIT, &key)) { - perror("ioctl(NCRIO_KEY_INIT)"); - return 1; - } - - keydata.key_id[0] = 'a'; - keydata.key_id[2] = 'b'; - keydata.key_id_size = 2; - keydata.type = NCR_KEY_TYPE_SECRET; - keydata.algorithm = NCR_ALG_AES_CBC; - keydata.flags = NCR_KEY_FLAG_EXPORTABLE; - - - fprintf(stdout, "Tests on AES Encryption\n"); - for (i=0;i #include -/* Only the output buffer is given as scatterlist */ -static int get_userbuf1(struct session_item_st* ses, - struct ncr_session_op_st* op, struct scatterlist **dst_sg, unsigned *dst_cnt) -{ - int pagecount = 0; - - if (op->data.udata.output == NULL) { - return -EINVAL; - } - - pagecount = PAGECOUNT(op->data.udata.output, op->data.udata.output_size); - - - ses->available_pages = pagecount; - - if (pagecount > ses->array_size) { - while (ses->array_size < pagecount) - ses->array_size *= 2; - - dprintk(2, KERN_DEBUG, "%s: reallocating to %d elements\n", - __func__, ses->array_size); - ses->pages = krealloc(ses->pages, ses->array_size * - sizeof(struct page *), GFP_KERNEL); - ses->sg = krealloc(ses->sg, ses->array_size * - sizeof(struct scatterlist), GFP_KERNEL); - - if (ses->sg == NULL || ses->pages == NULL) { - return -ENOMEM; - } - } - - if (__get_userbuf(op->data.udata.output, op->data.udata.output_size, 1, - pagecount, ses->pages, ses->sg)) { - dprintk(1, KERN_ERR, "failed to get user pages for data input\n"); - return -EINVAL; - } - (*dst_sg) = ses->sg; - *dst_cnt = pagecount; - - return 0; -} - -/* make op->data.udata.input and op->data.udata.output available in scatterlists */ -static int get_userbuf2(struct session_item_st* ses, - struct ncr_session_op_st* op, struct scatterlist **src_sg, - unsigned *src_cnt, struct scatterlist **dst_sg, unsigned *dst_cnt) -{ - int src_pagecount, dst_pagecount = 0, pagecount, write_src = 1; - - if (op->data.udata.input == NULL) { - return -EINVAL; - } - - src_pagecount = PAGECOUNT(op->data.udata.input, op->data.udata.input_size); - - if (op->data.udata.input != op->data.udata.output) { /* non-in-situ transformation */ - if (op->data.udata.output != NULL) { - dst_pagecount = PAGECOUNT(op->data.udata.output, op->data.udata.output_size); - write_src = 0; - } else { - dst_pagecount = 0; - } - } - - ses->available_pages = pagecount = src_pagecount + dst_pagecount; - - if (pagecount > ses->array_size) { - while (ses->array_size < pagecount) - ses->array_size *= 2; - - dprintk(2, KERN_DEBUG, "%s: reallocating to %d elements\n", - __func__, ses->array_size); - ses->pages = krealloc(ses->pages, ses->array_size * - sizeof(struct page *), GFP_KERNEL); - ses->sg = krealloc(ses->sg, ses->array_size * - sizeof(struct scatterlist), GFP_KERNEL); - - if (ses->sg == NULL || ses->pages == NULL) { - return -ENOMEM; - } - } - - if (__get_userbuf(op->data.udata.input, op->data.udata.input_size, write_src, - src_pagecount, ses->pages, ses->sg)) { - dprintk(1, KERN_ERR, "failed to get user pages for data input\n"); - return -EINVAL; - } - (*src_sg) = ses->sg; - *src_cnt = src_pagecount; - - if (dst_pagecount) { - *dst_cnt = dst_pagecount; - (*dst_sg) = ses->sg + src_pagecount; - - if (__get_userbuf(op->data.udata.output, op->data.udata.output_size, 1, dst_pagecount, - ses->pages + src_pagecount, *dst_sg)) { - dprintk(1, KERN_ERR, "failed to get user pages for data output\n"); - release_user_pages(ses->pages, src_pagecount); - return -EINVAL; - } - } else { - if (op->data.udata.output != NULL) { - *dst_cnt = src_pagecount; - (*dst_sg) = (*src_sg); - } else { - *dst_cnt = 0; - *dst_sg = NULL; - } - } - - return 0; -} - -/* Called when userspace buffers are used */ -int _ncr_session_direct_update(struct ncr_lists* lists, struct ncr_session_op_st* op) -{ - int ret; - struct session_item_st* sess; - struct scatterlist *isg; - struct scatterlist *osg; - unsigned osg_cnt=0, isg_cnt=0; - size_t isg_size, osg_size; - - sess = ncr_sessions_item_get( &lists->sessions, op->ses); - if (sess == NULL) { - err(); - return -EINVAL; - } - - if (down_interruptible(&sess->mem_mutex)) { - err(); - _ncr_sessions_item_put(sess); - return -ERESTARTSYS; - } - - ret = get_userbuf2(sess, op, &isg, &isg_cnt, &osg, &osg_cnt); - if (ret < 0) { - err(); - goto fail; - } - isg_size = op->data.udata.input_size; - osg_size = op->data.udata.output_size; - - switch(sess->op) { - case NCR_OP_ENCRYPT: - if (osg == NULL) { - err(); - ret = -EINVAL; - goto fail; - } - - ret = _ncr_session_encrypt(sess, isg, isg_cnt, isg_size, - osg, osg_cnt, &osg_size); - if (ret < 0) { - err(); - goto fail; - } - op->data.udata.output_size = osg_size; - - break; - case NCR_OP_DECRYPT: - if (osg == NULL) { - err(); - ret = -EINVAL; - goto fail; - } - - if (osg_size < isg_size) { - err(); - ret = -EINVAL; - goto fail; - } - - ret = _ncr_session_decrypt(sess, isg, isg_cnt, isg_size, - osg, osg_cnt, &osg_size); - if (ret < 0) { - err(); - goto fail; - } - op->data.udata.output_size = osg_size; - - break; - - case NCR_OP_SIGN: - case NCR_OP_VERIFY: - ret = cryptodev_hash_update(&sess->hash, isg, isg_size); - if (ret < 0) { - err(); - goto fail; - } - break; - default: - err(); - ret = -EINVAL; - goto fail; - } - - ret = 0; - -fail: - if (sess->available_pages) { - release_user_pages(sess->pages, sess->available_pages); - sess->available_pages = 0; - } - up(&sess->mem_mutex); - _ncr_sessions_item_put(sess); - - return ret; -} - -static int try_session_direct_update(struct ncr_lists* lists, struct ncr_session_op_st* op) -{ - if (op->data.udata.input != NULL) { - return _ncr_session_direct_update(lists, op); - } - - return 0; -} - -int _ncr_session_direct_final(struct ncr_lists* lists, struct ncr_session_op_st* op) -{ - int ret; - struct session_item_st* sess; - struct data_item_st* odata = NULL; - int digest_size; - uint8_t digest[NCR_HASH_MAX_OUTPUT_SIZE]; - uint8_t vdigest[NCR_HASH_MAX_OUTPUT_SIZE]; - struct scatterlist *osg; - unsigned osg_cnt=0; - size_t osg_size = 0; - size_t orig_osg_size; - - sess = ncr_sessions_item_get( &lists->sessions, op->ses); - if (sess == NULL) { - err(); - return -EINVAL; - } - - ret = try_session_direct_update(lists, op); - if (ret < 0) { - err(); - _ncr_sessions_item_put(sess); - return ret; - } - - if (down_interruptible(&sess->mem_mutex)) { - err(); - _ncr_sessions_item_put(sess); - return -ERESTARTSYS; - } - - switch(sess->op) { - case NCR_OP_ENCRYPT: - case NCR_OP_DECRYPT: - break; - case NCR_OP_VERIFY: - ret = get_userbuf1(sess, op, &osg, &osg_cnt); - if (ret < 0) { - err(); - goto fail; - } - orig_osg_size = osg_size = op->data.udata.output_size; - - digest_size = sess->hash.digestsize; - if (digest_size == 0 || sizeof(digest) < digest_size) { - err(); - ret = -EINVAL; - goto fail; - } - ret = cryptodev_hash_final(&sess->hash, digest); - if (ret < 0) { - err(); - goto fail; - } - - if (sess->algorithm->is_hmac) { - ret = sg_copy_to_buffer(osg, osg_cnt, vdigest, digest_size); - if (ret != digest_size) { - err(); - ret = -EINVAL; - goto fail; - } - - if (digest_size != odata->data_size || - memcmp(vdigest, digest, digest_size) != 0) { - - op->err = NCR_VERIFICATION_FAILED; - } else { - op->err = NCR_SUCCESS; - } - } else { - /* PK signature */ - ret = ncr_pk_cipher_verify(&sess->pk, osg, osg_cnt, osg_size, - digest, digest_size, &op->err); - if (ret < 0) { - err(); - goto fail; - } - } - break; - - case NCR_OP_SIGN: - ret = get_userbuf1(sess, op, &osg, &osg_cnt); - if (ret < 0) { - err(); - goto fail; - } - orig_osg_size = osg_size = op->data.udata.output_size; - - digest_size = sess->hash.digestsize; - if (digest_size == 0 || osg_size < digest_size) { - err(); - ret = -EINVAL; - goto fail; - } - - ret = cryptodev_hash_final(&sess->hash, digest); - if (ret < 0) { - err(); - goto fail; - } - - ret = sg_copy_from_buffer(osg, osg_cnt, digest, digest_size); - if (ret != digest_size) { - err(); - ret = -EINVAL; - goto fail; - } - osg_size = digest_size; - - cryptodev_hash_deinit(&sess->hash); - - if (sess->algorithm->is_pk) { - /* PK signature */ - - ret = ncr_pk_cipher_sign(&sess->pk, osg, osg_cnt, osg_size, - osg, osg_cnt, &orig_osg_size); - if (ret < 0) { - err(); - goto fail; - } - osg_size = orig_osg_size; - } - break; - default: - err(); - ret = -EINVAL; - goto fail; - } - - if (osg_size > 0) - op->data.udata.output_size = osg_size; - - ret = 0; - -fail: - if (sess->available_pages) { - release_user_pages(sess->pages, sess->available_pages); - sess->available_pages = 0; - } - up(&sess->mem_mutex); - - cryptodev_hash_deinit(&sess->hash); - if (sess->algorithm->is_symmetric) { - cryptodev_cipher_deinit(&sess->cipher); - } else { - ncr_pk_cipher_deinit(&sess->pk); - } - - _ncr_sessions_item_put(sess); - _ncr_session_remove(&lists->sessions, op->ses); - - return ret; -} - diff --git a/ncr-sessions.c b/ncr-sessions.c index 3202e69..f0aebc5 100644 --- a/ncr-sessions.c +++ b/ncr-sessions.c @@ -27,6 +27,8 @@ #include #include +static int _ncr_session_direct_update_key(struct ncr_lists* lists, struct ncr_session_op_st* op); + void ncr_sessions_list_deinit(struct list_sem_st* lst) { if(lst) { @@ -468,15 +470,147 @@ int ret; return 0; } -/* Main update function - */ -static int _ncr_session_update(struct ncr_lists* lists, struct ncr_session_op_st* op) +void _ncr_session_remove(struct list_sem_st* lst, ncr_session_t desc) +{ + struct session_item_st * item, *tmp; + + down(&lst->sem); + + list_for_each_entry_safe(item, tmp, &lst->list, list) { + if(item->desc == desc) { + list_del(&item->list); + _ncr_sessions_item_put( item); /* decrement ref count */ + break; + } + } + + up(&lst->sem); + + return; +} + +/* Only the output buffer is given as scatterlist */ +static int get_userbuf1(struct session_item_st* ses, + struct ncr_session_op_st* op, struct scatterlist **dst_sg, unsigned *dst_cnt) +{ + int pagecount = 0; + + if (op->data.udata.output == NULL) { + return -EINVAL; + } + + pagecount = PAGECOUNT(op->data.udata.output, op->data.udata.output_size); + + + ses->available_pages = pagecount; + + if (pagecount > ses->array_size) { + while (ses->array_size < pagecount) + ses->array_size *= 2; + + dprintk(2, KERN_DEBUG, "%s: reallocating to %d elements\n", + __func__, ses->array_size); + ses->pages = krealloc(ses->pages, ses->array_size * + sizeof(struct page *), GFP_KERNEL); + ses->sg = krealloc(ses->sg, ses->array_size * + sizeof(struct scatterlist), GFP_KERNEL); + + if (ses->sg == NULL || ses->pages == NULL) { + return -ENOMEM; + } + } + + if (__get_userbuf(op->data.udata.output, op->data.udata.output_size, 1, + pagecount, ses->pages, ses->sg)) { + dprintk(1, KERN_ERR, "failed to get user pages for data input\n"); + return -EINVAL; + } + (*dst_sg) = ses->sg; + *dst_cnt = pagecount; + + return 0; +} + +/* make op->data.udata.input and op->data.udata.output available in scatterlists */ +static int get_userbuf2(struct session_item_st* ses, + struct ncr_session_op_st* op, struct scatterlist **src_sg, + unsigned *src_cnt, struct scatterlist **dst_sg, unsigned *dst_cnt) +{ + int src_pagecount, dst_pagecount = 0, pagecount, write_src = 1; + + if (op->data.udata.input == NULL) { + return -EINVAL; + } + + src_pagecount = PAGECOUNT(op->data.udata.input, op->data.udata.input_size); + + if (op->data.udata.input != op->data.udata.output) { /* non-in-situ transformation */ + if (op->data.udata.output != NULL) { + dst_pagecount = PAGECOUNT(op->data.udata.output, op->data.udata.output_size); + write_src = 0; + } else { + dst_pagecount = 0; + } + } + + ses->available_pages = pagecount = src_pagecount + dst_pagecount; + + if (pagecount > ses->array_size) { + while (ses->array_size < pagecount) + ses->array_size *= 2; + + dprintk(2, KERN_DEBUG, "%s: reallocating to %d elements\n", + __func__, ses->array_size); + ses->pages = krealloc(ses->pages, ses->array_size * + sizeof(struct page *), GFP_KERNEL); + ses->sg = krealloc(ses->sg, ses->array_size * + sizeof(struct scatterlist), GFP_KERNEL); + + if (ses->sg == NULL || ses->pages == NULL) { + return -ENOMEM; + } + } + + if (__get_userbuf(op->data.udata.input, op->data.udata.input_size, write_src, + src_pagecount, ses->pages, ses->sg)) { + dprintk(1, KERN_ERR, "failed to get user pages for data input\n"); + return -EINVAL; + } + (*src_sg) = ses->sg; + *src_cnt = src_pagecount; + + if (dst_pagecount) { + *dst_cnt = dst_pagecount; + (*dst_sg) = ses->sg + src_pagecount; + + if (__get_userbuf(op->data.udata.output, op->data.udata.output_size, 1, dst_pagecount, + ses->pages + src_pagecount, *dst_sg)) { + dprintk(1, KERN_ERR, "failed to get user pages for data output\n"); + release_user_pages(ses->pages, src_pagecount); + return -EINVAL; + } + } else { + if (op->data.udata.output != NULL) { + *dst_cnt = src_pagecount; + (*dst_sg) = (*src_sg); + } else { + *dst_cnt = 0; + *dst_sg = NULL; + } + } + + return 0; +} + +/* Called when userspace buffers are used */ +int _ncr_session_direct_update(struct ncr_lists* lists, struct ncr_session_op_st* op) { int ret; struct session_item_st* sess; - struct data_item_st* data = NULL; - struct data_item_st* odata = NULL; - size_t new_size; + struct scatterlist *isg; + struct scatterlist *osg; + unsigned osg_cnt=0, isg_cnt=0; + size_t isg_size, osg_size; sess = ncr_sessions_item_get( &lists->sessions, op->ses); if (sess == NULL) { @@ -484,65 +618,63 @@ static int _ncr_session_update(struct ncr_lists* lists, struct ncr_session_op_st return -EINVAL; } - /* obtain data item */ - data = ncr_data_item_get( &lists->data, op->data.ndata.input); - if (data == NULL) { + if (down_interruptible(&sess->mem_mutex)) { + err(); + _ncr_sessions_item_put(sess); + return -ERESTARTSYS; + } + + ret = get_userbuf2(sess, op, &isg, &isg_cnt, &osg, &osg_cnt); + if (ret < 0) { err(); - ret = -EINVAL; goto fail; } + isg_size = op->data.udata.input_size; + osg_size = op->data.udata.output_size; switch(sess->op) { case NCR_OP_ENCRYPT: - odata = ncr_data_item_get( &lists->data, op->data.ndata.output); - if (odata == NULL) { - err(); - ret = -EINVAL; - goto fail; - } - - if (odata->max_data_size < data->data_size) { + if (osg == NULL) { err(); ret = -EINVAL; goto fail; } - odata->data_size = odata->max_data_size; - ret = _ncr_session_encrypt(sess, &data->sg, 1, data->data_size, - &odata->sg, 1, &odata->data_size); + ret = _ncr_session_encrypt(sess, isg, isg_cnt, isg_size, + osg, osg_cnt, &osg_size); if (ret < 0) { err(); goto fail; } + op->data.udata.output_size = osg_size; + break; case NCR_OP_DECRYPT: - odata = ncr_data_item_get( &lists->data, op->data.ndata.output); - if (odata == NULL) { + if (osg == NULL) { err(); ret = -EINVAL; goto fail; } - if (odata->max_data_size < data->data_size) { + if (osg_size < isg_size) { err(); ret = -EINVAL; goto fail; } - new_size = odata->max_data_size; - ret = _ncr_session_decrypt(sess, &data->sg, 1, data->data_size, - &odata->sg, 1, &new_size); + ret = _ncr_session_decrypt(sess, isg, isg_cnt, isg_size, + osg, osg_cnt, &osg_size); if (ret < 0) { err(); goto fail; } - odata->data_size = new_size; + op->data.udata.output_size = osg_size; break; case NCR_OP_SIGN: case NCR_OP_VERIFY: - ret = cryptodev_hash_update(&sess->hash, &data->sg, data->data_size); + ret = cryptodev_hash_update(&sess->hash, isg, isg_size); if (ret < 0) { err(); goto fail; @@ -557,48 +689,41 @@ static int _ncr_session_update(struct ncr_lists* lists, struct ncr_session_op_st ret = 0; fail: - if (odata) _ncr_data_item_put(odata); - if (data) _ncr_data_item_put(data); + if (sess->available_pages) { + release_user_pages(sess->pages, sess->available_pages); + sess->available_pages = 0; + } + up(&sess->mem_mutex); _ncr_sessions_item_put(sess); return ret; } -void _ncr_session_remove(struct list_sem_st* lst, ncr_session_t desc) -{ - struct session_item_st * item, *tmp; - - down(&lst->sem); - - list_for_each_entry_safe(item, tmp, &lst->list, list) { - if(item->desc == desc) { - list_del(&item->list); - _ncr_sessions_item_put( item); /* decrement ref count */ - break; - } - } - - up(&lst->sem); - - return; -} - -static int try_session_update(struct ncr_lists* lists, struct ncr_session_op_st* op) +static int try_session_direct_update(struct ncr_lists* lists, struct ncr_session_op_st* op) { - if (op->data.ndata.input != NCR_DATA_INVALID) { - return _ncr_session_update(lists, op); + if (op->type == NCR_KEY_DATA) { + if (op->data.kdata.input != NCR_KEY_INVALID) + return _ncr_session_direct_update_key(lists, op); + } else if (op->type == NCR_DIRECT_DATA) { + if (op->data.udata.input != NULL) + return _ncr_session_direct_update(lists, op); } return 0; } -static int _ncr_session_final(struct ncr_lists* lists, struct ncr_session_op_st* op) +int _ncr_session_direct_final(struct ncr_lists* lists, struct ncr_session_op_st* op) { int ret; struct session_item_st* sess; struct data_item_st* odata = NULL; int digest_size; uint8_t digest[NCR_HASH_MAX_OUTPUT_SIZE]; + uint8_t vdigest[NCR_HASH_MAX_OUTPUT_SIZE]; + struct scatterlist *osg; + unsigned osg_cnt=0; + size_t osg_size = 0; + size_t orig_osg_size; sess = ncr_sessions_item_get( &lists->sessions, op->ses); if (sess == NULL) { @@ -606,18 +731,31 @@ static int _ncr_session_final(struct ncr_lists* lists, struct ncr_session_op_st* return -EINVAL; } - ret = try_session_update(lists, op); + ret = try_session_direct_update(lists, op); if (ret < 0) { err(); - goto fail; + _ncr_sessions_item_put(sess); + return ret; + } + + if (down_interruptible(&sess->mem_mutex)) { + err(); + _ncr_sessions_item_put(sess); + return -ERESTARTSYS; } switch(sess->op) { case NCR_OP_ENCRYPT: case NCR_OP_DECRYPT: break; - case NCR_OP_VERIFY: + ret = get_userbuf1(sess, op, &osg, &osg_cnt); + if (ret < 0) { + err(); + goto fail; + } + orig_osg_size = osg_size = op->data.udata.output_size; + digest_size = sess->hash.digestsize; if (digest_size == 0 || sizeof(digest) < digest_size) { err(); @@ -630,16 +768,16 @@ static int _ncr_session_final(struct ncr_lists* lists, struct ncr_session_op_st* goto fail; } - odata = ncr_data_item_get( &lists->data, op->data.ndata.output); - if (odata == NULL) { - err(); - ret = -EINVAL; - goto fail; - } - if (sess->algorithm->is_hmac) { + ret = sg_copy_to_buffer(osg, osg_cnt, vdigest, digest_size); + if (ret != digest_size) { + err(); + ret = -EINVAL; + goto fail; + } + if (digest_size != odata->data_size || - memcmp(odata->data, digest, digest_size) != 0) { + memcmp(vdigest, digest, digest_size) != 0) { op->err = NCR_VERIFICATION_FAILED; } else { @@ -647,7 +785,7 @@ static int _ncr_session_final(struct ncr_lists* lists, struct ncr_session_op_st* } } else { /* PK signature */ - ret = ncr_pk_cipher_verify(&sess->pk, &odata->sg, 1, odata->data_size, + ret = ncr_pk_cipher_verify(&sess->pk, osg, osg_cnt, osg_size, digest, digest_size, &op->err); if (ret < 0) { err(); @@ -657,34 +795,46 @@ static int _ncr_session_final(struct ncr_lists* lists, struct ncr_session_op_st* break; case NCR_OP_SIGN: - odata = ncr_data_item_get( &lists->data, op->data.ndata.output); - if (odata == NULL) { + ret = get_userbuf1(sess, op, &osg, &osg_cnt); + if (ret < 0) { err(); - ret = -EINVAL; goto fail; } + orig_osg_size = osg_size = op->data.udata.output_size; digest_size = sess->hash.digestsize; - if (digest_size == 0 || odata->max_data_size < digest_size) { + if (digest_size == 0 || osg_size < digest_size) { + err(); + ret = -EINVAL; + goto fail; + } + + ret = cryptodev_hash_final(&sess->hash, digest); + if (ret < 0) { + err(); + goto fail; + } + + ret = sg_copy_from_buffer(osg, osg_cnt, digest, digest_size); + if (ret != digest_size) { err(); ret = -EINVAL; goto fail; } - ret = cryptodev_hash_final(&sess->hash, odata->data); - odata->data_size = digest_size; + osg_size = digest_size; cryptodev_hash_deinit(&sess->hash); if (sess->algorithm->is_pk) { /* PK signature */ - size_t new_size = odata->max_data_size; - ret = ncr_pk_cipher_sign(&sess->pk, &odata->sg, 1, odata->data_size, - &odata->sg, 1, &new_size); + + ret = ncr_pk_cipher_sign(&sess->pk, osg, osg_cnt, osg_size, + osg, osg_cnt, &orig_osg_size); if (ret < 0) { err(); goto fail; } - odata->data_size = new_size; + osg_size = orig_osg_size; } break; default: @@ -693,10 +843,18 @@ static int _ncr_session_final(struct ncr_lists* lists, struct ncr_session_op_st* goto fail; } + if (osg_size > 0) + op->data.udata.output_size = osg_size; + ret = 0; fail: - if (odata) _ncr_data_item_put(odata); + if (sess->available_pages) { + release_user_pages(sess->pages, sess->available_pages); + sess->available_pages = 0; + } + up(&sess->mem_mutex); + cryptodev_hash_deinit(&sess->hash); if (sess->algorithm->is_symmetric) { cryptodev_cipher_deinit(&sess->cipher); @@ -710,6 +868,85 @@ fail: return ret; } +/* Direct with key: Allows to hash a key */ +/* Called when userspace buffers are used */ +static int _ncr_session_direct_update_key(struct ncr_lists* lists, struct ncr_session_op_st* op) +{ + int ret; + struct session_item_st* sess; + struct key_item_st* key = NULL; + struct scatterlist *osg; + unsigned osg_cnt=0; + size_t osg_size; + + sess = ncr_sessions_item_get( &lists->sessions, op->ses); + if (sess == NULL) { + err(); + return -EINVAL; + } + + /* read key */ + ret = ncr_key_item_get_read( &key, &lists->key, op->data.kdata.input); + if (ret < 0) { + err(); + goto fail; + } + + if (key->type != NCR_KEY_TYPE_SECRET) { + err(); + ret = -EINVAL; + goto fail; + } + + if (down_interruptible(&sess->mem_mutex)) { + err(); + _ncr_sessions_item_put(sess); + return -ERESTARTSYS; + } + + ret = get_userbuf1(sess, op, &osg, &osg_cnt); + if (ret < 0) { + err(); + goto fail; + } + + osg_size = op->data.kdata.output_size; + + switch(sess->op) { + case NCR_OP_ENCRYPT: + case NCR_OP_DECRYPT: + err(); + ret = -EINVAL; + goto fail; + case NCR_OP_SIGN: + case NCR_OP_VERIFY: + ret = _cryptodev_hash_update(&sess->hash, + key->key.secret.data, key->key.secret.size); + if (ret < 0) { + err(); + goto fail; + } + break; + default: + err(); + ret = -EINVAL; + goto fail; + } + + ret = 0; + +fail: + if (sess->available_pages) { + release_user_pages(sess->pages, sess->available_pages); + sess->available_pages = 0; + } + up(&sess->mem_mutex); + if (key) _ncr_key_item_put(key); + _ncr_sessions_item_put(sess); + + return ret; +} + int ncr_session_update(struct ncr_lists* lists, void __user* arg) { struct ncr_session_op_st op; @@ -722,8 +959,8 @@ int ncr_session_update(struct ncr_lists* lists, void __user* arg) if (op.type == NCR_DIRECT_DATA) ret = _ncr_session_direct_update(lists, &op); - else if (op.type == NCR_DATA) - ret = _ncr_session_update(lists, &op); + else if (op.type == NCR_KEY_DATA) + ret = _ncr_session_direct_update_key(lists, &op); else ret = -EINVAL; @@ -750,14 +987,7 @@ int ncr_session_final(struct ncr_lists* lists, void __user* arg) return -EFAULT; } - if (op.type == NCR_DATA) { - ret = _ncr_session_final(lists, &op); - } else if (op.type == NCR_DIRECT_DATA) { - ret = _ncr_session_direct_final(lists, &op); - } else { - ret = -EINVAL; - } - + ret = _ncr_session_direct_final(lists, &op); if (unlikely(ret)) { err(); return ret; @@ -787,13 +1017,7 @@ int ncr_session_once(struct ncr_lists* lists, void __user* arg) } kop.op.ses = kop.init.ses; - if (kop.op.type == NCR_DIRECT_DATA) - ret = _ncr_session_direct_final(lists, &kop.op); - else if (kop.op.type == NCR_DATA) - ret = _ncr_session_final(lists, &kop.op); - else - ret = -EINVAL; - + ret = _ncr_session_direct_final(lists, &kop.op); if (ret < 0) { err(); return ret; diff --git a/ncr.h b/ncr.h index 37d1f5d..e992c7b 100644 --- a/ncr.h +++ b/ncr.h @@ -281,7 +281,7 @@ typedef enum { } ncr_error_t; typedef enum { - NCR_DATA, + NCR_KEY_DATA, NCR_DIRECT_DATA, } ncr_data_type_t; @@ -291,11 +291,12 @@ struct ncr_session_op_st { union { struct { - ncr_data_t input; - ncr_data_t output; /* when verifying signature this is + ncr_key_t input; + void* output; /* when verifying signature this is * the place of the signature. */ - } ndata; + size_t output_size; + } kdata; struct { void* input; size_t input_size; -- cgit From f84ea240b18ce93ae26030ce28d19af4bc9962a1 Mon Sep 17 00:00:00 2001 From: Nikos Mavrogiannopoulos Date: Mon, 26 Jul 2010 00:19:45 +0200 Subject: removed the data type. --- Makefile | 2 +- examples/Makefile | 5 +- examples/ncr.c | 399 ++++++------------------------------------------------ examples/pk.c | 148 +++++++------------- examples/speed.c | 113 ---------------- ncr-data.c | 303 ----------------------------------------- ncr-int.h | 55 +------- ncr-key.c | 100 ++++++++------ ncr-limits.c | 2 - ncr-pk.c | 14 +- ncr-sessions.c | 14 +- ncr.c | 14 +- ncr.h | 33 +---- 13 files changed, 175 insertions(+), 1027 deletions(-) delete mode 100644 ncr-data.c diff --git a/Makefile b/Makefile index f85e7bd..3b7ebf6 100644 --- a/Makefile +++ b/Makefile @@ -67,7 +67,7 @@ TOMCRYPT_OBJECTS = libtomcrypt/misc/zeromem.o libtomcrypt/misc/crypt/crypt_argch libtomcrypt/pk/asn1/der/x509/der_decode_subject_public_key_info.o cryptodev-objs = cryptodev_main.o cryptodev_cipher.o ncr.o \ - ncr-data.o ncr-key.o ncr-limits.o ncr-pk.o \ + ncr-key.o ncr-limits.o ncr-pk.o \ ncr-sessions-direct.o ncr-sessions.o \ ncr-key-wrap.o ncr-key-storage.o $(TOMMATH_OBJECTS) \ $(TOMCRYPT_OBJECTS) diff --git a/examples/Makefile b/examples/Makefile index ff5381d..100cc49 100644 --- a/examples/Makefile +++ b/examples/Makefile @@ -1,7 +1,7 @@ CC = gcc CFLAGS = -Wall -g -O2 -progs := cipher hmac ncr pk speed ncr-direct +progs := cipher hmac ncr pk speed all: $(progs) @@ -22,11 +22,10 @@ pk: pk.c check: $(progs) ./ncr - ./ncr-direct ./pk ./cipher ./hmac ./speed clean: - rm -f *.o *~ hmac cipher ncr pk speed ncr-direct + rm -f *.o *~ hmac cipher ncr pk speed \ No newline at end of file diff --git a/examples/ncr.c b/examples/ncr.c index f2c4b72..4ff59fd 100644 --- a/examples/ncr.c +++ b/examples/ncr.c @@ -32,11 +32,9 @@ int i; static int test_ncr_key(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; uint8_t data[KEY_DATA_SIZE]; uint8_t data_bak[KEY_DATA_SIZE]; @@ -51,17 +49,6 @@ test_ncr_key(int cfd) randomize_data(data, sizeof(data)); memcpy(data_bak, data, sizeof(data)); - dinit.max_object_size = KEY_DATA_SIZE; - dinit.flags = NCR_DATA_FLAG_EXPORTABLE; - dinit.initial_data = data; - dinit.initial_data_size = sizeof(data); - - if (ioctl(cfd, NCRIO_DATA_INIT, &dinit)) { - fprintf(stderr, "Error: %s:%d\n", __func__, __LINE__); - perror("ioctl(NCRIO_DATA_INIT)"); - return 1; - } - /* convert it to key */ if (ioctl(cfd, NCRIO_KEY_INIT, &key)) { perror("ioctl(NCRIO_KEY_INIT)"); @@ -76,7 +63,8 @@ test_ncr_key(int cfd) keydata.flags = NCR_KEY_FLAG_EXPORTABLE; keydata.key = key; - keydata.data = dinit.desc; + keydata.idata = data; + keydata.idata_size = sizeof(data); if (ioctl(cfd, NCRIO_KEY_IMPORT, &keydata)) { fprintf(stderr, "Error: %s:%d\n", __func__, __LINE__); @@ -86,43 +74,21 @@ test_ncr_key(int cfd) /* now try to read it */ fprintf(stdout, "\tKey export...\n"); - if (ioctl(cfd, NCRIO_DATA_DEINIT, &dinit.desc)) { - fprintf(stderr, "Error: %s:%d\n", __func__, __LINE__); - perror("ioctl(NCRIO_DATA_DEINIT)"); - return 1; - } - - dinit.max_object_size = DATA_SIZE; - dinit.flags = NCR_DATA_FLAG_EXPORTABLE; - dinit.initial_data = NULL; - dinit.initial_data_size = 0; - - if (ioctl(cfd, NCRIO_DATA_INIT, &dinit)) { - fprintf(stderr, "Error: %s:%d\n", __func__, __LINE__); - perror("ioctl(NCRIO_DATA_INIT)"); - return 1; - } memset(&keydata, 0, sizeof(keydata)); keydata.key = key; - keydata.data = dinit.desc; + keydata.idata = data; + keydata.idata_size = sizeof(data); if (ioctl(cfd, NCRIO_KEY_EXPORT, &keydata)) { fprintf(stderr, "Error: %s:%d\n", __func__, __LINE__); perror("ioctl(NCRIO_KEY_IMPORT)"); return 1; } - - /* now read data */ - memset(&kdata, 0, sizeof(kdata)); - - kdata.desc = dinit.desc; - kdata.data = data; - kdata.data_size = sizeof(data); - - if (ioctl(cfd, NCRIO_DATA_GET, &kdata)) { + + if (keydata.idata_size != sizeof(data)) { fprintf(stderr, "Error: %s:%d\n", __func__, __LINE__); - perror("ioctl(NCRIO_DATA_GET)"); + fprintf(stderr, "data returned but differ!\n"); return 1; } @@ -162,9 +128,12 @@ test_ncr_key(int cfd) return 1; } + memset(data, 0, sizeof(data)); + memset(&keydata, 0, sizeof(keydata)); keydata.key = key; - keydata.data = dinit.desc; + keydata.idata = data; + keydata.idata_size = sizeof(data); if (ioctl(cfd, NCRIO_KEY_EXPORT, &keydata)) { fprintf(stderr, "Error: %s:%d\n", __func__, __LINE__); @@ -172,27 +141,16 @@ test_ncr_key(int cfd) return 1; } - /* now read data */ - memset(data, 0, sizeof(data)); - - kdata.desc = dinit.desc; - kdata.data = data; - kdata.data_size = sizeof(data); - - if (ioctl(cfd, NCRIO_DATA_GET, &kdata)) { + if (keydata.idata_size == 0 || (data[0] == 0 && data[1] == 0 && data[2] == 0 && data[4] == 0)) { fprintf(stderr, "Error: %s:%d\n", __func__, __LINE__); - perror("ioctl(NCRIO_DATA_GET)"); + fprintf(stderr, "Generated key: %.2x.%.2x.%.2x.%.2x.%.2x.%.2x.%.2x.%.2x." + "%.2x.%.2x.%.2x.%.2x.%.2x.%.2x.%.2x.%.2x\n", data[0], data[1], + data[2], data[3], data[4], data[5], data[6], data[7], data[8], + data[9], data[10], data[11], data[12], data[13], data[14], + data[15]); return 1; } -#if 0 - fprintf(stderr, "Generated key: %.2x.%.2x.%.2x.%.2x.%.2x.%.2x.%.2x.%.2x." - "%.2x.%.2x.%.2x.%.2x.%.2x.%.2x.%.2x.%.2x\n", data[0], data[1], - data[2], data[3], data[4], data[5], data[6], data[7], data[8], - data[9], data[10], data[11], data[12], data[13], data[14], - data[15]); -#endif - if (ioctl(cfd, NCRIO_KEY_DEINIT, &key)) { fprintf(stderr, "Error: %s:%d\n", __func__, __LINE__); perror("ioctl(NCRIO_KEY_DEINIT)"); @@ -219,24 +177,16 @@ test_ncr_key(int cfd) return 1; } + memset(data, 0, sizeof(data)); + memset(&keydata, 0, sizeof(keydata)); keydata.key = key; - keydata.data = dinit.desc; - - if (ioctl(cfd, NCRIO_KEY_EXPORT, &keydata)) { - fprintf(stderr, "Error: %s:%d\n", __func__, __LINE__); - perror("ioctl(NCRIO_KEY_EXPORT)"); - return 1; - } + keydata.idata = data; + keydata.idata_size = sizeof(data); /* try to get the output data - should fail */ - memset(data, 0, sizeof(data)); - - kdata.desc = dinit.desc; - kdata.data = data; - kdata.data_size = sizeof(data); - if (ioctl(cfd, NCRIO_DATA_GET, &kdata)==0) { + if (ioctl(cfd, NCRIO_KEY_EXPORT, &keydata)==0) { fprintf(stderr, "Error: %s:%d\n", __func__, __LINE__); fprintf(stderr, "Data were exported, but shouldn't be!\n"); return 1; @@ -252,135 +202,14 @@ test_ncr_key(int cfd) } -static int test_ncr_data(int cfd) -{ - struct ncr_data_init_st init; - struct ncr_data_st kdata; - uint8_t data[DATA_SIZE]; - uint8_t data_bak[DATA_SIZE]; - int i; - - fprintf(stdout, "Tests on Data:\n"); - - randomize_data(data, sizeof(data)); - memcpy(data_bak, data, sizeof(data)); - - init.max_object_size = DATA_SIZE; - init.flags = NCR_DATA_FLAG_EXPORTABLE; - init.initial_data = data; - init.initial_data_size = sizeof(data); - - if (ioctl(cfd, NCRIO_DATA_INIT, &init)) { - perror("ioctl(NCRIO_DATA_INIT)"); - return 1; - } - - fprintf(stdout, "\tData Import...\n"); - - memset(data, 0, sizeof(data)); - - kdata.desc = init.desc; - kdata.data = data; - kdata.data_size = sizeof(data); - - if (ioctl(cfd, NCRIO_DATA_GET, &kdata)) { - perror("ioctl(NCRIO_DATA_GET)"); - return 1; - } - - if (memcmp(data, data_bak, sizeof(data))!=0) { - fprintf(stderr, "data returned but differ!\n"); - return 1; - } - - fprintf(stdout, "\tData Export...\n"); - - /* test set */ - memset(data, 0xf1, sizeof(data)); - - kdata.desc = init.desc; - kdata.data = data; - kdata.data_size = sizeof(data); - - if (ioctl(cfd, NCRIO_DATA_SET, &kdata)) { - perror("ioctl(NCRIO_DATA_SET)"); - return 1; - } - - /* test get after set */ - memset(data, 0, sizeof(data)); - - kdata.desc = init.desc; - kdata.data = data; - kdata.data_size = sizeof(data); - - if (ioctl(cfd, NCRIO_DATA_GET, &kdata)) { - perror("ioctl(NCRIO_DATA_GET)"); - return 1; - } - - for(i=0;i - * - * This file is part of linux cryptodev. - * - * cryptodev is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * cryptodev is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include -#include -#include -#include "cryptodev.h" -#include -#include -#include -#include "ncr.h" -#include "ncr-int.h" - -/* must be called with data semaphore down */ -static void _ncr_data_unlink_item(struct data_item_st *item) -{ - list_del(&item->list); - _ncr_data_item_put( item); /* decrement ref count */ -} - -void ncr_data_list_deinit(struct list_sem_st* lst) -{ - if(lst) { - struct data_item_st * item, *tmp; - - down(&lst->sem); - - list_for_each_entry_safe(item, tmp, &lst->list, list) { - _ncr_data_unlink_item(item); - } - up(&lst->sem); - - } -} - -/* must be called with data semaphore down - */ -static ncr_data_t _ncr_data_get_new_desc( struct list_sem_st* lst) -{ -struct data_item_st* item; -int mx = 1; - - list_for_each_entry(item, &lst->list, list) { - mx = max(mx, item->desc); - } - mx++; - - return mx; -} - -/* returns the data item corresponding to desc */ -struct data_item_st* ncr_data_item_get( struct list_sem_st* lst, ncr_data_t desc) -{ -struct data_item_st* item; - - down(&lst->sem); - list_for_each_entry(item, &lst->list, list) { - if (item->desc == desc) { - atomic_inc(&item->refcnt); - up(&lst->sem); - return item; - } - } - up(&lst->sem); - - err(); - return NULL; -} - -static void* data_alloc(size_t size) -{ - /* FIXME: enforce a maximum memory limit per process and per user */ - /* ncr_data_set() relies this function enforcing a reasonable upper - limit. */ - if (size > 64*1024) { - err(); - return NULL; - } - return kmalloc(size, GFP_KERNEL); -} - -void _ncr_data_item_put( struct data_item_st* item) -{ - if (atomic_dec_and_test(&item->refcnt)) { - ncr_limits_remove(item->uid, item->pid, LIMIT_TYPE_DATA); - kfree(item->data); - kfree(item); - } -} - -int ncr_data_init(struct list_sem_st* lst, void __user* arg) -{ - struct ncr_data_init_st init; - struct data_item_st* data; - int ret; - - ret = ncr_limits_add_and_check(current_euid(), task_pid_nr(current), LIMIT_TYPE_DATA); - if (ret < 0) { - err(); - return ret; - } - - if (unlikely(copy_from_user(&init, arg, sizeof(init)))) { - err(); - ret = -EFAULT; - goto err_limits; - } - - data = kmalloc(sizeof(*data), GFP_KERNEL); - if (data == NULL) { - err(); - ret = -ENOMEM; - goto err_limits; - } - - memset(data, 0, sizeof(*data)); - - data->flags = init.flags; - data->uid = current_euid(); - data->pid = task_pid_nr(current); - - atomic_set(&data->refcnt, 1); - - data->data = data_alloc(init.max_object_size); - if (data->data == NULL) { - err(); - ret = -ENOMEM; - goto err_data; - } - data->max_data_size = init.max_object_size; - - sg_init_one(&data->sg, data->data, data->max_data_size); - - if (init.initial_data != NULL) { - if (unlikely(copy_from_user(data->data, init.initial_data, - init.initial_data_size))) { - err(); - _ncr_data_item_put(data); - return -EFAULT; - } - data->data_size = init.initial_data_size; - } - - down(&lst->sem); - - data->desc = _ncr_data_get_new_desc(lst); - - list_add(&data->list, &lst->list); - - up(&lst->sem); - - init.desc = data->desc; - ret = copy_to_user(arg, &init, sizeof(init)); - if (unlikely(ret)) { - down(&lst->sem); - _ncr_data_unlink_item(data); - up(&lst->sem); - return -EFAULT; - } - return ret; - - err_data: - kfree(data); - err_limits: - ncr_limits_remove(current_euid(), task_pid_nr(current), - LIMIT_TYPE_DATA); - return ret; -} - - -int ncr_data_deinit(struct list_sem_st* lst, void __user* arg) -{ - ncr_data_t desc; - struct data_item_st * item, *tmp; - - if (unlikely(copy_from_user(&desc, arg, sizeof(desc)))) { - err(); - return -EFAULT; - } - down(&lst->sem); - - list_for_each_entry_safe(item, tmp, &lst->list, list) { - if(item->desc == desc) { - _ncr_data_unlink_item(item); - break; - } - } - - up(&lst->sem); - - return 0; -} - -int ncr_data_get(struct list_sem_st* lst, void __user* arg) -{ - struct ncr_data_st get; - struct data_item_st * data; - size_t len; - int ret; - - if (unlikely(copy_from_user(&get, arg, sizeof(get)))) { - err(); - return -EFAULT; - } - - data = ncr_data_item_get( lst, get.desc); - - if (data == NULL) { - err(); - return -EINVAL; - } - - if (!(data->flags & NCR_DATA_FLAG_EXPORTABLE)) { - err(); - ret = -EPERM; - goto cleanup; - } - - len = min(get.data_size, data->data_size); - - /* update length */ - get.data_size = len; - - ret = copy_to_user(arg, &get, sizeof(get)); - if (unlikely(ret)) { - err(); - ret = -EFAULT; - } - - if (ret == 0 && len > 0) { - ret = copy_to_user(get.data, data->data, len); - if (unlikely(ret)) { - err(); - ret = -EFAULT; - } - } - -cleanup: - _ncr_data_item_put( data); - - return ret; -} - -int ncr_data_set(struct list_sem_st* lst, void __user* arg) -{ - struct ncr_data_st get; - struct data_item_st * data; - int ret; - - if (unlikely(copy_from_user(&get, arg, sizeof(get)))) { - err(); - return -EFAULT; - } - - data = ncr_data_item_get( lst, get.desc); - - if (data == NULL) { - err(); - return -EINVAL; - } - - if ((get.data_size > data->max_data_size) || - (get.data == NULL && get.data_size != 0)) { - err(); - ret = -EINVAL; - goto cleanup; - } - - if (get.data != NULL) { - if (unlikely(copy_from_user(data->data, get.data, - get.data_size))) { - err(); - ret = -EFAULT; - goto cleanup; - } - } - data->data_size = get.data_size; - - ret = 0; - -cleanup: - _ncr_data_item_put( data); - - return ret; -} diff --git a/ncr-int.h b/ncr-int.h index 6ccbcd2..03fab19 100644 --- a/ncr-int.h +++ b/ncr-int.h @@ -55,27 +55,6 @@ struct session_item_st { ncr_session_t desc; }; -struct data_item_st { - struct list_head list; - /* This object is not protected from concurrent access. - * I see no reason to allow concurrent writes (reads are - * not an issue). - */ - struct scatterlist sg; /* points to data */ - - uint8_t* data; - size_t data_size; - size_t max_data_size; - unsigned int flags; - atomic_t refcnt; - - /* owner. The one charged with this */ - uid_t uid; - pid_t pid; - - ncr_data_t desc; -}; - struct key_item_st { struct list_head list; /* This object is also not protected from concurrent access. @@ -129,20 +108,10 @@ void ncr_deinit_lists(struct ncr_lists *lst); int ncr_ioctl(struct ncr_lists*, struct file *filp, unsigned int cmd, unsigned long arg); -int ncr_data_set(struct list_sem_st*, void __user* arg); -int ncr_data_get(struct list_sem_st*, void __user* arg); -int ncr_data_deinit(struct list_sem_st*, void __user* arg); -int ncr_data_init(struct list_sem_st*, void __user* arg); -void ncr_data_list_deinit(struct list_sem_st*); -struct data_item_st* ncr_data_item_get( struct list_sem_st* lst, ncr_data_t desc); -void _ncr_data_item_put( struct data_item_st* item); - int ncr_key_init(struct list_sem_st*, void __user* arg); int ncr_key_deinit(struct list_sem_st*, void __user* arg); -int ncr_key_export(struct list_sem_st* data_lst, - struct list_sem_st* key_lst,void __user* arg); -int ncr_key_import(struct list_sem_st* data_lst, - struct list_sem_st* key_lst,void __user* arg); +int ncr_key_export(struct list_sem_st* key_lst,void __user* arg); +int ncr_key_import(struct list_sem_st* key_lst,void __user* arg); void ncr_key_list_deinit(struct list_sem_st* lst); int ncr_key_generate(struct list_sem_st* data_lst, void __user* arg); int ncr_key_info(struct list_sem_st*, void __user* arg); @@ -160,7 +129,6 @@ void _ncr_key_item_put( struct key_item_st* item); typedef enum { LIMIT_TYPE_KEY, - LIMIT_TYPE_DATA } limits_type_t; void ncr_limits_remove(uid_t uid, pid_t pid, limits_type_t type); @@ -195,25 +163,6 @@ int key_to_storage_data( uint8_t** data, size_t * data_size, const struct key_it /* misc helper macros */ -inline static unsigned int key_flags_to_data(unsigned int key_flags) -{ - unsigned int flags = 0; - - if (key_flags & NCR_KEY_FLAG_EXPORTABLE) - flags |= NCR_DATA_FLAG_EXPORTABLE; - - return flags; -} - -inline static unsigned int data_flags_to_key(unsigned int data_flags) -{ - unsigned int flags = 0; - - if (data_flags & NCR_DATA_FLAG_EXPORTABLE) - flags |= NCR_KEY_FLAG_EXPORTABLE; - - return flags; -} const struct algo_properties_st *_ncr_algo_to_properties(ncr_algorithm_t algo); const struct algo_properties_st *ncr_key_params_get_sign_hash(const struct algo_properties_st *algo, struct ncr_key_params_st * params); diff --git a/ncr-key.c b/ncr-key.c index 126d1bf..9e67b52 100644 --- a/ncr-key.c +++ b/ncr-key.c @@ -231,13 +231,12 @@ int ncr_key_deinit(struct list_sem_st* lst, void __user* arg) /* "exports" a key to a data item. If the key is not exportable * to userspace then the data item will also not be. */ -int ncr_key_export(struct list_sem_st* data_lst, - struct list_sem_st* key_lst, void __user* arg) +int ncr_key_export(struct list_sem_st* key_lst, void __user* arg) { struct ncr_key_data_st data; struct key_item_st* item = NULL; -struct data_item_st* ditem = NULL; -uint32_t size; +void* tmp = NULL; +uint32_t tmp_size; int ret; if (unlikely(copy_from_user(&data, arg, sizeof(data)))) { @@ -251,18 +250,15 @@ int ret; return ret; } - ditem = ncr_data_item_get( data_lst, data.data); - if (ditem == NULL) { + if (!(item->flags & NCR_KEY_FLAG_EXPORTABLE)) { err(); - ret = -EINVAL; + ret = -EPERM; goto fail; } - ditem->flags = key_flags_to_data(item->flags); - switch (item->type) { case NCR_KEY_TYPE_SECRET: - if (item->key.secret.size > ditem->max_data_size) { + if (item->key.secret.size > data.idata_size) { err(); ret = -EINVAL; goto fail; @@ -270,21 +266,40 @@ int ret; /* found */ if (item->key.secret.size > 0) { - memcpy(ditem->data, item->key.secret.data, item->key.secret.size); + ret = copy_to_user(data.idata, item->key.secret.data, item->key.secret.size); + if (unlikely(ret)) { + err(); + ret = -EFAULT; + goto fail; + } } - ditem->data_size = item->key.secret.size; + data.idata_size = item->key.secret.size; break; case NCR_KEY_TYPE_PUBLIC: case NCR_KEY_TYPE_PRIVATE: - size = ditem->max_data_size; - ret = ncr_pk_pack(item, ditem->data, &size); + tmp_size = data.idata_size; - ditem->data_size = size; + tmp = kmalloc(tmp_size, GFP_KERNEL); + if (tmp == NULL) { + err(); + ret = -ENOMEM; + goto fail; + } + + ret = ncr_pk_pack(item, tmp, &tmp_size); + data.idata_size = tmp_size; if (ret < 0) { err(); goto fail; } + + ret = copy_to_user(data.idata, tmp, tmp_size); + if (unlikely(ret)) { + err(); + ret = -EFAULT; + goto fail; + } break; default: @@ -293,16 +308,16 @@ int ret; goto fail; } - _ncr_key_item_put( item); - _ncr_data_item_put( ditem); - - return 0; + if (unlikely(copy_to_user(arg, &data, sizeof(data)))) { + err(); + ret = -EFAULT; + } else + ret = 0; fail: + kfree(tmp); if (item) _ncr_key_item_put(item); - if (ditem) - _ncr_data_item_put(ditem); return ret; } @@ -310,13 +325,13 @@ fail: /* "imports" a key from a data item. If the key is not exportable * to userspace then the key item will also not be. */ -int ncr_key_import(struct list_sem_st* data_lst, - struct list_sem_st* key_lst, void __user* arg) +int ncr_key_import(struct list_sem_st* key_lst, void __user* arg) { struct ncr_key_data_st data; struct key_item_st* item = NULL; -struct data_item_st* ditem = NULL; int ret; +void* tmp = NULL; +size_t tmp_size; if (unlikely(copy_from_user(&data, arg, sizeof(data)))) { err(); @@ -329,13 +344,20 @@ int ret; return ret; } - ditem = ncr_data_item_get( data_lst, data.data); - if (ditem == NULL) { + tmp = kmalloc(data.idata_size, GFP_KERNEL); + if (tmp == NULL) { err(); - ret = -EINVAL; + ret = -ENOMEM; goto fail; } - + + if (unlikely(copy_from_user(tmp, data.idata, data.idata_size))) { + err(); + ret = -EFAULT; + goto fail; + } + tmp_size = data.idata_size; + item->type = data.type; item->algorithm = _ncr_algo_to_properties(data.algorithm); if (item->algorithm == NULL) { @@ -344,11 +366,6 @@ int ret; goto fail; } item->flags = data.flags; - /* if data cannot be exported then the flags above - * should be overriden */ - if (!(ditem->flags & NCR_DATA_FLAG_EXPORTABLE)) { - item->flags &= ~NCR_KEY_FLAG_EXPORTABLE; - } if (data.key_id_size > MAX_KEY_ID_SIZE) { err(); @@ -363,18 +380,18 @@ int ret; switch(item->type) { case NCR_KEY_TYPE_SECRET: - if (ditem->data_size > NCR_CIPHER_MAX_KEY_LEN) { + if (tmp_size > NCR_CIPHER_MAX_KEY_LEN) { err(); ret = -EINVAL; goto fail; } - memcpy(item->key.secret.data, ditem->data, ditem->data_size); - item->key.secret.size = ditem->data_size; + memcpy(item->key.secret.data, tmp, tmp_size); + item->key.secret.size = tmp_size; break; case NCR_KEY_TYPE_PRIVATE: case NCR_KEY_TYPE_PUBLIC: - ret = ncr_pk_unpack( item, ditem->data, ditem->data_size); + ret = ncr_pk_unpack( item, tmp, tmp_size); if (ret < 0) { err(); goto fail; @@ -387,16 +404,13 @@ int ret; goto fail; } - _ncr_key_item_put( item); - _ncr_data_item_put( ditem); - - return 0; + ret = 0; fail: if (item) _ncr_key_item_put(item); - if (ditem) - _ncr_data_item_put(ditem); + kfree(tmp); + return ret; } diff --git a/ncr-limits.c b/ncr-limits.c index 5340954..7a98f3c 100644 --- a/ncr-limits.c +++ b/ncr-limits.c @@ -34,12 +34,10 @@ /* arbitrary now */ static unsigned int max_per_user[] = { [LIMIT_TYPE_KEY] = 128, - [LIMIT_TYPE_DATA] = 128, }; static unsigned int max_per_process[] = { [LIMIT_TYPE_KEY] = 64, - [LIMIT_TYPE_DATA] = 64, }; struct limit_user_item_st { diff --git a/ncr-pk.c b/ncr-pk.c index cb217d7..ecb2ce3 100644 --- a/ncr-pk.c +++ b/ncr-pk.c @@ -359,9 +359,13 @@ int ncr_pk_cipher_init(const struct algo_properties_st *algo, err(); return -EINVAL; } - } else if (params->params.rsa.type == RSA_PKCS1_PSS) + } else if (params->params.rsa.type == RSA_PKCS1_PSS) { ctx->type = LTC_LTC_PKCS_1_PSS; - + } else { + err(); + return -EINVAL; + } + ctx->salt_len = params->params.rsa.pss_salt; break; case NCR_ALG_DSA: @@ -534,7 +538,6 @@ void * input, *output; case NCR_ALG_RSA: cret = rsa_sign_hash_ex( input, isg_size, output, &osize, ctx->type, ctx->sign_hash, ctx->salt_len, &ctx->key->key.pk.rsa); - if (cret != CRYPT_OK) { err(); return tomerr(cret); @@ -575,7 +578,7 @@ int ncr_pk_cipher_verify(const struct ncr_pk_ctx* ctx, const void* hash, size_t hash_size, ncr_error_t* err) { int cret, ret; -int stat; +int stat = 0; uint8_t* sig; sig = kmalloc(sign_sg_size, GFP_KERNEL); @@ -596,13 +599,12 @@ uint8_t* sig; cret = rsa_verify_hash_ex( sig, sign_sg_size, hash, hash_size, ctx->type, ctx->sign_hash, ctx->salt_len, &stat, &ctx->key->key.pk.rsa); - if (cret != CRYPT_OK) { err(); ret = tomerr(cret); goto fail; } - + if (stat == 1) *err = 0; else diff --git a/ncr-sessions.c b/ncr-sessions.c index f0aebc5..8986379 100644 --- a/ncr-sessions.c +++ b/ncr-sessions.c @@ -537,12 +537,13 @@ static int get_userbuf2(struct session_item_st* ses, unsigned *src_cnt, struct scatterlist **dst_sg, unsigned *dst_cnt) { int src_pagecount, dst_pagecount = 0, pagecount, write_src = 1; + size_t input_size = op->data.udata.input_size; if (op->data.udata.input == NULL) { return -EINVAL; } - src_pagecount = PAGECOUNT(op->data.udata.input, op->data.udata.input_size); + src_pagecount = PAGECOUNT(op->data.udata.input, input_size); if (op->data.udata.input != op->data.udata.output) { /* non-in-situ transformation */ if (op->data.udata.output != NULL) { @@ -551,6 +552,10 @@ static int get_userbuf2(struct session_item_st* ses, } else { dst_pagecount = 0; } + } else { + src_pagecount = max((int)(PAGECOUNT(op->data.udata.output, op->data.udata.output_size)), + src_pagecount); + input_size = max(input_size, (size_t)op->data.udata.output_size); } ses->available_pages = pagecount = src_pagecount + dst_pagecount; @@ -571,7 +576,7 @@ static int get_userbuf2(struct session_item_st* ses, } } - if (__get_userbuf(op->data.udata.input, op->data.udata.input_size, write_src, + if (__get_userbuf(op->data.udata.input, input_size, write_src, src_pagecount, ses->pages, ses->sg)) { dprintk(1, KERN_ERR, "failed to get user pages for data input\n"); return -EINVAL; @@ -639,7 +644,7 @@ int _ncr_session_direct_update(struct ncr_lists* lists, struct ncr_session_op_st ret = -EINVAL; goto fail; } - + ret = _ncr_session_encrypt(sess, isg, isg_cnt, isg_size, osg, osg_cnt, &osg_size); if (ret < 0) { @@ -716,7 +721,6 @@ int _ncr_session_direct_final(struct ncr_lists* lists, struct ncr_session_op_st* { int ret; struct session_item_st* sess; - struct data_item_st* odata = NULL; int digest_size; uint8_t digest[NCR_HASH_MAX_OUTPUT_SIZE]; uint8_t vdigest[NCR_HASH_MAX_OUTPUT_SIZE]; @@ -776,7 +780,7 @@ int _ncr_session_direct_final(struct ncr_lists* lists, struct ncr_session_op_st* goto fail; } - if (digest_size != odata->data_size || + if (digest_size != osg_size || memcmp(vdigest, digest, digest_size) != 0) { op->err = NCR_VERIFICATION_FAILED; diff --git a/ncr.c b/ncr.c index 4813eef..1d91456 100644 --- a/ncr.c +++ b/ncr.c @@ -64,7 +64,6 @@ void* ncr_init_lists(void) void ncr_deinit_lists(struct ncr_lists *lst) { if(lst) { - ncr_data_list_deinit(&lst->data); ncr_key_list_deinit(&lst->key); ncr_sessions_list_deinit(&lst->sessions); kfree(lst); @@ -124,15 +123,6 @@ ncr_ioctl(struct ncr_lists* lst, struct file *filp, BUG(); switch (cmd) { - case NCRIO_DATA_INIT: - return ncr_data_init(&lst->data, arg); - case NCRIO_DATA_GET: - return ncr_data_get(&lst->data, arg); - case NCRIO_DATA_SET: - return ncr_data_set(&lst->data, arg); - case NCRIO_DATA_DEINIT: - return ncr_data_deinit(&lst->data, arg); - case NCRIO_KEY_INIT: return ncr_key_init(&lst->key, arg); case NCRIO_KEY_DEINIT: @@ -140,9 +130,9 @@ ncr_ioctl(struct ncr_lists* lst, struct file *filp, case NCRIO_KEY_GENERATE: return ncr_key_generate(&lst->key, arg); case NCRIO_KEY_EXPORT: - return ncr_key_export(&lst->data, &lst->key, arg); + return ncr_key_export(&lst->key, arg); case NCRIO_KEY_IMPORT: - return ncr_key_import(&lst->data, &lst->key, arg); + return ncr_key_import(&lst->key, arg); case NCRIO_KEY_GET_INFO: return ncr_key_info(&lst->key, arg); case NCRIO_KEY_WRAP: diff --git a/ncr.h b/ncr.h index e992c7b..3c87f59 100644 --- a/ncr.h +++ b/ncr.h @@ -55,34 +55,6 @@ typedef enum { NCR_KEY_TYPE_PRIVATE=3, } ncr_key_type_t; -/* Data Handling - */ -#define NCR_DATA_FLAG_EXPORTABLE 1 -#define NCR_DATA_FLAG_SIGN_ONLY 2 /* this object can only be used with hash/sign operations */ - -typedef int ncr_data_t; -#define NCR_DATA_INVALID (ncr_data_t)(0) - -struct ncr_data_init_st { - ncr_data_t desc; - size_t max_object_size; - unsigned int flags; - void __user *initial_data; /* can be null */ - size_t initial_data_size; -}; - -struct ncr_data_st { - ncr_data_t desc; - void __user *data; - size_t data_size; /* rw in get */ - unsigned int append_flag; /* only when used with NCRIO_DATA_SET */ -}; - -#define NCRIO_DATA_INIT _IOWR('c', 200, struct ncr_data_init_st) -#define NCRIO_DATA_GET _IOWR('c', 201, struct ncr_data_st) -#define NCRIO_DATA_SET _IOR('c', 202, struct ncr_data_st) -#define NCRIO_DATA_DEINIT _IOR('c', 203, ncr_data_t) - /* Key handling */ @@ -187,7 +159,10 @@ struct ncr_key_info_st { struct ncr_key_data_st { ncr_key_t key; - ncr_data_t data; + + void __user *idata; + size_t idata_size; /* rw in get */ + /* in case of import this will be used as key id */ uint8_t key_id[MAX_KEY_ID_SIZE]; size_t key_id_size; -- cgit From 2c3943aab40b4c0b34809153c29f3a3a4eaebe72 Mon Sep 17 00:00:00 2001 From: Nikos Mavrogiannopoulos Date: Sat, 24 Jul 2010 18:56:53 +0200 Subject: Added AES in CTR mode. --- cryptodev_main.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/cryptodev_main.c b/cryptodev_main.c index 3cb96fb..7ed0911 100644 --- a/cryptodev_main.c +++ b/cryptodev_main.c @@ -136,6 +136,9 @@ crypto_create_session(struct fcrypt *fcr, struct session_op *sop) case CRYPTO_CAMELLIA_CBC: alg_name = "cbc(camelia)"; break; + case CRYPTO_AES_CTR: + alg_name = "ctr(aes)"; + break; case CRYPTO_NULL: alg_name = "ecb(cipher_null)"; break; -- cgit From bd29b1337fab4bb0ca41ff83271482bfe551d38b Mon Sep 17 00:00:00 2001 From: Nikos Mavrogiannopoulos Date: Mon, 26 Jul 2010 01:29:04 +0200 Subject: Corrected issue when finalizing sessions that hashed keys. --- Makefile | 3 +-- ncr-sessions-direct.c | 30 ------------------------- ncr-sessions.c | 62 +++++++++++++++++++++++++++++++-------------------- ncr-sessions.h | 16 ------------- ncr.h | 4 ++-- 5 files changed, 41 insertions(+), 74 deletions(-) delete mode 100644 ncr-sessions-direct.c delete mode 100644 ncr-sessions.h diff --git a/Makefile b/Makefile index 3b7ebf6..41c82c4 100644 --- a/Makefile +++ b/Makefile @@ -67,8 +67,7 @@ TOMCRYPT_OBJECTS = libtomcrypt/misc/zeromem.o libtomcrypt/misc/crypt/crypt_argch libtomcrypt/pk/asn1/der/x509/der_decode_subject_public_key_info.o cryptodev-objs = cryptodev_main.o cryptodev_cipher.o ncr.o \ - ncr-key.o ncr-limits.o ncr-pk.o \ - ncr-sessions-direct.o ncr-sessions.o \ + ncr-key.o ncr-limits.o ncr-pk.o ncr-sessions.o \ ncr-key-wrap.o ncr-key-storage.o $(TOMMATH_OBJECTS) \ $(TOMCRYPT_OBJECTS) diff --git a/ncr-sessions-direct.c b/ncr-sessions-direct.c deleted file mode 100644 index 3d41f12..0000000 --- a/ncr-sessions-direct.c +++ /dev/null @@ -1,30 +0,0 @@ -/* - * New driver for /dev/crypto device (aka CryptoDev) - - * Copyright (c) 2010 Nikos Mavrogiannopoulos - * - * This file is part of linux cryptodev. - * - * cryptodev is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * cryptodev is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include -#include "cryptodev.h" -#include "ncr.h" -#include "ncr-int.h" -#include -#include -#include - - diff --git a/ncr-sessions.c b/ncr-sessions.c index 8986379..f9043ec 100644 --- a/ncr-sessions.c +++ b/ncr-sessions.c @@ -25,9 +25,9 @@ #include "ncr-int.h" #include #include -#include -static int _ncr_session_direct_update_key(struct ncr_lists* lists, struct ncr_session_op_st* op); +static int _ncr_session_update_key(struct ncr_lists* lists, struct ncr_session_op_st* op); +static void _ncr_session_remove(struct list_sem_st* lst, ncr_session_t desc); void ncr_sessions_list_deinit(struct list_sem_st* lst) { @@ -491,16 +491,15 @@ void _ncr_session_remove(struct list_sem_st* lst, ncr_session_t desc) /* Only the output buffer is given as scatterlist */ static int get_userbuf1(struct session_item_st* ses, - struct ncr_session_op_st* op, struct scatterlist **dst_sg, unsigned *dst_cnt) + void __user * udata, size_t udata_size, struct scatterlist **dst_sg, unsigned *dst_cnt) { int pagecount = 0; - if (op->data.udata.output == NULL) { + if (udata == NULL) { return -EINVAL; } - pagecount = PAGECOUNT(op->data.udata.output, op->data.udata.output_size); - + pagecount = PAGECOUNT(udata, udata_size); ses->available_pages = pagecount; @@ -520,7 +519,7 @@ static int get_userbuf1(struct session_item_st* ses, } } - if (__get_userbuf(op->data.udata.output, op->data.udata.output_size, 1, + if (__get_userbuf(udata, udata_size, 1, pagecount, ses->pages, ses->sg)) { dprintk(1, KERN_ERR, "failed to get user pages for data input\n"); return -EINVAL; @@ -608,7 +607,7 @@ static int get_userbuf2(struct session_item_st* ses, } /* Called when userspace buffers are used */ -int _ncr_session_direct_update(struct ncr_lists* lists, struct ncr_session_op_st* op) +int _ncr_session_update(struct ncr_lists* lists, struct ncr_session_op_st* op) { int ret; struct session_item_st* sess; @@ -704,20 +703,20 @@ fail: return ret; } -static int try_session_direct_update(struct ncr_lists* lists, struct ncr_session_op_st* op) +static int try_session_update(struct ncr_lists* lists, struct ncr_session_op_st* op) { if (op->type == NCR_KEY_DATA) { if (op->data.kdata.input != NCR_KEY_INVALID) - return _ncr_session_direct_update_key(lists, op); + return _ncr_session_update_key(lists, op); } else if (op->type == NCR_DIRECT_DATA) { if (op->data.udata.input != NULL) - return _ncr_session_direct_update(lists, op); + return _ncr_session_update(lists, op); } return 0; } -int _ncr_session_direct_final(struct ncr_lists* lists, struct ncr_session_op_st* op) +int _ncr_session_final(struct ncr_lists* lists, struct ncr_session_op_st* op) { int ret; struct session_item_st* sess; @@ -728,6 +727,8 @@ int _ncr_session_direct_final(struct ncr_lists* lists, struct ncr_session_op_st* unsigned osg_cnt=0; size_t osg_size = 0; size_t orig_osg_size; + void __user * udata = NULL; + size_t *udata_size; sess = ncr_sessions_item_get( &lists->sessions, op->ses); if (sess == NULL) { @@ -735,7 +736,7 @@ int _ncr_session_direct_final(struct ncr_lists* lists, struct ncr_session_op_st* return -EINVAL; } - ret = try_session_direct_update(lists, op); + ret = try_session_update(lists, op); if (ret < 0) { err(); _ncr_sessions_item_put(sess); @@ -747,18 +748,30 @@ int _ncr_session_direct_final(struct ncr_lists* lists, struct ncr_session_op_st* _ncr_sessions_item_put(sess); return -ERESTARTSYS; } + + if (op->type == NCR_DIRECT_DATA) { + udata = op->data.udata.output; + udata_size = &op->data.udata.output_size; + } else if (op->type == NCR_KEY_DATA) { + udata = op->data.kdata.output; + udata_size = &op->data.kdata.output_size; + } else { + err(); + ret = -EINVAL; + goto fail; + } switch(sess->op) { case NCR_OP_ENCRYPT: case NCR_OP_DECRYPT: break; case NCR_OP_VERIFY: - ret = get_userbuf1(sess, op, &osg, &osg_cnt); + ret = get_userbuf1(sess, udata, *udata_size, &osg, &osg_cnt); if (ret < 0) { err(); goto fail; } - orig_osg_size = osg_size = op->data.udata.output_size; + orig_osg_size = osg_size = *udata_size; digest_size = sess->hash.digestsize; if (digest_size == 0 || sizeof(digest) < digest_size) { @@ -799,12 +812,12 @@ int _ncr_session_direct_final(struct ncr_lists* lists, struct ncr_session_op_st* break; case NCR_OP_SIGN: - ret = get_userbuf1(sess, op, &osg, &osg_cnt); + ret = get_userbuf1(sess, udata, *udata_size, &osg, &osg_cnt); if (ret < 0) { err(); goto fail; } - orig_osg_size = osg_size = op->data.udata.output_size; + orig_osg_size = osg_size = *udata_size; digest_size = sess->hash.digestsize; if (digest_size == 0 || osg_size < digest_size) { @@ -848,7 +861,7 @@ int _ncr_session_direct_final(struct ncr_lists* lists, struct ncr_session_op_st* } if (osg_size > 0) - op->data.udata.output_size = osg_size; + *udata_size = osg_size; ret = 0; @@ -874,7 +887,7 @@ fail: /* Direct with key: Allows to hash a key */ /* Called when userspace buffers are used */ -static int _ncr_session_direct_update_key(struct ncr_lists* lists, struct ncr_session_op_st* op) +static int _ncr_session_update_key(struct ncr_lists* lists, struct ncr_session_op_st* op) { int ret; struct session_item_st* sess; @@ -908,7 +921,8 @@ static int _ncr_session_direct_update_key(struct ncr_lists* lists, struct ncr_se return -ERESTARTSYS; } - ret = get_userbuf1(sess, op, &osg, &osg_cnt); + ret = get_userbuf1(sess, op->data.kdata.output, op->data.kdata.output_size, + &osg, &osg_cnt); if (ret < 0) { err(); goto fail; @@ -962,9 +976,9 @@ int ncr_session_update(struct ncr_lists* lists, void __user* arg) } if (op.type == NCR_DIRECT_DATA) - ret = _ncr_session_direct_update(lists, &op); + ret = _ncr_session_update(lists, &op); else if (op.type == NCR_KEY_DATA) - ret = _ncr_session_direct_update_key(lists, &op); + ret = _ncr_session_update_key(lists, &op); else ret = -EINVAL; @@ -991,7 +1005,7 @@ int ncr_session_final(struct ncr_lists* lists, void __user* arg) return -EFAULT; } - ret = _ncr_session_direct_final(lists, &op); + ret = _ncr_session_final(lists, &op); if (unlikely(ret)) { err(); return ret; @@ -1021,7 +1035,7 @@ int ncr_session_once(struct ncr_lists* lists, void __user* arg) } kop.op.ses = kop.init.ses; - ret = _ncr_session_direct_final(lists, &kop.op); + ret = _ncr_session_final(lists, &kop.op); if (ret < 0) { err(); return ret; diff --git a/ncr-sessions.h b/ncr-sessions.h deleted file mode 100644 index d6185aa..0000000 --- a/ncr-sessions.h +++ /dev/null @@ -1,16 +0,0 @@ -#ifndef NCR_SESSIONS_H -# define NCR_SESSIONS_H - -int _ncr_session_direct_final(struct ncr_lists* lists, struct ncr_session_op_st* op); -int _ncr_session_direct_update(struct ncr_lists* lists, struct ncr_session_op_st* op); - -int _ncr_session_encrypt(struct session_item_st* sess, const struct scatterlist* input, unsigned input_cnt, - size_t input_size, void *output, unsigned output_cnt, size_t *output_size); - -int _ncr_session_decrypt(struct session_item_st* sess, const struct scatterlist* input, - unsigned input_cnt, size_t input_size, - struct scatterlist *output, unsigned output_cnt, size_t *output_size); - -void _ncr_session_remove(struct list_sem_st* lst, ncr_session_t desc); - -#endif diff --git a/ncr.h b/ncr.h index 3c87f59..ccb0bb1 100644 --- a/ncr.h +++ b/ncr.h @@ -271,13 +271,13 @@ struct ncr_session_op_st { * the place of the signature. */ size_t output_size; - } kdata; + } kdata; /* NCR_KEY_DATA */ struct { void* input; size_t input_size; void* output; size_t output_size; - } udata; + } udata; /* NCR_DIRECT_DATA */ } data; ncr_data_type_t type; -- cgit From 5af672c074827d4321807ee25c2b57eed7b24a35 Mon Sep 17 00:00:00 2001 From: Nikos Mavrogiannopoulos Date: Mon, 26 Jul 2010 09:15:13 +0200 Subject: Corrected PSS signature generation and verification. --- libtomcrypt/pk/pkcs1/pkcs_1_pss_decode.c | 4 +++- libtomcrypt/pk/pkcs1/pkcs_1_pss_encode.c | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/libtomcrypt/pk/pkcs1/pkcs_1_pss_decode.c b/libtomcrypt/pk/pkcs1/pkcs_1_pss_decode.c index 4249743..b9ade4b 100644 --- a/libtomcrypt/pk/pkcs1/pkcs_1_pss_decode.c +++ b/libtomcrypt/pk/pkcs1/pkcs_1_pss_decode.c @@ -130,8 +130,10 @@ int pkcs_1_pss_decode(const unsigned char *msghash, unsigned long msghashlen, goto LBL_ERR; } + zeromem(mask, 8); + /* M = (eight) 0x00 || msghash || salt, mask = H(M) */ - err = hash_memory_multi(hash_algo, mask, &hLen, mask, 8, msghash, (unsigned long)msghashlen, DB+x, (unsigned long)saltlen, NULL, 0); + err = hash_memory_multi(hash_algo, mask, &hLen, mask, (unsigned long)8, msghash, (unsigned long)msghashlen, DB+x, (unsigned long)saltlen, NULL, 0); if (err != CRYPT_OK) { goto LBL_ERR; } diff --git a/libtomcrypt/pk/pkcs1/pkcs_1_pss_encode.c b/libtomcrypt/pk/pkcs1/pkcs_1_pss_encode.c index 956c79e..f8f763b 100644 --- a/libtomcrypt/pk/pkcs1/pkcs_1_pss_encode.c +++ b/libtomcrypt/pk/pkcs1/pkcs_1_pss_encode.c @@ -81,9 +81,11 @@ int pkcs_1_pss_encode(const unsigned char *msghash, unsigned long msghashlen, if (saltlen > 0) { get_random_bytes(salt, saltlen); } + + zeromem(DB, 8); /* M = (eight) 0x00 || msghash || salt, hash = H(M) */ - err = hash_memory_multi(hash_algo, hash, &hLen, DB, 8, msghash, (unsigned long)msghashlen, salt, (unsigned long)saltlen, NULL, 0); + err = hash_memory_multi(hash_algo, hash, &hLen, DB, (unsigned long)8, msghash, (unsigned long)msghashlen, salt, (unsigned long)saltlen, NULL, 0); if (err != CRYPT_OK) { goto LBL_ERR; } -- cgit From e8313378c5da5f8e3c856939f3c5a441720accc7 Mon Sep 17 00:00:00 2001 From: Nikos Mavrogiannopoulos Date: Mon, 26 Jul 2010 09:46:50 +0200 Subject: Added __user to userspace buffers. --- ncr.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/ncr.h b/ncr.h index ccb0bb1..ee6d502 100644 --- a/ncr.h +++ b/ncr.h @@ -196,7 +196,7 @@ struct ncr_key_wrap_st { ncr_key_t key; struct ncr_key_params_st params; - void* io; /* encrypted keytowrap */ + void __user * io; /* encrypted keytowrap */ size_t io_size; /* this will be updated by the actual size on wrap */ }; @@ -216,7 +216,7 @@ struct ncr_master_key_st { struct ncr_key_storage_wrap_st { ncr_key_t keytowrap; - void* io; /* encrypted keytowrap */ + void __user * io; /* encrypted keytowrap */ size_t io_size; /* this will be updated by the actual size on wrap */ }; @@ -267,15 +267,15 @@ struct ncr_session_op_st { union { struct { ncr_key_t input; - void* output; /* when verifying signature this is + void __user * output; /* when verifying signature this is * the place of the signature. */ size_t output_size; } kdata; /* NCR_KEY_DATA */ struct { - void* input; + void __user * input; size_t input_size; - void* output; + void __user * output; size_t output_size; } udata; /* NCR_DIRECT_DATA */ } data; -- cgit From 935be4945512eb37461a226c51ede5e8b05cbe24 Mon Sep 17 00:00:00 2001 From: Nikos Mavrogiannopoulos Date: Mon, 26 Jul 2010 09:46:56 +0200 Subject: Added test case for hashing secret keys. Some corrections in independent session updates. --- examples/ncr.c | 116 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ncr-sessions.c | 58 +++++++++++++---------------- 2 files changed, 141 insertions(+), 33 deletions(-) diff --git a/examples/ncr.c b/examples/ncr.c index 4ff59fd..4231ffa 100644 --- a/examples/ncr.c +++ b/examples/ncr.c @@ -797,6 +797,119 @@ test_ncr_hash(int cfd) } +static int +test_ncr_hash_key(int cfd) +{ + ncr_key_t key; + struct ncr_key_data_st keydata; + uint8_t data[HASH_DATA_SIZE]; + int j, data_size; + struct ncr_session_op_st op; + struct ncr_session_st op_init; + const uint8_t *output = (void*)"\xe2\xd7\x2c\x2e\x14\xad\x97\xc8\xd2\xdb\xce\xd8\xb3\x52\x9f\x1c\xb3\x2c\x5c\xec"; + + /* convert it to key */ + if (ioctl(cfd, NCRIO_KEY_INIT, &key)) { + perror("ioctl(NCRIO_KEY_INIT)"); + return 1; + } + + keydata.key_id[0] = 'a'; + keydata.key_id[2] = 'b'; + keydata.key_id_size = 2; + keydata.type = NCR_KEY_TYPE_SECRET; + keydata.algorithm = NCR_ALG_AES_CBC; + keydata.flags = NCR_KEY_FLAG_EXPORTABLE; + + fprintf(stdout, "Tests on Hashes of Keys\n"); + + fprintf(stdout, "\t%s:\n", hash_vectors[0].name); + /* import key */ + keydata.key = key; + keydata.idata = (void*)hash_vectors[0].plaintext; + keydata.idata_size = hash_vectors[0].plaintext_size; + if (ioctl(cfd, NCRIO_KEY_IMPORT, &keydata)) { + fprintf(stderr, "Error: %s:%d\n", __func__, __LINE__); + perror("ioctl(NCRIO_KEY_IMPORT)"); + return 1; + } + + /* encrypt */ + memset(&op_init, 0, sizeof(op_init)); + op_init.algorithm = hash_vectors[0].algorithm; + op_init.op = hash_vectors[0].op; + + if (ioctl(cfd, NCRIO_SESSION_INIT, &op_init)) { + fprintf(stderr, "Error: %s:%d\n", __func__, __LINE__); + perror("ioctl(NCRIO_SESSION_INIT)"); + return 1; + } + + memset(&op, 0, sizeof(op)); + op.ses = op_init.ses; + op.data.udata.input = (void*)hash_vectors[0].plaintext; + op.data.udata.input_size = hash_vectors[0].plaintext_size; + op.data.udata.output = NULL; + op.data.udata.output_size = 0; + op.type = NCR_DIRECT_DATA; + + if (ioctl(cfd, NCRIO_SESSION_UPDATE, &op)) { + fprintf(stderr, "Error: %s:%d\n", __func__, __LINE__); + perror("ioctl(NCRIO_SESSION_UPDATE)"); + return 1; + } + + memset(&op, 0, sizeof(op)); + op.ses = op_init.ses; + op.data.kdata.input = key; + op.data.kdata.output = NULL; + op.data.kdata.output_size = 0; + op.type = NCR_KEY_DATA; + + if (ioctl(cfd, NCRIO_SESSION_UPDATE, &op)) { + fprintf(stderr, "Error: %s:%d\n", __func__, __LINE__); + perror("ioctl(NCRIO_SESSION_UPDATE)"); + return 1; + } + + op.data.udata.input = NULL; + op.data.udata.input_size = 0; + op.data.udata.output = data; + op.data.udata.output_size = sizeof(data); + op.type = NCR_DIRECT_DATA; + + if (ioctl(cfd, NCRIO_SESSION_FINAL, &op)) { + fprintf(stderr, "Error: %s:%d\n", __func__, __LINE__); + perror("ioctl(NCRIO_SESSION_FINAL)"); + return 1; + } + + data_size = op.data.udata.output_size; + + + if (data_size != hash_vectors[0].output_size || + memcmp(data, output, hash_vectors[0].output_size) != 0) { + fprintf(stderr, "HASH test vector %d failed!\n", 0); + + fprintf(stderr, "Output[%d]: ", (int)data_size); + for(j=0;jsg == NULL || ses->pages == NULL)) { + err(); + return -ENOMEM; + } - ses->available_pages = pagecount; + pagecount = PAGECOUNT(udata, udata_size); if (pagecount > ses->array_size) { while (ses->array_size < pagecount) @@ -514,19 +518,21 @@ static int get_userbuf1(struct session_item_st* ses, ses->sg = krealloc(ses->sg, ses->array_size * sizeof(struct scatterlist), GFP_KERNEL); - if (ses->sg == NULL || ses->pages == NULL) { + if (unlikely(ses->sg == NULL || ses->pages == NULL)) { return -ENOMEM; } } if (__get_userbuf(udata, udata_size, 1, pagecount, ses->pages, ses->sg)) { - dprintk(1, KERN_ERR, "failed to get user pages for data input\n"); + err(); return -EINVAL; } (*dst_sg) = ses->sg; *dst_cnt = pagecount; + ses->available_pages = pagecount; + return 0; } @@ -538,16 +544,22 @@ static int get_userbuf2(struct session_item_st* ses, int src_pagecount, dst_pagecount = 0, pagecount, write_src = 1; size_t input_size = op->data.udata.input_size; - if (op->data.udata.input == NULL) { + if (unlikely(op->data.udata.input == NULL)) { + err(); return -EINVAL; } + if (unlikely(ses->sg == NULL || ses->pages == NULL)) { + err(); + return -ENOMEM; + } + src_pagecount = PAGECOUNT(op->data.udata.input, input_size); if (op->data.udata.input != op->data.udata.output) { /* non-in-situ transformation */ + write_src = 0; if (op->data.udata.output != NULL) { dst_pagecount = PAGECOUNT(op->data.udata.output, op->data.udata.output_size); - write_src = 0; } else { dst_pagecount = 0; } @@ -557,7 +569,7 @@ static int get_userbuf2(struct session_item_st* ses, input_size = max(input_size, (size_t)op->data.udata.output_size); } - ses->available_pages = pagecount = src_pagecount + dst_pagecount; + pagecount = src_pagecount + dst_pagecount; if (pagecount > ses->array_size) { while (ses->array_size < pagecount) @@ -577,7 +589,8 @@ static int get_userbuf2(struct session_item_st* ses, if (__get_userbuf(op->data.udata.input, input_size, write_src, src_pagecount, ses->pages, ses->sg)) { - dprintk(1, KERN_ERR, "failed to get user pages for data input\n"); + err(); + printk("write: %d\n", write_src); return -EINVAL; } (*src_sg) = ses->sg; @@ -589,7 +602,7 @@ static int get_userbuf2(struct session_item_st* ses, if (__get_userbuf(op->data.udata.output, op->data.udata.output_size, 1, dst_pagecount, ses->pages + src_pagecount, *dst_sg)) { - dprintk(1, KERN_ERR, "failed to get user pages for data output\n"); + err(); release_user_pages(ses->pages, src_pagecount); return -EINVAL; } @@ -602,6 +615,8 @@ static int get_userbuf2(struct session_item_st* ses, *dst_sg = NULL; } } + + ses->available_pages = pagecount; return 0; } @@ -892,9 +907,6 @@ static int _ncr_session_update_key(struct ncr_lists* lists, struct ncr_session_o int ret; struct session_item_st* sess; struct key_item_st* key = NULL; - struct scatterlist *osg; - unsigned osg_cnt=0; - size_t osg_size; sess = ncr_sessions_item_get( &lists->sessions, op->ses); if (sess == NULL) { @@ -915,21 +927,6 @@ static int _ncr_session_update_key(struct ncr_lists* lists, struct ncr_session_o goto fail; } - if (down_interruptible(&sess->mem_mutex)) { - err(); - _ncr_sessions_item_put(sess); - return -ERESTARTSYS; - } - - ret = get_userbuf1(sess, op->data.kdata.output, op->data.kdata.output_size, - &osg, &osg_cnt); - if (ret < 0) { - err(); - goto fail; - } - - osg_size = op->data.kdata.output_size; - switch(sess->op) { case NCR_OP_ENCRYPT: case NCR_OP_DECRYPT: @@ -954,11 +951,6 @@ static int _ncr_session_update_key(struct ncr_lists* lists, struct ncr_session_o ret = 0; fail: - if (sess->available_pages) { - release_user_pages(sess->pages, sess->available_pages); - sess->available_pages = 0; - } - up(&sess->mem_mutex); if (key) _ncr_key_item_put(key); _ncr_sessions_item_put(sess); -- cgit