summaryrefslogtreecommitdiffstats
path: root/crypto/userspace/ncr-pk.c
diff options
context:
space:
mode:
Diffstat (limited to 'crypto/userspace/ncr-pk.c')
-rw-r--r--crypto/userspace/ncr-pk.c348
1 files changed, 159 insertions, 189 deletions
diff --git a/crypto/userspace/ncr-pk.c b/crypto/userspace/ncr-pk.c
index 4500495430a..4b2b6aaf770 100644
--- a/crypto/userspace/ncr-pk.c
+++ b/crypto/userspace/ncr-pk.c
@@ -29,6 +29,7 @@
#include <linux/random.h>
#include <linux/uaccess.h>
#include <linux/scatterlist.h>
+#include <net/netlink.h>
#include "ncr-int.h"
#include <tomcrypt.h>
@@ -36,7 +37,7 @@ int _ncr_tomerr(int err)
{
switch (err) {
case CRYPT_BUFFER_OVERFLOW:
- return -EOVERFLOW;
+ return -ERANGE;
case CRYPT_MEM:
return -ENOMEM;
default:
@@ -122,7 +123,8 @@ 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_algo_to_properties(NCR_ALG_SHA1), tmp, max_size, private->key_id, &key_id_size);
+ cret = hash_memory(_ncr_algo_to_properties("sha1"), tmp, max_size,
+ private->key_id, &key_id_size);
if (cret != CRYPT_OK) {
err();
ret = _ncr_tomerr(cret);
@@ -166,8 +168,9 @@ int ncr_pk_pack( const struct key_item_st * key, uint8_t * packed, uint32_t * pa
}
break;
case NCR_ALG_DH:
- ret = dh_export(packed, &max_size, key->key.pk.dsa.type, (void*)&key->key.pk.dsa);
+ ret = dh_export(packed, &max_size, key->key.pk.dh.type, (void*)&key->key.pk.dh);
if (ret < 0) {
+ *packed_size = max_size;
err();
return ret;
}
@@ -221,75 +224,88 @@ int ncr_pk_unpack( struct key_item_st * key, const void * packed, size_t packed_
return 0;
}
-struct keygen_st {
-};
+static int binary_to_ulong(unsigned long *dest, const struct nlattr *nla)
+{
+ unsigned long value;
+ const uint8_t *start, *end, *p;
+
+ value = 0;
+ start = nla_data(nla);
+ end = start + nla_len(nla);
+ for (p = start; p < end; p++) {
+ if (value > (ULONG_MAX - *p) / 256)
+ return -EOVERFLOW;
+ value = value * 256 + *p;
+ }
+ *dest = value;
+ return 0;
+}
-int ncr_pk_generate(const struct algo_properties_st *algo,
- struct ncr_key_generate_params_st * params,
+int ncr_pk_generate(const struct algo_properties_st *algo, struct nlattr *tb[],
struct key_item_st* private, struct key_item_st* public)
{
+ const struct nlattr *nla;
unsigned long e;
int cret, ret;
- uint8_t * tmp = NULL;
private->algorithm = public->algorithm = algo;
ret = 0;
switch(algo->algo) {
case NCR_ALG_RSA:
- e = params->params.rsa.e;
-
- if (e == 0)
+ nla = tb[NCR_ATTR_RSA_E];
+ if (nla != NULL) {
+ ret = binary_to_ulong(&e, nla);
+ if (ret != 0)
+ break;
+ } else
e = 65537;
- cret = rsa_make_key(params->params.rsa.bits/8, e, &private->key.pk.rsa);
+
+ nla = tb[NCR_ATTR_RSA_MODULUS_BITS];
+ if (nla == NULL) {
+ ret = -EINVAL;
+ break;
+ }
+ cret = rsa_make_key(nla_get_u32(nla) / 8, e, &private->key.pk.rsa);
if (cret != CRYPT_OK) {
err();
return _ncr_tomerr(cret);
}
break;
- case NCR_ALG_DSA:
- if (params->params.dsa.q_bits==0)
- params->params.dsa.q_bits = 160;
- if (params->params.dsa.p_bits==0)
- params->params.dsa.p_bits = 1024;
+ case NCR_ALG_DSA: {
+ u32 q_bits, p_bits;
- cret = dsa_make_key(params->params.dsa.q_bits/8,
- params->params.dsa.p_bits/8, &private->key.pk.dsa);
+ nla = tb[NCR_ATTR_DSA_Q_BITS];
+ if (nla != NULL)
+ q_bits = nla_get_u32(nla);
+ else
+ q_bits = 160;
+ nla = tb[NCR_ATTR_DSA_P_BITS];
+ if (nla != NULL)
+ p_bits = nla_get_u32(nla);
+ else
+ p_bits = 1024;
+ cret = dsa_make_key(q_bits / 8, p_bits / 8,
+ &private->key.pk.dsa);
if (cret != CRYPT_OK) {
err();
return _ncr_tomerr(cret);
}
break;
+ }
case NCR_ALG_DH: {
- uint8_t * p, *g;
- size_t p_size, g_size;
-
- p_size = params->params.dh.p_size;
- g_size = params->params.dh.g_size;
-
- tmp = kmalloc(g_size+p_size, GFP_KERNEL);
- if (tmp == NULL) {
- err();
- ret = -ENOMEM;
- goto fail;
- }
-
- p = tmp;
- g = &tmp[p_size];
-
- if (unlikely(copy_from_user(p, params->params.dh.p, p_size))) {
- err();
- ret = -EFAULT;
- goto fail;
- }
+ const struct nlattr *p, *g;
- if (unlikely(copy_from_user(g, params->params.dh.g, g_size))) {
- err();
- ret = -EFAULT;
+ p = tb[NCR_ATTR_DH_PRIME];
+ g = tb[NCR_ATTR_DH_BASE];
+ if (p == NULL || g == NULL) {
+ ret = -EINVAL;
goto fail;
}
-
- ret = dh_import_params(&private->key.pk.dh, p, p_size, g, g_size);
+
+ ret = dh_import_params(&private->key.pk.dh, nla_data(p),
+ nla_len(p), nla_data(g),
+ nla_len(g));
if (ret < 0) {
err();
goto fail;
@@ -308,8 +324,6 @@ int ncr_pk_generate(const struct algo_properties_st *algo,
}
fail:
- kfree(tmp);
-
if (ret < 0) {
err();
return ret;
@@ -324,25 +338,6 @@ fail:
return 0;
}
-const struct algo_properties_st *ncr_key_params_get_sign_hash(
- const struct algo_properties_st *algo,
- struct ncr_key_params_st * params)
-{
- ncr_algorithm_t id;
-
- switch(algo->algo) {
- case NCR_ALG_RSA:
- id = params->params.rsa.sign_hash;
- break;
- case NCR_ALG_DSA:
- id = params->params.dsa.sign_hash;
- break;
- default:
- return ERR_PTR(-EINVAL);
- }
- return _ncr_algo_to_properties(id);
-}
-
/* Encryption/Decryption
*/
@@ -355,12 +350,17 @@ void ncr_pk_cipher_deinit(struct ncr_pk_ctx* ctx)
}
int ncr_pk_cipher_init(const struct algo_properties_st *algo,
- struct ncr_pk_ctx* ctx, struct ncr_key_params_st* params,
- struct key_item_st *key, const struct algo_properties_st *sign_hash)
+ struct ncr_pk_ctx* ctx, struct nlattr *tb[],
+ struct key_item_st *key,
+ const struct algo_properties_st *sign_hash)
{
+ const struct nlattr *nla;
+
memset(ctx, 0, sizeof(*ctx));
- if (key->algorithm != algo) {
+ /* Allow using the same key for transparent and non-transparent
+ hashing. */
+ if (key->algorithm->algo != algo->algo) {
err();
return -EINVAL;
}
@@ -368,26 +368,38 @@ int ncr_pk_cipher_init(const struct algo_properties_st *algo,
ctx->algorithm = algo;
ctx->key = key;
ctx->sign_hash = sign_hash;
+ ctx->salt_len = 0;
switch(algo->algo) {
case NCR_ALG_RSA:
- if (params->params.rsa.type == RSA_PKCS1_V1_5)
+ nla = tb[NCR_ATTR_RSA_ENCODING_METHOD];
+ if (nla == NULL) {
+ err();
+ return -EINVAL;
+ }
+ switch (nla_get_u32(nla)) {
+ case RSA_PKCS1_V1_5:
ctx->type = LTC_LTC_PKCS_1_V1_5;
- else if (params->params.rsa.type == RSA_PKCS1_OAEP) {
+ break;
+ case RSA_PKCS1_OAEP:
ctx->type = LTC_LTC_PKCS_1_OAEP;
- ctx->oaep_hash = _ncr_algo_to_properties(params->params.rsa.oaep_hash);
+ nla = tb[NCR_ATTR_RSA_OAEP_HASH_ALGORITHM];
+ ctx->oaep_hash = _ncr_nla_to_properties(nla);
if (ctx->oaep_hash == NULL) {
err();
return -EINVAL;
}
- } else if (params->params.rsa.type == RSA_PKCS1_PSS) {
+ break;
+ case RSA_PKCS1_PSS:
ctx->type = LTC_LTC_PKCS_1_PSS;
- } else {
+ nla = tb[NCR_ATTR_RSA_PSS_SALT_LENGTH];
+ if (nla != NULL)
+ ctx->salt_len = nla_get_u32(nla);
+ break;
+ default:
err();
return -EINVAL;
}
-
- ctx->salt_len = params->params.rsa.pss_salt;
break;
case NCR_ALG_DSA:
break;
@@ -530,30 +542,11 @@ fail:
return ret;
}
-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_sign(const struct ncr_pk_ctx *ctx, const void *hash,
+ size_t hash_size, void *sig, size_t *sig_size)
{
-int cret, ret;
-unsigned long osize = *osg_size;
-uint8_t* tmp;
-void * input, *output;
-
- tmp = kmalloc(isg_size + *osg_size, GFP_KERNEL);
- if (tmp == NULL) {
- err();
- return -ENOMEM;
- }
-
- input = tmp;
- output = &tmp[isg_size];
-
- ret = sg_copy_to_buffer((struct scatterlist*)isg, isg_cnt, input, isg_size);
- if (ret != isg_size) {
- err();
- ret = -EINVAL;
- goto fail;
- }
+ int cret;
+ unsigned long osize = *sig_size;
switch(ctx->algorithm->algo) {
case NCR_ALG_RSA:
@@ -561,63 +554,35 @@ void * input, *output;
err();
return -EINVAL;
}
- cret = rsa_sign_hash_ex( input, isg_size, output, &osize,
+ cret = rsa_sign_hash_ex(hash, hash_size, sig, &osize,
ctx->type, ctx->sign_hash, ctx->salt_len, &ctx->key->key.pk.rsa);
if (cret != CRYPT_OK) {
err();
return _ncr_tomerr(cret);
}
- *osg_size = osize;
+ *sig_size = osize;
break;
case NCR_ALG_DSA:
- cret = dsa_sign_hash( input, isg_size, output, &osize,
+ cret = dsa_sign_hash(hash, hash_size, sig, &osize,
&ctx->key->key.pk.dsa);
if (cret != CRYPT_OK) {
err();
return _ncr_tomerr(cret);
}
- *osg_size = osize;
+ *sig_size = osize;
break;
default:
err();
- ret = -EINVAL;
- goto fail;
- }
-
- ret = sg_copy_from_buffer(osg, osg_cnt, output, *osg_size);
- if (ret != *osg_size) {
- err();
- ret = -EINVAL;
- goto fail;
+ return -EINVAL;
}
- ret = 0;
-fail:
- kfree(tmp);
-
- return ret;
+ return 0;
}
-int ncr_pk_cipher_verify(const struct ncr_pk_ctx* ctx,
- 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 ncr_pk_cipher_verify(const struct ncr_pk_ctx* ctx, const void *sig,
+ size_t sig_size, const void *hash, size_t hash_size)
{
-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;
- }
+ int cret, ret, stat;
switch(ctx->algorithm->algo) {
case NCR_ALG_RSA:
@@ -625,35 +590,28 @@ uint8_t* sig;
err();
return -EINVAL;
}
- 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);
+ cret = rsa_verify_hash_ex(sig, sig_size, hash,
+ hash_size, ctx->type,
+ ctx->sign_hash, ctx->salt_len,
+ &stat, &ctx->key->key.pk.rsa);
if (cret != CRYPT_OK) {
err();
ret = _ncr_tomerr(cret);
goto fail;
}
- if (stat == 1)
- *err = 0;
- else
- *err = NCR_VERIFICATION_FAILED;
-
+ ret = (stat == 1);
break;
case NCR_ALG_DSA:
- cret = dsa_verify_hash( sig, sign_sg_size,
- hash, hash_size, &stat, &ctx->key->key.pk.dsa);
+ cret = dsa_verify_hash(sig, sig_size, hash, hash_size,
+ &stat, &ctx->key->key.pk.dsa);
if (cret != CRYPT_OK) {
err();
ret = _ncr_tomerr(cret);
goto fail;
}
- if (stat == 1)
- *err = 0;
- else
- *err = NCR_VERIFICATION_FAILED;
-
+ ret = (stat == 1);
break;
default:
err();
@@ -661,55 +619,67 @@ uint8_t* sig;
goto fail;
}
- ret = 0;
fail:
- kfree(sig);
return ret;
}
int ncr_pk_derive(struct key_item_st* newkey, struct key_item_st* oldkey,
- struct ncr_key_derivation_params_st * params)
+ struct nlattr *tb[])
{
+const struct nlattr *nla;
int ret;
-void* tmp = NULL;
-size_t size;
- switch(params->derive) {
- case NCR_DERIVE_DH:
- if (oldkey->type != NCR_KEY_TYPE_PRIVATE &&
- oldkey->algorithm->algo != NCR_ALG_DH) {
- err();
- return -EINVAL;
- }
-
- size = params->params.params.dh.pub_size;
- tmp = kmalloc(size, GFP_KERNEL);
- if (tmp == NULL) {
- err();
- return -ENOMEM;
- }
-
- if (unlikely(copy_from_user(tmp, params->params.params.dh.pub,
- size))) {
- err();
- ret = -EFAULT;
- goto fail;
- }
-
- ret = dh_derive_gxy(newkey, &oldkey->key.pk.dh, tmp, size);
- if (ret < 0) {
- err();
- goto fail;
- }
-
- break;
- default:
+ nla = tb[NCR_ATTR_DERIVATION_ALGORITHM];
+ if (nla == NULL) {
+ err();
+ return -EINVAL;
+ }
+ if (nla_strcmp(nla, NCR_DERIVE_DH) == 0) {
+ if (oldkey->type != NCR_KEY_TYPE_PRIVATE &&
+ oldkey->algorithm->algo != NCR_ALG_DH) {
+ err();
+ return -EINVAL;
+ }
+
+ nla = tb[NCR_ATTR_DH_PUBLIC];
+ if (nla == NULL) {
err();
return -EINVAL;
+ }
+ ret = dh_derive_gxy(newkey, &oldkey->key.pk.dh, nla_data(nla),
+ nla_len(nla));
+ if (ret < 0) {
+ err();
+ return ret;
+ }
+ } else {
+ err();
+ return -EINVAL;
}
- ret = 0;
-fail:
- kfree(tmp);
+ return 0;
+}
+
+int ncr_pk_get_rsa_size( rsa_key* key)
+{
+int ret;
+ ret = mp_count_bits(&key->N);
+ if (ret <= 0) {
+ err();
+ return -EINVAL;
+ }
+
+ return ret;
+}
+
+int ncr_pk_get_dsa_size( dsa_key* key)
+{
+int ret;
+ ret = mp_count_bits(&key->p);
+ if (ret <= 0) {
+ err();
+ return -EINVAL;
+ }
+
return ret;
}