base64.c
Go to the documentation of this file.
1 /**
2  * @file base64.c
3  * @brief Base64 encoding scheme
4  *
5  * @section License
6  *
7  * Copyright (C) 2010-2018 Oryx Embedded SARL. All rights reserved.
8  *
9  * This file is part of CycloneCrypto Open.
10  *
11  * This program is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU General Public License
13  * as published by the Free Software Foundation; either version 2
14  * of the License, or (at your option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, write to the Free Software Foundation,
23  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
24  *
25  * @section Description
26  *
27  * Base64 is a encoding scheme that represents binary data in an ASCII string
28  * format by translating it into a radix-64 representation. Refer to RFC 4648
29  * for more details
30  *
31  * @author Oryx Embedded SARL (www.oryx-embedded.com)
32  * @version 1.9.0
33  **/
34 
35 //Switch to the appropriate trace level
36 #define TRACE_LEVEL CRYPTO_TRACE_LEVEL
37 
38 //Dependencies
39 #include "core/crypto.h"
40 #include "encoding/base64.h"
41 
42 //Check crypto library configuration
43 #if (BASE64_SUPPORT == ENABLED)
44 
45 //Base64 encoding table
46 static const char_t base64EncTable[64] =
47 {
48  'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
49  'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',
50  'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
51  'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/'
52 };
53 
54 //Base64 decoding table
55 static const uint8_t base64DecTable[128] =
56 {
57  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
58  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
59  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3E, 0xFF, 0xFF, 0xFF, 0x3F,
60  0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
61  0xFF, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E,
62  0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
63  0xFF, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28,
64  0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x30, 0x31, 0x32, 0x33, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
65 };
66 
67 
68 /**
69  * @brief Base64 encoding algorithm
70  * @param[in] input Input data to encode
71  * @param[in] inputLen Length of the data to encode
72  * @param[out] output NULL-terminated string encoded with Base64 algorithm
73  * @param[out] outputLen Length of the encoded string (optional parameter)
74  **/
75 
76 void base64Encode(const void *input, size_t inputLen,
77  char_t *output, size_t *outputLen)
78 {
79  size_t n;
80  uint8_t a;
81  uint8_t b;
82  uint8_t c;
83  uint8_t d;
84  const uint8_t *p;
85 
86  //Point to the first byte of the input data
87  p = (const uint8_t *) input;
88 
89  //Divide the input stream into blocks of 3 bytes
90  n = inputLen / 3;
91 
92  //A full encoding quantum is always completed at the end of a quantity
93  if(inputLen == (n * 3 + 1))
94  {
95  //The final quantum of encoding input is exactly 8 bits
96  if(input != NULL && output != NULL)
97  {
98  //Read input data
99  a = (p[n * 3] & 0xFC) >> 2;
100  b = (p[n * 3] & 0x03) << 4;
101 
102  //The final unit of encoded output will be two characters followed
103  //by two "=" padding characters
104  output[n * 4] = base64EncTable[a];
105  output[n * 4 + 1] = base64EncTable[b];
106  output[n * 4 + 2] = '=';
107  output[n * 4 + 3] = '=';
108  output[n * 4 + 4] = '\0';
109  }
110 
111  //Length of the encoded string (excluding the terminating NULL)
112  if(outputLen != NULL)
113  *outputLen = n * 4 + 4;
114  }
115  else if(inputLen == (n * 3 + 2))
116  {
117  //The final quantum of encoding input is exactly 16 bits
118  if(input != NULL && output != NULL)
119  {
120  //Read input data
121  a = (p[n * 3] & 0xFC) >> 2;
122  b = ((p[n * 3] & 0x03) << 4) | ((p[n * 3 + 1] & 0xF0) >> 4);
123  c = (p[n * 3 + 1] & 0x0F) << 2;
124 
125  //The final unit of encoded output will be three characters followed
126  //by one "=" padding character
127  output[n * 4] = base64EncTable[a];
128  output[n * 4 + 1] = base64EncTable[b];
129  output[n * 4 + 2] = base64EncTable[c];
130  output[n * 4 + 3] = '=';
131  output[n * 4 + 4] = '\0';
132  }
133 
134  //Length of the encoded string (excluding the terminating NULL)
135  if(outputLen != NULL)
136  *outputLen = n * 4 + 4;
137  }
138  else
139  {
140  //The final quantum of encoding input is an integral multiple of 24 bits
141  if(output != NULL)
142  {
143  //The final unit of encoded output will be an integral multiple of 4
144  //characters with no "=" padding
145  output[n * 4] = '\0';
146  }
147 
148  //Length of the encoded string (excluding the terminating NULL)
149  if(outputLen != NULL)
150  *outputLen = n * 4;
151  }
152 
153  //If the output parameter is NULL, then the function calculates the
154  //length of the resulting Base64 string without copying any data
155  if(input != NULL && output != NULL)
156  {
157  //The input data is processed block by block
158  while(n-- > 0)
159  {
160  //Read input data
161  a = (p[n * 3] & 0xFC) >> 2;
162  b = ((p[n * 3] & 0x03) << 4) | ((p[n * 3 + 1] & 0xF0) >> 4);
163  c = ((p[n * 3 + 1] & 0x0F) << 2) | ((p[n * 3 + 2] & 0xC0) >> 6);
164  d = p[n * 3 + 2] & 0x3F;
165 
166  //Map each 3-byte block to 4 printable characters using the Base64
167  //character set
168  output[n * 4] = base64EncTable[a];
169  output[n * 4 + 1] = base64EncTable[b];
170  output[n * 4 + 2] = base64EncTable[c];
171  output[n * 4 + 3] = base64EncTable[d];
172  }
173  }
174 }
175 
176 
177 /**
178  * @brief Base64 decoding algorithm
179  * @param[in] input Base64 encoded string
180  * @param[in] inputLen Length of the encoded string
181  * @param[out] output Resulting decoded data
182  * @param[out] outputLen Length of the decoded data
183  * @return Error code
184  **/
185 
186 error_t base64Decode(const char_t *input, size_t inputLen,
187  void *output, size_t *outputLen)
188 {
189  size_t i;
190  size_t j;
191  uint32_t value;
192  uint8_t *p;
193 
194  //Check parameters
195  if(input == NULL && inputLen != 0)
197  if(outputLen == NULL)
199 
200  //Point to the buffer where to write the decoded data
201  p = (uint8_t *) output;
202  //Length of the decoded data
203  i = 0;
204 
205  //The length of the string to decode must be a multiple of 4
206  if((inputLen % 4) != 0)
207  return ERROR_INVALID_LENGTH;
208 
209  //Process the Base64 encoded string
210  while(inputLen >= 4)
211  {
212  //Divide the input stream into blocks of 4 characters
213  for(value = 0, j = 0; j < 4; j++)
214  {
215  //The "==" sequence indicates that the last block contains only 1 byte
216  if(inputLen == 2 && input[0] == '=' && input[1] == '=')
217  {
218  //Decode the last byte
219  if(p != NULL)
220  p[i] = (value >> 4) & 0xFF;
221 
222  //Return the length of the decoded data
223  *outputLen = i + 1;
224 
225  //Decoding is now complete
226  return NO_ERROR;
227  }
228  //The "=" sequence indicates that the last block contains only 2 bytes
229  else if(inputLen == 1 && input[0] == '=')
230  {
231  //Decode the last two bytes
232  if(p != NULL)
233  {
234  p[i] = (value >> 10) & 0xFF;
235  p[i + 1] = (value >> 2) & 0xFF;
236  }
237 
238  //Return the length of the decoded data
239  *outputLen = i + 2;
240 
241  //Decoding is now complete
242  return NO_ERROR;
243  }
244 
245  //Ensure the current character belongs to the Base64 character set
246  if(((uint8_t) *input) > 127 || base64DecTable[(uint8_t) *input] > 63)
247  {
248  //Decoding failed
250  }
251 
252  //Decode the current character
253  value = (value << 6) | base64DecTable[(uint8_t) *input];
254 
255  //Point to the next character to decode
256  input++;
257  //Remaining bytes to process
258  inputLen--;
259  }
260 
261  //Map each 4-character block to 3 bytes
262  if(p != NULL)
263  {
264  p[i] = (value >> 16) & 0xFF;
265  p[i + 1] = (value >> 8) & 0xFF;
266  p[i + 2] = value & 0xFF;
267  }
268 
269  //Next block
270  i += 3;
271  }
272 
273  //Return the length of the decoded data
274  *outputLen = i;
275 
276  //Decoding is now complete
277  return NO_ERROR;
278 }
279 
280 #endif
char char_t
Definition: compiler_port.h:41
uint8_t c
Definition: ndp.h:510
uint8_t p
Definition: ndp.h:295
General definitions for cryptographic algorithms.
Invalid parameter.
Definition: error.h:45
error_t base64Decode(const char_t *input, size_t inputLen, void *output, size_t *outputLen)
Base64 decoding algorithm.
Definition: base64.c:186
void base64Encode(const void *input, size_t inputLen, char_t *output, size_t *outputLen)
Base64 encoding algorithm.
Definition: base64.c:76
uint8_t a
Definition: ndp.h:407
Success.
Definition: error.h:42
error_t
Error codes.
Definition: error.h:40
Base64 encoding scheme.
uint8_t value[]
Definition: dtls_misc.h:141
uint8_t n
uint8_t b[6]
Definition: dtls_misc.h:130