VECTOR_HANDLE decode_pem()

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;
}