diff -ru beecrypt/base64.c beecrypt.rpm/base64.c --- beecrypt/base64.c Thu May 15 15:35:52 2003 +++ beecrypt.rpm/base64.c Fri May 16 16:16:40 2003 @@ -63,10 +55,10 @@ while (div > 0) { - buf[0] = to_b64[ (data[0] >> 2) & 0x3f]; - buf[1] = to_b64[((data[0] << 4) & 0x30) | ((data[1] >> 4) & 0xf)]; - buf[2] = to_b64[((data[1] << 2) & 0x3c) | ((data[2] >> 6) & 0x3)]; - buf[3] = to_b64[ data[2] & 0x3f]; + buf[0] = to_b64[ ((unsigned)data[0] >> 2) & 0x3f]; + buf[1] = to_b64[(((unsigned)data[0] << 4) & 0x30) | (((unsigned)data[1] >> 4) & 0xf)]; + buf[2] = to_b64[(((unsigned)data[1] << 2) & 0x3c) | (((unsigned)data[2] >> 6) & 0x3)]; + buf[3] = to_b64[ (unsigned)data[2] & 0x3f]; data += 3; buf += 4; div--; @@ -81,16 +73,16 @@ switch (rem) { case 2: - buf[0] = to_b64[ (data[0] >> 2) & 0x3f]; - buf[1] = to_b64[((data[0] << 4) & 0x30) + ((data[1] >> 4) & 0xf)]; - buf[2] = to_b64[ (data[1] << 2) & 0x3c]; + buf[0] = to_b64[ ((unsigned)data[0] >> 2) & 0x3f]; + buf[1] = to_b64[(((unsigned)data[0] << 4) & 0x30) + (((unsigned)data[1] >> 4) & 0xf)]; + buf[2] = to_b64[ ((unsigned)data[1] << 2) & 0x3c]; buf[3] = '='; buf += 4; chars += 4; break; case 1: - buf[0] = to_b64[ (data[0] >> 2) & 0x3f]; - buf[1] = to_b64[ (data[0] << 4) & 0x30]; + buf[0] = to_b64[ ((unsigned)data[0] >> 2) & 0x3f]; + buf[1] = to_b64[ ((unsigned)data[0] << 4) & 0x30]; buf[2] = '='; buf[3] = '='; buf += 4; @@ -183,6 +177,7 @@ if (isspace(ch)) continue; + bits = 0; if ((ch >= 'A') && (ch <= 'Z')) { bits = (byte) (ch - 'A'); @@ -237,3 +232,222 @@ return rc; } + +int b64encode_chars_per_line = B64ENCODE_CHARS_PER_LINE; + +const char * b64encode_eolstr = B64ENCODE_EOLSTR; + +/*@-internalglobs -modfilesys @*/ +char * b64encode (const void * data, size_t 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 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 > 0) { + +if (0) +fprintf(stderr, "%7u %02x %02x %02x -> %02x %02x %02x %02x\n", +(unsigned)ns, (unsigned)s[0], (unsigned)s[1], (unsigned)s[2], +(unsigned)(s[0] >> 2), +(unsigned)((s[0] & 0x3) << 4) | (s[1] >> 4), +(unsigned)((s[1] & 0xf) << 2) | (s[2] >> 6), +(unsigned)(s[2]& 0x3f)); + c = *s++; + *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) ], lc++; + if (--ns == 0) { + *te++ = '='; + continue; + } + *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 != '\0'; e++) + *te++ = *e; + lc = 0; + } + } + s++; + --ns; + } + + if (te) { + /* Append eol string if desired. */ + if (b64encode_chars_per_line > 0 && b64encode_eolstr != NULL) { + if (lc != 0) { + for (e = b64encode_eolstr; *e != '\0'; e++) + *te++ = *e; + } + } + *te = '\0'; + } + + /*@-mustfree -compdef @*/ + return t; + /*@=mustfree =compdef @*/ +} +/*@=globs =internalglobs =modfilesys @*/ + +/*@-internalglobs -modfilesys @*/ +#define CRC24_INIT 0xb704ceL +#define CRC24_POLY 0x1864cfbL + +char * b64crc (const unsigned char * data, size_t ns) +{ + const unsigned char *s = data; + uint32_t crc = CRC24_INIT; + + while (ns-- > 0) { + int i; + crc ^= (*s++) << 16; + for (i = 0; i < 8; i++) { + crc <<= 1; + if (crc & 0x1000000) + crc ^= CRC24_POLY; + } + } + crc &= 0xffffff; + /*@-unrecog@*/ /* FIX: include endianness.h? */ + #if !WORDS_BIGENDIAN + crc = swapu32(crc); + #endif + /*@=unrecog@*/ + data = (byte *)&crc; + data++; + ns = 3; + return b64encode(data, ns); +} +/*@=internalglobs =modfilesys @*/ + +const char * b64decode_whitespace = B64DECODE_WHITESPACE; + +/*@-internalglobs -modfilesys @*/ +int b64decode (const char * s, void ** datap, size_t *lenp) +{ + unsigned char b64dec[256]; + const unsigned char *t; + unsigned char *te; + int ns, nt; + unsigned a, b, c, d; + + if (s == NULL) return 1; + + /* 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 != '\0'; e++) { + if (b64dec[ (unsigned)*e ] == 0x80) + b64dec[ (unsigned)*e ] = 0x81; + } + } + + /* Validate input buffer */ + ns = 0; + for (t = s; *t != '\0'; t++) { + switch (b64dec[ (unsigned)*t ]) { + case 0x80: /* invalid chararcter */ +if (0) +fprintf(stderr, "--- b64decode %c(%02x) %02x\n", *t, (unsigned)(*t & 0xff), (unsigned)b64dec[ (unsigned)*t ]); + return 3; + /*@notreached@*/ /*@switchbreak@*/ break; + case 0x81: /* white space */ + /*@switchbreak@*/ break; + default: + ns++; + /*@switchbreak@*/ break; + } + } + + if (((unsigned)ns) & 0x3) return 2; + + nt = (ns / 4) * 3; + t = te = malloc(nt + 1); + + while (ns > 0) { + + /* 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 (0) +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; + *te++ = (b << 4) | (c >> 2); + if (s[-1] == '=') break; + *te++ = (c << 6) | d; + } + + if (ns != 0) { /* XXX can't happen, just in case */ + if (t) free((void *)t); + return 1; + } + if (lenp) + *lenp = (te - t); + + if (datap) + *datap = (void *)t; + else + if (t) free((void *)t); + + return 0; +} +/*@=globs =internalglobs =modfilesys @*/ +/*@=type@*/ diff -ru beecrypt/base64.h beecrypt.rpm/base64.h --- beecrypt/base64.h Fri Jun 21 14:17:24 2002 +++ beecrypt.rpm/base64.h Fri May 16 16:16:40 2003 @@ -27,13 +27,76 @@ #include "beecrypt.h" +/** + * Decode white space character set (default). + */ +/*@-exportlocal@*/ +/*@unchecked@*/ /*@observer@*/ /*@null@*/ +extern const char * b64decode_whitespace; +/*@=exportlocal@*/ +#define B64DECODE_WHITESPACE " \f\n\r\t\v" + +/** + * Encode 72 characters per line (default). + */ +/*@-exportlocal@*/ +/*@unchecked@*/ +extern int b64encode_chars_per_line; +/*@=exportlocal@*/ +#define B64ENCODE_CHARS_PER_LINE 72 + +/** + * Encode end-of-line string (default). + */ +/*@-exportlocal@*/ +/*@unchecked@*/ /*@observer@*/ /*@null@*/ +extern const char * b64encode_eolstr; +/*@=exportlocal@*/ +#define B64ENCODE_EOLSTR "\n" + #ifdef __cplusplus extern "C" { #endif -BEECRYPTAPI +/** + * Encode chunks of 3 bytes of binary input into 4 bytes of base64 output. + * @param data binary data + * @param ns no. bytes of data (0 uses strlen(data)) + * @return (malloc'd) base64 string + */ +BEECRYPTAPI /*@only@*/ /*@null@*/ /*@unused@*/ +char * b64encode (const void * data, size_t ns) + /*@*/; + +/** + * Encode crc of binary input data into 5 bytes of base64 output. + * @param data binary data + * @param ns no. bytes of binary data + * @return (malloc'd) base64 string + */ +BEECRYPTAPI /*@only@*/ /*@null@*/ /*@unused@*/ +char * b64crc (const unsigned char * data, size_t ns) + /*@*/; + +/** + * Decode chunks of 4 bytes of base64 input into 3 bytes of binary output. + * @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, 1: s == NULL, 2: bad length, 3: bad char + */ +BEECRYPTAPI /*@unused@*/ +int b64decode (const char * s, /*@out@*/ void ** datap, /*@out@*/ size_t *lenp) + /*@modifies *datap, *lenp @*/; + +/** + */ +BEECRYPTAPI /*@only@*/ /*@null@*/ /*@unused@*/ char* b64enc(const memchunk*); -BEECRYPTAPI + +/** + */ +BEECRYPTAPI /*@only@*/ /*@null@*/ /*@unused@*/ memchunk* b64dec(const char*); #ifdef __cplusplus