]> git.proxmox.com Git - ceph.git/blame - ceph/src/common/armor.c
import quincy beta 17.1.0
[ceph.git] / ceph / src / common / armor.c
CommitLineData
7c673cae
FG
1
2#if defined(__linux__)
3#include <linux/errno.h>
4#else
5#include <sys/errno.h>
6#endif
7
8/*
9 * base64 encode/decode.
10 */
11
12const char *pem_key = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
13
14static int encode_bits(int c)
15{
16 return pem_key[c];
17}
18
19static 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 == '+' || c == '-')
28 return 62;
29 if (c == '/' || c == '_')
30 return 63;
31 if (c == '=')
32 return 0; /* just non-negative, please */
33 return -EINVAL;
34}
35
36static int set_str_val(char **pdst, const char *end, char c)
37{
38 if (*pdst < end) {
39 char *p = *pdst;
40 *p = c;
41 (*pdst)++;
42 } else
43 return -ERANGE;
44
45 return 0;
46}
47
20effc67 48int ceph_armor_line_break(char *dst, char * const dst_end, const char *src, const char *end, int line_width)
7c673cae
FG
49{
50 int olen = 0;
51 int line = 0;
52
53#define SET_DST(c) do { \
54 int __ret = set_str_val(&dst, dst_end, c); \
55 if (__ret < 0) \
56 return __ret; \
57} while (0);
58
59 while (src < end) {
60 unsigned char a;
61
62 a = *src++;
63 SET_DST(encode_bits(a >> 2));
64 if (src < end) {
65 unsigned char b;
66 b = *src++;
67 SET_DST(encode_bits(((a & 3) << 4) | (b >> 4)));
68 if (src < end) {
69 unsigned char c;
70 c = *src++;
71 SET_DST(encode_bits(((b & 15) << 2) |
72 (c >> 6)));
73 SET_DST(encode_bits(c & 63));
74 } else {
75 SET_DST(encode_bits((b & 15) << 2));
76 SET_DST('=');
77 }
78 } else {
79 SET_DST(encode_bits(((a & 3) << 4)));
80 SET_DST('=');
81 SET_DST('=');
82 }
83 olen += 4;
84 line += 4;
85 if (line_width && line == line_width) {
86 line = 0;
87 SET_DST('\n');
88 olen++;
89 }
90 }
91 return olen;
92}
93
20effc67 94int ceph_armor(char *dst, char * const dst_end, const char *src, const char *end)
7c673cae
FG
95{
96 return ceph_armor_line_break(dst, dst_end, src, end, 0);
97}
98
20effc67 99int ceph_unarmor(char *dst, char * const dst_end, const char *src, const char *end)
7c673cae
FG
100{
101 int olen = 0;
102
103 while (src < end) {
104 int a, b, c, d;
105
106 if (src[0] == '\n') {
107 src++;
108 continue;
109 }
110
111 if (src + 4 > end)
112 return -EINVAL;
113 a = decode_bits(src[0]);
114 b = decode_bits(src[1]);
115 c = decode_bits(src[2]);
116 d = decode_bits(src[3]);
117 if (a < 0 || b < 0 || c < 0 || d < 0)
118 return -EINVAL;
119
120 SET_DST((a << 2) | (b >> 4));
121 if (src[2] == '=')
122 return olen + 1;
123 SET_DST(((b & 15) << 4) | (c >> 2));
124 if (src[3] == '=')
125 return olen + 2;
126 SET_DST(((c & 3) << 6) | d);
127 olen += 3;
128 src += 4;
129 }
130 return olen;
131}