1 /* tlspool/libtlspool.c -- Library function for starttls go-get-it */
15 #include <sys/types.h>
16 #include <sys/socket.h>
18 #include <sys/select.h>
19 #include <sys/resource.h>
21 #include <tlspool/starttls.h>
22 #include <tlspool/commands.h>
26 /* The master thread will run the receiving side of the socket that connects
27 * to the TLS Pool. The have_master_lock is used with _trylock() and will
28 * succeed to lock once, thereby approving the creation of the master thread.
31 static pthread_mutex_t have_master_lock = PTHREAD_MUTEX_INITIALIZER;
33 static void *master_thread (void *path);
35 static int poolfd = -1; /* Blocked retrieval with tlspool_socket() */
37 static pthread_cond_t updated_poolfd = PTHREAD_COND_INITIALIZER;
39 static pthread_mutex_t prng_lock = PTHREAD_MUTEX_INITIALIZER;
42 * Quick and dirty function to get the PID of the tlspool daemon
45 int tlspool_getpid () {
48 if ((fd = open("/var/run/tlspool.pid", O_RDONLY)) != -1) {
51 if (read(fd, str_pid, sizeof(str_pid)) != -1) {
58 /* The library function for starttls, which is normally called through one
59 * of the two inline variations below, which start client and server sides.
61 * As a side effect, this routine ensures that a master thread is running
62 * on the poolfd. This is the process that actually contacts the TLS Pool
63 * and sets up the poolfd socket.
65 int tlspool_socket (char *path) {
66 int poolfdsample = poolfd;
67 if (poolfdsample < 0) {
68 pthread_mutex_t local_cond_wait = PTHREAD_MUTEX_INITIALIZER;
70 // Now that we have established a (first) poolfd, start up
71 // the master thread that will recv() from it, and distribute.
72 if (pthread_mutex_trylock (&have_master_lock) == 0) {
77 path = TLSPOOL_DEFAULT_SOCKET_PATH;
79 if (strlen (path) + 1 > sizeof (((struct sockaddr_un *) NULL)->sun_path)) {
80 syslog (LOG_ERR, "TLS Pool path name too long for UNIX domain socket");
83 if (pthread_create (&thr, NULL, master_thread, (void *) path) != 0) {
84 syslog (LOG_NOTICE, "Failed to create TLS Pool client master thread");
85 pthread_mutex_unlock (&have_master_lock);
92 // We need enough randomness to avoid clashing ctlkeys
94 seed = ((unsigned int) time (NULL)) ^ (((unsigned int) me) << 16);
98 // Wait until the master thread signals that it updated the
99 // poolfd, as long as it is invalid.
101 // The cond_wait requires a mutex to wait on; the specs leave
102 // room for different mutexes for each waiter (otherwise it
103 // would not have been supplied with each pthread_cond_wait()
104 // call) and that helps to avoid threads to contend on a
105 // shared mutex -- which is why we use a local mutex per
106 // thread: we don't need to wait for unique access.
107 assert (pthread_mutex_lock (&local_cond_wait) == 0);
108 while (poolfdsample = poolfd, poolfdsample < 0) {
109 pthread_cond_wait (&updated_poolfd, &local_cond_wait);
111 pthread_mutex_unlock (&local_cond_wait);
117 /* Determine an upper limit for simultaneous STARTTLS threads, based on the
118 * number of available file descriptors. Note: The result is cached, so
119 * don't use root to increase beyond max in setrlimit() after calling this.
121 int tlspool_simultaneous_starttls (void) {
122 static int simu = -1;
124 struct rlimit rlimit_nofile;
125 if (getrlimit (RLIMIT_NOFILE, &rlimit_nofile) == -1) {
126 syslog (LOG_NOTICE, "Failed to determine simultaneous STARTTLS: %s", strerror (errno));
127 rlimit_nofile.rlim_max = 1024; // Pick something
129 simu = rlimit_nofile.rlim_max / 2; // 2 FDs per STARTTLS
135 /* The request registry is an array of pointers, filled by the starttls_xxx()
136 * functions for as long as they have requests standing out. The registry
137 * permits instant lookup of a mutex to signal, so the receiving end may
138 * pickup the message in its also-registered tlspool command buffer.
141 struct registry_entry {
142 pthread_mutex_t *sig; /* Wait for master thread's recvmsg() */
143 struct tlspool_command *buf; /* Buffer to hold received command */
144 int pfd; /* Client thread's assumed poolfd */
147 static struct registry_entry **registry;
149 static pthread_mutex_t registry_lock = PTHREAD_MUTEX_INITIALIZER;
152 /* Register a request handling structure under a request ID. Registers the
153 * registry entry at the given reqid; if reqid is -1, a new one, mappable to
154 * the uint16_t type for the field is allocated and set in *reqid. When the
155 * registry entry is NULL, it will be removed from the registry and the reqid
158 * The return value is 0 on success, or -1 on failure; the most probable
159 * cause for failure is
161 static int registry_update (int *reqid, struct registry_entry *entry) {
162 static int simu = -1;
163 static uint16_t pos = 0;
165 if (registry == NULL) {
166 simu = tlspool_simultaneous_starttls ();
167 registry = calloc (simu, sizeof (struct registry_entry *));
168 if (registry == NULL) {
169 syslog (LOG_NOTICE, "Failed to allocate TLS Pool request registry");
174 /* Set the entry in the given entry */
176 /* Allocate an entry in the registry */
177 assert (pthread_mutex_lock (®istry_lock) == 0);
180 if (registry [pos] == NULL) {
181 registry [pos] = entry;
190 pthread_mutex_unlock (®istry_lock);
196 if ((*reqid < 0) || (*reqid >= simu)) {
199 /* Remove the entry from the given entry */
200 assert (pthread_mutex_lock (®istry_lock) == 0);
201 registry [*reqid] = NULL; /* may not be atomic */
203 pthread_mutex_unlock (®istry_lock);
209 /* Flush registry entries with an older poolfd value; this is used after
210 * reconnecting to the TLS Pool, presumably having closed the old poolfd.
211 * Any outstanding registry entries will be sent an ERROR value at this
214 static void registry_flush (int poolfd) {
215 int regid = tlspool_simultaneous_starttls ();
216 assert (pthread_mutex_lock (®istry_lock) == 0);
217 while (regid-- > 0) {
218 struct registry_entry *entry = registry [regid];
219 if ((entry != NULL) && (entry->pfd != poolfd)) {
220 // Fill the cmd buffer with an error message
221 entry->buf->pio_cmd = PIOC_ERROR_V2;
222 entry->buf->pio_data.pioc_error.tlserrno = EPIPE;
223 strncpy (entry->buf->pio_data.pioc_error.message,
224 "No reply from TLS Pool",
225 sizeof (entry->buf->pio_data.pioc_error.message));
226 // Signal continuation to the recipient
227 pthread_mutex_unlock (entry->sig);
228 // Do not remove the entry; the recipient will do this
231 pthread_mutex_unlock (®istry_lock);
235 /* The master thread issues the recv() commands on the TLS Pool socket, and
236 * redistributes the result to the registry entries that are waiting for
237 * the data. The thread is started when the poolfd is first requested.
239 * Having a dedicated master thread is a great design simplification over
240 * temporary promotion of one of the application threads to a master status.
241 * The locking involved in the distinct state without a master, and the
242 * raceconditions while establishing the first on-demand master are dreadful.
244 * An additional advantage of a separate master thread is that it will
245 * instantly notice when the TLS Pool goes offline. At this time, it will
246 * lock the registry and cancel any requests in the registry that are
247 * waiting for the older connection. Subsequent attempts to receive are
248 * stopped immediately. The TLS Pool then tries to reconnect to the
249 * TLS Pool anew, using exponential back-off.
251 static void *master_thread (void *path) {
253 struct sockaddr_un sun;
254 struct tlspool_command cmd;
255 //NOT-USED// char anc [CMSG_SPACE(sizeof (int))];
257 struct cmsghdr *cmsg;
258 struct msghdr mh = { 0 };
259 struct registry_entry *entry;
262 // Setup path information -- value and size were checked
263 bzero (&sun, sizeof (sun));
264 strcpy (sun.sun_path, (char *) path);
265 sun.sun_family = AF_UNIX;
270 // If any old socket clients persist, tell them that the
271 // TLS Pool has been disconnected.
273 int poolfdcopy = poolfd;
274 // printf ("DEBUG: Removing old poolfd %d\n", poolfd);
280 // First, connect to the TLS Pool; upon failure, retry
281 // with 1s, 2s, 4s, 8s, 16s, 32s, 32s, 32s, ... intervals.
284 int newpoolfd = socket (AF_UNIX, SOCK_STREAM, 0);
285 if (newpoolfd != -1) {
286 if (connect (newpoolfd, (struct sockaddr *) &sun, SUN_LEN (&sun)) == 0) {
287 // printf ("DEBUG: Succeeded connect() to TLS Pool\n");
294 // printf ("DEBUG: Trying new poolfd %d for path %s\n", poolfd, sun.sun_path);
296 // Signal a newly set poolfd value to all waiting.
297 // Note that we do not need to claim a mutex first;
298 // there is always one writer to poolfd (namely, this
299 // master_thread) and the rest simply reads it. This
300 // makes a silent assumption of atomic writes to the
301 // poolfd, which seems fair because the size of an
302 // fd table has been smaller than the size of the
303 // data bus since the times of ZX Spectrum and CP/M.
304 pthread_cond_broadcast (&updated_poolfd);
305 // printf ("DEBUG: Signalled slave threads with poolfd %d\n", poolfd);
307 // Wait before repeating, with exponential back-off
311 if (usec > 32000000) {
317 // We now have an established link to the TLS Pool, until
318 // further notice -- that is, until the TLS Pool terminates.
319 // At that time, a break ends the following loop and jumps
320 // back up to the re-connection logic.
324 iov.iov_len = sizeof (cmd);
327 //NOT-USED// mh.msg_control = anc;
328 //NOT-USED// mh.msg_controllen = sizeof (anc);
329 retval = recvmsg (poolfd, &mh, MSG_NOSIGNAL);
330 if ((retval == -1) && (errno = EINTR)) {
331 continue; // Badly masked user signal
338 // This includes EPIPE, or EOF, for detached
339 // TLS Pool; the treatment is to reconnect.
340 // printf ("DEBUG: recvmsg() returned -1 due to: %s\n", strerror (errno));
344 // Determine where to post the received message
345 entry = registry [cmd.pio_reqid];
347 // Protocol error! Client detached!
348 // printf ("DEBUG: Client detached! poolfd=%d, cmd=0x%08x, reqid=%d, cbid=%d\n", poolfd, cmd.pio_cmd, cmd.pio_reqid, cmd.pio_cbid);
349 if ((cmd.pio_cbid != 0) && (cmd.pio_cmd != PIOC_ERROR_V2)) {
350 // printf ("DEBUG: Will send PIOC_ERROR_V2 as callback to TLS Pool\n");
351 // TLS Pool is waiting for a callback;
352 // Send it an ERROR message instead.
353 cmd.pio_cmd = PIOC_ERROR_V2;
354 cmd.pio_data.pioc_error.tlserrno = EPIPE;
355 strncpy (cmd.pio_data.pioc_error.message, "Client prematurely left TLS Pool negotiations", sizeof (cmd.pio_data.pioc_error.message));
356 sendmsg (poolfd, &mh, MSG_NOSIGNAL);
358 printf ("DEBUG: Sent PIOC_ERROR_V2 as callback to TLS Pool\n");
360 // Do not attempt delivery
363 if (entry->pfd != poolfd) {
364 // printf ("DEBUG: Registry entry has older poolfd %d not %d, flushing registry\n", entry->pfd, poolfd);
365 registry_flush (poolfd);
367 memcpy (entry->buf, &cmd, sizeof (cmd));
368 //NOT-USED// deliver anc or passfd to recipient
369 pthread_mutex_unlock (entry->sig);
370 // printf ("DEBUG: Signalled slave with new message in place\n");
376 /* Consider handling the message reception interface, if no other thread is
377 * doing that yet. Then, wait until a message has been received.
379 static void registry_recvmsg (struct registry_entry *entry) {
380 static int lastpoolfd = -1;
382 // Detect poolfd socket change for potential dangling recipients
383 if (entry->pfd != lastpoolfd) {
384 lastpoolfd = tlspool_socket (NULL);
385 if ((entry->pfd != lastpoolfd) && (lastpoolfd != -1)) {
386 // Signal PIOC_ERROR to outdated recipients.
387 // (That will include the current recipient.)
388 registry_flush (lastpoolfd);
392 // Now wait for the registered command structure to be filled
393 // by the master thread. Note that the call to tlspool_socket()
394 // above is made when this function is first called, and that
395 // routine ensures running of the master thread.
396 assert (pthread_mutex_lock (entry->sig) == 0);
400 /* The library function for ping, which is called to establish the API
401 * version and a list of facilities supported by the TLS Pool. The data
402 * supplied to the TLS Pool should represent the environment of the
403 * application, which is why no defaults are provided by this function
404 * but the application should supply all ping data.
406 * The pioc_ping structure will be copied into the command structure,
407 * and upon completion it will be copied back. Normally, the application
408 * would set YYYYMMDD_producer to TLSPOOL_IDENTITY_V2, and facilities
409 * to PIOF_FACILITY_ALL_CURRENT. The TLS Pool overwrites the former and
410 * resets unsupported bits in the latter. Note that facilities may be
411 * unsupported due to the compile-time environment of the TLS Pool or
412 * because it was configured without the requested support.
414 * This function returns zero on success, and -1 on failure. In case of
415 * failure, errno will be set.
417 int tlspool_ping (pingpool_t *pingdata) {
418 struct tlspool_command cmd;
419 pthread_mutex_t recvwait = PTHREAD_MUTEX_INITIALIZER;
420 struct registry_entry regent = { .sig = &recvwait, .buf = &cmd };
421 int entry_reqid = -1;
424 struct msghdr mh = { 0 };
426 /* Prepare command structure */
427 poolfd = tlspool_socket (NULL);
432 /* Finish setting up the registry entry */
434 pthread_mutex_lock (&recvwait); // Will await unlock by master
435 /* Determine the request ID */
436 if (registry_update (&entry_reqid, ®ent) != 0) {
440 bzero (&cmd, sizeof (cmd)); /* Do not leak old stack info */
441 cmd.pio_reqid = entry_reqid;
443 cmd.pio_cmd = PIOC_PING_V2;
444 memcpy (&cmd.pio_data.pioc_ping, pingdata, sizeof (struct pioc_ping));
446 /* Send the request */
448 iov.iov_len = sizeof (cmd);
451 if (sendmsg (poolfd, &mh, MSG_NOSIGNAL) == -1) {
452 // Let SIGPIPE be reported as EPIPE
453 registry_update (&entry_reqid, NULL);
454 // errno inherited from sendmsg()
458 /* Await response and process it */
459 registry_recvmsg (®ent);
460 registry_update (&entry_reqid, NULL);
461 switch (cmd.pio_cmd) {
463 /* Bad luck, we failed */
464 syslog (LOG_INFO, "TLS Pool error to tlspool_ping(): %s", cmd.pio_data.pioc_error.message);
465 errno = cmd.pio_data.pioc_error.tlserrno;
468 /* Wheee!!! we're done */
469 memcpy (pingdata, &cmd.pio_data.pioc_ping, sizeof (pingpool_t));
472 /* V2 protocol error */
479 /* The library function for starttls, which is normally called through one
480 * of the two inline variations below, which start client and server sides.
482 * The cryptfd handle supplies the TLS connection that is assumed to have
483 * been setup. When the function ends, either in success or failure, this
484 * handle will no longer be available to the caller; the responsibility of
485 * closing it is passed on to the function and/or the TLS Pool.
487 * The tlsdata structure will be copied into the command structure,
488 * and upon completion it will be copied back. You can use it to
489 * communicate flags, protocols and other parameters, including the
490 * most important settings -- local and remote identifiers. See
491 * the socket protocol document for details.
493 * The privdata handle is used in conjunction with the namedconnect() call;
494 * it is passed on to connect the latter to the context from which it was
495 * called and is not further acted upon by this function.
497 * The namedconnect() function is called when the identities have been
498 * exchanged, and established, in the TLS handshake. This is the point
499 * at which a connection to the plaintext side is needed, and a callback
500 * to namedconnect() is made to find a handle for it. The function is
501 * called with a version of the tlsdata that has been updated by the
502 * TLS Pool to hold the local and remote identities. The return value
503 * should be -1 on error, with errno set, or it should be a valid file
504 * handle that can be passed back to the TLS Pool to connect to.
506 * When the namedconnect argument passed is NULL, default behaviour is
507 * triggered. This interprets the privdata handle as an (int *) holding
508 * a file descriptor. If its value is valid, that is, >= 0, it will be
509 * returned directly; otherwise, a socketpair is constructed, one of the
510 * sockets is stored in privdata for use by the caller and the other is
511 * returned as the connected file descriptor for use by the TLS Pool.
512 * This means that the privdata must be properly initialised for this
513 * use, with either -1 (to create a socketpair) or the TLS Pool's
514 * plaintext file descriptor endpoint. The file handle returned in
515 * privdata, if it is >= 0, should be closed by the caller, both in case
516 * of success and failure.
518 * This function returns zero on success, and -1 on failure. In case of
519 * failure, errno will be set.
521 int tlspool_starttls (int cryptfd, starttls_t *tlsdata,
523 int (*namedconnect) (starttls_t *tlsdata,void *privdata)) {
524 struct tlspool_command cmd;
525 pthread_mutex_t recvwait = PTHREAD_MUTEX_INITIALIZER;
526 struct registry_entry regent = { .sig = &recvwait, .buf = &cmd };
527 int entry_reqid = -1;
531 char anc [CMSG_SPACE(sizeof (int))];
533 struct cmsghdr *cmsg;
534 struct msghdr mh = { 0 };
536 int renegotiate = 0 != (tlsdata->flags & PIOF_STARTTLS_RENEGOTIATE);
538 /* Prepare command structure */
539 poolfd = tlspool_socket (NULL);
545 /* Finish setting up the registry entry */
547 pthread_mutex_lock (&recvwait); // Will await unlock by master
548 /* Determine the request ID */
549 if (registry_update (&entry_reqid, ®ent) != 0) {
554 bzero (&cmd, sizeof (cmd)); /* Do not leak old stack info */
555 cmd.pio_reqid = entry_reqid;
557 cmd.pio_cmd = PIOC_STARTTLS_V2;
558 memcpy (&cmd.pio_data.pioc_starttls, tlsdata, sizeof (struct pioc_starttls));
560 #if RAND_MAX < 0xfffff
561 # error "Failure on assumption of 16 bits of random material per random() call"
564 #if TLSPOOL_CTLKEYLEN != 16
565 # error "Failure on assumption of 16 bytes per ctlkey"
569 assert (pthread_mutex_lock (&prng_lock) == 0);
570 * (uint16_t *) &cmd.pio_data.pioc_starttls.ctlkey [ 0] = random ();
571 * (uint16_t *) &cmd.pio_data.pioc_starttls.ctlkey [ 2] = random ();
572 * (uint16_t *) &cmd.pio_data.pioc_starttls.ctlkey [ 4] = random ();
573 * (uint16_t *) &cmd.pio_data.pioc_starttls.ctlkey [ 6] = random ();
574 * (uint16_t *) &cmd.pio_data.pioc_starttls.ctlkey [ 8] = random ();
575 * (uint16_t *) &cmd.pio_data.pioc_starttls.ctlkey [10] = random ();
576 * (uint16_t *) &cmd.pio_data.pioc_starttls.ctlkey [12] = random ();
577 * (uint16_t *) &cmd.pio_data.pioc_starttls.ctlkey [14] = random ();
578 pthread_mutex_unlock (&prng_lock);
580 // printf ("DEBUG: ctlkey =");
581 // {int i; for (i=0;i<16;i++) printf (" %02x", cmd.pio_data.pioc_starttls.ctlkey [i]);}
584 /* Send the request */
586 iov.iov_len = sizeof (cmd);
591 mh.msg_control = anc;
592 mh.msg_controllen = sizeof (anc);
593 cmsg = CMSG_FIRSTHDR (&mh);
594 cmsg->cmsg_level = SOL_SOCKET;
595 cmsg->cmsg_type = SCM_RIGHTS;
596 * (int *) CMSG_DATA (cmsg) = cryptfd; /* cannot close it yet */
597 cmsg->cmsg_len = CMSG_LEN (sizeof (int));
598 #else /* ifdef WINDOWS */
600 int len = sizeof(tmp);
602 // cmd was already set to 0, including ancilary data simulation
603 if (getsockopt ((SOCKET) cryptfd, SOL_SOCKET, SO_DONTLINGER, (char *) &tmp, &len) != SOCKET_ERROR || WSAGetLastError () != WSAENOTSOCK) {
605 int pid = tlspool_getpid();
607 cmd.pio_ancil_type = ANCIL_TYPE_SOCKET;
608 WSADuplicateSocket(cryptfd, pid, &cmd.pio_ancil_data.pioa_socket);
609 //... (..., &cmd.pio_ancil_data.pioa_socket, ...);
611 // Send a file handle
612 cmd.pio_ancil_type = ANCIL_TYPE_FILEHANDLE;
613 //... (..., &cmd.pio_ancil_data.pioa_filehandle, ...);
617 if (sendmsg (poolfd, &mh, MSG_NOSIGNAL) == -1) {
618 // Let SIGPIPE be reported as EPIPE
620 registry_update (&entry_reqid, NULL);
621 // errno inherited from sendmsg()
624 sentfd = cryptfd; /* Close anytime after response and before fn end */
626 /* Handle responses until success or error */
629 //NOTUSED// mh.msg_control = anc;
630 //NOTUSED// mh.msg_controllen = sizeof (anc);
631 registry_recvmsg (®ent);
636 switch (cmd.pio_cmd) {
638 /* Bad luck, we failed */
639 syslog (LOG_INFO, "TLS Pool error to tlspool_starttls(): %s", cmd.pio_data.pioc_error.message);
640 registry_update (&entry_reqid, NULL);
641 errno = cmd.pio_data.pioc_error.tlserrno;
643 case PIOC_STARTTLS_LOCALID_V2:
644 case PIOC_PLAINTEXT_CONNECT_V2:
646 plainfd = (*namedconnect) (tlsdata, privdata);
648 /* default namedconnect() implementation */
649 plainfd = * (int *) privdata;
650 if ((plainfd < 0) && (cmd.pio_cmd == PIOC_PLAINTEXT_CONNECT_V2)) {
652 //TODO// Setup for TCP, UDP, SCTP
653 if (socketpair (AF_UNIX, SOCK_SEQPACKET, 0, soxx) == 0) {
654 /* Socketpair created */
656 * (int *) privdata = soxx [1];
658 /* Socketpair failed */
659 cmd.pio_cmd = PIOC_ERROR_V2;
660 cmd.pio_data.pioc_error.tlserrno = errno;
665 /* We may now have a value to send in plainfd */
668 mh.msg_control = anc;
669 mh.msg_controllen = sizeof (anc);
670 cmsg = CMSG_FIRSTHDR (&mh);
671 cmsg->cmsg_level = SOL_SOCKET;
672 cmsg->cmsg_type = SCM_RIGHTS;
673 * (int *) CMSG_DATA (cmsg) = plainfd;
674 cmsg->cmsg_len = CMSG_LEN (sizeof (int));
675 #else /* ifdef WINDOWS */
677 int len = sizeof(tmp);
679 // cmd was already set to 0, including ancilary data simulation
680 if (getsockopt ((SOCKET) cryptfd, SOL_SOCKET, SO_DONTLINGER, (char *) &tmp, &len) != SOCKET_ERROR || WSAGetLastError () != WSAENOTSOCK) {
682 int pid = tlspool_getpid();
684 cmd.pio_ancil_type = ANCIL_TYPE_SOCKET;
685 WSADuplicateSocket(cryptfd, pid, &cmd.pio_ancil_data.pioa_socket);
686 //... (..., &cmd.pio_ancil_data.pioa_socket, ...);
688 // Send a file handle
689 cmd.pio_ancil_type = ANCIL_TYPE_FILEHANDLE;
690 //... (..., &cmd.pio_ancil_data.pioa_filehandle, ...);
694 /* Now supply plainfd in the callback response */
696 if (sendmsg (poolfd, &mh, MSG_NOSIGNAL) == -1) {
697 // Let SIGPIPE be reported as EPIPE
702 registry_update (&entry_reqid, NULL);
703 // errno inherited from sendmsg()
706 break; // Loop around and try again
707 case PIOC_STARTTLS_V2:
708 /* Wheee!!! we're done */
712 /* V2 protocol error */
713 registry_update (&entry_reqid, NULL);
719 /* Close the now-duplicated or now-erradicated plaintext fd */
721 memcpy (tlsdata, &cmd.pio_data.pioc_starttls, sizeof (struct pioc_starttls));
722 printf ("DEBUG: Returning control key %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n", tlsdata->ctlkey [0], tlsdata->ctlkey [1], tlsdata->ctlkey [2], tlsdata->ctlkey [3], tlsdata->ctlkey [4], tlsdata->ctlkey [5], tlsdata->ctlkey [6], tlsdata->ctlkey [7], tlsdata->ctlkey [8], tlsdata->ctlkey [9], tlsdata->ctlkey [10], tlsdata->ctlkey [11], tlsdata->ctlkey [12], tlsdata->ctlkey [13], tlsdata->ctlkey [14], tlsdata->ctlkey [15]);
723 registry_update (&entry_reqid, NULL);
728 /* The library function to send a control connection command, notably
729 * TLSPOOL_CONTROL_DETACH and TLSPOOL_CONTROL_REATTACH.
731 * This function returns zero on success, and -1 on failure. In case of
732 * failure, errno will be set.
734 int _tlspool_control_command (int cmdcode, uint8_t *ctlkey) {
735 struct tlspool_command cmd;
736 pthread_mutex_t recvwait = PTHREAD_MUTEX_INITIALIZER;
737 struct registry_entry regent = { .sig = &recvwait, .buf = &cmd };
738 int entry_reqid = -1;
741 /* Prepare command structure */
742 poolfd = tlspool_socket (NULL);
747 /* Finish setting up the registry entry */
749 pthread_mutex_lock (&recvwait); // Will await unlock by master
750 /* Determine the request ID */
751 if (registry_update (&entry_reqid, ®ent) != 0) {
755 bzero (&cmd, sizeof (cmd)); /* Do not leak old stack info */
756 cmd.pio_reqid = entry_reqid;
758 cmd.pio_cmd = cmdcode;
759 memcpy (&cmd.pio_data.pioc_control.ctlkey, ctlkey, TLSPOOL_CTLKEYLEN);
760 // printf ("DEBUG: Using control key %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n", cmd.pio_data.pioc_control.ctlkey [0], cmd.pio_data.pioc_control.ctlkey [1], cmd.pio_data.pioc_control.ctlkey [2], cmd.pio_data.pioc_control.ctlkey [3], cmd.pio_data.pioc_control.ctlkey [4], cmd.pio_data.pioc_control.ctlkey [5], cmd.pio_data.pioc_control.ctlkey [6], cmd.pio_data.pioc_control.ctlkey [7], cmd.pio_data.pioc_control.ctlkey [8], cmd.pio_data.pioc_control.ctlkey [9], cmd.pio_data.pioc_control.ctlkey [10], cmd.pio_data.pioc_control.ctlkey [11], cmd.pio_data.pioc_control.ctlkey [12], cmd.pio_data.pioc_control.ctlkey [13], cmd.pio_data.pioc_control.ctlkey [14], cmd.pio_data.pioc_control.ctlkey [15]);
762 /* Send the request */
763 if (send (poolfd, &cmd, sizeof (cmd), MSG_NOSIGNAL) == -1) {
764 // Let SIGPIPE be reported as EPIPE
765 registry_update (&entry_reqid, NULL);
766 // errno inherited from send()
770 /* Receive the response */
771 registry_recvmsg (®ent);
772 switch (cmd.pio_cmd) {
773 case PIOC_SUCCESS_V2:
778 errno = cmd.pio_data.pioc_error.tlserrno;
788 /* Generate a pseudo-random sequence based on session cryptographic keys.
790 * In the case of TLS, this adheres to RFC 5705; other protocols may or
791 * may not support a similar mechanism, in which case an error is returned.
793 * This leans on access privileges to an existing connection at a meta-level,
794 * for which we use the customary ctlkey verification mechanism introduced with
795 * tlspool_starttls (). Note that random material may be used for security
796 * purposes, such as finding the same session key for both sides deriving from
797 * prior key negotiation; the protection of a ctlkey for such applications is
800 * The inputs to this function must adhere to the following restrictions:
801 * - label must not be a NULL pointer, but opt_ctxvalue may be set to NULL
802 * to bypass the use of a context value. Note that passing an empty string
803 * in opt_ctxvalue is different from not providing the string at all by
804 * setting it to NULL.
805 * - label and opt_ctxvalue (if non-NULL) refer to ASCII strings with
806 * printable characters, terminated with a NUL character. The maximum
807 * string length of each is 254 bytes.
808 * - prng_len holds the requested number of pseudo-random bytes
809 * - prng_buf points is a non-NULL pointer to a buffer that can hold
812 * If the operation succeeds, then prng_buf holds prng_len bytes of random
813 * material, and zero is returned. If the operation fails, then prng_buf
814 * is filled with zero bytes (to make it stand out as a rather rare case of
815 * a random byte string) and -1 is returned.
817 * Note a few restrictions to the generality of this function, as a result of
818 * the underlying packet format for the communication with the TLS Pool; but
819 * the dimensions have been choosen such that these restrictions would not
820 * typically be a problem in practice:
821 * - it constrains the string lengths of label and opt_ctxvalue
822 * - it constrains prng_len to a maximum value of TLSPOOL_PRNGBUFLEN
824 * The TLS Pool may limit certain TLS PRNG labels, in adherence to the
825 * IANA-maintained TLS Exporter Label Registry. It additionally supports
826 * the EXPERIMENTAL label prefix specified in RFC 5705.
828 * Be advised that the maximum size of buffer may increase in future releases.
829 * So, be sure to use TLSPOOL_PRNGBUFLEN which holds the header-file defined
832 int tlspool_prng (char *label, char *opt_ctxvalue,
833 uint16_t prng_len, uint8_t *prng_buf,
835 struct tlspool_command cmd;
836 pthread_mutex_t recvwait = PTHREAD_MUTEX_INITIALIZER;
837 struct registry_entry regent = { .sig = &recvwait, .buf = &cmd };
838 int entry_reqid = -1;
841 struct msghdr mh = { 0 };
843 bzero (prng_buf, prng_len);
846 if ((prng_len > TLSPOOL_PRNGBUFLEN) ||
847 (label == NULL) || (strlen (label) > 254) ||
848 ((opt_ctxvalue != NULL) &&
849 ((strlen (opt_ctxvalue) > 254) ||
850 (strlen (label) + strlen (opt_ctxvalue) > TLSPOOL_PRNGBUFLEN - TLSPOOL_CTLKEYLEN)))) {
856 /* Prepare command structure */
857 poolfd = tlspool_socket (NULL);
862 /* Finish setting up the registry entry */
864 pthread_mutex_lock (&recvwait); // Will await unlock by master
865 /* Determine the request ID */
866 if (registry_update (&entry_reqid, ®ent) != 0) {
870 bzero (&cmd, sizeof (cmd)); /* Do not leak old stack info */
871 cmd.pio_reqid = entry_reqid;
873 cmd.pio_cmd = PIOC_PRNG_V2;
874 cmd.pio_data.pioc_prng.prng_len = prng_len;
875 memcpy (cmd.pio_data.pioc_prng.buffer, ctlkey, TLSPOOL_CTLKEYLEN);
876 cmd.pio_data.pioc_prng.in1_len = strlen (label);
877 memcpy (cmd.pio_data.pioc_prng.buffer + TLSPOOL_CTLKEYLEN, label, cmd.pio_data.pioc_prng.in1_len);
878 if (opt_ctxvalue != NULL) {
879 cmd.pio_data.pioc_prng.in2_len = strlen (opt_ctxvalue);
880 memcpy (cmd.pio_data.pioc_prng.buffer + TLSPOOL_CTLKEYLEN + cmd.pio_data.pioc_prng.in1_len, opt_ctxvalue, cmd.pio_data.pioc_prng.in2_len);
882 cmd.pio_data.pioc_prng.in2_len = -1;
885 /* Send the request */
887 iov.iov_len = sizeof (cmd);
890 if (sendmsg (poolfd, &mh, MSG_NOSIGNAL) == -1) {
891 // Let SIGPIPE be reported as EPIPE
892 registry_update (&entry_reqid, NULL);
893 // errno inherited from sendmsg()
897 /* Await response and process it */
898 registry_recvmsg (®ent);
899 registry_update (&entry_reqid, NULL);
900 switch (cmd.pio_cmd) {
902 /* Bad luck, we failed */
903 syslog (LOG_INFO, "TLS Pool error to tlspool_ping(): %s", cmd.pio_data.pioc_error.message);
904 errno = cmd.pio_data.pioc_error.tlserrno;
907 /* Wheee!!! we're done */
908 memcpy (prng_buf, cmd.pio_data.pioc_prng.buffer, prng_len);
911 /* V2 protocol error */