1 #include "base64.h" 2 #include "edk/BaseTypes.h" 3 4 #include <stdlib.h> 5 #include <string.h> 6 #include <stdio.h> 7 #include <assert.h> 8 9 static const UINT8 encode_table[65] = 10 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; 11 12 /** 13 * 14 * Caller is responsible for freeing the returned buffer. 15 */ 16 CHAR8 *base64_encode(const UINT8 *src, INT32 len, INT32 *out_len) 17 { 18 CHAR8 *out; 19 CHAR8 *out_pos; 20 const UINT8 *src_end; 21 const UINT8 *in_pos; 22 23 if (!out_len) { 24 return NULL; 25 } 26 27 // 3 byte blocks to 4 byte blocks plus up to 2 bytes of padding 28 *out_len = 4 * ((len + 2) / 3); 29 30 // Handle overflows 31 if (*out_len < len) { 32 return NULL; 33 } 34 35 out = malloc(*out_len); 36 if (out == NULL) { 37 return NULL; 38 } 39 40 src_end = src + len; 41 in_pos = src; 42 out_pos = out; 43 while (src_end - in_pos >= 3) { 44 *out_pos++ = encode_table[in_pos[0] >> 2]; 45 *out_pos++ = encode_table[((in_pos[0] & 0x03) << 4) | 46 (in_pos[1] >> 4)]; 47 *out_pos++ = encode_table[((in_pos[1] & 0x0f) << 2) | 48 (in_pos[2] >> 6)]; 49 *out_pos++ = encode_table[in_pos[2] & 0x3f]; 50 in_pos += 3; 51 } 52 53 if (src_end - in_pos) { 54 *out_pos++ = encode_table[in_pos[0] >> 2]; 55 if (src_end - in_pos == 1) { 56 *out_pos++ = encode_table[(in_pos[0] & 0x03) << 4]; 57 *out_pos++ = '='; 58 } else { 59 *out_pos++ = encode_table[((in_pos[0] & 0x03) << 4) | 60 (in_pos[1] >> 4)]; 61 *out_pos++ = encode_table[(in_pos[1] & 0x0f) << 2]; 62 } 63 *out_pos++ = '='; 64 } 65 66 return out; 67 } 68 69 // Base64 decode table. Invalid values are specified with 0x80. 70 UINT8 decode_table[256] = 71 "\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80" 72 "\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80" 73 "\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x3e\x80\x80\x80\x3f" 74 "\x34\x35\x36\x37\x38\x39\x3a\x3b\x3c\x3d\x80\x80\x80\x00\x80\x80" 75 "\x80\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e" 76 "\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x80\x80\x80\x80\x80" 77 "\x80\x1a\x1b\x1c\x1d\x1e\x1f\x20\x21\x22\x23\x24\x25\x26\x27\x28" 78 "\x29\x2a\x2b\x2c\x2d\x2e\x2f\x30\x31\x32\x33\x80\x80\x80\x80\x80" 79 "\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80" 80 "\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80" 81 "\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80" 82 "\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80" 83 "\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80" 84 "\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80" 85 "\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80" 86 "\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80\x80"; 87 88 /** 89 * 90 * Caller is responsible for freeing the returned buffer. 91 */ 92 UINT8 *base64_decode(const CHAR8 *src, INT32 len, INT32 *out_len) 93 { 94 UINT8 *out; 95 UINT8 *pos; 96 UINT8 block[4]; 97 UINT8 tmp; 98 INT32 block_index; 99 INT32 src_index; 100 UINT32 pad_count = 0; 101 102 if (!out_len) { 103 return NULL; 104 } 105 106 // Malloc might be up to 2 larger dependent on padding 107 *out_len = len / 4 * 3; 108 pos = out = malloc(*out_len); 109 if (out == NULL) { 110 return NULL; 111 } 112 113 block_index = 0; 114 for (src_index = 0; src_index < len; src_index++) { 115 tmp = decode_table[(UINT8)src[src_index]]; 116 if (tmp == 0x80) { 117 free(out); 118 return NULL; 119 } 120 121 if (src[src_index] == '=') { 122 pad_count++; 123 } 124 125 block[block_index] = tmp; 126 block_index++; 127 if (block_index == 4) { 128 *pos++ = (block[0] << 2) | (block[1] >> 4); 129 *pos++ = (block[1] << 4) | (block[2] >> 2); 130 *pos++ = (block[2] << 6) | block[3]; 131 if (pad_count > 0) { 132 if (pad_count == 1) { 133 pos--; 134 } else if (pad_count == 2) { 135 pos -= 2; 136 } else { 137 /* Invalid pad_counting */ 138 free(out); 139 return NULL; 140 } 141 break; 142 } 143 block_index = 0; 144 } 145 } 146 147 *out_len = pos - out; 148 return out; 149 } 150