summaryrefslogtreecommitdiffstats
path: root/lib/ncrypto_alg.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/ncrypto_alg.c')
-rw-r--r--lib/ncrypto_alg.c139
1 files changed, 120 insertions, 19 deletions
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)