| 1155 | #define BASE64URL_CHAR(x) BASE64URL_CHARS[ (unsigned int)(x) & 0x3fu ] |
| 1156 | |
| 1157 | apr_size_t md_util_base64url_decode(md_data_t *decoded, const char *encoded, |
| 1158 | apr_pool_t *pool) |
| 1159 | { |
| 1160 | const unsigned char *e = (const unsigned char *)encoded; |
| 1161 | const unsigned char *p = e; |
| 1162 | unsigned char *d; |
| 1163 | unsigned int n; |
| 1164 | long len, mlen, remain, i; |
| 1165 | |
| 1166 | while (*p && BASE64URL_UINT6[ *p ] != N6) { |
| 1167 | ++p; |
| 1168 | } |
| 1169 | len = (int)(p - e); |
| 1170 | mlen = (len/4)*4; |
| 1171 | decoded->data = apr_pcalloc(pool, (apr_size_t)len + 1); |
| 1172 | |
| 1173 | i = 0; |
| 1174 | d = (unsigned char*)decoded->data; |
| 1175 | for (; i < mlen; i += 4) { |
| 1176 | n = ((BASE64URL_UINT6[ e[i+0] ] << 18) + |
| 1177 | (BASE64URL_UINT6[ e[i+1] ] << 12) + |
| 1178 | (BASE64URL_UINT6[ e[i+2] ] << 6) + |
| 1179 | (BASE64URL_UINT6[ e[i+3] ])); |
| 1180 | *d++ = (unsigned char)(n >> 16); |
| 1181 | *d++ = (unsigned char)(n >> 8 & 0xffu); |
| 1182 | *d++ = (unsigned char)(n & 0xffu); |
| 1183 | } |
| 1184 | remain = len - mlen; |
| 1185 | switch (remain) { |
| 1186 | case 2: |
| 1187 | n = ((BASE64URL_UINT6[ e[mlen+0] ] << 18) + |
| 1188 | (BASE64URL_UINT6[ e[mlen+1] ] << 12)); |
| 1189 | *d++ = (unsigned char)(n >> 16); |
| 1190 | remain = 1; |
| 1191 | break; |
| 1192 | case 3: |
| 1193 | n = ((BASE64URL_UINT6[ e[mlen+0] ] << 18) + |
| 1194 | (BASE64URL_UINT6[ e[mlen+1] ] << 12) + |
| 1195 | (BASE64URL_UINT6[ e[mlen+2] ] << 6)); |
| 1196 | *d++ = (unsigned char)(n >> 16); |
| 1197 | *d++ = (unsigned char)(n >> 8 & 0xffu); |
| 1198 | remain = 2; |
| 1199 | break; |
| 1200 | default: /* do nothing */ |
| 1201 | break; |
| 1202 | } |
| 1203 | decoded->len = (apr_size_t)(mlen/4*3 + remain); |
| 1204 | return decoded->len; |
| 1205 | } |
| 1206 | |
| 1207 | const char *md_util_base64url_encode(const md_data_t *data, apr_pool_t *pool) |
| 1208 | { |
no outgoing calls
no test coverage detected