in Sources/CCryptoBoringSSL/crypto/pem/pem_lib.c [588:756]
int PEM_read_bio(BIO *bp, char **name, char **header, unsigned char **data,
long *len)
{
EVP_ENCODE_CTX ctx;
int end = 0, i, k, bl = 0, hl = 0, nohead = 0;
char buf[256];
BUF_MEM *nameB;
BUF_MEM *headerB;
BUF_MEM *dataB, *tmpB;
nameB = BUF_MEM_new();
headerB = BUF_MEM_new();
dataB = BUF_MEM_new();
if ((nameB == NULL) || (headerB == NULL) || (dataB == NULL)) {
BUF_MEM_free(nameB);
BUF_MEM_free(headerB);
BUF_MEM_free(dataB);
OPENSSL_PUT_ERROR(PEM, ERR_R_MALLOC_FAILURE);
return (0);
}
buf[254] = '\0';
for (;;) {
i = BIO_gets(bp, buf, 254);
if (i <= 0) {
OPENSSL_PUT_ERROR(PEM, PEM_R_NO_START_LINE);
goto err;
}
while ((i >= 0) && (buf[i] <= ' '))
i--;
buf[++i] = '\n';
buf[++i] = '\0';
if (strncmp(buf, "-----BEGIN ", 11) == 0) {
i = strlen(&(buf[11]));
if (strncmp(&(buf[11 + i - 6]), "-----\n", 6) != 0)
continue;
if (!BUF_MEM_grow(nameB, i + 9)) {
OPENSSL_PUT_ERROR(PEM, ERR_R_MALLOC_FAILURE);
goto err;
}
OPENSSL_memcpy(nameB->data, &(buf[11]), i - 6);
nameB->data[i - 6] = '\0';
break;
}
}
hl = 0;
if (!BUF_MEM_grow(headerB, 256)) {
OPENSSL_PUT_ERROR(PEM, ERR_R_MALLOC_FAILURE);
goto err;
}
headerB->data[0] = '\0';
for (;;) {
i = BIO_gets(bp, buf, 254);
if (i <= 0)
break;
while ((i >= 0) && (buf[i] <= ' '))
i--;
buf[++i] = '\n';
buf[++i] = '\0';
if (buf[0] == '\n')
break;
if (!BUF_MEM_grow(headerB, hl + i + 9)) {
OPENSSL_PUT_ERROR(PEM, ERR_R_MALLOC_FAILURE);
goto err;
}
if (strncmp(buf, "-----END ", 9) == 0) {
nohead = 1;
break;
}
OPENSSL_memcpy(&(headerB->data[hl]), buf, i);
headerB->data[hl + i] = '\0';
hl += i;
}
bl = 0;
if (!BUF_MEM_grow(dataB, 1024)) {
OPENSSL_PUT_ERROR(PEM, ERR_R_MALLOC_FAILURE);
goto err;
}
dataB->data[0] = '\0';
if (!nohead) {
for (;;) {
i = BIO_gets(bp, buf, 254);
if (i <= 0)
break;
while ((i >= 0) && (buf[i] <= ' '))
i--;
buf[++i] = '\n';
buf[++i] = '\0';
if (i != 65)
end = 1;
if (strncmp(buf, "-----END ", 9) == 0)
break;
if (i > 65)
break;
if (!BUF_MEM_grow_clean(dataB, i + bl + 9)) {
OPENSSL_PUT_ERROR(PEM, ERR_R_MALLOC_FAILURE);
goto err;
}
OPENSSL_memcpy(&(dataB->data[bl]), buf, i);
dataB->data[bl + i] = '\0';
bl += i;
if (end) {
buf[0] = '\0';
i = BIO_gets(bp, buf, 254);
if (i <= 0)
break;
while ((i >= 0) && (buf[i] <= ' '))
i--;
buf[++i] = '\n';
buf[++i] = '\0';
break;
}
}
} else {
tmpB = headerB;
headerB = dataB;
dataB = tmpB;
bl = hl;
}
i = strlen(nameB->data);
if ((strncmp(buf, "-----END ", 9) != 0) ||
(strncmp(nameB->data, &(buf[9]), i) != 0) ||
(strncmp(&(buf[9 + i]), "-----\n", 6) != 0)) {
OPENSSL_PUT_ERROR(PEM, PEM_R_BAD_END_LINE);
goto err;
}
EVP_DecodeInit(&ctx);
i = EVP_DecodeUpdate(&ctx,
(unsigned char *)dataB->data, &bl,
(unsigned char *)dataB->data, bl);
if (i < 0) {
OPENSSL_PUT_ERROR(PEM, PEM_R_BAD_BASE64_DECODE);
goto err;
}
i = EVP_DecodeFinal(&ctx, (unsigned char *)&(dataB->data[bl]), &k);
if (i < 0) {
OPENSSL_PUT_ERROR(PEM, PEM_R_BAD_BASE64_DECODE);
goto err;
}
bl += k;
if (bl == 0)
goto err;
*name = nameB->data;
*header = headerB->data;
*data = (unsigned char *)dataB->data;
*len = bl;
OPENSSL_free(nameB);
OPENSSL_free(headerB);
OPENSSL_free(dataB);
return (1);
err:
BUF_MEM_free(nameB);
BUF_MEM_free(headerB);
BUF_MEM_free(dataB);
return (0);
}