libtc  20160415
Threshold Cryptography functions library
algorithms_base64.c
Go to the documentation of this file.
1 /* Copyright (c) 2015 Francisco Cifuentes <franchoco@gmail.com>
2  *
3  * Permission is hereby granted, free of charge, to any person obtaining a copy
4  * of this software and associated documentation files (the "Software"), to deal
5  * in the Software without restriction, including without limitation the rights
6  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7  * copies of the Software, and to permit persons to whom the Software is
8  * furnished to do so, subject to the following conditions:
9  *
10  * The above copyright notice and this permission notice shall be included in
11  * all copies or substantial portions of the Software.
12  *
13  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19  * THE SOFTWARE.
20  */
21 
22 #include <stdint.h>
23 #include <stdlib.h>
24 #include <string.h>
25 
26 #include "tc.h"
27 #include "tc_internal.h"
28 
29 static const char lookup_table[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
30 static const char pad = '=';
31 
32 
33 static char *b64_encode (const uint8_t * buffer, size_t len )
34 {
35  /* In Base 64 we represent 6 bits with each character */
36  uint32_t temp;
37  char *out, *p;
38 
39  // For each 3 byte input->4 byte char output. if there still need for 1 or 2 extra bytes,
40  // you need 4 extra bytes. The last 1 extra byte is for null-byte termination.
41  size_t buf_len = 4*(len/3) + 4 + 1;
42 
43  p = out = alloc(buf_len);
44 
45  const uint8_t * cur = buffer;
46  for(size_t i = 0; i < len/3; i++) {
47  temp = ( *cur++ ) << 16;
48  temp += ( *cur++ ) << 8;
49  temp += ( *cur++ );
50 
51  *p++ = lookup_table[( temp & 0x00FC0000 ) >> 18];
52  *p++ = lookup_table[( temp & 0x0003F000 ) >> 12];
53  *p++ = lookup_table[( temp & 0x00000FC0 ) >> 6 ];
54  *p++ = lookup_table[( temp & 0x0000003F ) ];
55  }
56  switch(len % 3) {
57  case 1:
58  temp = ( *cur++ ) << 16;
59  *p++ = lookup_table[( temp & 0x00FC0000 ) >> 18];
60  *p++ = lookup_table[( temp & 0x0003F000 ) >> 12];
61  *p++ = pad;
62  *p++ = pad;
63  break;
64  case 2:
65  temp = ( *cur++ ) << 16;
66  temp += ( *cur++ ) << 8;
67  *p++ = lookup_table[( temp & 0x00FC0000 ) >> 18];
68  *p++ = lookup_table[( temp & 0x0003F000 ) >> 12];
69  *p++ = lookup_table[( temp & 0x00000FC0 ) >> 6 ];
70  *p++ = pad;
71  break;
72  }
73  *p = '\0';
74 
75  return out;
76 }
77 
78 static size_t b64_length(const char *input, size_t len) {
79  size_t padding =
80  input[len-2] == pad? 2 :
81  input[len-1] == pad? 1 : 0;
82 
83  return 3*len/4 - padding;
84 }
85 
86 static uint8_t *b64_decode ( const char *input, size_t len , size_t *out_size)
87 {
88  if ( len % 4 ) {
89  return NULL;
90  }
91 
92  *out_size = b64_length(input, len);
93 
94  uint8_t *out;
95  uint8_t *p = out = alloc(*out_size);
96 
97  uint32_t temp = 0;
98  const char * cur = input;
99  while ( cur < input + len ) {
100  for ( size_t i = 0; i < 4; i++ ) {
101  temp <<= 6;
102  if ( *cur >= 0x41 && *cur <= 0x5A ) {
103  temp |= *cur - 0x41;
104  } else if ( *cur >= 0x61 && *cur <= 0x7A ) {
105  temp |= *cur - 0x47;
106  } else if ( *cur >= 0x30 && *cur <= 0x39 ) {
107  temp |= *cur + 0x04;
108  } else if ( *cur == 0x2B ) {
109  temp |= 0x3E;
110  } else if ( *cur == 0x2F ) {
111  temp |= 0x3F;
112  } else if ( *cur == pad ) {
113  switch ( input + len - cur ) {
114  case 1:
115  *p++ = ( ( temp >> 16 ) & 0x000000FF );
116  *p++ = ( ( temp >> 8 ) & 0x000000FF );
117  return out;
118  case 2:
119  *p++ = ( ( temp >> 10 ) & 0x000000FF );
120  return out;
121  default:
122  goto on_error;
123  }
124  } else {
125  goto on_error;
126  }
127  cur++;
128  }
129  *p++ = ( ( temp >> 16 ) & 0x000000FF );
130  *p++ = ( ( temp >> 8 ) & 0x000000FF );
131  *p++ = ( ( temp ) & 0x000000FF );
132  }
133  return out;
134 
135 on_error:
136  free(out);
137  return NULL;
138 }
139 
140 char *tc_bytes_b64(const bytes_t * b) {
141  return b64_encode(b->data, b->data_len);
142 }
143 
144 bytes_t * tc_b64_bytes(const char *b64){
145  size_t b64_len = strlen(b64);
146 
147  size_t b_len = 0;
148  uint8_t * b = b64_decode(b64, b64_len, &b_len);
149 
150  return tc_init_bytes(b, b_len);
151 }
152 
char * tc_bytes_b64(const bytes_t *b)
Structure that&#39;s stores a pointer that points to data_len bytes.
Definition: tc.h:14
void * data
Definition: tc.h:15
uint32_t data_len
Definition: tc.h:16
void * alloc(size_t size)
Definition: structs_init.c:9
bytes_t * tc_init_bytes(void *bs, size_t len)
Definition: structs_init.c:18
bytes_t * tc_b64_bytes(const char *b64)