Crypt-Bear
view release on metacpan or search on metacpan
include/bearssl_x509.h view on Meta::CPAN
#ifndef BR_BEARSSL_X509_H__
#define BR_BEARSSL_X509_H__
#include <stddef.h>
#include <stdint.h>
#include "bearssl_ec.h"
#include "bearssl_hash.h"
#include "bearssl_rsa.h"
#ifdef __cplusplus
extern "C" {
#endif
/** \file bearssl_x509.h
*
* # X.509 Certificate Chain Processing
*
* An X.509 processing engine receives an X.509 chain, chunk by chunk,
* as received from a SSL/TLS client or server (the client receives the
* server's certificate chain, and the server receives the client's
* certificate chain if it requested a client certificate). The chain
* is thus injected in the engine in SSL order (end-entity first).
*
* The engine's job is to return the public key to use for SSL/TLS.
* How exactly that key is obtained and verified is entirely up to the
* engine.
*
* **The "known key" engine** returns a public key which is already known
* from out-of-band information (e.g. the client _remembers_ the key from
* a previous connection, as in the usual SSH model). This is the simplest
* engine since it simply ignores the chain, thereby avoiding the need
* for any decoding logic.
*
* **The "minimal" engine** implements minimal X.509 decoding and chain
* validation:
*
* - The provided chain should validate "as is". There is no attempt
* at reordering, skipping or downloading extra certificates.
*
* - X.509 v1, v2 and v3 certificates are supported.
*
* - Trust anchors are a DN and a public key. Each anchor is either a
* "CA" anchor, or a non-CA.
*
* - If the end-entity certificate matches a non-CA anchor (subject DN
* is equal to the non-CA name, and public key is also identical to
* the anchor key), then this is a _direct trust_ case and the
* remaining certificates are ignored.
*
* - Unless direct trust is applied, the chain must be verifiable up to
* a certificate whose issuer DN matches the DN from a "CA" trust anchor,
* and whose signature is verifiable against that anchor's public key.
* Subsequent certificates in the chain are ignored.
*
* - The engine verifies subject/issuer DN matching, and enforces
* processing of Basic Constraints and Key Usage extensions. The
* Authority Key Identifier, Subject Key Identifier, Issuer Alt Name,
* Subject Directory Attribute, CRL Distribution Points, Freshest CRL,
* Authority Info Access and Subject Info Access extensions are
* ignored. The Subject Alt Name is decoded for the end-entity
* certificate under some conditions (see below). Other extensions
* are ignored if non-critical, or imply chain rejection if critical.
*
* - The Subject Alt Name extension is parsed for names of type `dNSName`
* when decoding the end-entity certificate, and only if there is a
* server name to match. If there is no SAN extension, then the
* Common Name from the subjectDN is used. That name matching is
* case-insensitive and honours a single starting wildcard (i.e. if
* the name in the certificate starts with "`*.`" then this matches
* any word as first element). Note: this name matching is performed
* also in the "direct trust" model.
*
* - DN matching is byte-to-byte equality (a future version might
* include some limited processing for case-insensitive matching and
* whitespace normalisation).
*
* - Successful validation produces a public key type but also a set
* of allowed usages (`BR_KEYTYPE_KEYX` and/or `BR_KEYTYPE_SIGN`).
* The caller is responsible for checking that the key type and
* usages are compatible with the expected values (e.g. with the
* selected cipher suite, when the client validates the server's
* certificate).
*
* **Important caveats:**
*
* - The "minimal" engine does not check revocation status. The relevant
* extensions are ignored, and CRL or OCSP responses are not gathered
* or checked.
*
* - The "minimal" engine does not currently support Name Constraints
* (some basic functionality to handle sub-domains may be added in a
* later version).
*
* - The decoder is not "validating" in the sense that it won't reject
* some certificates with invalid field values when these fields are
* not actually processed.
*/
/*
* X.509 error codes are in the 32..63 range.
*/
/** \brief X.509 status: validation was successful; this is not actually
an error. */
#define BR_ERR_X509_OK 32
/** \brief X.509 status: invalid value in an ASN.1 structure. */
#define BR_ERR_X509_INVALID_VALUE 33
/** \brief X.509 status: truncated certificate. */
#define BR_ERR_X509_TRUNCATED 34
/** \brief X.509 status: empty certificate chain (no certificate at all). */
#define BR_ERR_X509_EMPTY_CHAIN 35
/** \brief X.509 status: decoding error: inner element extends beyond
outer element size. */
#define BR_ERR_X509_INNER_TRUNC 36
/** \brief X.509 status: decoding error: unsupported tag class (application
include/bearssl_x509.h view on Meta::CPAN
*
* \param ctx validation context.
* \param server_name server name to match (or `NULL`).
*/
void (*start_chain)(const br_x509_class **ctx,
const char *server_name);
/**
* \brief Start a new certificate.
*
* \param ctx validation context.
* \param length new certificate length (in bytes).
*/
void (*start_cert)(const br_x509_class **ctx, uint32_t length);
/**
* \brief Receive some bytes for the current certificate.
*
* This function may be called several times in succession for
* a given certificate. The caller guarantees that for each
* call, `len` is not zero, and the sum of all chunk lengths
* for a certificate matches the total certificate length which
* was provided in the previous `start_cert()` call.
*
* If the new certificate is empty (no byte at all) then this
* function won't be called at all.
*
* \param ctx validation context.
* \param buf certificate data chunk.
* \param len certificate data chunk length (in bytes).
*/
void (*append)(const br_x509_class **ctx,
const unsigned char *buf, size_t len);
/**
* \brief Finish the current certificate.
*
* This function is called when the end of the current certificate
* is reached.
*
* \param ctx validation context.
*/
void (*end_cert)(const br_x509_class **ctx);
/**
* \brief Finish the chain.
*
* This function is called at the end of the chain. It shall
* return either 0 if the validation was successful, or a
* non-zero error code. The `BR_ERR_X509_*` constants are
* error codes, though other values may be possible.
*
* \param ctx validation context.
* \return 0 on success, or a non-zero error code.
*/
unsigned (*end_chain)(const br_x509_class **ctx);
/**
* \brief Get the resulting end-entity public key.
*
* The decoded public key is returned. The returned pointer
* may be valid only as long as the context structure is
* unmodified, i.e. it may cease to be valid if the context
* is released or reused.
*
* This function _may_ return `NULL` if the validation failed.
* However, returning a public key does not mean that the
* validation was wholly successful; some engines may return
* a decoded public key even if the chain did not end on a
* trusted anchor.
*
* If validation succeeded and `usage` is not `NULL`, then
* `*usage` is filled with a combination of `BR_KEYTYPE_SIGN`
* and/or `BR_KEYTYPE_KEYX` that specifies the validated key
* usage types. It is the caller's responsibility to check
* that value against the intended use of the public key.
*
* \param ctx validation context.
* \return the end-entity public key, or `NULL`.
*/
const br_x509_pkey *(*get_pkey)(
const br_x509_class *const *ctx, unsigned *usages);
};
/**
* \brief The "known key" X.509 engine structure.
*
* The structure contents are opaque (they shall not be accessed directly),
* except for the first field (the vtable).
*
* The "known key" engine returns an externally configured public key,
* and totally ignores the certificate contents.
*/
typedef struct {
/** \brief Reference to the context vtable. */
const br_x509_class *vtable;
#ifndef BR_DOXYGEN_IGNORE
br_x509_pkey pkey;
unsigned usages;
#endif
} br_x509_knownkey_context;
/**
* \brief Class instance for the "known key" X.509 engine.
*/
extern const br_x509_class br_x509_knownkey_vtable;
/**
* \brief Initialize a "known key" X.509 engine with a known RSA public key.
*
* The `usages` parameter indicates the allowed key usages for that key
* (`BR_KEYTYPE_KEYX` and/or `BR_KEYTYPE_SIGN`).
*
* The provided pointers are linked in, not copied, so they must remain
* valid while the public key may be in usage.
*
* \param ctx context to initialise.
* \param pk known public key.
* \param usages allowed key usages.
*/
void br_x509_knownkey_init_rsa(br_x509_knownkey_context *ctx,
const br_rsa_public_key *pk, unsigned usages);
/**
* \brief Initialize a "known key" X.509 engine with a known EC public key.
*
* The `usages` parameter indicates the allowed key usages for that key
* (`BR_KEYTYPE_KEYX` and/or `BR_KEYTYPE_SIGN`).
*
include/bearssl_x509.h view on Meta::CPAN
*
* 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 Callback for validity date checks.
*
* The function receives as parameter an arbitrary user-provided context,
* and the notBefore and notAfter dates specified in an X.509 certificate,
* both expressed as a number of days and a number of seconds:
*
* - Days are counted in a proleptic Gregorian calendar since
* January 1st, 0 AD. Year "0 AD" is the one that preceded "1 AD";
* it is also traditionally known as "1 BC".
*
* - Seconds are counted since midnight, from 0 to 86400 (a count of
* 86400 is possible only if a leap second happened).
*
* Each date and time is understood in the UTC time zone. The "Unix
* Epoch" (January 1st, 1970, 00:00 UTC) corresponds to days=719528 and
* seconds=0; the "Windows Epoch" (January 1st, 1601, 00:00 UTC) is
* days=584754, seconds=0.
*
* This function must return -1 if the current date is strictly before
* the "notBefore" time, or +1 if the current date is strictly after the
* "notAfter" time. If neither condition holds, then the function returns
* 0, which means that the current date falls within the validity range of
* the certificate. If the function returns a value distinct from -1, 0
* and +1, then this is interpreted as an unavailability of the current
* time, which normally ends the validation process with a
* `BR_ERR_X509_TIME_UNKNOWN` error.
*
* During path validation, this callback will be invoked for each
* considered X.509 certificate. Validation fails if any of the calls
* returns a non-zero value.
*
* The context value is an abritrary pointer set by the caller when
* configuring this callback.
*
* \param tctx context pointer.
* \param not_before_days notBefore date (days since Jan 1st, 0 AD).
* \param not_before_seconds notBefore time (seconds, at most 86400).
* \param not_after_days notAfter date (days since Jan 1st, 0 AD).
* \param not_after_seconds notAfter time (seconds, at most 86400).
* \return -1, 0 or +1.
*/
typedef int (*br_x509_time_check)(void *tctx,
uint32_t not_before_days, uint32_t not_before_seconds,
uint32_t not_after_days, uint32_t not_after_seconds);
/**
* \brief The "minimal" X.509 engine structure.
*
* The structure contents are opaque (they shall not be accessed directly),
* except for the first field (the vtable).
*
* The "minimal" engine performs a rudimentary but serviceable X.509 path
* validation.
*/
typedef struct {
const br_x509_class *vtable;
#ifndef BR_DOXYGEN_IGNORE
/* Structure for returning the EE public key. */
br_x509_pkey pkey;
/* CPU for the T0 virtual machine. */
struct {
uint32_t *dp;
uint32_t *rp;
const unsigned char *ip;
} cpu;
uint32_t dp_stack[31];
uint32_t rp_stack[31];
int err;
/* Server name to match with the SAN / CN of the EE certificate. */
const char *server_name;
/* Validated key usages. */
unsigned char key_usages;
/* Explicitly set date and time. */
uint32_t days, seconds;
/* Current certificate length (in bytes). Set to 0 when the
certificate has been fully processed. */
uint32_t cert_length;
/* Number of certificates processed so far in the current chain.
It is incremented at the end of the processing of a certificate,
so it is 0 for the EE. */
uint32_t num_certs;
/* Certificate data chunk. */
const unsigned char *hbuf;
size_t hlen;
/* The pad serves as destination for various operations. */
unsigned char pad[256];
/* Buffer for EE public key data. */
unsigned char ee_pkey_data[BR_X509_BUFSIZE_KEY];
/* Buffer for currently decoded public key. */
unsigned char pkey_data[BR_X509_BUFSIZE_KEY];
/* Signature type: signer key type, offset to the hash
function OID (in the T0 data block) and hash function
output length (TBS hash length). */
unsigned char cert_signer_key_type;
uint16_t cert_sig_hash_oid;
unsigned char cert_sig_hash_len;
/* Current/last certificate signature. */
unsigned char cert_sig[BR_X509_BUFSIZE_SIG];
uint16_t cert_sig_len;
/* Minimum RSA key length (difference in bytes from 128). */
int16_t min_rsa_size;
/* Configured trust anchors. */
const br_x509_trust_anchor *trust_anchors;
size_t trust_anchors_num;
/*
* Multi-hasher for the TBS.
*/
unsigned char do_mhash;
br_multihash_context mhash;
unsigned char tbs_hash[64];
/*
* Simple hasher for the subject/issuer DN.
*/
unsigned char do_dn_hash;
const br_hash_class *dn_hash_impl;
br_hash_compat_context dn_hash;
unsigned char current_dn_hash[64];
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;
/*
* Callback function (and context) to get the current date.
*/
void *itime_ctx;
br_x509_time_check itime;
/*
* Public key cryptography implementations (signature verification).
*/
br_rsa_pkcs1_vrfy irsa;
br_ecdsa_vrfy iecdsa;
const br_ec_impl *iec;
#endif
} br_x509_minimal_context;
/**
include/bearssl_x509.h view on Meta::CPAN
* (both end-entity, and intermediate CA) but not to "CA" trust anchors.
*
* \param ctx validation context.
* \param byte_length minimum RSA key length, **in bytes** (not bits).
*/
static inline void
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.
*
* This structure is _not_ for X.509 validation, but for extracting
* names and public keys from encoded certificates. Intended usage is
* to use (self-signed) certificates as trust anchors.
*
* Contents are opaque and shall not be accessed directly.
*/
typedef struct {
#ifndef BR_DOXYGEN_IGNORE
/* Structure for returning the public key. */
br_x509_pkey pkey;
/* CPU for the T0 virtual machine. */
struct {
uint32_t *dp;
uint32_t *rp;
const unsigned char *ip;
} cpu;
uint32_t dp_stack[32];
uint32_t rp_stack[32];
int err;
/* The pad serves as destination for various operations. */
unsigned char pad[256];
/* Flag set when decoding succeeds. */
unsigned char decoded;
/* Validity dates. */
uint32_t notbefore_days, notbefore_seconds;
uint32_t notafter_days, notafter_seconds;
/* The "CA" flag. This is set to true if the certificate contains
a Basic Constraints extension that asserts CA status. */
unsigned char isCA;
/* DN processing: the subject DN is extracted and pushed to the
provided callback. */
unsigned char copy_dn;
void *append_dn_ctx;
void (*append_dn)(void *ctx, const void *buf, size_t len);
/* Certificate data chunk. */
const unsigned char *hbuf;
size_t hlen;
/* Buffer for decoded public key. */
unsigned char pkey_data[BR_X509_BUFSIZE_KEY];
/* Type of key and hash function used in the certificate signature. */
unsigned char signer_key_type;
unsigned char signer_hash_id;
#endif
} br_x509_decoder_context;
/**
* \brief Initialise an X.509 decoder context for processing a new
* certificate.
*
* The `append_dn()` callback (with opaque context `append_dn_ctx`)
* will be invoked to receive, chunk by chunk, the certificate's
* subject DN. If `append_dn` is `0` then the subject DN will be
* ignored.
*
* \param ctx X.509 decoder context to initialise.
* \param append_dn DN receiver callback (or `0`).
* \param append_dn_ctx context for the DN receiver callback.
*/
void br_x509_decoder_init(br_x509_decoder_context *ctx,
void (*append_dn)(void *ctx, const void *buf, size_t len),
void *append_dn_ctx);
/**
* \brief Push some certificate bytes into a decoder context.
*
* If `len` is non-zero, then that many bytes are pushed, from address
* `data`, into the provided decoder context.
*
* \param ctx X.509 decoder context.
* \param data certificate data chunk.
* \param len certificate data chunk length (in bytes).
*/
void br_x509_decoder_push(br_x509_decoder_context *ctx,
const void *data, size_t len);
/**
* \brief Obtain the decoded public key.
*
* Returned value is a pointer to a structure internal to the decoder
* context; releasing or reusing the decoder context invalidates that
* structure.
*
* If decoding was not finished, or failed, then `NULL` is returned.
*
* \param ctx X.509 decoder context.
* \return the public key, or `NULL` on unfinished/error.
*/
static inline br_x509_pkey *
br_x509_decoder_get_pkey(br_x509_decoder_context *ctx)
{
if (ctx->decoded && ctx->err == 0) {
return &ctx->pkey;
} else {
return NULL;
}
}
/**
* \brief Get decoder error status.
*
* If no error was reported yet but the certificate decoding is not
* finished, then the error code is `BR_ERR_X509_TRUNCATED`. If decoding
* was successful, then 0 is returned.
*
* \param ctx X.509 decoder context.
* \return 0 on successful decoding, or a non-zero error code.
*/
static inline int
br_x509_decoder_last_error(br_x509_decoder_context *ctx)
{
if (ctx->err != 0) {
return ctx->err;
}
if (!ctx->decoded) {
return BR_ERR_X509_TRUNCATED;
}
return 0;
}
/**
* \brief Get the "isCA" flag from an X.509 decoder context.
*
* This flag is set if the decoded certificate claims to be a CA through
* a Basic Constraints extension. This flag should not be read before
* decoding completed successfully.
*
* \param ctx X.509 decoder context.
* \return the "isCA" flag.
*/
static inline int
br_x509_decoder_isCA(br_x509_decoder_context *ctx)
{
return ctx->isCA;
}
/**
* \brief Get the issuing CA key type (type of algorithm used to sign the
* decoded certificate).
*
* This is `BR_KEYTYPE_RSA` or `BR_KEYTYPE_EC`. The value 0 is returned
* if the signature type was not recognised.
*
* \param ctx X.509 decoder context.
* \return the issuing CA key type.
*/
static inline int
br_x509_decoder_get_signer_key_type(br_x509_decoder_context *ctx)
{
return ctx->signer_key_type;
}
/**
* \brief Get the identifier for the hash function used to sign the decoded
* certificate.
*
* This is 0 if the hash function was not recognised.
*
* \param ctx X.509 decoder context.
* \return the signature hash function identifier.
*/
static inline int
br_x509_decoder_get_signer_hash_id(br_x509_decoder_context *ctx)
{
return ctx->signer_hash_id;
}
/**
* \brief Type for an X.509 certificate (DER-encoded).
*/
typedef struct {
/** \brief The DER-encoded certificate data. */
unsigned char *data;
/** \brief The DER-encoded certificate length (in bytes). */
size_t data_len;
} br_x509_certificate;
/**
* \brief Private key decoder context.
*
* The private key decoder recognises RSA and EC private keys, either in
* their raw, DER-encoded format, or wrapped in an unencrypted PKCS#8
* archive (again DER-encoded).
*
* Structure contents are opaque and shall not be accessed directly.
*/
typedef struct {
#ifndef BR_DOXYGEN_IGNORE
/* Structure for returning the private key. */
union {
br_rsa_private_key rsa;
br_ec_private_key ec;
} key;
/* CPU for the T0 virtual machine. */
struct {
uint32_t *dp;
uint32_t *rp;
const unsigned char *ip;
} cpu;
uint32_t dp_stack[32];
uint32_t rp_stack[32];
int err;
/* Private key data chunk. */
const unsigned char *hbuf;
size_t hlen;
/* The pad serves as destination for various operations. */
unsigned char pad[256];
/* Decoded key type; 0 until decoding is complete. */
unsigned char key_type;
/* Buffer for the private key elements. It shall be large enough
to accommodate all elements for a RSA-4096 private key (roughly
five 2048-bit integers, possibly a bit more). */
unsigned char key_data[3 * BR_X509_BUFSIZE_SIG];
#endif
} br_skey_decoder_context;
/**
* \brief Initialise a private key decoder context.
*
* \param ctx key decoder context to initialise.
*/
void br_skey_decoder_init(br_skey_decoder_context *ctx);
/**
* \brief Push some data bytes into a private key decoder context.
*
* If `len` is non-zero, then that many data bytes, starting at address
* `data`, are pushed into the decoder.
*
* \param ctx key decoder context.
* \param data private key data chunk.
* \param len private key data chunk length (in bytes).
*/
void br_skey_decoder_push(br_skey_decoder_context *ctx,
const void *data, size_t len);
/**
* \brief Get the decoding status for a private key.
*
* Decoding status is 0 on success, or a non-zero error code. If the
* decoding is unfinished when this function is called, then the
* status code `BR_ERR_X509_TRUNCATED` is returned.
*
* \param ctx key decoder context.
* \return 0 on successful decoding, or a non-zero error code.
*/
static inline int
br_skey_decoder_last_error(const br_skey_decoder_context *ctx)
{
if (ctx->err != 0) {
return ctx->err;
}
if (ctx->key_type == 0) {
return BR_ERR_X509_TRUNCATED;
}
return 0;
}
/**
* \brief Get the decoded private key type.
*
* Private key type is `BR_KEYTYPE_RSA` or `BR_KEYTYPE_EC`. If decoding is
* not finished or failed, then 0 is returned.
*
* \param ctx key decoder context.
* \return decoded private key type, or 0.
*/
static inline int
br_skey_decoder_key_type(const br_skey_decoder_context *ctx)
{
if (ctx->err == 0) {
return ctx->key_type;
} else {
return 0;
}
}
/**
* \brief Get the decoded RSA private key.
*
* This function returns `NULL` if the decoding failed, or is not
* finished, or the key is not RSA. The returned pointer references
* structures within the context that can become invalid if the context
* is reused or released.
*
* \param ctx key decoder context.
* \return decoded RSA private key, or `NULL`.
*/
static inline const br_rsa_private_key *
br_skey_decoder_get_rsa(const br_skey_decoder_context *ctx)
{
if (ctx->err == 0 && ctx->key_type == BR_KEYTYPE_RSA) {
return &ctx->key.rsa;
} else {
return NULL;
}
}
/**
* \brief Get the decoded EC private key.
*
* This function returns `NULL` if the decoding failed, or is not
* finished, or the key is not EC. The returned pointer references
* structures within the context that can become invalid if the context
* is reused or released.
*
* \param ctx key decoder context.
* \return decoded EC private key, or `NULL`.
*/
static inline const br_ec_private_key *
br_skey_decoder_get_ec(const br_skey_decoder_context *ctx)
{
if (ctx->err == 0 && ctx->key_type == BR_KEYTYPE_EC) {
return &ctx->key.ec;
} else {
return NULL;
}
}
/**
* \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
*
( run in 0.864 second using v1.01-cache-2.11-cpan-39bf76dae61 )