diff options
32 files changed, 1197 insertions, 1178 deletions
diff --git a/crypto/userspace/Makefile b/crypto/userspace/Makefile index 4a13497cc10..6e5d5388499 100644 --- a/crypto/userspace/Makefile +++ b/crypto/userspace/Makefile @@ -64,7 +64,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-sessions.o ncr-pk.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/crypto/userspace/cryptodev_cipher.c b/crypto/userspace/cryptodev_cipher.c index da111c76981..d5e1df729ba 100644 --- a/crypto/userspace/cryptodev_cipher.c +++ b/crypto/userspace/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/crypto/userspace/cryptodev_int.h b/crypto/userspace/cryptodev_int.h index 59144d0aab0..4b63225d09e 100644 --- a/crypto/userspace/cryptodev_int.h +++ b/crypto/userspace/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/crypto/userspace/cryptodev_main.c b/crypto/userspace/cryptodev_main.c index 6e93060e872..167689e73af 100644 --- a/crypto/userspace/cryptodev_main.c +++ b/crypto/userspace/cryptodev_main.c @@ -41,7 +41,7 @@ #include <asm/ioctl.h> #include <linux/scatterlist.h> #include "cryptodev_int.h" -#include "ncr_int.h" +#include "ncr-int.h" #include <linux/version.h> MODULE_AUTHOR("Nikos Mavrogiannopoulos <nmav@gnutls.org>"); @@ -64,8 +64,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; @@ -137,6 +135,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; @@ -494,7 +495,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])) @@ -503,16 +504,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/crypto/userspace/libtomcrypt/hashes/crypt_hash_is_valid.c b/crypto/userspace/libtomcrypt/hashes/crypt_hash_is_valid.c index 32e869989d4..d01d4183f80 100644 --- a/crypto/userspace/libtomcrypt/hashes/crypt_hash_is_valid.c +++ b/crypto/userspace/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/crypto/userspace/libtomcrypt/hashes/hash_get_oid.c b/crypto/userspace/libtomcrypt/hashes/hash_get_oid.c index 32e439058b7..39f43722884 100644 --- a/crypto/userspace/libtomcrypt/hashes/hash_get_oid.c +++ b/crypto/userspace/libtomcrypt/hashes/hash_get_oid.c @@ -8,7 +8,7 @@ * */ #include "tomcrypt.h" -#include <ncr_int.h> +#include <ncr-int.h> /* Returns the OID of the hash. @@ -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/crypto/userspace/libtomcrypt/hashes/hash_memory.c b/crypto/userspace/libtomcrypt/hashes/hash_memory.c index 274c208d4f9..a416de9624e 100644 --- a/crypto/userspace/libtomcrypt/hashes/hash_memory.c +++ b/crypto/userspace/libtomcrypt/hashes/hash_memory.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> #include <cryptodev_int.h> /** @@ -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/crypto/userspace/libtomcrypt/hashes/hash_memory_multi.c b/crypto/userspace/libtomcrypt/hashes/hash_memory_multi.c index 6a85f6502fe..a9149166700 100644 --- a/crypto/userspace/libtomcrypt/hashes/hash_memory_multi.c +++ b/crypto/userspace/libtomcrypt/hashes/hash_memory_multi.c @@ -10,7 +10,7 @@ */ #include "tomcrypt.h" #include <stdarg.h> -#include <ncr_int.h> +#include <ncr-int.h> #include <cryptodev_int.h> /** @@ -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/crypto/userspace/libtomcrypt/headers/tomcrypt_hash.h b/crypto/userspace/libtomcrypt/headers/tomcrypt_hash.h index 417e4812440..e4e84e4841b 100644 --- a/crypto/userspace/libtomcrypt/headers/tomcrypt_hash.h +++ b/crypto/userspace/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/crypto/userspace/libtomcrypt/headers/tomcrypt_pk.h b/crypto/userspace/libtomcrypt/headers/tomcrypt_pk.h index fa6030ed30d..145165efe51 100644 --- a/crypto/userspace/libtomcrypt/headers/tomcrypt_pk.h +++ b/crypto/userspace/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/crypto/userspace/libtomcrypt/headers/tomcrypt_pkcs.h b/crypto/userspace/libtomcrypt/headers/tomcrypt_pkcs.h index 8e439423eef..be0d7f6822a 100644 --- a/crypto/userspace/libtomcrypt/headers/tomcrypt_pkcs.h +++ b/crypto/userspace/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/crypto/userspace/libtomcrypt/pk/pkcs1/pkcs_1_mgf1.c b/crypto/userspace/libtomcrypt/pk/pkcs1/pkcs_1_mgf1.c index 01fe231a84e..58052ebeaf3 100644 --- a/crypto/userspace/libtomcrypt/pk/pkcs1/pkcs_1_mgf1.c +++ b/crypto/userspace/libtomcrypt/pk/pkcs1/pkcs_1_mgf1.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 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/crypto/userspace/libtomcrypt/pk/pkcs1/pkcs_1_oaep_decode.c b/crypto/userspace/libtomcrypt/pk/pkcs1/pkcs_1_oaep_decode.c index 4114c564436..5214a2920d8 100644 --- a/crypto/userspace/libtomcrypt/pk/pkcs1/pkcs_1_oaep_decode.c +++ b/crypto/userspace/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 <ncr_int.h> +#include <ncr-int.h> /** @file 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/crypto/userspace/libtomcrypt/pk/pkcs1/pkcs_1_oaep_encode.c b/crypto/userspace/libtomcrypt/pk/pkcs1/pkcs_1_oaep_encode.c index ccee5cfb7b4..ef644f9ba2e 100644 --- a/crypto/userspace/libtomcrypt/pk/pkcs1/pkcs_1_oaep_encode.c +++ b/crypto/userspace/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 <ncr_int.h> +#include <ncr-int.h> /** @file 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/crypto/userspace/libtomcrypt/pk/pkcs1/pkcs_1_pss_decode.c b/crypto/userspace/libtomcrypt/pk/pkcs1/pkcs_1_pss_decode.c index 5a26654f019..b9ade4b62f9 100644 --- a/crypto/userspace/libtomcrypt/pk/pkcs1/pkcs_1_pss_decode.c +++ b/crypto/userspace/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 <ncr_int.h> +#include <ncr-int.h> /** @file 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; } @@ -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_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, (unsigned long)8, msghash, (unsigned long)msghashlen, DB+x, (unsigned long)saltlen, NULL, 0); if (err != CRYPT_OK) { goto LBL_ERR; } diff --git a/crypto/userspace/libtomcrypt/pk/pkcs1/pkcs_1_pss_encode.c b/crypto/userspace/libtomcrypt/pk/pkcs1/pkcs_1_pss_encode.c index 382820d8bc2..f8f763b48a1 100644 --- a/crypto/userspace/libtomcrypt/pk/pkcs1/pkcs_1_pss_encode.c +++ b/crypto/userspace/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 <ncr_int.h> +#include <ncr-int.h> /** @file 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 */ @@ -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_idx, 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; } @@ -97,7 +99,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/crypto/userspace/libtomcrypt/pk/rsa/rsa_decrypt_key.c b/crypto/userspace/libtomcrypt/pk/rsa/rsa_decrypt_key.c index 52885e82654..a8f3ac461ca 100644 --- a/crypto/userspace/libtomcrypt/pk/rsa/rsa_decrypt_key.c +++ b/crypto/userspace/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/crypto/userspace/libtomcrypt/pk/rsa/rsa_encrypt_key.c b/crypto/userspace/libtomcrypt/pk/rsa/rsa_encrypt_key.c index d59699c6ef1..8d3f2db1daa 100644 --- a/crypto/userspace/libtomcrypt/pk/rsa/rsa_encrypt_key.c +++ b/crypto/userspace/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/crypto/userspace/libtomcrypt/pk/rsa/rsa_export.c b/crypto/userspace/libtomcrypt/pk/rsa/rsa_export.c index 33c222d17a1..905bb6f9bca 100644 --- a/crypto/userspace/libtomcrypt/pk/rsa/rsa_export.c +++ b/crypto/userspace/libtomcrypt/pk/rsa/rsa_export.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_export.c Export RSA LTC_PKCS keys, Tom St Denis diff --git a/crypto/userspace/libtomcrypt/pk/rsa/rsa_sign_hash.c b/crypto/userspace/libtomcrypt/pk/rsa/rsa_sign_hash.c index 1298d46c896..f27789d2df0 100644 --- a/crypto/userspace/libtomcrypt/pk/rsa/rsa_sign_hash.c +++ b/crypto/userspace/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/crypto/userspace/libtomcrypt/pk/rsa/rsa_verify_hash.c b/crypto/userspace/libtomcrypt/pk/rsa/rsa_verify_hash.c index 773ea7db11c..c8a113dd822 100644 --- a/crypto/userspace/libtomcrypt/pk/rsa/rsa_verify_hash.c +++ b/crypto/userspace/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/crypto/userspace/ncr-data.c b/crypto/userspace/ncr-data.c deleted file mode 100644 index 1c8c99a8fa2..00000000000 --- a/crypto/userspace/ncr-data.c +++ /dev/null @@ -1,301 +0,0 @@ -/* - * New driver for /dev/crypto device (aka CryptoDev) - - * Copyright (c) 2010 Nikos Mavrogiannopoulos <nmav@gnutls.org> - * - * 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 <http://www.gnu.org/licenses/>. - */ - -#include <linux/crypto.h> -#include <linux/cryptodev.h> -#include <linux/mm.h> -#include <linux/highmem.h> -#include <linux/ncr.h> -#include <asm/uaccess.h> -#include <asm/ioctl.h> -#include <linux/scatterlist.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; - - 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/crypto/userspace/ncr_int.h b/crypto/userspace/ncr-int.h index 253ad519eee..db6950b596c 100644 --- a/crypto/userspace/ncr_int.h +++ b/crypto/userspace/ncr-int.h @@ -10,10 +10,27 @@ #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; - ncr_algorithm_t algorithm; + const struct algo_properties_st *algorithm; ncr_crypto_op_t op; /* contexts for various options. @@ -24,39 +41,27 @@ 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; 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). - */ - - 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; - 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; @@ -103,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); @@ -134,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); @@ -142,12 +136,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); -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); -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); @@ -171,28 +163,8 @@ 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 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 diff --git a/crypto/userspace/ncr-key-storage.c b/crypto/userspace/ncr-key-storage.c index 6b8d197274d..af6c9c15531 100644 --- a/crypto/userspace/ncr-key-storage.c +++ b/crypto/userspace/ncr-key-storage.c @@ -25,7 +25,7 @@ #include <asm/uaccess.h> #include <asm/ioctl.h> #include <linux/scatterlist.h> -#include "ncr_int.h" +#include "ncr-int.h" #include "cryptodev_int.h" struct packed_key { @@ -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/crypto/userspace/ncr-key-wrap.c b/crypto/userspace/ncr-key-wrap.c index 4cdccde705e..e105e3ad415 100644 --- a/crypto/userspace/ncr-key-wrap.c +++ b/crypto/userspace/ncr-key-wrap.c @@ -27,7 +27,7 @@ #include <asm/uaccess.h> #include <asm/ioctl.h> #include <linux/scatterlist.h> -#include "ncr_int.h" +#include "ncr-int.h" #include "cryptodev_int.h" typedef uint8_t val64_t[8]; @@ -44,13 +44,13 @@ static void val64_xor( val64_t val, uint32_t x) } static int rfc3394_wrap(val64_t R[], unsigned int n, struct cipher_data* ctx, - struct data_item_st* output, const uint8_t iv[8]) + uint8_t* output, size_t *output_size, const uint8_t iv[8]) { val64_t A; uint8_t aes_block[16]; int i,j; - if (output->max_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;j<n;j++) - memcpy(&output->data[(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 (;i<n*8;i++) { R[i/8][i%8] = 0; } - ret = rfc3394_wrap( R, n, &ctx, output, iv); + ret = rfc3394_wrap( R, n, &ctx, output, output_size, iv); kfree(R); if (ret < 0) { err(); @@ -174,10 +174,9 @@ cleanup: } static int _unwrap_aes_rfc5649(void* kdata, size_t *kdata_size, struct key_item_st* kek, - struct data_item_st *wrapped, const void* _iv, size_t iv_size) + const 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; int i, ret; struct cipher_data ctx; uint8_t iv[4]; @@ -196,9 +195,6 @@ size_t size; return ret; } - wrapped_key = wrapped->data; - 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/crypto/userspace/ncr-key.c b/crypto/userspace/ncr-key.c index 5954d38fb7a..09e3174a19b 100644 --- a/crypto/userspace/ncr-key.c +++ b/crypto/userspace/ncr-key.c @@ -26,7 +26,7 @@ #include <asm/uaccess.h> #include <asm/ioctl.h> #include <linux/scatterlist.h> -#include "ncr_int.h" +#include "ncr-int.h" static void ncr_key_clear(struct key_item_st* item); @@ -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,21 +344,28 @@ 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 = data.algorithm; - 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; + item->algorithm = _ncr_algo_to_properties(data.algorithm); + if (item->algorithm == NULL) { + err(); + ret = -EINVAL; + goto fail; } + item->flags = data.flags; if (data.key_id_size > MAX_KEY_ID_SIZE) { err(); @@ -358,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; @@ -382,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; } @@ -414,6 +433,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 +452,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 +511,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 +547,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/crypto/userspace/ncr-limits.c b/crypto/userspace/ncr-limits.c index 472f5cee33b..1e8da1af4ac 100644 --- a/crypto/userspace/ncr-limits.c +++ b/crypto/userspace/ncr-limits.c @@ -29,17 +29,15 @@ #include <linux/version.h> #include <linux/file.h> #include <linux/cred.h> -#include "ncr_int.h" +#include "ncr-int.h" /* 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/crypto/userspace/ncr-pk.c b/crypto/userspace/ncr-pk.c index 9c047c91ae6..de23e94d73b 100644 --- a/crypto/userspace/ncr-pk.c +++ b/crypto/userspace/ncr-pk.c @@ -26,7 +26,7 @@ #include <asm/uaccess.h> #include <asm/ioctl.h> #include <linux/scatterlist.h> -#include "ncr_int.h" +#include "ncr-int.h" #include <tomcrypt.h> static struct workqueue_struct * pk_wq = NULL; @@ -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,26 @@ 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; + } else { + err(); + return -EINVAL; + } + ctx->salt_len = params->params.rsa.pss_salt; break; case NCR_ALG_DSA: @@ -373,123 +381,230 @@ int ret; } 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; + } - switch(ctx->algorithm) { + 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; - switch(ctx->algorithm) { + 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; - switch(ctx->algorithm) { + 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_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 stat; +int cret, ret; +int stat = 0; +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) { + switch(ctx->algorithm->algo) { case NCR_ALG_RSA: - 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) *err = 0; else @@ -497,11 +612,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) @@ -512,8 +628,12 @@ int stat; break; default: err(); - return -EINVAL; + ret = -EINVAL; + goto fail; } - - return 0; + + ret = 0; +fail: + kfree(sig); + return ret; } diff --git a/crypto/userspace/ncr-pk.h b/crypto/userspace/ncr-pk.h index 11800175c3b..fdc5e1c005b 100644 --- a/crypto/userspace/ncr-pk.h +++ b/crypto/userspace/ncr-pk.h @@ -4,11 +4,11 @@ #include <tomcrypt.h> 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,19 +30,25 @@ 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); -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/crypto/userspace/ncr-sessions.c b/crypto/userspace/ncr-sessions.c index 5d9fc93f3be..42a352ca62b 100644 --- a/crypto/userspace/ncr-sessions.c +++ b/crypto/userspace/ncr-sessions.c @@ -22,8 +22,11 @@ #include <linux/crypto.h> #include <linux/cryptodev.h> #include <linux/ncr.h> -#include "ncr_int.h" +#include "ncr-int.h" +#include <linux/mm_types.h> +#include <linux/scatterlist.h> +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) @@ -84,6 +87,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 +97,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); @@ -112,186 +129,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 }, - { .algo = NCR_ALG_RSA, .kstr = NULL, - .can_encrypt=1, .can_sign=1}, - { .algo = NCR_ALG_DSA, .kstr = NULL, - .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, .is_pk = 1, + .can_encrypt=1, .can_sign=1, .key_type = NCR_KEY_TYPE_PUBLIC }, + { .algo = NCR_ALG_DSA, .kstr = NULL, .is_pk = 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 +227,17 @@ 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 +255,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 +277,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,89 +291,83 @@ 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 && !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) { - str = _ncr_algo_to_str(session->algorithm); - if (str == NULL) { - err(); - return -EINVAL; - } - - ret = cryptodev_hash_init(&ns->hash, str, 1, - ns->key->key.secret.data, ns->key->key.secret.size); - if (ret < 0) { + if (ns->algorithm->can_digest) { + if (ns->algorithm->kstr == NULL) { err(); + ret = -EINVAL; goto fail; } - } 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); + ret = cryptodev_hash_init(&ns->hash, ns->algorithm->kstr, 0, NULL, 0); if (ret < 0) { err(); - return ret; - } - sign_hash = ret; - - if (algo_can_digest(sign_hash) == 0) { - err(); - ret = -EINVAL; goto fail; } - str = _ncr_algo_to_str(sign_hash); - if (str == NULL) { - err(); - ret = -EINVAL; - goto fail; - } - - ret = ncr_pk_cipher_init(ns->algorithm, &ns->pk, - &session->params, ns->key); + + } else { + /* read key */ + ret = ncr_key_item_get_read( &ns->key, &lists->key, session->key); if (ret < 0) { err(); goto fail; } - ret = cryptodev_hash_init(&ns->hash, str, 0, NULL, 0); - if (ret < 0) { + 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, 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; } - } else { - err(); - ret = -EINVAL; - goto fail; - } - - break; - case NCR_OP_DIGEST: - if (algo_can_digest(session->algorithm)==0) { - err(); - ret = -EINVAL; - goto fail; - } - str = _ncr_algo_to_str(session->algorithm); - if (str == NULL) { - err(); - ret = -EINVAL; - goto fail; - } - - ret = cryptodev_hash_init(&ns->hash, str, 0, NULL, 0); - if (ret < 0) { - err(); - goto fail; } break; @@ -487,14 +413,223 @@ int ncr_session_init(struct ncr_lists* lists, void __user* arg) return ret; } -/* Main update function - */ -static int _ncr_session_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 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; +} + +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, + void __user * udata, size_t udata_size, struct scatterlist **dst_sg, unsigned *dst_cnt) +{ + int pagecount = 0; + + if (unlikely(udata == NULL)) { + err(); + return -EINVAL; + } + + if (unlikely(ses->sg == NULL || ses->pages == NULL)) { + err(); + return -ENOMEM; + } + + pagecount = PAGECOUNT(udata, udata_size); + + 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 (unlikely(ses->sg == NULL || ses->pages == NULL)) { + return -ENOMEM; + } + } + + if (__get_userbuf(udata, udata_size, 1, + pagecount, ses->pages, ses->sg)) { + err(); + return -EINVAL; + } + (*dst_sg) = ses->sg; + *dst_cnt = pagecount; + + ses->available_pages = 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; + size_t input_size = op->data.udata.input_size; + + 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); + } 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); + } + + 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, input_size, write_src, + src_pagecount, ses->pages, ses->sg)) { + err(); + printk("write: %d\n", write_src); + 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)) { + err(); + 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; + } + } + + ses->available_pages = pagecount; + + return 0; +} + +/* Called when userspace buffers are used */ +int _ncr_session_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; + 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) { @@ -502,131 +637,68 @@ static int _ncr_session_update(struct ncr_lists* lists, struct ncr_session_op_st 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: - /* obtain data item */ - data = ncr_data_item_get( &lists->data, op->data.cipher.plaintext); - if (data == NULL) { - err(); - ret = -EINVAL; - goto fail; - } - - odata = ncr_data_item_get( &lists->data, op->data.cipher.ciphertext); - if (odata == NULL) { + if (osg == NULL) { err(); ret = -EINVAL; goto fail; } - if (odata->max_data_size < data->data_size) { + ret = _ncr_session_encrypt(sess, isg, isg_cnt, isg_size, + osg, osg_cnt, &osg_size); + if (ret < 0) { err(); - ret = -EINVAL; goto fail; } + op->data.udata.output_size = osg_size; - if (algo_is_symmetric(sess->algorithm)) { - /* 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->data.cipher.ciphertext); - if (data == NULL) { + if (osg == NULL) { err(); ret = -EINVAL; goto fail; } - odata = ncr_data_item_get( &lists->data, op->data.cipher.plaintext); - if (odata == NULL) { + if (osg_size < isg_size) { err(); ret = -EINVAL; goto fail; } - if (odata->max_data_size < data->data_size) { + ret = _ncr_session_decrypt(sess, isg, isg_cnt, isg_size, + osg, osg_cnt, &osg_size); + if (ret < 0) { err(); - ret = -EINVAL; goto fail; } - - /* read key */ - if (algo_is_symmetric(sess->algorithm)) { - 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; - } - } + op->data.udata.output_size = osg_size; break; case NCR_OP_SIGN: - case NCR_OP_DIGEST: - /* obtain data item */ - data = ncr_data_item_get( &lists->data, op->data.sign.text); - if (data == NULL) { - err(); - ret = -EINVAL; - goto fail; - } - - ret = _cryptodev_hash_update(&sess->hash, data->data, data->data_size); - if (ret < 0) { - err(); - goto fail; - } - break; - case NCR_OP_VERIFY: - /* obtain data item */ - data = ncr_data_item_get( &lists->data, op->data.verify.text); - 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, isg, isg_size); if (ret < 0) { err(); goto fail; } break; - default: err(); ret = -EINVAL; @@ -636,51 +708,42 @@ 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; } -int ncr_session_update(struct ncr_lists* lists, void __user* arg) +static int try_session_update(struct ncr_lists* lists, struct ncr_session_op_st* op) { - struct ncr_session_op_st op; - - if (unlikely(copy_from_user( &op, arg, sizeof(op)))) { - err(); - return -EFAULT; + if (op->type == NCR_KEY_DATA) { + if (op->data.kdata.input != NCR_KEY_INVALID) + return _ncr_session_update_key(lists, op); + } else if (op->type == NCR_DIRECT_DATA) { + if (op->data.udata.input != NULL) + return _ncr_session_update(lists, op); } - - return _ncr_session_update(lists, &op); -} - -static 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; + return 0; } -static int _ncr_session_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; - 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; + void __user * udata = NULL; + size_t *udata_size; sess = ncr_sessions_item_get( &lists->sessions, op->ses); if (sess == NULL) { @@ -688,32 +751,42 @@ 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(); + _ncr_sessions_item_put(sess); + return ret; + } + + if (down_interruptible(&sess->mem_mutex)) { + err(); + _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: - /* obtain data item */ - if (op->data.cipher.plaintext != NCR_DATA_INVALID && - op->data.cipher.ciphertext != NCR_DATA_INVALID) { - ret = _ncr_session_update(lists, op); - if (ret < 0) - goto fail; - } break; - case NCR_OP_VERIFY: - /* obtain data item */ - if (op->data.sign.text != 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); - if (odata == NULL) { + ret = get_userbuf1(sess, udata, *udata_size, &osg, &osg_cnt); + if (ret < 0) { err(); - ret = -EINVAL; goto fail; } + orig_osg_size = osg_size = *udata_size; digest_size = sess->hash.digestsize; if (digest_size == 0 || sizeof(digest) < digest_size) { @@ -726,11 +799,17 @@ static int _ncr_session_final(struct ncr_lists* lists, struct ncr_session_op_st* err(); goto fail; } - - if (algo_is_hmac(sess->algorithm)) { - if (digest_size != odata->data_size || - memcmp(odata->data, digest, digest_size) != 0) { + 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 != osg_size || + memcmp(vdigest, digest, digest_size) != 0) { op->err = NCR_VERIFICATION_FAILED; } else { @@ -738,7 +817,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(); @@ -748,41 +827,46 @@ 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) { - ret = _ncr_session_update(lists, op); - if (ret < 0) - goto fail; + ret = get_userbuf1(sess, udata, *udata_size, &osg, &osg_cnt); + if (ret < 0) { + err(); + goto fail; } - odata = ncr_data_item_get( &lists->data, op->data.sign.output); - if (odata == NULL) { + orig_osg_size = osg_size = *udata_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->op != NCR_OP_DIGEST && !algo_is_hmac(sess->algorithm)) { + 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: @@ -791,12 +875,20 @@ static int _ncr_session_final(struct ncr_lists* lists, struct ncr_session_op_st* goto fail; } + if (osg_size > 0) + *udata_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 (algo_is_symmetric(sess->algorithm)) { + if (sess->algorithm->is_symmetric) { cryptodev_cipher_deinit(&sess->cipher); } else { ncr_pk_cipher_deinit(&sess->pk); @@ -808,6 +900,93 @@ fail: return ret; } +/* Direct with key: Allows to hash a key */ +/* Called when userspace buffers are used */ +static int _ncr_session_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; + + 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; + } + + 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 (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; + int ret; + + if (unlikely(copy_from_user( &op, arg, sizeof(op)))) { + err(); + return -EFAULT; + } + + if (op.type == NCR_DIRECT_DATA) + ret = _ncr_session_update(lists, &op); + else if (op.type == NCR_KEY_DATA) + ret = _ncr_session_update_key(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; @@ -858,4 +1037,3 @@ int ncr_session_once(struct ncr_lists* lists, void __user* arg) return -EFAULT; return 0; } - diff --git a/crypto/userspace/ncr.c b/crypto/userspace/ncr.c index 60d76166246..f1d22bdf787 100644 --- a/crypto/userspace/ncr.c +++ b/crypto/userspace/ncr.c @@ -30,7 +30,7 @@ #include <linux/cred.h> #include <linux/capability.h> #include <linux/ncr.h> -#include "ncr_int.h" +#include "ncr-int.h" #include <linux/workqueue.h> /* This is the master wrapping key for storage of keys @@ -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,19 +130,19 @@ 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: - 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: @@ -161,6 +151,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: @@ -173,31 +164,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/include/linux/ncr.h b/include/linux/ncr.h index 5103e1e8b6a..bb6c12b9a00 100644 --- a/include/linux/ncr.h +++ b/include/linux/ncr.h @@ -52,34 +52,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 */ @@ -184,7 +156,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; @@ -209,7 +184,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; @@ -217,10 +192,12 @@ struct ncr_key_wrap_st { ncr_key_t key; struct ncr_key_params_st params; - ncr_data_t data; /* encrypted keytowrap */ + + void __user * 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 */ @@ -235,10 +212,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 __user * 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 @@ -247,7 +226,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; @@ -274,24 +252,31 @@ typedef enum { NCR_VERIFICATION_FAILED = -2, } ncr_error_t; +typedef enum { + NCR_KEY_DATA, + NCR_DIRECT_DATA, +} ncr_data_type_t; + 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 */ + ncr_key_t input; + void __user * output; /* when verifying signature this is + * the place of the signature. + */ + size_t output_size; + } kdata; /* NCR_KEY_DATA */ struct { - ncr_data_t text; - ncr_data_t signature; - } verify; /* mac/sign */ + void __user * input; + size_t input_size; + void __user * output; + size_t output_size; + } udata; /* NCR_DIRECT_DATA */ } data; + ncr_data_type_t type; /* output of verification */ ncr_error_t err; @@ -304,7 +289,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) |