libalpm
Arch Linux Package Manager Library
base64.c
Go to the documentation of this file.
00001 /*
00002  *  RFC 1521 base64 encoding/decoding
00003  *
00004  *  Copyright (C) 2006-2010, Brainspark B.V.
00005  *
00006  *  This file is part of PolarSSL (http://www.polarssl.org)
00007  *  Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
00008  *
00009  *  All rights reserved.
00010  *
00011  *  This program is free software; you can redistribute it and/or modify
00012  *  it under the terms of the GNU General Public License as published by
00013  *  the Free Software Foundation; either version 2 of the License, or
00014  *  (at your option) any later version.
00015  *
00016  *  This program is distributed in the hope that it will be useful,
00017  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00018  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00019  *  GNU General Public License for more details.
00020  *
00021  *  You should have received a copy of the GNU General Public License
00022  *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
00023  */
00024 /*
00025  *  Pacman Notes:
00026  *
00027  *  Taken from the PolarSSL project at www.polarssl.org under terms of the
00028  *  GPL. This is from version 0.14.2 of the library, and has been modified
00029  *  as following, which may be helpful for future updates:
00030  *  * remove "polarssl/config.h" include
00031  *  * change include from "polarssl/base64.h" to "base64.h"
00032  *  * removal of SELF_TEST code
00033  */
00034 
00035 #include <stdint.h>
00036 
00037 #include "base64.h"
00038 
00039 static const unsigned char base64_enc_map[64] =
00040 {
00041     'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J',
00042     'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T',
00043     'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd',
00044     'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
00045     'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x',
00046     'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7',
00047     '8', '9', '+', '/'
00048 };
00049 
00050 static const unsigned char base64_dec_map[128] =
00051 {
00052     127, 127, 127, 127, 127, 127, 127, 127, 127, 127,
00053     127, 127, 127, 127, 127, 127, 127, 127, 127, 127,
00054     127, 127, 127, 127, 127, 127, 127, 127, 127, 127,
00055     127, 127, 127, 127, 127, 127, 127, 127, 127, 127,
00056     127, 127, 127,  62, 127, 127, 127,  63,  52,  53,
00057      54,  55,  56,  57,  58,  59,  60,  61, 127, 127,
00058     127,  64, 127, 127, 127,   0,   1,   2,   3,   4,
00059       5,   6,   7,   8,   9,  10,  11,  12,  13,  14,
00060      15,  16,  17,  18,  19,  20,  21,  22,  23,  24,
00061      25, 127, 127, 127, 127, 127, 127,  26,  27,  28,
00062      29,  30,  31,  32,  33,  34,  35,  36,  37,  38,
00063      39,  40,  41,  42,  43,  44,  45,  46,  47,  48,
00064      49,  50,  51, 127, 127, 127, 127, 127
00065 };
00066 
00067 #if 0
00068 /*
00069  * Encode a buffer into base64 format
00070  */
00071 int base64_encode( unsigned char *dst, size_t *dlen,
00072                    const unsigned char *src, size_t slen )
00073 {
00074     size_t i, n;
00075     int C1, C2, C3;
00076     unsigned char *p;
00077 
00078     if( slen == 0 )
00079         return( 0 );
00080 
00081     n = (slen << 3) / 6;
00082 
00083     switch( (slen << 3) - (n * 6) )
00084     {
00085         case  2: n += 3; break;
00086         case  4: n += 2; break;
00087         default: break;
00088     }
00089 
00090     if( *dlen < n + 1 )
00091     {
00092         *dlen = n + 1;
00093         return( POLARSSL_ERR_BASE64_BUFFER_TOO_SMALL );
00094     }
00095 
00096     n = (slen / 3) * 3;
00097 
00098     for( i = 0, p = dst; i < n; i += 3 )
00099     {
00100         C1 = *src++;
00101         C2 = *src++;
00102         C3 = *src++;
00103 
00104         *p++ = base64_enc_map[(C1 >> 2) & 0x3F];
00105         *p++ = base64_enc_map[(((C1 &  3) << 4) + (C2 >> 4)) & 0x3F];
00106         *p++ = base64_enc_map[(((C2 & 15) << 2) + (C3 >> 6)) & 0x3F];
00107         *p++ = base64_enc_map[C3 & 0x3F];
00108     }
00109 
00110     if( i < slen )
00111     {
00112         C1 = *src++;
00113         C2 = ((i + 1) < slen) ? *src++ : 0;
00114 
00115         *p++ = base64_enc_map[(C1 >> 2) & 0x3F];
00116         *p++ = base64_enc_map[(((C1 & 3) << 4) + (C2 >> 4)) & 0x3F];
00117 
00118         if( (i + 1) < slen )
00119              *p++ = base64_enc_map[((C2 & 15) << 2) & 0x3F];
00120         else *p++ = '=';
00121 
00122         *p++ = '=';
00123     }
00124 
00125     *dlen = p - dst;
00126     *p = 0;
00127 
00128     return( 0 );
00129 }
00130 #endif
00131 
00132 /*
00133  * Decode a base64-formatted buffer
00134  */
00135 int base64_decode( unsigned char *dst, size_t *dlen,
00136                    const unsigned char *src, size_t slen )
00137 {
00138     size_t i, n;
00139     uint32_t j, x;
00140     unsigned char *p;
00141 
00142     for( i = j = n = 0; i < slen; i++ )
00143     {
00144         if( ( slen - i ) >= 2 &&
00145             src[i] == '\r' && src[i + 1] == '\n' )
00146             continue;
00147 
00148         if( src[i] == '\n' )
00149             continue;
00150 
00151         if( src[i] == '=' && ++j > 2 )
00152             return( POLARSSL_ERR_BASE64_INVALID_CHARACTER );
00153 
00154         if( src[i] > 127 || base64_dec_map[src[i]] == 127 )
00155             return( POLARSSL_ERR_BASE64_INVALID_CHARACTER );
00156 
00157         if( base64_dec_map[src[i]] < 64 && j != 0 )
00158             return( POLARSSL_ERR_BASE64_INVALID_CHARACTER );
00159 
00160         n++;
00161     }
00162 
00163     if( n == 0 )
00164         return( 0 );
00165 
00166     n = ((n * 6) + 7) >> 3;
00167 
00168     if( *dlen < n )
00169     {
00170         *dlen = n;
00171         return( POLARSSL_ERR_BASE64_BUFFER_TOO_SMALL );
00172     }
00173 
00174    for( j = 3, n = x = 0, p = dst; i > 0; i--, src++ )
00175    {
00176         if( *src == '\r' || *src == '\n' )
00177             continue;
00178 
00179         j -= ( base64_dec_map[*src] == 64 );
00180         x  = (x << 6) | ( base64_dec_map[*src] & 0x3F );
00181 
00182         if( ++n == 4 )
00183         {
00184             n = 0;
00185             if( j > 0 ) *p++ = (unsigned char)( x >> 16 );
00186             if( j > 1 ) *p++ = (unsigned char)( x >>  8 );
00187             if( j > 2 ) *p++ = (unsigned char)( x       );
00188         }
00189     }
00190 
00191     *dlen = p - dst;
00192 
00193     return( 0 );
00194 }