| Sage Weil | 8b6e4f2 | 2010-02-02 16:07:07 -0800 | [diff] [blame] | 1 |  | 
 | 2 | #include <linux/errno.h> | 
 | 3 |  | 
| Yehuda Sadeh | cd84db6 | 2010-06-11 16:58:48 -0700 | [diff] [blame] | 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 |  | 
| Sage Weil | 8b6e4f2 | 2010-02-02 16:07:07 -0800 | [diff] [blame] | 7 | /* | 
 | 8 |  * base64 encode/decode. | 
 | 9 |  */ | 
 | 10 |  | 
| Yehuda Sadeh | cd84db6 | 2010-06-11 16:58:48 -0700 | [diff] [blame] | 11 | static const char *pem_key = | 
 | 12 | 	"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; | 
| Sage Weil | 8b6e4f2 | 2010-02-02 16:07:07 -0800 | [diff] [blame] | 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 | } |