]>
Commit | Line | Data |
---|---|---|
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 | ||
12 | const char *pem_key = "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 == '+' || 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 | ||
36 | static 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 | ||
48 | int ceph_armor_line_break(char *dst, const char *dst_end, const char *src, const char *end, int line_width) | |
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 | ||
94 | int ceph_armor(char *dst, const char *dst_end, const char *src, const char *end) | |
95 | { | |
96 | return ceph_armor_line_break(dst, dst_end, src, end, 0); | |
97 | } | |
98 | ||
99 | int ceph_unarmor(char *dst, const char *dst_end, const char *src, const char *end) | |
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 | } |