Encoder:
- Return the desired length when the buffer is too small. - Annotate the switch so Bullseye doesn't complain about an uncovered default case. Decoder: - The table approach was a good idea, but there was no way to tell the difference between a character that decodes as 0 and an invalid character. Modify the tables so an invalid character is indicated by 0xff instead of 0x00. - Check that padding starts in a valid position. Note that we still don't check for left-over bits. - The overflow test always failed, because we set *olen = len before comparing them. git-svn-id: svn+ssh://svn.openpam.org/svn/openpam/trunk@776 185d5e19-27fe-0310-9dcf-9bff6b9f3609
This commit is contained in:
parent
d60017fe80
commit
75a6073d2c
|
@ -37,32 +37,47 @@
|
|||
|
||||
#include <errno.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <security/oath.h>
|
||||
|
||||
#include "oath_impl.h"
|
||||
|
||||
static const char b32enc[] =
|
||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZ234567";
|
||||
|
||||
static const char b32dec[256] = {
|
||||
['A'] = 0, ['B'] = 1, ['C'] = 2, ['D'] = 3,
|
||||
['E'] = 4, ['F'] = 5, ['G'] = 6, ['H'] = 7,
|
||||
['I'] = 8, ['J'] = 9, ['K'] = 10, ['L'] = 11,
|
||||
['M'] = 12, ['N'] = 13, ['O'] = 14, ['P'] = 15,
|
||||
['Q'] = 16, ['R'] = 17, ['S'] = 18, ['T'] = 19,
|
||||
['U'] = 20, ['V'] = 21, ['W'] = 22, ['X'] = 23,
|
||||
['Y'] = 24, ['Z'] = 25,
|
||||
|
||||
['a'] = 0, ['b'] = 1, ['c'] = 2, ['d'] = 3,
|
||||
['e'] = 4, ['f'] = 5, ['g'] = 6, ['h'] = 7,
|
||||
['i'] = 8, ['j'] = 9, ['k'] = 10, ['l'] = 11,
|
||||
['m'] = 12, ['n'] = 13, ['o'] = 14, ['p'] = 15,
|
||||
['q'] = 16, ['r'] = 17, ['s'] = 18, ['t'] = 19,
|
||||
['u'] = 20, ['v'] = 21, ['w'] = 22, ['x'] = 23,
|
||||
['y'] = 24, ['z'] = 25,
|
||||
|
||||
['2'] = 26, ['3'] = 27, ['4'] = 28, ['5'] = 29,
|
||||
['6'] = 30, ['7'] = 31,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06,
|
||||
0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e,
|
||||
0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16,
|
||||
0x17, 0x18, 0x19, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -75,6 +90,7 @@ base32_enc(const char *in, size_t ilen, char *out, size_t *olen)
|
|||
uint64_t bits;
|
||||
|
||||
if (*olen <= base32_enclen(ilen)) {
|
||||
*olen = base32_enclen(ilen) + 1;
|
||||
errno = ENOSPC;
|
||||
return (-1);
|
||||
}
|
||||
|
@ -110,6 +126,7 @@ base32_enc(const char *in, size_t ilen, char *out, size_t *olen)
|
|||
bits |= (uint64_t)in[1] << 24;
|
||||
case 1:
|
||||
bits |= (uint64_t)in[0] << 32;
|
||||
COVERAGE_NO_DEFAULT_CASE
|
||||
}
|
||||
out[0] = b32enc[bits >> 35 & 0x1f];
|
||||
out[1] = b32enc[bits >> 30 & 0x1f];
|
||||
|
@ -153,11 +170,11 @@ base32_dec(const char *in, size_t ilen, char *out, size_t *olen)
|
|||
(padding && *in == '=')) {
|
||||
/* consume */
|
||||
continue;
|
||||
} else if (!padding && b32dec[(int)*in]) {
|
||||
} else if (!padding && b32dec[(int)*in] >= 0) {
|
||||
/* shift into accumulator */
|
||||
shift += 5;
|
||||
bits = bits << 5 | b32dec[(int)*in];
|
||||
} else if (!padding && shift && *in == '=') {
|
||||
} else if (!padding && shift > 0 && shift < 5 && *in == '=') {
|
||||
/* final byte */
|
||||
shift = 0;
|
||||
padding = 1;
|
||||
|
@ -175,11 +192,12 @@ base32_dec(const char *in, size_t ilen, char *out, size_t *olen)
|
|||
}
|
||||
}
|
||||
/* report decoded length */
|
||||
*olen = len;
|
||||
if (len > *olen) {
|
||||
/* overflow */
|
||||
*olen = len;
|
||||
errno = ENOSPC;
|
||||
return (-1);
|
||||
}
|
||||
*olen = len;
|
||||
return (0);
|
||||
}
|
||||
|
|
|
@ -40,28 +40,46 @@
|
|||
|
||||
#include <security/oath.h>
|
||||
|
||||
#include "oath_impl.h"
|
||||
|
||||
static const char b64enc[] =
|
||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||
"abcdefghijklmnopqrstuvwxyz"
|
||||
"0123456789+/";
|
||||
|
||||
static const char b64dec[256] = {
|
||||
['A'] = 0, ['B'] = 1, ['C'] = 2, ['D'] = 3,
|
||||
['E'] = 4, ['F'] = 5, ['G'] = 6, ['H'] = 7,
|
||||
['I'] = 8, ['J'] = 9, ['K'] = 10, ['L'] = 11,
|
||||
['M'] = 12, ['N'] = 13, ['O'] = 14, ['P'] = 15,
|
||||
['Q'] = 16, ['R'] = 17, ['S'] = 18, ['T'] = 19,
|
||||
['U'] = 20, ['V'] = 21, ['W'] = 22, ['X'] = 23,
|
||||
['Y'] = 24, ['Z'] = 25, ['a'] = 26, ['b'] = 27,
|
||||
['c'] = 28, ['d'] = 29, ['e'] = 30, ['f'] = 31,
|
||||
['g'] = 32, ['h'] = 33, ['i'] = 34, ['j'] = 35,
|
||||
['k'] = 36, ['l'] = 37, ['m'] = 38, ['n'] = 39,
|
||||
['o'] = 40, ['p'] = 41, ['q'] = 42, ['r'] = 43,
|
||||
['s'] = 44, ['t'] = 45, ['u'] = 46, ['v'] = 47,
|
||||
['w'] = 48, ['x'] = 49, ['y'] = 50, ['z'] = 51,
|
||||
['0'] = 52, ['1'] = 53, ['2'] = 54, ['3'] = 55,
|
||||
['4'] = 56, ['5'] = 57, ['6'] = 58, ['7'] = 59,
|
||||
['8'] = 60, ['9'] = 61, ['+'] = 62, ['/'] = 63,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0x3e, 0xff, 0xff, 0xff, 0x3f,
|
||||
0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b,
|
||||
0x3c, 0x3d, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06,
|
||||
0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e,
|
||||
0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16,
|
||||
0x17, 0x18, 0x19, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20,
|
||||
0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28,
|
||||
0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30,
|
||||
0x31, 0x32, 0x33, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -73,8 +91,11 @@ base64_enc(const char *in, size_t ilen, char *out, size_t *olen)
|
|||
{
|
||||
uint32_t bits;
|
||||
|
||||
if (*olen <= base64_enclen(ilen))
|
||||
if (*olen <= base64_enclen(ilen)) {
|
||||
*olen = base64_enclen(ilen) + 1;
|
||||
errno = ENOSPC;
|
||||
return (-1);
|
||||
}
|
||||
*olen = 0;
|
||||
while (ilen >= 3) {
|
||||
bits = 0;
|
||||
|
@ -97,6 +118,7 @@ base64_enc(const char *in, size_t ilen, char *out, size_t *olen)
|
|||
bits |= (uint32_t)in[1] << 8;
|
||||
case 1:
|
||||
bits |= (uint32_t)in[0] << 16;
|
||||
COVERAGE_NO_DEFAULT_CASE
|
||||
}
|
||||
out[0] = b64enc[bits >> 18 & 0x3f];
|
||||
out[1] = b64enc[bits >> 12 & 0x3f];
|
||||
|
@ -136,11 +158,11 @@ base64_dec(const char *in, size_t ilen, char *out, size_t *olen)
|
|||
(padding && *in == '=')) {
|
||||
/* consume */
|
||||
continue;
|
||||
} else if (!padding && b64dec[(int)*in]) {
|
||||
} else if (!padding && b64dec[(int)*in] >= 0) {
|
||||
/* shift into accumulator */
|
||||
shift += 6;
|
||||
bits = bits << 6 | b64dec[(int)*in];
|
||||
} else if (!padding && shift && *in == '=') {
|
||||
} else if (!padding && shift > 0 && shift != 6 && *in == '=') {
|
||||
/* final byte */
|
||||
shift = 0;
|
||||
padding = 1;
|
||||
|
@ -158,11 +180,12 @@ base64_dec(const char *in, size_t ilen, char *out, size_t *olen)
|
|||
}
|
||||
}
|
||||
/* report decoded length */
|
||||
*olen = len;
|
||||
if (len > *olen) {
|
||||
/* overflow */
|
||||
*olen = len;
|
||||
errno = ENOSPC;
|
||||
return (-1);
|
||||
}
|
||||
*olen = len;
|
||||
return (0);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue