^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) #include <linux/errno.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) int ceph_armor(char *dst, const char *src, const char *end);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) int ceph_unarmor(char *dst, const char *src, const char *end);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * base64 encode/decode.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) static const char *pem_key =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) static int encode_bits(int c)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) return pem_key[c];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) static int decode_bits(char c)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) if (c >= 'A' && c <= 'Z')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) return c - 'A';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) if (c >= 'a' && c <= 'z')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) return c - 'a' + 26;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) if (c >= '0' && c <= '9')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) return c - '0' + 52;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) if (c == '+')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) return 62;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) if (c == '/')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) return 63;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) if (c == '=')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) return 0; /* just non-negative, please */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) int ceph_armor(char *dst, const char *src, const char *end)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) int olen = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) int line = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) while (src < end) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) unsigned char a, b, c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) a = *src++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) *dst++ = encode_bits(a >> 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) if (src < end) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) b = *src++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) *dst++ = encode_bits(((a & 3) << 4) | (b >> 4));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) if (src < end) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) c = *src++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) *dst++ = encode_bits(((b & 15) << 2) |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) (c >> 6));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) *dst++ = encode_bits(c & 63);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) *dst++ = encode_bits((b & 15) << 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) *dst++ = '=';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) *dst++ = encode_bits(((a & 3) << 4));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) *dst++ = '=';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) *dst++ = '=';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) olen += 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) line += 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) if (line == 64) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) line = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) *(dst++) = '\n';
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) olen++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) return olen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) int ceph_unarmor(char *dst, const char *src, const char *end)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) int olen = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) while (src < end) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) int a, b, c, d;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) if (src[0] == '\n') {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) src++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) if (src + 4 > end)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) a = decode_bits(src[0]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) b = decode_bits(src[1]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) c = decode_bits(src[2]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) d = decode_bits(src[3]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) if (a < 0 || b < 0 || c < 0 || d < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) *dst++ = (a << 2) | (b >> 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) if (src[2] == '=')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) return olen + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) *dst++ = ((b & 15) << 4) | (c >> 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) if (src[3] == '=')
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) return olen + 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) *dst++ = ((c & 3) << 6) | d;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) olen += 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) src += 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) return olen;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) }