X-Git-Url: https://www.bearssl.org/gitweb//home/git/?p=BearSSL;a=blobdiff_plain;f=inc%2Fbearssl_x509.h;h=49d2fba0d5bc45a99ba0e47fd7d76924205e57c7;hp=c73b5b3f5a89613ffd2d659901dfb6f97a02a95a;hb=15b3af72f3220cae0bba4080db653d0124bf9414;hpb=e61ad42191511226309bad2cbde8cd9e8cc743cb diff --git a/inc/bearssl_x509.h b/inc/bearssl_x509.h index c73b5b3..49d2fba 100644 --- a/inc/bearssl_x509.h +++ b/inc/bearssl_x509.h @@ -32,6 +32,10 @@ #include "bearssl_hash.h" #include "bearssl_rsa.h" +#ifdef __cplusplus +extern "C" { +#endif + /** \file bearssl_x509.h * * # X.509 Certificate Chain Processing @@ -356,7 +360,7 @@ typedef struct { * - `end_chain()` is called when the last certificate in the chain * was processed. * - `get_pkey()` is called after chain processing, if the chain - * validation was succesfull. + * validation was successful. * * A context structure may be reused; the `start_chain()` method shall * ensure (re)initialisation. @@ -551,6 +555,76 @@ void br_x509_knownkey_init_ec(br_x509_knownkey_context *ctx, #define BR_X509_BUFSIZE_SIG 512 #endif +/** + * \brief Type for receiving a name element. + * + * An array of such structures can be provided to the X.509 decoding + * engines. If the specified elements are found in the certificate + * subject DN or the SAN extension, then the name contents are copied + * as zero-terminated strings into the buffer. + * + * The decoder converts TeletexString and BMPString to UTF8String, and + * ensures that the resulting string is zero-terminated. If the string + * does not fit in the provided buffer, then the copy is aborted and an + * error is reported. + */ +typedef struct { + /** + * \brief Element OID. + * + * For X.500 name elements (to be extracted from the subject DN), + * this is the encoded OID for the requested name element; the + * first byte shall contain the length of the DER-encoded OID + * value, followed by the OID value (for instance, OID 2.5.4.3, + * for id-at-commonName, will be `03 55 04 03`). This is + * equivalent to full DER encoding with the length but without + * the tag. + * + * For SAN name elements, the first byte (`oid[0]`) has value 0, + * followed by another byte that matches the expected GeneralName + * tag. Allowed second byte values are then: + * + * - 1: `rfc822Name` + * + * - 2: `dNSName` + * + * - 6: `uniformResourceIdentifier` + * + * - 0: `otherName` + * + * If first and second byte are 0, then this is a SAN element of + * type `otherName`; the `oid[]` array should then contain, right + * after the two bytes of value 0, an encoded OID (with the same + * conventions as for X.500 name elements). If a match is found + * for that OID, then the corresponding name element will be + * extracted, as long as it is a supported string type. + */ + const unsigned char *oid; + + /** + * \brief Destination buffer. + */ + char *buf; + + /** + * \brief Length (in bytes) of the destination buffer. + * + * The buffer MUST NOT be smaller than 1 byte. + */ + size_t len; + + /** + * \brief Decoding status. + * + * Status is 0 if the name element was not found, 1 if it was + * found and decoded, or -1 on error. Error conditions include + * an unrecognised encoding, an invalid encoding, or a string + * too large for the destination buffer. + */ + int status; + +} br_name_element; + /** * \brief The "minimal" X.509 engine structure. * @@ -643,6 +717,12 @@ typedef struct { unsigned char next_dn_hash[64]; unsigned char saved_dn_hash[64]; + /* + * Name elements to gather. + */ + br_name_element *name_elts; + size_t num_name_elts; + /* * Public key cryptography implementations (signature verification). */ @@ -746,6 +826,20 @@ br_x509_minimal_set_ecdsa(br_x509_minimal_context *ctx, ctx->iec = iec; } +/** + * \brief Initialise a "minimal" X.509 engine with default algorithms. + * + * This function performs the same job as `br_x509_minimal_init()`, but + * also sets implementations for RSA, ECDSA, and the standard hash + * functions. + * + * \param ctx context to initialise. + * \param trust_anchors trust anchors. + * \param trust_anchors_num number of trust anchors. + */ +void br_x509_minimal_init_full(br_x509_minimal_context *ctx, + const br_x509_trust_anchor *trust_anchors, size_t trust_anchors_num); + /** * \brief Set the validation time for the X.509 "minimal" engine. * @@ -798,6 +892,26 @@ br_x509_minimal_set_minrsa(br_x509_minimal_context *ctx, int byte_length) ctx->min_rsa_size = (int16_t)(byte_length - 128); } +/** + * \brief Set the name elements to gather. + * + * The provided array is linked in the context. The elements are + * gathered from the EE certificate. If the same element type is + * requested several times, then the relevant structures will be filled + * in the order the matching values are encountered in the certificate. + * + * \param ctx validation context. + * \param elts array of name element structures to fill. + * \param num_elts number of name element structures to fill. + */ +static inline void +br_x509_minimal_set_name_elements(br_x509_minimal_context *ctx, + br_name_element *elts, size_t num_elts) +{ + ctx->name_elts = elts; + ctx->num_name_elts = num_elts; +} + /** * \brief X.509 decoder context. * @@ -1135,4 +1249,149 @@ br_skey_decoder_get_ec(const br_skey_decoder_context *ctx) } } +/** + * \brief Encode an RSA private key (raw DER format). + * + * This function encodes the provided key into the "raw" format specified + * in PKCS#1 (RFC 8017, Appendix C, type `RSAPrivateKey`), with DER + * encoding rules. + * + * The key elements are: + * + * - `sk`: the private key (`p`, `q`, `dp`, `dq` and `iq`) + * + * - `pk`: the public key (`n` and `e`) + * + * - `d` (size: `dlen` bytes): the private exponent + * + * The public key elements, and the private exponent `d`, can be + * recomputed from the private key (see `br_rsa_compute_modulus()`, + * `br_rsa_compute_pubexp()` and `br_rsa_compute_privexp()`). + * + * If `dest` is not `NULL`, then the encoded key is written at that + * address, and the encoded length (in bytes) is returned. If `dest` is + * `NULL`, then nothing is written, but the encoded length is still + * computed and returned. + * + * \param dest the destination buffer (or `NULL`). + * \param sk the RSA private key. + * \param pk the RSA public key. + * \param d the RSA private exponent. + * \param dlen the RSA private exponent length (in bytes). + * \return the encoded key length (in bytes). + */ +size_t br_encode_rsa_raw_der(void *dest, const br_rsa_private_key *sk, + const br_rsa_public_key *pk, const void *d, size_t dlen); + +/** + * \brief Encode an RSA private key (PKCS#8 DER format). + * + * This function encodes the provided key into the PKCS#8 format + * (RFC 5958, type `OneAsymmetricKey`). It wraps around the "raw DER" + * format for the RSA key, as implemented by `br_encode_rsa_raw_der()`. + * + * The key elements are: + * + * - `sk`: the private key (`p`, `q`, `dp`, `dq` and `iq`) + * + * - `pk`: the public key (`n` and `e`) + * + * - `d` (size: `dlen` bytes): the private exponent + * + * The public key elements, and the private exponent `d`, can be + * recomputed from the private key (see `br_rsa_compute_modulus()`, + * `br_rsa_compute_pubexp()` and `br_rsa_compute_privexp()`). + * + * If `dest` is not `NULL`, then the encoded key is written at that + * address, and the encoded length (in bytes) is returned. If `dest` is + * `NULL`, then nothing is written, but the encoded length is still + * computed and returned. + * + * \param dest the destination buffer (or `NULL`). + * \param sk the RSA private key. + * \param pk the RSA public key. + * \param d the RSA private exponent. + * \param dlen the RSA private exponent length (in bytes). + * \return the encoded key length (in bytes). + */ +size_t br_encode_rsa_pkcs8_der(void *dest, const br_rsa_private_key *sk, + const br_rsa_public_key *pk, const void *d, size_t dlen); + +/** + * \brief Encode an EC private key (raw DER format). + * + * This function encodes the provided key into the "raw" format specified + * in RFC 5915 (type `ECPrivateKey`), with DER encoding rules. + * + * The private key is provided in `sk`, the public key being `pk`. If + * `pk` is `NULL`, then the encoded key will not include the public key + * in its `publicKey` field (which is nominally optional). + * + * If `dest` is not `NULL`, then the encoded key is written at that + * address, and the encoded length (in bytes) is returned. If `dest` is + * `NULL`, then nothing is written, but the encoded length is still + * computed and returned. + * + * If the key cannot be encoded (e.g. because there is no known OBJECT + * IDENTIFIER for the used curve), then 0 is returned. + * + * \param dest the destination buffer (or `NULL`). + * \param sk the EC private key. + * \param pk the EC public key (or `NULL`). + * \return the encoded key length (in bytes), or 0. + */ +size_t br_encode_ec_raw_der(void *dest, + const br_ec_private_key *sk, const br_ec_public_key *pk); + +/** + * \brief Encode an EC private key (PKCS#8 DER format). + * + * This function encodes the provided key into the PKCS#8 format + * (RFC 5958, type `OneAsymmetricKey`). The curve is identified + * by an OID provided as parameters to the `privateKeyAlgorithm` + * field. The private key value (contents of the `privateKey` field) + * contains the DER encoding of the `ECPrivateKey` type defined in + * RFC 5915, without the `parameters` field (since they would be + * redundant with the information in `privateKeyAlgorithm`). + * + * The private key is provided in `sk`, the public key being `pk`. If + * `pk` is not `NULL`, then the encoded public key is included in the + * `publicKey` field of the private key value (but not in the `publicKey` + * field of the PKCS#8 `OneAsymmetricKey` wrapper). + * + * If `dest` is not `NULL`, then the encoded key is written at that + * address, and the encoded length (in bytes) is returned. If `dest` is + * `NULL`, then nothing is written, but the encoded length is still + * computed and returned. + * + * If the key cannot be encoded (e.g. because there is no known OBJECT + * IDENTIFIER for the used curve), then 0 is returned. + * + * \param dest the destination buffer (or `NULL`). + * \param sk the EC private key. + * \param pk the EC public key (or `NULL`). + * \return the encoded key length (in bytes), or 0. + */ +size_t br_encode_ec_pkcs8_der(void *dest, + const br_ec_private_key *sk, const br_ec_public_key *pk); + +/** + * \brief PEM banner for RSA private key (raw). + */ +#define BR_ENCODE_PEM_RSA_RAW "RSA PRIVATE KEY" + +/** + * \brief PEM banner for EC private key (raw). + */ +#define BR_ENCODE_PEM_EC_RAW "EC PRIVATE KEY" + +/** + * \brief PEM banner for an RSA or EC private key in PKCS#8 format. + */ +#define BR_ENCODE_PEM_PKCS8 "PRIVATE KEY" + +#ifdef __cplusplus +} +#endif + #endif