bcrypt-ruby 2.1.4-x86-mswin32-60 → 3.0.0-x86-mswin32-60
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
}
|