summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMiloslav Trmač <mitr@redhat.com>2010-10-29 20:08:32 +0200
committerMiloslav Trmač <mitr@redhat.com>2010-10-29 20:08:32 +0200
commite6b6e8785e16f1c824fd1f1f333ef2591f6f0a10 (patch)
treeb57fd771372d24cdcf18c8ee6e2393be3aff4ed4
parent7241ddaa5924bc10c7a813c9163443e67b04e8d1 (diff)
parent843862b7ce325e70a0ff715006fb29fffd81e0a6 (diff)
downloadncrypto-e6b6e8785e16f1c824fd1f1f333ef2591f6f0a10.tar.gz
ncrypto-e6b6e8785e16f1c824fd1f1f333ef2591f6f0a10.tar.xz
ncrypto-e6b6e8785e16f1c824fd1f1f333ef2591f6f0a10.zip
Merge branch 'local', port cloning to AF_ALG
Conflicts: lib/ncrypto_local.c
-rw-r--r--include/ncrypto/ncrypto.h4
-rw-r--r--lib/ncrypto_alg.c139
-rw-r--r--tests/digests.c43
-rw-r--r--tests/symm_signatures.c93
4 files changed, 260 insertions, 19 deletions
diff --git a/include/ncrypto/ncrypto.h b/include/ncrypto/ncrypto.h
index f82cf0e..01964f9 100644
--- a/include/ncrypto/ncrypto.h
+++ b/include/ncrypto/ncrypto.h
@@ -124,6 +124,8 @@ struct ncr_digest_session;
CK_RV ncr_digest_alloc (struct ncr_digest_session **sess,
CK_MECHANISM_TYPE mech);
CK_RV ncr_digest_free (struct ncr_digest_session *sess);
+CK_RV ncr_digest_clone (struct ncr_digest_session **clone,
+ struct ncr_digest_session *sess);
/* Use either ncr_digest_{init,update*,final} (), or
ncr_{digest_init,digest} (). After finishing such a call sequence, a new
sequence can be started within the same session. */
@@ -189,6 +191,8 @@ struct ncr_symm_signature_session;
CK_RV ncr_symm_signature_alloc (struct ncr_symm_signature_session **sess,
CK_MECHANISM_TYPE mech);
CK_RV ncr_symm_signature_free (struct ncr_symm_signature_session *sess);
+CK_RV ncr_symm_signature_clone (struct ncr_symm_signature_session **clone,
+ struct ncr_symm_signature_session *sess);
/* Use either ncr_symm_signature_sign_{init,update,final} (), or
ncr_symm_signature_{sign_init,sign} (). After finishing such a call
sequence, a new sequence can be started within the same session. Same for
diff --git a/lib/ncrypto_alg.c b/lib/ncrypto_alg.c
index 8d0d900..d3a8393 100644
--- a/lib/ncrypto_alg.c
+++ b/lib/ncrypto_alg.c
@@ -159,6 +159,34 @@ ncr_digest_free (struct ncr_digest_session *sess)
}
CK_RV
+ncr_digest_clone (struct ncr_digest_session **clone,
+ struct ncr_digest_session *sess)
+{
+ struct ncr_digest_session *c;
+
+ g_return_val_if_fail (clone != NULL, CKR_ARGUMENTS_BAD);
+ g_return_val_if_fail (sess != NULL, CKR_SESSION_HANDLE_INVALID);
+ g_return_val_if_fail (sess->state == NDS_INITIALIZED
+ || sess->state == NDS_UPDATED,
+ CKR_OPERATION_NOT_INITIALIZED);
+
+ c = malloc (sizeof (*c));
+ if (c == NULL)
+ return CKR_HOST_MEMORY;
+
+ c->fd = accept (sess->fd, NULL, 0);
+ if (c->fd == -1)
+ {
+ free (c);
+ return ckr_errno ();
+ }
+ c->state = sess->state;
+ c->md_size = sess->md_size;
+ *clone = c;
+ return CKR_OK;
+}
+
+CK_RV
ncr_digest_init (struct ncr_digest_session *sess)
{
g_return_val_if_fail (sess != NULL, CKR_SESSION_HANDLE_INVALID);
@@ -344,12 +372,19 @@ ncr_digest_standalone (CK_MECHANISM_TYPE mech, void *dest,
slave file descriptor, but for HMAC we need the parent to be able to change
the key. */
-/* Semantically, md_size_ptr should be "size_t *", but values will fit into
- "int *" just as fine. */
+struct ncr_symm_signature_session
+{
+ int parent_fd, child_fd;
+ const struct sockaddr_alg *sa;
+ int md_size; /* size_t semantically */
+ bool signing;
+ /* Debugging only */
+ enum { NSSS_NEW, NSSS_INITIALIZED, NSSS_UPDATED, NSSS_FINISHED } state;
+};
+
static CK_RV
-symm_signature_params_from_mech (CK_MECHANISM_TYPE mech,
- const struct sockaddr_alg **sa_ptr,
- int *md_size_ptr)
+symm_signature_params_from_mech (struct ncr_symm_signature_session *sess,
+ CK_MECHANISM_TYPE mech)
{
const struct sockaddr_alg *sa;
int md_size;
@@ -377,26 +412,16 @@ symm_signature_params_from_mech (CK_MECHANISM_TYPE mech,
default:
g_return_val_if_reached (CKR_MECHANISM_INVALID);
}
- *sa_ptr = sa;
- *md_size_ptr = md_size;
+ sess->sa = sa;
+ sess->md_size = md_size;
return CKR_OK;
}
-struct ncr_symm_signature_session
-{
- int parent_fd, child_fd;
- int md_size; /* size_t semantically */
- bool signing;
- /* Debugging only */
- enum { NSSS_NEW, NSSS_INITIALIZED, NSSS_UPDATED, NSSS_FINISHED } state;
-};
-
CK_RV
ncr_symm_signature_alloc (struct ncr_symm_signature_session **sess,
CK_MECHANISM_TYPE mech)
{
struct ncr_symm_signature_session *s;
- const struct sockaddr_alg *sa;
CK_RV res;
g_return_val_if_fail (sess != NULL, CKR_ARGUMENTS_BAD);
@@ -405,7 +430,7 @@ ncr_symm_signature_alloc (struct ncr_symm_signature_session **sess,
if (s == NULL)
return CKR_HOST_MEMORY;
- res = symm_signature_params_from_mech (mech, &sa, &s->md_size);
+ res = symm_signature_params_from_mech (s, mech);
if (res != CKR_OK)
goto err_s;
@@ -415,7 +440,7 @@ ncr_symm_signature_alloc (struct ncr_symm_signature_session **sess,
res = ckr_errno ();
goto err_s;
}
- if (bind (s->parent_fd, (struct sockaddr *)sa, sizeof (*sa)) != 0)
+ if (bind (s->parent_fd, (struct sockaddr *)s->sa, sizeof (*s->sa)) != 0)
{
res = ckr_errno ();
goto err_parent_fd;
@@ -445,6 +470,82 @@ ncr_symm_signature_free (struct ncr_symm_signature_session *sess)
return CKR_OK;
}
+CK_RV
+ncr_symm_signature_clone (struct ncr_symm_signature_session **clone,
+ struct ncr_symm_signature_session *sess)
+{
+ struct ncr_symm_signature_session *c;
+ int new_sess_parent_fd;
+ CK_RV res;
+
+ g_return_val_if_fail (clone != NULL, CKR_ARGUMENTS_BAD);
+ g_return_val_if_fail (sess != NULL, CKR_SESSION_HANDLE_INVALID);
+ g_return_val_if_fail (sess->state == NSSS_INITIALIZED
+ || sess->state == NSSS_UPDATED,
+ CKR_OPERATION_NOT_INITIALIZED);
+
+ c = malloc (sizeof (*c));
+ if (c == NULL)
+ return CKR_HOST_MEMORY;
+
+ /* This is a little complicated: parent_fd holds the "transform", which is
+ parametrized by the key. A mere accept () on child_fd would create two
+ sockets sharing a parent_fd, and reinitializing a session on one with a
+ different key would change the underlying key of the other.
+
+ Therefore, create an entirely new parent_fd for _both_ clones. The
+ "old" parent_fd will be implicitly referred to by child_fd of both clones,
+ but any session reinitialization will use the new parent_fd values. */
+ new_sess_parent_fd = socket (AF_ALG, SOCK_SEQPACKET, 0);
+ if (new_sess_parent_fd == -1)
+ {
+ res = ckr_errno ();
+ goto err_c;
+ }
+ if (bind (new_sess_parent_fd, (struct sockaddr *)sess->sa,
+ sizeof (*sess->sa)) != 0)
+ {
+ res = ckr_errno ();
+ goto err_new_sess_parent_fd;
+ }
+
+ c->parent_fd = socket (AF_ALG, SOCK_SEQPACKET, 0);
+ if (c->parent_fd == -1)
+ {
+ res = ckr_errno ();
+ goto err_new_sess_parent_fd;
+ }
+ if (bind (c->parent_fd, (struct sockaddr *)sess->sa, sizeof (*sess->sa)) != 0)
+ {
+ res = ckr_errno ();
+ goto err_c_parent_fd;
+ }
+
+ c->child_fd = accept (sess->child_fd, NULL, 0);
+ if (c->child_fd == -1)
+ {
+ res = ckr_errno ();
+ goto err_c_parent_fd;
+ }
+
+ (void)close (sess->parent_fd);
+ sess->parent_fd = new_sess_parent_fd;
+ c->state = sess->state;
+ c->sa = sess->sa;
+ c->md_size = sess->md_size;
+ c->signing = sess->signing;
+ *clone = c;
+ return CKR_OK;
+
+ err_c_parent_fd:
+ (void)close (c->parent_fd);
+ err_new_sess_parent_fd:
+ (void)close (new_sess_parent_fd);
+ err_c:
+ free (c);
+ return res;
+}
+
static CK_RV
symm_signature_init (struct ncr_symm_signature_session *sess, bool sign,
struct ncr_symm_key *key)
diff --git a/tests/digests.c b/tests/digests.c
index 8013698..d8ca31c 100644
--- a/tests/digests.c
+++ b/tests/digests.c
@@ -142,6 +142,49 @@ main (void)
assert (res == CKR_OK);
for (j = 0; j < 2; j++)
{
+ struct ncr_digest_session *clone;
+
+ res = ncr_digest_init (sess);
+ assert (res == CKR_OK);
+
+ res = ncr_digest_update (sess, tvs[i].input, tvs[i].input_size / 2);
+ assert (res == CKR_OK);
+
+ res = ncr_digest_clone (&clone, sess);
+ assert (res == CKR_OK);
+
+ res = ncr_digest_update (sess, "", 1);
+ assert (res == CKR_OK);
+
+ dest_size = sizeof (dest);
+ res = ncr_digest_final (sess, dest, &dest_size);
+ assert (res == CKR_OK);
+ assert (dest_size == tvs[i].output_size);
+ assert (memcmp (dest, tvs[i].output, dest_size) != 0);
+
+ res = ncr_digest_update (clone, tvs[i].input + tvs[i].input_size / 2,
+ tvs[i].input_size - tvs[i].input_size / 2);
+ assert (res == CKR_OK);
+
+ dest_size = sizeof (dest);
+ res = ncr_digest_final (clone, dest, &dest_size);
+ assert (res == CKR_OK);
+ assert (dest_size == tvs[i].output_size);
+ assert (memcmp (dest, tvs[i].output, dest_size) == 0);
+
+ res = ncr_digest_free (clone);
+ assert (res == CKR_OK);
+ }
+ res = ncr_digest_free (sess);
+ assert (res == CKR_OK);
+ }
+
+ for (i = 0; i < G_N_ELEMENTS (tvs); i++)
+ {
+ res = ncr_digest_alloc (&sess, tvs[i].mech);
+ assert (res == CKR_OK);
+ for (j = 0; j < 2; j++)
+ {
res = ncr_digest_init (sess);
assert (res == CKR_OK);
diff --git a/tests/symm_signatures.c b/tests/symm_signatures.c
index 17ca560..003d19d 100644
--- a/tests/symm_signatures.c
+++ b/tests/symm_signatures.c
@@ -138,6 +138,99 @@ main (void)
for (j = 0; j < 2; j++)
{
+ struct ncr_symm_signature_session *clone;
+
+ res = ncr_symm_signature_sign_init (sess, key);
+ assert (res == CKR_OK);
+
+ res = ncr_symm_signature_sign_update (sess, tvs[i].input,
+ tvs[i].input_size / 2);
+ assert (res == CKR_OK);
+
+ res = ncr_symm_signature_clone (&clone, sess);
+ assert (res == CKR_OK);
+
+ res = ncr_symm_signature_sign_update (sess, "", 1);
+ assert (res == CKR_OK);
+
+ dest_size = sizeof (dest);
+ res = ncr_symm_signature_sign_final (sess, dest, &dest_size);
+ assert (res == CKR_OK);
+ assert (dest_size == tvs[i].output_size);
+ assert (memcmp (dest, tvs[i].output, dest_size) != 0);
+
+ res = ncr_symm_signature_sign_update (clone, tvs[i].input
+ + tvs[i].input_size / 2,
+ tvs[i].input_size
+ - tvs[i].input_size / 2);
+ assert (res == CKR_OK);
+
+ dest_size = sizeof (dest);
+ res = ncr_symm_signature_sign_final (clone, dest, &dest_size);
+ assert (res == CKR_OK);
+ assert (dest_size == tvs[i].output_size);
+ assert (memcmp (dest, tvs[i].output, dest_size) == 0);
+
+ res = ncr_symm_signature_free (clone);
+ assert (res == CKR_OK);
+
+ for (k = 0; k < 2; k++)
+ {
+ res = ncr_symm_signature_verify_init (sess, key);
+ assert (res == CKR_OK);
+
+ res = ncr_symm_signature_verify_update (sess, tvs[i].input,
+ tvs[i].input_size / 2);
+ assert (res == CKR_OK);
+
+ res = ncr_symm_signature_clone (&clone, sess);
+ assert (res == CKR_OK);
+
+ res = ncr_symm_signature_verify_update (sess, "", 1);
+ assert (res == CKR_OK);
+
+ res = ncr_symm_signature_verify_final (sess, tvs[i].output,
+ tvs[i].output_size);
+ assert (res == CKR_SIGNATURE_INVALID);
+
+ res = ncr_symm_signature_verify_update (clone, tvs[i].input
+ + tvs[i].input_size / 2,
+ tvs[i].input_size
+ - tvs[i].input_size / 2);
+ assert (res == CKR_OK);
+
+ memcpy (dest, tvs[i].output, tvs[i].output_size);
+ dest[0] += k;
+ res = ncr_symm_signature_verify_final (clone, dest,
+ tvs[i].output_size);
+ if (k == 0)
+ assert (res == CKR_OK);
+ else
+ assert (res == CKR_SIGNATURE_INVALID);
+
+ res = ncr_symm_signature_free (clone);
+ assert (res == CKR_OK);
+ }
+ }
+
+ res = ncr_symm_key_destroy (key);
+ assert (res == CKR_OK);
+
+ res = ncr_symm_signature_free (sess);
+ assert (res == CKR_OK);
+ }
+
+ for (i = 0; i < G_N_ELEMENTS (tvs); i++)
+ {
+ res = ncr_symm_signature_alloc (&sess, tvs[i].mech);
+ assert (res == CKR_OK);
+
+ res = ncr_symm_key_create (&key, CKK_GENERIC_SECRET, tvs[i].key,
+ tvs[i].key_size);
+ assert (res == CKR_OK);
+
+ for (j = 0; j < 2; j++)
+ {
res = ncr_symm_signature_sign_init (sess, key);
assert (res == CKR_OK);