Skip to content

Commit 5d03478

Browse files
b64_decode_cacerts: accept non-wrapped input
`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 this commit implements. Signed-off-by: Fraser Tweedale <[email protected]>
1 parent f8a6e5b commit 5d03478

File tree

1 file changed

+38
-3
lines changed

1 file changed

+38
-3
lines changed

src/est/est_client.c

Lines changed: 38 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -384,24 +384,59 @@ static EST_ERROR b64_decode_cacerts (unsigned char *cacerts, int *cacerts_len,
384384
ossl_dump_ssl_errors();
385385
return (EST_ERR_MALLOC);
386386
}
387+
387388
/*
388-
* Decoding will always take up less than the original buffer.
389+
* BIO_f_base64 either requires wrapped base64 with a short
390+
* initial line, or when BIO_FLAGS_BASE64_NO_NL is set, all data
391+
* must be on a single line (with or without trailing newline
392+
* character). See BIO_f_base64(3ossl) for more details.
393+
*
394+
* RFC 8951 (an update to RFC 7030) clarifies that senders are
395+
* not required to insert white space (such as LF) in
396+
* base64-encoded payloads. Therefore libest must handle
397+
* wrapped or unwrapped base64 with lines of any length.
398+
*
399+
* This leaves two options:
400+
*
401+
* 1. set BIO_FLAGS_BASE64_NO_NL and unwrap the input lines
402+
*
403+
* 2. leave the flag unset but split long lines and ensure the
404+
* input ends with a newline.
405+
*
406+
* Option 1 is simpler so that's what we do.
389407
*/
390-
in = BIO_new_mem_buf(cacerts, *cacerts_len);
408+
BIO_set_flags(b64, BIO_get_flags(b64) | BIO_FLAGS_BASE64_NO_NL);
409+
410+
in = BIO_new(BIO_s_mem());
391411
if (in == NULL) {
392412
EST_LOG_ERR("Unable to access the CA cert buffer");
393413
ossl_dump_ssl_errors();
394414
BIO_free_all(b64);
395415
return (EST_ERR_MALLOC);
396416
}
397-
in = BIO_push(b64, in);
417+
418+
/*
419+
* Unwrap the input (remove newlines) by reading from 'cacerts'
420+
* into 'in' line by line.
421+
*/
422+
unsigned char *p = cacerts, *end = p + *cacerts_len, *nl;
423+
while ((nl = memchr(p, '\n', end - p)) != NULL) {
424+
BIO_write_ex(in, p, nl - p, NULL);
425+
p = nl + 1;
426+
}
427+
BIO_write_ex(in, p, end - p, NULL);
428+
429+
/*
430+
* Decoding will always take up less than the original buffer.
431+
*/
398432
decoded_buf = malloc(*cacerts_len);
399433
if (decoded_buf == NULL) {
400434
EST_LOG_ERR("Unable to allocate CA cert buffer for decode");
401435
BIO_free_all(in);
402436
return (EST_ERR_MALLOC);
403437
}
404438

439+
in = BIO_push(b64, in);
405440
decoded_buf_len = BIO_read(in, decoded_buf, *cacerts_len);
406441

407442
*cacerts_decoded = decoded_buf;

0 commit comments

Comments
 (0)