bcrypt-ruby 2.1.4-x86-mingw32 → 3.0.0-x86-mingw32
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.gitignore +1 -0
- data/CHANGELOG +5 -1
- data/COPYING +23 -28
- data/Gemfile.lock +29 -0
- data/README.md +184 -0
- data/Rakefile +1 -0
- data/bcrypt-ruby.gemspec +3 -3
- data/ext/mri/bcrypt_ext.c +67 -65
- data/ext/mri/crypt.c +57 -0
- data/ext/mri/crypt.h +13 -0
- data/ext/mri/{blowfish.c → crypt_blowfish.c} +472 -321
- data/ext/mri/crypt_gensalt.c +111 -0
- data/ext/mri/extconf.rb +24 -2
- data/ext/mri/ow-crypt.h +35 -0
- data/ext/mri/wrapper.c +255 -0
- data/lib/bcrypt.rb +10 -5
- data/lib/bcrypt_engine.rb +34 -0
- data/spec/bcrypt/engine_spec.rb +3 -3
- data/spec/bcrypt/password_spec.rb +11 -2
- metadata +19 -16
- data/README +0 -175
- data/ext/mri/bcrypt.c +0 -297
- data/ext/mri/bcrypt.h +0 -67
- data/ext/mri/blf.h +0 -86
data/ext/mri/crypt.c
ADDED
@@ -0,0 +1,57 @@
|
|
1
|
+
#include <ruby.h>
|
2
|
+
#include <ow-crypt.h>
|
3
|
+
|
4
|
+
VALUE mCrypt;
|
5
|
+
|
6
|
+
static VALUE crypt_salt(VALUE self, VALUE prefix, VALUE count, VALUE input)
|
7
|
+
{
|
8
|
+
char * salt;
|
9
|
+
VALUE str_salt;
|
10
|
+
|
11
|
+
salt = crypt_gensalt_ra(
|
12
|
+
StringValuePtr(prefix),
|
13
|
+
NUM2ULONG(count),
|
14
|
+
NIL_P(input) ? NULL : StringValuePtr(input),
|
15
|
+
NIL_P(input) ? 0 : RSTRING_LEN(input));
|
16
|
+
|
17
|
+
if(!salt) return Qnil;
|
18
|
+
|
19
|
+
str_salt = rb_str_new2(salt);
|
20
|
+
free(salt);
|
21
|
+
|
22
|
+
return str_salt;
|
23
|
+
}
|
24
|
+
|
25
|
+
static VALUE ra(VALUE self, VALUE key, VALUE setting)
|
26
|
+
{
|
27
|
+
char * value;
|
28
|
+
void * data;
|
29
|
+
int size;
|
30
|
+
VALUE out;
|
31
|
+
|
32
|
+
data = NULL;
|
33
|
+
size = 0xDEADBEEF;
|
34
|
+
|
35
|
+
if(NIL_P(key) || NIL_P(setting)) return Qnil;
|
36
|
+
|
37
|
+
value = crypt_ra(
|
38
|
+
NIL_P(key) ? NULL : StringValuePtr(key),
|
39
|
+
NIL_P(setting) ? NULL : StringValuePtr(setting),
|
40
|
+
&data,
|
41
|
+
&size);
|
42
|
+
|
43
|
+
if(!value) return Qnil;
|
44
|
+
|
45
|
+
out = rb_str_new(data, size - 1);
|
46
|
+
|
47
|
+
free(data);
|
48
|
+
|
49
|
+
return out;
|
50
|
+
}
|
51
|
+
|
52
|
+
void Init_crypt()
|
53
|
+
{
|
54
|
+
mCrypt = rb_define_module("Crypt");
|
55
|
+
rb_define_singleton_method(mCrypt, "salt", crypt_salt, 3);
|
56
|
+
rb_define_singleton_method(mCrypt, "crypt", ra, 2);
|
57
|
+
}
|
data/ext/mri/crypt.h
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
/*
|
2
|
+
* Written by Solar Designer and placed in the public domain.
|
3
|
+
* See crypt_blowfish.c for more information.
|
4
|
+
*/
|
5
|
+
|
6
|
+
#include <gnu-crypt.h>
|
7
|
+
|
8
|
+
#if defined(_OW_SOURCE) || defined(__USE_OW)
|
9
|
+
#define __SKIP_GNU
|
10
|
+
#undef __SKIP_OW
|
11
|
+
#include <ow-crypt.h>
|
12
|
+
#undef __SKIP_GNU
|
13
|
+
#endif
|
@@ -1,119 +1,92 @@
|
|
1
|
-
/* $OpenBSD: blowfish.c,v 1.18 2004/11/02 17:23:26 hshoexer Exp $ */
|
2
1
|
/*
|
3
|
-
*
|
4
|
-
*
|
5
|
-
*
|
2
|
+
* This code comes from John the Ripper password cracker, with reentrant
|
3
|
+
* and crypt(3) interfaces added, but optimizations specific to password
|
4
|
+
* cracking removed.
|
6
5
|
*
|
7
|
-
*
|
6
|
+
* Written by Solar Designer <solar at openwall.com> in 1998-2002 and
|
7
|
+
* placed in the public domain. Quick self-test added in 2011 and also
|
8
|
+
* placed in the public domain.
|
8
9
|
*
|
9
|
-
*
|
10
|
-
* modification, are permitted provided that the following conditions
|
11
|
-
* are met:
|
12
|
-
* 1. Redistributions of source code must retain the above copyright
|
13
|
-
* notice, this list of conditions and the following disclaimer.
|
14
|
-
* 2. Redistributions in binary form must reproduce the above copyright
|
15
|
-
* notice, this list of conditions and the following disclaimer in the
|
16
|
-
* documentation and/or other materials provided with the distribution.
|
17
|
-
* 3. All advertising materials mentioning features or use of this software
|
18
|
-
* must display the following acknowledgement:
|
19
|
-
* This product includes software developed by Niels Provos.
|
20
|
-
* 4. The name of the author may not be used to endorse or promote products
|
21
|
-
* derived from this software without specific prior written permission.
|
10
|
+
* There's absolutely no warranty.
|
22
11
|
*
|
23
|
-
*
|
24
|
-
*
|
25
|
-
*
|
26
|
-
*
|
27
|
-
*
|
28
|
-
*
|
29
|
-
*
|
30
|
-
*
|
31
|
-
*
|
32
|
-
*
|
12
|
+
* It is my intent that you should be able to use this on your system,
|
13
|
+
* as a part of a software package, or anywhere else to improve security,
|
14
|
+
* ensure compatibility, or for any other purpose. I would appreciate
|
15
|
+
* it if you give credit where it is due and keep your modifications in
|
16
|
+
* the public domain as well, but I don't require that in order to let
|
17
|
+
* you place this code and any modifications you make under a license
|
18
|
+
* of your choice.
|
19
|
+
*
|
20
|
+
* This implementation is compatible with OpenBSD bcrypt.c (version 2a)
|
21
|
+
* by Niels Provos <provos at citi.umich.edu>, and uses some of his
|
22
|
+
* ideas. The password hashing algorithm was designed by David Mazieres
|
23
|
+
* <dm at lcs.mit.edu>.
|
24
|
+
*
|
25
|
+
* There's a paper on the algorithm that explains its design decisions:
|
26
|
+
*
|
27
|
+
* http://www.usenix.org/events/usenix99/provos.html
|
28
|
+
*
|
29
|
+
* Some of the tricks in BF_ROUND might be inspired by Eric Young's
|
30
|
+
* Blowfish library (I can't be sure if I would think of something if I
|
31
|
+
* hadn't seen his code).
|
33
32
|
*/
|
34
33
|
|
35
|
-
|
36
|
-
* This code is derived from section 14.3 and the given source
|
37
|
-
* in section V of Applied Cryptography, second edition.
|
38
|
-
* Blowfish is an unpatented fast block cipher designed by
|
39
|
-
* Bruce Schneier.
|
40
|
-
*/
|
34
|
+
#include <string.h>
|
41
35
|
|
42
|
-
#include
|
36
|
+
#include <errno.h>
|
37
|
+
#ifndef __set_errno
|
38
|
+
#define __set_errno(val) errno = (val)
|
39
|
+
#endif
|
43
40
|
|
44
|
-
#undef
|
41
|
+
#undef __CONST
|
45
42
|
#ifdef __GNUC__
|
46
|
-
#define
|
47
|
-
#else
|
48
|
-
#define
|
49
|
-
#endif
|
43
|
+
#define __CONST __const
|
44
|
+
#else
|
45
|
+
#define __CONST
|
46
|
+
#endif
|
50
47
|
|
51
|
-
/*
|
48
|
+
/*
|
49
|
+
* Please keep this enabled. We really don't want incompatible hashes to be
|
50
|
+
* produced. The performance cost of this quick self-test is around 0.6% at
|
51
|
+
* the "$2a$08" setting.
|
52
|
+
*/
|
53
|
+
#define BF_SELF_TEST
|
52
54
|
|
53
|
-
#
|
54
|
-
|
55
|
-
|
56
|
-
|
55
|
+
#if defined(__x86_64__) || defined(__alpha__) || defined(__hppa__)
|
56
|
+
#define BF_ASM 0
|
57
|
+
#define BF_SCALE 1
|
58
|
+
#else
|
59
|
+
#define BF_ASM 0
|
60
|
+
#define BF_SCALE 0
|
61
|
+
#endif
|
57
62
|
|
58
|
-
|
63
|
+
typedef unsigned int BF_word;
|
64
|
+
typedef signed int BF_word_signed;
|
59
65
|
|
60
|
-
|
61
|
-
|
62
|
-
{
|
63
|
-
uint32_t Xl;
|
64
|
-
uint32_t Xr;
|
65
|
-
uint32_t *s = c->S[0];
|
66
|
-
uint32_t *p = c->P;
|
67
|
-
|
68
|
-
Xl = *xl;
|
69
|
-
Xr = *xr;
|
70
|
-
|
71
|
-
Xl ^= p[0];
|
72
|
-
BLFRND(s, p, Xr, Xl, 1); BLFRND(s, p, Xl, Xr, 2);
|
73
|
-
BLFRND(s, p, Xr, Xl, 3); BLFRND(s, p, Xl, Xr, 4);
|
74
|
-
BLFRND(s, p, Xr, Xl, 5); BLFRND(s, p, Xl, Xr, 6);
|
75
|
-
BLFRND(s, p, Xr, Xl, 7); BLFRND(s, p, Xl, Xr, 8);
|
76
|
-
BLFRND(s, p, Xr, Xl, 9); BLFRND(s, p, Xl, Xr, 10);
|
77
|
-
BLFRND(s, p, Xr, Xl, 11); BLFRND(s, p, Xl, Xr, 12);
|
78
|
-
BLFRND(s, p, Xr, Xl, 13); BLFRND(s, p, Xl, Xr, 14);
|
79
|
-
BLFRND(s, p, Xr, Xl, 15); BLFRND(s, p, Xl, Xr, 16);
|
80
|
-
|
81
|
-
*xl = Xr ^ p[17];
|
82
|
-
*xr = Xl;
|
83
|
-
}
|
66
|
+
/* Number of Blowfish rounds, this is also hardcoded into a few places */
|
67
|
+
#define BF_N 16
|
84
68
|
|
85
|
-
|
86
|
-
Blowfish_decipher(blf_ctx *c, uint32_t *xl, uint32_t *xr)
|
87
|
-
{
|
88
|
-
uint32_t Xl;
|
89
|
-
uint32_t Xr;
|
90
|
-
uint32_t *s = c->S[0];
|
91
|
-
uint32_t *p = c->P;
|
92
|
-
|
93
|
-
Xl = *xl;
|
94
|
-
Xr = *xr;
|
95
|
-
|
96
|
-
Xl ^= p[17];
|
97
|
-
BLFRND(s, p, Xr, Xl, 16); BLFRND(s, p, Xl, Xr, 15);
|
98
|
-
BLFRND(s, p, Xr, Xl, 14); BLFRND(s, p, Xl, Xr, 13);
|
99
|
-
BLFRND(s, p, Xr, Xl, 12); BLFRND(s, p, Xl, Xr, 11);
|
100
|
-
BLFRND(s, p, Xr, Xl, 10); BLFRND(s, p, Xl, Xr, 9);
|
101
|
-
BLFRND(s, p, Xr, Xl, 8); BLFRND(s, p, Xl, Xr, 7);
|
102
|
-
BLFRND(s, p, Xr, Xl, 6); BLFRND(s, p, Xl, Xr, 5);
|
103
|
-
BLFRND(s, p, Xr, Xl, 4); BLFRND(s, p, Xl, Xr, 3);
|
104
|
-
BLFRND(s, p, Xr, Xl, 2); BLFRND(s, p, Xl, Xr, 1);
|
105
|
-
|
106
|
-
*xl = Xr ^ p[0];
|
107
|
-
*xr = Xl;
|
108
|
-
}
|
69
|
+
typedef BF_word BF_key[BF_N + 2];
|
109
70
|
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
71
|
+
typedef struct {
|
72
|
+
BF_word S[4][0x100];
|
73
|
+
BF_key P;
|
74
|
+
} BF_ctx;
|
114
75
|
|
115
|
-
|
116
|
-
|
76
|
+
/*
|
77
|
+
* Magic IV for 64 Blowfish encryptions that we do at the end.
|
78
|
+
* The string is "OrpheanBeholderScryDoubt" on big-endian.
|
79
|
+
*/
|
80
|
+
static BF_word BF_magic_w[6] = {
|
81
|
+
0x4F727068, 0x65616E42, 0x65686F6C,
|
82
|
+
0x64657253, 0x63727944, 0x6F756274
|
83
|
+
};
|
84
|
+
|
85
|
+
/*
|
86
|
+
* P-box and S-box tables initialized with digits of Pi.
|
87
|
+
*/
|
88
|
+
static BF_ctx BF_init_state = {
|
89
|
+
{
|
117
90
|
{
|
118
91
|
0xd1310ba6, 0x98dfb5ac, 0x2ffd72db, 0xd01adfb7,
|
119
92
|
0xb8e1afed, 0x6a267e96, 0xba7c9045, 0xf12c7f99,
|
@@ -178,8 +151,8 @@ Blowfish_initstate(blf_ctx *c)
|
|
178
151
|
0xd60f573f, 0xbc9bc6e4, 0x2b60a476, 0x81e67400,
|
179
152
|
0x08ba6fb5, 0x571be91f, 0xf296ec6b, 0x2a0dd915,
|
180
153
|
0xb6636521, 0xe7b9f9b6, 0xff34052e, 0xc5855664,
|
181
|
-
|
182
|
-
{
|
154
|
+
0x53b02d5d, 0xa99f8fa1, 0x08ba4799, 0x6e85076a
|
155
|
+
}, {
|
183
156
|
0x4b7a70e9, 0xb5b32944, 0xdb75092e, 0xc4192623,
|
184
157
|
0xad6ea6b0, 0x49a7df7d, 0x9cee60b8, 0x8fedb266,
|
185
158
|
0xecaa8c71, 0x699a17ff, 0x5664526c, 0xc2b19ee1,
|
@@ -243,8 +216,8 @@ Blowfish_initstate(blf_ctx *c)
|
|
243
216
|
0x9e447a2e, 0xc3453484, 0xfdd56705, 0x0e1e9ec9,
|
244
217
|
0xdb73dbd3, 0x105588cd, 0x675fda79, 0xe3674340,
|
245
218
|
0xc5c43465, 0x713e38d8, 0x3d28f89e, 0xf16dff20,
|
246
|
-
|
247
|
-
{
|
219
|
+
0x153e21e7, 0x8fb03d4a, 0xe6e39f2b, 0xdb83adf7
|
220
|
+
}, {
|
248
221
|
0xe93d5a68, 0x948140f7, 0xf64c261c, 0x94692934,
|
249
222
|
0x411520f7, 0x7602d4f7, 0xbcf46b2e, 0xd4a20068,
|
250
223
|
0xd4082471, 0x3320f46a, 0x43b7d4b7, 0x500061af,
|
@@ -308,8 +281,8 @@ Blowfish_initstate(blf_ctx *c)
|
|
308
281
|
0xed545578, 0x08fca5b5, 0xd83d7cd3, 0x4dad0fc4,
|
309
282
|
0x1e50ef5e, 0xb161e6f8, 0xa28514d9, 0x6c51133c,
|
310
283
|
0x6fd5c7e7, 0x56e14ec4, 0x362abfce, 0xddc6c837,
|
311
|
-
|
312
|
-
{
|
284
|
+
0xd79a3234, 0x92638212, 0x670efa8e, 0x406000e0
|
285
|
+
}, {
|
313
286
|
0x3a39ce37, 0xd3faf5cf, 0xabc27737, 0x5ac52d1b,
|
314
287
|
0x5cb0679e, 0x4fa33742, 0xd3822740, 0x99bc9bbe,
|
315
288
|
0xd5118e9d, 0xbf0f7315, 0xd62d1c7e, 0xc700c47b,
|
@@ -373,263 +346,441 @@ Blowfish_initstate(blf_ctx *c)
|
|
373
346
|
0x85cbfe4e, 0x8ae88dd8, 0x7aaaf9b0, 0x4cf9aa7e,
|
374
347
|
0x1948c25c, 0x02fb8a8c, 0x01c36ae4, 0xd6ebe1f9,
|
375
348
|
0x90d4f869, 0xa65cdea0, 0x3f09252d, 0xc208e69f,
|
376
|
-
|
377
|
-
|
378
|
-
{
|
349
|
+
0xb74e6132, 0xce77e25b, 0x578fdfe3, 0x3ac372e6
|
350
|
+
}
|
351
|
+
}, {
|
379
352
|
0x243f6a88, 0x85a308d3, 0x13198a2e, 0x03707344,
|
380
353
|
0xa4093822, 0x299f31d0, 0x082efa98, 0xec4e6c89,
|
381
354
|
0x452821e6, 0x38d01377, 0xbe5466cf, 0x34e90c6c,
|
382
355
|
0xc0ac29b7, 0xc97c50dd, 0x3f84d5b5, 0xb5470917,
|
383
356
|
0x9216d5d9, 0x8979fb1b
|
384
|
-
}
|
357
|
+
}
|
358
|
+
};
|
385
359
|
|
386
|
-
|
387
|
-
|
360
|
+
static unsigned char BF_itoa64[64 + 1] =
|
361
|
+
"./ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
|
388
362
|
|
389
|
-
|
390
|
-
|
391
|
-
|
392
|
-
|
393
|
-
|
394
|
-
|
395
|
-
|
363
|
+
static unsigned char BF_atoi64[0x60] = {
|
364
|
+
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 0, 1,
|
365
|
+
54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 64, 64, 64, 64, 64,
|
366
|
+
64, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
|
367
|
+
17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 64, 64, 64, 64, 64,
|
368
|
+
64, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42,
|
369
|
+
43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 64, 64, 64, 64, 64
|
370
|
+
};
|
396
371
|
|
397
|
-
|
398
|
-
|
372
|
+
/*
|
373
|
+
* This may be optimized out if built with function inlining and no BF_ASM.
|
374
|
+
*/
|
375
|
+
static void clean(void *data, int size)
|
376
|
+
{
|
377
|
+
memset(data, 0, size);
|
378
|
+
}
|
399
379
|
|
400
|
-
|
401
|
-
|
402
|
-
|
403
|
-
|
404
|
-
|
380
|
+
#define BF_safe_atoi64(dst, src) \
|
381
|
+
{ \
|
382
|
+
tmp = (unsigned char)(src); \
|
383
|
+
if ((unsigned int)(tmp -= 0x20) >= 0x60) return -1; \
|
384
|
+
tmp = BF_atoi64[tmp]; \
|
385
|
+
if (tmp > 63) return -1; \
|
386
|
+
(dst) = tmp; \
|
387
|
+
}
|
405
388
|
|
406
|
-
|
407
|
-
|
389
|
+
static int BF_decode(BF_word *dst, __CONST char *src, int size)
|
390
|
+
{
|
391
|
+
unsigned char *dptr = (unsigned char *)dst;
|
392
|
+
unsigned char *end = dptr + size;
|
393
|
+
unsigned char *sptr = (unsigned char *)src;
|
394
|
+
unsigned int tmp, c1, c2, c3, c4;
|
395
|
+
|
396
|
+
do {
|
397
|
+
BF_safe_atoi64(c1, *sptr++);
|
398
|
+
BF_safe_atoi64(c2, *sptr++);
|
399
|
+
*dptr++ = (c1 << 2) | ((c2 & 0x30) >> 4);
|
400
|
+
if (dptr >= end) break;
|
401
|
+
|
402
|
+
BF_safe_atoi64(c3, *sptr++);
|
403
|
+
*dptr++ = ((c2 & 0x0F) << 4) | ((c3 & 0x3C) >> 2);
|
404
|
+
if (dptr >= end) break;
|
405
|
+
|
406
|
+
BF_safe_atoi64(c4, *sptr++);
|
407
|
+
*dptr++ = ((c3 & 0x03) << 6) | c4;
|
408
|
+
} while (dptr < end);
|
409
|
+
|
410
|
+
return 0;
|
408
411
|
}
|
409
412
|
|
410
|
-
void
|
411
|
-
Blowfish_expand0state(blf_ctx *c, const uint8_t *key, uint16_t keybytes)
|
413
|
+
static void BF_encode(char *dst, __CONST BF_word *src, int size)
|
412
414
|
{
|
413
|
-
|
414
|
-
|
415
|
-
|
416
|
-
|
417
|
-
|
418
|
-
|
419
|
-
|
420
|
-
|
421
|
-
|
422
|
-
|
423
|
-
|
424
|
-
|
425
|
-
|
415
|
+
unsigned char *sptr = (unsigned char *)src;
|
416
|
+
unsigned char *end = sptr + size;
|
417
|
+
unsigned char *dptr = (unsigned char *)dst;
|
418
|
+
unsigned int c1, c2;
|
419
|
+
|
420
|
+
do {
|
421
|
+
c1 = *sptr++;
|
422
|
+
*dptr++ = BF_itoa64[c1 >> 2];
|
423
|
+
c1 = (c1 & 0x03) << 4;
|
424
|
+
if (sptr >= end) {
|
425
|
+
*dptr++ = BF_itoa64[c1];
|
426
|
+
break;
|
427
|
+
}
|
426
428
|
|
427
|
-
|
428
|
-
|
429
|
-
|
430
|
-
|
431
|
-
|
429
|
+
c2 = *sptr++;
|
430
|
+
c1 |= c2 >> 4;
|
431
|
+
*dptr++ = BF_itoa64[c1];
|
432
|
+
c1 = (c2 & 0x0f) << 2;
|
433
|
+
if (sptr >= end) {
|
434
|
+
*dptr++ = BF_itoa64[c1];
|
435
|
+
break;
|
436
|
+
}
|
432
437
|
|
433
|
-
|
434
|
-
|
435
|
-
|
438
|
+
c2 = *sptr++;
|
439
|
+
c1 |= c2 >> 6;
|
440
|
+
*dptr++ = BF_itoa64[c1];
|
441
|
+
*dptr++ = BF_itoa64[c2 & 0x3f];
|
442
|
+
} while (sptr < end);
|
443
|
+
}
|
436
444
|
|
437
|
-
|
438
|
-
|
439
|
-
|
445
|
+
static void BF_swap(BF_word *x, int count)
|
446
|
+
{
|
447
|
+
static int endianness_check = 1;
|
448
|
+
char *is_little_endian = (char *)&endianness_check;
|
449
|
+
BF_word tmp;
|
450
|
+
|
451
|
+
if (*is_little_endian)
|
452
|
+
do {
|
453
|
+
tmp = *x;
|
454
|
+
tmp = (tmp << 16) | (tmp >> 16);
|
455
|
+
*x++ = ((tmp & 0x00FF00FF) << 8) | ((tmp >> 8) & 0x00FF00FF);
|
456
|
+
} while (--count);
|
457
|
+
}
|
440
458
|
|
441
|
-
|
442
|
-
|
459
|
+
#if BF_SCALE
|
460
|
+
/* Architectures which can shift addresses left by 2 bits with no extra cost */
|
461
|
+
#define BF_ROUND(L, R, N) \
|
462
|
+
tmp1 = L & 0xFF; \
|
463
|
+
tmp2 = L >> 8; \
|
464
|
+
tmp2 &= 0xFF; \
|
465
|
+
tmp3 = L >> 16; \
|
466
|
+
tmp3 &= 0xFF; \
|
467
|
+
tmp4 = L >> 24; \
|
468
|
+
tmp1 = data.ctx.S[3][tmp1]; \
|
469
|
+
tmp2 = data.ctx.S[2][tmp2]; \
|
470
|
+
tmp3 = data.ctx.S[1][tmp3]; \
|
471
|
+
tmp3 += data.ctx.S[0][tmp4]; \
|
472
|
+
tmp3 ^= tmp2; \
|
473
|
+
R ^= data.ctx.P[N + 1]; \
|
474
|
+
tmp3 += tmp1; \
|
475
|
+
R ^= tmp3;
|
476
|
+
#else
|
477
|
+
/* Architectures with no complicated addressing modes supported */
|
478
|
+
#define BF_INDEX(S, i) \
|
479
|
+
(*((BF_word *)(((unsigned char *)S) + (i))))
|
480
|
+
#define BF_ROUND(L, R, N) \
|
481
|
+
tmp1 = L & 0xFF; \
|
482
|
+
tmp1 <<= 2; \
|
483
|
+
tmp2 = L >> 6; \
|
484
|
+
tmp2 &= 0x3FC; \
|
485
|
+
tmp3 = L >> 14; \
|
486
|
+
tmp3 &= 0x3FC; \
|
487
|
+
tmp4 = L >> 22; \
|
488
|
+
tmp4 &= 0x3FC; \
|
489
|
+
tmp1 = BF_INDEX(data.ctx.S[3], tmp1); \
|
490
|
+
tmp2 = BF_INDEX(data.ctx.S[2], tmp2); \
|
491
|
+
tmp3 = BF_INDEX(data.ctx.S[1], tmp3); \
|
492
|
+
tmp3 += BF_INDEX(data.ctx.S[0], tmp4); \
|
493
|
+
tmp3 ^= tmp2; \
|
494
|
+
R ^= data.ctx.P[N + 1]; \
|
495
|
+
tmp3 += tmp1; \
|
496
|
+
R ^= tmp3;
|
497
|
+
#endif
|
498
|
+
|
499
|
+
/*
|
500
|
+
* Encrypt one block, BF_N is hardcoded here.
|
501
|
+
*/
|
502
|
+
#define BF_ENCRYPT \
|
503
|
+
L ^= data.ctx.P[0]; \
|
504
|
+
BF_ROUND(L, R, 0); \
|
505
|
+
BF_ROUND(R, L, 1); \
|
506
|
+
BF_ROUND(L, R, 2); \
|
507
|
+
BF_ROUND(R, L, 3); \
|
508
|
+
BF_ROUND(L, R, 4); \
|
509
|
+
BF_ROUND(R, L, 5); \
|
510
|
+
BF_ROUND(L, R, 6); \
|
511
|
+
BF_ROUND(R, L, 7); \
|
512
|
+
BF_ROUND(L, R, 8); \
|
513
|
+
BF_ROUND(R, L, 9); \
|
514
|
+
BF_ROUND(L, R, 10); \
|
515
|
+
BF_ROUND(R, L, 11); \
|
516
|
+
BF_ROUND(L, R, 12); \
|
517
|
+
BF_ROUND(R, L, 13); \
|
518
|
+
BF_ROUND(L, R, 14); \
|
519
|
+
BF_ROUND(R, L, 15); \
|
520
|
+
tmp4 = R; \
|
521
|
+
R = L; \
|
522
|
+
L = tmp4 ^ data.ctx.P[BF_N + 1];
|
523
|
+
|
524
|
+
#define BF_body() \
|
525
|
+
L = R = 0; \
|
526
|
+
ptr = data.ctx.P; \
|
527
|
+
do { \
|
528
|
+
ptr += 2; \
|
529
|
+
BF_ENCRYPT; \
|
530
|
+
*(ptr - 2) = L; \
|
531
|
+
*(ptr - 1) = R; \
|
532
|
+
} while (ptr < &data.ctx.P[BF_N + 2]); \
|
533
|
+
\
|
534
|
+
ptr = data.ctx.S[0]; \
|
535
|
+
do { \
|
536
|
+
ptr += 2; \
|
537
|
+
BF_ENCRYPT; \
|
538
|
+
*(ptr - 2) = L; \
|
539
|
+
*(ptr - 1) = R; \
|
540
|
+
} while (ptr < &data.ctx.S[3][0xFF]);
|
541
|
+
|
542
|
+
static void BF_set_key(__CONST char *key, BF_key expanded, BF_key initial,
|
543
|
+
int sign_extension_bug)
|
544
|
+
{
|
545
|
+
__CONST char *ptr = key;
|
546
|
+
int i, j;
|
547
|
+
BF_word tmp;
|
548
|
+
|
549
|
+
for (i = 0; i < BF_N + 2; i++) {
|
550
|
+
tmp = 0;
|
551
|
+
for (j = 0; j < 4; j++) {
|
552
|
+
tmp <<= 8;
|
553
|
+
if (sign_extension_bug)
|
554
|
+
tmp |= (BF_word_signed)(signed char)*ptr;
|
555
|
+
else
|
556
|
+
tmp |= (unsigned char)*ptr;
|
557
|
+
|
558
|
+
if (!*ptr) ptr = key; else ptr++;
|
443
559
|
}
|
560
|
+
|
561
|
+
expanded[i] = tmp;
|
562
|
+
initial[i] = BF_init_state.P[i] ^ tmp;
|
444
563
|
}
|
445
564
|
}
|
446
565
|
|
447
|
-
|
448
|
-
|
449
|
-
|
450
|
-
const uint8_t *key, uint16_t keybytes)
|
566
|
+
static char *BF_crypt(__CONST char *key, __CONST char *setting,
|
567
|
+
char *output, int size,
|
568
|
+
BF_word min)
|
451
569
|
{
|
452
|
-
|
453
|
-
|
454
|
-
|
455
|
-
|
456
|
-
|
457
|
-
|
458
|
-
|
459
|
-
|
460
|
-
|
461
|
-
|
462
|
-
|
463
|
-
|
570
|
+
struct {
|
571
|
+
BF_ctx ctx;
|
572
|
+
BF_key expanded_key;
|
573
|
+
union {
|
574
|
+
BF_word salt[4];
|
575
|
+
BF_word output[6];
|
576
|
+
} binary;
|
577
|
+
} data;
|
578
|
+
BF_word L, R;
|
579
|
+
BF_word tmp1, tmp2, tmp3, tmp4;
|
580
|
+
BF_word *ptr;
|
581
|
+
BF_word count;
|
582
|
+
int i;
|
583
|
+
|
584
|
+
if (size < 7 + 22 + 31 + 1) {
|
585
|
+
__set_errno(ERANGE);
|
586
|
+
return NULL;
|
464
587
|
}
|
465
588
|
|
466
|
-
|
467
|
-
|
468
|
-
|
469
|
-
|
470
|
-
|
471
|
-
|
472
|
-
|
589
|
+
if (setting[0] != '$' ||
|
590
|
+
setting[1] != '2' ||
|
591
|
+
(setting[2] != 'a' && setting[2] != 'x') ||
|
592
|
+
setting[3] != '$' ||
|
593
|
+
setting[4] < '0' || setting[4] > '3' ||
|
594
|
+
setting[5] < '0' || setting[5] > '9' ||
|
595
|
+
(setting[4] == '3' && setting[5] > '1') ||
|
596
|
+
setting[6] != '$') {
|
597
|
+
__set_errno(EINVAL);
|
598
|
+
return NULL;
|
599
|
+
}
|
473
600
|
|
474
|
-
|
475
|
-
|
601
|
+
count = (BF_word)1 << ((setting[4] - '0') * 10 + (setting[5] - '0'));
|
602
|
+
if (count < min || BF_decode(data.binary.salt, &setting[7], 16)) {
|
603
|
+
clean(data.binary.salt, sizeof(data.binary.salt));
|
604
|
+
__set_errno(EINVAL);
|
605
|
+
return NULL;
|
476
606
|
}
|
607
|
+
BF_swap(data.binary.salt, 4);
|
477
608
|
|
478
|
-
|
479
|
-
for (k = 0; k < 256; k += 2) {
|
480
|
-
datal ^= Blowfish_stream2word(data, databytes, &j);
|
481
|
-
datar ^= Blowfish_stream2word(data, databytes, &j);
|
482
|
-
Blowfish_encipher(c, &datal, &datar);
|
609
|
+
BF_set_key(key, data.expanded_key, data.ctx.P, setting[2] == 'x');
|
483
610
|
|
484
|
-
|
485
|
-
|
486
|
-
|
611
|
+
memcpy(data.ctx.S, BF_init_state.S, sizeof(data.ctx.S));
|
612
|
+
|
613
|
+
L = R = 0;
|
614
|
+
for (i = 0; i < BF_N + 2; i += 2) {
|
615
|
+
L ^= data.binary.salt[i & 2];
|
616
|
+
R ^= data.binary.salt[(i & 2) + 1];
|
617
|
+
BF_ENCRYPT;
|
618
|
+
data.ctx.P[i] = L;
|
619
|
+
data.ctx.P[i + 1] = R;
|
487
620
|
}
|
488
621
|
|
489
|
-
|
622
|
+
ptr = data.ctx.S[0];
|
623
|
+
do {
|
624
|
+
ptr += 4;
|
625
|
+
L ^= data.binary.salt[(BF_N + 2) & 3];
|
626
|
+
R ^= data.binary.salt[(BF_N + 3) & 3];
|
627
|
+
BF_ENCRYPT;
|
628
|
+
*(ptr - 4) = L;
|
629
|
+
*(ptr - 3) = R;
|
630
|
+
|
631
|
+
L ^= data.binary.salt[(BF_N + 4) & 3];
|
632
|
+
R ^= data.binary.salt[(BF_N + 5) & 3];
|
633
|
+
BF_ENCRYPT;
|
634
|
+
*(ptr - 2) = L;
|
635
|
+
*(ptr - 1) = R;
|
636
|
+
} while (ptr < &data.ctx.S[3][0xFF]);
|
637
|
+
|
638
|
+
do {
|
639
|
+
data.ctx.P[0] ^= data.expanded_key[0];
|
640
|
+
data.ctx.P[1] ^= data.expanded_key[1];
|
641
|
+
data.ctx.P[2] ^= data.expanded_key[2];
|
642
|
+
data.ctx.P[3] ^= data.expanded_key[3];
|
643
|
+
data.ctx.P[4] ^= data.expanded_key[4];
|
644
|
+
data.ctx.P[5] ^= data.expanded_key[5];
|
645
|
+
data.ctx.P[6] ^= data.expanded_key[6];
|
646
|
+
data.ctx.P[7] ^= data.expanded_key[7];
|
647
|
+
data.ctx.P[8] ^= data.expanded_key[8];
|
648
|
+
data.ctx.P[9] ^= data.expanded_key[9];
|
649
|
+
data.ctx.P[10] ^= data.expanded_key[10];
|
650
|
+
data.ctx.P[11] ^= data.expanded_key[11];
|
651
|
+
data.ctx.P[12] ^= data.expanded_key[12];
|
652
|
+
data.ctx.P[13] ^= data.expanded_key[13];
|
653
|
+
data.ctx.P[14] ^= data.expanded_key[14];
|
654
|
+
data.ctx.P[15] ^= data.expanded_key[15];
|
655
|
+
data.ctx.P[16] ^= data.expanded_key[16];
|
656
|
+
data.ctx.P[17] ^= data.expanded_key[17];
|
657
|
+
|
658
|
+
BF_body();
|
659
|
+
|
660
|
+
tmp1 = data.binary.salt[0];
|
661
|
+
tmp2 = data.binary.salt[1];
|
662
|
+
tmp3 = data.binary.salt[2];
|
663
|
+
tmp4 = data.binary.salt[3];
|
664
|
+
data.ctx.P[0] ^= tmp1;
|
665
|
+
data.ctx.P[1] ^= tmp2;
|
666
|
+
data.ctx.P[2] ^= tmp3;
|
667
|
+
data.ctx.P[3] ^= tmp4;
|
668
|
+
data.ctx.P[4] ^= tmp1;
|
669
|
+
data.ctx.P[5] ^= tmp2;
|
670
|
+
data.ctx.P[6] ^= tmp3;
|
671
|
+
data.ctx.P[7] ^= tmp4;
|
672
|
+
data.ctx.P[8] ^= tmp1;
|
673
|
+
data.ctx.P[9] ^= tmp2;
|
674
|
+
data.ctx.P[10] ^= tmp3;
|
675
|
+
data.ctx.P[11] ^= tmp4;
|
676
|
+
data.ctx.P[12] ^= tmp1;
|
677
|
+
data.ctx.P[13] ^= tmp2;
|
678
|
+
data.ctx.P[14] ^= tmp3;
|
679
|
+
data.ctx.P[15] ^= tmp4;
|
680
|
+
data.ctx.P[16] ^= tmp1;
|
681
|
+
data.ctx.P[17] ^= tmp2;
|
682
|
+
|
683
|
+
BF_body();
|
684
|
+
} while (--count);
|
685
|
+
|
686
|
+
for (i = 0; i < 6; i += 2) {
|
687
|
+
L = BF_magic_w[i];
|
688
|
+
R = BF_magic_w[i + 1];
|
689
|
+
|
690
|
+
count = 64;
|
691
|
+
do {
|
692
|
+
BF_ENCRYPT;
|
693
|
+
} while (--count);
|
694
|
+
|
695
|
+
data.binary.output[i] = L;
|
696
|
+
data.binary.output[i + 1] = R;
|
697
|
+
}
|
490
698
|
|
491
|
-
|
492
|
-
|
493
|
-
|
494
|
-
/* Initialize S-boxes and subkeys with Pi */
|
495
|
-
Blowfish_initstate(c);
|
699
|
+
memcpy(output, setting, 7 + 22 - 1);
|
700
|
+
output[7 + 22 - 1] = BF_itoa64[(int)
|
701
|
+
BF_atoi64[(int)setting[7 + 22 - 1] - 0x20] & 0x30];
|
496
702
|
|
497
|
-
|
498
|
-
|
499
|
-
|
703
|
+
/* This has to be bug-compatible with the original implementation, so
|
704
|
+
* only encode 23 of the 24 bytes. :-) */
|
705
|
+
BF_swap(data.binary.output, 6);
|
706
|
+
BF_encode(&output[7 + 22], data.binary.output, 23);
|
707
|
+
output[7 + 22 + 31] = '\0';
|
500
708
|
|
501
|
-
|
502
|
-
|
503
|
-
|
504
|
-
|
505
|
-
|
709
|
+
#ifndef BF_SELF_TEST
|
710
|
+
/* Overwrite the most obvious sensitive data we have on the stack. Note
|
711
|
+
* that this does not guarantee there's no sensitive data left on the
|
712
|
+
* stack and/or in registers; I'm not aware of portable code that does. */
|
713
|
+
clean(&data, sizeof(data));
|
714
|
+
#endif
|
506
715
|
|
507
|
-
|
508
|
-
for (i = 0; i < blocks; i++) {
|
509
|
-
Blowfish_encipher(c, d, d + 1);
|
510
|
-
d += 2;
|
511
|
-
}
|
716
|
+
return output;
|
512
717
|
}
|
513
718
|
|
514
|
-
|
515
|
-
|
719
|
+
char *_crypt_blowfish_rn(__CONST char *key, __CONST char *setting,
|
720
|
+
char *output, int size)
|
516
721
|
{
|
517
|
-
|
518
|
-
|
519
|
-
|
520
|
-
|
521
|
-
|
522
|
-
|
523
|
-
|
524
|
-
|
722
|
+
#ifdef BF_SELF_TEST
|
723
|
+
__CONST char *test_key = "8b \xd0\xc1\xd2\xcf\xcc\xd8";
|
724
|
+
__CONST char *test_2a =
|
725
|
+
"$2a$00$abcdefghijklmnopqrstuui1D709vfamulimlGcq0qq3UvuUasvEa"
|
726
|
+
"\0"
|
727
|
+
"canary";
|
728
|
+
__CONST char *test_2x =
|
729
|
+
"$2x$00$abcdefghijklmnopqrstuuVUrPmXD6q/nVSSp7pNDhCR9071IfIRe"
|
730
|
+
"\0"
|
731
|
+
"canary";
|
732
|
+
__CONST char *test_hash, *p;
|
733
|
+
int ok;
|
734
|
+
char buf[7 + 22 + 31 + 1 + 6 + 1];
|
735
|
+
|
736
|
+
output = BF_crypt(key, setting, output, size, 16);
|
737
|
+
|
738
|
+
/* Do a quick self-test. This also happens to overwrite BF_crypt()'s data. */
|
739
|
+
test_hash = (setting[2] == 'x') ? test_2x : test_2a;
|
740
|
+
memcpy(buf, test_hash, sizeof(buf));
|
741
|
+
memset(buf, -1, sizeof(buf) - (6 + 1)); /* keep "canary" only */
|
742
|
+
p = BF_crypt(test_key, test_hash, buf, sizeof(buf) - 6, 1);
|
743
|
+
|
744
|
+
ok = (p == buf && !memcmp(p, test_hash, sizeof(buf)));
|
745
|
+
|
746
|
+
/* This could reveal what hash type we were using last. Unfortunately, we
|
747
|
+
* can't reliably clean the test_hash pointer. */
|
748
|
+
clean(&buf, sizeof(buf));
|
749
|
+
|
750
|
+
if (ok)
|
751
|
+
return output;
|
752
|
+
|
753
|
+
/* Should not happen */
|
754
|
+
__set_errno(EINVAL); /* pretend we don't support this hash type */
|
755
|
+
return NULL;
|
756
|
+
#else
|
757
|
+
#warning Self-test is disabled, please enable
|
758
|
+
return BF_crypt(key, setting, output, size, 16);
|
759
|
+
#endif
|
525
760
|
}
|
526
761
|
|
527
|
-
|
528
|
-
|
762
|
+
char *_crypt_gensalt_blowfish_rn(unsigned long count,
|
763
|
+
__CONST char *input, int size, char *output, int output_size)
|
529
764
|
{
|
530
|
-
|
531
|
-
|
532
|
-
|
533
|
-
|
534
|
-
|
535
|
-
r = data[4] << 24 | data[5] << 16 | data[6] << 8 | data[7];
|
536
|
-
Blowfish_encipher(c, &l, &r);
|
537
|
-
data[0] = l >> 24 & 0xff;
|
538
|
-
data[1] = l >> 16 & 0xff;
|
539
|
-
data[2] = l >> 8 & 0xff;
|
540
|
-
data[3] = l & 0xff;
|
541
|
-
data[4] = r >> 24 & 0xff;
|
542
|
-
data[5] = r >> 16 & 0xff;
|
543
|
-
data[6] = r >> 8 & 0xff;
|
544
|
-
data[7] = r & 0xff;
|
545
|
-
data += 8;
|
765
|
+
if (size < 16 || output_size < 7 + 22 + 1 ||
|
766
|
+
(count && (count < 4 || count > 31))) {
|
767
|
+
if (output_size > 0) output[0] = '\0';
|
768
|
+
__set_errno((output_size < 7 + 22 + 1) ? ERANGE : EINVAL);
|
769
|
+
return NULL;
|
546
770
|
}
|
547
|
-
}
|
548
771
|
|
549
|
-
|
550
|
-
blf_ecb_decrypt(blf_ctx *c, uint8_t *data, uint32_t len)
|
551
|
-
{
|
552
|
-
uint32_t l, r;
|
553
|
-
uint32_t i;
|
554
|
-
|
555
|
-
for (i = 0; i < len; i += 8) {
|
556
|
-
l = data[0] << 24 | data[1] << 16 | data[2] << 8 | data[3];
|
557
|
-
r = data[4] << 24 | data[5] << 16 | data[6] << 8 | data[7];
|
558
|
-
Blowfish_decipher(c, &l, &r);
|
559
|
-
data[0] = l >> 24 & 0xff;
|
560
|
-
data[1] = l >> 16 & 0xff;
|
561
|
-
data[2] = l >> 8 & 0xff;
|
562
|
-
data[3] = l & 0xff;
|
563
|
-
data[4] = r >> 24 & 0xff;
|
564
|
-
data[5] = r >> 16 & 0xff;
|
565
|
-
data[6] = r >> 8 & 0xff;
|
566
|
-
data[7] = r & 0xff;
|
567
|
-
data += 8;
|
568
|
-
}
|
569
|
-
}
|
772
|
+
if (!count) count = 5;
|
570
773
|
|
571
|
-
|
572
|
-
|
573
|
-
|
574
|
-
|
575
|
-
|
576
|
-
|
577
|
-
|
578
|
-
for (j = 0; j < 8; j++)
|
579
|
-
data[j] ^= iv[j];
|
580
|
-
l = data[0] << 24 | data[1] << 16 | data[2] << 8 | data[3];
|
581
|
-
r = data[4] << 24 | data[5] << 16 | data[6] << 8 | data[7];
|
582
|
-
Blowfish_encipher(c, &l, &r);
|
583
|
-
data[0] = l >> 24 & 0xff;
|
584
|
-
data[1] = l >> 16 & 0xff;
|
585
|
-
data[2] = l >> 8 & 0xff;
|
586
|
-
data[3] = l & 0xff;
|
587
|
-
data[4] = r >> 24 & 0xff;
|
588
|
-
data[5] = r >> 16 & 0xff;
|
589
|
-
data[6] = r >> 8 & 0xff;
|
590
|
-
data[7] = r & 0xff;
|
591
|
-
iv = data;
|
592
|
-
data += 8;
|
593
|
-
}
|
594
|
-
}
|
774
|
+
output[0] = '$';
|
775
|
+
output[1] = '2';
|
776
|
+
output[2] = 'a';
|
777
|
+
output[3] = '$';
|
778
|
+
output[4] = '0' + count / 10;
|
779
|
+
output[5] = '0' + count % 10;
|
780
|
+
output[6] = '$';
|
595
781
|
|
596
|
-
|
597
|
-
|
598
|
-
|
599
|
-
|
600
|
-
uint8_t *iv;
|
601
|
-
uint32_t i, j;
|
602
|
-
|
603
|
-
iv = data + len - 16;
|
604
|
-
data = data + len - 8;
|
605
|
-
for (i = len - 8; i >= 8; i -= 8) {
|
606
|
-
l = data[0] << 24 | data[1] << 16 | data[2] << 8 | data[3];
|
607
|
-
r = data[4] << 24 | data[5] << 16 | data[6] << 8 | data[7];
|
608
|
-
Blowfish_decipher(c, &l, &r);
|
609
|
-
data[0] = l >> 24 & 0xff;
|
610
|
-
data[1] = l >> 16 & 0xff;
|
611
|
-
data[2] = l >> 8 & 0xff;
|
612
|
-
data[3] = l & 0xff;
|
613
|
-
data[4] = r >> 24 & 0xff;
|
614
|
-
data[5] = r >> 16 & 0xff;
|
615
|
-
data[6] = r >> 8 & 0xff;
|
616
|
-
data[7] = r & 0xff;
|
617
|
-
for (j = 0; j < 8; j++)
|
618
|
-
data[j] ^= iv[j];
|
619
|
-
iv -= 8;
|
620
|
-
data -= 8;
|
621
|
-
}
|
622
|
-
l = data[0] << 24 | data[1] << 16 | data[2] << 8 | data[3];
|
623
|
-
r = data[4] << 24 | data[5] << 16 | data[6] << 8 | data[7];
|
624
|
-
Blowfish_decipher(c, &l, &r);
|
625
|
-
data[0] = l >> 24 & 0xff;
|
626
|
-
data[1] = l >> 16 & 0xff;
|
627
|
-
data[2] = l >> 8 & 0xff;
|
628
|
-
data[3] = l & 0xff;
|
629
|
-
data[4] = r >> 24 & 0xff;
|
630
|
-
data[5] = r >> 16 & 0xff;
|
631
|
-
data[6] = r >> 8 & 0xff;
|
632
|
-
data[7] = r & 0xff;
|
633
|
-
for (j = 0; j < 8; j++)
|
634
|
-
data[j] ^= iva[j];
|
782
|
+
BF_encode(&output[7], (BF_word *)input, 16);
|
783
|
+
output[7 + 22] = '\0';
|
784
|
+
|
785
|
+
return output;
|
635
786
|
}
|