Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 38 additions & 3 deletions src/est/est_client.c
Original file line number Diff line number Diff line change
Expand Up @@ -384,24 +384,59 @@ static EST_ERROR b64_decode_cacerts (unsigned char *cacerts, int *cacerts_len,
ossl_dump_ssl_errors();
return (EST_ERR_MALLOC);
}

/*
* Decoding will always take up less than the original buffer.
* BIO_f_base64 either requires wrapped base64 with a short
* initial line, or when BIO_FLAGS_BASE64_NO_NL is set, all data
* must be on a single line (with or without trailing newline
* character). See BIO_f_base64(3ossl) for more details.
*
* RFC 8951 (an update to RFC 7030) clarifies that senders are
* not required to insert white space (such as LF) in
* base64-encoded payloads. Therefore libest must handle
* wrapped or unwrapped base64 with lines of any length.
*
* This leaves two options:
*
* 1. set BIO_FLAGS_BASE64_NO_NL and unwrap the input lines
*
* 2. leave the flag unset but split long lines and ensure the
* input ends with a newline.
*
* Option 1 is simpler so that's what we do.
*/
in = BIO_new_mem_buf(cacerts, *cacerts_len);
BIO_set_flags(b64, BIO_get_flags(b64) | BIO_FLAGS_BASE64_NO_NL);

in = BIO_new(BIO_s_mem());
if (in == NULL) {
EST_LOG_ERR("Unable to access the CA cert buffer");
ossl_dump_ssl_errors();
BIO_free_all(b64);
return (EST_ERR_MALLOC);
}
in = BIO_push(b64, in);

/*
* Unwrap the input (remove newlines) by reading from 'cacerts'
* into 'in' line by line.
*/
unsigned char *p = cacerts, *end = p + *cacerts_len, *nl;
while ((nl = memchr(p, '\n', end - p)) != NULL) {
BIO_write_ex(in, p, nl - p, NULL);
p = nl + 1;
}
BIO_write_ex(in, p, end - p, NULL);

/*
* Decoding will always take up less than the original buffer.
*/
decoded_buf = malloc(*cacerts_len);
if (decoded_buf == NULL) {
EST_LOG_ERR("Unable to allocate CA cert buffer for decode");
BIO_free_all(in);
return (EST_ERR_MALLOC);
}

in = BIO_push(b64, in);
decoded_buf_len = BIO_read(in, decoded_buf, *cacerts_len);

*cacerts_decoded = decoded_buf;
Expand Down