Commit 0384fc6f authored by Niels Möller's avatar Niels Möller

(base64_encode): Encode from the end of the data

towards the start, in order to support overlapping areas.

Rev: src/nettle/base64.c:1.3
Rev: src/nettle/base64.h:1.5
parent d889111d
...@@ -26,6 +26,7 @@ ...@@ -26,6 +26,7 @@
#include "base64.h" #include "base64.h"
#include <assert.h> #include <assert.h>
#include <stdlib.h>
#define TABLE_INVALID -1 #define TABLE_INVALID -1
#define TABLE_SPACE -2 #define TABLE_SPACE -2
...@@ -56,42 +57,55 @@ static const signed char decode_table[256] = ...@@ -56,42 +57,55 @@ static const signed char decode_table[256] =
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
}; };
#define ENCODE(x) (encode_table[0x3F & (x)])
unsigned unsigned
base64_encode(uint8_t *dst, base64_encode(uint8_t *dst,
unsigned src_length, unsigned src_length,
const uint8_t *src) const uint8_t *src)
{ {
uint8_t *out = dst; unsigned dst_length = BASE64_ENCODE_LENGTH(src_length);
const uint8_t *in = src + src_length;
uint8_t *out = dst + dst_length;
unsigned left_over = src_length % 3;
while (src_length >= 3) if (left_over)
{ {
*out++ = encode_table[0x3F & (src[0] >> 2)]; switch(left_over)
*out++ = encode_table[0x3F & ((src[0] << 4) | (src[1] >> 4))]; {
*out++ = encode_table[0x3F & ((src[1] << 2) | (src[2] >> 6))]; case 1:
*out++ = encode_table[0x3F & src[2]]; in--;
src += 3; *--out = '=';
src_length -= 3; *--out = '=';
} *--out = ENCODE(in[0] << 4);
*--out = ENCODE(in[0] >> 2);
break;
case 2:
in-= 2;
*--out = '=';
*--out = ENCODE( in[1] << 2);
*--out = ENCODE((in[0] << 4) | (in[1] >> 4));
*--out = ENCODE( in[0] >> 2);
break;
switch (src_length) default:
abort();
}
}
while (in > src)
{ {
case 2: in -= 3;
*out++ = encode_table[0x3F & (src[0] >> 2)]; *--out = ENCODE( in[2]);
*out++ = encode_table[0x3F & ((src[0] << 4) | (src[1] >> 4))]; *--out = ENCODE((in[1] << 2) | (in[2] >> 6));
*out++ = encode_table[0x3F & (src[1] << 2)]; *--out = ENCODE((in[0] << 4) | (in[1] >> 4));
*out++ = '='; *--out = ENCODE( in[0] >> 2);
break;
case 1:
*out++ = encode_table[0x3F & (src[0] >> 2)];
*out++ = encode_table[0x3F & (src[0] << 4)];
*out++ = '=';
*out++ = '=';
break;
case 0:
break;
} }
return out - dst; assert(out == dst);
return dst_length;
} }
void void
......
...@@ -33,6 +33,9 @@ ...@@ -33,6 +33,9 @@
#define BASE64_BINARY_BLOCK_SIZE 3 #define BASE64_BINARY_BLOCK_SIZE 3
#define BASE64_TEXT_BLOCK_SIZE 4 #define BASE64_TEXT_BLOCK_SIZE 4
/* Overlapping source and destination is allowed, as long as the start
* of the source area is not later than the start of the destination
* area. */
unsigned /* Returns the length of encoded data */ unsigned /* Returns the length of encoded data */
base64_encode(uint8_t *dst, base64_encode(uint8_t *dst,
unsigned src_length, unsigned src_length,
...@@ -53,6 +56,9 @@ struct base64_ctx /* Internal, do not modify */ ...@@ -53,6 +56,9 @@ struct base64_ctx /* Internal, do not modify */
void void
base64_decode_init(struct base64_ctx *ctx); base64_decode_init(struct base64_ctx *ctx);
/* Overlapping source and destination is allowed, as long as the start
* of the source area is not before the start of the destination
* area. */
unsigned /* Returns the length of decoded data */ unsigned /* Returns the length of decoded data */
base64_decode_update(struct base64_ctx *ctx, base64_decode_update(struct base64_ctx *ctx,
uint8_t *dst, uint8_t *dst,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment