1 /* 2 * base64 encoder/decoder 3 * 4 * Copyright 2005 by Kai Blin 5 * 6 * This library is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU Lesser General Public 8 * License as published by the Free Software Foundation; either 9 * version 2 of the License, or (at your option) any later version. 10 * 11 * This library 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 GNU 14 * Lesser General Public License for more details. 15 * 16 * You should have received a copy of the GNU Lesser General Public 17 * License along with this library; if not, write to the Free Software 18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 19 */ 20 21 #include "precomp.h" 22 23 #include <wine/debug.h> 24 WINE_DEFAULT_DEBUG_CHANNEL(ntlm); 25 26 static const char b64[] = 27 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; 28 29 SECURITY_STATUS encodeBase64(PBYTE in_buf, int in_len, char* out_buf, 30 int max_len, int *out_len) 31 { 32 int div, i; 33 PBYTE d = in_buf; 34 int bytes = (in_len*8 + 5)/6, pad_bytes = (bytes % 4) ? 4 - (bytes % 4) : 0; 35 36 TRACE("bytes is %d, pad bytes is %d\n", bytes, pad_bytes); 37 *out_len = bytes + pad_bytes; 38 39 if(bytes + pad_bytes + 1 > max_len) 40 return SEC_E_BUFFER_TOO_SMALL; 41 42 /* Three bytes of input give 4 chars of output */ 43 div = in_len / 3; 44 45 i = 0; 46 while(div > 0) 47 { 48 /* first char is the first 6 bits of the first byte*/ 49 out_buf[i + 0] = b64[ ( d[0] >> 2) & 0x3f ]; 50 /* second char is the last 2 bits of the first byte and the first 4 51 * bits of the second byte */ 52 out_buf[i + 1] = b64[ ((d[0] << 4) & 0x30) | (d[1] >> 4 & 0x0f)]; 53 /* third char is the last 4 bits of the second byte and the first 2 54 * bits of the third byte */ 55 out_buf[i + 2] = b64[ ((d[1] << 2) & 0x3c) | (d[2] >> 6 & 0x03)]; 56 /* fourth char is the remaining 6 bits of the third byte */ 57 out_buf[i + 3] = b64[ d[2] & 0x3f]; 58 i += 4; 59 d += 3; 60 div--; 61 } 62 63 switch(pad_bytes) 64 { 65 case 1: 66 /* first char is the first 6 bits of the first byte*/ 67 out_buf[i + 0] = b64[ ( d[0] >> 2) & 0x3f ]; 68 /* second char is the last 2 bits of the first byte and the first 4 69 * bits of the second byte */ 70 out_buf[i + 1] = b64[ ((d[0] << 4) & 0x30) | (d[1] >> 4 & 0x0f)]; 71 /* third char is the last 4 bits of the second byte padded with 72 * two zeroes */ 73 out_buf[i + 2] = b64[ ((d[1] << 2) & 0x3c) ]; 74 /* fourth char is a = to indicate one byte of padding */ 75 out_buf[i + 3] = '='; 76 out_buf[i + 4] = 0; 77 break; 78 case 2: 79 /* first char is the first 6 bits of the first byte*/ 80 out_buf[i + 0] = b64[ ( d[0] >> 2) & 0x3f ]; 81 /* second char is the last 2 bits of the first byte padded with 82 * four zeroes*/ 83 out_buf[i + 1] = b64[ ((d[0] << 4) & 0x30)]; 84 /* third char is = to indicate padding */ 85 out_buf[i + 2] = '='; 86 /* fourth char is = to indicate padding */ 87 out_buf[i + 3] = '='; 88 out_buf[i + 4] = 0; 89 break; 90 default: 91 out_buf[i] = 0; 92 } 93 94 return SEC_E_OK; 95 } 96 97 static inline BYTE decode(char c) 98 { 99 if( c >= 'A' && c <= 'Z') 100 return c - 'A'; 101 if( c >= 'a' && c <= 'z') 102 return c - 'a' + 26; 103 if( c >= '0' && c <= '9') 104 return c - '0' + 52; 105 if( c == '+') 106 return 62; 107 if( c == '/') 108 return 63; 109 else 110 return 64; 111 } 112 113 SECURITY_STATUS decodeBase64(char *in_buf, int in_len, PBYTE out_buf, 114 int max_len, int *out_len) 115 { 116 int len = in_len, i; 117 char *d = in_buf; 118 int ip0, ip1, ip2, ip3; 119 120 TRACE("in_len: %d\n", in_len); 121 122 if((in_len % 4) != 0) 123 return SEC_E_INVALID_TOKEN; 124 125 if(in_len > max_len) 126 return SEC_E_BUFFER_TOO_SMALL; 127 128 i = 0; 129 while(len > 4) 130 { 131 if((ip0 = decode(d[0])) > 63) 132 return SEC_E_INVALID_TOKEN; 133 if((ip1 = decode(d[1])) > 63) 134 return SEC_E_INVALID_TOKEN; 135 if((ip2 = decode(d[2])) > 63) 136 return SEC_E_INVALID_TOKEN; 137 if((ip3 = decode(d[3])) > 63) 138 return SEC_E_INVALID_TOKEN; 139 140 out_buf[i + 0] = (ip0 << 2) | (ip1 >> 4); 141 out_buf[i + 1] = (ip1 << 4) | (ip2 >> 2); 142 out_buf[i + 2] = (ip2 << 6) | ip3; 143 len -= 4; 144 i += 3; 145 d += 4; 146 } 147 148 if(d[2] == '=') 149 { 150 if((ip0 = decode(d[0])) > 63) 151 return SEC_E_INVALID_TOKEN; 152 if((ip1 = decode(d[1])) > 63) 153 return SEC_E_INVALID_TOKEN; 154 155 out_buf[i] = (ip0 << 2) | (ip1 >> 4); 156 i++; 157 } 158 else if(d[3] == '=') 159 { 160 if((ip0 = decode(d[0])) > 63) 161 return SEC_E_INVALID_TOKEN; 162 if((ip1 = decode(d[1])) > 63) 163 return SEC_E_INVALID_TOKEN; 164 if((ip2 = decode(d[2])) > 63) 165 return SEC_E_INVALID_TOKEN; 166 167 out_buf[i + 0] = (ip0 << 2) | (ip1 >> 4); 168 out_buf[i + 1] = (ip1 << 4) | (ip2 >> 2); 169 i += 2; 170 } 171 else 172 { 173 if((ip0 = decode(d[0])) > 63) 174 return SEC_E_INVALID_TOKEN; 175 if((ip1 = decode(d[1])) > 63) 176 return SEC_E_INVALID_TOKEN; 177 if((ip2 = decode(d[2])) > 63) 178 return SEC_E_INVALID_TOKEN; 179 if((ip3 = decode(d[3])) > 63) 180 return SEC_E_INVALID_TOKEN; 181 182 183 out_buf[i + 0] = (ip0 << 2) | (ip1 >> 4); 184 out_buf[i + 1] = (ip1 << 4) | (ip2 >> 2); 185 out_buf[i + 2] = (ip2 << 6) | ip3; 186 i += 3; 187 } 188 *out_len = i; 189 return SEC_E_OK; 190 } 191