Skip to content

Commit

Permalink
crypto: akcipher - Changes to asymmetric key API
Browse files Browse the repository at this point in the history
Setkey function has been split into set_priv_key and set_pub_key.
Akcipher requests takes sgl for src and dst instead of void *.
Users of the API i.e. two existing RSA implementation and
test mgr code have been updated accordingly.

Signed-off-by: Tadeusz Struk <[email protected]>
Signed-off-by: Herbert Xu <[email protected]>
  • Loading branch information
tstruk authored and herbertx committed Oct 14, 2015
1 parent 2d4d1ee commit 22287b0
Show file tree
Hide file tree
Showing 15 changed files with 407 additions and 164 deletions.
9 changes: 6 additions & 3 deletions crypto/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,13 @@ obj-$(CONFIG_CRYPTO_HASH2) += crypto_hash.o
obj-$(CONFIG_CRYPTO_PCOMP2) += pcompress.o
obj-$(CONFIG_CRYPTO_AKCIPHER2) += akcipher.o

$(obj)/rsakey-asn1.o: $(obj)/rsakey-asn1.c $(obj)/rsakey-asn1.h
clean-files += rsakey-asn1.c rsakey-asn1.h
$(obj)/rsapubkey-asn1.o: $(obj)/rsapubkey-asn1.c $(obj)/rsapubkey-asn1.h
$(obj)/rsaprivkey-asn1.o: $(obj)/rsaprivkey-asn1.c $(obj)/rsaprivkey-asn1.h
clean-files += rsapubkey-asn1.c rsapubkey-asn1.h
clean-files += rsaprivkey-asn1.c rsaprivkey-asn1.h

rsa_generic-y := rsakey-asn1.o
rsa_generic-y := rsapubkey-asn1.o
rsa_generic-y += rsaprivkey-asn1.o
rsa_generic-y += rsa.o
rsa_generic-y += rsa_helper.o
obj-$(CONFIG_CRYPTO_RSA) += rsa_generic.o
Expand Down
83 changes: 49 additions & 34 deletions crypto/rsa.c
Original file line number Diff line number Diff line change
Expand Up @@ -97,24 +97,21 @@ static int rsa_enc(struct akcipher_request *req)
goto err_free_c;
}

m = mpi_read_raw_data(req->src, req->src_len);
if (!m) {
ret = -ENOMEM;
ret = -ENOMEM;
m = mpi_read_raw_from_sgl(req->src, req->src_len);
if (!m)
goto err_free_c;
}

ret = _rsa_enc(pkey, c, m);
if (ret)
goto err_free_m;

ret = mpi_read_buffer(c, req->dst, req->dst_len, &req->dst_len, &sign);
ret = mpi_write_to_sgl(c, req->dst, &req->dst_len, &sign);
if (ret)
goto err_free_m;

if (sign < 0) {
if (sign < 0)
ret = -EBADMSG;
goto err_free_m;
}

err_free_m:
mpi_free(m);
Expand Down Expand Up @@ -145,25 +142,21 @@ static int rsa_dec(struct akcipher_request *req)
goto err_free_m;
}

c = mpi_read_raw_data(req->src, req->src_len);
if (!c) {
ret = -ENOMEM;
ret = -ENOMEM;
c = mpi_read_raw_from_sgl(req->src, req->src_len);
if (!c)
goto err_free_m;
}

ret = _rsa_dec(pkey, m, c);
if (ret)
goto err_free_c;

ret = mpi_read_buffer(m, req->dst, req->dst_len, &req->dst_len, &sign);
ret = mpi_write_to_sgl(m, req->dst, &req->dst_len, &sign);
if (ret)
goto err_free_c;

if (sign < 0) {
if (sign < 0)
ret = -EBADMSG;
goto err_free_c;
}

err_free_c:
mpi_free(c);
err_free_m:
Expand Down Expand Up @@ -193,24 +186,21 @@ static int rsa_sign(struct akcipher_request *req)
goto err_free_s;
}

m = mpi_read_raw_data(req->src, req->src_len);
if (!m) {
ret = -ENOMEM;
ret = -ENOMEM;
m = mpi_read_raw_from_sgl(req->src, req->src_len);
if (!m)
goto err_free_s;
}

ret = _rsa_sign(pkey, s, m);
if (ret)
goto err_free_m;

ret = mpi_read_buffer(s, req->dst, req->dst_len, &req->dst_len, &sign);
ret = mpi_write_to_sgl(s, req->dst, &req->dst_len, &sign);
if (ret)
goto err_free_m;

if (sign < 0) {
if (sign < 0)
ret = -EBADMSG;
goto err_free_m;
}

err_free_m:
mpi_free(m);
Expand Down Expand Up @@ -241,7 +231,8 @@ static int rsa_verify(struct akcipher_request *req)
goto err_free_m;
}

