diff options
Diffstat (limited to 'ncr-sessions.c')
-rw-r--r-- | ncr-sessions.c | 1115 |
1 files changed, 580 insertions, 535 deletions
diff --git a/ncr-sessions.c b/ncr-sessions.c index 3f39d6d..a716670 100644 --- a/ncr-sessions.c +++ b/ncr-sessions.c @@ -133,7 +133,7 @@ static void session_publish_ref(struct ncr_lists *lst, static struct session_item_st *session_get_ref(struct ncr_lists *lst, ncr_session_t desc) { -struct session_item_st* item; + struct session_item_st *item; mutex_lock(&lst->session_idr_mutex); /* item may be NULL for pre-allocated session IDs. */ @@ -185,7 +185,7 @@ static void _ncr_sessions_item_put(struct session_item_st *item) static struct session_item_st *ncr_session_new(ncr_session_t desc) { - struct session_item_st* sess; + struct session_item_st *sess; sess = kzalloc(sizeof(*sess), GFP_KERNEL); if (sess == NULL) { @@ -195,9 +195,9 @@ static struct session_item_st *ncr_session_new(ncr_session_t desc) sess->array_size = DEFAULT_PREALLOC_PAGES; sess->pages = kzalloc(sess->array_size * - sizeof(struct page *), GFP_KERNEL); + sizeof(struct page *), GFP_KERNEL); sess->sg = kzalloc(sess->array_size * - sizeof(struct scatterlist), GFP_KERNEL); + sizeof(struct scatterlist), GFP_KERNEL); if (sess->sg == NULL || sess->pages == NULL) { err(); goto err_sess; @@ -216,84 +216,85 @@ err_sess: return NULL; } -const oid_st* _ncr_properties_to_oid(const struct algo_properties_st * prop, int key_size) +const oid_st *_ncr_properties_to_oid(const struct algo_properties_st *prop, + int key_size) { -int i = 0; + int i = 0; if (prop->oids == NULL) return NULL; - + do { if (key_size == prop->oids[i].key_size || - prop->oids[i].key_size == -1 /* catch all */) { - + prop->oids[i].key_size == -1 /* catch all */ ) { + return &prop->oids[i].oid; } - } while(prop->oids[++i].key_size != 0); + } while (prop->oids[++i].key_size != 0); return NULL; } const static struct algo_oid_st aes_cbc_oids[] = { - {.key_size=16, - .oid = {{2,16,840,1,101,3,4,1,2}, 9}}, - {.key_size=24, - .oid = {{2,16,840,1,101,3,4,1,22}, 9}}, - {.key_size=32, - .oid = {{2,16,840,1,101,3,4,1,42}, 9}}, - {.key_size=0 } + {.key_size = 16, + .oid = {{2, 16, 840, 1, 101, 3, 4, 1, 2}, 9}}, + {.key_size = 24, + .oid = {{2, 16, 840, 1, 101, 3, 4, 1, 22}, 9}}, + {.key_size = 32, + .oid = {{2, 16, 840, 1, 101, 3, 4, 1, 42}, 9}}, + {.key_size = 0} }; const static struct algo_oid_st aes_ecb_oids[] = { - {.key_size=16, - .oid = {{2,16,840,1,101,3,4,1,1}, 9}}, - {.key_size=24, - .oid = {{2,16,840,1,101,3,4,1,21}, 9}}, - {.key_size=32, - .oid = {{2,16,840,1,101,3,4,1,41}, 9}}, - {.key_size=0 } + {.key_size = 16, + .oid = {{2, 16, 840, 1, 101, 3, 4, 1, 1}, 9}}, + {.key_size = 24, + .oid = {{2, 16, 840, 1, 101, 3, 4, 1, 21}, 9}}, + {.key_size = 32, + .oid = {{2, 16, 840, 1, 101, 3, 4, 1, 41}, 9}}, + {.key_size = 0} }; const static struct algo_oid_st des3_cbc_oids[] = { - {.key_size=-1, - .oid = {{1,2,840,113549,3,7}, 6}}, - {.key_size=0 } + {.key_size = -1, + .oid = {{1, 2, 840, 113549, 3, 7}, 6}}, + {.key_size = 0} }; /* http://www.oid-info.com/get/1.3.6.1.4.1.4929.1.7 */ const static struct algo_oid_st des3_ecb_oids[] = { - {.key_size=-1, - .oid = {{1,3,6,1,4,1,4929,1,7}, 9}}, - {.key_size=0 } + {.key_size = -1, + .oid = {{1, 3, 6, 1, 4, 1, 4929, 1, 7}, 9}}, + {.key_size = 0} }; const static struct algo_oid_st camelia_cbc_oids[] = { - {.key_size=16, - .oid = {{1,2,392,200011,61,1,1,1,2}, 9}}, - {.key_size=24, - .oid = {{1,2,392,200011,61,1,1,1,3}, 9}}, - {.key_size=32, - .oid = {{1,2,392,200011,61,1,1,1,4}, 9}}, - {.key_size=0 } + {.key_size = 16, + .oid = {{1, 2, 392, 200011, 61, 1, 1, 1, 2}, 9}}, + {.key_size = 24, + .oid = {{1, 2, 392, 200011, 61, 1, 1, 1, 3}, 9}}, + {.key_size = 32, + .oid = {{1, 2, 392, 200011, 61, 1, 1, 1, 4}, 9}}, + {.key_size = 0} }; const static struct algo_oid_st rsa_oid[] = { - {.key_size=-1, - .oid = {{1,2,840,113549,1,1,1}, 7}}, - {.key_size=0 } + {.key_size = -1, + .oid = {{1, 2, 840, 113549, 1, 1, 1}, 7}}, + {.key_size = 0} }; const static struct algo_oid_st dsa_oid[] = { - {.key_size=-1, - .oid = {{1,2,840,10040,4,1}, 6}}, - {.key_size=0 } + {.key_size = -1, + .oid = {{1, 2, 840, 10040, 4, 1}, 6}}, + {.key_size = 0} }; const static struct algo_oid_st dh_oid[] = { - {.key_size=-1, - .oid = {{1,2,840,10046,2,1}, 6}}, - {.key_size=0 } + {.key_size = -1, + .oid = {{1, 2, 840, 10046, 2, 1}, 6}}, + {.key_size = 0} }; /* OIDs are used in cipher algorithms to distinguish keys on key wrapping. @@ -301,87 +302,87 @@ const static struct algo_oid_st dh_oid[] = { static const struct algo_properties_st algo_properties[] = { #define KSTR(x) .kstr = x, .kstr_len = sizeof(x) - 1 - { .algo = NCR_ALG_NULL, KSTR("ecb(cipher_null)"), - .needs_iv = 0, .is_symmetric=1, .can_encrypt=1, - .key_type = NCR_KEY_TYPE_INVALID }, - { .algo = NCR_ALG_3DES_CBC, KSTR("cbc(des3_ede)"), - .needs_iv = 1, .is_symmetric=1, .can_encrypt=1, - .key_type = NCR_KEY_TYPE_SECRET, .oids = des3_cbc_oids }, - { .algo = NCR_ALG_3DES_ECB, KSTR("ecb(des3_ede)"), - .needs_iv = 0, .is_symmetric=1, .can_encrypt=1, - .key_type = NCR_KEY_TYPE_SECRET, .oids = des3_ecb_oids }, - { .algo = NCR_ALG_AES_CBC, KSTR("cbc(aes)"), - .needs_iv = 1, .is_symmetric=1, .can_encrypt=1, - .key_type = NCR_KEY_TYPE_SECRET, .oids = aes_cbc_oids }, - { .algo = NCR_ALG_CAMELIA_CBC, KSTR("cbc(camelia)"), - .needs_iv = 1, .is_symmetric=1, .can_encrypt=1, - .key_type = NCR_KEY_TYPE_SECRET, .oids = camelia_cbc_oids }, - { .algo = NCR_ALG_AES_CTR, KSTR("ctr(aes)"), - .needs_iv = 1, .is_symmetric=1, .can_encrypt=1, - .key_type = NCR_KEY_TYPE_SECRET, /* FIXME: no OIDs */ }, - { .algo = NCR_ALG_CAMELIA_CTR, KSTR("ctr(camelia)"), - .needs_iv = 1, .is_symmetric=1, .can_encrypt=1, - .key_type = NCR_KEY_TYPE_SECRET, /* FIXME: no OIDs */ }, - { .algo = NCR_ALG_AES_ECB, KSTR("ecb(aes)"), - .needs_iv = 0, .is_symmetric=1, .can_encrypt=1, - .key_type = NCR_KEY_TYPE_SECRET, .oids = aes_ecb_oids }, - { .algo = NCR_ALG_CAMELIA_ECB, KSTR("ecb(camelia)"), - .needs_iv = 0, .is_symmetric=1, .can_encrypt=1, - .key_type = NCR_KEY_TYPE_SECRET, /* FIXME: no OIDs */ }, - { .algo = NCR_ALG_SHA1, KSTR("sha1"), - .digest_size = 20, .can_digest=1, - .key_type = NCR_KEY_TYPE_INVALID }, - { .algo = NCR_ALG_MD5, KSTR("md5"), - .digest_size = 16, .can_digest=1, - .key_type = NCR_KEY_TYPE_INVALID }, - { .algo = NCR_ALG_SHA2_224, KSTR("sha224"), - .digest_size = 28, .can_digest=1, - .key_type = NCR_KEY_TYPE_INVALID }, - { .algo = NCR_ALG_SHA2_256, KSTR("sha256"), - .digest_size = 32, .can_digest=1, - .key_type = NCR_KEY_TYPE_INVALID }, - { .algo = NCR_ALG_SHA2_384, KSTR("sha384"), - .digest_size = 48, .can_digest=1, - .key_type = NCR_KEY_TYPE_INVALID }, - { .algo = NCR_ALG_SHA2_512, KSTR("sha512"), - .digest_size = 64, .can_digest=1, - .key_type = NCR_KEY_TYPE_INVALID }, - { .is_hmac = 1, KSTR("hmac(sha1)"), - .digest_size = 20, .can_sign=1, - .key_type = NCR_KEY_TYPE_SECRET }, - { .is_hmac = 1, KSTR("hmac(md5)"), - .digest_size = 16, .can_sign=1, - .key_type = NCR_KEY_TYPE_SECRET }, - { .is_hmac = 1, KSTR("hmac(sha224)"), - .digest_size = 28, .can_sign=1, - .key_type = NCR_KEY_TYPE_SECRET }, - { .is_hmac = 1, KSTR("hmac(sha256)"), - .digest_size = 32, .can_sign=1, - .key_type = NCR_KEY_TYPE_SECRET }, - { .is_hmac = 1, KSTR("hmac(sha384)"), - .digest_size = 48, .can_sign=1, - .key_type = NCR_KEY_TYPE_SECRET }, - { .is_hmac = 1, KSTR("hmac(sha512)"), - .digest_size = 64, .can_sign=1, - .key_type = NCR_KEY_TYPE_SECRET }, + {.algo = NCR_ALG_NULL, KSTR("ecb(cipher_null)"), + .needs_iv = 0,.is_symmetric = 1,.can_encrypt = 1, + .key_type = NCR_KEY_TYPE_INVALID}, + {.algo = NCR_ALG_3DES_CBC, KSTR("cbc(des3_ede)"), + .needs_iv = 1,.is_symmetric = 1,.can_encrypt = 1, + .key_type = NCR_KEY_TYPE_SECRET,.oids = des3_cbc_oids}, + {.algo = NCR_ALG_3DES_ECB, KSTR("ecb(des3_ede)"), + .needs_iv = 0,.is_symmetric = 1,.can_encrypt = 1, + .key_type = NCR_KEY_TYPE_SECRET,.oids = des3_ecb_oids}, + {.algo = NCR_ALG_AES_CBC, KSTR("cbc(aes)"), + .needs_iv = 1,.is_symmetric = 1,.can_encrypt = 1, + .key_type = NCR_KEY_TYPE_SECRET,.oids = aes_cbc_oids}, + {.algo = NCR_ALG_CAMELIA_CBC, KSTR("cbc(camelia)"), + .needs_iv = 1,.is_symmetric = 1,.can_encrypt = 1, + .key_type = NCR_KEY_TYPE_SECRET,.oids = camelia_cbc_oids}, + {.algo = NCR_ALG_AES_CTR, KSTR("ctr(aes)"), + .needs_iv = 1,.is_symmetric = 1,.can_encrypt = 1, + .key_type = NCR_KEY_TYPE_SECRET, /* FIXME: no OIDs */ }, + {.algo = NCR_ALG_CAMELIA_CTR, KSTR("ctr(camelia)"), + .needs_iv = 1,.is_symmetric = 1,.can_encrypt = 1, + .key_type = NCR_KEY_TYPE_SECRET, /* FIXME: no OIDs */ }, + {.algo = NCR_ALG_AES_ECB, KSTR("ecb(aes)"), + .needs_iv = 0,.is_symmetric = 1,.can_encrypt = 1, + .key_type = NCR_KEY_TYPE_SECRET,.oids = aes_ecb_oids}, + {.algo = NCR_ALG_CAMELIA_ECB, KSTR("ecb(camelia)"), + .needs_iv = 0,.is_symmetric = 1,.can_encrypt = 1, + .key_type = NCR_KEY_TYPE_SECRET, /* FIXME: no OIDs */ }, + {.algo = NCR_ALG_SHA1, KSTR("sha1"), + .digest_size = 20,.can_digest = 1, + .key_type = NCR_KEY_TYPE_INVALID}, + {.algo = NCR_ALG_MD5, KSTR("md5"), + .digest_size = 16,.can_digest = 1, + .key_type = NCR_KEY_TYPE_INVALID}, + {.algo = NCR_ALG_SHA2_224, KSTR("sha224"), + .digest_size = 28,.can_digest = 1, + .key_type = NCR_KEY_TYPE_INVALID}, + {.algo = NCR_ALG_SHA2_256, KSTR("sha256"), + .digest_size = 32,.can_digest = 1, + .key_type = NCR_KEY_TYPE_INVALID}, + {.algo = NCR_ALG_SHA2_384, KSTR("sha384"), + .digest_size = 48,.can_digest = 1, + .key_type = NCR_KEY_TYPE_INVALID}, + {.algo = NCR_ALG_SHA2_512, KSTR("sha512"), + .digest_size = 64,.can_digest = 1, + .key_type = NCR_KEY_TYPE_INVALID}, + {.is_hmac = 1, KSTR("hmac(sha1)"), + .digest_size = 20,.can_sign = 1, + .key_type = NCR_KEY_TYPE_SECRET}, + {.is_hmac = 1, KSTR("hmac(md5)"), + .digest_size = 16,.can_sign = 1, + .key_type = NCR_KEY_TYPE_SECRET}, + {.is_hmac = 1, KSTR("hmac(sha224)"), + .digest_size = 28,.can_sign = 1, + .key_type = NCR_KEY_TYPE_SECRET}, + {.is_hmac = 1, KSTR("hmac(sha256)"), + .digest_size = 32,.can_sign = 1, + .key_type = NCR_KEY_TYPE_SECRET}, + {.is_hmac = 1, KSTR("hmac(sha384)"), + .digest_size = 48,.can_sign = 1, + .key_type = NCR_KEY_TYPE_SECRET}, + {.is_hmac = 1, KSTR("hmac(sha512)"), + .digest_size = 64,.can_sign = 1, + .key_type = NCR_KEY_TYPE_SECRET}, /* NOTE: These algorithm names are not available through the kernel API (yet). */ - { .algo = NCR_ALG_RSA, KSTR("rsa"), .is_pk = 1, - .can_encrypt=1, .can_sign=1, .key_type = NCR_KEY_TYPE_PUBLIC, - .oids = rsa_oid }, - { .algo = NCR_ALG_DSA, KSTR("dsa"), .is_pk = 1, - .can_sign=1, .key_type = NCR_KEY_TYPE_PUBLIC, - .oids = dsa_oid }, - { .algo = NCR_ALG_DH, KSTR("dh"), .is_pk = 1, - .can_kx=1, .key_type = NCR_KEY_TYPE_PUBLIC, - .oids = dh_oid }, - - { .algo = NCR_ALG_DSA, KSTR(NCR_ALG_DSA_TRANSPARENT_HASH), .is_pk = 1, - .can_sign=1, .has_transparent_hash = 1, - .key_type = NCR_KEY_TYPE_PUBLIC, .oids = rsa_oid }, - { .algo = NCR_ALG_RSA, KSTR(NCR_ALG_RSA_TRANSPARENT_HASH), .is_pk = 1, - .can_encrypt=1, .can_sign=1, .has_transparent_hash = 1, - .key_type = NCR_KEY_TYPE_PUBLIC, .oids = dsa_oid }, + {.algo = NCR_ALG_RSA, KSTR("rsa"),.is_pk = 1, + .can_encrypt = 1,.can_sign = 1,.key_type = NCR_KEY_TYPE_PUBLIC, + .oids = rsa_oid}, + {.algo = NCR_ALG_DSA, KSTR("dsa"),.is_pk = 1, + .can_sign = 1,.key_type = NCR_KEY_TYPE_PUBLIC, + .oids = dsa_oid}, + {.algo = NCR_ALG_DH, KSTR("dh"),.is_pk = 1, + .can_kx = 1,.key_type = NCR_KEY_TYPE_PUBLIC, + .oids = dh_oid}, + + {.algo = NCR_ALG_DSA, KSTR(NCR_ALG_DSA_TRANSPARENT_HASH),.is_pk = 1, + .can_sign = 1,.has_transparent_hash = 1, + .key_type = NCR_KEY_TYPE_PUBLIC,.oids = rsa_oid}, + {.algo = NCR_ALG_RSA, KSTR(NCR_ALG_RSA_TRANSPARENT_HASH),.is_pk = 1, + .can_encrypt = 1,.can_sign = 1,.has_transparent_hash = 1, + .key_type = NCR_KEY_TYPE_PUBLIC,.oids = dsa_oid}, #undef KSTR }; @@ -401,21 +402,21 @@ const struct algo_properties_st *_ncr_algo_to_properties(ncr_algorithm_t algo) return NULL; } -static void print_oid(oid_st* oid) +static void print_oid(oid_st * oid) { -char txt[128]=""; -char tmp[64]; -int i; + char txt[128] = ""; + char tmp[64]; + int i; - for (i=0;i<oid->OIDlen;i++) { + for (i = 0; i < oid->OIDlen; i++) { sprintf(tmp, "%d.", (int)oid->OID[i]); strcat(txt, tmp); } - + dprintk(1, KERN_DEBUG, "unknown oid: %s\n", txt); } -const struct algo_properties_st *_ncr_oid_to_properties(oid_st* oid) +const struct algo_properties_st *_ncr_oid_to_properties(oid_st * oid) { const struct algo_properties_st *a; int i; @@ -423,22 +424,25 @@ const struct algo_properties_st *_ncr_oid_to_properties(oid_st* oid) for (a = algo_properties; a < algo_properties + ARRAY_SIZE(algo_properties); a++) { - i=0; - - if (a->oids == NULL) continue; - + i = 0; + + if (a->oids == NULL) + continue; + do { - if (a->oids[i].oid.OIDlen == oid->OIDlen && - memcmp(oid->OID, a->oids[i].oid.OID, oid->OIDlen*sizeof(oid->OID[0]))==0) + if (a->oids[i].oid.OIDlen == oid->OIDlen && + memcmp(oid->OID, a->oids[i].oid.OID, + oid->OIDlen * sizeof(oid->OID[0])) == 0) return a; - } while(a->oids[++i].key_size != 0); + } while (a->oids[++i].key_size != 0); } print_oid(oid); return NULL; } -const struct algo_properties_st *_ncr_nla_to_properties(const struct nlattr *nla) +const struct algo_properties_st *_ncr_nla_to_properties(const struct nlattr + *nla) { const struct algo_properties_st *a; size_t name_len; @@ -543,228 +547,251 @@ static struct session_item_st *_ncr_session_init(struct ncr_lists *lists, } } else ns->algorithm = old_session->algorithm; - - switch(op) { - case NCR_OP_ENCRYPT: - case NCR_OP_DECRYPT: - if (!ns->algorithm->can_encrypt) { + + switch (op) { + case NCR_OP_ENCRYPT: + case NCR_OP_DECRYPT: + if (!ns->algorithm->can_encrypt) { + err(); + ret = -EINVAL; + goto fail; + } + + if (old_session != NULL) { + err(); + ret = -EOPNOTSUPP; + goto fail; + } + + /* read key */ + ret = key_item_get_nla_read(&ns->key, lists, tb[NCR_ATTR_KEY]); + if (ret < 0) { + err(); + goto fail; + } + + /* wrapping keys cannot be used for encryption or decryption + */ + if (ns->key->flags & NCR_KEY_FLAG_WRAPPING + || ns->key->flags & NCR_KEY_FLAG_UNWRAPPING) { + err(); + ret = -EINVAL; + goto fail; + } + + if (ns->key->type == NCR_KEY_TYPE_SECRET) { + int keysize = ns->key->key.secret.size; + + if (ns->algorithm->algo == NCR_ALG_NULL) + keysize = 0; + + if (ns->algorithm->is_pk) { err(); ret = -EINVAL; goto fail; } - if (old_session != NULL) { + ret = + cryptodev_cipher_init(&ns->cipher, + ns->algorithm->kstr, + ns->key->key.secret.data, + keysize); + if (ret < 0) { err(); - ret = -EOPNOTSUPP; goto fail; } - /* read key */ - ret = key_item_get_nla_read(&ns->key, lists, - tb[NCR_ATTR_KEY]); + if (ns->algorithm->needs_iv) { + nla = tb[NCR_ATTR_IV]; + if (nla == NULL) { + err(); + ret = -EINVAL; + goto fail; + } + cryptodev_cipher_set_iv(&ns->cipher, + nla_data(nla), + nla_len(nla)); + } +#ifdef CONFIG_ASSYMETRIC + } else if (ns->key->type == NCR_KEY_TYPE_PRIVATE + || ns->key->type == NCR_KEY_TYPE_PUBLIC) { + ret = + ncr_pk_cipher_init(ns->algorithm, &ns->pk, tb, + ns->key, NULL); if (ret < 0) { err(); goto fail; } - - /* wrapping keys cannot be used for encryption or decryption - */ - if (ns->key->flags & NCR_KEY_FLAG_WRAPPING || ns->key->flags & NCR_KEY_FLAG_UNWRAPPING) { +#endif + } else { + err(); + ret = -EINVAL; + goto fail; + } + break; + + case NCR_OP_SIGN: + case NCR_OP_VERIFY: + if (!ns->algorithm->can_sign && !ns->algorithm->can_digest) { + err(); + ret = -EINVAL; + goto fail; + } + + if (ns->algorithm->can_digest) { + if (ns->algorithm->is_pk) { err(); ret = -EINVAL; goto fail; } - if (ns->key->type == NCR_KEY_TYPE_SECRET) { - int keysize = ns->key->key.secret.size; - - if (ns->algorithm->algo == NCR_ALG_NULL) - keysize = 0; - - if (ns->algorithm->is_pk) { - err(); - ret = -EINVAL; - goto fail; - } - - ret = cryptodev_cipher_init(&ns->cipher, ns->algorithm->kstr, - ns->key->key.secret.data, keysize); - if (ret < 0) { - err(); - goto fail; - } + ret = init_or_clone_hash(ns, old_session, + ns->algorithm, NULL, 0); + if (ret < 0) { + err(); + goto fail; + } - if (ns->algorithm->needs_iv) { - nla = tb[NCR_ATTR_IV]; - if (nla == NULL) { - err(); - ret = -EINVAL; - goto fail; - } - cryptodev_cipher_set_iv(&ns->cipher, - nla_data(nla), - nla_len(nla)); - } -#ifdef CONFIG_ASSYMETRIC - } else if (ns->key->type == NCR_KEY_TYPE_PRIVATE || ns->key->type == NCR_KEY_TYPE_PUBLIC) { - ret = ncr_pk_cipher_init(ns->algorithm, &ns->pk, - tb, ns->key, NULL); + } else { + /* Get key */ + if (old_session == NULL) { + ret = key_item_get_nla_read(&ns->key, + lists, + tb[NCR_ATTR_KEY]); if (ret < 0) { err(); goto fail; } -#endif } else { + atomic_inc(&old_session->key->refcnt); + ns->key = old_session->key; + } + + /* wrapping keys cannot be used for anything except wrapping. + */ + if (ns->key->flags & NCR_KEY_FLAG_WRAPPING + || ns->key->flags & NCR_KEY_FLAG_UNWRAPPING) { err(); ret = -EINVAL; goto fail; } - break; - case NCR_OP_SIGN: - case NCR_OP_VERIFY: - if (!ns->algorithm->can_sign && !ns->algorithm->can_digest) { + /* wrapping keys cannot be used for anything except wrapping. + */ + if (ns->key->flags & NCR_KEY_FLAG_WRAPPING) { err(); ret = -EINVAL; goto fail; } - if (ns->algorithm->can_digest) { + if (ns->algorithm->is_hmac + && ns->key->type == NCR_KEY_TYPE_SECRET) { if (ns->algorithm->is_pk) { err(); ret = -EINVAL; goto fail; } - ret = init_or_clone_hash(ns, old_session, - ns->algorithm, NULL, - 0); + ret = + init_or_clone_hash(ns, old_session, + ns->algorithm, + ns->key->key.secret.data, + ns->key->key.secret. + size); if (ret < 0) { err(); goto fail; } - - } else { - /* Get key */ - if (old_session == NULL) { - ret = key_item_get_nla_read(&ns->key, - lists, - tb[NCR_ATTR_KEY]); - if (ret < 0) { - err(); - goto fail; - } - } else { - atomic_inc(&old_session->key->refcnt); - ns->key = old_session->key; +#ifdef CONFIG_ASSYMETRIC + } else if (ns->algorithm->is_pk + && (ns->key->type == NCR_KEY_TYPE_PRIVATE + || ns->key->type == + NCR_KEY_TYPE_PUBLIC)) { + const struct algo_properties_st *sign_hash; + + if (old_session != NULL) { + err(); + ret = -EOPNOTSUPP; + goto fail; } - /* wrapping keys cannot be used for anything except wrapping. - */ - if (ns->key->flags & NCR_KEY_FLAG_WRAPPING || ns->key->flags & NCR_KEY_FLAG_UNWRAPPING) { + nla = tb[NCR_ATTR_SIGNATURE_HASH_ALGORITHM]; + sign_hash = _ncr_nla_to_properties(nla); + if (sign_hash == NULL) { err(); ret = -EINVAL; goto fail; } - /* wrapping keys cannot be used for anything except wrapping. - */ - if (ns->key->flags & NCR_KEY_FLAG_WRAPPING) { + if (!sign_hash->can_digest) { err(); ret = -EINVAL; goto fail; } - if (ns->algorithm->is_hmac && ns->key->type == NCR_KEY_TYPE_SECRET) { - if (ns->algorithm->is_pk) { - err(); - ret = -EINVAL; - goto fail; - } - - ret = init_or_clone_hash(ns, old_session, ns->algorithm, - ns->key->key.secret.data, ns->key->key.secret.size); - if (ret < 0) { - err(); - goto fail; - } -#ifdef CONFIG_ASSYMETRIC - } else if (ns->algorithm->is_pk && (ns->key->type == NCR_KEY_TYPE_PRIVATE || ns->key->type == NCR_KEY_TYPE_PUBLIC)) { - const struct algo_properties_st *sign_hash; - - if (old_session != NULL) { - err(); - ret = -EOPNOTSUPP; - goto fail; - } - - nla = tb[NCR_ATTR_SIGNATURE_HASH_ALGORITHM]; - sign_hash = _ncr_nla_to_properties(nla); - if (sign_hash == NULL) { - err(); - ret = -EINVAL; - goto fail; - } + if (sign_hash->is_pk) { + err(); + ret = -EINVAL; + goto fail; + } - if (!sign_hash->can_digest) { - err(); - ret = -EINVAL; - goto fail; - } + ret = ncr_pk_cipher_init(ns->algorithm, &ns->pk, + tb, ns->key, + sign_hash); + if (ret < 0) { + err(); + goto fail; + } - if (sign_hash->is_pk) { - err(); - ret = -EINVAL; - goto fail; - } + ret = + cryptodev_hash_init(&ns->hash, + sign_hash->kstr, NULL, + 0); + if (ret < 0) { + err(); + goto fail; + } - ret = ncr_pk_cipher_init(ns->algorithm, &ns->pk, - tb, ns->key, sign_hash); - if (ret < 0) { + if (ns->algorithm->has_transparent_hash) { + /* transparent hash has to be allowed by the key + */ + if (! + (ns->key-> + flags & + NCR_KEY_FLAG_ALLOW_TRANSPARENT_HASH)) + { err(); + ret = -EPERM; goto fail; } - ret = cryptodev_hash_init(&ns->hash, sign_hash->kstr, NULL, 0); - if (ret < 0) { + ns->transparent_hash = + kzalloc(ns->hash.digestsize, + GFP_KERNEL); + if (ns->transparent_hash == NULL) { err(); + ret = -ENOMEM; goto fail; } - - if (ns->algorithm->has_transparent_hash) { - /* transparent hash has to be allowed by the key - */ - if (!(ns->key->flags & NCR_KEY_FLAG_ALLOW_TRANSPARENT_HASH)) { - err(); - ret = -EPERM; - goto fail; - } - - ns->transparent_hash = kzalloc(ns->hash.digestsize, GFP_KERNEL); - if (ns->transparent_hash == NULL) { - err(); - ret = -ENOMEM; - goto fail; - } - } -#endif - } else { - err(); - ret = -EINVAL; - goto fail; } +#endif + } else { + err(); + ret = -EINVAL; + goto fail; } + } - break; - default: - err(); - ret = -EINVAL; - goto fail; + break; + default: + err(); + ret = -EINVAL; + goto fail; } if (old_session != NULL) _ncr_sessions_item_put(old_session); - + return ns; fail: @@ -801,26 +828,31 @@ int ncr_session_init(struct ncr_lists *lists, } /* The caller is responsible for locking of the session. */ -static int _ncr_session_encrypt(struct session_item_st* sess, const struct scatterlist* input, unsigned input_cnt, - size_t input_size, void *output, unsigned output_cnt, size_t *output_size) +static int _ncr_session_encrypt(struct session_item_st *sess, + const struct scatterlist *input, + unsigned input_cnt, size_t input_size, + void *output, unsigned output_cnt, + size_t * output_size) { -int ret; + int ret; if (sess->algorithm->is_symmetric) { /* read key */ - ret = cryptodev_cipher_encrypt(&sess->cipher, input, - output, input_size); + ret = cryptodev_cipher_encrypt(&sess->cipher, input, + output, input_size); if (ret < 0) { err(); return ret; } /* FIXME: handle ciphers that do not require that */ *output_size = input_size; - } else { /* public key */ + } else { /* public key */ #ifdef CONFIG_ASSYMETRIC - ret = ncr_pk_cipher_encrypt(&sess->pk, input, input_cnt, input_size, - output, output_cnt, output_size); - + ret = + ncr_pk_cipher_encrypt(&sess->pk, input, input_cnt, + input_size, output, output_cnt, + output_size); + if (ret < 0) { err(); return ret; @@ -830,32 +862,36 @@ int ret; #endif } - + return 0; } /* The caller is responsible for locking of the session. */ -static int _ncr_session_decrypt(struct session_item_st* sess, const struct scatterlist* input, - unsigned input_cnt, size_t input_size, - struct scatterlist *output, unsigned output_cnt, size_t *output_size) +static int _ncr_session_decrypt(struct session_item_st *sess, + const struct scatterlist *input, + unsigned input_cnt, size_t input_size, + struct scatterlist *output, unsigned output_cnt, + size_t * output_size) { -int ret; + int ret; if (sess->algorithm->is_symmetric) { /* read key */ - ret = cryptodev_cipher_decrypt(&sess->cipher, input, - output, input_size); + ret = cryptodev_cipher_decrypt(&sess->cipher, input, + output, input_size); if (ret < 0) { err(); return ret; } /* FIXME: handle ciphers that do not require equality */ *output_size = input_size; - } else { /* public key */ + } else { /* public key */ #ifdef CONFIG_ASSYMETRIC - ret = ncr_pk_cipher_decrypt(&sess->pk, input, input_cnt, input_size, - output, output_cnt, output_size); - + ret = + ncr_pk_cipher_decrypt(&sess->pk, input, input_cnt, + input_size, output, output_cnt, + output_size); + if (ret < 0) { err(); return ret; @@ -865,7 +901,7 @@ int ret; #endif } - + return 0; } @@ -880,8 +916,7 @@ static int _ncr_session_grow_pages(struct session_item_st *ses, int pagecount) return 0; for (array_size = ses->array_size; array_size < pagecount; - array_size *= 2) - ; + array_size *= 2) ; dprintk(2, KERN_DEBUG, "%s: reallocating to %d elements\n", __func__, array_size); @@ -905,7 +940,8 @@ static int _ncr_session_grow_pages(struct session_item_st *ses, int pagecount) The caller is responsible for locking of the session. */ static int get_userbuf2(struct session_item_st *ses, struct nlattr *tb[], struct scatterlist **src_sg, unsigned *src_cnt, - size_t *src_size, struct ncr_session_output_buffer *dst, + size_t * src_size, + struct ncr_session_output_buffer *dst, struct scatterlist **dst_sg, unsigned *dst_cnt, int compat) { @@ -986,7 +1022,7 @@ static int get_userbuf2(struct session_item_st *ses, struct nlattr *tb[], *dst_sg = NULL; } } - + ses->available_pages = pagecount; return 0; @@ -1001,7 +1037,7 @@ static int _ncr_session_update(struct session_item_st *sess, int ret; struct scatterlist *isg = NULL; struct scatterlist *osg = NULL; - unsigned osg_cnt=0, isg_cnt=0; + unsigned osg_cnt = 0, isg_cnt = 0; size_t isg_size = 0, osg_size; struct ncr_session_output_buffer out; @@ -1012,111 +1048,108 @@ static int _ncr_session_update(struct session_item_st *sess, return ret; } - switch(sess->op) { - case NCR_OP_ENCRYPT: - if (osg == NULL) { - err(); - ret = -EINVAL; - goto fail; - } + switch (sess->op) { + case NCR_OP_ENCRYPT: + if (osg == NULL) { + err(); + ret = -EINVAL; + goto fail; + } - osg_size = out.buffer_size; - if (osg_size < isg_size) { - err(); - ret = -EINVAL; - goto fail; - } + osg_size = out.buffer_size; + if (osg_size < isg_size) { + err(); + ret = -EINVAL; + goto fail; + } - if (sess->algorithm->is_symmetric - && sess->algorithm->needs_iv) { - nla = tb[NCR_ATTR_IV]; - if (nla != NULL) - cryptodev_cipher_set_iv(&sess->cipher, - nla_data(nla), - nla_len(nla)); - } + if (sess->algorithm->is_symmetric && sess->algorithm->needs_iv) { + nla = tb[NCR_ATTR_IV]; + if (nla != NULL) + cryptodev_cipher_set_iv(&sess->cipher, + nla_data(nla), + nla_len(nla)); + } - ret = _ncr_session_encrypt(sess, isg, isg_cnt, isg_size, - osg, osg_cnt, &osg_size); - if (ret < 0) { - err(); - goto fail; - } + ret = _ncr_session_encrypt(sess, isg, isg_cnt, isg_size, + osg, osg_cnt, &osg_size); + if (ret < 0) { + err(); + goto fail; + } - ret = ncr_session_output_buffer_set_size(&out, osg_size, - compat); - if (ret != 0) { - err(); - goto fail; - } - break; - case NCR_OP_DECRYPT: - if (osg == NULL) { + ret = ncr_session_output_buffer_set_size(&out, osg_size, + compat); + if (ret != 0) { + err(); + goto fail; + } + break; + case NCR_OP_DECRYPT: + if (osg == NULL) { + err(); + ret = -EINVAL; + goto fail; + } + + osg_size = out.buffer_size; + if (osg_size < isg_size) { + err(); + ret = -EINVAL; + goto fail; + } + + if (sess->algorithm->is_symmetric && sess->algorithm->needs_iv) { + nla = tb[NCR_ATTR_IV]; + if (nla != NULL) + cryptodev_cipher_set_iv(&sess->cipher, + nla_data(nla), + nla_len(nla)); + } + + ret = _ncr_session_decrypt(sess, isg, isg_cnt, isg_size, + osg, osg_cnt, &osg_size); + if (ret < 0) { + err(); + goto fail; + } + + ret = ncr_session_output_buffer_set_size(&out, osg_size, + compat); + if (ret != 0) { + err(); + goto fail; + } + break; + + case NCR_OP_SIGN: + case NCR_OP_VERIFY: + if (sess->algorithm->has_transparent_hash) { + if (isg_size != sess->hash.digestsize) { err(); ret = -EINVAL; goto fail; } - - osg_size = out.buffer_size; - if (osg_size < isg_size) { + ret = sg_copy_to_buffer(isg, isg_cnt, + sess->transparent_hash, + isg_size); + if (ret != isg_size) { err(); ret = -EINVAL; goto fail; } - - if (sess->algorithm->is_symmetric - && sess->algorithm->needs_iv) { - nla = tb[NCR_ATTR_IV]; - if (nla != NULL) - cryptodev_cipher_set_iv(&sess->cipher, - nla_data(nla), - nla_len(nla)); - } - - ret = _ncr_session_decrypt(sess, isg, isg_cnt, isg_size, - osg, osg_cnt, &osg_size); + } else { + ret = cryptodev_hash_update(&sess->hash, isg, isg_size); if (ret < 0) { err(); goto fail; } - - ret = ncr_session_output_buffer_set_size(&out, osg_size, - compat); - if (ret != 0) { - err(); - goto fail; - } - break; - - case NCR_OP_SIGN: - case NCR_OP_VERIFY: - if (sess->algorithm->has_transparent_hash) { - if (isg_size != sess->hash.digestsize) { - err(); - ret = -EINVAL; - goto fail; - } - ret = sg_copy_to_buffer(isg, isg_cnt, - sess->transparent_hash, - isg_size); - if (ret != isg_size) { - err(); - ret = -EINVAL; - goto fail; - } - } else { - ret = cryptodev_hash_update(&sess->hash, isg, - isg_size); - if (ret < 0) { - err(); - goto fail; - } - } - break; - default: - err(); - ret = -EINVAL; - goto fail; + } + break; + default: + err(); + ret = -EINVAL; + goto fail; } ret = 0; @@ -1162,146 +1195,157 @@ static int _ncr_session_final(struct ncr_lists *lists, return ret; } - switch(sess->op) { + switch (sess->op) { case NCR_OP_ENCRYPT: case NCR_OP_DECRYPT: break; - case NCR_OP_VERIFY: { - struct ncr_session_input_data src; + case NCR_OP_VERIFY:{ + struct ncr_session_input_data src; - nla = tb[NCR_ATTR_FINAL_INPUT_DATA]; - ret = ncr_session_input_data_from_nla(&src, nla, compat); - if (unlikely(ret != 0)) { - err(); - goto fail; - } - - buffer = kmalloc(src.data_size, GFP_KERNEL); - if (buffer == NULL) { - err(); - ret = -ENOMEM; - goto fail; - } - if (unlikely(copy_from_user(buffer, src.data, src.data_size))) { - err(); - ret = -EFAULT; - goto fail; - } - - digest_size = sess->hash.digestsize; - if (digest_size == 0 || sizeof(digest) < digest_size) { - err(); - ret = -EINVAL; - goto fail; - } - if (sess->algorithm->has_transparent_hash) - memcpy(digest, sess->transparent_hash, digest_size); - else { - ret = cryptodev_hash_final(&sess->hash, digest); - if (ret < 0) { + nla = tb[NCR_ATTR_FINAL_INPUT_DATA]; + ret = + ncr_session_input_data_from_nla(&src, nla, compat); + if (unlikely(ret != 0)) { err(); goto fail; } - } - if (!sess->algorithm->is_pk) - ret = (digest_size == src.data_size - && memcmp(buffer, digest, digest_size) == 0); - else { -#ifdef CONFIG_ASSYMETRIC - ret = ncr_pk_cipher_verify(&sess->pk, buffer, - src.data_size, digest, - digest_size); - if (ret < 0) { + buffer = kmalloc(src.data_size, GFP_KERNEL); + if (buffer == NULL) { err(); + ret = -ENOMEM; goto fail; } -#else - ret = -EOPNOTSUPP; - goto fail; -#endif - } - break; - } - - case NCR_OP_SIGN: { - struct ncr_session_output_buffer dst; - size_t output_size; - - nla = tb[NCR_ATTR_FINAL_OUTPUT_BUFFER]; - ret = ncr_session_output_buffer_from_nla(&dst, nla, compat); - if (unlikely(ret != 0)) { - err(); - goto fail; - } - - digest_size = sess->hash.digestsize; - if (digest_size == 0) { - err(); - ret = -EINVAL; - goto fail; - } - - if (sess->algorithm->has_transparent_hash) - memcpy(digest, sess->transparent_hash, digest_size); - else { - ret = cryptodev_hash_final(&sess->hash, digest); - if (ret < 0) { + if (unlikely + (copy_from_user(buffer, src.data, src.data_size))) { err(); + ret = -EFAULT; goto fail; } - } - - cryptodev_hash_deinit(&sess->hash); - if (!sess->algorithm->is_pk) { - if (dst.buffer_size < digest_size) { + digest_size = sess->hash.digestsize; + if (digest_size == 0 || sizeof(digest) < digest_size) { err(); - ret = -ERANGE; + ret = -EINVAL; goto fail; } - if (unlikely(copy_to_user(dst.buffer, digest, - digest_size))) { - err(); - ret = -EFAULT; - goto fail; + if (sess->algorithm->has_transparent_hash) + memcpy(digest, sess->transparent_hash, + digest_size); + else { + ret = cryptodev_hash_final(&sess->hash, digest); + if (ret < 0) { + err(); + goto fail; + } } - output_size = digest_size; - } else { + + if (!sess->algorithm->is_pk) + ret = (digest_size == src.data_size + && memcmp(buffer, digest, + digest_size) == 0); + else { #ifdef CONFIG_ASSYMETRIC - output_size = dst.buffer_size; - buffer = kmalloc(output_size, GFP_KERNEL); - if (buffer == NULL) { - err(); - ret = -ENOMEM; + ret = ncr_pk_cipher_verify(&sess->pk, buffer, + src.data_size, + digest, digest_size); + if (ret < 0) { + err(); + goto fail; + } +#else + ret = -EOPNOTSUPP; goto fail; +#endif } - ret = ncr_pk_cipher_sign(&sess->pk, digest, digest_size, - buffer, &output_size); - if (ret < 0) { + break; + } + + case NCR_OP_SIGN:{ + struct ncr_session_output_buffer dst; + size_t output_size; + + nla = tb[NCR_ATTR_FINAL_OUTPUT_BUFFER]; + ret = + ncr_session_output_buffer_from_nla(&dst, nla, + compat); + if (unlikely(ret != 0)) { err(); goto fail; } - if (unlikely(copy_to_user(dst.buffer, buffer, - output_size))) { + + digest_size = sess->hash.digestsize; + if (digest_size == 0) { err(); - ret = -EFAULT; + ret = -EINVAL; goto fail; } + + if (sess->algorithm->has_transparent_hash) + memcpy(digest, sess->transparent_hash, + digest_size); + else { + ret = cryptodev_hash_final(&sess->hash, digest); + if (ret < 0) { + err(); + goto fail; + } + } + + cryptodev_hash_deinit(&sess->hash); + + if (!sess->algorithm->is_pk) { + if (dst.buffer_size < digest_size) { + err(); + ret = -ERANGE; + goto fail; + } + if (unlikely(copy_to_user(dst.buffer, digest, + digest_size))) { + err(); + ret = -EFAULT; + goto fail; + } + output_size = digest_size; + } else { +#ifdef CONFIG_ASSYMETRIC + output_size = dst.buffer_size; + buffer = kmalloc(output_size, GFP_KERNEL); + if (buffer == NULL) { + err(); + ret = -ENOMEM; + goto fail; + } + ret = + ncr_pk_cipher_sign(&sess->pk, digest, + digest_size, buffer, + &output_size); + if (ret < 0) { + err(); + goto fail; + } + if (unlikely(copy_to_user(dst.buffer, buffer, + output_size))) { + err(); + ret = -EFAULT; + goto fail; + } #else - ret = -EOPNOTSUPP; - goto fail; + ret = -EOPNOTSUPP; + goto fail; #endif - } + } - ret = ncr_session_output_buffer_set_size(&dst, output_size, - compat); - if (ret != 0) { - err(); - goto fail; + ret = + ncr_session_output_buffer_set_size(&dst, + output_size, + compat); + if (ret != 0) { + err(); + goto fail; + } + break; } - break; - } default: err(); ret = -EINVAL; @@ -1317,11 +1361,11 @@ fail: /* Direct with key: Allows to hash a key. The caller is responsible for locking of the session. */ static int _ncr_session_update_key(struct ncr_lists *lists, - struct session_item_st* sess, + struct session_item_st *sess, struct nlattr *tb[]) { int ret; - struct key_item_st* key = NULL; + struct key_item_st *key = NULL; /* read key */ ret = key_item_get_nla_read(&key, lists, @@ -1330,43 +1374,44 @@ static int _ncr_session_update_key(struct ncr_lists *lists, err(); return ret; } - + if (key->type != NCR_KEY_TYPE_SECRET) { err(); ret = -EINVAL; goto fail; } - + if (!(key->flags & NCR_KEY_FLAG_HASHABLE)) { err(); ret = -EPERM; goto fail; } - switch(sess->op) { - case NCR_OP_ENCRYPT: - case NCR_OP_DECRYPT: + switch (sess->op) { + case NCR_OP_ENCRYPT: + case NCR_OP_DECRYPT: + err(); + ret = -EINVAL; + goto fail; + case NCR_OP_SIGN: + case NCR_OP_VERIFY: + if (sess->algorithm->has_transparent_hash) { err(); ret = -EINVAL; goto fail; - case NCR_OP_SIGN: - case NCR_OP_VERIFY: - if (sess->algorithm->has_transparent_hash) { - err(); - ret = -EINVAL; - goto fail; - } - ret = _cryptodev_hash_update(&sess->hash, - key->key.secret.data, key->key.secret.size); - if (ret < 0) { - err(); - goto fail; - } - break; - default: + } + ret = _cryptodev_hash_update(&sess->hash, + key->key.secret.data, + key->key.secret.size); + if (ret < 0) { err(); - ret = -EINVAL; goto fail; + } + break; + default: + err(); + ret = -EINVAL; + goto fail; } ret = 0; |