in adapters/tlsio_bearssl.c [276:391]
VECTOR_HANDLE decode_pem(const void *src, size_t len)
{
VECTOR_HANDLE pem_list;
br_pem_decoder_context pc;
pem_object po;
//pem_object *pos;
const unsigned char *buf;
BUFFER_HANDLE bv = NULL;
int inobj;
int extra_nl;
size_t i;
pem_list = VECTOR_create(sizeof(pem_object));
if (pem_list == NULL)
{
LogError("Unable to allocate vectore to decode PEM");
}
else
{
br_pem_decoder_init(&pc);
buf = src;
inobj = 0;
po.name = NULL;
po.data = NULL;
po.data_len = 0;
extra_nl = 1;
while (len > 0) {
size_t tlen;
tlen = br_pem_decoder_push(&pc, buf, len);
buf += tlen;
len -= tlen;
switch (br_pem_decoder_event(&pc)) {
case BR_PEM_BEGIN_OBJ:
inobj = 1;
if (0 != mallocAndStrcpy_s(&po.name, br_pem_decoder_name(&pc)))
{
LogError("Unable to allocate memory for certificate name");
break;
}
bv = BUFFER_new();
if (bv == NULL)
{
LogError("Unable to allocate buffer to decode pem");
len = 0;
extra_nl = 0;
}
else
{
br_pem_decoder_setdest(&pc, vblob_append, bv);
}
break;
case BR_PEM_END_OBJ:
if (inobj)
{
po.data = BUFFER_u_char(bv);
po.data_len = BUFFER_length(bv);
free(bv);
bv = NULL;
VECTOR_push_back(pem_list, &po, 1);
po.name = NULL;
po.data = NULL;
po.data_len = 0;
inobj = 0;
}
break;
case BR_PEM_ERROR:
LogError("ERROR: invalid PEM encoding");
inobj = 1;
break;
}
/*
* We add an extra newline at the end, in order to
* support PEM files that lack the newline on their last
* line (this is somewhat invalid, but PEM format is not
* standardised and such files do exist in the wild, so
* we'd better accept them).
*/
if (len == 0 && extra_nl) {
extra_nl = 0;
buf = (const unsigned char *)"\n";
len = 1;
}
}
if (inobj)
{
LogError("Unable to decode pem");
for (i = 0; i < VECTOR_size(pem_list); i++)
{
free(((pem_object *)VECTOR_element(pem_list, i))->name);
free(((pem_object *)VECTOR_element(pem_list, i))->data);
}
VECTOR_clear(pem_list);
free(po.name);
po.name = NULL;
BUFFER_delete(bv);
bv = NULL;
pem_list = NULL;
}
}
return pem_list;
}