diff options
author | Miloslav Trmač <mitr@redhat.com> | 2010-08-27 09:31:07 +0200 |
---|---|---|
committer | Miloslav Trmač <mitr@redhat.com> | 2010-08-27 09:31:07 +0200 |
commit | 3d758323280763fe59b1f61d4f86aa2a29fe3775 (patch) | |
tree | f195a8cb4aa2ff6fbb5a51e0e6c13df1968401b6 /ncr-pk.c | |
parent | 40b5088d61e6f0830302b253ad407d06e46364b6 (diff) | |
parent | dd5317620d70e6b438e40370163257e47ca385a3 (diff) | |
download | kernel-crypto-3d758323280763fe59b1f61d4f86aa2a29fe3775.tar.gz kernel-crypto-3d758323280763fe59b1f61d4f86aa2a29fe3775.tar.xz kernel-crypto-3d758323280763fe59b1f61d4f86aa2a29fe3775.zip |
Merge remote branch 'standalone/master' into standalone-master
Conflicts:
cryptodev_main.c
ncr-int.h
ncr.c
Diffstat (limited to 'ncr-pk.c')
-rw-r--r-- | ncr-pk.c | 349 |
1 files changed, 159 insertions, 190 deletions
@@ -27,8 +27,8 @@ #include <linux/slab.h> #include <linux/random.h> #include <linux/uaccess.h> -#include "cryptodev.h" #include <linux/scatterlist.h> +#include <net/netlink.h> #include "ncr.h" #include "ncr-int.h" #include <tomcrypt.h> @@ -37,7 +37,7 @@ int _ncr_tomerr(int err) { switch (err) { case CRYPT_BUFFER_OVERFLOW: - return -EOVERFLOW; + return -ERANGE; case CRYPT_MEM: return -ENOMEM; default: @@ -123,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); @@ -167,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; } @@ -222,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; @@ -309,8 +324,6 @@ int ncr_pk_generate(const struct algo_properties_st *algo, } fail: - kfree(tmp); - if (ret < 0) { err(); return ret; @@ -325,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 */ @@ -356,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; } @@ -369,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; @@ -531,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: @@ -562,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: @@ -626,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(); @@ -662,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; } |