@brief Simple Base64 decoder for Basic Auth @param input Base64 encoded string @param output Output buffer (must be at least (inputLen * 3 / 4) + 1 bytes) @param max_output_len Maximum size of output buffer @return Length of decoded data, or -1 on error
| 285 | /// @param max_output_len Maximum size of output buffer |
| 286 | /// @return Length of decoded data, or -1 on error |
| 287 | int decodeBase64(const char* input, char* output, size_t max_output_len) { |
| 288 | static const char base64_chars[] = |
| 289 | "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; |
| 290 | |
| 291 | if (!input || !output || max_output_len == 0) { |
| 292 | return -1; |
| 293 | } |
| 294 | |
| 295 | int in_len = strlen(input); |
| 296 | if (in_len == 0) { |
| 297 | output[0] = '\0'; |
| 298 | return 0; |
| 299 | } |
| 300 | |
| 301 | int out_len = 0; |
| 302 | |
| 303 | for (int i = 0; i < in_len && i + 3 < in_len; i += 4) { |
| 304 | // Get 4 base64 characters |
| 305 | const char* pos_a = strchr(base64_chars, input[i]); |
| 306 | const char* pos_b = strchr(base64_chars, input[i + 1]); |
| 307 | const char* pos_c = (input[i + 2] == '=') ? nullptr : strchr(base64_chars, input[i + 2]); |
| 308 | const char* pos_d = (input[i + 3] == '=') ? nullptr : strchr(base64_chars, input[i + 3]); |
| 309 | |
| 310 | // Check for invalid characters |
| 311 | if (!pos_a || !pos_b) { |
| 312 | return -1; |
| 313 | } |
| 314 | |
| 315 | u32 sextet_a = pos_a - base64_chars; |
| 316 | u32 sextet_b = pos_b - base64_chars; |
| 317 | u32 sextet_c = pos_c ? (pos_c - base64_chars) : 0; |
| 318 | u32 sextet_d = pos_d ? (pos_d - base64_chars) : 0; |
| 319 | |
| 320 | // Combine into 3 bytes |
| 321 | u32 triple = (sextet_a << 18) | (sextet_b << 12) | (sextet_c << 6) | sextet_d; |
| 322 | |
| 323 | // Write output bytes with bounds checking |
| 324 | if (out_len + 1 <= (int)max_output_len) { |
| 325 | output[out_len++] = (triple >> 16) & 0xFF; |
| 326 | } else { |
| 327 | return -1; // Buffer overflow |
| 328 | } |
| 329 | |
| 330 | if (input[i + 2] != '=' && out_len + 1 <= (int)max_output_len) { |
| 331 | output[out_len++] = (triple >> 8) & 0xFF; |
| 332 | } else if (input[i + 2] != '=') { |
| 333 | return -1; // Buffer overflow |
| 334 | } |
| 335 | |
| 336 | if (input[i + 3] != '=' && out_len + 1 <= (int)max_output_len) { |
| 337 | output[out_len++] = triple & 0xFF; |
| 338 | } else if (input[i + 3] != '=') { |
| 339 | return -1; // Buffer overflow |
| 340 | } |
| 341 | } |
| 342 | |
| 343 | // Null terminate |
| 344 | if (out_len < (int)max_output_len) { |
no test coverage detected