summaryrefslogtreecommitdiff
path: root/beecrypt
diff options
context:
space:
mode:
authorjbj <devnull@localhost>2001-09-24 19:02:24 +0000
committerjbj <devnull@localhost>2001-09-24 19:02:24 +0000
commit9db80726185159ff58598c6be52ca192602323c7 (patch)
treea8a82cc60fdcf9058b53845707a62c7671cb5b8f /beecrypt
parent3e3ac9b75fadfd6e79bb7463af51ba94349eafca (diff)
downloadrpm-9db80726185159ff58598c6be52ca192602323c7.tar.gz
rpm-9db80726185159ff58598c6be52ca192602323c7.tar.bz2
rpm-9db80726185159ff58598c6be52ca192602323c7.zip
Handle white space in b64{dec,enc}.
CVS patchset: 5075 CVS date: 2001/09/24 19:02:24
Diffstat (limited to 'beecrypt')
-rw-r--r--beecrypt/base64.c132
-rw-r--r--beecrypt/base64.h12
-rw-r--r--beecrypt/tests/openpgp.c122
3 files changed, 166 insertions, 100 deletions
diff --git a/beecrypt/base64.c b/beecrypt/base64.c
index 734b602b6..8ff800c12 100644
--- a/beecrypt/base64.c
+++ b/beecrypt/base64.c
@@ -114,27 +114,39 @@ char* b64enc(const memchunk* chunk)
#include <stdio.h>
-/*@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 1b319156f..cefd34149 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 d5648716e..5ee992c75 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 = "\
-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\
+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\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