1/* Licensed to the Apache Software Foundation (ASF) under one or more 2 * contributor license agreements. See the NOTICE file distributed with 3 * this work for additional information regarding copyright ownership. 4 * The ASF licenses this file to You under the Apache License, Version 2.0 5 * (the "License"); you may not use this file except in compliance with 6 * the License. You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17/* base64 encoder/decoder. Originally part of main/util.c 18 * but moved here so that support/ab and apr_sha1.c could 19 * use it. This meant removing the apr_palloc()s and adding 20 * ugly 'len' functions, which is quite a nasty cost. 21 */ 22 23#include "apr_base64.h" 24#if APR_CHARSET_EBCDIC 25#include "apr_xlate.h" 26#endif /* APR_CHARSET_EBCDIC */ 27 28/* aaaack but it's fast and const should make it shared text page. */ 29static const unsigned char pr2six[256] = 30{ 31#if !APR_CHARSET_EBCDIC 32 /* ASCII table */ 33 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 34 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 35 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 62, 64, 64, 64, 63, 36 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 64, 64, 64, 64, 64, 64, 37 64, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 38 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 64, 64, 64, 64, 64, 39 64, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 40 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 64, 64, 64, 64, 64, 41 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 42 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 43 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 44 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 45 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 46 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 47 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 48 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64 49#else /*APR_CHARSET_EBCDIC*/ 50 /* EBCDIC table */ 51 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 52 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 53 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 54 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 55 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 62, 64, 56 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 57 64, 63, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 58 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 59 64, 26, 27, 28, 29, 30, 31, 32, 33, 34, 64, 64, 64, 64, 64, 64, 60 64, 35, 36, 37, 38, 39, 40, 41, 42, 43, 64, 64, 64, 64, 64, 64, 61 64, 64, 44, 45, 46, 47, 48, 49, 50, 51, 64, 64, 64, 64, 64, 64, 62 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 63 64, 0, 1, 2, 3, 4, 5, 6, 7, 8, 64, 64, 64, 64, 64, 64, 64 64, 9, 10, 11, 12, 13, 14, 15, 16, 17, 64, 64, 64, 64, 64, 64, 65 64, 64, 18, 19, 20, 21, 22, 23, 24, 25, 64, 64, 64, 64, 64, 64, 66 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 64, 64, 64, 64, 64, 64 67#endif /*APR_CHARSET_EBCDIC*/ 68}; 69 70#if APR_CHARSET_EBCDIC 71static apr_xlate_t *xlate_to_ebcdic; 72static unsigned char os_toascii[256]; 73 74APU_DECLARE(apr_status_t) apr_base64init_ebcdic(apr_xlate_t *to_ascii, 75 apr_xlate_t *to_ebcdic) 76{ 77 int i; 78 apr_size_t inbytes_left, outbytes_left; 79 apr_status_t rv; 80 int onoff; 81 82 /* Only single-byte conversion is supported. 83 */ 84 rv = apr_xlate_sb_get(to_ascii, &onoff); 85 if (rv) { 86 return rv; 87 } 88 if (!onoff) { /* If conversion is not single-byte-only */ 89 return APR_EINVAL; 90 } 91 rv = apr_xlate_sb_get(to_ebcdic, &onoff); 92 if (rv) { 93 return rv; 94 } 95 if (!onoff) { /* If conversion is not single-byte-only */ 96 return APR_EINVAL; 97 } 98 xlate_to_ebcdic = to_ebcdic; 99 for (i = 0; i < sizeof(os_toascii); i++) { 100 os_toascii[i] = i; 101 } 102 inbytes_left = outbytes_left = sizeof(os_toascii); 103 apr_xlate_conv_buffer(to_ascii, os_toascii, &inbytes_left, 104 os_toascii, &outbytes_left); 105 106 return APR_SUCCESS; 107} 108#endif /*APR_CHARSET_EBCDIC*/ 109 110APU_DECLARE(int) apr_base64_decode_len(const char *bufcoded) 111{ 112 int nbytesdecoded; 113 register const unsigned char *bufin; 114 register apr_size_t nprbytes; 115 116 bufin = (const unsigned char *) bufcoded; 117 while (pr2six[*(bufin++)] <= 63); 118 119 nprbytes = (bufin - (const unsigned char *) bufcoded) - 1; 120 nbytesdecoded = (((int)nprbytes + 3) / 4) * 3; 121 122 return nbytesdecoded + 1; 123} 124 125APU_DECLARE(int) apr_base64_decode(char *bufplain, const char *bufcoded) 126{ 127#if APR_CHARSET_EBCDIC 128 apr_size_t inbytes_left, outbytes_left; 129#endif /* APR_CHARSET_EBCDIC */ 130 int len; 131 132 len = apr_base64_decode_binary((unsigned char *) bufplain, bufcoded); 133#if APR_CHARSET_EBCDIC 134 inbytes_left = outbytes_left = len; 135 apr_xlate_conv_buffer(xlate_to_ebcdic, bufplain, &inbytes_left, 136 bufplain, &outbytes_left); 137#endif /* APR_CHARSET_EBCDIC */ 138 bufplain[len] = '\0'; 139 return len; 140} 141 142/* This is the same as apr_base64_decode() except on EBCDIC machines, where 143 * the conversion of the output to ebcdic is left out. 144 */ 145APU_DECLARE(int) apr_base64_decode_binary(unsigned char *bufplain, 146 const char *bufcoded) 147{ 148 int nbytesdecoded; 149 register const unsigned char *bufin; 150 register unsigned char *bufout; 151 register apr_size_t nprbytes; 152 153 bufin = (const unsigned char *) bufcoded; 154 while (pr2six[*(bufin++)] <= 63); 155 nprbytes = (bufin - (const unsigned char *) bufcoded) - 1; 156 nbytesdecoded = (((int)nprbytes + 3) / 4) * 3; 157 158 bufout = (unsigned char *) bufplain; 159 bufin = (const unsigned char *) bufcoded; 160 161 while (nprbytes > 4) { 162 *(bufout++) = 163 (unsigned char) (pr2six[*bufin] << 2 | pr2six[bufin[1]] >> 4); 164 *(bufout++) = 165 (unsigned char) (pr2six[bufin[1]] << 4 | pr2six[bufin[2]] >> 2); 166 *(bufout++) = 167 (unsigned char) (pr2six[bufin[2]] << 6 | pr2six[bufin[3]]); 168 bufin += 4; 169 nprbytes -= 4; 170 } 171 172 /* Note: (nprbytes == 1) would be an error, so just ingore that case */ 173 if (nprbytes > 1) { 174 *(bufout++) = 175 (unsigned char) (pr2six[*bufin] << 2 | pr2six[bufin[1]] >> 4); 176 } 177 if (nprbytes > 2) { 178 *(bufout++) = 179 (unsigned char) (pr2six[bufin[1]] << 4 | pr2six[bufin[2]] >> 2); 180 } 181 if (nprbytes > 3) { 182 *(bufout++) = 183 (unsigned char) (pr2six[bufin[2]] << 6 | pr2six[bufin[3]]); 184 } 185 186 nbytesdecoded -= (4 - (int)nprbytes) & 3; 187 return nbytesdecoded; 188} 189 190static const char basis_64[] = 191 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; 192 193APU_DECLARE(int) apr_base64_encode_len(int len) 194{ 195 return ((len + 2) / 3 * 4) + 1; 196} 197 198APU_DECLARE(int) apr_base64_encode(char *encoded, const char *string, int len) 199{ 200#if !APR_CHARSET_EBCDIC 201 return apr_base64_encode_binary(encoded, (const unsigned char *) string, len); 202#else /* APR_CHARSET_EBCDIC */ 203 int i; 204 char *p; 205 206 p = encoded; 207 for (i = 0; i < len - 2; i += 3) { 208 *p++ = basis_64[(os_toascii[string[i]] >> 2) & 0x3F]; 209 *p++ = basis_64[((os_toascii[string[i]] & 0x3) << 4) | 210 ((int) (os_toascii[string[i + 1]] & 0xF0) >> 4)]; 211 *p++ = basis_64[((os_toascii[string[i + 1]] & 0xF) << 2) | 212 ((int) (os_toascii[string[i + 2]] & 0xC0) >> 6)]; 213 *p++ = basis_64[os_toascii[string[i + 2]] & 0x3F]; 214 } 215 if (i < len) { 216 *p++ = basis_64[(os_toascii[string[i]] >> 2) & 0x3F]; 217 if (i == (len - 1)) { 218 *p++ = basis_64[((os_toascii[string[i]] & 0x3) << 4)]; 219 *p++ = '='; 220 } 221 else { 222 *p++ = basis_64[((os_toascii[string[i]] & 0x3) << 4) | 223 ((int) (os_toascii[string[i + 1]] & 0xF0) >> 4)]; 224 *p++ = basis_64[((os_toascii[string[i + 1]] & 0xF) << 2)]; 225 } 226 *p++ = '='; 227 } 228 229 *p++ = '\0'; 230 return p - encoded; 231#endif /* APR_CHARSET_EBCDIC */ 232} 233 234/* This is the same as apr_base64_encode() except on EBCDIC machines, where 235 * the conversion of the input to ascii is left out. 236 */ 237APU_DECLARE(int) apr_base64_encode_binary(char *encoded, 238 const unsigned char *string, int len) 239{ 240 int i; 241 char *p; 242 243 p = encoded; 244 for (i = 0; i < len - 2; i += 3) { 245 *p++ = basis_64[(string[i] >> 2) & 0x3F]; 246 *p++ = basis_64[((string[i] & 0x3) << 4) | 247 ((int) (string[i + 1] & 0xF0) >> 4)]; 248 *p++ = basis_64[((string[i + 1] & 0xF) << 2) | 249 ((int) (string[i + 2] & 0xC0) >> 6)]; 250 *p++ = basis_64[string[i + 2] & 0x3F]; 251 } 252 if (i < len) { 253 *p++ = basis_64[(string[i] >> 2) & 0x3F]; 254 if (i == (len - 1)) { 255 *p++ = basis_64[((string[i] & 0x3) << 4)]; 256 *p++ = '='; 257 } 258 else { 259 *p++ = basis_64[((string[i] & 0x3) << 4) | 260 ((int) (string[i + 1] & 0xF0) >> 4)]; 261 *p++ = basis_64[((string[i + 1] & 0xF) << 2)]; 262 } 263 *p++ = '='; 264 } 265 266 *p++ = '\0'; 267 return (int)(p - encoded); 268} 269