162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci 362306a36Sopenharmony_ci#include <linux/errno.h> 462306a36Sopenharmony_ci 562306a36Sopenharmony_ciint ceph_armor(char *dst, const char *src, const char *end); 662306a36Sopenharmony_ciint ceph_unarmor(char *dst, const char *src, const char *end); 762306a36Sopenharmony_ci 862306a36Sopenharmony_ci/* 962306a36Sopenharmony_ci * base64 encode/decode. 1062306a36Sopenharmony_ci */ 1162306a36Sopenharmony_ci 1262306a36Sopenharmony_cistatic const char *pem_key = 1362306a36Sopenharmony_ci "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; 1462306a36Sopenharmony_ci 1562306a36Sopenharmony_cistatic int encode_bits(int c) 1662306a36Sopenharmony_ci{ 1762306a36Sopenharmony_ci return pem_key[c]; 1862306a36Sopenharmony_ci} 1962306a36Sopenharmony_ci 2062306a36Sopenharmony_cistatic int decode_bits(char c) 2162306a36Sopenharmony_ci{ 2262306a36Sopenharmony_ci if (c >= 'A' && c <= 'Z') 2362306a36Sopenharmony_ci return c - 'A'; 2462306a36Sopenharmony_ci if (c >= 'a' && c <= 'z') 2562306a36Sopenharmony_ci return c - 'a' + 26; 2662306a36Sopenharmony_ci if (c >= '0' && c <= '9') 2762306a36Sopenharmony_ci return c - '0' + 52; 2862306a36Sopenharmony_ci if (c == '+') 2962306a36Sopenharmony_ci return 62; 3062306a36Sopenharmony_ci if (c == '/') 3162306a36Sopenharmony_ci return 63; 3262306a36Sopenharmony_ci if (c == '=') 3362306a36Sopenharmony_ci return 0; /* just non-negative, please */ 3462306a36Sopenharmony_ci return -EINVAL; 3562306a36Sopenharmony_ci} 3662306a36Sopenharmony_ci 3762306a36Sopenharmony_ciint ceph_armor(char *dst, const char *src, const char *end) 3862306a36Sopenharmony_ci{ 3962306a36Sopenharmony_ci int olen = 0; 4062306a36Sopenharmony_ci int line = 0; 4162306a36Sopenharmony_ci 4262306a36Sopenharmony_ci while (src < end) { 4362306a36Sopenharmony_ci unsigned char a, b, c; 4462306a36Sopenharmony_ci 4562306a36Sopenharmony_ci a = *src++; 4662306a36Sopenharmony_ci *dst++ = encode_bits(a >> 2); 4762306a36Sopenharmony_ci if (src < end) { 4862306a36Sopenharmony_ci b = *src++; 4962306a36Sopenharmony_ci *dst++ = encode_bits(((a & 3) << 4) | (b >> 4)); 5062306a36Sopenharmony_ci if (src < end) { 5162306a36Sopenharmony_ci c = *src++; 5262306a36Sopenharmony_ci *dst++ = encode_bits(((b & 15) << 2) | 5362306a36Sopenharmony_ci (c >> 6)); 5462306a36Sopenharmony_ci *dst++ = encode_bits(c & 63); 5562306a36Sopenharmony_ci } else { 5662306a36Sopenharmony_ci *dst++ = encode_bits((b & 15) << 2); 5762306a36Sopenharmony_ci *dst++ = '='; 5862306a36Sopenharmony_ci } 5962306a36Sopenharmony_ci } else { 6062306a36Sopenharmony_ci *dst++ = encode_bits(((a & 3) << 4)); 6162306a36Sopenharmony_ci *dst++ = '='; 6262306a36Sopenharmony_ci *dst++ = '='; 6362306a36Sopenharmony_ci } 6462306a36Sopenharmony_ci olen += 4; 6562306a36Sopenharmony_ci line += 4; 6662306a36Sopenharmony_ci if (line == 64) { 6762306a36Sopenharmony_ci line = 0; 6862306a36Sopenharmony_ci *(dst++) = '\n'; 6962306a36Sopenharmony_ci olen++; 7062306a36Sopenharmony_ci } 7162306a36Sopenharmony_ci } 7262306a36Sopenharmony_ci return olen; 7362306a36Sopenharmony_ci} 7462306a36Sopenharmony_ci 7562306a36Sopenharmony_ciint ceph_unarmor(char *dst, const char *src, const char *end) 7662306a36Sopenharmony_ci{ 7762306a36Sopenharmony_ci int olen = 0; 7862306a36Sopenharmony_ci 7962306a36Sopenharmony_ci while (src < end) { 8062306a36Sopenharmony_ci int a, b, c, d; 8162306a36Sopenharmony_ci 8262306a36Sopenharmony_ci if (src[0] == '\n') { 8362306a36Sopenharmony_ci src++; 8462306a36Sopenharmony_ci continue; 8562306a36Sopenharmony_ci } 8662306a36Sopenharmony_ci if (src + 4 > end) 8762306a36Sopenharmony_ci return -EINVAL; 8862306a36Sopenharmony_ci a = decode_bits(src[0]); 8962306a36Sopenharmony_ci b = decode_bits(src[1]); 9062306a36Sopenharmony_ci c = decode_bits(src[2]); 9162306a36Sopenharmony_ci d = decode_bits(src[3]); 9262306a36Sopenharmony_ci if (a < 0 || b < 0 || c < 0 || d < 0) 9362306a36Sopenharmony_ci return -EINVAL; 9462306a36Sopenharmony_ci 9562306a36Sopenharmony_ci *dst++ = (a << 2) | (b >> 4); 9662306a36Sopenharmony_ci if (src[2] == '=') 9762306a36Sopenharmony_ci return olen + 1; 9862306a36Sopenharmony_ci *dst++ = ((b & 15) << 4) | (c >> 2); 9962306a36Sopenharmony_ci if (src[3] == '=') 10062306a36Sopenharmony_ci return olen + 2; 10162306a36Sopenharmony_ci *dst++ = ((c & 3) << 6) | d; 10262306a36Sopenharmony_ci olen += 3; 10362306a36Sopenharmony_ci src += 4; 10462306a36Sopenharmony_ci } 10562306a36Sopenharmony_ci return olen; 10662306a36Sopenharmony_ci} 107