summaryrefslogtreecommitdiffstats
path: root/crypto
diff options
context:
space:
mode:
authorMiloslav Trmač <mitr@redhat.com>2010-07-26 20:40:47 +0200
committerMiloslav Trmač <mitr@redhat.com>2010-07-26 20:40:47 +0200
commita04fd1aa4f807e2f97632a46070306e1389264ed (patch)
treefc2511add6defbbcb3f5285ef78fd0c34ccc5512 /crypto
parent16ace6317db2c47b36b08b0addfe91356151c08d (diff)
parent935be4945512eb37461a226c51ede5e8b05cbe24 (diff)
downloadkernel-crypto-a04fd1aa4f807e2f97632a46070306e1389264ed.tar.gz
kernel-crypto-a04fd1aa4f807e2f97632a46070306e1389264ed.tar.xz
kernel-crypto-a04fd1aa4f807e2f97632a46070306e1389264ed.zip
Merge branch 'standalone-master' into standalone-rename
Conflicts: crypto/userspace/ncr-data.c crypto/userspace/ncr_int.h examples/Makefile examples/ncr.c examples/pk.c examples/speed.c ncr-int.h ncr_int.h
Diffstat (limited to 'crypto')
-rw-r--r--crypto/userspace/Makefile14
-rw-r--r--crypto/userspace/cryptodev_cipher.c8
-rw-r--r--crypto/userspace/cryptodev_int.h16
-rw-r--r--crypto/userspace/cryptodev_main.c16
-rw-r--r--crypto/userspace/libtomcrypt/hashes/crypt_hash_is_valid.c4
-rw-r--r--crypto/userspace/libtomcrypt/hashes/hash_get_oid.c6
-rw-r--r--crypto/userspace/libtomcrypt/hashes/hash_memory.c16
-rw-r--r--crypto/userspace/libtomcrypt/hashes/hash_memory_multi.c16
-rw-r--r--crypto/userspace/libtomcrypt/headers/tomcrypt_hash.h10
-rw-r--r--crypto/userspace/libtomcrypt/headers/tomcrypt_pk.h26
-rw-r--r--crypto/userspace/libtomcrypt/headers/tomcrypt_pkcs.h12
-rw-r--r--crypto/userspace/libtomcrypt/pk/pkcs1/pkcs_1_mgf1.c12
-rw-r--r--crypto/userspace/libtomcrypt/pk/pkcs1/pkcs_1_oaep_decode.c18
-rw-r--r--crypto/userspace/libtomcrypt/pk/pkcs1/pkcs_1_oaep_encode.c18
-rw-r--r--crypto/userspace/libtomcrypt/pk/pkcs1/pkcs_1_pss_decode.c16
-rw-r--r--crypto/userspace/libtomcrypt/pk/pkcs1/pkcs_1_pss_encode.c16
-rw-r--r--crypto/userspace/libtomcrypt/pk/rsa/rsa_decrypt_key.c9
-rw-r--r--crypto/userspace/libtomcrypt/pk/rsa/rsa_encrypt_key.c11
-rw-r--r--crypto/userspace/libtomcrypt/pk/rsa/rsa_export.c2
-rw-r--r--crypto/userspace/libtomcrypt/pk/rsa/rsa_sign_hash.c11
-rw-r--r--crypto/userspace/libtomcrypt/pk/rsa/rsa_verify_hash.c11
-rw-r--r--crypto/userspace/ncr-data.c301
-rw-r--r--crypto/userspace/ncr-int.h (renamed from crypto/userspace/ncr_int.h)98
-rw-r--r--crypto/userspace/ncr-key-storage.c10
-rw-r--r--crypto/userspace/ncr-key-wrap.c173
-rw-r--r--crypto/userspace/ncr-key.c133
-rw-r--r--crypto/userspace/ncr-limits.c4
-rw-r--r--crypto/userspace/ncr-pk.c282
-rw-r--r--crypto/userspace/ncr-pk.h34
-rw-r--r--crypto/userspace/ncr-sessions.c954
-rw-r--r--crypto/userspace/ncr.c53
31 files changed, 1172 insertions, 1138 deletions
diff --git a/crypto/userspace/Makefile b/crypto/userspace/Makefile
index 0b031d4b533..41c82c42e6a 100644
--- a/crypto/userspace/Makefile
+++ b/crypto/userspace/Makefile
@@ -67,7 +67,7 @@ TOMCRYPT_OBJECTS = libtomcrypt/misc/zeromem.o libtomcrypt/misc/crypt/crypt_argch
libtomcrypt/pk/asn1/der/x509/der_decode_subject_public_key_info.o
cryptodev-objs = cryptodev_main.o cryptodev_cipher.o ncr.o \
- ncr-data.o ncr-key.o ncr-limits.o ncr-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)
@@ -75,22 +75,22 @@ cryptodev-objs = cryptodev_main.o cryptodev_cipher.o ncr.o \
obj-m += cryptodev.o
build:
- @make version.h
- make -C $(KERNEL_DIR) SUBDIRS=`pwd` modules
+ @$(MAKE) version.h
+ $(MAKE) -C $(KERNEL_DIR) SUBDIRS=`pwd` modules
install:
- make -C $(KERNEL_DIR) SUBDIRS=`pwd` modules_install
+ $(MAKE) -C $(KERNEL_DIR) SUBDIRS=`pwd` modules_install
@echo "Installing cryptodev.h in /usr/include/crypto ..."
@install -D cryptodev.h /usr/include/crypto/cryptodev.h
@install -D ncr.h /usr/include/crypto/ncr.h
clean:
- make -C $(KERNEL_DIR) SUBDIRS=`pwd` clean
+ $(MAKE) -C $(KERNEL_DIR) SUBDIRS=`pwd` clean
rm -f $(hostprogs)
- KERNEL_DIR=$(KERNEL_DIR) make -C examples clean
+ KERNEL_DIR=$(KERNEL_DIR) $(MAKE) -C examples clean
check:
- KERNEL_DIR=$(KERNEL_DIR) make -C examples check
+ KERNEL_DIR=$(KERNEL_DIR) $(MAKE) -C examples check
FILEBASE = cryptodev-linux-$(VERSION)
TMPDIR ?= /tmp
diff --git a/crypto/userspace/cryptodev_cipher.c b/crypto/userspace/cryptodev_cipher.c
index fa5aab28942..0dd0db77120 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 a0d30731d40..3c6eca475a2 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 0316a74dbb9..7ed09116e25 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>
#include "version.h"
@@ -65,8 +65,6 @@ module_param(enable_stats, int, 0644);
MODULE_PARM_DESC(enable_stats, "collect statictics about cryptodev usage");
#endif
-#define DEFAULT_PREALLOC_PAGES 16
-
/* ====== CryptoAPI ====== */
struct fcrypt {
struct list_head list;
@@ -138,6 +136,9 @@ crypto_create_session(struct fcrypt *fcr, struct session_op *sop)
case CRYPTO_CAMELLIA_CBC:
alg_name = "cbc(camelia)";
break;
+ case CRYPTO_AES_CTR:
+ alg_name = "ctr(aes)";
+ break;
case CRYPTO_NULL:
alg_name = "ecb(cipher_null)";
break;
@@ -495,7 +496,7 @@ __crypto_run_std(struct csession *ses_ptr, struct crypt_op *cop)
#ifndef DISABLE_ZCOPY
-static void release_user_pages(struct page **pg, int pagecount)
+void release_user_pages(struct page **pg, int pagecount)
{
while (pagecount--) {
if (!PageReserved(pg[pagecount]))
@@ -504,16 +505,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 21aabe4fccb..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/mm.h>
-#include <linux/highmem.h>
-#include "cryptodev.h"
-#include <asm/uaccess.h>
-#include <asm/ioctl.h>
-#include <linux/scatterlist.h>
-#include "ncr.h"
-#include "ncr_int.h"
-
-/* must be called with data semaphore down */
-static void _ncr_data_unlink_item(struct data_item_st *item)
-{
- list_del(&item->list);
- _ncr_data_item_put( item); /* decrement ref count */
-}
-
-void ncr_data_list_deinit(struct list_sem_st* lst)
-{
- if(lst) {
- struct data_item_st * item, *tmp;
-
- down(&lst->sem);
-
- list_for_each_entry_safe(item, tmp, &lst->list, list) {
- _ncr_data_unlink_item(item);
- }
- up(&lst->sem);
-
- }
-}
-
-/* must be called with data semaphore down
- */
-static ncr_data_t _ncr_data_get_new_desc( struct list_sem_st* lst)
-{
-struct data_item_st* item;
-int mx = 1;
-
- list_for_each_entry(item, &lst->list, list) {
- mx = max(mx, item->desc);
- }
- mx++;
-
- return mx;
-}
-
-/* returns the data item corresponding to desc */
-struct data_item_st* ncr_data_item_get( struct list_sem_st* lst, ncr_data_t desc)
-{
-struct data_item_st* item;
-
- down(&lst->sem);
- list_for_each_entry(item, &lst->list, list) {
- if (item->desc == desc) {
- atomic_inc(&item->refcnt);
- up(&lst->sem);
- return item;
- }
- }
- up(&lst->sem);
-
- err();
- return NULL;
-}
-
-static void* data_alloc(size_t size)
-{
- /* FIXME: enforce a maximum memory limit per process and per user */
- /* ncr_data_set() relies this function enforcing a reasonable upper
- limit. */
- if (size > 64*1024) {
- err();
- return NULL;
- }
- return kmalloc(size, GFP_KERNEL);
-}
-
-void _ncr_data_item_put( struct data_item_st* item)
-{
- if (atomic_dec_and_test(&item->refcnt)) {
- ncr_limits_remove(item->uid, item->pid, LIMIT_TYPE_DATA);
- kfree(item->data);
- kfree(item);
- }
-}
-
-int ncr_data_init(struct list_sem_st* lst, void __user* arg)
-{
- struct ncr_data_init_st init;
- struct data_item_st* data;
- int ret;
-
- ret = ncr_limits_add_and_check(current_euid(), task_pid_nr(current), LIMIT_TYPE_DATA);
- if (ret < 0) {
- err();
- return ret;
- }
-
- if (unlikely(copy_from_user(&init, arg, sizeof(init)))) {
- err();
- ret = -EFAULT;
- goto err_limits;
- }
-
- data = kmalloc(sizeof(*data), GFP_KERNEL);
- if (data == NULL) {
- err();
- ret = -ENOMEM;
- goto err_limits;
- }
-
- memset(data, 0, sizeof(*data));
-
- data->flags = init.flags;
- data->uid = current_euid();
- data->pid = task_pid_nr(current);
-
- atomic_set(&data->refcnt, 1);
-
- data->data = data_alloc(init.max_object_size);
- if (data->data == NULL) {
- err();
- ret = -ENOMEM;
- goto err_data;
- }
- data->max_data_size = init.max_object_size;
-
- 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 12c053afbb2..03fab19a0bd 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 69e1c50910f..a1788dc4f97 100644
--- a/crypto/userspace/ncr-key-storage.c
+++ b/crypto/userspace/ncr-key-storage.c
@@ -25,7 +25,7 @@
#include <asm/ioctl.h>
#include <linux/scatterlist.h>
#include "ncr.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 939c1367135..2edcefb78e6 100644
--- a/crypto/userspace/ncr-key-wrap.c
+++ b/crypto/userspace/ncr-key-wrap.c
@@ -27,7 +27,7 @@
#include <asm/ioctl.h>
#include <linux/scatterlist.h>
#include "ncr.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 134831e55b6..9e67b5246a7 100644
--- a/crypto/userspace/ncr-key.c
+++ b/crypto/userspace/ncr-key.c
@@ -26,7 +26,7 @@
#include <asm/ioctl.h>
#include <linux/scatterlist.h>
#include "ncr.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 746434c5d1b..7a98f3c4f38 100644
--- a/crypto/userspace/ncr-limits.c
+++ b/crypto/userspace/ncr-limits.c
@@ -29,17 +29,15 @@
#include <linux/file.h>
#include <linux/cred.h>
#include "ncr.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 b95256ddc40..ecb2ce3f5b0 100644
--- a/crypto/userspace/ncr-pk.c
+++ b/crypto/userspace/ncr-pk.c
@@ -26,7 +26,7 @@
#include <asm/ioctl.h>
#include <linux/scatterlist.h>
#include "ncr.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 68563101400..466558b7095 100644
--- a/crypto/userspace/ncr-sessions.c
+++ b/crypto/userspace/ncr-sessions.c
@@ -22,8 +22,11 @@
#include <linux/crypto.h>
#include "cryptodev.h"
#include "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 5740580ca74..1d91456af5c 100644
--- a/crypto/userspace/ncr.c
+++ b/crypto/userspace/ncr.c
@@ -30,7 +30,7 @@
#include <linux/cred.h>
#include <linux/capability.h>
#include "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;
- }
-
-}
-
-