30#include <ascii-chat/common.h>
31#include <ascii-chat/crypto/pem_utils.h>
32#include <ascii-chat/asciichat_errno.h>
34#include <ascii-chat-deps/bearssl/inc/bearssl.h>
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) {
93 buf = SAFE_MALLOC(len,
void *);
97static void xfree(
void *buf) {
103static void *xblobdup(
const void *src,
size_t len) {
108 buf = SAFE_MALLOC(len,
void *);
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++;
198static void free_pem_object_t_contents(
pem_object_t *po) {
205static void vblob_append(
void *cc,
const void *data,
size_t len) {
214static pem_object_t *decode_pem(
const void *src,
size_t len,
size_t *num) {
216 br_pem_decoder_context pc;
218 const unsigned char *buf;
224 br_pem_decoder_init(&pc);
235 tlen = br_pem_decoder_push(&pc, buf, len);
239 switch (br_pem_decoder_event(&pc)) {
241 case BR_PEM_BEGIN_OBJ:
242 po.
name = xstrdup(br_pem_decoder_name(&pc));
243 br_pem_decoder_setdest(&pc, vblob_append, &bv);
263 log_error(
"Invalid PEM encoding");
273 if (len == 0 && extra_nl) {
275 buf = (
const unsigned char *)
"\n";
281 log_error(
"Unfinished PEM object");
301static br_x509_certificate *read_certificates_from_memory(
const unsigned char *buf,
size_t len,
size_t *num) {
305 br_x509_certificate *xcs;
306 br_x509_certificate dummy;
311 if (looks_like_DER(buf, len)) {
312 xcs = xmalloc(2 *
sizeof *xcs);
313 xcs[0].data = xblobdup(buf, len);
314 xcs[0].data_len = len;
322 pos = decode_pem(buf, len, &num_pos);
328 for (u = 0; u < num_pos; u++) {
331 const char *name = pos[u].
name;
334 size_t name_len = strlen(name);
335 while (name_len > 0 && name[name_len - 1] ==
'-') {
340 if ((name_len == 11 && strncmp(name,
"CERTIFICATE", 11) == 0) ||
341 (name_len == 16 && strncmp(name,
"X509 CERTIFICATE", 16) == 0)) {
342 br_x509_certificate xc;
343 xc.data = pos[u].
data;
352 for (u = 0; u < num_pos; u++) {
353 free_pem_object_t_contents(&pos[u]);
358 log_error(
"No certificates found in PEM data");
371static void free_certificates(br_x509_certificate *certs,
size_t num) {
373 for (u = 0; u < num; u++) {
374 xfree((
void *)certs[u].data);
381static void dn_append(
void *ctx,
const void *buf,
size_t len) {
385static asciichat_error_t certificate_to_trust_anchor_inner(br_x509_trust_anchor *ta, br_x509_certificate *xc) {
386 br_x509_decoder_context dc;
390 br_x509_decoder_init(&dc, dn_append, &vdn);
391 br_x509_decoder_push(&dc, xc->data, xc->data_len);
392 pk = br_x509_decoder_get_pkey(&dc);
395 return SET_ERRNO(ERROR_CRYPTO,
"CA decoding failed with error %d", br_x509_decoder_last_error(&dc));
402 if (br_x509_decoder_isCA(&dc)) {
403 ta->flags |= BR_X509_TA_CA;
406 switch (pk->key_type) {
408 ta->pkey.key_type = BR_KEYTYPE_RSA;
409 ta->pkey.key.rsa.n = xblobdup(pk->key.rsa.n, pk->key.rsa.nlen);
410 ta->pkey.key.rsa.nlen = pk->key.rsa.nlen;
411 ta->pkey.key.rsa.e = xblobdup(pk->key.rsa.e, pk->key.rsa.elen);
412 ta->pkey.key.rsa.elen = pk->key.rsa.elen;
415 ta->pkey.key_type = BR_KEYTYPE_EC;
416 ta->pkey.key.ec.curve = pk->key.ec.curve;
417 ta->pkey.key.ec.q = xblobdup(pk->key.ec.q, pk->key.ec.qlen);
418 ta->pkey.key.ec.qlen = pk->key.ec.qlen;
422 return SET_ERRNO(ERROR_CRYPTO,
"Unsupported public key type in CA certificate");
433 switch (ta->pkey.key_type) {
435 xfree((
void *)ta->pkey.key.rsa.n);
436 xfree((
void *)ta->pkey.key.rsa.e);
439 xfree((
void *)ta->pkey.key.ec.q);
442 SET_ERRNO(ERROR_CRYPTO,
"Unknown public key type in CA");
450 br_x509_certificate *xcs;
454 xcs = read_certificates_from_memory(pem_data, pem_len, &num);
459 for (u = 0; u < num; u++) {
460 br_x509_trust_anchor ta;
462 if (certificate_to_trust_anchor_inner(&ta, &xcs[u]) != ASCIICHAT_OK) {
464 free_certificates(xcs, num);
472 free_certificates(xcs, num);
#define VEC_CLEAREXT(vec, fun)
#define VEC_ADDMANY(vec, xp, num)
#define VEC_ELT(vec, idx)
size_t read_trust_anchors_from_memory(anchor_list *dst, const unsigned char *pem_data, size_t pem_len)
void free_ta_contents(br_x509_trust_anchor *ta)
Dynamic byte vector for PEM decoding.
Parsed PEM object with name and data.
char * name
PEM object name (e.g., "CERTIFICATE", "PRIVATE KEY")
size_t data_len
Length of data in bytes.
unsigned char * data
Decoded binary data.