s6-networking
Software
skarnet.org
libsbearssl is a support library for the s6-tlsc and s6-tlsd executables when they're built against the BearSSL backend. Among other things, it offers interfaces to read private keys and certificates from a Unix filesystem, which BearSSL does not provide on its own.
BearSSL provides engines to decode PEM objects and X.509 certificates, and to run a TLS/SSL connection. However, it does not store such objects: it never allocates memory, and does not interact with the filesystem. sbearssl provides functions to address this.
When reading an object into memory, sbearssl stores all the bytes of the object in a stralloc, and the sbearssl_* structures contain indices of bytes in that stralloc. That allows the structures to remain valid even when the stralloc contents get reallocated and move to some other place in the heap. After you have finished adding data to the stralloc and are sure its contents will not move again, you can use the sbearssl_*_to functions to convert sbearssl_* structures to the corresponding br_* structures (native BearSSL), which contain pointers to memory.
BearSSL handles two types of private keys: RSA keys and EC keys (i.e. points on an elliptic curve). sbearssl adds some generic functions to handle keys no matter their type.
int sbearssl_rsa_skey_from (sbearssl_rsa_skey *l, br_rsa_private_key const *k, stralloc *sa)
Converts the RSA private key from BearSSL format (reading from a structure pointed to by k) to sbearssl format (writing to a structure pointed to by l). The data from *k's contents are copied into the stralloc in *sa. The function returns 1 on success and 0 (and sets errno) on failure.
void sbearssl_rsa_skey_to (sbearssl_rsa_skey const *l, br_rsa_private_key *k, char *s)
Converts the RSA private key from sbearssl format (reading from a structure pointed to by l) to BearSSL format (writing to a structure pointed to by k). The indices in l must refer to data stored in the string s.
int sbearssl_ec_skey_from (sbearssl_ec_skey *l, br_ec_private_key const *k, stralloc *sa)
Converts the EC private key from BearSSL format (reading from a structure pointed to by k) to sbearssl format (writing to a structure pointed to by l). The data from *k's contents are copied into the stralloc in *sa. The function returns 1 on success and 0 (and sets errno) on failure.
void sbearssl_ec_skey_to (sbearssl_ec_skey const *l, br_ec_private_key *k, char *s)
Converts the EC private key from sbearssl format (reading from a structure pointed to by l) to BearSSL format (writing to a structure pointed to by k). The indices in l must refer to data stored in the string s.
int sbearssl_skey_from (sbearssl_skey *l, br_skey const *k, stralloc *sa)
Converts the private key from BearSSL format (reading from a structure pointed to by k) to sbearssl format (writing to a structure pointed to by l). The data from *k's contents are copied into the stralloc in *sa. The function returns 1 on success and 0 (and sets errno) on failure.
void sbearssl_skey_to (sbearssl_skey const *l, br_skey *k, char *s)
Converts the private key from sbearssl format (reading from a structure pointed to by l) to BearSSL format (writing to a structure pointed to by k). The indices in l must refer to data stored in the string s.
int sbearssl_skey_readfile (char const *fn, sbearssl_skey *key, stralloc *sa)
Reads a private key from the file named fn and stores it in sbearssl format into the structure in *key, the bytes of the key being added to the stralloc in *sa.
The private key in fn can be either DER-encoded (binary format) or PEM-encoded (text format).
The function returns 0 on success. It returns a negative value in case of a system error, in which case errno identifies the error. It returns a positive value in case of an error returned by a BearSSL decoder, in which case an appropriate message can be obtained with the sbearssl_error_str() function.
BearSSL handles two types of public keys: RSA keys and EC keys (i.e. points on an elliptic curve). sbearssl adds some generic functions to handle keys no matter their type.
You normally should not handle public keys directly; you should handle x509 certificate chains instead.
int sbearssl_rsa_pkey_from (sbearssl_rsa_pkey *l, br_rsa_public_key const *k, stralloc *sa)
Converts the RSA public key from BearSSL format (reading from a structure pointed to by k) to sbearssl format (writing to a structure pointed to by l). The data from *k's contents are copied into the stralloc in *sa. The function returns 1 on success and 0 (and sets errno) on failure.
void sbearssl_rsa_pkey_to (sbearssl_rsa_pkey const *l, br_rsa_public_key *k, char *s)
Converts the RSA public key from sbearssl format (reading from a structure pointed to by l) to BearSSL format (writing to a structure pointed to by k). The indices in l must refer to data stored in the string s.
int sbearssl_ec_pkey_from (sbearssl_ec_skey *l, br_ec_public_key const *k, stralloc *sa)
Converts the EC public key from BearSSL format (reading from a structure pointed to by k) to sbearssl format (writing to a structure pointed to by l). The data from *k's contents are copied into the stralloc in *sa. The function returns 1 on success and 0 (and sets errno) on failure.
void sbearssl_ec_pkey_to (sbearssl_ec_pkey const *l, br_ec_public_key *k, char *s)
Converts the EC public key from sbearssl format (reading from a structure pointed to by l) to BearSSL format (writing to a structure pointed to by k). The indices in l must refer to data stored in the string s.
int sbearssl_pkey_from (sbearssl_pkey *l, br_x509_pkey const *k, stralloc *sa)
Converts the public key from BearSSL format (reading from a structure pointed to by k) to sbearssl format (writing to a structure pointed to by l). The data from *k's contents are copied into the stralloc in *sa. The function returns 1 on success and 0 (and sets errno) on failure.
void sbearssl_pkey_to (sbearssl_pkey const *l, br_x509_pkey *k, char *s)
Converts the public key from sbearssl format (reading from a structure pointed to by l) to BearSSL format (writing to a structure pointed to by k). The indices in l must refer to data stored in the string s.
You normally should not have to call these functions directly. Instead, you should use the higher-level functions for private keys, X509 certificate chains and trust anchors, which will perform the PEM decoding for you.
int sbearssl_pem_decode_from_buffer (buffer *b, genalloc *list, stralloc *sa)
Decodes a PEM object, reading from the buffer in *b. The decoded bytes are appended to *sa. list points to a genalloc containing objects of type sbearssl_pemobject. One sbearssl_pemobject is appended to the genalloc per PEM entity decoded from the byte stream read from the buffer.
The function returns 0 on success. It returns a negative value in case of a system error, in which case errno identifies the error. It returns a positive value in case of an error returned by a BearSSL decoder, in which case an appropriate message can be obtained with the sbearssl_error_str() function.
int sbearssl_pem_decode_from_string (char const *s, size_t len, genalloc *list, stralloc *sa)
Decodes a PEM object from the len bytes pointed to by s. The decoded bytes are appended to *sa. list points to a genalloc containing objects of type sbearssl_pemobject. One sbearssl_pemobject is appended to the genalloc per PEM entity found in the bytes in s.
The function returns 0 on success. It returns a negative value in case of a system error, in which case errno identifies the error. It returns a positive value in case of an error returned by a BearSSL decoder, in which case an appropriate message can be obtained with the sbearssl_error_str() function.
int sbearssl_cert_from (sbearssl_cert *l, br_x509_certificate const *k, stralloc *sa)
Converts a certificate from BearSSL format (reading from a structure pointed to by k) to sbearssl format (writing to a structure pointed to by l). The data from *k's contents are copied into the stralloc in *sa. The function returns 1 on success and 0 (and sets errno) on failure.
void sbearssl_cert_to (sbearssl_cert const *l, br_x509_certificate *k, char *s)
Converts a certificate from sbearssl format (reading from a structure pointed to by l) to BearSSL format (writing to a structure pointed to by k). The indices in l must refer to data stored in the string s.
int sbearssl_cert_readfile (char const *fn, genalloc *list, stralloc *sa)
Reads one or more certificates from the file named fn and appends them to the genalloc in *list, which is a dynamically growing list of sbearssl_cert structures. The bytes of the (maybe PEM-decoded, but still DER-encoded) certificate are appended to the stralloc in *sa.
The fn file can be either DER-encoded (binary format) or PEM-encoded (text format). If it is DER-encoded, it must contain exactly one X.509 certificate. If it is PEM-encoded, it may contain a chain of certificates as long as the PEM file fits within the size limits.
fn must not be bigger than SBEARSSL_MAXCERTFILESIZE, which is 8 kB. This function is meant to read individual certificates, not files containing large certificate chains or sets of trust anchors. To do that, use sbearssl_cert_readbigpem() instead.
The function returns 0 on success. It returns a negative value in case of a system error, in which case errno identifies the error. It returns a positive value in case of an error returned by a BearSSL decoder, in which case an appropriate message can be obtained with the sbearssl_error_str() function.
int sbearssl_cert_readbigpem (char const *fn, genalloc *, stralloc *sa)
Reads one or more PEM-encoded certificates from the file named fn and appends them to the genalloc in *list, which is a dynamically growing list of sbearssl_cert structures. The bytes of the PEM-decoded (but still DER-encoded) certificates are appended to the stralloc in *sa.
The function will refuse to read a file that is not valid PEM. Inside the file, It will ignore PEM objects that are not X.509 certificates.
The function returns 0 on success. It returns a negative value in case of a system error, in which case errno identifies the error. It returns a positive value in case of an error returned by a BearSSL decoder, in which case an appropriate message can be obtained with the sbearssl_error_str() function.
BearSSL clients do not use X.509-encoded certificates, they use sets of trust anchors, i.e. structures decoded from certificates representing (intermediate or) root CAs.
int sbearssl_ta_from (sbearssl_ta *l, br_x509_trust_anchor const *k, stralloc *sa)
Converts a trust anchor from BearSSL format (reading from a structure pointed to by k) to sbearssl format (writing to a structure pointed to by l). The data from *k's contents are copied into the stralloc in *sa. The function returns 1 on success and 0 (and sets errno) on failure.
void sbearssl_ta_to (sbearssl_ta const *l, br_x509_trust_anchor *k, char *s)
Converts a trust anchor from sbearssl format (reading from a structure pointed to by l) to BearSSL format (writing to a structure pointed to by k). The indices in l must refer to data stored in the string s.
int sbearssl_ta_readfile (char const *fn, genalloc *list, stralloc *sa)
Reads a set of trust anchors from a PEM file named fn which must contain a list of (intermediate or) root CA certificates. The trust anchors are appended to the genalloc in *list, which is a dynamically growing list of sbearssl_ta structures. The contents of the trust anchors are appended to *sa, which is a stralloc used for storage.
The function returns 0 on success. It returns a negative value in case of a system error, in which case errno identifies the error. It returns a positive value in case of an error returned by a BearSSL decoder, in which case an appropriate message can be obtained with the sbearssl_error_str() function.
int sbearssl_ta_readdir (char const *dir, genalloc *list, stralloc *sa)
Reads a set of trust anchors from a directory named dir, which must contain a list of (intermediate or) root CA certificates stored as individual DER- or PEM-encoded files. The trust anchors are appended to the genalloc in *list, which is a dynamically growing list of sbearssl_ta structures. The contents of the trust anchors are appended to *sa, which is a stralloc used for storage.
The function ignores files that do not contain valid DER or PEM objects containing X.509 certificates representing certification authorities.
The function returns 0 on success. It returns a negative value in case of a system error, in which case errno identifies the error. It returns a positive value in case of an error returned by a BearSSL decoder, in which case an appropriate message can be obtained with the sbearssl_error_str() function.
You probably shouldn't need to call any of these functions directly, except for the first one.
char const *sbearssl_error_str (int err)
Returns a fixed string containing an error message corresponding to the err code, which must be non-negative. The return value from a few sbearssl functions, if positive, can be interpreted via this function.
int sbearssl_isder (unsigned char const *s, size_t len)
Tests whether the array of len bytes pointed to by s looks like a DER-encoded object. Returns 1 if it does and 0 otherwise.
int sbearssl_tai_from_dayseconds (tai *t, uint32_t days, uint32_t seconds)
Makes a TAI absolute time from the date given in days and seconds as provided in an x509 certificate. Returns 1 on success and 0 on failure (which probably means days/seconds don't encode a valid date).
int sbearssl_dayseconds_from_tai (uint32_t *days, uint32_t *seconds, tai const *t)
Compute suitable days and seconds, for an x509 certificate, from an absolute TAI date. Returns 1 on success and 0 on failure (which probably means the given date doesn't fit the days/seconds format).
int sbearssl_x509_minimal_set_tai (br_x509_minimal_context *ctx, tai const *t)
Sets the validation time for the X.509 context in *ctx to the absolute time contained in *t, which is a tai. Returns 1 if it succeeds, or 0 if it fails - probably because *t does not represent a valid time.
int sbearssl_x509_minimal_set_tain (br_x509_minimal_context *ctx, tain const *a)
Same as the above function, except the time is given as a tain, i.e. a tai plus nanoseconds (which are simply ignored).
void sbearssl_drop (void)
If the process is running as root, then this function drops its privileges (else it does nothing). The gid to drop to is read from the TLS_GID environment variable; the uid to drop to is read from the TLS_UID environment variable. If those variables are not given, then the uid, or gid, or both, are not changed. If they contain something else than numerical uid/gids, the process exits 111 with an error message.
int sbearssl_send_environment (br_ssl_engine_context *ctx, int fd)
Writes a series of null-terminated strings of the form key=value to file descriptor fd; the series is terminated with an additional null character. The strings represent information about the TLS connection represented by context ctx; it is only valid to call this function after the handshake has completed. The exact keys used will change over time, but at least SSL_PROTOCOL=value and SSL_CIPHER=value are transmitted. The function returns 1 if it succeeds and 0 if it fails.
void sbearssl_run (br_ssl_engine_context *ctx, int *fds, tain const *tto, uint32_t options, unsigned int verbosity, sbearssl_handshake_cb_t_ref cb, sbearssl_handshake_cb_context_t *cbarg)
This function runs a full-duplex TLS/SSL engine, reading/writing clear text from/to two file descriptors, and writing/reading ciphertext to/from two other file descriptors, until the connection is closed both ways (either with a SSL close, or with EOF). It does not return.
sbearssl_run will make the process die with an appropriate error message if it encounters an unrecoverable error. If there were no problems and the SSL/TLS connection closed cleanly, the process exits 0.
void sbearssl_client_init_and_run (int *fds, tain const *tto, uint32_t preoptions, uint32_t options, unsigned int verbosity, char const *servername, sbearssl_handshake_cb_t_ref cb, unsigned int notif)
This function initializes a TLS context for a client-side connection, then runs the TLS engine via a call to sbearssl_run(). The function does not return. If the context cannot be initialized, the process exits 96 with an appropriate error message.
If the CADIR environment variable is set, then it must contain the path of a directory containing the hashed names of the public certificates identifying the trust anchors. Else, if the CAFILE environment variable is set, then it must contain the path to a PEM file containing all the certificates for the trust anchors. Else, the process exits 100 with an error message.
The arguments are as follows:
void sbearssl_server_init_and_run (int *fds, tain const *tto, uint32_t preoptions, uint32_t options, unsigned int verbosity, sbearssl_handshake_cb_t_ref cb, unsigned int notif)
Same as the previous function, but on the server side. No servername argument is required. The CERTFILE and KEYFILE environment variables are mandatory, they point to the server's certificate and private key. It is only necessary to set CADIR or CAFILE when bit 0 of preoptions is set (this functionality is supported server-side), in which case client authentication will be requested, and a list of trust anchors (read from either the directory in CADIR or the PEM file in CAFILE) will be used to verify the client certificate.