ceph: factor out libceph from Ceph file system
[linux-3.10.git] / net / ceph / armor.c
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 }