Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

b64_decode_cacerts: accept non-wrapped input #114

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
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