Back to index

opendkim  2.6.6
base64.c
Go to the documentation of this file.
00001 /*
00002 **  Copyright (c) 2005, 2008 Sendmail, Inc. and its suppliers.
00003 **    All rights reserved.
00004 **
00005 **  Copyright (c) 2009, The OpenDKIM Project.  All rights reserved.
00006 */
00007 
00008 #ifndef lint
00009 static char base64_c_id[] = "@(#)$Id: base64.c,v 1.2 2009/07/23 17:40:23 cm-msk Exp $";
00010 #endif /* !lint */
00011 
00012 /* system includes */
00013 #include <sys/types.h>
00014 #include <assert.h>
00015 
00016 /* libopendkim includes */
00017 #include "base64.h"
00018 
00019 /* base64 alphabet */
00020 static unsigned char alphabet[64] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
00021 
00022 /* base64 decode stuff */
00023 static int decoder[256] =
00024 {
00025        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00026        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00027        0, 62, 0, 0, 0, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 0,
00028        0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13,
00029        14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 0, 0, 0, 0, 0,
00030        0, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
00031        41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 0, 0, 0, 0, 0, 0, 0,
00032        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00033        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00034        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00035        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00036        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
00037        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
00038 };
00039 
00040 #ifndef NULL
00041 # define NULL 0
00042 #endif /* ! NULL */
00043 
00044 /*
00045 **  DKIM_BASE64_DECODE -- decode a base64 blob
00046 **
00047 **  Parameters:
00048 **     str -- string to decide
00049 **     buf -- where to write it
00050 **     buflen -- bytes available at "buf"
00051 **
00052 **  Return value:
00053 **     >= 0 -- success; length of what was decoded is returned
00054 **     -1 -- corrupt
00055 **     -2 -- not enough space at "buf"
00056 */
00057 
00058 int
00059 dkim_base64_decode(u_char *str, u_char *buf, size_t buflen)
00060 {
00061        int n = 0;
00062        int bits = 0;
00063        int char_count = 0;
00064        u_char *c;
00065 
00066        assert(str != NULL);
00067        assert(buf != NULL);
00068 
00069        for (c = str; *c != '=' && *c != '\0'; c++)
00070        {
00071               /* end padding */
00072               if (*c == '=' || *c == '\0')
00073                      break;
00074 
00075               /* skip stuff not part of the base64 alphabet (RFC2045) */
00076               if (!((*c >= 'A' && *c <= 'Z') ||
00077                     (*c >= 'a' && *c <= 'z') ||
00078                     (*c >= '0' && *c <= '9') ||
00079                     (*c == '+') ||
00080                     (*c == '/')))
00081                      continue;
00082 
00083               /* everything else gets decoded */
00084               bits += decoder[(int) *c];
00085               char_count++;
00086               if (n + 3 > buflen)
00087                      return -2;
00088               if (char_count == 4)
00089               {
00090                      buf[n++] = (bits >> 16);
00091                      buf[n++] = ((bits >> 8) & 0xff);
00092                      buf[n++] = (bits & 0xff);
00093                      bits = 0;
00094                      char_count = 0;
00095               }
00096               else
00097               {
00098                      bits <<= 6;
00099               }
00100        }
00101 
00102        /* XXX -- don't bother checking for proper termination (for now) */
00103 
00104        /* process trailing data, if any */
00105        switch (char_count)
00106        {
00107          case 0:
00108               break;
00109 
00110          case 1:
00111               /* base64 decoding incomplete; at least two bits missing */
00112               return -1;
00113 
00114          case 2:
00115               if (n + 1 > buflen)
00116                      return -2;
00117               buf[n++] = (bits >> 10);
00118               break;
00119 
00120          case 3:
00121               if (n + 2 > buflen)
00122                      return -2;
00123               buf[n++] = (bits >> 16);
00124               buf[n++] = ((bits >> 8) & 0xff);
00125               break;
00126        }
00127 
00128        return n;
00129 }
00130 
00131 /*
00132 **  DKIM_BASE64_ENCODE -- encode base64 data
00133 **
00134 **  Parameters:
00135 **     data -- data to encode
00136 **     datalen -- bytes at "data" to encode
00137 **     buf -- where to write the encoding
00138 **     buflen -- bytes available at "buf"
00139 **
00140 **  Return value:
00141 **     >= 0 -- success; number of bytes written to "buf" returned
00142 **     -1 -- failure (not enough space at "buf")
00143 */
00144 
00145 int
00146 dkim_base64_encode(u_char *data, size_t datalen, u_char *buf, size_t buflen)
00147 {
00148        int bits;
00149        int c;
00150        int char_count;
00151        size_t n;
00152 
00153        assert(data != NULL);
00154        assert(buf != NULL);
00155 
00156        bits = 0;
00157        char_count = 0;
00158        n = 0;
00159 
00160        for (c = 0; c < datalen; c++)
00161        {
00162               bits += data[c];
00163               char_count++;
00164               if (char_count == 3)
00165               {
00166                      if (n + 4 > buflen)
00167                             return -1;
00168 
00169                      buf[n++] = alphabet[bits >> 18];
00170                      buf[n++] = alphabet[(bits >> 12) & 0x3f];
00171                      buf[n++] = alphabet[(bits >> 6) & 0x3f];
00172                      buf[n++] = alphabet[bits & 0x3f];
00173                      bits = 0;
00174                      char_count = 0;
00175               }
00176               else
00177               {
00178                      bits <<= 8;
00179               }
00180        }
00181 
00182        if (char_count != 0)
00183        {
00184               if (n + 4 > buflen)
00185                      return -1;
00186 
00187               bits <<= 16 - (8 * char_count);
00188               buf[n++] = alphabet[bits >> 18];
00189               buf[n++] = alphabet[(bits >> 12) & 0x3f];
00190               if (char_count == 1)
00191               {
00192                      buf[n++] = '=';
00193                      buf[n++] = '=';
00194               }
00195               else
00196               {
00197                      buf[n++] = alphabet[(bits >> 6) & 0x3f];
00198                      buf[n++] = '=';
00199               }
00200        }
00201 
00202        return n;
00203 }