~ubuntu-branches/ubuntu/natty/php5/natty-updates

« back to all changes in this revision

Viewing changes to debian/patches/php5-CVE-2011-2483.patch

  • Committer: Package Import Robot
  • Author(s): Steve Beattie, Angel Abad, Steve Beattie
  • Date: 2011-10-13 13:49:23 UTC
  • Revision ID: package-import@ubuntu.com-20111013134923-m0vw36h5ox5glvhn
Tags: 5.3.5-1ubuntu7.3
[ Angel Abad ]
* SECURITY UPDATE: File path injection vulnerability in RFC1867 File
  upload filename (LP: #813115)
  - debian/patches/php5-CVE-2011-2202.patch:
  - CVE-2011-2202
* SECURITY UPDATE: Fixed stack buffer overflow in socket_connect()
  (LP: #813110)
  - debian/patches/php5-CVE-2011-1938.patch:
  - CVE-2011-1938

[ Steve Beattie ]
* SECURITY UPDATE: DoS in zip handling due to addGlob() crashing
  on invalid flags
  - debian/patches/php5-CVE-2011-1657.patch: check for valid flags
  - CVE-2011-1657
* SECURITY UPDATE: crypt_blowfish doesn't properly handle 8-bit
  (non-ascii) passwords leading to a smaller collision space
  - debian/patches/php5-CVE-2011-2483.patch: update crypt_blowfish
    to 1.2 to correct handling of passwords containing 8-bit
    (non-ascii) characters.
    CVE-2011-2483
* SECURITY UPDATE: DoS due to failure to check for memory allocation errors
  - debian/patches/php5-CVE-2011-3182.patch: check the return values
    of the malloc, calloc, and realloc functions
  - CVE-2011-3182
* SECURITY UPDATE:  DoS in errorlog() when passed NULL
  - debian/patches/php5-CVE-2011-3267.patch: fix NULL pointer crash in
    errorlog()
  - CVE-2011-3267
* debian/patches/fix_crash_in__php_mssql_get_column_content_without_type.patch:
  refresh patch to make it cleanly apply.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
From: Solar Designer
 
2
Origin: http://svn.php.net/viewvc?view=revision&revision=313406
 
3
Subject: update crypt_blowfish to 1.2. (CVE-2011-2483) (Solar Designer)
 
4
 
 
5
- update blowfish to 1.2 (Solar Designer)
 
6
 
 
7
CVE-2011-2483
 
8
 
 
9
[Ubuntu note: patch differs from upstream commit in that the added
 
10
 header crypt_blowfish.h has been dropped, to prevent possible 3rd
 
11
 party build problems by introducing the new header.  Also, the changes
 
12
 to the News file have been dropped to reduce conflicts. --sbeattie]
 
13
 
 
14
---
 
15
 README.REDIST.BINS            |   27 ++
 
16
 ext/standard/crypt_blowfish.c |  379 +++++++++++++++++++++++++++++-------------
 
17
 ext/standard/crypt_blowfish.h |   32 +++
 
18
 ext/standard/php_crypt_r.h    |    4 
 
19
 4 files changed, 320 insertions(+), 122 deletions(-)
 
20
 
 
21
Index: b/README.REDIST.BINS
 
22
===================================================================
 
23
--- a/README.REDIST.BINS
 
24
+++ b/README.REDIST.BINS
 
25
@@ -51,27 +51,40 @@ SUCH DAMAGE.
 
26
 
 
27
 6. ext/standard crypt's blowfish implementation
 
28
 
 
29
+The crypt_blowfish homepage is:
 
30
+
 
31
+http://www.openwall.com/crypt/
 
32
+
 
33
 This code comes from John the Ripper password cracker, with reentrant
 
34
 and crypt(3) interfaces added, but optimizations specific to password
 
35
 cracking removed.
 
36
 
 
37
-Written by Solar Designer <solar at openwall.com> in 1998-2002 and
 
38
-placed in the public domain.
 
39
+Written by Solar Designer <solar at openwall.com> in 1998-2011.
 
40
+No copyright is claimed, and the software is hereby placed in the public
 
41
+domain. In case this attempt to disclaim copyright and place the software
 
42
+in the public domain is deemed null and void, then the software is
 
43
+Copyright (c) 1998-2011 Solar Designer and it is hereby released to the
 
44
+general public under the following terms:
 
45
+
 
46
+Redistribution and use in source and binary forms, with or without
 
47
+modification, are permitted.
 
48
 
 
49
-There's absolutely no warranty.
 
50
+There's ABSOLUTELY NO WARRANTY, express or implied.
 
51
 
 
52
 It is my intent that you should be able to use this on your system,
 
53
-as a part of a software package, or anywhere else to improve security,
 
54
+as part of a software package, or anywhere else to improve security,
 
55
 ensure compatibility, or for any other purpose. I would appreciate
 
56
 it if you give credit where it is due and keep your modifications in
 
57
 the public domain as well, but I don't require that in order to let
 
58
 you place this code and any modifications you make under a license
 
59
 of your choice.
 
60
 
 
61
-This implementation is compatible with OpenBSD bcrypt.c (version 2a)
 
62
-by Niels Provos <provos at citi.umich.edu>, and uses some of his
 
63
+This implementation is mostly compatible with OpenBSD's bcrypt.c (prefix
 
64
+"$2a$") by Niels Provos <provos at citi.umich.edu>, and uses some of his
 
65
 ideas. The password hashing algorithm was designed by David Mazieres
 
66
-<dm at lcs.mit.edu>.
 
67
+<dm at lcs.mit.edu>. For more information on the level of compatibility,
 
68
+please refer to the comments in BF_set_key() and to the crypt(3) man page
 
69
+included in the crypt_blowfish tarball.
 
70
 
 
71
 There's a paper on the algorithm that explains its design decisions:
 
72
 
 
73
Index: b/ext/standard/crypt_blowfish.c
 
74
===================================================================
 
75
--- a/ext/standard/crypt_blowfish.c
 
76
+++ b/ext/standard/crypt_blowfish.c
 
77
@@ -1,28 +1,39 @@
 
78
+/* $Id: crypt_blowfish.c 313406 2011-07-18 21:26:29Z pajoye $ */
 
79
 /*
 
80
-  $Id: crypt_blowfish.c 295339 2010-02-21 23:47:14Z pajoye $ 
 
81
-*/
 
82
-/*
 
83
+ * The crypt_blowfish homepage is:
 
84
+ *
 
85
+ *     http://www.openwall.com/crypt/
 
86
+ *
 
87
  * This code comes from John the Ripper password cracker, with reentrant
 
88
  * and crypt(3) interfaces added, but optimizations specific to password
 
89
  * cracking removed.
 
90
  *
 
91
- * Written by Solar Designer <solar at openwall.com> in 1998-2002 and
 
92
- * placed in the public domain.
 
93
+ * Written by Solar Designer <solar at openwall.com> in 1998-2011.
 
94
+ * No copyright is claimed, and the software is hereby placed in the public
 
95
+ * domain. In case this attempt to disclaim copyright and place the software
 
96
+ * in the public domain is deemed null and void, then the software is
 
97
+ * Copyright (c) 1998-2011 Solar Designer and it is hereby released to the
 
98
+ * general public under the following terms:
 
99
  *
 
100
- * There's absolutely no warranty.
 
101
+ * Redistribution and use in source and binary forms, with or without
 
102
+ * modification, are permitted.
 
103
+ *
 
104
+ * There's ABSOLUTELY NO WARRANTY, express or implied.
 
105
  *
 
106
  * It is my intent that you should be able to use this on your system,
 
107
- * as a part of a software package, or anywhere else to improve security,
 
108
+ * as part of a software package, or anywhere else to improve security,
 
109
  * ensure compatibility, or for any other purpose. I would appreciate
 
110
  * it if you give credit where it is due and keep your modifications in
 
111
  * the public domain as well, but I don't require that in order to let
 
112
  * you place this code and any modifications you make under a license
 
113
  * of your choice.
 
114
  *
 
115
- * This implementation is compatible with OpenBSD bcrypt.c (version 2a)
 
116
- * by Niels Provos <provos at citi.umich.edu>, and uses some of his
 
117
+ * This implementation is mostly compatible with OpenBSD's bcrypt.c (prefix
 
118
+ * "$2a$") by Niels Provos <provos at citi.umich.edu>, and uses some of his
 
119
  * ideas. The password hashing algorithm was designed by David Mazieres
 
120
- * <dm at lcs.mit.edu>.
 
121
+ * <dm at lcs.mit.edu>. For more information on the level of compatibility,
 
122
+ * please refer to the comments in BF_set_key() below and to the crypt(3)
 
123
+ * man page included in the crypt_blowfish tarball.
 
124
  *
 
125
  * There's a paper on the algorithm that explains its design decisions:
 
126
  *
 
127
@@ -40,16 +51,8 @@
 
128
 #define __set_errno(val) errno = (val)
 
129
 #endif
 
130
 
 
131
-
 
132
-#ifndef __const
 
133
-#ifdef __GNUC__
 
134
-#define __CONST __const
 
135
-#else
 
136
-#define __CONST
 
137
-#endif
 
138
-#else
 
139
-#define __CONST __const
 
140
-#endif
 
141
+/* Just to make sure the prototypes match the actual definitions */
 
142
+// skip including "crypt_blowfish.h" as it's been dropped -sbeattie
 
143
 
 
144
 #ifdef __i386__
 
145
 #define BF_ASM                         0
 
146
@@ -63,6 +66,7 @@
 
147
 #endif
 
148
 
 
149
 typedef unsigned int BF_word;
 
150
+typedef signed int BF_word_signed;
 
151
 
 
152
 /* Number of Blowfish rounds, this is also hardcoded into a few places */
 
153
 #define BF_N                           16
 
154
@@ -370,35 +374,21 @@ static unsigned char BF_atoi64[0x60] = {
 
155
        43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 64, 64, 64, 64, 64
 
156
 };
 
157
 
 
158
-/*
 
159
- * This may be optimized out if built with function inlining and no BF_ASM.
 
160
- */
 
161
-static void clean(void *data, int size)
 
162
-{
 
163
-#if BF_ASM
 
164
-       extern void _BF_clean(void *data);
 
165
-#endif
 
166
-       memset(data, 0, size);
 
167
-#if BF_ASM
 
168
-       _BF_clean(data);
 
169
-#endif
 
170
-}
 
171
-
 
172
 #define BF_safe_atoi64(dst, src) \
 
173
 { \
 
174
        tmp = (unsigned char)(src); \
 
175
-       if (tmp == '$') break; \
 
176
+       if (tmp == '$') break; /* PHP hack */ \
 
177
        if ((unsigned int)(tmp -= 0x20) >= 0x60) return -1; \
 
178
        tmp = BF_atoi64[tmp]; \
 
179
        if (tmp > 63) return -1; \
 
180
        (dst) = tmp; \
 
181
 }
 
182
 
 
183
-static int BF_decode(BF_word *dst, __CONST char *src, int size)
 
184
+static int BF_decode(BF_word *dst, const char *src, int size)
 
185
 {
 
186
        unsigned char *dptr = (unsigned char *)dst;
 
187
        unsigned char *end = dptr + size;
 
188
-       unsigned char *sptr = (unsigned char *)src;
 
189
+       const unsigned char *sptr = (const unsigned char *)src;
 
190
        unsigned int tmp, c1, c2, c3, c4;
 
191
 
 
192
        do {
 
193
@@ -415,16 +405,16 @@ static int BF_decode(BF_word *dst, __CON
 
194
                *dptr++ = ((c3 & 0x03) << 6) | c4;
 
195
        } while (dptr < end);
 
196
 
 
197
-       while (dptr < end)
 
198
+       while (dptr < end) /* PHP hack */
 
199
                *dptr++ = 0;
 
200
 
 
201
        return 0;
 
202
 }
 
203
 
 
204
-static void BF_encode(char *dst, __CONST BF_word *src, int size)
 
205
+static void BF_encode(char *dst, const BF_word *src, int size)
 
206
 {
 
207
-       unsigned char *sptr = (unsigned char *)src;
 
208
-       unsigned char *end = sptr + size;
 
209
+       const unsigned char *sptr = (const unsigned char *)src;
 
210
+       const unsigned char *end = sptr + size;
 
211
        unsigned char *dptr = (unsigned char *)dst;
 
212
        unsigned int c1, c2;
 
213
 
 
214
@@ -555,32 +545,117 @@ static void BF_swap(BF_word *x, int coun
 
215
        } while (ptr < &data.ctx.S[3][0xFF]);
 
216
 #endif
 
217
 
 
218
-static void BF_set_key(__CONST char *key, BF_key expanded, BF_key initial)
 
219
+static void BF_set_key(const char *key, BF_key expanded, BF_key initial,
 
220
+    unsigned char flags)
 
221
 {
 
222
-       __CONST char *ptr = key;
 
223
-       int i, j;
 
224
-       BF_word tmp;
 
225
+       const char *ptr = key;
 
226
+       unsigned int bug, i, j;
 
227
+       BF_word safety, sign, diff, tmp[2];
 
228
+
 
229
+/*
 
230
+ * There was a sign extension bug in older revisions of this function. While
 
231
+ * we would have liked to simply fix the bug and move on, we have to provide
 
232
+ * a backwards compatibility feature (essentially the bug) for some systems and
 
233
+ * a safety measure for some others. The latter is needed because for certain
 
234
+ * multiple inputs to the buggy algorithm there exist easily found inputs to
 
235
+ * the correct algorithm that produce the same hash. Thus, we optionally
 
236
+ * deviate from the correct algorithm just enough to avoid such collisions.
 
237
+ * While the bug itself affected the majority of passwords containing
 
238
+ * characters with the 8th bit set (although only a percentage of those in a
 
239
+ * collision-producing way), the anti-collision safety measure affects
 
240
+ * only a subset of passwords containing the '\xff' character (not even all of
 
241
+ * those passwords, just some of them). This character is not found in valid
 
242
+ * UTF-8 sequences and is rarely used in popular 8-bit character encodings.
 
243
+ * Thus, the safety measure is unlikely to cause much annoyance, and is a
 
244
+ * reasonable tradeoff to use when authenticating against existing hashes that
 
245
+ * are not reliably known to have been computed with the correct algorithm.
 
246
+ *
 
247
+ * We use an approach that tries to minimize side-channel leaks of password
 
248
+ * information - that is, we mostly use fixed-cost bitwise operations instead
 
249
+ * of branches or table lookups. (One conditional branch based on password
 
250
+ * length remains. It is not part of the bug aftermath, though, and is
 
251
+ * difficult and possibly unreasonable to avoid given the use of C strings by
 
252
+ * the caller, which results in similar timing leaks anyway.)
 
253
+ *
 
254
+ * For actual implementation, we set an array index in the variable "bug"
 
255
+ * (0 means no bug, 1 means sign extension bug emulation) and a flag in the
 
256
+ * variable "safety" (bit 16 is set when the safety measure is requested).
 
257
+ * Valid combinations of settings are:
 
258
+ *
 
259
+ * Prefix "$2a$": bug = 0, safety = 0x10000
 
260
+ * Prefix "$2x$": bug = 1, safety = 0
 
261
+ * Prefix "$2y$": bug = 0, safety = 0
 
262
+ */
 
263
+       bug = (unsigned int)flags & 1;
 
264
+       safety = ((BF_word)flags & 2) << 15;
 
265
+
 
266
+       sign = diff = 0;
 
267
 
 
268
        for (i = 0; i < BF_N + 2; i++) {
 
269
-               tmp = 0;
 
270
+               tmp[0] = tmp[1] = 0;
 
271
                for (j = 0; j < 4; j++) {
 
272
-                       tmp <<= 8;
 
273
-                       tmp |= *ptr;
 
274
-
 
275
-                       if (!*ptr) ptr = key; else ptr++;
 
276
+                       tmp[0] <<= 8;
 
277
+                       tmp[0] |= (unsigned char)*ptr; /* correct */
 
278
+                       tmp[1] <<= 8;
 
279
+                       tmp[1] |= (BF_word_signed)(signed char)*ptr; /* bug */
 
280
+/*
 
281
+ * Sign extension in the first char has no effect - nothing to overwrite yet,
 
282
+ * and those extra 24 bits will be fully shifted out of the 32-bit word. For
 
283
+ * chars 2, 3, 4 in each four-char block, we set bit 7 of "sign" if sign
 
284
+ * extension in tmp[1] occurs. Once this flag is set, it remains set.
 
285
+ */
 
286
+                       if (j)
 
287
+                               sign |= tmp[1] & 0x80;
 
288
+                       if (!*ptr)
 
289
+                               ptr = key;
 
290
+                       else
 
291
+                               ptr++;
 
292
                }
 
293
+               diff |= tmp[0] ^ tmp[1]; /* Non-zero on any differences */
 
294
 
 
295
-               expanded[i] = tmp;
 
296
-               initial[i] = BF_init_state.P[i] ^ tmp;
 
297
+               expanded[i] = tmp[bug];
 
298
+               initial[i] = BF_init_state.P[i] ^ tmp[bug];
 
299
        }
 
300
+
 
301
+/*
 
302
+ * At this point, "diff" is zero iff the correct and buggy algorithms produced
 
303
+ * exactly the same result. If so and if "sign" is non-zero, which indicates
 
304
+ * that there was a non-benign sign extension, this means that we have a
 
305
+ * collision between the correctly computed hash for this password and a set of
 
306
+ * passwords that could be supplied to the buggy algorithm. Our safety measure
 
307
+ * is meant to protect from such many-buggy to one-correct collisions, by
 
308
+ * deviating from the correct algorithm in such cases. Let's check for this.
 
309
+ */
 
310
+       diff |= diff >> 16; /* still zero iff exact match */
 
311
+       diff &= 0xffff; /* ditto */
 
312
+       diff += 0xffff; /* bit 16 set iff "diff" was non-zero (on non-match) */
 
313
+       sign <<= 9; /* move the non-benign sign extension flag to bit 16 */
 
314
+       sign &= ~diff & safety; /* action needed? */
 
315
+
 
316
+/*
 
317
+ * If we have determined that we need to deviate from the correct algorithm,
 
318
+ * flip bit 16 in initial expanded key. (The choice of 16 is arbitrary, but
 
319
+ * let's stick to it now. It came out of the approach we used above, and it's
 
320
+ * not any worse than any other choice we could make.)
 
321
+ *
 
322
+ * It is crucial that we don't do the same to the expanded key used in the main
 
323
+ * Eksblowfish loop. By doing it to only one of these two, we deviate from a
 
324
+ * state that could be directly specified by a password to the buggy algorithm
 
325
+ * (and to the fully correct one as well, but that's a side-effect).
 
326
+ */
 
327
+       initial[0] ^= sign;
 
328
 }
 
329
 
 
330
-char *php_crypt_blowfish_rn(__CONST char *key, __CONST char *setting,
 
331
-       char *output, int size)
 
332
+static char *BF_crypt(const char *key, const char *setting,
 
333
+       char *output, int size,
 
334
+       BF_word min)
 
335
 {
 
336
 #if BF_ASM
 
337
        extern void _BF_body_r(BF_ctx *ctx);
 
338
 #endif
 
339
+       static const unsigned char flags_by_subtype[26] =
 
340
+               {2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
 
341
+               0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 4, 0};
 
342
        struct {
 
343
                BF_ctx ctx;
 
344
                BF_key expanded_key;
 
345
@@ -602,7 +677,8 @@ char *php_crypt_blowfish_rn(__CONST char
 
346
 
 
347
        if (setting[0] != '$' ||
 
348
            setting[1] != '2' ||
 
349
-           setting[2] != 'a' ||
 
350
+           setting[2] < 'a' || setting[2] > 'z' ||
 
351
+           !flags_by_subtype[(unsigned int)(unsigned char)setting[2] - 'a'] ||
 
352
            setting[3] != '$' ||
 
353
            setting[4] < '0' || setting[4] > '3' ||
 
354
            setting[5] < '0' || setting[5] > '9' ||
 
355
@@ -613,15 +689,14 @@ char *php_crypt_blowfish_rn(__CONST char
 
356
        }
 
357
 
 
358
        count = (BF_word)1 << ((setting[4] - '0') * 10 + (setting[5] - '0'));
 
359
-       if (count < 16 || BF_decode(data.binary.salt, &setting[7], 16)) {
 
360
-               clean(data.binary.salt, sizeof(data.binary.salt));
 
361
+       if (count < min || BF_decode(data.binary.salt, &setting[7], 16)) {
 
362
                __set_errno(EINVAL);
 
363
                return NULL;
 
364
        }
 
365
-
 
366
        BF_swap(data.binary.salt, 4);
 
367
 
 
368
-       BF_set_key(key, data.expanded_key, data.ctx.P);
 
369
+       BF_set_key(key, data.expanded_key, data.ctx.P,
 
370
+           flags_by_subtype[(unsigned int)(unsigned char)setting[2] - 'a']);
 
371
 
 
372
        memcpy(data.ctx.S, BF_init_state.S, sizeof(data.ctx.S));
 
373
 
 
374
@@ -651,51 +726,33 @@ char *php_crypt_blowfish_rn(__CONST char
 
375
        } while (ptr < &data.ctx.S[3][0xFF]);
 
376
 
 
377
        do {
 
378
-               data.ctx.P[0] ^= data.expanded_key[0];
 
379
-               data.ctx.P[1] ^= data.expanded_key[1];
 
380
-               data.ctx.P[2] ^= data.expanded_key[2];
 
381
-               data.ctx.P[3] ^= data.expanded_key[3];
 
382
-               data.ctx.P[4] ^= data.expanded_key[4];
 
383
-               data.ctx.P[5] ^= data.expanded_key[5];
 
384
-               data.ctx.P[6] ^= data.expanded_key[6];
 
385
-               data.ctx.P[7] ^= data.expanded_key[7];
 
386
-               data.ctx.P[8] ^= data.expanded_key[8];
 
387
-               data.ctx.P[9] ^= data.expanded_key[9];
 
388
-               data.ctx.P[10] ^= data.expanded_key[10];
 
389
-               data.ctx.P[11] ^= data.expanded_key[11];
 
390
-               data.ctx.P[12] ^= data.expanded_key[12];
 
391
-               data.ctx.P[13] ^= data.expanded_key[13];
 
392
-               data.ctx.P[14] ^= data.expanded_key[14];
 
393
-               data.ctx.P[15] ^= data.expanded_key[15];
 
394
-               data.ctx.P[16] ^= data.expanded_key[16];
 
395
-               data.ctx.P[17] ^= data.expanded_key[17];
 
396
-
 
397
-               BF_body();
 
398
-
 
399
-               tmp1 = data.binary.salt[0];
 
400
-               tmp2 = data.binary.salt[1];
 
401
-               tmp3 = data.binary.salt[2];
 
402
-               tmp4 = data.binary.salt[3];
 
403
-               data.ctx.P[0] ^= tmp1;
 
404
-               data.ctx.P[1] ^= tmp2;
 
405
-               data.ctx.P[2] ^= tmp3;
 
406
-               data.ctx.P[3] ^= tmp4;
 
407
-               data.ctx.P[4] ^= tmp1;
 
408
-               data.ctx.P[5] ^= tmp2;
 
409
-               data.ctx.P[6] ^= tmp3;
 
410
-               data.ctx.P[7] ^= tmp4;
 
411
-               data.ctx.P[8] ^= tmp1;
 
412
-               data.ctx.P[9] ^= tmp2;
 
413
-               data.ctx.P[10] ^= tmp3;
 
414
-               data.ctx.P[11] ^= tmp4;
 
415
-               data.ctx.P[12] ^= tmp1;
 
416
-               data.ctx.P[13] ^= tmp2;
 
417
-               data.ctx.P[14] ^= tmp3;
 
418
-               data.ctx.P[15] ^= tmp4;
 
419
-               data.ctx.P[16] ^= tmp1;
 
420
-               data.ctx.P[17] ^= tmp2;
 
421
+               int done;
 
422
 
 
423
-               BF_body();
 
424
+               for (i = 0; i < BF_N + 2; i += 2) {
 
425
+                       data.ctx.P[i] ^= data.expanded_key[i];
 
426
+                       data.ctx.P[i + 1] ^= data.expanded_key[i + 1];
 
427
+               }
 
428
+
 
429
+               done = 0;
 
430
+               do {
 
431
+                       BF_body();
 
432
+                       if (done)
 
433
+                               break;
 
434
+                       done = 1;
 
435
+
 
436
+                       tmp1 = data.binary.salt[0];
 
437
+                       tmp2 = data.binary.salt[1];
 
438
+                       tmp3 = data.binary.salt[2];
 
439
+                       tmp4 = data.binary.salt[3];
 
440
+                       for (i = 0; i < BF_N; i += 4) {
 
441
+                               data.ctx.P[i] ^= tmp1;
 
442
+                               data.ctx.P[i + 1] ^= tmp2;
 
443
+                               data.ctx.P[i + 2] ^= tmp3;
 
444
+                               data.ctx.P[i + 3] ^= tmp4;
 
445
+                       }
 
446
+                       data.ctx.P[16] ^= tmp1;
 
447
+                       data.ctx.P[17] ^= tmp2;
 
448
+               } while (1);
 
449
        } while (--count);
 
450
 
 
451
        for (i = 0; i < 6; i += 2) {
 
452
@@ -721,19 +778,114 @@ char *php_crypt_blowfish_rn(__CONST char
 
453
        BF_encode(&output[7 + 22], data.binary.output, 23);
 
454
        output[7 + 22 + 31] = '\0';
 
455
 
 
456
-/* Overwrite the most obvious sensitive data we have on the stack. Note
 
457
- * that this does not guarantee there's no sensitive data left on the
 
458
- * stack and/or in registers; I'm not aware of portable code that does. */
 
459
-       clean(&data, sizeof(data));
 
460
-
 
461
        return output;
 
462
 }
 
463
 
 
464
-char *php_crypt_gensalt_blowfish_rn(unsigned long count,
 
465
-       __CONST char *input, int size, char *output, int output_size)
 
466
+static int _crypt_output_magic(const char *setting, char *output, int size)
 
467
+{
 
468
+       if (size < 3)
 
469
+               return -1;
 
470
+
 
471
+       output[0] = '*';
 
472
+       output[1] = '0';
 
473
+       output[2] = '\0';
 
474
+
 
475
+       if (setting[0] == '*' && setting[1] == '0')
 
476
+               output[1] = '1';
 
477
+
 
478
+       return 0;
 
479
+}
 
480
+
 
481
+/*
 
482
+ * Please preserve the runtime self-test. It serves two purposes at once:
 
483
+ *
 
484
+ * 1. We really can't afford the risk of producing incompatible hashes e.g.
 
485
+ * when there's something like gcc bug 26587 again, whereas an application or
 
486
+ * library integrating this code might not also integrate our external tests or
 
487
+ * it might not run them after every build. Even if it does, the miscompile
 
488
+ * might only occur on the production build, but not on a testing build (such
 
489
+ * as because of different optimization settings). It is painful to recover
 
490
+ * from incorrectly-computed hashes - merely fixing whatever broke is not
 
491
+ * enough. Thus, a proactive measure like this self-test is needed.
 
492
+ *
 
493
+ * 2. We don't want to leave sensitive data from our actual password hash
 
494
+ * computation on the stack or in registers. Previous revisions of the code
 
495
+ * would do explicit cleanups, but simply running the self-test after hash
 
496
+ * computation is more reliable.
 
497
+ *
 
498
+ * The performance cost of this quick self-test is around 0.6% at the "$2a$08"
 
499
+ * setting.
 
500
+ */
 
501
+char *php_crypt_blowfish_rn(const char *key, const char *setting,
 
502
+       char *output, int size)
 
503
+{
 
504
+       const char *test_key = "8b \xd0\xc1\xd2\xcf\xcc\xd8";
 
505
+       const char *test_setting = "$2a$00$abcdefghijklmnopqrstuu";
 
506
+       static const char * const test_hash[2] =
 
507
+               {"VUrPmXD6q/nVSSp7pNDhCR9071IfIRe\0\x55", /* $2x$ */
 
508
+               "i1D709vfamulimlGcq0qq3UvuUasvEa\0\x55"}; /* $2a$, $2y$ */
 
509
+       char *retval;
 
510
+       const char *p;
 
511
+       int save_errno, ok;
 
512
+       struct {
 
513
+               char s[7 + 22 + 1];
 
514
+               char o[7 + 22 + 31 + 1 + 1 + 1];
 
515
+       } buf;
 
516
+
 
517
+/* Hash the supplied password */
 
518
+       _crypt_output_magic(setting, output, size);
 
519
+       retval = BF_crypt(key, setting, output, size, 16);
 
520
+       save_errno = errno;
 
521
+
 
522
+/*
 
523
+ * Do a quick self-test. It is important that we make both calls to BF_crypt()
 
524
+ * from the same scope such that they likely use the same stack locations,
 
525
+ * which makes the second call overwrite the first call's sensitive data on the
 
526
+ * stack and makes it more likely that any alignment related issues would be
 
527
+ * detected by the self-test.
 
528
+ */
 
529
+       memcpy(buf.s, test_setting, sizeof(buf.s));
 
530
+       if (retval)
 
531
+               buf.s[2] = setting[2];
 
532
+       memset(buf.o, 0x55, sizeof(buf.o));
 
533
+       buf.o[sizeof(buf.o) - 1] = 0;
 
534
+       p = BF_crypt(test_key, buf.s, buf.o, sizeof(buf.o) - (1 + 1), 1);
 
535
+
 
536
+       ok = (p == buf.o &&
 
537
+           !memcmp(p, buf.s, 7 + 22) &&
 
538
+           !memcmp(p + (7 + 22),
 
539
+           test_hash[(unsigned int)(unsigned char)buf.s[2] & 1],
 
540
+           31 + 1 + 1 + 1));
 
541
+
 
542
+       {
 
543
+               const char *k = "\xff\xa3" "34" "\xff\xff\xff\xa3" "345";
 
544
+               BF_key ae, ai, ye, yi;
 
545
+               BF_set_key(k, ae, ai, 2); /* $2a$ */
 
546
+               BF_set_key(k, ye, yi, 4); /* $2y$ */
 
547
+               ai[0] ^= 0x10000; /* undo the safety (for comparison) */
 
548
+               ok = ok && ai[0] == 0xdb9c59bc && ye[17] == 0x33343500 &&
 
549
+                   !memcmp(ae, ye, sizeof(ae)) &&
 
550
+                   !memcmp(ai, yi, sizeof(ai));
 
551
+       }
 
552
+
 
553
+       __set_errno(save_errno);
 
554
+       if (ok)
 
555
+               return retval;
 
556
+
 
557
+/* Should not happen */
 
558
+       _crypt_output_magic(setting, output, size);
 
559
+       __set_errno(EINVAL); /* pretend we don't support this hash type */
 
560
+       return NULL;
 
561
+}
 
562
+
 
563
+#if 0
 
564
+char *_crypt_gensalt_blowfish_rn(const char *prefix, unsigned long count,
 
565
+       const char *input, int size, char *output, int output_size)
 
566
 {
 
567
        if (size < 16 || output_size < 7 + 22 + 1 ||
 
568
-           (count && (count < 4 || count > 31))) {
 
569
+           (count && (count < 4 || count > 31)) ||
 
570
+           prefix[0] != '$' || prefix[1] != '2' ||
 
571
+           (prefix[2] != 'a' && prefix[2] != 'y')) {
 
572
                if (output_size > 0) output[0] = '\0';
 
573
                __set_errno((output_size < 7 + 22 + 1) ? ERANGE : EINVAL);
 
574
                return NULL;
 
575
@@ -743,14 +895,15 @@ char *php_crypt_gensalt_blowfish_rn(unsi
 
576
 
 
577
        output[0] = '$';
 
578
        output[1] = '2';
 
579
-       output[2] = 'a';
 
580
+       output[2] = prefix[2];
 
581
        output[3] = '$';
 
582
        output[4] = '0' + count / 10;
 
583
        output[5] = '0' + count % 10;
 
584
        output[6] = '$';
 
585
 
 
586
-       BF_encode(&output[7], (BF_word *)input, 16);
 
587
+       BF_encode(&output[7], (const BF_word *)input, 16);
 
588
        output[7 + 22] = '\0';
 
589
 
 
590
        return output;
 
591
 }
 
592
+#endif