diff options
Diffstat (limited to 'lib/ncrypto_alg.c')
-rw-r--r-- | lib/ncrypto_alg.c | 139 |
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) |