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