/*1* Copyright (c) 2016 Thomas Pornin <[email protected]>2*3* Permission is hereby granted, free of charge, to any person obtaining4* a copy of this software and associated documentation files (the5* "Software"), to deal in the Software without restriction, including6* without limitation the rights to use, copy, modify, merge, publish,7* distribute, sublicense, and/or sell copies of the Software, and to8* permit persons to whom the Software is furnished to do so, subject to9* the following conditions:10*11* The above copyright notice and this permission notice shall be12* included in all copies or substantial portions of the Software.13*14* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,15* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF16* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND17* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS18* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN19* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN20* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE21* SOFTWARE.22*/2324#ifndef BR_BEARSSL_PEM_H__25#define BR_BEARSSL_PEM_H__2627#include <stddef.h>28#include <stdint.h>2930#ifdef __cplusplus31extern "C" {32#endif3334/** \file bearssl_pem.h35*36* # PEM Support37*38* PEM is a traditional encoding layer use to store binary objects (in39* particular X.509 certificates, and private keys) in text files. While40* the acronym comes from an old, defunct standard ("Privacy Enhanced41* Mail"), the format has been reused, with some variations, by many42* systems, and is a _de facto_ standard, even though it is not, actually,43* specified in all clarity anywhere.44*45* ## Format Details46*47* BearSSL contains a generic, streamed PEM decoder, which handles the48* following format:49*50* - The input source (a sequence of bytes) is assumed to be the51* encoding of a text file in an ASCII-compatible charset. This52* includes ISO-8859-1, Windows-1252, and UTF-8 encodings. Each53* line ends on a newline character (U+000A LINE FEED). The54* U+000D CARRIAGE RETURN characters are ignored, so the code55* accepts both Windows-style and Unix-style line endings.56*57* - Each object begins with a banner that occurs at the start of58* a line; the first banner characters are "`-----BEGIN `" (five59* dashes, the word "BEGIN", and a space). The banner matching is60* not case-sensitive.61*62* - The _object name_ consists in the characters that follow the63* banner start sequence, up to the end of the line, but without64* trailing dashes (in "normal" PEM, there are five trailing65* dashes, but this implementation is not picky about these dashes).66* The BearSSL decoder normalises the name characters to uppercase67* (for ASCII letters only) and accepts names up to 127 characters.68*69* - The object ends with a banner that again occurs at the start of70* a line, and starts with "`-----END `" (again case-insensitive).71*72* - Between that start and end banner, only Base64 data shall occur.73* Base64 converts each sequence of three bytes into four74* characters; the four characters are ASCII letters, digits, "`+`"75* or "`-`" signs, and one or two "`=`" signs may occur in the last76* quartet. Whitespace is ignored (whitespace is any ASCII character77* of code 32 or less, so control characters are whitespace) and78* lines may have arbitrary length; the only restriction is that the79* four characters of a quartet must appear on the same line (no80* line break inside a quartet).81*82* - A single file may contain more than one PEM object. Bytes that83* occur between objects are ignored.84*85*86* ## PEM Decoder API87*88* The PEM decoder offers a state-machine API. The caller allocates a89* decoder context, then injects source bytes. Source bytes are pushed90* with `br_pem_decoder_push()`. The decoder stops accepting bytes when91* it reaches an "event", which is either the start of an object, the92* end of an object, or a decoding error within an object.93*94* The `br_pem_decoder_event()` function is used to obtain the current95* event; it also clears it, thus allowing the decoder to accept more96* bytes. When a object start event is raised, the decoder context97* offers the found object name (normalised to ASCII uppercase).98*99* When an object is reached, the caller must set an appropriate callback100* function, which will receive (by chunks) the decoded object data.101*102* Since the decoder context makes no dynamic allocation, it requires103* no explicit deallocation.104*/105106/**107* \brief PEM decoder context.108*109* Contents are opaque (they should not be accessed directly).110*/111typedef struct {112#ifndef BR_DOXYGEN_IGNORE113/* CPU for the T0 virtual machine. */114struct {115uint32_t *dp;116uint32_t *rp;117const unsigned char *ip;118} cpu;119uint32_t dp_stack[32];120uint32_t rp_stack[32];121int err;122123const unsigned char *hbuf;124size_t hlen;125126void (*dest)(void *dest_ctx, const void *src, size_t len);127void *dest_ctx;128129unsigned char event;130char name[128];131unsigned char buf[255];132size_t ptr;133#endif134} br_pem_decoder_context;135136/**137* \brief Initialise a PEM decoder structure.138*139* \param ctx decoder context to initialise.140*/141void br_pem_decoder_init(br_pem_decoder_context *ctx);142143/**144* \brief Push some bytes into the decoder.145*146* Returned value is the number of bytes actually consumed; this may be147* less than the number of provided bytes if an event is raised. When an148* event is raised, it must be read (with `br_pem_decoder_event()`);149* until the event is read, this function will return 0.150*151* \param ctx decoder context.152* \param data new data bytes.153* \param len number of new data bytes.154* \return the number of bytes actually received (may be less than `len`).155*/156size_t br_pem_decoder_push(br_pem_decoder_context *ctx,157const void *data, size_t len);158159/**160* \brief Set the receiver for decoded data.161*162* When an object is entered, the provided function (with opaque context163* pointer) will be called repeatedly with successive chunks of decoded164* data for that object. If `dest` is set to 0, then decoded data is165* simply ignored. The receiver can be set at any time, but, in practice,166* it should be called immediately after receiving a "start of object"167* event.168*169* \param ctx decoder context.170* \param dest callback for receiving decoded data.171* \param dest_ctx opaque context pointer for the `dest` callback.172*/173static inline void174br_pem_decoder_setdest(br_pem_decoder_context *ctx,175void (*dest)(void *dest_ctx, const void *src, size_t len),176void *dest_ctx)177{178ctx->dest = dest;179ctx->dest_ctx = dest_ctx;180}181182/**183* \brief Get the last event.184*185* If an event was raised, then this function returns the event value, and186* also clears it, thereby allowing the decoder to proceed. If no event187* was raised since the last call to `br_pem_decoder_event()`, then this188* function returns 0.189*190* \param ctx decoder context.191* \return the raised event, or 0.192*/193int br_pem_decoder_event(br_pem_decoder_context *ctx);194195/**196* \brief Event: start of object.197*198* This event is raised when the start of a new object has been detected.199* The object name (normalised to uppercase) can be accessed with200* `br_pem_decoder_name()`.201*/202#define BR_PEM_BEGIN_OBJ 1203204/**205* \brief Event: end of object.206*207* This event is raised when the end of the current object is reached208* (normally, i.e. with no decoding error).209*/210#define BR_PEM_END_OBJ 2211212/**213* \brief Event: decoding error.214*215* This event is raised when decoding fails within an object.216* This formally closes the current object and brings the decoder back217* to the "out of any object" state. The offending line in the source218* is consumed.219*/220#define BR_PEM_ERROR 3221222/**223* \brief Get the name of the encountered object.224*225* The encountered object name is defined only when the "start of object"226* event is raised. That name is normalised to uppercase (for ASCII letters227* only) and does not include trailing dashes.228*229* \param ctx decoder context.230* \return the current object name.231*/232static inline const char *233br_pem_decoder_name(br_pem_decoder_context *ctx)234{235return ctx->name;236}237238/**239* \brief Encode an object in PEM.240*241* This function encodes the provided binary object (`data`, of length `len`242* bytes) into PEM. The `banner` text will be included in the header and243* footer (e.g. use `"CERTIFICATE"` to get a `"BEGIN CERTIFICATE"` header).244*245* The length (in characters) of the PEM output is returned; that length246* does NOT include the terminating zero, that this function nevertheless247* adds. If using the returned value for allocation purposes, the allocated248* buffer size MUST be at least one byte larger than the returned size.249*250* If `dest` is `NULL`, then the encoding does not happen; however, the251* length of the encoded object is still computed and returned.252*253* The `data` pointer may be `NULL` only if `len` is zero (when encoding254* an object of length zero, which is not very useful), or when `dest`255* is `NULL` (in that case, source data bytes are ignored).256*257* Some `flags` can be specified to alter the encoding behaviour:258*259* - If `BR_PEM_LINE64` is set, then line-breaking will occur after260* every 64 characters of output, instead of the default of 76.261*262* - If `BR_PEM_CRLF` is set, then end-of-line sequence will use263* CR+LF instead of a single LF.264*265* The `data` and `dest` buffers may overlap, in which case the source266* binary data is destroyed in the process. Note that the PEM-encoded output267* is always larger than the source binary.268*269* \param dest the destination buffer (or `NULL`).270* \param data the source buffer (can be `NULL` in some cases).271* \param len the source length (in bytes).272* \param banner the PEM banner expression.273* \param flags the behavioural flags.274* \return the PEM object length (in characters), EXCLUDING the final zero.275*/276size_t br_pem_encode(void *dest, const void *data, size_t len,277const char *banner, unsigned flags);278279/**280* \brief PEM encoding flag: split lines at 64 characters.281*/282#define BR_PEM_LINE64 0x0001283284/**285* \brief PEM encoding flag: use CR+LF line endings.286*/287#define BR_PEM_CRLF 0x0002288289#ifdef __cplusplus290}291#endif292293#endif294295296