Skip to content
Merged
Show file tree
Hide file tree
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
15 changes: 13 additions & 2 deletions include/tscore/ink_base64.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,5 +42,16 @@ bool ats_base64_encode(const unsigned char *inBuffer, size_t inBufferSize, char
bool ats_base64_decode(const char *inBuffer, size_t inBufferSize, unsigned char *outBuffer, size_t outBufSize, size_t *length);

// Little helper functions to calculate minimum required output buffer for encoding/decoding.
#define ATS_BASE64_ENCODE_DSTLEN(_length) ((_length * 8) / 6 + 4)
#define ATS_BASE64_DECODE_DSTLEN(_length) (((_length + 3) / 4) * 3)
// These sizes include one byte for null termination, because ats_base64_encode and ats_base64_decode will always write a null
// terminator.
inline constexpr size_t
ats_base64_encode_dstlen(size_t length)
{
return ((length + 2) / 3) * 4 + 1;
}

inline constexpr size_t
ats_base64_decode_dstlen(size_t length)
{
return ((length + 3) / 4) * 3 + 1;
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not?

inline constexpr size_t
ats_base64_encode_dstlen(size_t length, bool pad = true)
{
  size_t num_bit_pairs = 4 * length;
  return (pad ? (((num_bit_pairs + 11) / 12) * 4) : ((num_bit_pairs + 2) / 3)) + 1;
}

inline constexpr size_t
ats_base64_unpadded_decode_dstlen(size_t length)
{
  return (((length / 4) * 3) + (length % 4)) + 1;
}

inline size_t
ats_base64_padded_decode_dstlen(char const *data, size_t length)
{
  ink_assert(!(length % 4));

  if (length && ('=' == data[length - 1])) {
    --length;
  }
  if (length && ('=' == data[length - 1])) {
    --length;
  }

  return ats_base64_unpadded_decode_dstlen(length);
}

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The length calculation is meant for ats_base64_encode(), so the goal is to just give the length of the buffer needed to store the encoded output. Both ats_base64_encode() and the RFC specify padding that is non-optional.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Then why not?

inline size_t
ats_base64_decode_dstlen(char const *data, size_t length)
{
  ink_assert(!(length % 4));

  size_t adjust = 0;
  if (length && ('=' == data[length - 1])) {
    adjust = ('=' == data[length - 2])) ? 2 : 1;
  }
  return (((length / 4) * 3) - adjust + 1;
}

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If I'm reading this right, you're trying to give a buffer size that is as small as possible, accounting for the possibility of padding characters at the end. While I appreciate being frugal with allocation size, I think that the size savings of possibly one or two bytes may not warrant such an increase in complexity when computing the buffer size.

18 changes: 9 additions & 9 deletions plugins/experimental/access_control/unit_tests/test_utils.cc
Original file line number Diff line number Diff line change
Expand Up @@ -36,19 +36,19 @@ TEST_CASE("Base64: estimate buffer size needed to encode a message", "[Base64][a

/* Test with a zero decoded message length */
encodedLen = cryptoBase64EncodedSize(0);
CHECK(4 == encodedLen);
CHECK(1 == encodedLen);

/* Test with a random non-zero decoded message length */
encodedLen = cryptoBase64EncodedSize(64);
CHECK(89 == encodedLen);

/* Test the space for padding. Size of encoding that would result in 2 x "=" padding */
encodedLen = cryptoBase64EncodedSize(strlen("176a1620e31b14782ba2b66de3edc5b3cb19630475b2ce2ee292d5fd0fe41c3abc"));
CHECK(92 == encodedLen);
CHECK(89 == encodedLen);

/* Test the space for padding. Size of encoding that would result in 1 x "=" padding */
encodedLen = cryptoBase64EncodedSize(strlen("176a1620e31b14782ba2b66de3edc5b3cb19630475b2ce2ee292d5fd0fe41c3ab"));
CHECK(90 == encodedLen);
CHECK(89 == encodedLen);

/* Test the space for padding. Size of encoding that would result in no padding */
encodedLen = cryptoBase64EncodedSize(strlen("176a1620e31b14782ba2b66de3edc5b3cb19630475b2ce2ee292d5fd0fe41c3a"));
Expand All @@ -63,27 +63,27 @@ TEST_CASE("Base64: estimate buffer size needed to decode a message", "[Base64][a
/* Padding with 2 x '=' */
encoded = "MTc2YTE2MjBlMzFiMTQ3ODJiYTJiNjZkZTNlZGM1YjNjYjE5NjMwNDc1YjJjZTJlZTI5MmQ1ZmQwZmU0MWMzYQ==";
encodedLen = cryptoBase64DecodeSize(encoded, strlen(encoded));
CHECK(66 == encodedLen);
CHECK(67 == encodedLen);

/* Padding with 1 x '=' */
encoded = "MTc2YTE2MjBlMzFiMTQ3ODJiYTJiNjZkZTNlZGM1YjNjYjE5NjMwNDc1YjJjZTJlZTI5MmQ1ZmQwZmU0MWMzYWI=";
encodedLen = cryptoBase64DecodeSize(encoded, strlen(encoded));
CHECK(66 == encodedLen);
CHECK(67 == encodedLen);

/* Padding with 0 x "=" */
encoded = "MTc2YTE2MjBlMzFiMTQ3ODJiYTJiNjZkZTNlZGM1YjNjYjE5NjMwNDc1YjJjZTJlZTI5MmQ1ZmQwZmU0MWMzYWJj";
encodedLen = cryptoBase64DecodeSize(encoded, strlen(encoded));
CHECK(66 == encodedLen);
CHECK(67 == encodedLen);

/* Test empty encoded message calculation */
encoded = "";
encodedLen = cryptoBase64DecodeSize(encoded, strlen(encoded));
CHECK(0 == encodedLen);
CHECK(1 == encodedLen);

/* Test empty encoded message calculation */
encoded = nullptr;
encodedLen = cryptoBase64DecodeSize(encoded, 0);
CHECK(0 == encodedLen);
CHECK(1 == encodedLen);
}

TEST_CASE("Base64: quick encode / decode", "[Base64][access_control][utility]")
Expand All @@ -103,7 +103,7 @@ TEST_CASE("Base64: quick encode / decode", "[Base64][access_control][utility]")
encodedMessageLen));

size_t decodedMessageEstimatedLen = cryptoBase64DecodeSize(encodedMessage, encodedMessageLen);
CHECK(66 == decodedMessageEstimatedLen);
CHECK(67 == decodedMessageEstimatedLen);
char decodedMessage[encodedMessageEstimatedLen];
size_t decodedMessageLen = cryptoBase64Decode(encodedMessage, encodedMessageLen, decodedMessage, encodedMessageLen);

Expand Down
4 changes: 2 additions & 2 deletions plugins/experimental/access_control/utils.cc
Original file line number Diff line number Diff line change
Expand Up @@ -296,7 +296,7 @@ cryptoMessageDigestEqual(const char *md1, size_t md1Len, const char *md2, size_t
size_t
cryptoBase64EncodedSize(size_t decodedSize)
{
return ATS_BASE64_ENCODE_DSTLEN(decodedSize);
return ats_base64_encode_dstlen(decodedSize);
}

/**
Expand All @@ -308,7 +308,7 @@ cryptoBase64EncodedSize(size_t decodedSize)
size_t
cryptoBase64DecodeSize(const char *encoded, size_t encodedLen)
{
return ATS_BASE64_DECODE_DSTLEN(encodedLen);
return ats_base64_decode_dstlen(encodedLen);
}

/**
Expand Down
2 changes: 1 addition & 1 deletion plugins/experimental/metalink/metalink.cc
Original file line number Diff line number Diff line change
Expand Up @@ -693,7 +693,7 @@ location_handler(TSCont contp, TSEvent event, void * /* edata ATS_UNUSED */)
const char *value;
int length;

char digest[33]; /* ATS_BASE64_DECODE_DSTLEN() */
char digest[33]; /* ats_base64_decode_dstlen() */

SendData *data = static_cast<SendData *>(TSContDataGet(contp));
TSContDestroy(contp);
Expand Down
6 changes: 2 additions & 4 deletions src/tscore/ink_base64.cc
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,6 @@
* authentication scheme does not require them. This implementation is
* intended for web-related use, and line breaks are not implemented.
*
* These routines return char*'s to malloc-ed strings. The caller is
* responsible for freeing the strings.
*/
#include "tscore/ink_platform.h"
#include "tscore/ink_base64.h"
Expand All @@ -44,7 +42,7 @@ ats_base64_encode(const unsigned char *inBuffer, size_t inBufferSize, char *outB
char *obuf = outBuffer;
char in_tail[4];

if (outBufSize < ATS_BASE64_ENCODE_DSTLEN(inBufferSize)) {
if (outBufSize < ats_base64_encode_dstlen(inBufferSize)) {
return false;
}

Expand Down Expand Up @@ -130,7 +128,7 @@ ats_base64_decode(const char *inBuffer, size_t inBufferSize, unsigned char *outB
int inputBytesDecoded = 0;

// Make sure there is sufficient space in the output buffer
if (outBufSize < ATS_BASE64_DECODE_DSTLEN(inBufferSize)) {
if (outBufSize < ats_base64_decode_dstlen(inBufferSize)) {
return false;
}

Expand Down