xref: /linux/net/ceph/armor.c (revision bb9707077b4ee5f77bc9939b057ff8a0d410296f)
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[0] == '\n') {
82 			src++;
83 			continue;
84 		}
85 		if (src + 4 > end)
86 			return -EINVAL;
87 		a = decode_bits(src[0]);
88 		b = decode_bits(src[1]);
89 		c = decode_bits(src[2]);
90 		d = decode_bits(src[3]);
91 		if (a < 0 || b < 0 || c < 0 || d < 0)
92 			return -EINVAL;
93 
94 		*dst++ = (a << 2) | (b >> 4);
95 		if (src[2] == '=')
96 			return olen + 1;
97 		*dst++ = ((b & 15) << 4) | (c >> 2);
98 		if (src[3] == '=')
99 			return olen + 2;
100 		*dst++ = ((c & 3) << 6) | d;
101 		olen += 3;
102 		src += 4;
103 	}
104 	return olen;
105 }
106