]> git.cryptolib.org Git - arm-crypto-lib.git/blob - base64/base64_dec.c
more precise type for arguments of bcal_nessie_multiple()
[arm-crypto-lib.git] / base64 / base64_dec.c
1 /* base64_dec.c */
2 /*
3  *   This file is part of the ARM-Crypto-Lib.
4  *   Copyright (C) 2006-2010  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 /**
22  * base64 decoder (RFC3548)
23  * Author: Daniel Otte
24  * License: GPLv3
25  * 
26  * 
27  */
28
29 #include <stdint.h>
30 #include "base64_dec.h"
31
32
33 /*
34 #define USE_GCC_EXTENSION
35 */
36
37 #ifdef USE_GCC_EXTENSION
38
39 static
40 int ascii2bit6(char a){
41         switch(a){
42                 case 'A'...'Z':
43                         return a-'A';
44                 case 'a'...'z':
45                         return a-'a'+26;
46                 case '0'...'9':
47                         return a-'0'+52;
48                 case '+':
49                 case '-':
50                         return 62;
51                 case '/':
52                 case '_':
53                         return 63;
54                 default:
55                         return -1;
56         }
57 }
58
59 #else
60
61 static
62 uint8_t ascii2bit6(char a){
63         int r;
64         switch(a>>4){
65                 case 0x5:
66                 case 0x4: 
67                         r=a-'A';
68                         if(r<0 || r>25){
69                                 return -1;
70                         } else {
71                                 return r;
72                         }
73                 case 0x7:
74                 case 0x6: 
75                         r=a-'a';
76                         if(r<0 || r>25){
77                                 return -1;
78                         } else {
79                                 return r+26;
80                         }
81                         break;
82                 case 0x3:
83                         if(a>'9')
84                                 return -1;
85                         return a-'0'+52;
86                 default:
87                         break;  
88         }
89         switch (a){
90                 case '+':
91                 case '-':
92                         return 62;
93                 case '/':
94                 case '_':
95                         return 63;
96                 default:
97                         return 0xff;
98         }
99 }
100
101 #endif
102
103 int base64_binlength(char* str, uint8_t strict){
104         int l=0;
105         uint8_t term=0;
106         for(;;){
107                 if(*str=='\0')
108                         break;
109                 if(*str=='\n' || *str=='\r'){
110                         str++;
111                         continue;
112                 }
113                 if(*str=='='){
114                         term++;
115                         str++;
116                         if(term==2){
117                                 break;
118                         }
119                         continue;
120                 }
121                 if(term)
122                         return -1;
123                 if(ascii2bit6(*str)==-1){
124                         if(strict)
125                                 return -1;
126                 } else {
127                         l++;
128                 }
129                 str++;
130         }
131         switch(term){
132                 case 0:
133                         if(l%4!=0)
134                                 return -1;
135                         return l/4*3;
136                 case 1:
137                         if(l%4!=3)
138                                 return -1;
139                         return (l+1)/4*3-1;
140                 case 2:
141                         if(l%4!=2)
142                                 return -1;
143                         return (l+2)/4*3-2;
144                 default:
145                         return -1;
146         }
147 }
148
149 /*
150   |543210543210543210543210|
151   |765432107654321076543210|
152
153         .      .      .     .
154   |54321054|32105432|10543210|
155   |76543210|76543210|76543210|
156
157 */
158
159 int base64dec(void* dest, const char* b64str, uint8_t strict){
160         uint8_t buffer[4];
161         uint8_t idx=0;
162         uint8_t term=0;
163         for(;;){
164                 buffer[idx]= ascii2bit6(*b64str);
165                 
166                 if(buffer[idx]==0xFF){
167                         if(*b64str=='='){
168                                 term++;
169                                 b64str++;
170                                 if(term==2)
171                                         goto finalize; /* definitly the end */
172                         }else{
173                                 if(*b64str == '\0'){
174                                         goto finalize; /* definitly the end */
175                                 }else{
176                                         if(*b64str == '\r' || *b64str == '\n' || !(strict)){
177                                                 b64str++; /* charcters that we simply ignore */
178                                         }else{
179                                                 return -1;
180                                         }
181                                 }
182                         }
183                 }else{
184                         if(term)
185                                 return -1; /* this happens if we get a '=' in the stream */
186                         idx++;
187                         b64str++;
188                 }
189                 if(idx==4){
190                         ((uint8_t*)dest)[0] = buffer[0]<<2 | buffer[1]>>4;
191                         ((uint8_t*)dest)[1] = buffer[1]<<4 | buffer[2]>>2;
192                         ((uint8_t*)dest)[2] = buffer[2]<<6 | buffer[3];
193                         dest = (uint8_t*)dest +3;
194                         idx=0;
195                 }
196         }
197   finalize:     
198         /* the final touch */
199         if(idx==0)
200                 return 0;
201         if(term==1){
202                 ((uint8_t*)dest)[0] = buffer[0]<<2 | buffer[1]>>4;
203                 ((uint8_t*)dest)[1] = buffer[1]<<4 | buffer[2]>>2;                      
204                 return 0;
205         }
206         if(term==2){
207                 ((uint8_t*)dest)[0] = buffer[0]<<2 | buffer[1]>>4;
208                 return 0;
209         }
210         return -1;
211 }