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