summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNikos Mavrogiannopoulos <nmav@gnutls.org>2010-07-12 16:00:16 +0200
committerNikos Mavrogiannopoulos <nmav@gnutls.org>2010-07-12 16:00:16 +0200
commit111dbe139333a0fa697d7621414f1785b078468b (patch)
tree94c1ea175a395300287b0969059efaabc9383170
parent4f7b10f59b97b45d42577c4d6d33958d9565aef7 (diff)
downloadcryptodev-linux-111dbe139333a0fa697d7621414f1785b078468b.tar.gz
cryptodev-linux-111dbe139333a0fa697d7621414f1785b078468b.tar.xz
cryptodev-linux-111dbe139333a0fa697d7621414f1785b078468b.zip
Added signature generation and verification.
-rw-r--r--.gitignore6
-rw-r--r--cryptodev_cipher.c16
-rw-r--r--ncr-pk.c103
-rw-r--r--ncr-sessions.c350
-rw-r--r--ncr.h17
-rw-r--r--ncr_int.h29
6 files changed, 439 insertions, 82 deletions
diff --git a/.gitignore b/.gitignore
index 51f27fd..8c055a6 100644
--- a/.gitignore
+++ b/.gitignore
@@ -9,6 +9,10 @@ Module.symvers
modules.order
examples/cipher
examples/hmac
-examples/new
+examples/ncr
+examples/pk
releases
scripts
+userspace/ncr-setkey
+version.h
+tags
diff --git a/cryptodev_cipher.c b/cryptodev_cipher.c
index 0dd2f10..3ec5cd5 100644
--- a/cryptodev_cipher.c
+++ b/cryptodev_cipher.c
@@ -120,11 +120,13 @@ error:
void cryptodev_cipher_deinit(struct cipher_data* cdata)
{
- crypto_free_ablkcipher(cdata->async.s);
- kfree(cdata->async.result);
- ablkcipher_request_free(cdata->async.request);
+ if (cdata->init) {
+ crypto_free_ablkcipher(cdata->async.s);
+ kfree(cdata->async.result);
+ ablkcipher_request_free(cdata->async.request);
- cdata->init = 0;
+ cdata->init = 0;
+ }
}
void cryptodev_cipher_set_iv(struct cipher_data* cdata, void __user* iv, size_t iv_size)
@@ -265,8 +267,10 @@ error:
void cryptodev_hash_deinit(struct hash_data* hdata)
{
- crypto_free_ahash(hdata->async.s);
- hdata->init = 0;
+ if (hdata->init) {
+ crypto_free_ahash(hdata->async.s);
+ hdata->init = 0;
+ }
}
int cryptodev_hash_reset( struct hash_data* hdata)
diff --git a/ncr-pk.c b/ncr-pk.c
index 4cfd185..31bad73 100644
--- a/ncr-pk.c
+++ b/ncr-pk.c
@@ -306,7 +306,10 @@ void ncr_pk_queue_deinit(void)
void ncr_pk_cipher_deinit(struct ncr_pk_ctx* ctx)
{
- ctx->key = NULL;
+ if (ctx->init) {
+ ctx->init = 0;
+ ctx->key = NULL;
+ }
}
int ncr_pk_cipher_init(ncr_algorithm_t algo,
@@ -322,15 +325,19 @@ int ncr_pk_cipher_init(ncr_algorithm_t algo,
ctx->algorithm = algo;
ctx->key = key;
+ ctx->sign_hash = params->params.pk.sign_hash;
switch(algo) {
case NCR_ALG_RSA:
- if (params->params.rsa.type == RSA_PKCS1_V1_5)
+ if (params->params.pk.type == RSA_PKCS1_V1_5)
ctx->type = LTC_LTC_PKCS_1_V1_5;
- else
+ else if (params->params.pk.type == RSA_PKCS1_OAEP)
ctx->type = LTC_LTC_PKCS_1_OAEP;
+ else if (params->params.pk.type == RSA_PKCS1_PSS)
+ ctx->type = LTC_LTC_PKCS_1_PSS;
- ctx->hash = params->params.rsa.hash;
+ ctx->oaep_hash = params->params.pk.oaep_hash;
+ ctx->salt_len = params->params.pk.pss_salt;
break;
case NCR_ALG_DSA:
break;
@@ -339,6 +346,8 @@ int ncr_pk_cipher_init(ncr_algorithm_t algo,
return -EINVAL;
}
+ ctx->init = 1;
+
return 0;
}
@@ -352,7 +361,7 @@ unsigned long osize = *output_size;
switch(ctx->algorithm) {
case NCR_ALG_RSA:
cret = rsa_encrypt_key_ex( input, input_size, output, &osize,
- NULL, 0, ctx->hash, ctx->type, &ctx->key->key.pk.rsa);
+ NULL, 0, ctx->oaep_hash, ctx->type, &ctx->key->key.pk.rsa);
if (cret != CRYPT_OK) {
err();
@@ -381,7 +390,7 @@ int stat;
switch(ctx->algorithm) {
case NCR_ALG_RSA:
cret = rsa_decrypt_key_ex( input, input_size, output, &osize,
- NULL, 0, ctx->hash, ctx->type, &stat, &ctx->key->key.pk.rsa);
+ NULL, 0, ctx->oaep_hash, ctx->type, &stat, &ctx->key->key.pk.rsa);
if (cret != CRYPT_OK) {
err();
@@ -404,3 +413,85 @@ int stat;
return 0;
}
+
+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 cret;
+unsigned long osize = *output_size;
+
+ switch(ctx->algorithm) {
+ case NCR_ALG_RSA:
+ cret = rsa_sign_hash_ex( input, input_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;
+ break;
+ case NCR_ALG_DSA:
+ cret = dsa_sign_hash( input, input_size, output, &osize,
+ &ctx->key->key.pk.dsa);
+
+ if (cret != CRYPT_OK) {
+ err();
+ return tomerr(cret);
+ }
+ *output_size = osize;
+ break;
+ default:
+ err();
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+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* err)
+{
+int cret;
+int stat;
+
+ switch(ctx->algorithm) {
+ case NCR_ALG_RSA:
+ cret = rsa_verify_hash_ex( signature, signature_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);
+ }
+
+ if (stat == 1)
+ *err = 0;
+ else
+ *err = NCR_VERIFICATION_FAILED;
+
+ break;
+ case NCR_ALG_DSA:
+ cret = dsa_verify_hash( signature, signature_size,
+ hash, hash_size, &stat, &ctx->key->key.pk.dsa);
+ if (cret != CRYPT_OK) {
+ err();
+ return tomerr(cret);
+ }
+
+ if (stat == 1)
+ *err = 0;
+ else
+ *err = NCR_VERIFICATION_FAILED;
+
+ break;
+ default:
+ err();
+ return -EINVAL;
+ }
+
+ return 0;
+}
diff --git a/ncr-sessions.c b/ncr-sessions.c
index a461bf1..b61879c 100644
--- a/ncr-sessions.c
+++ b/ncr-sessions.c
@@ -110,29 +110,54 @@ struct session_item_st* ncr_session_new(struct list_sem_st* lst)
static const struct algo_properties_st {
ncr_algorithm_t algo;
const char* kstr;
- int needs_iv;
+ int needs_iv:1;
+ int hmac:1;
+ int can_sign:1;
+ int can_digest:1;
+ int can_encrypt:1;
+ int symmetric:1;
int digest_size;
} algo_properties[] = {
- { .algo = NCR_ALG_3DES_CBC, .kstr = "cbc(des3_ede)", .needs_iv = 1 },
- { .algo = NCR_ALG_AES_CBC, .kstr = "cbc(aes)", .needs_iv = 1 },
- { .algo = NCR_ALG_CAMELLIA_CBC, .kstr = "ecb(camelia)", .needs_iv = 1 },
- { .algo = NCR_ALG_ARCFOUR, .kstr = NULL, .needs_iv = 0 },
- { .algo = NCR_ALG_AES_ECB, .kstr = "ecb(aes)", .needs_iv = 0 },
- { .algo = NCR_ALG_SHA1, .kstr = "sha1", .needs_iv = 0, .digest_size = 20 },
- { .algo = NCR_ALG_MD5, .kstr = "md5", .needs_iv = 0, .digest_size = 16 },
- { .algo = NCR_ALG_SHA2_224, .kstr = "sha224", .needs_iv = 0, .digest_size = 28 },
- { .algo = NCR_ALG_SHA2_256, .kstr = "sha256", .needs_iv = 0, .digest_size = 32 },
- { .algo = NCR_ALG_SHA2_384, .kstr = "sha384", .needs_iv = 0, .digest_size = 48 },
- { .algo = NCR_ALG_SHA2_512, .kstr = "sha512", .needs_iv = 0, .digest_size = 64 },
- { .algo = NCR_ALG_HMAC_SHA1, .kstr = "hmac(sha1)", .needs_iv = 0, .digest_size = 20 },
- { .algo = NCR_ALG_HMAC_MD5, .kstr = "hmac(md5)", .needs_iv = 0, .digest_size = 16 },
- { .algo = NCR_ALG_HMAC_SHA2_224, .kstr = "hmac(sha224)", .needs_iv = 0, .digest_size = 28 },
- { .algo = NCR_ALG_HMAC_SHA2_256, .kstr = "hmac(sha256)", .needs_iv = 0, .digest_size = 32 },
- { .algo = NCR_ALG_HMAC_SHA2_384, .kstr = "hmac(sha384)", .needs_iv = 0, .digest_size = 48 },
- { .algo = NCR_ALG_HMAC_SHA2_512, .kstr = "hmac(sha512)", .needs_iv = 0, .digest_size = 64 },
- { .algo = NCR_ALG_RSA, .kstr = NULL, .needs_iv = 0 },
- { .algo = NCR_ALG_DSA, .kstr = NULL, .needs_iv = 0 },
+ { .algo = NCR_ALG_3DES_CBC, .kstr = "cbc(des3_ede)",
+ .needs_iv = 1, .symmetric=1, .can_encrypt=1 },
+ { .algo = NCR_ALG_AES_CBC, .kstr = "cbc(aes)",
+ .needs_iv = 1, .symmetric=1, .can_encrypt=1 },
+ { .algo = NCR_ALG_CAMELLIA_CBC, .kstr = "ecb(camelia)",
+ .needs_iv = 1, .symmetric=1, .can_encrypt=1 },
+ { .algo = NCR_ALG_ARCFOUR, .kstr = NULL,
+ .needs_iv = 0, .symmetric=1, .can_encrypt=1 },
+ { .algo = NCR_ALG_AES_ECB, .kstr = "ecb(aes)",
+ .needs_iv = 0, .symmetric=1, .can_encrypt=1 },
+ { .algo = NCR_ALG_SHA1, .kstr = "sha1",
+ .digest_size = 20, .can_digest=1 },
+ { .algo = NCR_ALG_MD5, .kstr = "md5",
+ .digest_size = 16, .can_digest=1 },
+ { .algo = NCR_ALG_SHA2_224, .kstr = "sha224",
+ .digest_size = 28, .can_digest=1 },
+ { .algo = NCR_ALG_SHA2_256, .kstr = "sha256",
+ .digest_size = 32, .can_digest=1 },
+ { .algo = NCR_ALG_SHA2_384, .kstr = "sha384",
+ .digest_size = 48, .can_digest=1 },
+ { .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 },
{ .algo = NCR_ALG_NONE }
+
};
const char* _ncr_algo_to_str(ncr_algorithm_t algo)
@@ -163,6 +188,77 @@ int i = 0;
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;
@@ -186,7 +282,7 @@ static int _ncr_session_init(struct ncr_lists* lists, struct ncr_session_st* ses
str = _ncr_algo_to_str(session->algorithm);
if (str == NULL) {
err();
- return NCR_SESSION_INVALID;
+ return -EINVAL;
}
ns = ncr_session_new(&lists->sessions);
@@ -196,10 +292,16 @@ static int _ncr_session_init(struct ncr_lists* lists, struct ncr_session_st* ses
}
ns->op = session->op;
- ns->algo = session->algorithm;
+ ns->algorithm = session->algorithm;
switch(session->op) {
case NCR_OP_ENCRYPT:
case NCR_OP_DECRYPT:
+ if (algo_can_encrypt(session->algorithm)==0) {
+ err();
+ ret = -EINVAL;
+ goto fail;
+ }
+
/* read key */
ret = ncr_key_item_get_read( &ns->key, &lists->key, session->params.key);
if (ret < 0) {
@@ -208,7 +310,7 @@ static int _ncr_session_init(struct ncr_lists* lists, struct ncr_session_st* ses
}
if (ns->key->type == NCR_KEY_TYPE_SECRET) {
- ret = cryptodev_cipher_init(&ns->ctx.cipher, str,
+ ret = cryptodev_cipher_init(&ns->cipher, str,
ns->key->key.secret.data, ns->key->key.secret.size);
if (ret < 0) {
err();
@@ -221,10 +323,10 @@ static int _ncr_session_init(struct ncr_lists* lists, struct ncr_session_st* ses
ret = -EINVAL;
goto fail;
}
- cryptodev_cipher_set_iv(&ns->ctx.cipher, session->params.params.cipher.iv, session->params.params.cipher.iv_size);
+ cryptodev_cipher_set_iv(&ns->cipher, session->params.params.cipher.iv, session->params.params.cipher.iv_size);
}
} else if (ns->key->type == NCR_KEY_TYPE_PRIVATE || ns->key->type == NCR_KEY_TYPE_PUBLIC) {
- ret = ncr_pk_cipher_init(ns->algo, &ns->ctx.pk,
+ ret = ncr_pk_cipher_init(ns->algorithm, &ns->pk,
&session->params, ns->key);
if (ret < 0) {
err();
@@ -237,7 +339,14 @@ static int _ncr_session_init(struct ncr_lists* lists, struct ncr_session_st* ses
}
break;
- case NCR_OP_MAC:
+ case NCR_OP_SIGN:
+ case NCR_OP_VERIFY:
+ if (algo_can_sign(session->algorithm)==0) {
+ err();
+ ret = -EINVAL;
+ goto fail;
+ }
+
/* read key */
ret = ncr_key_item_get_read( &ns->key, &lists->key, session->params.key);
if (ret < 0) {
@@ -245,33 +354,61 @@ static int _ncr_session_init(struct ncr_lists* lists, struct ncr_session_st* ses
goto fail;
}
- if (ns->key->type != NCR_KEY_TYPE_SECRET) {
+ if (ns->key->type == NCR_KEY_TYPE_SECRET) {
+ ret = cryptodev_hash_init(&ns->hash, str, 1,
+ ns->key->key.secret.data, ns->key->key.secret.size);
+ if (ret < 0) {
+ err();
+ goto fail;
+ }
+
+ } else if (ns->key->type == NCR_KEY_TYPE_PRIVATE || ns->key->type == NCR_KEY_TYPE_PUBLIC) {
+ str = _ncr_algo_to_str(session->params.params.pk.sign_hash);
+ if (str == NULL) {
+ err();
+ ret = -EINVAL;
+ goto fail;
+ }
+
+ ret = ncr_pk_cipher_init(ns->algorithm, &ns->pk,
+ &session->params, ns->key);
+ if (ret < 0) {
+ err();
+ goto fail;
+ }
+
+ ret = cryptodev_hash_init(&ns->hash, str, 0, NULL, 0);
+ if (ret < 0) {
+ err();
+ goto fail;
+ }
+ } else {
err();
ret = -EINVAL;
goto fail;
}
- ret = cryptodev_hash_init(&ns->ctx.hash, str, 1, ns->key->key.secret.data, ns->key->key.secret.size);
+ ret = cryptodev_hash_reset(&ns->hash);
if (ret < 0) {
err();
goto fail;
}
- ret = cryptodev_hash_reset(&ns->ctx.hash);
- if (ret < 0) {
+ break;
+ case NCR_OP_DIGEST:
+ if (algo_can_digest(session->algorithm)==0) {
err();
+ ret = -EINVAL;
goto fail;
}
- break;
- case NCR_OP_DIGEST:
- ret = cryptodev_hash_init(&ns->ctx.hash, str, 0, NULL, 0);
+ ret = cryptodev_hash_init(&ns->hash, str, 0, NULL, 0);
if (ret < 0) {
err();
goto fail;
}
- ret = cryptodev_hash_reset(&ns->ctx.hash);
+ ret = cryptodev_hash_reset(&ns->hash);
if (ret < 0) {
err();
goto fail;
@@ -290,10 +427,10 @@ static int _ncr_session_init(struct ncr_lists* lists, struct ncr_session_st* ses
fail:
if (ret < 0) {
if (ns->key) _ncr_key_item_put(ns->key);
- if (ns->ctx.cipher.init)
- cryptodev_cipher_deinit(&ns->ctx.cipher);
- if (ns->ctx.hash.init)
- cryptodev_hash_deinit(&ns->ctx.hash);
+
+ ncr_pk_cipher_deinit(&ns->pk);
+ cryptodev_cipher_deinit(&ns->cipher);
+ cryptodev_hash_deinit(&ns->hash);
_ncr_session_remove(&lists->sessions, ns->desc);
}
@@ -320,6 +457,8 @@ int ncr_session_init(struct ncr_lists* lists, void __user* arg)
return copy_to_user( arg, &session, sizeof(session));
}
+/* Main update function
+ */
static int _ncr_session_update(struct ncr_lists* lists, struct ncr_session_op_st* op)
{
struct key_item_st *key = NULL;
@@ -357,15 +496,28 @@ static int _ncr_session_update(struct ncr_lists* lists, struct ncr_session_op_st
goto fail;
}
- /* read key */
- ret = _cryptodev_cipher_encrypt(&sess->ctx.cipher, data->data, data->data_size, odata->data, data->data_size);
- if (ret < 0) {
- err();
- goto fail;
+ 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;
+ }
}
- /* FIXME: handle ciphers that do not require that */
- odata->data_size = data->data_size;
-
break;
case NCR_OP_DECRYPT:
/* obtain data item */
@@ -390,7 +542,7 @@ static int _ncr_session_update(struct ncr_lists* lists, struct ncr_session_op_st
}
/* read key */
- ret = _cryptodev_cipher_decrypt(&sess->ctx.cipher, data->data, data->data_size, odata->data, data->data_size);
+ ret = _cryptodev_cipher_decrypt(&sess->cipher, data->data, data->data_size, odata->data, data->data_size);
if (ret < 0) {
err();
goto fail;
@@ -400,7 +552,7 @@ static int _ncr_session_update(struct ncr_lists* lists, struct ncr_session_op_st
break;
- case NCR_OP_MAC:
+ case NCR_OP_SIGN:
case NCR_OP_DIGEST:
/* obtain data item */
data = ncr_data_item_get( &lists->data, op->data.digest.text);
@@ -410,12 +562,29 @@ static int _ncr_session_update(struct ncr_lists* lists, struct ncr_session_op_st
goto fail;
}
- ret = _cryptodev_hash_update(&sess->ctx.hash, data->data, data->data_size);
+ 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);
if (ret < 0) {
err();
goto fail;
}
break;
+
default:
err();
ret = -EINVAL;
@@ -474,6 +643,7 @@ static int _ncr_session_final(struct ncr_lists* lists, struct ncr_session_op_st*
struct data_item_st* data = NULL;
struct data_item_st* odata = NULL;
int digest_size;
+ uint8_t digest[NCR_HASH_MAX_OUTPUT_SIZE];
sess = ncr_sessions_item_get( &lists->sessions, op->ses);
if (sess == NULL) {
@@ -489,9 +659,60 @@ static int _ncr_session_final(struct ncr_lists* lists, struct ncr_session_op_st*
op->data.cipher.ciphertext != NCR_DATA_INVALID) {
_ncr_session_update(lists, op);
}
- cryptodev_cipher_deinit(&sess->ctx.cipher);
+
+ if (algo_is_symmetric(sess->algorithm)) {
+ cryptodev_cipher_deinit(&sess->cipher);
+ } else {
+ ncr_pk_cipher_deinit(&sess->pk);
+ }
+ break;
+
+ case NCR_OP_VERIFY:
+ /* obtain data item */
+ if (op->data.digest.text != NCR_DATA_INVALID) {
+ _ncr_session_update(lists, op);
+ }
+
+ odata = ncr_data_item_get( &lists->data, op->data.verify.signature);
+ if (odata == NULL) {
+ err();
+ ret = -EINVAL;
+ goto fail;
+ }
+
+ digest_size = _ncr_algo_digest_size(sess->algorithm);
+ if (digest_size == 0 || sizeof(digest) < digest_size) {
+ err();
+ ret = -EINVAL;
+ goto fail;
+ }
+ ret = cryptodev_hash_final(&sess->hash, digest);
+ odata->data_size = digest_size;
+
+ cryptodev_hash_deinit(&sess->hash);
+
+ if (algo_is_hmac(sess->algorithm)) {
+ if (digest_size != odata->data_size ||
+ memcmp(odata->data, digest, digest_size) != 0) {
+
+ op->err = NCR_VERIFICATION_FAILED;
+ } else {
+ op->err = NCR_SUCCESS;
+ }
+ } else {
+ /* PK signature */
+ ret = ncr_pk_cipher_verify(&sess->pk, odata->data, odata->data_size,
+ digest, digest_size, &op->err);
+ if (ret < 0) {
+ err();
+ goto fail;
+ }
+
+ ncr_pk_cipher_deinit(&sess->pk);
+ }
break;
- case NCR_OP_MAC:
+
+ case NCR_OP_SIGN:
case NCR_OP_DIGEST:
/* obtain data item */
if (op->data.digest.text != NCR_DATA_INVALID) {
@@ -504,16 +725,29 @@ static int _ncr_session_final(struct ncr_lists* lists, struct ncr_session_op_st*
goto fail;
}
- digest_size = _ncr_algo_digest_size(sess->algo);
+ digest_size = _ncr_algo_digest_size(sess->algorithm);
if (digest_size == 0 || odata->max_data_size < digest_size) {
err();
ret = -EINVAL;
goto fail;
}
- ret = cryptodev_hash_final(&sess->ctx.hash, odata->data);
+ ret = cryptodev_hash_final(&sess->hash, odata->data);
odata->data_size = digest_size;
- cryptodev_hash_deinit(&sess->ctx.hash);
+ cryptodev_hash_deinit(&sess->hash);
+
+ if (sess->op != NCR_OP_DIGEST && !algo_is_hmac(sess->algorithm)) {
+ /* 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);
+ if (ret < 0) {
+ err();
+ goto fail;
+ }
+
+ ncr_pk_cipher_deinit(&sess->pk);
+ }
break;
default:
err();
@@ -543,7 +777,13 @@ int ncr_session_final(struct ncr_lists* lists, void __user* arg)
return ret;
}
- return _ncr_session_final(lists, &op);
+ ret = _ncr_session_final(lists, &op);
+ if (unlikely(ret)) {
+ err();
+ return ret;
+ }
+
+ return copy_to_user(arg, &op, sizeof(op));
}
int ncr_session_once(struct ncr_lists* lists, void __user* arg)
diff --git a/ncr.h b/ncr.h
index 49d32a6..0576c62 100644
--- a/ncr.h
+++ b/ncr.h
@@ -128,8 +128,9 @@ struct ncr_key_generate_st {
};
typedef enum {
- RSA_PKCS1_V1_5,
- RSA_PKCS1_OAEP,
+ RSA_PKCS1_V1_5, /* both signatures and encryption */
+ RSA_PKCS1_OAEP, /* for encryption only */
+ RSA_PKCS1_PSS, /* for signatures only */
} ncr_rsa_type_t;
/* used in derivation/encryption
@@ -148,8 +149,10 @@ struct ncr_key_params_st {
} dh;
struct {
ncr_rsa_type_t type;
- ncr_algorithm_t hash; /* for OAEP */
- } rsa;
+ ncr_algorithm_t oaep_hash; /* for OAEP */
+ ncr_algorithm_t sign_hash; /* for signatures */
+ unsigned int pss_salt; /* PSS signatures */
+ } pk;
} params;
};
@@ -237,7 +240,6 @@ typedef enum {
NCR_OP_ENCRYPT=1,
NCR_OP_DECRYPT,
NCR_OP_DIGEST,
- NCR_OP_MAC,
NCR_OP_SIGN,
NCR_OP_VERIFY,
} ncr_crypto_op_t;
@@ -259,6 +261,7 @@ struct ncr_session_st {
typedef enum {
NCR_SUCCESS = 0,
NCR_ERROR_GENERIC = -1,
+ NCR_VERIFICATION_FAILED = -2,
} ncr_error_t;
struct ncr_session_op_st {
@@ -277,10 +280,10 @@ struct ncr_session_op_st {
struct {
ncr_data_t text;
ncr_data_t signature;
- } verify; /* mac/hash/sign */
+ } verify; /* mac/sign */
} data;
- /* output */
+ /* output of verification */
ncr_error_t err;
};
diff --git a/ncr_int.h b/ncr_int.h
index 49373ca..293e833 100644
--- a/ncr_int.h
+++ b/ncr_int.h
@@ -12,8 +12,14 @@
struct ncr_pk_ctx {
ncr_algorithm_t algorithm; /* algorithm */
- ncr_algorithm_t hash; /* if hash is required is of this type */
+
+ ncr_algorithm_t sign_hash; /* for verification */
+
+ ncr_algorithm_t oaep_hash;
+ int salt_len; /* for RSA-PSS signatures */
+
int type; /* libtomcrypt type */
+ int init; /* non zero if initialized */
struct key_item_st * key;
};
@@ -21,13 +27,16 @@ struct ncr_pk_ctx {
struct session_item_st {
struct list_head list;
- ncr_algorithm_t algo;
+ ncr_algorithm_t algorithm;
ncr_crypto_op_t op;
- union {
- struct cipher_data cipher;
- struct hash_data hash;
- struct ncr_pk_ctx pk;
- } ctx;
+
+ /* contexts for various options.
+ * simpler to have them like that than
+ * in a union.
+ */
+ struct cipher_data cipher;
+ struct ncr_pk_ctx pk;
+ struct hash_data hash;
struct key_item_st* key;
@@ -220,6 +229,12 @@ 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_verify(const struct ncr_pk_ctx* ctx,
+ const void* signature, size_t signature_size,
+ const void* hash, size_t hash_size, ncr_error_t*);