]> git.cryptolib.org Git - avr-crypto-lib.git/blob - base64/base64_enc.c
187e002279caf15a2228a8bd73e9a855b149732a
[avr-crypto-lib.git] / base64 / base64_enc.c
1 /* base64_enc.c */
2 /*
3  *   This file is part of the AVR-Crypto-Lib.
4  *   Copyright (C) 2006, 2007, 2008  Daniel Otte (daniel.otte@rub.de)
5  *
6  *   This program is free software: you can redistribute it and/or modify
7  *   it under the terms of the GNU General Public License as published by
8  *   the Free Software Foundation, either version 3 of the License, or
9  *   (at your option) any later version.
10  *
11  *   This program is distributed in the hope that it will be useful,
12  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  *   GNU General Public License for more details.
15  *
16  *   You should have received a copy of the GNU General Public License
17  *   along with this program.  If not, see <http://www.gnu.org/licenses/>.
18  */
19
20 /**
21  * base64 encoder (RFC3548)
22  * Author: Daniel Otte
23  * License: GPLv3
24  * 
25  * 
26  */
27
28 #include <stdint.h>
29 #include "base64_enc.h"
30
31 #if 1
32 #include <avr/pgmspace.h>
33
34 const char base64_alphabet[64] PROGMEM = {
35         'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
36         'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
37         'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X',
38         'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',
39         'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
40         'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
41         'w', 'x', 'y', 'z', '0', '1', '2', '3',
42         '4', '5', '6', '7', '8', '9', '+', '/' };
43
44 static
45 char bit6toAscii(uint8_t a)
46 {
47     a &= (uint8_t) 0x3F;
48     return pgm_read_byte(base64_alphabet + a);
49 }
50
51 #else
52
53 static
54 char bit6toAscii(uint8_t a) {
55     a &= (uint8_t)0x3F;
56
57     if(a<=25) {
58         return a+'A';
59     } else {
60         if(a<=51) {
61             return a-26+'a';
62         } else {
63             if(a<=61) {
64                 return a-52+'0';
65             } else {
66                 if(a==62) {
67                     return '+';
68                 } else {
69                     return '/'; /* a == 63 */
70                 }
71             }
72         }
73     }
74 }
75
76 #endif
77
78 void base64enc(char *dest, const void *src, uint16_t length)
79 {
80     uint16_t i, j;
81     uint8_t a[4];
82     for (i = 0; i < length / 3; ++i) {
83         a[0] = (((uint8_t*) src)[i * 3 + 0]) >> 2;
84         a[1] = (((((uint8_t*) src)[i * 3 + 0]) << 4)
85                 | ((((uint8_t*) src)[i * 3 + 1]) >> 4)) & 0x3F;
86         a[2] = (((((uint8_t*) src)[i * 3 + 1]) << 2)
87                 | ((((uint8_t*) src)[i * 3 + 2]) >> 6)) & 0x3F;
88         a[3] = (((uint8_t*) src)[i * 3 + 2]) & 0x3F;
89         for (j = 0; j < 4; ++j) {
90             *dest++ = bit6toAscii(a[j]);
91         }
92     }
93     /* now we do the rest */
94     switch (length % 3) {
95     case 0:
96         break;
97     case 1:
98         a[0] = (((uint8_t*) src)[i * 3 + 0]) >> 2;
99         a[1] = ((((uint8_t*) src)[i * 3 + 0]) << 4) & 0x3F;
100         *dest++ = bit6toAscii(a[0]);
101         *dest++ = bit6toAscii(a[1]);
102         *dest++ = '=';
103         *dest++ = '=';
104         break;
105     case 2:
106         a[0] = (((uint8_t*) src)[i * 3 + 0]) >> 2;
107         a[1] = (((((uint8_t*) src)[i * 3 + 0]) << 4)
108                 | ((((uint8_t*) src)[i * 3 + 1]) >> 4)) & 0x3F;
109         a[2] = ((((uint8_t*) src)[i * 3 + 1]) << 2) & 0x3F;
110         *dest++ = bit6toAscii(a[0]);
111         *dest++ = bit6toAscii(a[1]);
112         *dest++ = bit6toAscii(a[2]);
113         *dest++ = '=';
114         break;
115     default: /* this will not happen! */
116         break;
117     }
118     /*  finalize: */
119     *dest = '\0';
120 }
121