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