Skip to content
Snippets Groups Projects
Commit 62e431b4 authored by Niels Möller's avatar Niels Möller
Browse files

* base64-decode.c (base64_decode_single): Return -1 on error.

Also keep track of the number of padding characters ('=') seen.
(base64_decode_update): New argument dst_length. Return -1 on error.
(base64_decode_status):  Renamed function...
(base64_decode_final): ... to this.

* base64.h (struct base64_decode_ctx): Deleted STATUS attribute.
Added PADDING attribute.

Rev: src/nettle/base64-decode.c:1.4
Rev: src/nettle/base64.h:1.11
parent e3e5eb76
No related branches found
No related tags found
No related merge requests found
...@@ -57,30 +57,26 @@ decode_table[0x100] = ...@@ -57,30 +57,26 @@ decode_table[0x100] =
void void
base64_decode_init(struct base64_decode_ctx *ctx) base64_decode_init(struct base64_decode_ctx *ctx)
{ {
ctx->word = ctx->bits = 0; ctx->word = ctx->bits = ctx->padding = 0;
ctx->status = BASE64_DECODE_OK;
} }
unsigned int
base64_decode_single(struct base64_decode_ctx *ctx, base64_decode_single(struct base64_decode_ctx *ctx,
uint8_t *dst, uint8_t *dst,
uint8_t src) uint8_t src)
{ {
int data; int data;
if (ctx->status == BASE64_DECODE_ERROR)
return 0;
data = decode_table[src]; data = decode_table[src];
switch(data) switch(data)
{ {
default: default:
assert(data >= 0 && data < 0x40); assert(data >= 0 && data < 0x40);
if (ctx->status != BASE64_DECODE_OK) if (ctx->padding)
goto invalid; return -1;
ctx->word = ctx->word << 6 | data; ctx->word = ctx->word << 6 | data;
ctx->bits += 6; ctx->bits += 6;
...@@ -93,56 +89,60 @@ base64_decode_single(struct base64_decode_ctx *ctx, ...@@ -93,56 +89,60 @@ base64_decode_single(struct base64_decode_ctx *ctx,
else return 0; else return 0;
case TABLE_INVALID: case TABLE_INVALID:
invalid: return -1;
ctx->status = BASE64_DECODE_ERROR;
/* Fall through */
case TABLE_SPACE: case TABLE_SPACE:
return 0; return 0;
case TABLE_END: case TABLE_END:
if (!ctx->bits) /* There can be at most two padding characters. */
goto invalid; if (!ctx->bits || ctx->padding > 2)
return -1;
if (ctx->word & ( (1<<ctx->bits) - 1)) if (ctx->word & ( (1<<ctx->bits) - 1))
/* We shouldn't have any leftover bits */ /* We shouldn't have any leftover bits */
goto invalid; return -1;
ctx->status = BASE64_DECODE_END; ctx->padding++;
ctx->bits -= 2; ctx->bits -= 2;
return 0; return 0;
} }
} }
unsigned int
base64_decode_update(struct base64_decode_ctx *ctx, base64_decode_update(struct base64_decode_ctx *ctx,
unsigned *dst_length,
uint8_t *dst, uint8_t *dst,
unsigned length, unsigned src_length,
const uint8_t *src) const uint8_t *src)
{ {
unsigned done; unsigned done;
unsigned i; unsigned i;
if (ctx->status == BASE64_DECODE_ERROR)
return 0;
for (i = 0, done = 0; i<length; i++) assert(*dst_length >= BASE64_DECODE_LENGTH(src_length));
done += base64_decode_single(ctx, dst + done, src[i]);
for (i = 0, done = 0; i<src_length; i++)
assert(done <= BASE64_DECODE_LENGTH(length)); switch(base64_decode_single(ctx, dst + done, src[i]))
{
case -1:
return 0;
case 1:
done++;
/* Fall through */
case 0:
break;
default:
abort();
}
return done; assert(done <= BASE64_DECODE_LENGTH(src_length));
*dst_length = done;
return 1;
} }
int int
base64_decode_status(struct base64_decode_ctx *ctx) base64_decode_final(struct base64_decode_ctx *ctx)
{ {
switch (ctx->status) return ctx->bits == 0;
{
case BASE64_DECODE_END:
case BASE64_DECODE_OK:
return ctx->bits == 0;
case BASE64_DECODE_ERROR:
return 0;
}
abort();
} }
...@@ -95,36 +95,40 @@ base64_encode_group(uint8_t *dst, uint32_t group); ...@@ -95,36 +95,40 @@ base64_encode_group(uint8_t *dst, uint32_t group);
struct base64_decode_ctx struct base64_decode_ctx
{ {
enum
{
BASE64_DECODE_OK,
BASE64_DECODE_ERROR,
BASE64_DECODE_END
} status;
unsigned word; /* Leftover bits */ unsigned word; /* Leftover bits */
unsigned bits; /* Number buffered bits */ unsigned bits; /* Number buffered bits */
/* Number of padding characters encountered */
unsigned padding;
}; };
void void
base64_decode_init(struct base64_decode_ctx *ctx); base64_decode_init(struct base64_decode_ctx *ctx);
/* Decodes a single byte. Returns amount of output (always 0 or 1). /* Decodes a single byte. Returns amount of output (0 or 1), or -1 on
* FIXME: What to return on errors? */ * errors. */
unsigned int
base64_decode_single(struct base64_decode_ctx *ctx, base64_decode_single(struct base64_decode_ctx *ctx,
uint8_t *dst, uint8_t *dst,
uint8_t src); uint8_t src);
/* Returns the number of output characters. DST should point to an /* Returns 1 on success, 0 on error. DST should point to an area of
* area of size at least BASE64_DECODE_LENGTH(length). */ * size at least BASE64_DECODE_LENGTH(length), and for sanity
unsigned * checking, *DST_LENGTH should be initialized to the size of that
* area before the call. *DST_LENGTH is updated to the amount of
* decoded output. */
/* FIXME: Currently results in an assertion failure if *DST_LENGTH is
* too small. Return some error instead? */
int
base64_decode_update(struct base64_decode_ctx *ctx, base64_decode_update(struct base64_decode_ctx *ctx,
unsigned *dst_length,
uint8_t *dst, uint8_t *dst,
unsigned length, unsigned src_length,
const uint8_t *src); const uint8_t *src);
/* Returns 1 on success. */ /* Returns 1 on success. */
int int
base64_decode_status(struct base64_decode_ctx *ctx); base64_decode_final(struct base64_decode_ctx *ctx);
#endif /* NETTLE_BASE64_H_INCLUDED */ #endif /* NETTLE_BASE64_H_INCLUDED */
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment