]>
Commit | Line | Data |
---|---|---|
bf34b4af TT |
1 | /* |
2 | * lib/ext2fs/digest_encode.c | |
3 | * | |
4 | * A function to encode a digest using 64 characters that are valid in a | |
5 | * filename per ext2fs rules. | |
6 | * | |
7 | * Written by Uday Savagaonkar, 2014. | |
8 | * | |
9 | * Copyright 2014 Google Inc. All Rights Reserved. | |
10 | * | |
11 | * %Begin-Header% | |
12 | * This file may be redistributed under the terms of the GNU Library | |
13 | * General Public License, version 2. | |
14 | * %End-Header% | |
15 | */ | |
16 | ||
17 | #include "config.h" | |
18 | #if HAVE_SYS_TYPES_H | |
19 | #include <sys/types.h> | |
20 | #endif | |
21 | #include "ext2fs.h" | |
22 | ||
437651ad TT |
23 | static const char *lookup_table = |
24 | "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+,"; | |
25 | ||
bf34b4af TT |
26 | /** |
27 | * ext2fs_digest_encode() - | |
28 | * | |
29 | * Encodes the input digest using characters from the set [a-zA-Z0-9_+]. | |
30 | * The encoded string is roughly 4/3 times the size of the input string. | |
31 | */ | |
437651ad | 32 | int ext2fs_digest_encode(const char *src, int len, char *dst) |
bf34b4af | 33 | { |
437651ad TT |
34 | int i = 0, bits = 0, ac = 0; |
35 | char *cp = dst; | |
bf34b4af | 36 | |
437651ad TT |
37 | while (i < len) { |
38 | ac += (((unsigned char) src[i]) << bits); | |
39 | bits += 8; | |
40 | do { | |
41 | *cp++ = lookup_table[ac & 0x3f]; | |
42 | ac >>= 6; | |
43 | bits -= 6; | |
44 | } while (bits >= 6); | |
45 | i++; | |
bf34b4af | 46 | } |
437651ad TT |
47 | if (bits) |
48 | *cp++ = lookup_table[ac & 0x3f]; | |
49 | return cp - dst; | |
50 | } | |
51 | ||
52 | int ext2fs_digest_decode(const char *src, int len, char *dst) | |
53 | { | |
54 | int i = 0, bits = 0, ac = 0; | |
55 | const char *p; | |
56 | char *cp = dst; | |
57 | ||
58 | while (i < len) { | |
59 | p = strchr(lookup_table, src[i]); | |
60 | if (p == NULL || src[i] == 0) | |
61 | return -1; | |
62 | ac += (p - lookup_table) << bits; | |
63 | bits += 6; | |
64 | if (bits >= 8) { | |
65 | *cp++ = ac & 0xff; | |
66 | ac >>= 8; | |
67 | bits -= 8; | |
68 | } | |
8afaf3be | 69 | i++; |
bf34b4af | 70 | } |
437651ad TT |
71 | if (ac) |
72 | return -1; | |
73 | return cp - dst; | |
bf34b4af TT |
74 | } |
75 | ||
437651ad | 76 | |
bf34b4af TT |
77 | #ifdef UNITTEST |
78 | static const struct { | |
79 | unsigned char d[32]; | |
8afaf3be | 80 | unsigned int len; |
fa04febc | 81 | const char *ed; |
bf34b4af TT |
82 | } tests[] = { |
83 | { { 0xe3, 0xb0, 0xc4, 0x42, 0x98, 0xfc, 0x1c, 0x14, | |
84 | 0x9a, 0xfb, 0xf4, 0xc8, 0x99, 0x6f, 0xb9, 0x24, | |
85 | 0x27, 0xae, 0x41, 0xe4, 0x64, 0x9b, 0x93, 0x4c, | |
8afaf3be | 86 | 0xa4, 0x95, 0x99, 0x1b, 0x78, 0x52, 0xb8, 0x55 }, 32, |
437651ad | 87 | "jDLxChJ,cQhm7TPyZ+WukcirBROZbOJTkWZmbgnU4WF" |
bf34b4af TT |
88 | }, |
89 | { { 0xba, 0x78, 0x16, 0xbf, 0x8f, 0x01, 0xcf, 0xea, | |
90 | 0x41, 0x41, 0x40, 0xde, 0x5d, 0xae, 0x22, 0x23, | |
91 | 0xb0, 0x03, 0x61, 0xa3, 0x96, 0x17, 0x7a, 0x9c, | |
8afaf3be | 92 | 0xb4, 0x10, 0xff, 0x61, 0xf2, 0x00, 0x15, 0xad }, 32, |
437651ad | 93 | "6inF,+YAPreQBBk3d5qIjA7AhNqlXoHn0Cx,hJPAV0K" |
bf34b4af TT |
94 | }, |
95 | { { 0x24, 0x8d, 0x6a, 0x61, 0xd2, 0x06, 0x38, 0xb8, | |
96 | 0xe5, 0xc0, 0x26, 0x93, 0x0c, 0x3e, 0x60, 0x39, | |
97 | 0xa3, 0x3c, 0xe4, 0x59, 0x64, 0xff, 0x21, 0x67, | |
8afaf3be | 98 | 0xf6, 0xec, 0xed, 0xd4, 0x19, 0xdb, 0x06, 0xc1 }, 32, |
437651ad | 99 | "k0oahJtB4gb5AbykM4DY5MKPknFZ,HyZ2ze7Unx2GEM" |
bf34b4af | 100 | }, |
8afaf3be | 101 | { { 0x00, }, 1, |
437651ad | 102 | "AA" |
8afaf3be TT |
103 | }, |
104 | { { 0x01, }, 1, | |
437651ad | 105 | "BA" |
8afaf3be TT |
106 | }, |
107 | { { 0x01, 0x02 }, 2, | |
437651ad | 108 | "BIA" |
8afaf3be TT |
109 | }, |
110 | { { 0x01, 0x02, 0x03 }, 3, | |
437651ad | 111 | "BIwA" |
8afaf3be TT |
112 | }, |
113 | { { 0x01, 0x02, 0x03, 0x04 }, 4, | |
437651ad | 114 | "BIwAEA" |
8afaf3be TT |
115 | }, |
116 | { { 0x01, 0x02, 0x03, 0x04, 0xff }, 5, | |
437651ad | 117 | "BIwAE8P" |
8afaf3be TT |
118 | }, |
119 | { { 0x01, 0x02, 0x03, 0x04, 0xff, 0xfe }, 6, | |
437651ad | 120 | "BIwAE8v," |
8afaf3be TT |
121 | }, |
122 | { { 0x01, 0x02, 0x03, 0x04, 0xff, 0xfe, 0xfd }, 7, | |
437651ad | 123 | "BIwAE8v,9D" |
8afaf3be | 124 | }, |
bf34b4af TT |
125 | }; |
126 | ||
127 | int main(int argc, char **argv) | |
128 | { | |
fa04febc | 129 | int i, ret, len; |
bf34b4af | 130 | int errors = 0; |
fa04febc | 131 | char tmp[1024], tmp2[1024]; |
bf34b4af | 132 | |
437651ad TT |
133 | if (argc == 3 && !strcmp(argv[1], "encode")) { |
134 | memset(tmp, 0, sizeof(tmp)); | |
135 | ext2fs_digest_encode(argv[2], strlen(argv[2]), tmp); | |
136 | puts(tmp); | |
137 | exit(0); | |
138 | } | |
139 | if (argc == 3 && !strcmp(argv[1], "decode")) { | |
140 | memset(tmp, 0, sizeof(tmp)); | |
141 | ret = ext2fs_digest_decode(argv[2], strlen(argv[2]), tmp); | |
142 | puts(tmp); | |
143 | fprintf(stderr, "returned %d\n", ret); | |
144 | exit(0); | |
145 | } | |
bf34b4af | 146 | for (i = 0; i < (int)(sizeof(tests) / sizeof(tests[0])); i++) { |
8afaf3be | 147 | memset(tmp, 0, sizeof(tmp)); |
fa04febc DL |
148 | ret = ext2fs_digest_encode((const char *) tests[i].d, |
149 | tests[i].len, tmp); | |
8afaf3be TT |
150 | len = strlen(tmp); |
151 | printf("Test Digest %d (returned %d): ", i, ret); | |
152 | if (ret != len) { | |
153 | printf("FAILED returned %d, string length was %d\n", | |
154 | ret, len); | |
155 | errors++; | |
437651ad TT |
156 | continue; |
157 | } else if (strcmp(tmp, tests[i].ed) != 0) { | |
8afaf3be TT |
158 | printf("FAILED: got %s, expected %s\n", tmp, |
159 | tests[i].ed); | |
bf34b4af | 160 | errors++; |
437651ad TT |
161 | continue; |
162 | } | |
163 | ret = ext2fs_digest_decode(tmp, len, tmp2); | |
164 | if (ret != tests[i].len) { | |
165 | printf("FAILED decode returned %d, expected %d\n", | |
166 | ret, tests[i].len); | |
167 | errors++; | |
168 | continue; | |
169 | } | |
170 | if (memcmp(tmp2, tests[i].d, ret) != 0) { | |
171 | puts("FAILED: decode mismatched"); | |
172 | errors++; | |
173 | continue; | |
174 | } | |
175 | printf("OK\n"); | |
bf34b4af | 176 | } |
8afaf3be TT |
177 | for (i = 1; i < argc; i++) { |
178 | memset(tmp, 0, sizeof(tmp)); | |
179 | ret = ext2fs_digest_encode(argv[i], strlen(argv[i]), tmp); | |
180 | len = strlen(tmp); | |
181 | printf("Digest of '%s' is '%s' (returned %d, length %d)\n", | |
182 | argv[i], tmp, ret, len); | |
183 | } | |
bf34b4af TT |
184 | return errors; |
185 | } | |
186 | ||
187 | #endif /* UNITTEST */ |