s6-networking
Software
skarnet.org

The sbearssl library interface

General information

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.

Compiling

Linking

Programming

General concepts

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.

Private keys (typically for servers)

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.

Public keys

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.

Generic PEM objects

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.

X.509 certificates (typically for servers)

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.

Trust anchors (typically for clients)

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.

Miscellaneous utilities

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_x509_minimal_set_tai (br_x509_minimal_context *ctx, tai_t t)

Sets the validation time for the X.509 context in *ctx to the absolute time contained in *t, which is a tai_t. 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_t a)

Same as the above function, except the time is given as a tain_t, i.e. a tai_t plus nanoseconds (which are simply ignored).

Running the TLS/SSL engine (both clients and servers)

int sbearssl_run (br_ssl_engine_context *ctx, int *fds, pid_t pid, unsigned int verbosity, uint32_t options, tain_t const *tto)

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) or a given subprocess dies.

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, it returns -1. If the application subprocess dies early, sbearssl_run returns the wstat for that subprocess, i.e. the integer containing the information about its exit code or crash signal. No matter how sbearssl_run returns, the first four descriptors in fds are closed, but the selfpipe is untouched and the caller should free ctx itself.

int sbearssl_s6tlsc (char const *const *argv, char const *const *envp, tain_t const *tto, uint32_t preoptions, uint32_t options, uid_t uid, gid_t gid, unsigned int verbosity, char const *servername, int *sfd)

This function implements s6-tlsc on top of BearSSL. It has no other practical purpose; you're better off directly invoking s6-tlsc.

int sbearssl_s6tlsd (char const *const *argv, char const *const *envp, tain_t const *tto, uint32_t preoptions, uint32_t options, uid_t uid, gid_t gid, unsigned int verbosity)

This function implements s6-tlsd on top of BearSSL. It has no other practical purpose; you're better off directly invoking s6-tlsd.