aboutsummaryrefslogtreecommitdiff
path: root/libbb
diff options
context:
space:
mode:
authorNguyễn Thái Ngọc Duy <pclouds@gmail.com>2011-01-04 19:40:30 +0700
committerNguyễn Thái Ngọc Duy <pclouds@gmail.com>2011-01-04 19:40:30 +0700
commit3b5c308768d76298bb964814ecc34de47bcac0b4 (patch)
tree795340e9d8f5e5bf9e8d895641099af343eec2a0 /libbb
parent2b9a0e715ec459198f486653023d963b79291da7 (diff)
parent5fe2f863b9cee5ab0e7ac873538bce48846dbad8 (diff)
downloadbusybox-w32-3b5c308768d76298bb964814ecc34de47bcac0b4.tar.gz
busybox-w32-3b5c308768d76298bb964814ecc34de47bcac0b4.tar.bz2
busybox-w32-3b5c308768d76298bb964814ecc34de47bcac0b4.zip
Merge commit '06f719fd79fe15ce6fd5431bc58fcb22851de24d^'
Diffstat (limited to 'libbb')
-rw-r--r--libbb/appletlib.c8
-rw-r--r--libbb/md5.c245
-rw-r--r--libbb/procps.c2
-rw-r--r--libbb/pw_encrypt_md5.c32
-rw-r--r--libbb/sha1.c204
-rw-r--r--libbb/uuencode.c76
-rw-r--r--libbb/xfuncs_printf.c2
7 files changed, 355 insertions, 214 deletions
diff --git a/libbb/appletlib.c b/libbb/appletlib.c
index ab1d48c31..3b691f945 100644
--- a/libbb/appletlib.c
+++ b/libbb/appletlib.c
@@ -592,9 +592,11 @@ static const char usr_sbin[] ALIGN1 = "/usr/sbin/";
592static const char *const install_dir[] = { 592static const char *const install_dir[] = {
593 &usr_bin [8], /* "/" */ 593 &usr_bin [8], /* "/" */
594 &usr_bin [4], /* "/bin/" */ 594 &usr_bin [4], /* "/bin/" */
595 &usr_sbin[4], /* "/sbin/" */ 595 &usr_sbin[4] /* "/sbin/" */
596 usr_bin, 596# if !ENABLE_INSTALL_NO_USR
597 usr_sbin 597 ,usr_bin
598 ,usr_sbin
599# endif
598}; 600};
599 601
600 602
diff --git a/libbb/md5.c b/libbb/md5.c
index d8655ba91..051c8ede4 100644
--- a/libbb/md5.c
+++ b/libbb/md5.c
@@ -1,7 +1,7 @@
1/* vi: set sw=4 ts=4: */ 1/* vi: set sw=4 ts=4: */
2/* 2/*
3 * md5.c - Compute MD5 checksum of strings according to the 3 * Compute MD5 checksum of strings according to the
4 * definition of MD5 in RFC 1321 from April 1992. 4 * definition of MD5 in RFC 1321 from April 1992.
5 * 5 *
6 * Written by Ulrich Drepper <drepper@gnu.ai.mit.edu>, 1995. 6 * Written by Ulrich Drepper <drepper@gnu.ai.mit.edu>, 1995.
7 * 7 *
@@ -33,8 +33,7 @@ void FAST_FUNC md5_begin(md5_ctx_t *ctx)
33 ctx->B = 0xefcdab89; 33 ctx->B = 0xefcdab89;
34 ctx->C = 0x98badcfe; 34 ctx->C = 0x98badcfe;
35 ctx->D = 0x10325476; 35 ctx->D = 0x10325476;
36 ctx->total = 0; 36 ctx->total64 = 0;
37 ctx->buflen = 0;
38} 37}
39 38
40/* These are the four functions used in the four steps of the MD5 algorithm 39/* These are the four functions used in the four steps of the MD5 algorithm
@@ -49,13 +48,14 @@ void FAST_FUNC md5_begin(md5_ctx_t *ctx)
49 48
50#define rotl32(w, s) (((w) << (s)) | ((w) >> (32 - (s)))) 49#define rotl32(w, s) (((w) << (s)) | ((w) >> (32 - (s))))
51 50
52/* Hash a single block, 64 bytes long and 4-byte aligned. */ 51/* Hash a single block, 64 bytes long and 4-byte aligned */
53static void md5_hash_block(const void *buffer, md5_ctx_t *ctx) 52static void md5_process_block64(md5_ctx_t *ctx)
54{ 53{
55 uint32_t correct_words[16];
56 const uint32_t *words = buffer;
57
58#if MD5_SIZE_VS_SPEED > 0 54#if MD5_SIZE_VS_SPEED > 0
55 /* Before we start, one word to the strange constants.
56 They are defined in RFC 1321 as
57 T[i] = (int)(4294967296.0 * fabs(sin(i))), i=1..64
58 */
59 static const uint32_t C_array[] = { 59 static const uint32_t C_array[] = {
60 /* round 1 */ 60 /* round 1 */
61 0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee, 61 0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee,
@@ -64,7 +64,7 @@ static void md5_hash_block(const void *buffer, md5_ctx_t *ctx)
64 0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821, 64 0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821,
65 /* round 2 */ 65 /* round 2 */
66 0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa, 66 0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa,
67 0xd62f105d, 0x2441453, 0xd8a1e681, 0xe7d3fbc8, 67 0xd62f105d, 0x02441453, 0xd8a1e681, 0xe7d3fbc8,
68 0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed, 68 0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed,
69 0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a, 69 0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a,
70 /* round 3 */ 70 /* round 3 */
@@ -86,40 +86,33 @@ static void md5_hash_block(const void *buffer, md5_ctx_t *ctx)
86 5, 8, 11, 14, 1, 4, 7, 10, 13, 0, 3, 6, 9, 12, 15, 2, /* 3 */ 86 5, 8, 11, 14, 1, 4, 7, 10, 13, 0, 3, 6, 9, 12, 15, 2, /* 3 */
87 0, 7, 14, 5, 12, 3, 10, 1, 8, 15, 6, 13, 4, 11, 2, 9 /* 4 */ 87 0, 7, 14, 5, 12, 3, 10, 1, 8, 15, 6, 13, 4, 11, 2, 9 /* 4 */
88 }; 88 };
89# if MD5_SIZE_VS_SPEED > 1
90 static const char S_array[] ALIGN1 = {
91 7, 12, 17, 22,
92 5, 9, 14, 20,
93 4, 11, 16, 23,
94 6, 10, 15, 21
95 };
96# endif /* MD5_SIZE_VS_SPEED > 1 */
97#endif 89#endif
90 uint32_t *words = (void*) ctx->wbuffer;
98 uint32_t A = ctx->A; 91 uint32_t A = ctx->A;
99 uint32_t B = ctx->B; 92 uint32_t B = ctx->B;
100 uint32_t C = ctx->C; 93 uint32_t C = ctx->C;
101 uint32_t D = ctx->D; 94 uint32_t D = ctx->D;
102 95
103 /* Process all bytes in the buffer with 64 bytes in each round of 96#if MD5_SIZE_VS_SPEED >= 2 /* 2 or 3 */
104 the loop. */
105 uint32_t *cwp = correct_words;
106 uint32_t A_save = A;
107 uint32_t B_save = B;
108 uint32_t C_save = C;
109 uint32_t D_save = D;
110 97
111#if MD5_SIZE_VS_SPEED > 1 98 static const char S_array[] ALIGN1 = {
99 7, 12, 17, 22,
100 5, 9, 14, 20,
101 4, 11, 16, 23,
102 6, 10, 15, 21
103 };
112 const uint32_t *pc; 104 const uint32_t *pc;
113 const char *pp; 105 const char *pp;
114 const char *ps; 106 const char *ps;
115 int i; 107 int i;
116 uint32_t temp; 108 uint32_t temp;
117 109
110# if BB_BIG_ENDIAN
118 for (i = 0; i < 16; i++) 111 for (i = 0; i < 16; i++)
119 cwp[i] = SWAP_LE32(words[i]); 112 words[i] = SWAP_LE32(words[i]);
120 words += 16; 113# endif
121 114
122# if MD5_SIZE_VS_SPEED > 2 115# if MD5_SIZE_VS_SPEED == 3
123 pc = C_array; 116 pc = C_array;
124 pp = P_array; 117 pp = P_array;
125 ps = S_array - 4; 118 ps = S_array - 4;
@@ -141,7 +134,7 @@ static void md5_hash_block(const void *buffer, md5_ctx_t *ctx)
141 case 3: 134 case 3:
142 temp += FI(B, C, D); 135 temp += FI(B, C, D);
143 } 136 }
144 temp += cwp[(int) (*pp++)] + *pc++; 137 temp += words[(int) (*pp++)] + *pc++;
145 temp = rotl32(temp, ps[i & 3]); 138 temp = rotl32(temp, ps[i & 3]);
146 temp += B; 139 temp += B;
147 A = D; 140 A = D;
@@ -149,13 +142,13 @@ static void md5_hash_block(const void *buffer, md5_ctx_t *ctx)
149 C = B; 142 C = B;
150 B = temp; 143 B = temp;
151 } 144 }
152# else 145# else /* MD5_SIZE_VS_SPEED == 2 */
153 pc = C_array; 146 pc = C_array;
154 pp = P_array; 147 pp = P_array;
155 ps = S_array; 148 ps = S_array;
156 149
157 for (i = 0; i < 16; i++) { 150 for (i = 0; i < 16; i++) {
158 temp = A + FF(B, C, D) + cwp[(int) (*pp++)] + *pc++; 151 temp = A + FF(B, C, D) + words[(int) (*pp++)] + *pc++;
159 temp = rotl32(temp, ps[i & 3]); 152 temp = rotl32(temp, ps[i & 3]);
160 temp += B; 153 temp += B;
161 A = D; 154 A = D;
@@ -165,7 +158,7 @@ static void md5_hash_block(const void *buffer, md5_ctx_t *ctx)
165 } 158 }
166 ps += 4; 159 ps += 4;
167 for (i = 0; i < 16; i++) { 160 for (i = 0; i < 16; i++) {
168 temp = A + FG(B, C, D) + cwp[(int) (*pp++)] + *pc++; 161 temp = A + FG(B, C, D) + words[(int) (*pp++)] + *pc++;
169 temp = rotl32(temp, ps[i & 3]); 162 temp = rotl32(temp, ps[i & 3]);
170 temp += B; 163 temp += B;
171 A = D; 164 A = D;
@@ -175,7 +168,7 @@ static void md5_hash_block(const void *buffer, md5_ctx_t *ctx)
175 } 168 }
176 ps += 4; 169 ps += 4;
177 for (i = 0; i < 16; i++) { 170 for (i = 0; i < 16; i++) {
178 temp = A + FH(B, C, D) + cwp[(int) (*pp++)] + *pc++; 171 temp = A + FH(B, C, D) + words[(int) (*pp++)] + *pc++;
179 temp = rotl32(temp, ps[i & 3]); 172 temp = rotl32(temp, ps[i & 3]);
180 temp += B; 173 temp += B;
181 A = D; 174 A = D;
@@ -185,7 +178,7 @@ static void md5_hash_block(const void *buffer, md5_ctx_t *ctx)
185 } 178 }
186 ps += 4; 179 ps += 4;
187 for (i = 0; i < 16; i++) { 180 for (i = 0; i < 16; i++) {
188 temp = A + FI(B, C, D) + cwp[(int) (*pp++)] + *pc++; 181 temp = A + FI(B, C, D) + words[(int) (*pp++)] + *pc++;
189 temp = rotl32(temp, ps[i & 3]); 182 temp = rotl32(temp, ps[i & 3]);
190 temp += B; 183 temp += B;
191 A = D; 184 A = D;
@@ -193,35 +186,41 @@ static void md5_hash_block(const void *buffer, md5_ctx_t *ctx)
193 C = B; 186 C = B;
194 B = temp; 187 B = temp;
195 } 188 }
189# endif
190 /* Add checksum to the starting values */
191 ctx->A += A;
192 ctx->B += B;
193 ctx->C += C;
194 ctx->D += D;
195
196#else /* MD5_SIZE_VS_SPEED == 0 or 1 */
197
198 uint32_t A_save = A;
199 uint32_t B_save = B;
200 uint32_t C_save = C;
201 uint32_t D_save = D;
202# if MD5_SIZE_VS_SPEED == 1
203 const uint32_t *pc;
204 const char *pp;
205 int i;
206# endif
196 207
197# endif /* MD5_SIZE_VS_SPEED > 2 */
198#else
199 /* First round: using the given function, the context and a constant 208 /* First round: using the given function, the context and a constant
200 the next context is computed. Because the algorithms processing 209 the next context is computed. Because the algorithm's processing
201 unit is a 32-bit word and it is determined to work on words in 210 unit is a 32-bit word and it is determined to work on words in
202 little endian byte order we perhaps have to change the byte order 211 little endian byte order we perhaps have to change the byte order
203 before the computation. To reduce the work for the next steps 212 before the computation. To reduce the work for the next steps
204 we store the swapped words in the array CORRECT_WORDS. */ 213 we save swapped words in WORDS array. */
214# undef OP
205# define OP(a, b, c, d, s, T) \ 215# define OP(a, b, c, d, s, T) \
206 do { \ 216 do { \
207 a += FF(b, c, d) + (*cwp++ = SWAP_LE32(*words)) + T; \ 217 a += FF(b, c, d) + (*words IF_BIG_ENDIAN(= SWAP_LE32(*words))) + T; \
208 ++words; \ 218 words++; \
209 a = rotl32(a, s); \ 219 a = rotl32(a, s); \
210 a += b; \ 220 a += b; \
211 } while (0) 221 } while (0)
212 222
213 /* Before we start, one word to the strange constants. 223 /* Round 1 */
214 They are defined in RFC 1321 as
215 T[i] = (int)(4294967296.0 * fabs(sin(i))), i=1..64
216 */
217
218# if MD5_SIZE_VS_SPEED == 1
219 const uint32_t *pc;
220 const char *pp;
221 int i;
222# endif /* MD5_SIZE_VS_SPEED */
223
224 /* Round 1. */
225# if MD5_SIZE_VS_SPEED == 1 224# if MD5_SIZE_VS_SPEED == 1
226 pc = C_array; 225 pc = C_array;
227 for (i = 0; i < 4; i++) { 226 for (i = 0; i < 4; i++) {
@@ -247,20 +246,21 @@ static void md5_hash_block(const void *buffer, md5_ctx_t *ctx)
247 OP(D, A, B, C, 12, 0xfd987193); 246 OP(D, A, B, C, 12, 0xfd987193);
248 OP(C, D, A, B, 17, 0xa679438e); 247 OP(C, D, A, B, 17, 0xa679438e);
249 OP(B, C, D, A, 22, 0x49b40821); 248 OP(B, C, D, A, 22, 0x49b40821);
250# endif /* MD5_SIZE_VS_SPEED == 1 */ 249# endif
250 words -= 16;
251 251
252 /* For the second to fourth round we have the possibly swapped words 252 /* For the second to fourth round we have the possibly swapped words
253 in CORRECT_WORDS. Redefine the macro to take an additional first 253 in WORDS. Redefine the macro to take an additional first
254 argument specifying the function to use. */ 254 argument specifying the function to use. */
255# undef OP 255# undef OP
256# define OP(f, a, b, c, d, k, s, T) \ 256# define OP(f, a, b, c, d, k, s, T) \
257 do { \ 257 do { \
258 a += f(b, c, d) + correct_words[k] + T; \ 258 a += f(b, c, d) + words[k] + T; \
259 a = rotl32(a, s); \ 259 a = rotl32(a, s); \
260 a += b; \ 260 a += b; \
261 } while (0) 261 } while (0)
262 262
263 /* Round 2. */ 263 /* Round 2 */
264# if MD5_SIZE_VS_SPEED == 1 264# if MD5_SIZE_VS_SPEED == 1
265 pp = P_array; 265 pp = P_array;
266 for (i = 0; i < 4; i++) { 266 for (i = 0; i < 4; i++) {
@@ -286,9 +286,9 @@ static void md5_hash_block(const void *buffer, md5_ctx_t *ctx)
286 OP(FG, D, A, B, C, 2, 9, 0xfcefa3f8); 286 OP(FG, D, A, B, C, 2, 9, 0xfcefa3f8);
287 OP(FG, C, D, A, B, 7, 14, 0x676f02d9); 287 OP(FG, C, D, A, B, 7, 14, 0x676f02d9);
288 OP(FG, B, C, D, A, 12, 20, 0x8d2a4c8a); 288 OP(FG, B, C, D, A, 12, 20, 0x8d2a4c8a);
289# endif /* MD5_SIZE_VS_SPEED == 1 */ 289# endif
290 290
291 /* Round 3. */ 291 /* Round 3 */
292# if MD5_SIZE_VS_SPEED == 1 292# if MD5_SIZE_VS_SPEED == 1
293 for (i = 0; i < 4; i++) { 293 for (i = 0; i < 4; i++) {
294 OP(FH, A, B, C, D, (int) (*pp++), 4, *pc++); 294 OP(FH, A, B, C, D, (int) (*pp++), 4, *pc++);
@@ -313,9 +313,9 @@ static void md5_hash_block(const void *buffer, md5_ctx_t *ctx)
313 OP(FH, D, A, B, C, 12, 11, 0xe6db99e5); 313 OP(FH, D, A, B, C, 12, 11, 0xe6db99e5);
314 OP(FH, C, D, A, B, 15, 16, 0x1fa27cf8); 314 OP(FH, C, D, A, B, 15, 16, 0x1fa27cf8);
315 OP(FH, B, C, D, A, 2, 23, 0xc4ac5665); 315 OP(FH, B, C, D, A, 2, 23, 0xc4ac5665);
316# endif /* MD5_SIZE_VS_SPEED == 1 */ 316# endif
317 317
318 /* Round 4. */ 318 /* Round 4 */
319# if MD5_SIZE_VS_SPEED == 1 319# if MD5_SIZE_VS_SPEED == 1
320 for (i = 0; i < 4; i++) { 320 for (i = 0; i < 4; i++) {
321 OP(FI, A, B, C, D, (int) (*pp++), 6, *pc++); 321 OP(FI, A, B, C, D, (int) (*pp++), 6, *pc++);
@@ -340,52 +340,62 @@ static void md5_hash_block(const void *buffer, md5_ctx_t *ctx)
340 OP(FI, D, A, B, C, 11, 10, 0xbd3af235); 340 OP(FI, D, A, B, C, 11, 10, 0xbd3af235);
341 OP(FI, C, D, A, B, 2, 15, 0x2ad7d2bb); 341 OP(FI, C, D, A, B, 2, 15, 0x2ad7d2bb);
342 OP(FI, B, C, D, A, 9, 21, 0xeb86d391); 342 OP(FI, B, C, D, A, 9, 21, 0xeb86d391);
343# endif /* MD5_SIZE_VS_SPEED == 1 */ 343# endif
344#endif /* MD5_SIZE_VS_SPEED > 1 */ 344 /* Add checksum to the starting values */
345 345 ctx->A = A_save + A;
346 /* Add the starting values of the context. */ 346 ctx->B = B_save + B;
347 A += A_save; 347 ctx->C = C_save + C;
348 B += B_save; 348 ctx->D = D_save + D;
349 C += C_save; 349#endif
350 D += D_save;
351
352 /* Put checksum in context given as argument. */
353 ctx->A = A;
354 ctx->B = B;
355 ctx->C = C;
356 ctx->D = D;
357} 350}
358 351
359/* Feed data through a temporary buffer to call md5_hash_aligned_block() 352/* Feed data through a temporary buffer to call md5_hash_aligned_block()
360 * with chunks of data that are 4-byte aligned and a multiple of 64 bytes. 353 * with chunks of data that are 4-byte aligned and a multiple of 64 bytes.
361 * This function's internal buffer remembers previous data until it has 64 354 * This function's internal buffer remembers previous data until it has 64
362 * bytes worth to pass on. Call md5_end() to flush this buffer. */ 355 * bytes worth to pass on. Call md5_end() to flush this buffer. */
363void FAST_FUNC md5_hash(const void *buffer, size_t len, md5_ctx_t *ctx) 356void FAST_FUNC md5_hash(md5_ctx_t *ctx, const void *buffer, size_t len)
364{ 357{
365 char *buf = (char *)buffer; 358 unsigned bufpos = ctx->total64 & 63;
359 unsigned remaining;
366 360
367 /* RFC 1321 specifies the possible length of the file up to 2^64 bits, 361 /* RFC 1321 specifies the possible length of the file up to 2^64 bits.
368 * Here we only track the number of bytes. */ 362 * Here we only track the number of bytes. */
369 ctx->total += len; 363 ctx->total64 += len;
370 364#if 0
371 /* Process all input. */ 365 remaining = 64 - bufpos;
372 while (len) { 366
373 unsigned i = 64 - ctx->buflen; 367 /* Hash whole blocks */
374 368 while (len >= remaining) {
375 /* Copy data into aligned buffer. */ 369 memcpy(ctx->wbuffer + bufpos, buffer, remaining);
376 if (i > len) 370 buffer = (const char *)buffer + remaining;
377 i = len; 371 len -= remaining;
378 memcpy(ctx->buffer + ctx->buflen, buf, i); 372 remaining = 64;
379 len -= i; 373 bufpos = 0;
380 ctx->buflen += i; 374 md5_process_block64(ctx);
381 buf += i; 375 }
382 376
383 /* When buffer fills up, process it. */ 377 /* Save last, partial blosk */
384 if (ctx->buflen == 64) { 378 memcpy(ctx->wbuffer + bufpos, buffer, len);
385 md5_hash_block(ctx->buffer, ctx); 379#else
386 ctx->buflen = 0; 380 /* Tiny bit smaller code */
387 } 381 while (1) {
382 remaining = 64 - bufpos;
383 if (remaining > len)
384 remaining = len;
385 /* Copy data into aligned buffer */
386 memcpy(ctx->wbuffer + bufpos, buffer, remaining);
387 len -= remaining;
388 buffer = (const char *)buffer + remaining;
389 bufpos += remaining;
390 /* clever way to do "if (bufpos != 64) break; ... ; bufpos = 0;" */
391 bufpos -= 64;
392 if (bufpos != 0)
393 break;
394 /* Buffer is filled up, process it */
395 md5_process_block64(ctx);
396 /*bufpos = 0; - already is */
388 } 397 }
398#endif
389} 399}
390 400
391/* Process the remaining bytes in the buffer and put result from CTX 401/* Process the remaining bytes in the buffer and put result from CTX
@@ -393,26 +403,31 @@ void FAST_FUNC md5_hash(const void *buffer, size_t len, md5_ctx_t *ctx)
393 * endian byte order, so that a byte-wise output yields to the wanted 403 * endian byte order, so that a byte-wise output yields to the wanted
394 * ASCII representation of the message digest. 404 * ASCII representation of the message digest.
395 */ 405 */
396void FAST_FUNC md5_end(void *resbuf, md5_ctx_t *ctx) 406void FAST_FUNC md5_end(md5_ctx_t *ctx, void *resbuf)
397{ 407{
398 char *buf = ctx->buffer; 408 unsigned bufpos = ctx->total64 & 63;
399 int i; 409 /* Pad the buffer to the next 64-byte boundary with 0x80,0,0,0... */
400 410 ctx->wbuffer[bufpos++] = 0x80;
401 /* Pad data to block size. */ 411
402 buf[ctx->buflen++] = 0x80; 412 /* This loop iterates either once or twice, no more, no less */
403 memset(buf + ctx->buflen, 0, 128 - ctx->buflen); 413 while (1) {
404 414 unsigned remaining = 64 - bufpos;
405 /* Put the 64-bit file length in *bits* at the end of the buffer. */ 415 memset(ctx->wbuffer + bufpos, 0, remaining);
406 ctx->total <<= 3; 416 /* Do we have enough space for the length count? */
407 if (ctx->buflen > 56) 417 if (remaining >= 8) {
408 buf += 64; 418 /* Store the 64-bit counter of bits in the buffer in BE format */
409 for (i = 0; i < 8; i++) 419 uint64_t t = ctx->total64 << 3;
410 buf[56 + i] = ctx->total >> (i*8); 420 unsigned i;
411 421 for (i = 0; i < 8; i++) {
412 /* Process last bytes. */ 422 ctx->wbuffer[56 + i] = t;
413 if (buf != ctx->buffer) 423 t >>= 8;
414 md5_hash_block(ctx->buffer, ctx); 424 }
415 md5_hash_block(buf, ctx); 425 }
426 md5_process_block64(ctx);
427 if (remaining >= 8)
428 break;
429 bufpos = 0;
430 }
416 431
417 /* The MD5 result is in little endian byte order. 432 /* The MD5 result is in little endian byte order.
418 * We (ab)use the fact that A-D are consecutive in memory. 433 * We (ab)use the fact that A-D are consecutive in memory.
diff --git a/libbb/procps.c b/libbb/procps.c
index 7ffcd8dbc..ec43b221e 100644
--- a/libbb/procps.c
+++ b/libbb/procps.c
@@ -121,7 +121,7 @@ void FAST_FUNC free_procps_scan(procps_status_t* sp)
121 free(sp); 121 free(sp);
122} 122}
123 123
124#if ENABLE_FEATURE_TOPMEM 124#if ENABLE_FEATURE_TOPMEM || ENABLE_PMAP
125static unsigned long fast_strtoul_16(char **endptr) 125static unsigned long fast_strtoul_16(char **endptr)
126{ 126{
127 unsigned char c; 127 unsigned char c;
diff --git a/libbb/pw_encrypt_md5.c b/libbb/pw_encrypt_md5.c
index 58964b567..889e09cab 100644
--- a/libbb/pw_encrypt_md5.c
+++ b/libbb/pw_encrypt_md5.c
@@ -92,10 +92,10 @@ md5_crypt(char result[MD5_OUT_BUFSIZE], const unsigned char *pw, const unsigned
92 /* Hash. the password first, since that is what is most unknown */ 92 /* Hash. the password first, since that is what is most unknown */
93 md5_begin(&ctx); 93 md5_begin(&ctx);
94 pw_len = strlen((char*)pw); 94 pw_len = strlen((char*)pw);
95 md5_hash(pw, pw_len, &ctx); 95 md5_hash(&ctx, pw, pw_len);
96 96
97 /* Then the salt including "$1$" */ 97 /* Then the salt including "$1$" */
98 md5_hash(salt, sl, &ctx); 98 md5_hash(&ctx, salt, sl);
99 99
100 /* Copy salt to result; skip "$1$" */ 100 /* Copy salt to result; skip "$1$" */
101 memcpy(result, salt, sl); 101 memcpy(result, salt, sl);
@@ -105,19 +105,19 @@ md5_crypt(char result[MD5_OUT_BUFSIZE], const unsigned char *pw, const unsigned
105 105
106 /* Then just as many characters of the MD5(pw, salt, pw) */ 106 /* Then just as many characters of the MD5(pw, salt, pw) */
107 md5_begin(&ctx1); 107 md5_begin(&ctx1);
108 md5_hash(pw, pw_len, &ctx1); 108 md5_hash(&ctx1, pw, pw_len);
109 md5_hash(salt, sl, &ctx1); 109 md5_hash(&ctx1, salt, sl);
110 md5_hash(pw, pw_len, &ctx1); 110 md5_hash(&ctx1, pw, pw_len);
111 md5_end(final, &ctx1); 111 md5_end(&ctx1, final);
112 for (pl = pw_len; pl > 0; pl -= 16) 112 for (pl = pw_len; pl > 0; pl -= 16)
113 md5_hash(final, pl > 16 ? 16 : pl, &ctx); 113 md5_hash(&ctx, final, pl > 16 ? 16 : pl);
114 114
115 /* Then something really weird... */ 115 /* Then something really weird... */
116 memset(final, 0, sizeof(final)); 116 memset(final, 0, sizeof(final));
117 for (i = pw_len; i; i >>= 1) { 117 for (i = pw_len; i; i >>= 1) {
118 md5_hash(((i & 1) ? final : (const unsigned char *) pw), 1, &ctx); 118 md5_hash(&ctx, ((i & 1) ? final : (const unsigned char *) pw), 1);
119 } 119 }
120 md5_end(final, &ctx); 120 md5_end(&ctx, final);
121 121
122 /* And now, just to make sure things don't run too fast. 122 /* And now, just to make sure things don't run too fast.
123 * On a 60 Mhz Pentium this takes 34 msec, so you would 123 * On a 60 Mhz Pentium this takes 34 msec, so you would
@@ -126,21 +126,21 @@ md5_crypt(char result[MD5_OUT_BUFSIZE], const unsigned char *pw, const unsigned
126 for (i = 0; i < 1000; i++) { 126 for (i = 0; i < 1000; i++) {
127 md5_begin(&ctx1); 127 md5_begin(&ctx1);
128 if (i & 1) 128 if (i & 1)
129 md5_hash(pw, pw_len, &ctx1); 129 md5_hash(&ctx1, pw, pw_len);
130 else 130 else
131 md5_hash(final, 16, &ctx1); 131 md5_hash(&ctx1, final, 16);
132 132
133 if (i % 3) 133 if (i % 3)
134 md5_hash(salt, sl, &ctx1); 134 md5_hash(&ctx1, salt, sl);
135 135
136 if (i % 7) 136 if (i % 7)
137 md5_hash(pw, pw_len, &ctx1); 137 md5_hash(&ctx1, pw, pw_len);
138 138
139 if (i & 1) 139 if (i & 1)
140 md5_hash(final, 16, &ctx1); 140 md5_hash(&ctx1, final, 16);
141 else 141 else
142 md5_hash(pw, pw_len, &ctx1); 142 md5_hash(&ctx1, pw, pw_len);
143 md5_end(final, &ctx1); 143 md5_end(&ctx1, final);
144 } 144 }
145 145
146 p = result + sl + 4; /* 12 bytes max (sl is up to 8 bytes) */ 146 p = result + sl + 4; /* 12 bytes max (sl is up to 8 bytes) */
diff --git a/libbb/sha1.c b/libbb/sha1.c
index beeb70cf6..d79291148 100644
--- a/libbb/sha1.c
+++ b/libbb/sha1.c
@@ -30,11 +30,29 @@
30 30
31#include "libbb.h" 31#include "libbb.h"
32 32
33#define rotl32(x,n) (((x) << (n)) | ((x) >> (32 - (n)))) 33/* gcc 4.2.1 optimizes rotr64 better with inline than with macro
34#define rotr32(x,n) (((x) >> (n)) | ((x) << (32 - (n)))) 34 * (for rotX32, there is no difference). Why? My guess is that
35/* for sha512: */ 35 * macro requires clever common subexpression elimination heuristics
36#define rotr64(x,n) (((x) >> (n)) | ((x) << (64 - (n)))) 36 * in gcc, while inline basically forces it to happen.
37 */
38//#define rotl32(x,n) (((x) << (n)) | ((x) >> (32 - (n))))
39static ALWAYS_INLINE uint32_t rotl32(uint32_t x, unsigned n)
40{
41 return (x << n) | (x >> (32 - n));
42}
43//#define rotr32(x,n) (((x) >> (n)) | ((x) << (32 - (n))))
44static ALWAYS_INLINE uint32_t rotr32(uint32_t x, unsigned n)
45{
46 return (x >> n) | (x << (32 - n));
47}
48/* rotr64 in needed for sha512 only: */
49//#define rotr64(x,n) (((x) >> (n)) | ((x) << (64 - (n))))
50static ALWAYS_INLINE uint64_t rotr64(uint64_t x, unsigned n)
51{
52 return (x >> n) | (x << (64 - n));
53}
37#if BB_LITTLE_ENDIAN 54#if BB_LITTLE_ENDIAN
55/* ALWAYS_INLINE below would hurt code size, using plain inline: */
38static inline uint64_t hton64(uint64_t v) 56static inline uint64_t hton64(uint64_t v)
39{ 57{
40 return (((uint64_t)htonl(v)) << 32) | htonl(v >> 32); 58 return (((uint64_t)htonl(v)) << 32) | htonl(v >> 32);
@@ -44,14 +62,6 @@ static inline uint64_t hton64(uint64_t v)
44#endif 62#endif
45#define ntoh64(v) hton64(v) 63#define ntoh64(v) hton64(v)
46 64
47/* To check alignment gcc has an appropriate operator. Other
48 compilers don't. */
49#if defined(__GNUC__) && __GNUC__ >= 2
50# define UNALIGNED_P(p,type) (((uintptr_t) p) % __alignof__(type) != 0)
51#else
52# define UNALIGNED_P(p,type) (((uintptr_t) p) % sizeof(type) != 0)
53#endif
54
55 65
56/* Some arch headers have conflicting defines */ 66/* Some arch headers have conflicting defines */
57#undef ch 67#undef ch
@@ -65,11 +75,8 @@ static void FAST_FUNC sha1_process_block64(sha1_ctx_t *ctx)
65 uint32_t W[80], a, b, c, d, e; 75 uint32_t W[80], a, b, c, d, e;
66 const uint32_t *words = (uint32_t*) ctx->wbuffer; 76 const uint32_t *words = (uint32_t*) ctx->wbuffer;
67 77
68 for (t = 0; t < 16; ++t) { 78 for (t = 0; t < 16; ++t)
69 W[t] = ntohl(*words); 79 W[t] = ntohl(words[t]);
70 words++;
71 }
72
73 for (/*t = 16*/; t < 80; ++t) { 80 for (/*t = 16*/; t < 80; ++t) {
74 uint32_t T = W[t - 3] ^ W[t - 8] ^ W[t - 14] ^ W[t - 16]; 81 uint32_t T = W[t - 3] ^ W[t - 8] ^ W[t - 14] ^ W[t - 16];
75 W[t] = rotl32(T, 1); 82 W[t] = rotl32(T, 1);
@@ -190,11 +197,8 @@ static void FAST_FUNC sha256_process_block64(sha256_ctx_t *ctx)
190#define R1(x) (rotr32(x, 17) ^ rotr32(x, 19) ^ (x >> 10)) 197#define R1(x) (rotr32(x, 17) ^ rotr32(x, 19) ^ (x >> 10))
191 198
192 /* Compute the message schedule according to FIPS 180-2:6.2.2 step 2. */ 199 /* Compute the message schedule according to FIPS 180-2:6.2.2 step 2. */
193 for (t = 0; t < 16; ++t) { 200 for (t = 0; t < 16; ++t)
194 W[t] = ntohl(*words); 201 W[t] = ntohl(words[t]);
195 words++;
196 }
197
198 for (/*t = 16*/; t < 64; ++t) 202 for (/*t = 16*/; t < 64; ++t)
199 W[t] = R1(W[t - 2]) + W[t - 7] + R0(W[t - 15]) + W[t - 16]; 203 W[t] = R1(W[t - 2]) + W[t - 7] + R0(W[t - 15]) + W[t - 16];
200 204
@@ -269,10 +273,8 @@ static void FAST_FUNC sha512_process_block128(sha512_ctx_t *ctx)
269#define R1(x) (rotr64(x, 19) ^ rotr64(x, 61) ^ (x >> 6)) 273#define R1(x) (rotr64(x, 19) ^ rotr64(x, 61) ^ (x >> 6))
270 274
271 /* Compute the message schedule according to FIPS 180-2:6.3.2 step 2. */ 275 /* Compute the message schedule according to FIPS 180-2:6.3.2 step 2. */
272 for (t = 0; t < 16; ++t) { 276 for (t = 0; t < 16; ++t)
273 W[t] = ntoh64(*words); 277 W[t] = ntoh64(words[t]);
274 words++;
275 }
276 for (/*t = 16*/; t < 80; ++t) 278 for (/*t = 16*/; t < 80; ++t)
277 W[t] = R1(W[t - 2]) + W[t - 7] + R0(W[t - 15]) + W[t - 16]; 279 W[t] = R1(W[t - 2]) + W[t - 7] + R0(W[t - 15]) + W[t - 16];
278 280
@@ -327,7 +329,9 @@ static const uint32_t init256[] = {
327 0x510e527f, 329 0x510e527f,
328 0x9b05688c, 330 0x9b05688c,
329 0x1f83d9ab, 331 0x1f83d9ab,
330 0x5be0cd19 332 0x5be0cd19,
333 0,
334 0,
331}; 335};
332static const uint32_t init512_lo[] = { 336static const uint32_t init512_lo[] = {
333 0xf3bcc908, 337 0xf3bcc908,
@@ -337,7 +341,9 @@ static const uint32_t init512_lo[] = {
337 0xade682d1, 341 0xade682d1,
338 0x2b3e6c1f, 342 0x2b3e6c1f,
339 0xfb41bd6b, 343 0xfb41bd6b,
340 0x137e2179 344 0x137e2179,
345 0,
346 0,
341}; 347};
342 348
343/* Initialize structure containing state of computation. 349/* Initialize structure containing state of computation.
@@ -345,7 +351,7 @@ static const uint32_t init512_lo[] = {
345void FAST_FUNC sha256_begin(sha256_ctx_t *ctx) 351void FAST_FUNC sha256_begin(sha256_ctx_t *ctx)
346{ 352{
347 memcpy(ctx->hash, init256, sizeof(init256)); 353 memcpy(ctx->hash, init256, sizeof(init256));
348 ctx->total64 = 0; 354 /*ctx->total64 = 0; - done by extending init256 with two 32-bit zeros */
349 ctx->process_block = sha256_process_block64; 355 ctx->process_block = sha256_process_block64;
350} 356}
351 357
@@ -354,36 +360,61 @@ void FAST_FUNC sha256_begin(sha256_ctx_t *ctx)
354void FAST_FUNC sha512_begin(sha512_ctx_t *ctx) 360void FAST_FUNC sha512_begin(sha512_ctx_t *ctx)
355{ 361{
356 int i; 362 int i;
357 for (i = 0; i < 8; i++) 363 /* Two extra iterations zero out ctx->total64[] */
364 for (i = 0; i < 8+2; i++)
358 ctx->hash[i] = ((uint64_t)(init256[i]) << 32) + init512_lo[i]; 365 ctx->hash[i] = ((uint64_t)(init256[i]) << 32) + init512_lo[i];
359 ctx->total64[0] = ctx->total64[1] = 0; 366 /*ctx->total64[0] = ctx->total64[1] = 0; - already done */
360} 367}
361 368
362 369
363/* Used also for sha256 */ 370/* Used also for sha256 */
364void FAST_FUNC sha1_hash(const void *buffer, size_t len, sha1_ctx_t *ctx) 371void FAST_FUNC sha1_hash(sha1_ctx_t *ctx, const void *buffer, size_t len)
365{ 372{
366 unsigned in_buf = ctx->total64 & 63; 373 unsigned bufpos = ctx->total64 & 63;
367 unsigned add = 64 - in_buf; 374 unsigned remaining;
368 375
369 ctx->total64 += len; 376 ctx->total64 += len;
370 377#if 0
371 while (len >= add) { /* transfer whole blocks while possible */ 378 remaining = 64 - bufpos;
372 memcpy(ctx->wbuffer + in_buf, buffer, add); 379
373 buffer = (const char *)buffer + add; 380 /* Hash whole blocks */
374 len -= add; 381 while (len >= remaining) {
375 add = 64; 382 memcpy(ctx->wbuffer + bufpos, buffer, remaining);
376 in_buf = 0; 383 buffer = (const char *)buffer + remaining;
384 len -= remaining;
385 remaining = 64;
386 bufpos = 0;
377 ctx->process_block(ctx); 387 ctx->process_block(ctx);
378 } 388 }
379 389
380 memcpy(ctx->wbuffer + in_buf, buffer, len); 390 /* Save last, partial blosk */
391 memcpy(ctx->wbuffer + bufpos, buffer, len);
392#else
393 /* Tiny bit smaller code */
394 while (1) {
395 remaining = 64 - bufpos;
396 if (remaining > len)
397 remaining = len;
398 /* Copy data into aligned buffer */
399 memcpy(ctx->wbuffer + bufpos, buffer, remaining);
400 len -= remaining;
401 buffer = (const char *)buffer + remaining;
402 bufpos += remaining;
403 /* clever way to do "if (bufpos != 64) break; ... ; bufpos = 0;" */
404 bufpos -= 64;
405 if (bufpos != 0)
406 break;
407 /* Buffer is filled up, process it */
408 ctx->process_block(ctx);
409 /*bufpos = 0; - already is */
410 }
411#endif
381} 412}
382 413
383void FAST_FUNC sha512_hash(const void *buffer, size_t len, sha512_ctx_t *ctx) 414void FAST_FUNC sha512_hash(sha512_ctx_t *ctx, const void *buffer, size_t len)
384{ 415{
385 unsigned in_buf = ctx->total64[0] & 127; 416 unsigned bufpos = ctx->total64[0] & 127;
386 unsigned add = 128 - in_buf; 417 unsigned remaining;
387 418
388 /* First increment the byte count. FIPS 180-2 specifies the possible 419 /* First increment the byte count. FIPS 180-2 specifies the possible
389 length of the file up to 2^128 _bits_. 420 length of the file up to 2^128 _bits_.
@@ -391,36 +422,57 @@ void FAST_FUNC sha512_hash(const void *buffer, size_t len, sha512_ctx_t *ctx)
391 ctx->total64[0] += len; 422 ctx->total64[0] += len;
392 if (ctx->total64[0] < len) 423 if (ctx->total64[0] < len)
393 ctx->total64[1]++; 424 ctx->total64[1]++;
394 425#if 0
395 while (len >= add) { /* transfer whole blocks while possible */ 426 remaining = 128 - bufpos;
396 memcpy(ctx->wbuffer + in_buf, buffer, add); 427
397 buffer = (const char *)buffer + add; 428 /* Hash whole blocks */
398 len -= add; 429 while (len >= remaining) {
399 add = 128; 430 memcpy(ctx->wbuffer + bufpos, buffer, remaining);
400 in_buf = 0; 431 buffer = (const char *)buffer + remaining;
432 len -= remaining;
433 remaining = 128;
434 bufpos = 0;
401 sha512_process_block128(ctx); 435 sha512_process_block128(ctx);
402 } 436 }
403 437
404 memcpy(ctx->wbuffer + in_buf, buffer, len); 438 /* Save last, partial blosk */
439 memcpy(ctx->wbuffer + bufpos, buffer, len);
440#else
441 while (1) {
442 remaining = 128 - bufpos;
443 if (remaining > len)
444 remaining = len;
445 /* Copy data into aligned buffer */
446 memcpy(ctx->wbuffer + bufpos, buffer, remaining);
447 len -= remaining;
448 buffer = (const char *)buffer + remaining;
449 bufpos += remaining;
450 /* clever way to do "if (bufpos != 128) break; ... ; bufpos = 0;" */
451 bufpos -= 128;
452 if (bufpos != 0)
453 break;
454 /* Buffer is filled up, process it */
455 sha512_process_block128(ctx);
456 /*bufpos = 0; - already is */
457 }
458#endif
405} 459}
406 460
407 461
408/* Used also for sha256 */ 462/* Used also for sha256 */
409void FAST_FUNC sha1_end(void *resbuf, sha1_ctx_t *ctx) 463void FAST_FUNC sha1_end(sha1_ctx_t *ctx, void *resbuf)
410{ 464{
411 unsigned pad, in_buf; 465 unsigned bufpos = ctx->total64 & 63;
412 466
413 in_buf = ctx->total64 & 63;
414 /* Pad the buffer to the next 64-byte boundary with 0x80,0,0,0... */ 467 /* Pad the buffer to the next 64-byte boundary with 0x80,0,0,0... */
415 ctx->wbuffer[in_buf++] = 0x80; 468 ctx->wbuffer[bufpos++] = 0x80;
416 469
417 /* This loop iterates either once or twice, no more, no less */ 470 /* This loop iterates either once or twice, no more, no less */
418 while (1) { 471 while (1) {
419 pad = 64 - in_buf; 472 unsigned remaining = 64 - bufpos;
420 memset(ctx->wbuffer + in_buf, 0, pad); 473 memset(ctx->wbuffer + bufpos, 0, remaining);
421 in_buf = 0;
422 /* Do we have enough space for the length count? */ 474 /* Do we have enough space for the length count? */
423 if (pad >= 8) { 475 if (remaining >= 8) {
424 /* Store the 64-bit counter of bits in the buffer in BE format */ 476 /* Store the 64-bit counter of bits in the buffer in BE format */
425 uint64_t t = ctx->total64 << 3; 477 uint64_t t = ctx->total64 << 3;
426 t = hton64(t); 478 t = hton64(t);
@@ -428,35 +480,32 @@ void FAST_FUNC sha1_end(void *resbuf, sha1_ctx_t *ctx)
428 *(uint64_t *) (&ctx->wbuffer[64 - 8]) = t; 480 *(uint64_t *) (&ctx->wbuffer[64 - 8]) = t;
429 } 481 }
430 ctx->process_block(ctx); 482 ctx->process_block(ctx);
431 if (pad >= 8) 483 if (remaining >= 8)
432 break; 484 break;
485 bufpos = 0;
433 } 486 }
434 487
435 in_buf = (ctx->process_block == sha1_process_block64) ? 5 : 8; 488 bufpos = (ctx->process_block == sha1_process_block64) ? 5 : 8;
436 /* This way we do not impose alignment constraints on resbuf: */ 489 /* This way we do not impose alignment constraints on resbuf: */
437 if (BB_LITTLE_ENDIAN) { 490 if (BB_LITTLE_ENDIAN) {
438 unsigned i; 491 unsigned i;
439 for (i = 0; i < in_buf; ++i) 492 for (i = 0; i < bufpos; ++i)
440 ctx->hash[i] = htonl(ctx->hash[i]); 493 ctx->hash[i] = htonl(ctx->hash[i]);
441 } 494 }
442 memcpy(resbuf, ctx->hash, sizeof(ctx->hash[0]) * in_buf); 495 memcpy(resbuf, ctx->hash, sizeof(ctx->hash[0]) * bufpos);
443} 496}
444 497
445void FAST_FUNC sha512_end(void *resbuf, sha512_ctx_t *ctx) 498void FAST_FUNC sha512_end(sha512_ctx_t *ctx, void *resbuf)
446{ 499{
447 unsigned pad, in_buf; 500 unsigned bufpos = ctx->total64[0] & 127;
448 501
449 in_buf = ctx->total64[0] & 127; 502 /* Pad the buffer to the next 128-byte boundary with 0x80,0,0,0... */
450 /* Pad the buffer to the next 128-byte boundary with 0x80,0,0,0... 503 ctx->wbuffer[bufpos++] = 0x80;
451 * (FIPS 180-2:5.1.2)
452 */
453 ctx->wbuffer[in_buf++] = 0x80;
454 504
455 while (1) { 505 while (1) {
456 pad = 128 - in_buf; 506 unsigned remaining = 128 - bufpos;
457 memset(ctx->wbuffer + in_buf, 0, pad); 507 memset(ctx->wbuffer + bufpos, 0, remaining);
458 in_buf = 0; 508 if (remaining >= 16) {
459 if (pad >= 16) {
460 /* Store the 128-bit counter of bits in the buffer in BE format */ 509 /* Store the 128-bit counter of bits in the buffer in BE format */
461 uint64_t t; 510 uint64_t t;
462 t = ctx->total64[0] << 3; 511 t = ctx->total64[0] << 3;
@@ -467,8 +516,9 @@ void FAST_FUNC sha512_end(void *resbuf, sha512_ctx_t *ctx)
467 *(uint64_t *) (&ctx->wbuffer[128 - 16]) = t; 516 *(uint64_t *) (&ctx->wbuffer[128 - 16]) = t;
468 } 517 }
469 sha512_process_block128(ctx); 518 sha512_process_block128(ctx);
470 if (pad >= 16) 519 if (remaining >= 16)
471 break; 520 break;
521 bufpos = 0;
472 } 522 }
473 523
474 if (BB_LITTLE_ENDIAN) { 524 if (BB_LITTLE_ENDIAN) {
diff --git a/libbb/uuencode.c b/libbb/uuencode.c
index 181f49de0..03e708fd5 100644
--- a/libbb/uuencode.c
+++ b/libbb/uuencode.c
@@ -1,6 +1,8 @@
1/* vi: set sw=4 ts=4: */ 1/* vi: set sw=4 ts=4: */
2/* 2/*
3 * Copyright 2006 Rob Landley <rob@landley.net> 3 * Copyright 2003, Glenn McGrath
4 * Copyright 2006, Rob Landley <rob@landley.net>
5 * Copyright 2010, Denys Vlasenko
4 * 6 *
5 * Licensed under GPLv2 or later, see file LICENSE in this source tree. 7 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
6 */ 8 */
@@ -69,3 +71,75 @@ void FAST_FUNC bb_uuencode(char *p, const void *src, int length, const char *tbl
69 length++; 71 length++;
70 } 72 }
71} 73}
74
75/*
76 * Decode base64 encoded stream.
77 * Can stop on EOF, specified char, or on uuencode-style "====" line:
78 * flags argument controls it.
79 */
80void FAST_FUNC read_base64(FILE *src_stream, FILE *dst_stream, int flags)
81{
82/* Note that EOF _can_ be passed as exit_char too */
83#define exit_char ((int)(signed char)flags)
84#define uu_style_end (flags & BASE64_FLAG_UU_STOP)
85
86 int term_count = 0;
87
88 while (1) {
89 unsigned char translated[4];
90 int count = 0;
91
92 /* Process one group of 4 chars */
93 while (count < 4) {
94 char *table_ptr;
95 int ch;
96
97 /* Get next _valid_ character.
98 * bb_uuenc_tbl_base64[] contains this string:
99 * 0 1 2 3 4 5 6
100 * 012345678901234567890123456789012345678901234567890123456789012345
101 * "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=\n"
102 */
103 do {
104 ch = fgetc(src_stream);
105 if (ch == exit_char && count == 0)
106 return;
107 if (ch == EOF)
108 bb_error_msg_and_die("truncated base64 input");
109 table_ptr = strchr(bb_uuenc_tbl_base64, ch);
110//TODO: add BASE64_FLAG_foo to die on bad char?
111//Note that then we may need to still allow '\r' (for mail processing)
112 } while (!table_ptr);
113
114 /* Convert encoded character to decimal */
115 ch = table_ptr - bb_uuenc_tbl_base64;
116
117 if (ch == 65 /* '\n' */) {
118 /* Terminating "====" line? */
119 if (uu_style_end && term_count == 4)
120 return; /* yes */
121 term_count = 0;
122 continue;
123 }
124 /* ch is 64 if char was '=', otherwise 0..63 */
125 translated[count] = ch & 63; /* 64 -> 0 */
126 if (ch == 64) {
127 term_count++;
128 break;
129 }
130 count++;
131 term_count = 0;
132 }
133
134 /* Merge 6 bit chars to 8 bit.
135 * count can be < 4 when we decode the tail:
136 * "eQ==" -> "y", not "y NUL NUL"
137 */
138 if (count > 1)
139 fputc(translated[0] << 2 | translated[1] >> 4, dst_stream);
140 if (count > 2)
141 fputc(translated[1] << 4 | translated[2] >> 2, dst_stream);
142 if (count > 3)
143 fputc(translated[2] << 6 | translated[3], dst_stream);
144 } /* while (1) */
145}
diff --git a/libbb/xfuncs_printf.c b/libbb/xfuncs_printf.c
index ae950f94f..8e60e2165 100644
--- a/libbb/xfuncs_printf.c
+++ b/libbb/xfuncs_printf.c
@@ -134,7 +134,7 @@ int FAST_FUNC xopen3(const char *pathname, int flags, int mode)
134 return ret; 134 return ret;
135} 135}
136 136
137// Die if we can't open an existing file and return a fd. 137// Die if we can't open a file and return a fd.
138int FAST_FUNC xopen(const char *pathname, int flags) 138int FAST_FUNC xopen(const char *pathname, int flags)
139{ 139{
140 return xopen3(pathname, flags, 0666); 140 return xopen3(pathname, flags, 0666);