s = mpi_read_raw_data(req->src, req->src_len);
ret = -ENOMEM;
s = mpi_read_raw_from_sgl(req->src, req->src_len);
if (!s) {
ret = -ENOMEM;
goto err_free_m;
Expand All @@ -251,14 +242,12 @@ static int rsa_verify(struct akcipher_request *req)
if (ret)
goto err_free_s;

ret = mpi_read_buffer(m, req->dst, req->dst_len, &req->dst_len, &sign);
ret = mpi_write_to_sgl(m, req->dst, &req->dst_len, &sign);
if (ret)
goto err_free_s;

if (sign < 0) {
if (sign < 0)
ret = -EBADMSG;
goto err_free_s;
}

err_free_s:
mpi_free(s);
Expand All @@ -282,13 +271,13 @@ static int rsa_check_key_length(unsigned int len)
return -EINVAL;
}

static int rsa_setkey(struct crypto_akcipher *tfm, const void *key,
unsigned int keylen)
static int rsa_set_pub_key(struct crypto_akcipher *tfm, const void *key,
unsigned int keylen)
{
struct rsa_key *pkey = akcipher_tfm_ctx(tfm);
int ret;

ret = rsa_parse_key(pkey, key, keylen);
ret = rsa_parse_pub_key(pkey, key, keylen);
if (ret)
return ret;

Expand All @@ -299,6 +288,30 @@ static int rsa_setkey(struct crypto_akcipher *tfm, const void *key,
return ret;
}

static int rsa_set_priv_key(struct crypto_akcipher *tfm, const void *key,
unsigned int keylen)
{
struct rsa_key *pkey = akcipher_tfm_ctx(tfm);
int ret;

ret = rsa_parse_priv_key(pkey, key, keylen);
if (ret)
return ret;

if (rsa_check_key_length(mpi_get_size(pkey->n) << 3)) {
rsa_free_key(pkey);
ret = -EINVAL;
}
return ret;
}

static int rsa_max_size(struct crypto_akcipher *tfm)
{
struct rsa_key *pkey = akcipher_tfm_ctx(tfm);

return pkey->n ? mpi_get_size(pkey->n) : -EINVAL;
}

static void rsa_exit_tfm(struct crypto_akcipher *tfm)
{
struct rsa_key *pkey = akcipher_tfm_ctx(tfm);
Expand All @@ -311,7 +324,9 @@ static struct akcipher_alg rsa = {
.decrypt = rsa_dec,
.sign = rsa_sign,
.verify = rsa_verify,
.setkey = rsa_setkey,
.set_priv_key = rsa_set_priv_key,
.set_pub_key = rsa_set_pub_key,
.max_size = rsa_max_size,
.exit = rsa_exit_tfm,
.base = {
.cra_name = "rsa",
Expand Down
42 changes: 35 additions & 7 deletions crypto/rsa_helper.c
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@
#include <linux/err.h>
#include <linux/fips.h>
#include <crypto/internal/rsa.h>
#include "rsakey-asn1.h"
#include "rsapubkey-asn1.h"
#include "rsaprivkey-asn1.h"

int rsa_get_n(void *context, size_t hdrlen, unsigned char tag,
const void *value, size_t vlen)
Expand Down Expand Up @@ -94,22 +95,22 @@ void rsa_free_key(struct rsa_key *key)
EXPORT_SYMBOL_GPL(rsa_free_key);

/**
* rsa_parse_key() - extracts an rsa key from BER encoded buffer
* and stores it in the provided struct rsa_key
* rsa_parse_pub_key() - extracts an rsa public key from BER encoded buffer
* and stores it in the provided struct rsa_key
*
* @rsa_key: struct rsa_key key representation
* @key: key in BER format
* @key_len: length of key
*
* Return: 0 on success or error code in case of error
*/
int rsa_parse_key(struct rsa_key *rsa_key, const void *key,
unsigned int key_len)
int rsa_parse_pub_key(struct rsa_key *rsa_key, const void *key,
unsigned int key_len)
{
int ret;

free_mpis(rsa_key);
ret = asn1_ber_decoder(&rsakey_decoder, rsa_key, key, key_len);
ret = asn1_ber_decoder(&rsapubkey_decoder, rsa_key, key, key_len);
if (ret < 0)
goto error;

Expand All @@ -118,4 +119,31 @@ int rsa_parse_key(struct rsa_key *rsa_key, const void *key,
free_mpis(rsa_key);
return ret;
}
EXPORT_SYMBOL_GPL(rsa_parse_key);
EXPORT_SYMBOL_GPL(rsa_parse_pub_key);

/**
* rsa_parse_pub_key() - extracts an rsa private key from BER encoded buffer
* and stores it in the provided struct rsa_key
*
* @rsa_key: struct rsa_key key representation
* @key: key in BER format
* @key_len: length of key
*
* Return: 0 on success or error code in case of error
*/
int rsa_parse_priv_key(struct rsa_key *rsa_key, const void *key,
unsigned int key_len)
{
int ret;

free_mpis(rsa_key);
ret = asn1_ber_decoder(&rsaprivkey_decoder, rsa_key, key, key_len);
if (ret < 0)
goto error;

return 0;
error:
free_mpis(rsa_key);
return ret;
}
EXPORT_SYMBOL_GPL(rsa_parse_priv_key);
5 changes: 0 additions & 5 deletions crypto/rsakey.asn1

This file was deleted.

11 changes: 11 additions & 0 deletions crypto/rsaprivkey.asn1
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
RsaPrivKey ::= SEQUENCE {
version INTEGER,
n INTEGER ({ rsa_get_n }),
e INTEGER ({ rsa_get_e }),
d INTEGER ({ rsa_get_d }),
prime1 INTEGER,
prime2 INTEGER,
exponent1 INTEGER,
exponent2 INTEGER,
coefficient INTEGER
}
4 changes: 4 additions & 0 deletions crypto/rsapubkey.asn1
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
RsaPubKey ::= SEQUENCE {
n INTEGER ({ rsa_get_n }),
e INTEGER ({ rsa_get_e })
}
39 changes: 20 additions & 19 deletions crypto/testmgr.c
Original file line number Diff line number Diff line change
Expand Up @@ -1845,34 +1845,34 @@ static int do_test_rsa(struct crypto_akcipher *tfm,
struct tcrypt_result result;
unsigned int out_len_max, out_len = 0;
int err = -ENOMEM;
struct scatterlist src, dst, src_tab[2];

req = akcipher_request_alloc(tfm, GFP_KERNEL);
if (!req)
return err;

init_completion(&result.completion);
err = crypto_akcipher_setkey(tfm, vecs->key, vecs->key_len);
if (err)
goto free_req;

akcipher_request_set_crypt(req, vecs->m, outbuf_enc, vecs->m_size,
out_len);
/* expect this to fail, and update the required buf len */
crypto_akcipher_encrypt(req);
out_len = req->dst_len;
if (!out_len) {
err = -EINVAL;
if (vecs->public_key_vec)
err = crypto_akcipher_set_pub_key(tfm, vecs->key,
vecs->key_len);
else
err = crypto_akcipher_set_priv_key(tfm, vecs->key,
vecs->key_len);
if (err)
goto free_req;
}

out_len_max = out_len;
err = -ENOMEM;
out_len_max = crypto_akcipher_maxsize(tfm);
outbuf_enc = kzalloc(out_len_max, GFP_KERNEL);
if (!outbuf_enc)
goto free_req;

akcipher_request_set_crypt(req, vecs->m, outbuf_enc, vecs->m_size,
out_len);
sg_init_table(src_tab, 2);
sg_set_buf(&src_tab[0], vecs->m, 8);
sg_set_buf(&src_tab[1], vecs->m + 8, vecs->m_size - 8);
sg_init_one(&dst, outbuf_enc, out_len_max);
akcipher_request_set_crypt(req, src_tab, &dst, vecs->m_size,
out_len_max);
akcipher_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG,
tcrypt_complete, &result);

Expand All @@ -1882,13 +1882,13 @@ static int do_test_rsa(struct crypto_akcipher *tfm,
pr_err("alg: rsa: encrypt test failed. err %d\n", err);
goto free_all;
}
if (out_len != vecs->c_size) {
if (req->dst_len != vecs->c_size) {
pr_err("alg: rsa: encrypt test failed. Invalid output len\n");
err = -EINVAL;
goto free_all;
}
/* verify that encrypted message is equal to expected */
if (memcmp(vecs->c, outbuf_enc, vecs->c_size)) {
if (memcmp(vecs->c, sg_virt(req->dst), vecs->c_size)) {
pr_err("alg: rsa: encrypt test failed. Invalid output\n");
err = -EINVAL;
goto free_all;
Expand All @@ -1903,9 +1903,10 @@ static int do_test_rsa(struct crypto_akcipher *tfm,
err = -ENOMEM;
goto free_all;
}
sg_init_one(&src, vecs->c, vecs->c_size);
sg_init_one(&dst, outbuf_dec, out_len_max);
init_completion(&result.completion);
akcipher_request_set_crypt(req, outbuf_enc, outbuf_dec, vecs->c_size,
out_len);
akcipher_request_set_crypt(req, &src, &dst, vecs->c_size, out_len_max);

/* Run RSA decrypt - m = c^d mod n;*/
err = wait_async_op(&result, crypto_akcipher_decrypt(req));
Expand Down
Loading

0 comments on commit 22287b0

Please sign in to comment.