From 9db80726185159ff58598c6be52ca192602323c7 Mon Sep 17 00:00:00 2001 From: jbj Date: Mon, 24 Sep 2001 19:02:24 +0000 Subject: [PATCH] Handle white space in b64{dec,enc}. CVS patchset: 5075 CVS date: 2001/09/24 19:02:24 --- beecrypt/base64.c | 132 ++++++++++++++++++++++++++++++++++------------- beecrypt/base64.h | 12 +++-- beecrypt/tests/openpgp.c | 122 +++++++++++++++++++++---------------------- 3 files changed, 166 insertions(+), 100 deletions(-) diff --git a/beecrypt/base64.c b/beecrypt/base64.c index 734b602..8ff800c 100644 --- a/beecrypt/base64.c +++ b/beecrypt/base64.c @@ -114,27 +114,39 @@ char* b64enc(const memchunk* chunk) #include -/*@unused@*/ int b64encode_chars_per_line = B64ENCODE_CHARS_PER_LINE; +int b64encode_chars_per_line = B64ENCODE_CHARS_PER_LINE; -/*@unused@*/ const char * b64encode_eolstr = B64ENCODE_EOLSTR; +const char * b64encode_eolstr = B64ENCODE_EOLSTR; /*@-internalglobs -modfilesys @*/ char * b64encode (const void * data, int ns) { static char b64enc[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + const char *e; const unsigned char *s = data; unsigned char *t, *te; int nt; + int lc; unsigned c; if (s == NULL) return NULL; - if (*s == '\0') return strdup(""); + if (*s == '\0') return calloc(1, sizeof(*t)); if (ns == 0) ns = strlen(s); nt = ((ns + 2) / 3) * 4; + + /* Add additional bytes necessary for eol string(s). */ + if (b64encode_chars_per_line > 0 && b64encode_eolstr != NULL) { + lc = (nt + b64encode_chars_per_line - 1) / b64encode_chars_per_line; + if (((nt + b64encode_chars_per_line - 1) % b64encode_chars_per_line) != 0) + ++lc; + nt += lc * strlen(b64encode_eolstr); + } + t = te = malloc(nt + 1); + lc = 0; if (te) while (ns) { @@ -146,24 +158,44 @@ fprintf(stderr, "%7u %02x %02x %02x -> %02x %02x %02x %02x\n", (unsigned)((s[1] & 0xf) << 2) | (s[2] >> 6), (unsigned)(s[2]& 0x3f)); c = *s++; - *te++ = b64enc[ (c >> 2) ]; - *te++ = b64enc[ ((c & 0x3) << 4) | (*s >> 4) ]; + *te++ = b64enc[ (c >> 2) ], lc++; + *te++ = b64enc[ ((c & 0x3) << 4) | (*s >> 4) ], lc++; if (--ns == 0) { *te++ = '='; *te++ = '='; continue; } c = *s++; - *te++ = b64enc[ ((c & 0xf) << 2) | (*s >> 6) ]; + *te++ = b64enc[ ((c & 0xf) << 2) | (*s >> 6) ], lc++; if (--ns == 0) { *te++ = '='; continue; } - *te++ = b64enc[ (int)(*s & 0x3f) ]; + *te++ = b64enc[ (int)(*s & 0x3f) ], lc++; + + /* Append eol string if desired. */ + if (b64encode_chars_per_line > 0 && b64encode_eolstr != NULL) { + if (lc >= b64encode_chars_per_line) { + for (e = b64encode_eolstr; *e; e++) + *te++ = *e; + lc = 0; + } + } s++; --ns; } - if (te) *te = '\0'; + + if (te) { + /* Append eol string if desired. */ + if (b64encode_chars_per_line > 0 && b64encode_eolstr != NULL) { + if (lc != 0) { + for (e = b64encode_eolstr; *e; e++) + *te++ = *e; + } + } + *te = '\0'; + } + /*@-mustfree@*/ return t; /*@=mustfree@*/ @@ -301,51 +333,79 @@ memchunk* b64dec(const char* string) } #else -/*@unused@*/ const char * b64decode_whitespace = B64DECODE_WHITESPACE; +const char * b64decode_whitespace = B64DECODE_WHITESPACE; /*@-internalglobs -modfilesys @*/ int b64decode (const char * s, void ** datap, int *lenp) { - static char b64dec[255]; - unsigned char *t, *te; + unsigned char b64dec[255]; + const unsigned char *t; + unsigned char *te; int ns, nt; unsigned a, b, c, d; if (s == NULL) return 1; - ns = strlen(s); - if (ns & 0x3) return 2; - if (b64dec[0] == '\0') { - memset(b64dec, 0x80, sizeof(b64dec)); - for (c = 'A'; c <= 'Z'; c++) - b64dec[ c ] = 0 + (c - 'A'); - for (c = 'a'; c <= 'z'; c++) - b64dec[ c ] = 26 + (c - 'a'); - for (c = '0'; c <= '9'; c++) - b64dec[ c ] = 52 + (c - '0'); - b64dec[(unsigned)'+'] = 62; - b64dec[(unsigned)'/'] = 63; - b64dec[(unsigned)'='] = 0; + /* Setup character lookup tables. */ + memset(b64dec, 0x80, sizeof(b64dec)); + for (c = 'A'; c <= 'Z'; c++) + b64dec[ c ] = 0 + (c - 'A'); + for (c = 'a'; c <= 'z'; c++) + b64dec[ c ] = 26 + (c - 'a'); + for (c = '0'; c <= '9'; c++) + b64dec[ c ] = 52 + (c - '0'); + b64dec[(unsigned)'+'] = 62; + b64dec[(unsigned)'/'] = 63; + b64dec[(unsigned)'='] = 0; + + /* Mark whitespace characters. */ + if (b64decode_whitespace) { + const char *e; + for (e = b64decode_whitespace; *e; e++) { + if (b64dec[ (unsigned)*e ] == 0x80) + b64dec[ (unsigned)*e ] = 0x81; + } } + /* Validate input buffer */ + ns = 0; + for (t = s; *t; t++) { + switch (b64dec[ (unsigned)*t ]) { + case 0x80: /* invalid chararcter */ + return 3; + /*@notreached@*/ /*@switchbreak@*/ break; + case 0x81: /* white space */ + /*@switchbreak@*/ break; + default: + ns++; + /*@switchbreak@*/ break; + } + } + + if (ns & 0x3) return 2; + nt = (ns / 4) * 3; t = te = malloc(nt + 1); while (ns > 0) { - if ((a = b64dec[ (unsigned)*s++ ]) == 0x80) - break; - if ((b = b64dec[ (unsigned)*s++ ]) == 0x80) - break; - if ((c = b64dec[ (unsigned)*s++ ]) == 0x80) - break; - if ((d = b64dec[ (unsigned)*s++ ]) == 0x80) - break; + + /* Get next 4 characters, ignoring whitespace. */ + while ((a = b64dec[ (unsigned)*s++ ]) == 0x81) + {}; + while ((b = b64dec[ (unsigned)*s++ ]) == 0x81) + {}; + while ((c = b64dec[ (unsigned)*s++ ]) == 0x81) + {}; + while ((d = b64dec[ (unsigned)*s++ ]) == 0x81) + {}; + if (_debug) fprintf(stderr, "%7u %02x %02x %02x %02x -> %02x %02x %02x\n", (unsigned)ns, a, b, c, d, (((a << 2) | (b >> 4)) & 0xff), (((b << 4) | (c >> 2)) & 0xff), (((c << 6) | d) & 0xff)); + ns -= 4; *te++ = (a << 2) | (b >> 4); if (s[-2] == '=') break; @@ -354,17 +414,17 @@ fprintf(stderr, "%7u %02x %02x %02x %02x -> %02x %02x %02x\n", *te++ = (c << 6) | d; } - if (ns > 0) { - if (t) free(t); + if (ns != 0) { /* XXX can't happen, just in case */ + if (t) free((void *)t); return 3; } if (lenp) *lenp = (te - t); if (datap) - *datap = t; + *datap = (void *)t; else - if (t) free(t); + if (t) free((void *)t); else {}; diff --git a/beecrypt/base64.h b/beecrypt/base64.h index 1b31915..cefd341 100644 --- a/beecrypt/base64.h +++ b/beecrypt/base64.h @@ -33,21 +33,27 @@ /** * Decode white space character set (default). */ -/*@observer@*/ +/*@-exportlocal@*/ +/*@observer@*/ /*@null@*/ extern const char * b64decode_whitespace; +/*@=exportlocal@*/ #define B64DECODE_WHITESPACE " \f\n\r\t\v" /** * Encode 72 characters per line (default). */ +/*@-exportlocal@*/ extern int b64encode_chars_per_line; +/*@=exportlocal@*/ #define B64ENCODE_CHARS_PER_LINE 72 /** * Encode end-of-line string (default). */ -/*@observer@*/ +/*@-exportlocal@*/ +/*@observer@*/ /*@null@*/ extern const char * b64encode_eolstr; +/*@=exportlocal@*/ #define B64ENCODE_EOLSTR "\n" #ifdef __cplusplus @@ -84,7 +90,7 @@ memchunk* b64dec(const char* string) * @param s base64 string * @retval datap address of (malloc'd) binary data * @retval lenp address of no. bytes of binary data - * @return 0 on success + * @return 0 on success, 1: s == NULL, 2: bad length, 3: bad char */ BEEDLLAPI /*@unused@*/ int b64decode (const char * s, /*@out@*/ void ** datap, /*@out@*/ int *lenp) diff --git a/beecrypt/tests/openpgp.c b/beecrypt/tests/openpgp.c index d564871..5ee992c 100644 --- a/beecrypt/tests/openpgp.c +++ b/beecrypt/tests/openpgp.c @@ -625,71 +625,71 @@ static int pr_keypkt(const byte *p) /* This is the unarmored RPM-GPG-KEY public key. */ const char * gpgsig = "\ -mQGiBDfqVDgRBADBKr3Bl6PO8BQ0H8sJoD6p9U7Yyl7pjtZqioviPwXP+DCWd4u8\ -HQzcxAZ57m8ssA1LK1Fx93coJhDzM130+p5BG9mYSWShLabR3N1KXdXQYYcowTOM\ -GxdwYRGr1Spw8QydLhjVfU1VSl4xt6bupPbWJbyjkg5Z3P7BlUOUJmrx3wCgobNV\ -EDGaWYJcch5z5B1of/41G8kEAKii6q7Gu/vhXXnLS6m15oNnPVybyngiw/23dKjS\ -ZVG7rKANEK2mxg1VB+vc/uUc4k49UxJJfCZg1gu1sPFV3GSa+Y/7jsiLktQvCiLP\ -lncQt1dV+ENmHR5BdIDPWDzKBVbgWnSDnqQ6KrZ7T6AlZ74VMpjGxxkWU6vV2xsW\ -XCLPA/9P/vtImA8CZN3jxGgtK5GGtDNJ/cMhhuv5tnfwFg4b/VGo2Jr8mhLUqoIb\ -E6zeGAmZbUpdckDco8D5fiFmqTf5+++pCEpJLJkkzel/32N2w4qzPrcRMCiBURES\ -PjCLd4Y5rPoU8E4kOHc/4BuHN903tiCsCPloCrWsQZ7UdxfQ5LQiUmVkIEhhdCwg\ -SW5jIDxzZWN1cml0eUByZWRoYXQuY29tPohVBBMRAgAVBQI36lQ4AwsKAwMVAwID\ -FgIBAheAAAoJECGRgM3bQqYOsBQAnRVtg7B25Hm11PHcpa8FpeddKiq2AJ9aO8sB\ -XmLDmPOEFI75mpTrKYHF6rkCDQQ36lRyEAgAokgI2xJ+3bZsk8jRA8ORIX8DH05U\ -lMH27qFYzLbT6npXwXYIOtVn0K2/iMDj+oEB1Aa2au4OnddYaLWp06v3d+XyS0t+\ -5ab2ZfIQzdh7wCwxqRkzR+/H5TLYbMG+hvtTdylfqIX0WEfoOXMtWEGSVwyUsnM3\ -Jy3LOi48rQQSCKtCAUdV20FoIGWhwnb/gHU1BnmES6UdQujFBE6EANqPhp0coYoI\ -hHJ2oIO8ujQItvvNaU88j/s/izQv5e7MXOgVSjKe/WX3s2JtB/tW7utpy12wh1J+\ -JsFdbLV/t8CozUTpJgx5mVA3RKlxjTA+On+1IEUWioB+iVfT7Ov/0kcAzwADBQf9\ -E4SKCWRand8K0XloMYgmipxMhJNnWDMLkokvbMNTUoNpSfRoQJ9EheXDxwMpTPwK\ -ti/PYrrL2J11P2ed0x7zm8v3gLrY0cue1iSba+8glY+p31ZPOr5ogaJw7ZARgoS8\ -BwjyRymXQp+8Dete0TELKOL2/itDOPGHW07SsVWOR6cmX4VlRRcWB5KejaNvdrE5\ -4XFtOd04NMgWI63uqZc4zkRa+kwEZtmbz3tHSdRCCE+Y7YVP6IUf/w6YPQFQriWY\ -FiA6fD10eB+BlIUqIw80VgjsBKmCwvKkn4jg8kibXgj4/TzQSx77uYokw1EqQ2wk\ -OZoaEtcubsNMquuLCMWijYhGBBgRAgAGBQI36lRyAAoJECGRgM3bQqYOhyYAnj7h\ -VDY/FJAGqmtZpwVp9IlitW5tAJ4xQApr/jNFZCTksnI+4O1765F7tA==\ +mQGiBDfqVDgRBADBKr3Bl6PO8BQ0H8sJoD6p9U7Yyl7pjtZqioviPwXP+DCWd4u8\n\ +HQzcxAZ57m8ssA1LK1Fx93coJhDzM130+p5BG9mYSWShLabR3N1KXdXQYYcowTOM\n\ +GxdwYRGr1Spw8QydLhjVfU1VSl4xt6bupPbWJbyjkg5Z3P7BlUOUJmrx3wCgobNV\n\ +EDGaWYJcch5z5B1of/41G8kEAKii6q7Gu/vhXXnLS6m15oNnPVybyngiw/23dKjS\n\ +ZVG7rKANEK2mxg1VB+vc/uUc4k49UxJJfCZg1gu1sPFV3GSa+Y/7jsiLktQvCiLP\n\ +lncQt1dV+ENmHR5BdIDPWDzKBVbgWnSDnqQ6KrZ7T6AlZ74VMpjGxxkWU6vV2xsW\n\ +XCLPA/9P/vtImA8CZN3jxGgtK5GGtDNJ/cMhhuv5tnfwFg4b/VGo2Jr8mhLUqoIb\n\ +E6zeGAmZbUpdckDco8D5fiFmqTf5+++pCEpJLJkkzel/32N2w4qzPrcRMCiBURES\n\ +PjCLd4Y5rPoU8E4kOHc/4BuHN903tiCsCPloCrWsQZ7UdxfQ5LQiUmVkIEhhdCwg\n\ +SW5jIDxzZWN1cml0eUByZWRoYXQuY29tPohVBBMRAgAVBQI36lQ4AwsKAwMVAwID\n\ +FgIBAheAAAoJECGRgM3bQqYOsBQAnRVtg7B25Hm11PHcpa8FpeddKiq2AJ9aO8sB\n\ +XmLDmPOEFI75mpTrKYHF6rkCDQQ36lRyEAgAokgI2xJ+3bZsk8jRA8ORIX8DH05U\n\ +lMH27qFYzLbT6npXwXYIOtVn0K2/iMDj+oEB1Aa2au4OnddYaLWp06v3d+XyS0t+\n\ +5ab2ZfIQzdh7wCwxqRkzR+/H5TLYbMG+hvtTdylfqIX0WEfoOXMtWEGSVwyUsnM3\n\ +Jy3LOi48rQQSCKtCAUdV20FoIGWhwnb/gHU1BnmES6UdQujFBE6EANqPhp0coYoI\n\ +hHJ2oIO8ujQItvvNaU88j/s/izQv5e7MXOgVSjKe/WX3s2JtB/tW7utpy12wh1J+\n\ +JsFdbLV/t8CozUTpJgx5mVA3RKlxjTA+On+1IEUWioB+iVfT7Ov/0kcAzwADBQf9\n\ +E4SKCWRand8K0XloMYgmipxMhJNnWDMLkokvbMNTUoNpSfRoQJ9EheXDxwMpTPwK\n\ +ti/PYrrL2J11P2ed0x7zm8v3gLrY0cue1iSba+8glY+p31ZPOr5ogaJw7ZARgoS8\n\ +BwjyRymXQp+8Dete0TELKOL2/itDOPGHW07SsVWOR6cmX4VlRRcWB5KejaNvdrE5\n\ +4XFtOd04NMgWI63uqZc4zkRa+kwEZtmbz3tHSdRCCE+Y7YVP6IUf/w6YPQFQriWY\n\ +FiA6fD10eB+BlIUqIw80VgjsBKmCwvKkn4jg8kibXgj4/TzQSx77uYokw1EqQ2wk\n\ +OZoaEtcubsNMquuLCMWijYhGBBgRAgAGBQI36lRyAAoJECGRgM3bQqYOhyYAnj7h\n\ +VDY/FJAGqmtZpwVp9IlitW5tAJ4xQApr/jNFZCTksnI+4O1765F7tA==\n\ "; /* This is the unarmored RPM-PGP-KEY public key. */ const char * pgpsig = "\ -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\ -z15FuA==\ +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\n\ +z15FuA==\n\ "; int -- 2.7.4