18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 28c2ecf20Sopenharmony_ci 38c2ecf20Sopenharmony_ci#include <linux/errno.h> 48c2ecf20Sopenharmony_ci 58c2ecf20Sopenharmony_ciint ceph_armor(char *dst, const char *src, const char *end); 68c2ecf20Sopenharmony_ciint ceph_unarmor(char *dst, const char *src, const char *end); 78c2ecf20Sopenharmony_ci 88c2ecf20Sopenharmony_ci/* 98c2ecf20Sopenharmony_ci * base64 encode/decode. 108c2ecf20Sopenharmony_ci */ 118c2ecf20Sopenharmony_ci 128c2ecf20Sopenharmony_cistatic const char *pem_key = 138c2ecf20Sopenharmony_ci "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; 148c2ecf20Sopenharmony_ci 158c2ecf20Sopenharmony_cistatic int encode_bits(int c) 168c2ecf20Sopenharmony_ci{ 178c2ecf20Sopenharmony_ci return pem_key[c]; 188c2ecf20Sopenharmony_ci} 198c2ecf20Sopenharmony_ci 208c2ecf20Sopenharmony_cistatic int decode_bits(char c) 218c2ecf20Sopenharmony_ci{ 228c2ecf20Sopenharmony_ci if (c >= 'A' && c <= 'Z') 238c2ecf20Sopenharmony_ci return c - 'A'; 248c2ecf20Sopenharmony_ci if (c >= 'a' && c <= 'z') 258c2ecf20Sopenharmony_ci return c - 'a' + 26; 268c2ecf20Sopenharmony_ci if (c >= '0' && c <= '9') 278c2ecf20Sopenharmony_ci return c - '0' + 52; 288c2ecf20Sopenharmony_ci if (c == '+') 298c2ecf20Sopenharmony_ci return 62; 308c2ecf20Sopenharmony_ci if (c == '/') 318c2ecf20Sopenharmony_ci return 63; 328c2ecf20Sopenharmony_ci if (c == '=') 338c2ecf20Sopenharmony_ci return 0; /* just non-negative, please */ 348c2ecf20Sopenharmony_ci return -EINVAL; 358c2ecf20Sopenharmony_ci} 368c2ecf20Sopenharmony_ci 378c2ecf20Sopenharmony_ciint ceph_armor(char *dst, const char *src, const char *end) 388c2ecf20Sopenharmony_ci{ 398c2ecf20Sopenharmony_ci int olen = 0; 408c2ecf20Sopenharmony_ci int line = 0; 418c2ecf20Sopenharmony_ci 428c2ecf20Sopenharmony_ci while (src < end) { 438c2ecf20Sopenharmony_ci unsigned char a, b, c; 448c2ecf20Sopenharmony_ci 458c2ecf20Sopenharmony_ci a = *src++; 468c2ecf20Sopenharmony_ci *dst++ = encode_bits(a >> 2); 478c2ecf20Sopenharmony_ci if (src < end) { 488c2ecf20Sopenharmony_ci b = *src++; 498c2ecf20Sopenharmony_ci *dst++ = encode_bits(((a & 3) << 4) | (b >> 4)); 508c2ecf20Sopenharmony_ci if (src < end) { 518c2ecf20Sopenharmony_ci c = *src++; 528c2ecf20Sopenharmony_ci *dst++ = encode_bits(((b & 15) << 2) | 538c2ecf20Sopenharmony_ci (c >> 6)); 548c2ecf20Sopenharmony_ci *dst++ = encode_bits(c & 63); 558c2ecf20Sopenharmony_ci } else { 568c2ecf20Sopenharmony_ci *dst++ = encode_bits((b & 15) << 2); 578c2ecf20Sopenharmony_ci *dst++ = '='; 588c2ecf20Sopenharmony_ci } 598c2ecf20Sopenharmony_ci } else { 608c2ecf20Sopenharmony_ci *dst++ = encode_bits(((a & 3) << 4)); 618c2ecf20Sopenharmony_ci *dst++ = '='; 628c2ecf20Sopenharmony_ci *dst++ = '='; 638c2ecf20Sopenharmony_ci } 648c2ecf20Sopenharmony_ci olen += 4; 658c2ecf20Sopenharmony_ci line += 4; 668c2ecf20Sopenharmony_ci if (line == 64) { 678c2ecf20Sopenharmony_ci line = 0; 688c2ecf20Sopenharmony_ci *(dst++) = '\n'; 698c2ecf20Sopenharmony_ci olen++; 708c2ecf20Sopenharmony_ci } 718c2ecf20Sopenharmony_ci } 728c2ecf20Sopenharmony_ci return olen; 738c2ecf20Sopenharmony_ci} 748c2ecf20Sopenharmony_ci 758c2ecf20Sopenharmony_ciint ceph_unarmor(char *dst, const char *src, const char *end) 768c2ecf20Sopenharmony_ci{ 778c2ecf20Sopenharmony_ci int olen = 0; 788c2ecf20Sopenharmony_ci 798c2ecf20Sopenharmony_ci while (src < end) { 808c2ecf20Sopenharmony_ci int a, b, c, d; 818c2ecf20Sopenharmony_ci 828c2ecf20Sopenharmony_ci if (src[0] == '\n') { 838c2ecf20Sopenharmony_ci src++; 848c2ecf20Sopenharmony_ci continue; 858c2ecf20Sopenharmony_ci } 868c2ecf20Sopenharmony_ci if (src + 4 > end) 878c2ecf20Sopenharmony_ci return -EINVAL; 888c2ecf20Sopenharmony_ci a = decode_bits(src[0]); 898c2ecf20Sopenharmony_ci b = decode_bits(src[1]); 908c2ecf20Sopenharmony_ci c = decode_bits(src[2]); 918c2ecf20Sopenharmony_ci d = decode_bits(src[3]); 928c2ecf20Sopenharmony_ci if (a < 0 || b < 0 || c < 0 || d < 0) 938c2ecf20Sopenharmony_ci return -EINVAL; 948c2ecf20Sopenharmony_ci 958c2ecf20Sopenharmony_ci *dst++ = (a << 2) | (b >> 4); 968c2ecf20Sopenharmony_ci if (src[2] == '=') 978c2ecf20Sopenharmony_ci return olen + 1; 988c2ecf20Sopenharmony_ci *dst++ = ((b & 15) << 4) | (c >> 2); 998c2ecf20Sopenharmony_ci if (src[3] == '=') 1008c2ecf20Sopenharmony_ci return olen + 2; 1018c2ecf20Sopenharmony_ci *dst++ = ((c & 3) << 6) | d; 1028c2ecf20Sopenharmony_ci olen += 3; 1038c2ecf20Sopenharmony_ci src += 4; 1048c2ecf20Sopenharmony_ci } 1058c2ecf20Sopenharmony_ci return olen; 1068c2ecf20Sopenharmony_ci} 107