From 111dbe139333a0fa697d7621414f1785b078468b Mon Sep 17 00:00:00 2001 From: Nikos Mavrogiannopoulos Date: Mon, 12 Jul 2010 16:00:16 +0200 Subject: Added signature generation and verification. --- .gitignore | 6 +- cryptodev_cipher.c | 16 ++- ncr-pk.c | 103 +++++++++++++++- ncr-sessions.c | 350 ++++++++++++++++++++++++++++++++++++++++++++--------- ncr.h | 17 +-- ncr_int.h | 29 +++-- 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*); -- cgit