48#define VEC_INIT {0, 0, 0}
51#define VEC_CLEAR(vec) \
53 SAFE_FREE((vec).buf); \
59#define VEC_CLEAREXT(vec, fun) \
62 for (vec_tmp = 0; vec_tmp < (vec).ptr; vec_tmp++) { \
63 (fun)(&(vec).buf[vec_tmp]); \
68#define VEC_ADD(vec, x) \
70 (vec).buf = vector_expand((vec).buf, sizeof *((vec).buf), &(vec).ptr, &(vec).len, 1); \
71 (vec).buf[(vec).ptr++] = (x); \
74#define VEC_ADDMANY(vec, xp, num) \
76 size_t vec_num = (num); \
77 (vec).buf = vector_expand((vec).buf, sizeof *((vec).buf), &(vec).ptr, &(vec).len, vec_num); \
78 memcpy((vec).buf + (vec).ptr, (xp), vec_num * sizeof *((vec).buf)); \
79 (vec).ptr += vec_num; \
82#define VEC_ELT(vec, idx) ((vec).buf[idx])
83#define VEC_LEN(vec) ((vec).ptr)
84#define VEC_TOARRAY(vec) xblobdup((vec).buf, sizeof *((vec).buf) * (vec).ptr)
88static void *xmalloc(
size_t len) {
97static void xfree(
void *buf) {
103static void *xblobdup(
const void *src,
size_t len) {
109 memcpy(buf, src, len);
113static char *xstrdup(
const char *src) {
114 return (
char *)xblobdup(src, strlen(src) + 1);
119static void *vector_expand(
void *buf,
size_t esize,
size_t *ptr,
size_t *len,
size_t extra) {
123 if (*len - *ptr >= extra) {
127 if (nlen - *ptr < extra) {
133 nbuf = xmalloc(nlen * esize);
135 memcpy(nbuf, buf, *len * esize);
144static int looks_like_DER(
const unsigned char *buf,
size_t len) {
151 if (*buf++ != 0x30) {
157 return (
size_t)fb == len;
164 if (len < (
size_t)fb + 2) {
170 if (dlen > (len >> 8)) {
173 dlen = (dlen << 8) + (
size_t)*buf++;
189static void free_pem_object_contents(
pem_object *po) {
196static void vblob_append(
void *cc,
const void *data,
size_t len) {
205static pem_object *decode_pem(
const void *src,
size_t len,
size_t *num) {
207 br_pem_decoder_context pc;
209 const unsigned char *buf;
215 br_pem_decoder_init(&pc);
226 tlen = br_pem_decoder_push(&pc, buf, len);
230 switch (br_pem_decoder_event(&pc)) {
232 case BR_PEM_BEGIN_OBJ:
233 po.
name = xstrdup(br_pem_decoder_name(&pc));
234 br_pem_decoder_setdest(&pc, vblob_append, &bv);
264 if (len == 0 && extra_nl) {
266 buf = (
const unsigned char *)
"\n";
292static br_x509_certificate *read_certificates_from_memory(
const unsigned char *buf,
size_t len,
size_t *num) {
296 br_x509_certificate *xcs;
297 br_x509_certificate dummy;
302 if (looks_like_DER(buf, len)) {
303 xcs = xmalloc(2 *
sizeof *xcs);
304 xcs[0].data = xblobdup(buf, len);
305 xcs[0].data_len = len;
313 pos = decode_pem(buf, len, &num_pos);
319 for (u = 0; u < num_pos; u++) {
322 const char *name = pos[u].
name;
325 size_t name_len = strlen(name);
326 while (name_len > 0 && name[name_len - 1] ==
'-') {
331 if ((name_len == 11 && strncmp(name,
"CERTIFICATE", 11) == 0) ||
332 (name_len == 16 && strncmp(name,
"X509 CERTIFICATE", 16) == 0)) {
333 br_x509_certificate xc;
334 xc.data = pos[u].
data;
343 for (u = 0; u < num_pos; u++) {
344 free_pem_object_contents(&pos[u]);
349 log_error(
"No certificates found in PEM data");
362static void free_certificates(br_x509_certificate *certs,
size_t num) {
364 for (u = 0; u < num; u++) {
365 xfree((
void *)certs[u].data);
372static void dn_append(
void *ctx,
const void *buf,
size_t len) {
376static asciichat_error_t certificate_to_trust_anchor_inner(br_x509_trust_anchor *ta, br_x509_certificate *xc) {
377 br_x509_decoder_context dc;
381 br_x509_decoder_init(&dc, dn_append, &vdn);
382 br_x509_decoder_push(&dc, xc->data, xc->data_len);
383 pk = br_x509_decoder_get_pkey(&dc);
393 if (br_x509_decoder_isCA(&dc)) {
394 ta->flags |= BR_X509_TA_CA;
397 switch (pk->key_type) {
399 ta->pkey.key_type = BR_KEYTYPE_RSA;
400 ta->pkey.key.rsa.n = xblobdup(pk->key.rsa.n, pk->key.rsa.nlen);
401 ta->pkey.key.rsa.nlen = pk->key.rsa.nlen;
402 ta->pkey.key.rsa.e = xblobdup(pk->key.rsa.e, pk->key.rsa.elen);
403 ta->pkey.key.rsa.elen = pk->key.rsa.elen;
406 ta->pkey.key_type = BR_KEYTYPE_EC;
407 ta->pkey.key.ec.curve = pk->key.ec.curve;
408 ta->pkey.key.ec.q = xblobdup(pk->key.ec.q, pk->key.ec.qlen);
409 ta->pkey.key.ec.qlen = pk->key.ec.qlen;
424 switch (ta->pkey.key_type) {
426 xfree((
void *)ta->pkey.key.rsa.n);
427 xfree((
void *)ta->pkey.key.rsa.e);
430 xfree((
void *)ta->pkey.key.ec.q);
441 br_x509_certificate *xcs;
445 xcs = read_certificates_from_memory(pem_data, pem_len, &num);
450 for (u = 0; u < num; u++) {
451 br_x509_trust_anchor ta;
453 if (certificate_to_trust_anchor_inner(&ta, &xcs[u]) !=
ASCIICHAT_OK) {
455 free_certificates(xcs, num);
463 free_certificates(xcs, num);
⚠️‼️ Error and/or exit() when things go bad.
#define SAFE_MALLOC(size, cast)
size_t read_trust_anchors_from_memory(anchor_list *dst, const unsigned char *pem_data, size_t pem_len)
Read trust anchors from PEM-encoded data in memory.
void free_ta_contents(br_x509_trust_anchor *ta)
Free the contents of a trust anchor.
#define SET_ERRNO(code, context_msg,...)
Set error code with custom context message and log it.
asciichat_error_t
Error and exit codes - unified status values (0-255)
#define log_error(...)
Log an ERROR message.
#define VEC_CLEAREXT(vec, fun)
#define VEC_ADDMANY(vec, xp, num)
#define VEC_ELT(vec, idx)
BearSSL PEM and trust anchor utilities adapted for in-memory data.
Vector type for trust anchors.