string-crypt 0.9.0
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.
- checksums.yaml +7 -0
- data/BSDL +22 -0
- data/CHANGELOG +3 -0
- data/README.rdoc +67 -0
- data/Rakefile +20 -0
- data/ext/string/crypt/crypt.c +103 -0
- data/ext/string/crypt/extconf.rb +61 -0
- data/ext/string/crypt/missing/crypt.c +888 -0
- data/ext/string/crypt/missing/crypt.h +242 -0
- data/ext/string/crypt/missing/des_tables.c +1616 -0
- data/test/test_string_crypt.rb +39 -0
- metadata +56 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: ba5c931398a8376cf8e8a13ac3c3fe7a84e5923c08b2d61adae2faf4b8182c96
|
4
|
+
data.tar.gz: 92de76e27edeaea32b3e51bd26b3e5206d4192f3943a175eb3afbb83ba79dc6f
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 3108245fc24192cb48e06d1d13d498371407d392f343ac3df81c3c73d178621cf0832058c969120418487cbcdc24425a389b754d40de701dc7bf81f9cbf994d1
|
7
|
+
data.tar.gz: 7987b1ca426ade3a11c8805ba81cf455da674c1b8f686fa77d2586843cba6fd4da3755c40b4412edfcede7d34771a2c141388dbcabc7d0af130757ccda36d60f
|
data/BSDL
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (C) 1993-2013 Yukihiro Matsumoto. All rights reserved.
|
2
|
+
|
3
|
+
Redistribution and use in source and binary forms, with or without
|
4
|
+
modification, are permitted provided that the following conditions
|
5
|
+
are met:
|
6
|
+
1. Redistributions of source code must retain the above copyright
|
7
|
+
notice, this list of conditions and the following disclaimer.
|
8
|
+
2. Redistributions in binary form must reproduce the above copyright
|
9
|
+
notice, this list of conditions and the following disclaimer in the
|
10
|
+
documentation and/or other materials provided with the distribution.
|
11
|
+
|
12
|
+
THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
13
|
+
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
14
|
+
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
15
|
+
ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
16
|
+
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
17
|
+
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
18
|
+
OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
19
|
+
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
20
|
+
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
21
|
+
OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
22
|
+
SUCH DAMAGE.
|
data/CHANGELOG
ADDED
data/README.rdoc
ADDED
@@ -0,0 +1,67 @@
|
|
1
|
+
= ruby-string-crypt
|
2
|
+
|
3
|
+
ruby-string-crypt is a backwards compatible implementation of
|
4
|
+
String#crypt for Ruby, so that the core String#crypt can be deprecated
|
5
|
+
and later removed.
|
6
|
+
|
7
|
+
String#crypt calls crypt(3) or crypt_r(3) for operating system-specific
|
8
|
+
password hashing. In cases where neither crypt(3) nor crypt_r(3) is
|
9
|
+
available, a DES-crypt implementation is used. DES-crypt should be
|
10
|
+
considered insecure, and users are strongly recommended to switch to a
|
11
|
+
secure password hashing library such as bcrypt, scrypt, or argon2.
|
12
|
+
|
13
|
+
== Usage
|
14
|
+
|
15
|
+
# Generate new password hash.
|
16
|
+
# Salt is an operating system specific string.
|
17
|
+
password_hash = "password".crypt(salt)
|
18
|
+
|
19
|
+
# Check for matching password hash.
|
20
|
+
# This is insecure as it is vulnerable to a timing attack.
|
21
|
+
"password".crypt(password_hash) == password_hash
|
22
|
+
|
23
|
+
# More secure method of checking for matching password hash
|
24
|
+
Rack::Utils.secure_compare(password_hash, "password".crypt(password_hash))
|
25
|
+
|
26
|
+
== Installing the gem
|
27
|
+
|
28
|
+
gem install string-crypt
|
29
|
+
|
30
|
+
If you want to have the library skip using crypt(3) or crypt_r(3) and
|
31
|
+
force the internal DES-crypt implementation:
|
32
|
+
|
33
|
+
STRING_CRYPT_FORCE_MISSING=1 gem install string-crypt
|
34
|
+
|
35
|
+
== Running the tests
|
36
|
+
|
37
|
+
In the repository:
|
38
|
+
|
39
|
+
rake test
|
40
|
+
|
41
|
+
This requires rake-compiler to compile the library, and minitest for
|
42
|
+
testing.
|
43
|
+
|
44
|
+
== Reporting issues/bugs
|
45
|
+
|
46
|
+
ruby-string-crypt uses GitHub Issues for tracking issues/bugs:
|
47
|
+
|
48
|
+
https://github.com/jeremyevans/ruby-string-crypt/issues
|
49
|
+
|
50
|
+
== Contributing
|
51
|
+
|
52
|
+
The source code is on GitHub:
|
53
|
+
|
54
|
+
https://github.com/jeremyevans/ruby-string-crypt
|
55
|
+
|
56
|
+
To get a copy:
|
57
|
+
|
58
|
+
git clone git://github.com/jeremyevans/ruby-string-crypt.git
|
59
|
+
|
60
|
+
== Platforms Supported
|
61
|
+
|
62
|
+
Ruby 2.1+ is supported. This library does not currently offer
|
63
|
+
support for JRuby.
|
64
|
+
|
65
|
+
== Maintainer
|
66
|
+
|
67
|
+
Jeremy Evans <code@jeremyevans.net>
|
data/Rakefile
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
require "rake"
|
2
|
+
require "rake/clean"
|
3
|
+
|
4
|
+
CLEAN.include %w'tmp string-crypt-*.gem lib'
|
5
|
+
|
6
|
+
desc "Build the gem"
|
7
|
+
task :package => :clean do
|
8
|
+
sh %{gem build string-crypt.gemspec}
|
9
|
+
end
|
10
|
+
|
11
|
+
begin
|
12
|
+
require 'rake/extensiontask'
|
13
|
+
Rake::ExtensionTask.new('string/crypt')
|
14
|
+
|
15
|
+
desc "Run tests"
|
16
|
+
task :test => :compile do
|
17
|
+
sh "#{FileUtils::RUBY} -w test/test_string_crypt.rb"
|
18
|
+
end
|
19
|
+
rescue LoadError
|
20
|
+
end
|
@@ -0,0 +1,103 @@
|
|
1
|
+
#include <errno.h>
|
2
|
+
|
3
|
+
#include "ruby.h"
|
4
|
+
#include "ruby/encoding.h"
|
5
|
+
|
6
|
+
#if defined HAVE_STRING_CRYPT_R
|
7
|
+
# if defined HAVE_STRING_CRYPT_H
|
8
|
+
# include <crypt.h>
|
9
|
+
# endif
|
10
|
+
#elif !defined HAVE_STRING_CRYPT
|
11
|
+
# include "missing/crypt.h"
|
12
|
+
# include "missing/crypt.c"
|
13
|
+
# define HAVE_STRING_CRYPT_R 1
|
14
|
+
#endif
|
15
|
+
|
16
|
+
static void
|
17
|
+
mustnot_wchar(VALUE str)
|
18
|
+
{
|
19
|
+
rb_encoding *enc = rb_enc_get(str);
|
20
|
+
if (rb_enc_mbminlen(enc) > 1) {
|
21
|
+
rb_raise(rb_eArgError, "wide char encoding: %s", rb_enc_name(enc));
|
22
|
+
}
|
23
|
+
}
|
24
|
+
|
25
|
+
/*
|
26
|
+
* call-seq:
|
27
|
+
* str.crypt(salt_str) -> new_str
|
28
|
+
*
|
29
|
+
* Applies a one-way cryptographic hash to <i>str</i> by invoking the
|
30
|
+
* standard library function <code>crypt(3)</code> with the given
|
31
|
+
* salt string. While the format and the result are system and
|
32
|
+
* implementation dependent, using a salt matching the regular
|
33
|
+
* expression <code>\A[a-zA-Z0-9./]{2}</code> should work on most
|
34
|
+
* most platforms, but on those platforms it uses insecure DES
|
35
|
+
* encryption, and only the first two characters of the salt string
|
36
|
+
* are significant.
|
37
|
+
*
|
38
|
+
* This method is for use in system specific scripts, so if you want
|
39
|
+
* a cross-platform hash function consider using Digest or OpenSSL
|
40
|
+
* instead.
|
41
|
+
*/
|
42
|
+
|
43
|
+
static VALUE
|
44
|
+
rb_string_crypt(VALUE str, VALUE salt)
|
45
|
+
{
|
46
|
+
#ifdef HAVE_STRING_CRYPT_R
|
47
|
+
VALUE databuf;
|
48
|
+
struct crypt_data *data;
|
49
|
+
# define STRING_CRYPT_END() ALLOCV_END(databuf)
|
50
|
+
#else
|
51
|
+
extern char *crypt(const char *, const char *);
|
52
|
+
# define STRING_CRYPT_END() (void)0
|
53
|
+
#endif
|
54
|
+
VALUE result;
|
55
|
+
const char *s, *saltp;
|
56
|
+
char *res;
|
57
|
+
#ifdef BROKEN_STRING_CRYPT
|
58
|
+
char salt_8bit_clean[3];
|
59
|
+
#endif
|
60
|
+
|
61
|
+
StringValue(salt);
|
62
|
+
mustnot_wchar(str);
|
63
|
+
mustnot_wchar(salt);
|
64
|
+
if (RSTRING_LEN(salt) < 2) {
|
65
|
+
short_salt:
|
66
|
+
rb_raise(rb_eArgError, "salt too short (need >=2 bytes)");
|
67
|
+
}
|
68
|
+
|
69
|
+
s = StringValueCStr(str);
|
70
|
+
saltp = RSTRING_PTR(salt);
|
71
|
+
if (!saltp[0] || !saltp[1]) goto short_salt;
|
72
|
+
#ifdef BROKEN_STRING_CRYPT
|
73
|
+
if (!ISASCII((unsigned char)saltp[0]) || !ISASCII((unsigned char)saltp[1])) {
|
74
|
+
salt_8bit_clean[0] = saltp[0] & 0x7f;
|
75
|
+
salt_8bit_clean[1] = saltp[1] & 0x7f;
|
76
|
+
salt_8bit_clean[2] = '\0';
|
77
|
+
saltp = salt_8bit_clean;
|
78
|
+
}
|
79
|
+
#endif
|
80
|
+
#ifdef HAVE_STRING_CRYPT_R
|
81
|
+
data = ALLOCV(databuf, sizeof(struct crypt_data));
|
82
|
+
# ifdef HAVE_STRUCT_STRING_CRYPT_DATA_INITIALIZED
|
83
|
+
data->initialized = 0;
|
84
|
+
# endif
|
85
|
+
res = crypt_r(s, saltp, data);
|
86
|
+
#else
|
87
|
+
res = crypt(s, saltp);
|
88
|
+
#endif
|
89
|
+
if (!res) {
|
90
|
+
int err = errno;
|
91
|
+
STRING_CRYPT_END();
|
92
|
+
rb_syserr_fail(err, "crypt");
|
93
|
+
}
|
94
|
+
result = rb_str_new_cstr(res);
|
95
|
+
STRING_CRYPT_END();
|
96
|
+
FL_SET_RAW(result, OBJ_TAINTED_RAW(str) | OBJ_TAINTED_RAW(salt));
|
97
|
+
return result;
|
98
|
+
}
|
99
|
+
|
100
|
+
void Init_crypt(void) {
|
101
|
+
rb_eval_string("class String; remove_method(:crypt) if instance_methods(false).include?(:crypt); end");
|
102
|
+
rb_define_method(rb_cString, "crypt", rb_string_crypt, 1);
|
103
|
+
}
|
@@ -0,0 +1,61 @@
|
|
1
|
+
require 'mkmf'
|
2
|
+
|
3
|
+
if ENV['STRING_CRYPT_FORCE_MISSING'] == '1'
|
4
|
+
puts "forcing internal DES-crypt implementation"
|
5
|
+
else
|
6
|
+
if /darwin/ =~ RUBY_PLATFORM && try_run(<<END)
|
7
|
+
#include <stdio.h>
|
8
|
+
#include <unistd.h>
|
9
|
+
#include <string.h>
|
10
|
+
|
11
|
+
void
|
12
|
+
broken_crypt(const char *salt, const char *buf1, const char *buf2)
|
13
|
+
{
|
14
|
+
#if 0
|
15
|
+
printf("%.2x%.2x: %s -> %s\n", (unsigned char)salt[0], (unsigned char)salt[1],
|
16
|
+
buf1+2, buf2+2);
|
17
|
+
#endif
|
18
|
+
}
|
19
|
+
|
20
|
+
int
|
21
|
+
main()
|
22
|
+
{
|
23
|
+
int i;
|
24
|
+
char salt[2], buf[256], *s;
|
25
|
+
for (i = 0; i < 128*128; i++) {
|
26
|
+
salt[0] = 0x80 | (i & 0x7f);
|
27
|
+
salt[1] = 0x80 | (i >> 7);
|
28
|
+
strcpy(buf, crypt("", salt));
|
29
|
+
if (strcmp(buf, s = crypt("", salt))) {
|
30
|
+
broken_crypt(salt, buf, s);
|
31
|
+
return 1;
|
32
|
+
}
|
33
|
+
}
|
34
|
+
salt[0] = salt[1] = ' ';
|
35
|
+
strcpy(buf, crypt("", salt));
|
36
|
+
salt[0] = salt[1] = 0x80 | ' ';
|
37
|
+
if (strcmp(buf, s = crypt("", salt))) {
|
38
|
+
broken_crypt(salt, buf, s);
|
39
|
+
return 1;
|
40
|
+
}
|
41
|
+
return 0;
|
42
|
+
}
|
43
|
+
END
|
44
|
+
$defs << "-DBROKEN_CRYPT"
|
45
|
+
end
|
46
|
+
|
47
|
+
if have_header('crypt.h')
|
48
|
+
have_struct_member("struct crypt_data", "initialized", "crypt.h")
|
49
|
+
end
|
50
|
+
|
51
|
+
have_library('crypt', 'crypt')
|
52
|
+
have_func('crypt_r')
|
53
|
+
have_func('crypt')
|
54
|
+
end
|
55
|
+
|
56
|
+
# Rename variables so variables from ruby/config.h are not picked up.
|
57
|
+
if $defs
|
58
|
+
$defs.map!{|s| s.sub('CRYPT', 'STRING_CRYPT')}
|
59
|
+
end
|
60
|
+
|
61
|
+
create_makefile 'string/crypt'
|
@@ -0,0 +1,888 @@
|
|
1
|
+
/*
|
2
|
+
* Copyright (c) 1989, 1993
|
3
|
+
* The Regents of the University of California. All rights reserved.
|
4
|
+
*
|
5
|
+
* This code is derived from software contributed to Berkeley by
|
6
|
+
* Tom Truscott.
|
7
|
+
*
|
8
|
+
* Redistribution and use in source and binary forms, with or without
|
9
|
+
* modification, are permitted provided that the following conditions
|
10
|
+
* are met:
|
11
|
+
* 1. Redistributions of source code must retain the above copyright
|
12
|
+
* notice, this list of conditions and the following disclaimer.
|
13
|
+
* 2. Redistributions in binary form must reproduce the above copyright
|
14
|
+
* notice, this list of conditions and the following disclaimer in the
|
15
|
+
* documentation and/or other materials provided with the distribution.
|
16
|
+
* 3. Neither the name of the University nor the names of its contributors
|
17
|
+
* may be used to endorse or promote products derived from this software
|
18
|
+
* without specific prior written permission.
|
19
|
+
*
|
20
|
+
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
21
|
+
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
22
|
+
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
23
|
+
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
24
|
+
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
25
|
+
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
26
|
+
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
27
|
+
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
28
|
+
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
29
|
+
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
30
|
+
* SUCH DAMAGE.
|
31
|
+
*/
|
32
|
+
|
33
|
+
#if defined(LIBC_SCCS) && !defined(lint)
|
34
|
+
static char sccsid[] = "@(#)crypt.c 8.1 (Berkeley) 6/4/93";
|
35
|
+
#endif /* LIBC_SCCS and not lint */
|
36
|
+
|
37
|
+
#include "ruby/missing.h"
|
38
|
+
#include "crypt.h"
|
39
|
+
#ifdef HAVE_UNISTD_H
|
40
|
+
#include <unistd.h>
|
41
|
+
#endif
|
42
|
+
#include <limits.h>
|
43
|
+
#ifdef HAVE_PWD_H
|
44
|
+
#include <pwd.h>
|
45
|
+
#endif
|
46
|
+
#include <stdio.h>
|
47
|
+
#include <string.h>
|
48
|
+
#ifndef _PASSWORD_EFMT1
|
49
|
+
#define _PASSWORD_EFMT1 '_'
|
50
|
+
#endif
|
51
|
+
|
52
|
+
#ifndef numberof
|
53
|
+
#define numberof(array) (int)(sizeof(array) / sizeof((array)[0]))
|
54
|
+
#endif
|
55
|
+
|
56
|
+
/*
|
57
|
+
* UNIX password, and DES, encryption.
|
58
|
+
* By Tom Truscott, trt@rti.rti.org,
|
59
|
+
* from algorithms by Robert W. Baldwin and James Gillogly.
|
60
|
+
*
|
61
|
+
* References:
|
62
|
+
* "Mathematical Cryptology for Computer Scientists and Mathematicians,"
|
63
|
+
* by Wayne Patterson, 1987, ISBN 0-8476-7438-X.
|
64
|
+
*
|
65
|
+
* "Password Security: A Case History," R. Morris and Ken Thompson,
|
66
|
+
* Communications of the ACM, vol. 22, pp. 594-597, Nov. 1979.
|
67
|
+
*
|
68
|
+
* "DES will be Totally Insecure within Ten Years," M.E. Hellman,
|
69
|
+
* IEEE Spectrum, vol. 16, pp. 32-39, July 1979.
|
70
|
+
*/
|
71
|
+
|
72
|
+
/* ===== Configuration ==================== */
|
73
|
+
|
74
|
+
/*
|
75
|
+
* define "MUST_ALIGN" if your compiler cannot load/store
|
76
|
+
* long integers at arbitrary (e.g. odd) memory locations.
|
77
|
+
* (Either that or never pass unaligned addresses to des_cipher!)
|
78
|
+
*/
|
79
|
+
#if !defined(vax)
|
80
|
+
#define MUST_ALIGN
|
81
|
+
#endif
|
82
|
+
|
83
|
+
#ifdef CHAR_BITS
|
84
|
+
#if CHAR_BITS != 8
|
85
|
+
#error C_block structure assumes 8 bit characters
|
86
|
+
#endif
|
87
|
+
#endif
|
88
|
+
|
89
|
+
#ifndef INIT_DES
|
90
|
+
# if defined DUMP || defined NO_DES_TABLES
|
91
|
+
# define INIT_DES 1
|
92
|
+
# else
|
93
|
+
# define INIT_DES 0
|
94
|
+
# endif
|
95
|
+
#endif
|
96
|
+
#if !INIT_DES
|
97
|
+
# include "des_tables.c"
|
98
|
+
# ifdef HAVE_DES_TABLES
|
99
|
+
# define init_des() ((void)0)
|
100
|
+
# else
|
101
|
+
# undef INIT_DES
|
102
|
+
# define INIT_DES 1
|
103
|
+
# endif
|
104
|
+
#endif
|
105
|
+
|
106
|
+
/*
|
107
|
+
* Convert twenty-four-bit long in host-order
|
108
|
+
* to six bits (and 2 low-order zeroes) per char little-endian format.
|
109
|
+
*/
|
110
|
+
#define TO_SIX_BIT(rslt, src) { \
|
111
|
+
C_block cvt; \
|
112
|
+
cvt.b[0] = (unsigned char)(src); (src) >>= 6; \
|
113
|
+
cvt.b[1] = (unsigned char)(src); (src) >>= 6; \
|
114
|
+
cvt.b[2] = (unsigned char)(src); (src) >>= 6; \
|
115
|
+
cvt.b[3] = (unsigned char)(src); \
|
116
|
+
(rslt) = (cvt.b32.i0 & 0x3f3f3f3fL) << 2; \
|
117
|
+
}
|
118
|
+
|
119
|
+
/*
|
120
|
+
* These macros may someday permit efficient use of 64-bit integers.
|
121
|
+
*/
|
122
|
+
#define ZERO(d,d0,d1) ((d0) = 0, (d1) = 0)
|
123
|
+
#define LOAD(d,d0,d1,bl) ((d0) = (bl).b32.i0, (d1) = (bl).b32.i1)
|
124
|
+
#define LOADREG(d,d0,d1,s,s0,s1) ((d0) = (s0), (d1) = (s1))
|
125
|
+
#define OR(d,d0,d1,bl) ((d0) |= (bl).b32.i0, (d1) |= (bl).b32.i1)
|
126
|
+
#define STORE(s,s0,s1,bl) ((bl).b32.i0 = (s0), (bl).b32.i1 = (s1))
|
127
|
+
#define DCL_BLOCK(d,d0,d1) long d0, d1
|
128
|
+
|
129
|
+
#if defined(LARGEDATA)
|
130
|
+
/* Waste memory like crazy. Also, do permutations in line */
|
131
|
+
#define PERM6464(d,d0,d1,cpp,p) \
|
132
|
+
LOAD((d),(d0),(d1),(p)[(0<<CHUNKBITS)+(cpp)[0]]); \
|
133
|
+
OR ((d),(d0),(d1),(p)[(1<<CHUNKBITS)+(cpp)[1]]); \
|
134
|
+
OR ((d),(d0),(d1),(p)[(2<<CHUNKBITS)+(cpp)[2]]); \
|
135
|
+
OR ((d),(d0),(d1),(p)[(3<<CHUNKBITS)+(cpp)[3]]); \
|
136
|
+
OR (d),(d0),(d1),(p)[(4<<CHUNKBITS)+(cpp)[4]]); \
|
137
|
+
OR (d),(d0),(d1),(p)[(5<<CHUNKBITS)+(cpp)[5]]); \
|
138
|
+
OR (d),(d0),(d1),(p)[(6<<CHUNKBITS)+(cpp)[6]]); \
|
139
|
+
OR (d),(d0),(d1),(p)[(7<<CHUNKBITS)+(cpp)[7]]);
|
140
|
+
#define PERM3264(d,d0,d1,cpp,p) \
|
141
|
+
LOAD((d),(d0),(d1),(p)[(0<<CHUNKBITS)+(cpp)[0]]); \
|
142
|
+
OR ((d),(d0),(d1),(p)[(1<<CHUNKBITS)+(cpp)[1]]); \
|
143
|
+
OR ((d),(d0),(d1),(p)[(2<<CHUNKBITS)+(cpp)[2]]); \
|
144
|
+
OR ((d),(d0),(d1),(p)[(3<<CHUNKBITS)+(cpp)[3]]);
|
145
|
+
#else
|
146
|
+
/* "small data" */
|
147
|
+
#define PERM6464(d,d0,d1,cpp,p) \
|
148
|
+
{ C_block tblk; permute((cpp),&tblk,(p),8); LOAD ((d),(d0),(d1),tblk); }
|
149
|
+
#define PERM3264(d,d0,d1,cpp,p) \
|
150
|
+
{ C_block tblk; permute((cpp),&tblk,(p),4); LOAD ((d),(d0),(d1),tblk); }
|
151
|
+
|
152
|
+
STATIC void
|
153
|
+
permute(const unsigned char *cp, C_block *out, register const C_block *p, int chars_in)
|
154
|
+
{
|
155
|
+
register DCL_BLOCK(D,D0,D1);
|
156
|
+
register const C_block *tp;
|
157
|
+
register int t;
|
158
|
+
|
159
|
+
ZERO(D,D0,D1);
|
160
|
+
do {
|
161
|
+
t = *cp++;
|
162
|
+
tp = &p[t&0xf]; OR(D,D0,D1,*tp); p += (1<<CHUNKBITS);
|
163
|
+
tp = &p[t>>4]; OR(D,D0,D1,*tp); p += (1<<CHUNKBITS);
|
164
|
+
} while (--chars_in > 0);
|
165
|
+
STORE(D,D0,D1,*out);
|
166
|
+
}
|
167
|
+
#endif /* LARGEDATA */
|
168
|
+
|
169
|
+
#ifdef DEBUG
|
170
|
+
STATIC void prtab(const char *s, const unsigned char *t, int num_rows);
|
171
|
+
#endif
|
172
|
+
|
173
|
+
#if INIT_DES
|
174
|
+
/* ===== (mostly) Standard DES Tables ==================== */
|
175
|
+
|
176
|
+
static const unsigned char IP[] = { /* initial permutation */
|
177
|
+
58, 50, 42, 34, 26, 18, 10, 2,
|
178
|
+
60, 52, 44, 36, 28, 20, 12, 4,
|
179
|
+
62, 54, 46, 38, 30, 22, 14, 6,
|
180
|
+
64, 56, 48, 40, 32, 24, 16, 8,
|
181
|
+
57, 49, 41, 33, 25, 17, 9, 1,
|
182
|
+
59, 51, 43, 35, 27, 19, 11, 3,
|
183
|
+
61, 53, 45, 37, 29, 21, 13, 5,
|
184
|
+
63, 55, 47, 39, 31, 23, 15, 7,
|
185
|
+
};
|
186
|
+
|
187
|
+
/* The final permutation is the inverse of IP - no table is necessary */
|
188
|
+
|
189
|
+
static const unsigned char ExpandTr[] = { /* expansion operation */
|
190
|
+
32, 1, 2, 3, 4, 5,
|
191
|
+
4, 5, 6, 7, 8, 9,
|
192
|
+
8, 9, 10, 11, 12, 13,
|
193
|
+
12, 13, 14, 15, 16, 17,
|
194
|
+
16, 17, 18, 19, 20, 21,
|
195
|
+
20, 21, 22, 23, 24, 25,
|
196
|
+
24, 25, 26, 27, 28, 29,
|
197
|
+
28, 29, 30, 31, 32, 1,
|
198
|
+
};
|
199
|
+
|
200
|
+
static const unsigned char PC1[] = { /* permuted choice table 1 */
|
201
|
+
57, 49, 41, 33, 25, 17, 9,
|
202
|
+
1, 58, 50, 42, 34, 26, 18,
|
203
|
+
10, 2, 59, 51, 43, 35, 27,
|
204
|
+
19, 11, 3, 60, 52, 44, 36,
|
205
|
+
|
206
|
+
63, 55, 47, 39, 31, 23, 15,
|
207
|
+
7, 62, 54, 46, 38, 30, 22,
|
208
|
+
14, 6, 61, 53, 45, 37, 29,
|
209
|
+
21, 13, 5, 28, 20, 12, 4,
|
210
|
+
};
|
211
|
+
#endif
|
212
|
+
|
213
|
+
static const unsigned char Rotates[] = { /* PC1 rotation schedule */
|
214
|
+
1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1,
|
215
|
+
};
|
216
|
+
|
217
|
+
#if INIT_DES
|
218
|
+
/* note: each "row" of PC2 is left-padded with bits that make it invertible */
|
219
|
+
static const unsigned char PC2[] = { /* permuted choice table 2 */
|
220
|
+
9, 18, 14, 17, 11, 24, 1, 5,
|
221
|
+
22, 25, 3, 28, 15, 6, 21, 10,
|
222
|
+
35, 38, 23, 19, 12, 4, 26, 8,
|
223
|
+
43, 54, 16, 7, 27, 20, 13, 2,
|
224
|
+
|
225
|
+
0, 0, 41, 52, 31, 37, 47, 55,
|
226
|
+
0, 0, 30, 40, 51, 45, 33, 48,
|
227
|
+
0, 0, 44, 49, 39, 56, 34, 53,
|
228
|
+
0, 0, 46, 42, 50, 36, 29, 32,
|
229
|
+
};
|
230
|
+
|
231
|
+
static const unsigned char S[8][64] = { /* 48->32 bit substitution tables */
|
232
|
+
{
|
233
|
+
/* S[1] */
|
234
|
+
14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7,
|
235
|
+
0, 15, 7, 4, 14, 2, 13, 1, 10, 6, 12, 11, 9, 5, 3, 8,
|
236
|
+
4, 1, 14, 8, 13, 6, 2, 11, 15, 12, 9, 7, 3, 10, 5, 0,
|
237
|
+
15, 12, 8, 2, 4, 9, 1, 7, 5, 11, 3, 14, 10, 0, 6, 13,
|
238
|
+
},
|
239
|
+
{
|
240
|
+
/* S[2] */
|
241
|
+
15, 1, 8, 14, 6, 11, 3, 4, 9, 7, 2, 13, 12, 0, 5, 10,
|
242
|
+
3, 13, 4, 7, 15, 2, 8, 14, 12, 0, 1, 10, 6, 9, 11, 5,
|
243
|
+
0, 14, 7, 11, 10, 4, 13, 1, 5, 8, 12, 6, 9, 3, 2, 15,
|
244
|
+
13, 8, 10, 1, 3, 15, 4, 2, 11, 6, 7, 12, 0, 5, 14, 9,
|
245
|
+
},
|
246
|
+
{
|
247
|
+
/* S[3] */
|
248
|
+
10, 0, 9, 14, 6, 3, 15, 5, 1, 13, 12, 7, 11, 4, 2, 8,
|
249
|
+
13, 7, 0, 9, 3, 4, 6, 10, 2, 8, 5, 14, 12, 11, 15, 1,
|
250
|
+
13, 6, 4, 9, 8, 15, 3, 0, 11, 1, 2, 12, 5, 10, 14, 7,
|
251
|
+
1, 10, 13, 0, 6, 9, 8, 7, 4, 15, 14, 3, 11, 5, 2, 12,
|
252
|
+
},
|
253
|
+
{
|
254
|
+
/* S[4] */
|
255
|
+
7, 13, 14, 3, 0, 6, 9, 10, 1, 2, 8, 5, 11, 12, 4, 15,
|
256
|
+
13, 8, 11, 5, 6, 15, 0, 3, 4, 7, 2, 12, 1, 10, 14, 9,
|
257
|
+
10, 6, 9, 0, 12, 11, 7, 13, 15, 1, 3, 14, 5, 2, 8, 4,
|
258
|
+
3, 15, 0, 6, 10, 1, 13, 8, 9, 4, 5, 11, 12, 7, 2, 14,
|
259
|
+
},
|
260
|
+
{
|
261
|
+
/* S[5] */
|
262
|
+
2, 12, 4, 1, 7, 10, 11, 6, 8, 5, 3, 15, 13, 0, 14, 9,
|
263
|
+
14, 11, 2, 12, 4, 7, 13, 1, 5, 0, 15, 10, 3, 9, 8, 6,
|
264
|
+
4, 2, 1, 11, 10, 13, 7, 8, 15, 9, 12, 5, 6, 3, 0, 14,
|
265
|
+
11, 8, 12, 7, 1, 14, 2, 13, 6, 15, 0, 9, 10, 4, 5, 3,
|
266
|
+
},
|
267
|
+
{
|
268
|
+
/* S[6] */
|
269
|
+
12, 1, 10, 15, 9, 2, 6, 8, 0, 13, 3, 4, 14, 7, 5, 11,
|
270
|
+
10, 15, 4, 2, 7, 12, 9, 5, 6, 1, 13, 14, 0, 11, 3, 8,
|
271
|
+
9, 14, 15, 5, 2, 8, 12, 3, 7, 0, 4, 10, 1, 13, 11, 6,
|
272
|
+
4, 3, 2, 12, 9, 5, 15, 10, 11, 14, 1, 7, 6, 0, 8, 13,
|
273
|
+
},
|
274
|
+
{
|
275
|
+
/* S[7] */
|
276
|
+
4, 11, 2, 14, 15, 0, 8, 13, 3, 12, 9, 7, 5, 10, 6, 1,
|
277
|
+
13, 0, 11, 7, 4, 9, 1, 10, 14, 3, 5, 12, 2, 15, 8, 6,
|
278
|
+
1, 4, 11, 13, 12, 3, 7, 14, 10, 15, 6, 8, 0, 5, 9, 2,
|
279
|
+
6, 11, 13, 8, 1, 4, 10, 7, 9, 5, 0, 15, 14, 2, 3, 12,
|
280
|
+
},
|
281
|
+
{
|
282
|
+
/* S[8] */
|
283
|
+
13, 2, 8, 4, 6, 15, 11, 1, 10, 9, 3, 14, 5, 0, 12, 7,
|
284
|
+
1, 15, 13, 8, 10, 3, 7, 4, 12, 5, 6, 11, 0, 14, 9, 2,
|
285
|
+
7, 11, 4, 1, 9, 12, 14, 2, 0, 6, 10, 13, 15, 3, 5, 8,
|
286
|
+
2, 1, 14, 7, 4, 10, 8, 13, 15, 12, 9, 0, 3, 5, 6, 11,
|
287
|
+
},
|
288
|
+
};
|
289
|
+
|
290
|
+
static const unsigned char P32Tr[] = { /* 32-bit permutation function */
|
291
|
+
16, 7, 20, 21,
|
292
|
+
29, 12, 28, 17,
|
293
|
+
1, 15, 23, 26,
|
294
|
+
5, 18, 31, 10,
|
295
|
+
2, 8, 24, 14,
|
296
|
+
32, 27, 3, 9,
|
297
|
+
19, 13, 30, 6,
|
298
|
+
22, 11, 4, 25,
|
299
|
+
};
|
300
|
+
|
301
|
+
static const unsigned char CIFP[] = { /* compressed/interleaved permutation */
|
302
|
+
1, 2, 3, 4, 17, 18, 19, 20,
|
303
|
+
5, 6, 7, 8, 21, 22, 23, 24,
|
304
|
+
9, 10, 11, 12, 25, 26, 27, 28,
|
305
|
+
13, 14, 15, 16, 29, 30, 31, 32,
|
306
|
+
|
307
|
+
33, 34, 35, 36, 49, 50, 51, 52,
|
308
|
+
37, 38, 39, 40, 53, 54, 55, 56,
|
309
|
+
41, 42, 43, 44, 57, 58, 59, 60,
|
310
|
+
45, 46, 47, 48, 61, 62, 63, 64,
|
311
|
+
};
|
312
|
+
#endif
|
313
|
+
|
314
|
+
static const unsigned char itoa64[] = /* 0..63 => ascii-64 */
|
315
|
+
"./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
|
316
|
+
|
317
|
+
/* table that converts chars "./0-9A-Za-z"to integers 0-63. */
|
318
|
+
static const unsigned char a64toi[256] = {
|
319
|
+
#define A64TOI1(c) \
|
320
|
+
((c) == '.' ? 0 : \
|
321
|
+
(c) == '/' ? 1 : \
|
322
|
+
('0' <= (c) && (c) <= '9') ? (c) - '0' + 2 : \
|
323
|
+
('A' <= (c) && (c) <= 'Z') ? (c) - 'A' + 12 : \
|
324
|
+
('a' <= (c) && (c) <= 'z') ? (c) - 'a' + 38 : \
|
325
|
+
0)
|
326
|
+
#define A64TOI4(base) A64TOI1(base+0), A64TOI1(base+1), A64TOI1(base+2), A64TOI1(base+3)
|
327
|
+
#define A64TOI16(base) A64TOI4(base+0), A64TOI4(base+4), A64TOI4(base+8), A64TOI4(base+12)
|
328
|
+
#define A64TOI64(base) A64TOI16(base+0x00), A64TOI16(base+0x10), A64TOI16(base+0x20), A64TOI16(base+0x30)
|
329
|
+
A64TOI64(0x00), A64TOI64(0x40),
|
330
|
+
A64TOI64(0x00), A64TOI64(0x40),
|
331
|
+
};
|
332
|
+
|
333
|
+
#if INIT_DES
|
334
|
+
/* ===== Tables that are initialized at run time ==================== */
|
335
|
+
|
336
|
+
typedef struct {
|
337
|
+
/* Initial key schedule permutation */
|
338
|
+
C_block PC1ROT[64/CHUNKBITS][1<<CHUNKBITS];
|
339
|
+
|
340
|
+
/* Subsequent key schedule rotation permutations */
|
341
|
+
C_block PC2ROT[2][64/CHUNKBITS][1<<CHUNKBITS];
|
342
|
+
|
343
|
+
/* Initial permutation/expansion table */
|
344
|
+
C_block IE3264[32/CHUNKBITS][1<<CHUNKBITS];
|
345
|
+
|
346
|
+
/* Table that combines the S, P, and E operations. */
|
347
|
+
unsigned long SPE[2][8][64];
|
348
|
+
|
349
|
+
/* compressed/interleaved => final permutation table */
|
350
|
+
C_block CF6464[64/CHUNKBITS][1<<CHUNKBITS];
|
351
|
+
|
352
|
+
int ready;
|
353
|
+
} des_tables_t;
|
354
|
+
static des_tables_t des_tables[1];
|
355
|
+
|
356
|
+
#define des_tables ((const des_tables_t *)des_tables)
|
357
|
+
#define PC1ROT (des_tables->PC1ROT)
|
358
|
+
#define PC2ROT (des_tables->PC2ROT)
|
359
|
+
#define IE3264 (des_tables->IE3264)
|
360
|
+
#define SPE (des_tables->SPE)
|
361
|
+
#define CF6464 (des_tables->CF6464)
|
362
|
+
|
363
|
+
STATIC void init_des(void);
|
364
|
+
STATIC void init_perm(C_block perm[64/CHUNKBITS][1<<CHUNKBITS], unsigned char p[64], int chars_in, int chars_out);
|
365
|
+
#endif
|
366
|
+
|
367
|
+
static const C_block constdatablock = {{0}}; /* encryption constant */
|
368
|
+
|
369
|
+
#define KS (data->KS)
|
370
|
+
#define cryptresult (data->cryptresult)
|
371
|
+
|
372
|
+
static void des_setkey_r(const unsigned char *key, struct crypt_data *data);
|
373
|
+
static void des_cipher_r(const unsigned char *in, unsigned char *out, long salt, int num_iter, struct crypt_data *data);
|
374
|
+
|
375
|
+
/*
|
376
|
+
* Return a pointer to data consisting of the "setting" followed by an
|
377
|
+
* encryption produced by the "key" and "setting".
|
378
|
+
*/
|
379
|
+
char *
|
380
|
+
crypt_r(const char *key, const char *setting, struct crypt_data *data)
|
381
|
+
{
|
382
|
+
register char *encp;
|
383
|
+
register long i;
|
384
|
+
register int t;
|
385
|
+
long salt;
|
386
|
+
int num_iter, salt_size;
|
387
|
+
C_block keyblock, rsltblock;
|
388
|
+
|
389
|
+
for (i = 0; i < 8; i++) {
|
390
|
+
if ((t = 2*(unsigned char)(*key)) != 0)
|
391
|
+
key++;
|
392
|
+
keyblock.b[i] = t;
|
393
|
+
}
|
394
|
+
des_setkey_r(keyblock.b, data); /* also initializes "a64toi" */
|
395
|
+
|
396
|
+
encp = &cryptresult[0];
|
397
|
+
switch (*setting) {
|
398
|
+
case _PASSWORD_EFMT1:
|
399
|
+
/*
|
400
|
+
* Involve the rest of the password 8 characters at a time.
|
401
|
+
*/
|
402
|
+
while (*key) {
|
403
|
+
des_cipher_r(keyblock.b, keyblock.b, 0L, 1, data);
|
404
|
+
for (i = 0; i < 8; i++) {
|
405
|
+
if ((t = 2*(unsigned char)(*key)) != 0)
|
406
|
+
key++;
|
407
|
+
keyblock.b[i] ^= t;
|
408
|
+
}
|
409
|
+
des_setkey_r(keyblock.b, data);
|
410
|
+
}
|
411
|
+
|
412
|
+
*encp++ = *setting++;
|
413
|
+
|
414
|
+
/* get iteration count */
|
415
|
+
num_iter = 0;
|
416
|
+
for (i = 4; --i >= 0; ) {
|
417
|
+
if ((t = (unsigned char)setting[i]) == '\0')
|
418
|
+
t = '.';
|
419
|
+
encp[i] = t;
|
420
|
+
num_iter = (num_iter<<6) | a64toi[t];
|
421
|
+
}
|
422
|
+
setting += 4;
|
423
|
+
encp += 4;
|
424
|
+
salt_size = 4;
|
425
|
+
break;
|
426
|
+
default:
|
427
|
+
num_iter = 25;
|
428
|
+
salt_size = 2;
|
429
|
+
}
|
430
|
+
|
431
|
+
salt = 0;
|
432
|
+
for (i = salt_size; --i >= 0; ) {
|
433
|
+
if ((t = (unsigned char)setting[i]) == '\0')
|
434
|
+
t = '.';
|
435
|
+
encp[i] = t;
|
436
|
+
salt = (salt<<6) | a64toi[t];
|
437
|
+
}
|
438
|
+
encp += salt_size;
|
439
|
+
des_cipher_r(constdatablock.b, rsltblock.b, salt, num_iter, data);
|
440
|
+
|
441
|
+
/*
|
442
|
+
* Encode the 64 cipher bits as 11 ascii characters.
|
443
|
+
*/
|
444
|
+
i = ((long)((rsltblock.b[0]<<8) | rsltblock.b[1])<<8) | rsltblock.b[2];
|
445
|
+
encp[3] = itoa64[i&0x3f]; i >>= 6;
|
446
|
+
encp[2] = itoa64[i&0x3f]; i >>= 6;
|
447
|
+
encp[1] = itoa64[i&0x3f]; i >>= 6;
|
448
|
+
encp[0] = itoa64[i]; encp += 4;
|
449
|
+
i = ((long)((rsltblock.b[3]<<8) | rsltblock.b[4])<<8) | rsltblock.b[5];
|
450
|
+
encp[3] = itoa64[i&0x3f]; i >>= 6;
|
451
|
+
encp[2] = itoa64[i&0x3f]; i >>= 6;
|
452
|
+
encp[1] = itoa64[i&0x3f]; i >>= 6;
|
453
|
+
encp[0] = itoa64[i]; encp += 4;
|
454
|
+
i = ((long)((rsltblock.b[6])<<8) | rsltblock.b[7])<<2;
|
455
|
+
encp[2] = itoa64[i&0x3f]; i >>= 6;
|
456
|
+
encp[1] = itoa64[i&0x3f]; i >>= 6;
|
457
|
+
encp[0] = itoa64[i];
|
458
|
+
|
459
|
+
encp[3] = 0;
|
460
|
+
|
461
|
+
return (cryptresult);
|
462
|
+
}
|
463
|
+
|
464
|
+
/*
|
465
|
+
* Set up the key schedule from the key.
|
466
|
+
*/
|
467
|
+
static void
|
468
|
+
des_setkey_r(const unsigned char *key, struct crypt_data *data)
|
469
|
+
{
|
470
|
+
register DCL_BLOCK(K, K0, K1);
|
471
|
+
register const C_block *ptabp;
|
472
|
+
register int i;
|
473
|
+
C_block *ksp;
|
474
|
+
|
475
|
+
init_des();
|
476
|
+
|
477
|
+
PERM6464(K,K0,K1,key,PC1ROT[0]);
|
478
|
+
ksp = &KS[0];
|
479
|
+
STORE(K&~0x03030303L, K0&~0x03030303L, K1, *ksp);
|
480
|
+
for (i = 1; i < numberof(KS); i++) {
|
481
|
+
ksp++;
|
482
|
+
STORE(K,K0,K1,*ksp);
|
483
|
+
ptabp = PC2ROT[Rotates[i]-1][0];
|
484
|
+
PERM6464(K,K0,K1,ksp->b,ptabp);
|
485
|
+
STORE(K&~0x03030303L, K0&~0x03030303L, K1, *ksp);
|
486
|
+
}
|
487
|
+
}
|
488
|
+
|
489
|
+
/*
|
490
|
+
* Encrypt (or decrypt if num_iter < 0) the 8 chars at "in" with abs(num_iter)
|
491
|
+
* iterations of DES, using the given 24-bit salt and the pre-computed key
|
492
|
+
* schedule, and store the resulting 8 chars at "out" (in == out is permitted).
|
493
|
+
*
|
494
|
+
* NOTE: the performance of this routine is critically dependent on your
|
495
|
+
* compiler and machine architecture.
|
496
|
+
*/
|
497
|
+
void
|
498
|
+
des_cipher_r(const unsigned char *in, unsigned char *out, long salt, int num_iter, struct crypt_data *data)
|
499
|
+
{
|
500
|
+
/* variables that we want in registers, most important first */
|
501
|
+
#if defined(pdp11)
|
502
|
+
register int j;
|
503
|
+
#endif
|
504
|
+
register unsigned long L0, L1, R0, R1, k;
|
505
|
+
register const C_block *kp;
|
506
|
+
register int ks_inc, loop_count;
|
507
|
+
C_block B;
|
508
|
+
|
509
|
+
L0 = salt;
|
510
|
+
TO_SIX_BIT(salt, L0); /* convert to 4*(6+2) format */
|
511
|
+
|
512
|
+
#if defined(vax) || defined(pdp11)
|
513
|
+
salt = ~salt; /* "x &~ y" is faster than "x & y". */
|
514
|
+
#define SALT (~salt)
|
515
|
+
#else
|
516
|
+
#define SALT salt
|
517
|
+
#endif
|
518
|
+
|
519
|
+
#if defined(MUST_ALIGN)
|
520
|
+
B.b[0] = in[0]; B.b[1] = in[1]; B.b[2] = in[2]; B.b[3] = in[3];
|
521
|
+
B.b[4] = in[4]; B.b[5] = in[5]; B.b[6] = in[6]; B.b[7] = in[7];
|
522
|
+
LOAD(L,L0,L1,B);
|
523
|
+
#else
|
524
|
+
LOAD(L,L0,L1,*(C_block *)in);
|
525
|
+
#endif
|
526
|
+
LOADREG(R,R0,R1,L,L0,L1);
|
527
|
+
L0 &= 0x55555555L;
|
528
|
+
L1 &= 0x55555555L;
|
529
|
+
L0 = (L0 << 1) | L1; /* L0 is the even-numbered input bits */
|
530
|
+
R0 &= 0xaaaaaaaaL;
|
531
|
+
R1 = (R1 >> 1) & 0x55555555L;
|
532
|
+
L1 = R0 | R1; /* L1 is the odd-numbered input bits */
|
533
|
+
STORE(L,L0,L1,B);
|
534
|
+
PERM3264(L,L0,L1,B.b, IE3264[0]); /* even bits */
|
535
|
+
PERM3264(R,R0,R1,B.b+4,IE3264[0]); /* odd bits */
|
536
|
+
|
537
|
+
if (num_iter >= 0)
|
538
|
+
{ /* encryption */
|
539
|
+
kp = &KS[0];
|
540
|
+
ks_inc = +1;
|
541
|
+
}
|
542
|
+
else
|
543
|
+
{ /* decryption */
|
544
|
+
num_iter = -num_iter;
|
545
|
+
kp = &KS[KS_SIZE-1];
|
546
|
+
ks_inc = -1;
|
547
|
+
}
|
548
|
+
|
549
|
+
while (--num_iter >= 0) {
|
550
|
+
loop_count = 8;
|
551
|
+
do {
|
552
|
+
|
553
|
+
#define SPTAB(t, i) (*(const unsigned long *)((const unsigned char *)(t) + (i)*(sizeof(long)/4)))
|
554
|
+
#if defined(gould)
|
555
|
+
/* use this if B.b[i] is evaluated just once ... */
|
556
|
+
#define DOXOR(x,y,i) (x)^=SPTAB(SPE[0][(i)],B.b[(i)]); (y)^=SPTAB(SPE[1][(i)],B.b[(i)]);
|
557
|
+
#else
|
558
|
+
#if defined(pdp11)
|
559
|
+
/* use this if your "long" int indexing is slow */
|
560
|
+
#define DOXOR(x,y,i) j=B.b[(i)]; (x)^=SPTAB(SPE[0][(i)],j); (y)^=SPTAB(SPE[1][(i)],j);
|
561
|
+
#else
|
562
|
+
/* use this if "k" is allocated to a register ... */
|
563
|
+
#define DOXOR(x,y,i) k=B.b[(i)]; (x)^=SPTAB(SPE[0][(i)],k); (y)^=SPTAB(SPE[1][(i)],k);
|
564
|
+
#endif
|
565
|
+
#endif
|
566
|
+
|
567
|
+
#define CRUNCH(p0, p1, q0, q1) \
|
568
|
+
k = ((q0) ^ (q1)) & SALT; \
|
569
|
+
B.b32.i0 = k ^ (q0) ^ kp->b32.i0; \
|
570
|
+
B.b32.i1 = k ^ (q1) ^ kp->b32.i1; \
|
571
|
+
kp += ks_inc; \
|
572
|
+
\
|
573
|
+
DOXOR((p0), (p1), 0); \
|
574
|
+
DOXOR((p0), (p1), 1); \
|
575
|
+
DOXOR((p0), (p1), 2); \
|
576
|
+
DOXOR((p0), (p1), 3); \
|
577
|
+
DOXOR((p0), (p1), 4); \
|
578
|
+
DOXOR((p0), (p1), 5); \
|
579
|
+
DOXOR((p0), (p1), 6); \
|
580
|
+
DOXOR((p0), (p1), 7);
|
581
|
+
|
582
|
+
CRUNCH(L0, L1, R0, R1);
|
583
|
+
CRUNCH(R0, R1, L0, L1);
|
584
|
+
} while (--loop_count != 0);
|
585
|
+
kp -= (ks_inc*KS_SIZE);
|
586
|
+
|
587
|
+
|
588
|
+
/* swap L and R */
|
589
|
+
L0 ^= R0; L1 ^= R1;
|
590
|
+
R0 ^= L0; R1 ^= L1;
|
591
|
+
L0 ^= R0; L1 ^= R1;
|
592
|
+
}
|
593
|
+
|
594
|
+
/* store the encrypted (or decrypted) result */
|
595
|
+
L0 = ((L0 >> 3) & 0x0f0f0f0fL) | ((L1 << 1) & 0xf0f0f0f0L);
|
596
|
+
L1 = ((R0 >> 3) & 0x0f0f0f0fL) | ((R1 << 1) & 0xf0f0f0f0L);
|
597
|
+
STORE(L,L0,L1,B);
|
598
|
+
PERM6464(L,L0,L1,B.b, CF6464[0]);
|
599
|
+
#if defined(MUST_ALIGN)
|
600
|
+
STORE(L,L0,L1,B);
|
601
|
+
out[0] = B.b[0]; out[1] = B.b[1]; out[2] = B.b[2]; out[3] = B.b[3];
|
602
|
+
out[4] = B.b[4]; out[5] = B.b[5]; out[6] = B.b[6]; out[7] = B.b[7];
|
603
|
+
#else
|
604
|
+
STORE(L,L0,L1,*(C_block *)out);
|
605
|
+
#endif
|
606
|
+
}
|
607
|
+
|
608
|
+
#undef des_tables
|
609
|
+
#undef KS
|
610
|
+
#undef cryptresult
|
611
|
+
|
612
|
+
#if INIT_DES
|
613
|
+
/*
|
614
|
+
* Initialize various tables. This need only be done once. It could even be
|
615
|
+
* done at compile time, if the compiler were capable of that sort of thing.
|
616
|
+
*/
|
617
|
+
STATIC void
|
618
|
+
init_des(void)
|
619
|
+
{
|
620
|
+
register int i, j;
|
621
|
+
register long k;
|
622
|
+
register int tableno;
|
623
|
+
unsigned char perm[64], tmp32[32];
|
624
|
+
|
625
|
+
if (des_tables->ready) return;
|
626
|
+
|
627
|
+
/*
|
628
|
+
* PC1ROT - bit reverse, then PC1, then Rotate, then PC2.
|
629
|
+
*/
|
630
|
+
for (i = 0; i < 64; i++)
|
631
|
+
perm[i] = 0;
|
632
|
+
for (i = 0; i < 64; i++) {
|
633
|
+
if ((k = PC2[i]) == 0)
|
634
|
+
continue;
|
635
|
+
k += Rotates[0]-1;
|
636
|
+
if ((k%28) < Rotates[0]) k -= 28;
|
637
|
+
k = PC1[k];
|
638
|
+
if (k > 0) {
|
639
|
+
k--;
|
640
|
+
k = (k|07) - (k&07);
|
641
|
+
k++;
|
642
|
+
}
|
643
|
+
perm[i] = (unsigned char)k;
|
644
|
+
}
|
645
|
+
#ifdef DEBUG
|
646
|
+
prtab("pc1tab", perm, 8);
|
647
|
+
#endif
|
648
|
+
init_perm(PC1ROT, perm, 8, 8);
|
649
|
+
|
650
|
+
/*
|
651
|
+
* PC2ROT - PC2 inverse, then Rotate (once or twice), then PC2.
|
652
|
+
*/
|
653
|
+
for (j = 0; j < 2; j++) {
|
654
|
+
unsigned char pc2inv[64];
|
655
|
+
for (i = 0; i < 64; i++)
|
656
|
+
perm[i] = pc2inv[i] = 0;
|
657
|
+
for (i = 0; i < 64; i++) {
|
658
|
+
if ((k = PC2[i]) == 0)
|
659
|
+
continue;
|
660
|
+
pc2inv[k-1] = i+1;
|
661
|
+
}
|
662
|
+
for (i = 0; i < 64; i++) {
|
663
|
+
if ((k = PC2[i]) == 0)
|
664
|
+
continue;
|
665
|
+
k += j;
|
666
|
+
if ((k%28) <= j) k -= 28;
|
667
|
+
perm[i] = pc2inv[k];
|
668
|
+
}
|
669
|
+
#ifdef DEBUG
|
670
|
+
prtab("pc2tab", perm, 8);
|
671
|
+
#endif
|
672
|
+
init_perm(PC2ROT[j], perm, 8, 8);
|
673
|
+
}
|
674
|
+
|
675
|
+
/*
|
676
|
+
* Bit reverse, then initial permutation, then expansion.
|
677
|
+
*/
|
678
|
+
for (i = 0; i < 8; i++) {
|
679
|
+
for (j = 0; j < 8; j++) {
|
680
|
+
k = (j < 2)? 0: IP[ExpandTr[i*6+j-2]-1];
|
681
|
+
if (k > 32)
|
682
|
+
k -= 32;
|
683
|
+
else if (k > 0)
|
684
|
+
k--;
|
685
|
+
if (k > 0) {
|
686
|
+
k--;
|
687
|
+
k = (k|07) - (k&07);
|
688
|
+
k++;
|
689
|
+
}
|
690
|
+
perm[i*8+j] = (unsigned char)k;
|
691
|
+
}
|
692
|
+
}
|
693
|
+
#ifdef DEBUG
|
694
|
+
prtab("ietab", perm, 8);
|
695
|
+
#endif
|
696
|
+
init_perm(IE3264, perm, 4, 8);
|
697
|
+
|
698
|
+
/*
|
699
|
+
* Compression, then final permutation, then bit reverse.
|
700
|
+
*/
|
701
|
+
for (i = 0; i < 64; i++) {
|
702
|
+
k = IP[CIFP[i]-1];
|
703
|
+
if (k > 0) {
|
704
|
+
k--;
|
705
|
+
k = (k|07) - (k&07);
|
706
|
+
k++;
|
707
|
+
}
|
708
|
+
perm[k-1] = i+1;
|
709
|
+
}
|
710
|
+
#ifdef DEBUG
|
711
|
+
prtab("cftab", perm, 8);
|
712
|
+
#endif
|
713
|
+
init_perm(CF6464, perm, 8, 8);
|
714
|
+
|
715
|
+
/*
|
716
|
+
* SPE table
|
717
|
+
*/
|
718
|
+
for (i = 0; i < 48; i++)
|
719
|
+
perm[i] = P32Tr[ExpandTr[i]-1];
|
720
|
+
for (tableno = 0; tableno < 8; tableno++) {
|
721
|
+
for (j = 0; j < 64; j++) {
|
722
|
+
k = (((j >> 0) &01) << 5)|
|
723
|
+
(((j >> 1) &01) << 3)|
|
724
|
+
(((j >> 2) &01) << 2)|
|
725
|
+
(((j >> 3) &01) << 1)|
|
726
|
+
(((j >> 4) &01) << 0)|
|
727
|
+
(((j >> 5) &01) << 4);
|
728
|
+
k = S[tableno][k];
|
729
|
+
k = (((k >> 3)&01) << 0)|
|
730
|
+
(((k >> 2)&01) << 1)|
|
731
|
+
(((k >> 1)&01) << 2)|
|
732
|
+
(((k >> 0)&01) << 3);
|
733
|
+
for (i = 0; i < 32; i++)
|
734
|
+
tmp32[i] = 0;
|
735
|
+
for (i = 0; i < 4; i++)
|
736
|
+
tmp32[4 * tableno + i] = (unsigned char)(k >> i) & 01;
|
737
|
+
k = 0;
|
738
|
+
for (i = 24; --i >= 0; )
|
739
|
+
k = (k<<1) | tmp32[perm[i]-1];
|
740
|
+
TO_SIX_BIT(SPE[0][tableno][j], k);
|
741
|
+
k = 0;
|
742
|
+
for (i = 24; --i >= 0; )
|
743
|
+
k = (k<<1) | tmp32[perm[i+24]-1];
|
744
|
+
TO_SIX_BIT(SPE[1][tableno][j], k);
|
745
|
+
}
|
746
|
+
}
|
747
|
+
|
748
|
+
des_tables->ready = 1;
|
749
|
+
}
|
750
|
+
|
751
|
+
/*
|
752
|
+
* Initialize "perm" to represent transformation "p", which rearranges
|
753
|
+
* (perhaps with expansion and/or contraction) one packed array of bits
|
754
|
+
* (of size "chars_in" characters) into another array (of size "chars_out"
|
755
|
+
* characters).
|
756
|
+
*
|
757
|
+
* "perm" must be all-zeroes on entry to this routine.
|
758
|
+
*/
|
759
|
+
STATIC void
|
760
|
+
init_perm(C_block perm[64/CHUNKBITS][1<<CHUNKBITS],
|
761
|
+
unsigned char p[64], int chars_in, int chars_out)
|
762
|
+
{
|
763
|
+
register int i, j, k, l;
|
764
|
+
|
765
|
+
for (k = 0; k < chars_out*8; k++) { /* each output bit position */
|
766
|
+
l = p[k] - 1; /* where this bit comes from */
|
767
|
+
if (l < 0)
|
768
|
+
continue; /* output bit is always 0 */
|
769
|
+
i = l>>LGCHUNKBITS; /* which chunk this bit comes from */
|
770
|
+
l = 1<<(l&(CHUNKBITS-1)); /* mask for this bit */
|
771
|
+
for (j = 0; j < (1<<CHUNKBITS); j++) { /* each chunk value */
|
772
|
+
if ((j & l) != 0)
|
773
|
+
perm[i][j].b[k>>3] |= 1<<(k&07);
|
774
|
+
}
|
775
|
+
}
|
776
|
+
}
|
777
|
+
#endif
|
778
|
+
|
779
|
+
#ifdef DEBUG
|
780
|
+
STATIC void
|
781
|
+
prtab(const char *s, const unsigned char *t, int num_rows)
|
782
|
+
{
|
783
|
+
register int i, j;
|
784
|
+
|
785
|
+
(void)printf("%s:\n", s);
|
786
|
+
for (i = 0; i < num_rows; i++) {
|
787
|
+
for (j = 0; j < 8; j++) {
|
788
|
+
(void)printf("%3d", t[i*8+j]);
|
789
|
+
}
|
790
|
+
(void)printf("\n");
|
791
|
+
}
|
792
|
+
(void)printf("\n");
|
793
|
+
}
|
794
|
+
#endif
|
795
|
+
|
796
|
+
#ifdef DUMP
|
797
|
+
void
|
798
|
+
dump_block(const C_block *block)
|
799
|
+
{
|
800
|
+
int i;
|
801
|
+
printf("{{");
|
802
|
+
for (i = 0; i < numberof(block->b); ++i) {
|
803
|
+
printf("%3d,", block->b[i]);
|
804
|
+
}
|
805
|
+
printf("}},\n");
|
806
|
+
}
|
807
|
+
|
808
|
+
int
|
809
|
+
main(void)
|
810
|
+
{
|
811
|
+
int i, j, k;
|
812
|
+
init_des();
|
813
|
+
|
814
|
+
printf("#ifndef HAVE_DES_TABLES\n\n");
|
815
|
+
printf("/* Initial key schedule permutation */\n");
|
816
|
+
printf("static const C_block PC1ROT[64/CHUNKBITS][1<<CHUNKBITS] = {\n");
|
817
|
+
for (i = 0; i < numberof(PC1ROT); ++i) {
|
818
|
+
printf("\t{\n");
|
819
|
+
for (j = 0; j < numberof(PC1ROT[0]); ++j) {
|
820
|
+
printf("\t\t");
|
821
|
+
dump_block(&PC1ROT[i][j]);
|
822
|
+
}
|
823
|
+
printf("\t},\n");
|
824
|
+
}
|
825
|
+
printf("};\n\n");
|
826
|
+
|
827
|
+
printf("/* Subsequent key schedule rotation permutations */\n");
|
828
|
+
printf("static const C_block PC2ROT[2][64/CHUNKBITS][1<<CHUNKBITS] = {\n");
|
829
|
+
for (i = 0; i < numberof(PC2ROT); ++i) {
|
830
|
+
printf("\t{\n");
|
831
|
+
for (j = 0; j < numberof(PC2ROT[0]); ++j) {
|
832
|
+
printf("\t\t{\n");
|
833
|
+
for (k = 0; k < numberof(PC2ROT[0][0]); ++k) {
|
834
|
+
printf("\t\t\t");
|
835
|
+
dump_block(&PC2ROT[i][j][k]);
|
836
|
+
}
|
837
|
+
printf("\t\t},\n");
|
838
|
+
}
|
839
|
+
printf("\t},\n");
|
840
|
+
}
|
841
|
+
printf("};\n\n");
|
842
|
+
|
843
|
+
printf("/* Initial permutation/expansion table */\n");
|
844
|
+
printf("static const C_block IE3264[32/CHUNKBITS][1<<CHUNKBITS] = {\n");
|
845
|
+
for (i = 0; i < numberof(IE3264); ++i) {
|
846
|
+
printf("\t{\n");
|
847
|
+
for (j = 0; j < numberof(IE3264[0]); ++j) {
|
848
|
+
printf("\t\t");
|
849
|
+
dump_block(&IE3264[i][j]);
|
850
|
+
}
|
851
|
+
printf("\t},\n");
|
852
|
+
}
|
853
|
+
printf("};\n\n");
|
854
|
+
|
855
|
+
printf("/* Table that combines the S, P, and E operations. */\n");
|
856
|
+
printf("static const unsigned long SPE[2][8][64] = {\n");
|
857
|
+
for (i = 0; i < numberof(SPE); ++i) {
|
858
|
+
printf("\t{\n");
|
859
|
+
for (j = 0; j < numberof(SPE[0]); ++j) {
|
860
|
+
int r = 0;
|
861
|
+
printf("\t\t{");
|
862
|
+
for (k = 0; k < numberof(SPE[0][0]); ++k) {
|
863
|
+
if (r == 0) printf("\n\t\t\t");
|
864
|
+
printf("%#10lx,", SPE[i][j][k]);
|
865
|
+
if (++r == 4) r = 0;
|
866
|
+
}
|
867
|
+
printf("\n\t\t},\n");
|
868
|
+
}
|
869
|
+
printf("\t},\n");
|
870
|
+
}
|
871
|
+
printf("};\n\n");
|
872
|
+
|
873
|
+
printf("/* compressed/interleaved => final permutation table */\n");
|
874
|
+
printf("static const C_block CF6464[64/CHUNKBITS][1<<CHUNKBITS] = {\n");
|
875
|
+
for (i = 0; i < numberof(CF6464); ++i) {
|
876
|
+
printf("\t{\n");
|
877
|
+
for (j = 0; j < numberof(CF6464[0]); ++j) {
|
878
|
+
printf("\t\t");
|
879
|
+
dump_block(&CF6464[i][j]);
|
880
|
+
}
|
881
|
+
printf("\t},\n");
|
882
|
+
}
|
883
|
+
printf("};\n\n");
|
884
|
+
printf("#define HAVE_DES_TABLES 1\n""#endif\n");
|
885
|
+
|
886
|
+
return 0;
|
887
|
+
}
|
888
|
+
#endif
|