line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
=head1 NAME |
2
|
|
|
|
|
|
|
|
3
|
|
|
|
|
|
|
Authen::DecHpwd - DEC VMS password hashing |
4
|
|
|
|
|
|
|
|
5
|
|
|
|
|
|
|
=head1 SYNOPSIS |
6
|
|
|
|
|
|
|
|
7
|
|
|
|
|
|
|
use Authen::DecHpwd qw( |
8
|
|
|
|
|
|
|
UAI_C_AD_II UAI_C_PURDY UAI_C_PURDY_V UAI_C_PURDY_S |
9
|
|
|
|
|
|
|
lgi_hpwd |
10
|
|
|
|
|
|
|
); |
11
|
|
|
|
|
|
|
|
12
|
|
|
|
|
|
|
$hash = lgi_hpwd("JRANDOM", "PASSWORD", UAI_C_PURDY_S, 1234); |
13
|
|
|
|
|
|
|
|
14
|
|
|
|
|
|
|
use Authen::DecHpwd qw(vms_username vms_password); |
15
|
|
|
|
|
|
|
|
16
|
|
|
|
|
|
|
$username = vms_username($username); |
17
|
|
|
|
|
|
|
$password = vms_password($password); |
18
|
|
|
|
|
|
|
|
19
|
|
|
|
|
|
|
=head1 DESCRIPTION |
20
|
|
|
|
|
|
|
|
21
|
|
|
|
|
|
|
This module implements the C password hashing function |
22
|
|
|
|
|
|
|
from VMS (also known as C), and some associated VMS username |
23
|
|
|
|
|
|
|
and password handling functions. |
24
|
|
|
|
|
|
|
|
25
|
|
|
|
|
|
|
The password hashing function is implemented in XS, with a hideously |
26
|
|
|
|
|
|
|
slow pure Perl backup version for systems that can't handle XS. |
27
|
|
|
|
|
|
|
|
28
|
|
|
|
|
|
|
=cut |
29
|
|
|
|
|
|
|
|
30
|
|
|
|
|
|
|
package Authen::DecHpwd; |
31
|
|
|
|
|
|
|
|
32
|
12
|
|
|
12
|
|
920467
|
{ use 5.006; } |
|
12
|
|
|
|
|
51
|
|
|
12
|
|
|
|
|
799
|
|
33
|
12
|
|
|
12
|
|
69
|
use warnings; |
|
12
|
|
|
|
|
23
|
|
|
12
|
|
|
|
|
412
|
|
34
|
12
|
|
|
12
|
|
74
|
use strict; |
|
12
|
|
|
|
|
31
|
|
|
12
|
|
|
|
|
510
|
|
35
|
|
|
|
|
|
|
|
36
|
12
|
|
|
12
|
|
17943
|
use Digest::CRC 0.14 qw(crc32); |
|
12
|
|
|
|
|
925881
|
|
|
12
|
|
|
|
|
1486
|
|
37
|
|
|
|
|
|
|
|
38
|
|
|
|
|
|
|
our $VERSION = "2.006"; |
39
|
|
|
|
|
|
|
|
40
|
12
|
|
|
12
|
|
7587
|
use parent "Exporter"; |
|
12
|
|
|
|
|
1404
|
|
|
12
|
|
|
|
|
95
|
|
41
|
|
|
|
|
|
|
our @EXPORT_OK = qw( |
42
|
|
|
|
|
|
|
UAI_C_AD_II UAI_C_PURDY UAI_C_PURDY_V UAI_C_PURDY_S |
43
|
|
|
|
|
|
|
lgi_hpwd |
44
|
|
|
|
|
|
|
vms_username vms_password |
45
|
|
|
|
|
|
|
); |
46
|
|
|
|
|
|
|
|
47
|
|
|
|
|
|
|
eval { local $SIG{__DIE__}; |
48
|
|
|
|
|
|
|
require XSLoader; |
49
|
|
|
|
|
|
|
XSLoader::load(__PACKAGE__, $VERSION); |
50
|
|
|
|
|
|
|
}; |
51
|
|
|
|
|
|
|
|
52
|
|
|
|
|
|
|
=head1 FUNCTIONS |
53
|
|
|
|
|
|
|
|
54
|
|
|
|
|
|
|
=over |
55
|
|
|
|
|
|
|
|
56
|
|
|
|
|
|
|
=item UAI_C_AD_II |
57
|
|
|
|
|
|
|
|
58
|
|
|
|
|
|
|
=item UAI_C_PURDY |
59
|
|
|
|
|
|
|
|
60
|
|
|
|
|
|
|
=item UAI_C_PURDY_V |
61
|
|
|
|
|
|
|
|
62
|
|
|
|
|
|
|
=item UAI_C_PURDY_S |
63
|
|
|
|
|
|
|
|
64
|
|
|
|
|
|
|
These constants are used to identify the four password hashing algorithms |
65
|
|
|
|
|
|
|
used by VMS. They are the C constants in VMS. |
66
|
|
|
|
|
|
|
|
67
|
|
|
|
|
|
|
C refers to a 32-bit CRC algorithm. The CRC polynomial used |
68
|
|
|
|
|
|
|
is the IEEE CRC-32 polynomial, as used in Ethernet, and in this context |
69
|
|
|
|
|
|
|
is known as "AUTODIN-II". The hash is merely the CRC of the password. |
70
|
|
|
|
|
|
|
|
71
|
|
|
|
|
|
|
C, C, and C refer to successive |
72
|
|
|
|
|
|
|
refinements of an algorithm based on Purdy polynomials. All of these |
73
|
|
|
|
|
|
|
algorithms use the salt and username parameters as salt, use the whole |
74
|
|
|
|
|
|
|
password, and return an eight-byte (64-bit) hash. The main part |
75
|
|
|
|
|
|
|
of the algorithm, the Purdy polynomial, is identical in all three. |
76
|
|
|
|
|
|
|
They differ in the pre-hashing, particularly in the treatment of the |
77
|
|
|
|
|
|
|
username parameter. |
78
|
|
|
|
|
|
|
|
79
|
|
|
|
|
|
|
In C the username is truncated or space-padded to 12 characters |
80
|
|
|
|
|
|
|
before being hashed in. C accepts a variable-length username. |
81
|
|
|
|
|
|
|
C accepts a variable-length username and also includes the |
82
|
|
|
|
|
|
|
password length in the hash. C also does some extra bit |
83
|
|
|
|
|
|
|
rotations when hashing in the username and password strings, in order |
84
|
|
|
|
|
|
|
to avoid aliasing. |
85
|
|
|
|
|
|
|
|
86
|
|
|
|
|
|
|
=cut |
87
|
|
|
|
|
|
|
|
88
|
12
|
|
|
12
|
|
1786
|
use constant UAI_C_AD_II => 0; |
|
12
|
|
|
|
|
73
|
|
|
12
|
|
|
|
|
1020
|
|
89
|
12
|
|
|
12
|
|
121
|
use constant UAI_C_PURDY => 1; |
|
12
|
|
|
|
|
27
|
|
|
12
|
|
|
|
|
915
|
|
90
|
12
|
|
|
12
|
|
67
|
use constant UAI_C_PURDY_V => 2; |
|
12
|
|
|
|
|
24
|
|
|
12
|
|
|
|
|
638
|
|
91
|
12
|
|
|
12
|
|
60
|
use constant UAI_C_PURDY_S => 3; |
|
12
|
|
|
|
|
28
|
|
|
12
|
|
|
|
|
4724
|
|
92
|
|
|
|
|
|
|
|
93
|
|
|
|
|
|
|
=item lgi_hpwd(USERNAME, PASSWORD, ALGORITHM, SALT) |
94
|
|
|
|
|
|
|
|
95
|
|
|
|
|
|
|
This is the C function from VMS (also known as |
96
|
|
|
|
|
|
|
C), but with the parameters in a different order. It hashes |
97
|
|
|
|
|
|
|
the PASSWORD string in a manner determined by the other parameters, |
98
|
|
|
|
|
|
|
and returns the hash as a string of bytes. |
99
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
ALGORITHM determines which hashing algorithm will be used. It must |
101
|
|
|
|
|
|
|
be the value of one of the algorithm constants supplied by this module |
102
|
|
|
|
|
|
|
(see above). |
103
|
|
|
|
|
|
|
|
104
|
|
|
|
|
|
|
SALT must be an integer in the range [0, 2^16). It modifies the hashing |
105
|
|
|
|
|
|
|
so that the same password does not always produce the same hash. |
106
|
|
|
|
|
|
|
|
107
|
|
|
|
|
|
|
USERNAME is a string that is used as more salt. In VMS it is the username |
108
|
|
|
|
|
|
|
of the account to which the password controls access. |
109
|
|
|
|
|
|
|
|
110
|
|
|
|
|
|
|
VMS usernames and passwords are constrained in character set and |
111
|
|
|
|
|
|
|
length, and are case-insensitive. This function does not enforce |
112
|
|
|
|
|
|
|
these restrictions, nor perform canonicalisation. If restrictions |
113
|
|
|
|
|
|
|
and canonicalisation are desired then they must be applied separately. |
114
|
|
|
|
|
|
|
The functions C and C described below may |
115
|
|
|
|
|
|
|
be useful. |
116
|
|
|
|
|
|
|
|
117
|
|
|
|
|
|
|
=cut |
118
|
|
|
|
|
|
|
|
119
|
5
|
100
|
100
|
5
|
1
|
29
|
unless(defined &lgi_hpwd) { { local $SIG{__DIE__}; eval q{ |
|
5
|
100
|
33
|
5
|
|
9
|
|
|
5
|
100
|
100
|
5
|
|
209
|
|
|
5
|
100
|
|
5
|
|
26
|
|
|
5
|
50
|
|
5
|
|
627
|
|
|
5
|
50
|
|
5
|
|
261
|
|
|
5
|
50
|
|
5
|
|
568223
|
|
|
5
|
100
|
|
5
|
|
55385
|
|
|
5
|
100
|
|
5
|
|
962
|
|
|
5
|
100
|
|
5
|
|
1036
|
|
|
5
|
100
|
|
5
|
|
1268
|
|
|
5
|
|
|
5
|
|
2368
|
|
|
5
|
|
|
5
|
|
34
|
|
|
5
|
|
|
5
|
|
12
|
|
|
5
|
|
|
5
|
|
391
|
|
|
5
|
|
|
5
|
|
26
|
|
|
5
|
|
|
5
|
|
12
|
|
|
5
|
|
|
5
|
|
295
|
|
|
5
|
|
|
5
|
|
27
|
|
|
5
|
|
|
2400
|
|
10
|
|
|
5
|
|
|
302400
|
|
439
|
|
|
5
|
|
|
258000
|
|
24
|
|
|
5
|
|
|
3600
|
|
8
|
|
|
5
|
|
|
100800
|
|
231
|
|
|
5
|
|
|
1200
|
|
22
|
|
|
5
|
|
|
50400
|
|
8
|
|
|
5
|
|
|
1200
|
|
194
|
|
|
5
|
|
|
1206
|
|
21
|
|
|
5
|
|
|
2412
|
|
8
|
|
|
5
|
|
|
1600
|
|
228
|
|
|
5
|
|
|
1600
|
|
22
|
|
|
5
|
|
|
1819304
|
|
7
|
|
|
5
|
|
|
0
|
|
310
|
|
|
5
|
|
|
2412
|
|
24
|
|
|
5
|
|
|
604800
|
|
8
|
|
|
5
|
|
|
33390
|
|
256
|
|
|
5
|
|
|
1602
|
|
23
|
|
|
5
|
|
|
|
|
8
|
|
|
5
|
|
|
|
|
207
|
|
|
5
|
|
|
|
|
22
|
|
|
5
|
|
|
|
|
7
|
|
|
5
|
|
|
|
|
268
|
|
|
5
|
|
|
|
|
23
|
|
|
5
|
|
|
|
|
9
|
|
|
5
|
|
|
|
|
245
|
|
|
5
|
|
|
|
|
22
|
|
|
5
|
|
|
|
|
7
|
|
|
5
|
|
|
|
|
260
|
|
|
5
|
|
|
|
|
23
|
|
|
5
|
|
|
|
|
6
|
|
|
5
|
|
|
|
|
248
|
|
|
5
|
|
|
|
|
32
|
|
|
5
|
|
|
|
|
6
|
|
|
5
|
|
|
|
|
253
|
|
|
5
|
|
|
|
|
23
|
|
|
5
|
|
|
|
|
8
|
|
|
5
|
|
|
|
|
9091
|
|
|
2400
|
|
|
|
|
5177
|
|
|
2400
|
|
|
|
|
10756
|
|
|
33390
|
|
|
|
|
144122
|
|
|
33390
|
|
|
|
|
137042
|
|
|
33390
|
|
|
|
|
1892212
|
|
|
1206
|
|
|
|
|
3357
|
|
|
302400
|
|
|
|
|
498942
|
|
|
302400
|
|
|
|
|
787917
|
|
|
302400
|
|
|
|
|
16976376
|
|
|
302400
|
|
|
|
|
15346373
|
|
|
302400
|
|
|
|
|
921445
|
|
|
302400
|
|
|
|
|
16527200
|
|
|
302400
|
|
|
|
|
20347659
|
|
|
302400
|
|
|
|
|
19884466
|
|
|
302400
|
|
|
|
|
16421073
|
|
|
302400
|
|
|
|
|
20136013
|
|
|
302400
|
|
|
|
|
20324045
|
|
|
258000
|
|
|
|
|
469412
|
|
|
258000
|
|
|
|
|
672506
|
|
|
258000
|
|
|
|
|
492586
|
|
|
258000
|
|
|
|
|
313786
|
|
|
258000
|
|
|
|
|
494882
|
|
|
258000
|
|
|
|
|
17207675
|
|
|
258000
|
|
|
|
|
17409969
|
|
|
46852
|
|
|
|
|
210914
|
|
|
46852
|
|
|
|
|
3023237
|
|
|
258000
|
|
|
|
|
4207674
|
|
|
3600
|
|
|
|
|
9411
|
|
|
3600
|
|
|
|
|
7327
|
|
|
3600
|
|
|
|
|
6357
|
|
|
3600
|
|
|
|
|
6056
|
|
|
3600
|
|
|
|
|
4964
|
|
|
3600
|
|
|
|
|
5638
|
|
|
3600
|
|
|
|
|
11045
|
|
|
37200
|
|
|
|
|
105313
|
|
|
15600
|
|
|
|
|
64120
|
|
|
12000
|
|
|
|
|
41130
|
|
|
3600
|
|
|
|
|
7920
|
|
|
3600
|
|
|
|
|
5147
|
|
|
15600
|
|
|
|
|
65306
|
|
|
3600
|
|
|
|
|
11650
|
|
|
12000
|
|
|
|
|
22932
|
|
|
33600
|
|
|
|
|
69235
|
|
|
33600
|
|
|
|
|
75140
|
|
|
33600
|
|
|
|
|
97419
|
|
|
0
|
|
|
|
|
0
|
|
|
100800
|
|
|
|
|
193860
|
|
|
100800
|
|
|
|
|
251041
|
|
|
100800
|
|
|
|
|
184516
|
|
|
100800
|
|
|
|
|
174905
|
|
|
100800
|
|
|
|
|
204683
|
|
|
100800
|
|
|
|
|
238746
|
|
|
100800
|
|
|
|
|
249657
|
|
|
1200
|
|
|
|
|
4152
|
|
|
1200
|
|
|
|
|
6833
|
|
|
0
|
|
|
|
|
0
|
|
|
50400
|
|
|
|
|
115413
|
|
|
50400
|
|
|
|
|
150698
|
|
|
50400
|
|
|
|
|
122971
|
|
|
50400
|
|
|
|
|
86987
|
|
|
50400
|
|
|
|
|
73539
|
|
|
50400
|
|
|
|
|
80720
|
|
|
50400
|
|
|
|
|
70952
|
|
|
50400
|
|
|
|
|
103310
|
|
|
50400
|
|
|
|
|
126498
|
|
|
50400
|
|
|
|
|
117248
|
|
|
50400
|
|
|
|
|
142752
|
|
|
50400
|
|
|
|
|
161679
|
|
|
50400
|
|
|
|
|
138828
|
|
|
50400
|
|
|
|
|
143607
|
|
|
50400
|
|
|
|
|
132811
|
|
|
50400
|
|
|
|
|
182372
|
|
|
1200
|
|
|
|
|
3305
|
|
|
1200
|
|
|
|
|
2064
|
|
|
1200
|
|
|
|
|
2057
|
|
|
1200
|
|
|
|
|
4554
|
|
|
1200
|
|
|
|
|
3994
|
|
|
1200
|
|
|
|
|
5153
|
|
|
1200
|
|
|
|
|
3505
|
|
|
1200
|
|
|
|
|
9720
|
|
|
1200
|
|
|
|
|
5490
|
|
|
1200
|
|
|
|
|
3580
|
|
|
1200
|
|
|
|
|
4798
|
|
|
1200
|
|
|
|
|
3337
|
|
|
1200
|
|
|
|
|
3440
|
|
|
1200
|
|
|
|
|
4341
|
|
|
1200
|
|
|
|
|
9477
|
|
|
1200
|
|
|
|
|
4422
|
|
|
1206
|
|
|
|
|
3488
|
|
|
1206
|
|
|
|
|
110094
|
|
|
2412
|
|
|
|
|
8829
|
|
|
1600
|
|
|
|
|
10194
|
|
|
1600
|
|
|
|
|
5066
|
|
|
1819304
|
|
|
|
|
58343038
|
|
|
1819304
|
|
|
|
|
6060226
|
|
|
1819304
|
|
|
|
|
103811827
|
|
|
0
|
|
|
|
|
0
|
|
|
2412
|
|
|
|
|
2833
|
|
|
2412
|
|
|
|
|
5601
|
|
|
2412
|
|
|
|
|
8445
|
|
|
604800
|
|
|
|
|
801184
|
|
|
604800
|
|
|
|
|
1477148
|
|
|
33390
|
|
|
|
|
121312
|
|
|
1602
|
|
|
|
|
24727343
|
|
|
1602
|
|
|
|
|
6919
|
|
|
0
|
|
|
|
|
0
|
|
|
1602
|
|
|
|
|
7001
|
|
|
1602
|
|
|
|
|
96085
|
|
|
1602
|
|
|
|
|
4494
|
|
|
1602
|
|
|
|
|
16753
|
|
|
1600
|
|
|
|
|
5410
|
|
|
400
|
|
|
|
|
1387
|
|
|
1200
|
|
|
|
|
3176
|
|
|
1200
|
|
|
|
|
2268
|
|
|
1200
|
|
|
|
|
5303
|
|
|
400
|
|
|
|
|
570
|
|
|
400
|
|
|
|
|
911
|
|
|
400
|
|
|
|
|
2501
|
|
|
1200
|
|
|
|
|
29184
|
|
|
1200
|
|
|
|
|
8406
|
|
|
1200
|
|
|
|
|
69320
|
|
|
1200
|
|
|
|
|
3899
|
|
|
1200
|
|
|
|
|
12143
|
|
120
|
|
|
|
|
|
|
|
121
|
|
|
|
|
|
|
use warnings; |
122
|
|
|
|
|
|
|
use strict; |
123
|
|
|
|
|
|
|
|
124
|
|
|
|
|
|
|
use Data::Integer 0.003 qw( |
125
|
|
|
|
|
|
|
natint_bits |
126
|
|
|
|
|
|
|
uint_shl uint_shr uint_rol |
127
|
|
|
|
|
|
|
uint_and uint_or |
128
|
|
|
|
|
|
|
uint_madd uint_cadd |
129
|
|
|
|
|
|
|
); |
130
|
|
|
|
|
|
|
use Scalar::String 0.000 qw(sclstr_is_downgraded sclstr_downgraded); |
131
|
|
|
|
|
|
|
|
132
|
|
|
|
|
|
|
my $u32_mask = 0xffffffff; |
133
|
|
|
|
|
|
|
|
134
|
|
|
|
|
|
|
sub _u32_shl($$) { |
135
|
|
|
|
|
|
|
if(natint_bits == 32) { |
136
|
|
|
|
|
|
|
return &uint_shl; |
137
|
|
|
|
|
|
|
} else { |
138
|
|
|
|
|
|
|
return uint_and(&uint_shl, $u32_mask); |
139
|
|
|
|
|
|
|
} |
140
|
|
|
|
|
|
|
} |
141
|
|
|
|
|
|
|
|
142
|
|
|
|
|
|
|
*_u32_shr = \&uint_shr; |
143
|
|
|
|
|
|
|
|
144
|
|
|
|
|
|
|
*_u32_and = \&uint_and; |
145
|
|
|
|
|
|
|
|
146
|
|
|
|
|
|
|
sub _u32_rol($$) { |
147
|
|
|
|
|
|
|
if(natint_bits == 32) { |
148
|
|
|
|
|
|
|
return &uint_rol; |
149
|
|
|
|
|
|
|
} else { |
150
|
|
|
|
|
|
|
return $_[0] if $_[1] == 0; |
151
|
|
|
|
|
|
|
return uint_and(uint_or(uint_shl($_[0], $_[1]), |
152
|
|
|
|
|
|
|
uint_shr($_[0], 32-$_[1])), |
153
|
|
|
|
|
|
|
$u32_mask); |
154
|
|
|
|
|
|
|
} |
155
|
|
|
|
|
|
|
} |
156
|
|
|
|
|
|
|
|
157
|
|
|
|
|
|
|
sub _u32_madd($$) { uint_and(&uint_madd, $u32_mask) } |
158
|
|
|
|
|
|
|
|
159
|
|
|
|
|
|
|
sub _u32_cadd($$$) { |
160
|
|
|
|
|
|
|
if(natint_bits == 32) { |
161
|
|
|
|
|
|
|
return &uint_cadd; |
162
|
|
|
|
|
|
|
} else { |
163
|
|
|
|
|
|
|
my(undef, $val) = uint_cadd($_[0], $_[1], $_[2]); |
164
|
|
|
|
|
|
|
return (uint_and(uint_shr($val, 32), 1), |
165
|
|
|
|
|
|
|
uint_and($val, $u32_mask)); |
166
|
|
|
|
|
|
|
} |
167
|
|
|
|
|
|
|
} |
168
|
|
|
|
|
|
|
|
169
|
|
|
|
|
|
|
my $u16_mask = 0xffff; |
170
|
|
|
|
|
|
|
|
171
|
|
|
|
|
|
|
sub _u16_madd($$) { uint_and(&uint_madd, $u16_mask) } |
172
|
|
|
|
|
|
|
|
173
|
|
|
|
|
|
|
my $u8_mask = 0xff; |
174
|
|
|
|
|
|
|
|
175
|
|
|
|
|
|
|
sub _u8_madd($$) { uint_and(&uint_madd, $u8_mask) } |
176
|
|
|
|
|
|
|
|
177
|
|
|
|
|
|
|
sub _addUnalignedWord($$) { |
178
|
|
|
|
|
|
|
$_[0] = pack("v", _u16_madd(unpack("v", $_[0]), $_[1])); |
179
|
|
|
|
|
|
|
} |
180
|
|
|
|
|
|
|
|
181
|
|
|
|
|
|
|
use constant _PURDY_USERNAME_LENGTH => 12; |
182
|
|
|
|
|
|
|
|
183
|
|
|
|
|
|
|
use constant _A => 59; |
184
|
|
|
|
|
|
|
use constant _DWORD_MAX => 0xffffffff; |
185
|
|
|
|
|
|
|
use constant _P_D_LOW => _DWORD_MAX - _A + 1; |
186
|
|
|
|
|
|
|
use constant _P_D_HIGH => _DWORD_MAX; |
187
|
|
|
|
|
|
|
|
188
|
|
|
|
|
|
|
use constant _N0 => 0xfffffd; |
189
|
|
|
|
|
|
|
use constant _N1 => 0xffffc1; |
190
|
|
|
|
|
|
|
use constant _Na => 448; |
191
|
|
|
|
|
|
|
use constant _Nb => 37449; |
192
|
|
|
|
|
|
|
|
193
|
|
|
|
|
|
|
use constant _MASK => 7; |
194
|
|
|
|
|
|
|
|
195
|
|
|
|
|
|
|
use constant _C1 => pack("VV", 0xffffffad, 0xffffffff); |
196
|
|
|
|
|
|
|
use constant _C2 => pack("VV", 0xffffff4d, 0xffffffff); |
197
|
|
|
|
|
|
|
use constant _C3 => pack("VV", 0xfffffeff, 0xffffffff); |
198
|
|
|
|
|
|
|
use constant _C4 => pack("VV", 0xfffffebd, 0xffffffff); |
199
|
|
|
|
|
|
|
use constant _C5 => pack("VV", 0xfffffe95, 0xffffffff); |
200
|
|
|
|
|
|
|
|
201
|
|
|
|
|
|
|
sub _PQMOD_R0($) { |
202
|
|
|
|
|
|
|
my($low, $high) = unpack("VV", $_[0]); |
203
|
|
|
|
|
|
|
if($high == _P_D_HIGH && $low >= _P_D_LOW) { |
204
|
|
|
|
|
|
|
$_[0] = pack("VV", _u32_madd($low, _A), 0); |
205
|
|
|
|
|
|
|
} |
206
|
|
|
|
|
|
|
} |
207
|
|
|
|
|
|
|
|
208
|
|
|
|
|
|
|
sub _ROL1($) { $_[0] = pack("V", _u32_rol(unpack("V", $_[0]), 1)); } |
209
|
|
|
|
|
|
|
|
210
|
|
|
|
|
|
|
sub _QROL1($) { |
211
|
|
|
|
|
|
|
_ROL1(substr($_[0], 0, 4)); |
212
|
|
|
|
|
|
|
_ROL1(substr($_[0], 4, 4)); |
213
|
|
|
|
|
|
|
} |
214
|
|
|
|
|
|
|
|
215
|
|
|
|
|
|
|
sub _EMULQ($$$) { |
216
|
|
|
|
|
|
|
my($a, $b, undef) = @_; |
217
|
|
|
|
|
|
|
my $hi = _u32_shr($a, 16) * _u32_shr($b, 16); |
218
|
|
|
|
|
|
|
my $lo = _u32_and($a, 0xffff) * _u32_and($b, 0xffff); |
219
|
|
|
|
|
|
|
my $carry; |
220
|
|
|
|
|
|
|
my $p = _u32_shr($a, 16) * _u32_and($b, 0xffff); |
221
|
|
|
|
|
|
|
($carry, $lo) = _u32_cadd($lo, _u32_shl($p, 16), 0); |
222
|
|
|
|
|
|
|
($carry, $hi) = _u32_cadd($hi, _u32_shr($p, 16), $carry); |
223
|
|
|
|
|
|
|
$p = _u32_and($a, 0xffff) * _u32_shr($b, 16); |
224
|
|
|
|
|
|
|
($carry, $lo) = _u32_cadd($lo, _u32_shl($p, 16), 0); |
225
|
|
|
|
|
|
|
($carry, $hi) = _u32_cadd($hi, _u32_shr($p, 16), $carry); |
226
|
|
|
|
|
|
|
$_[2] = pack("VV", $lo, $hi); |
227
|
|
|
|
|
|
|
} |
228
|
|
|
|
|
|
|
|
229
|
|
|
|
|
|
|
sub _PQADD_R0($$$) { |
230
|
|
|
|
|
|
|
my($u, $y, undef) = @_; |
231
|
|
|
|
|
|
|
my($ulo, $uhi) = unpack("VV", $u); |
232
|
|
|
|
|
|
|
my($ylo, $yhi) = unpack("VV", $y); |
233
|
|
|
|
|
|
|
my($carry, $rlo, $rhi); |
234
|
|
|
|
|
|
|
($carry, $rlo) = _u32_cadd($ulo, $ylo, 0); |
235
|
|
|
|
|
|
|
($carry, $rhi) = _u32_cadd($uhi, $yhi, $carry); |
236
|
|
|
|
|
|
|
while($carry) { |
237
|
|
|
|
|
|
|
($carry, $rlo) = _u32_cadd($rlo, _A, 0); |
238
|
|
|
|
|
|
|
($carry, $rhi) = _u32_cadd($rhi, 0, $carry); |
239
|
|
|
|
|
|
|
} |
240
|
|
|
|
|
|
|
$_[2] = pack("VV", $rlo, $rhi); |
241
|
|
|
|
|
|
|
} |
242
|
|
|
|
|
|
|
|
243
|
|
|
|
|
|
|
sub _COLLAPSE_R2($$$) { |
244
|
|
|
|
|
|
|
my($s, undef, $isPurdyS) = @_; |
245
|
|
|
|
|
|
|
for(my $p = length($s); $p != 0; $p--) { |
246
|
|
|
|
|
|
|
my $pp = $p & _MASK; |
247
|
|
|
|
|
|
|
substr($_[1], $pp, 1) = pack("C", |
248
|
|
|
|
|
|
|
_u8_madd(unpack("C", substr($_[1], $pp, 1)), |
249
|
|
|
|
|
|
|
unpack("C", substr($s, -$p, 1)))); |
250
|
|
|
|
|
|
|
if($isPurdyS && $pp == _MASK) { _QROL1($_[1]); } |
251
|
|
|
|
|
|
|
} |
252
|
|
|
|
|
|
|
} |
253
|
|
|
|
|
|
|
|
254
|
|
|
|
|
|
|
sub _PQLSH_R0($$) { |
255
|
|
|
|
|
|
|
my($u, undef) = @_; |
256
|
|
|
|
|
|
|
my($ulo, $uhi) = unpack("VV", $u); |
257
|
|
|
|
|
|
|
my $stack = pack("VV", 0, 0); |
258
|
|
|
|
|
|
|
my $x = pack("VV", 0, 0); |
259
|
|
|
|
|
|
|
_EMULQ($uhi, _A, $stack); |
260
|
|
|
|
|
|
|
$x = pack("VV", 0, $ulo); |
261
|
|
|
|
|
|
|
_PQADD_R0($x, $stack, $_[1]); |
262
|
|
|
|
|
|
|
} |
263
|
|
|
|
|
|
|
|
264
|
|
|
|
|
|
|
sub _PQMUL_R2($$$) { |
265
|
|
|
|
|
|
|
my($u, $y, undef) = @_; |
266
|
|
|
|
|
|
|
my($ulo, $uhi) = unpack("VV", $u); |
267
|
|
|
|
|
|
|
my($ylo, $yhi) = unpack("VV", $y); |
268
|
|
|
|
|
|
|
my $stack = pack("VV", 0, 0); |
269
|
|
|
|
|
|
|
my $part1 = pack("VV", 0, 0); |
270
|
|
|
|
|
|
|
my $part2 = pack("VV", 0, 0); |
271
|
|
|
|
|
|
|
my $part3 = pack("VV", 0, 0); |
272
|
|
|
|
|
|
|
_EMULQ($uhi, $yhi, $stack); |
273
|
|
|
|
|
|
|
_PQLSH_R0($stack, $part1); |
274
|
|
|
|
|
|
|
_EMULQ($uhi, $ylo, $stack); |
275
|
|
|
|
|
|
|
_EMULQ($ulo, $yhi, $part2); |
276
|
|
|
|
|
|
|
_PQADD_R0($stack, $part2, $part3); |
277
|
|
|
|
|
|
|
_PQADD_R0($part1, $part3, $stack); |
278
|
|
|
|
|
|
|
_PQLSH_R0($stack, $part1); |
279
|
|
|
|
|
|
|
_EMULQ($ulo, $ylo, $stack); |
280
|
|
|
|
|
|
|
_PQADD_R0($part1, $stack, $_[2]); |
281
|
|
|
|
|
|
|
} |
282
|
|
|
|
|
|
|
|
283
|
|
|
|
|
|
|
sub _PQEXP_R3($$$) { |
284
|
|
|
|
|
|
|
my($u, $n, undef) = @_; |
285
|
|
|
|
|
|
|
my $y = pack("VV", 0, 0); |
286
|
|
|
|
|
|
|
my $z = pack("VV", 0, 0); |
287
|
|
|
|
|
|
|
my $z1 = pack("VV", 0, 0); |
288
|
|
|
|
|
|
|
my $yok = 0; |
289
|
|
|
|
|
|
|
$z = $u; |
290
|
|
|
|
|
|
|
while($n != 0) { |
291
|
|
|
|
|
|
|
if($n & 1) { |
292
|
|
|
|
|
|
|
if($yok) { |
293
|
|
|
|
|
|
|
_PQMUL_R2($y, $z, $_[2]); |
294
|
|
|
|
|
|
|
} else { |
295
|
|
|
|
|
|
|
$_[2] = $z; |
296
|
|
|
|
|
|
|
$yok = 1; |
297
|
|
|
|
|
|
|
} |
298
|
|
|
|
|
|
|
if($n == 1) { return; } |
299
|
|
|
|
|
|
|
$y = $_[2]; |
300
|
|
|
|
|
|
|
} |
301
|
|
|
|
|
|
|
$n >>= 1; |
302
|
|
|
|
|
|
|
$z1 = $z; |
303
|
|
|
|
|
|
|
_PQMUL_R2($z1, $z1, $z); |
304
|
|
|
|
|
|
|
} |
305
|
|
|
|
|
|
|
$_[2] = pack("VV", 1, 0); |
306
|
|
|
|
|
|
|
} |
307
|
|
|
|
|
|
|
|
308
|
|
|
|
|
|
|
sub _Purdy($) { |
309
|
|
|
|
|
|
|
my $t1 = pack("VV", 0, 0); |
310
|
|
|
|
|
|
|
my $t2 = pack("VV", 0, 0); |
311
|
|
|
|
|
|
|
my $t3 = pack("VV", 0, 0); |
312
|
|
|
|
|
|
|
|
313
|
|
|
|
|
|
|
_PQEXP_R3($_[0], _Na, $t1); |
314
|
|
|
|
|
|
|
_PQEXP_R3($t1, _Nb, $t2); |
315
|
|
|
|
|
|
|
_PQEXP_R3($_[0], (_N0 - _N1), $t1); |
316
|
|
|
|
|
|
|
_PQADD_R0($t1, _C1, $t3); |
317
|
|
|
|
|
|
|
_PQMUL_R2($t2, $t3, $t1); |
318
|
|
|
|
|
|
|
|
319
|
|
|
|
|
|
|
_PQMUL_R2($_[0], _C2, $t2); |
320
|
|
|
|
|
|
|
_PQADD_R0($t2, _C3, $t3); |
321
|
|
|
|
|
|
|
_PQMUL_R2($_[0], $t3, $t2); |
322
|
|
|
|
|
|
|
_PQADD_R0($t2, _C4, $t3); |
323
|
|
|
|
|
|
|
|
324
|
|
|
|
|
|
|
_PQADD_R0($t1, $t3, $t2); |
325
|
|
|
|
|
|
|
_PQMUL_R2($_[0], $t2, $t1); |
326
|
|
|
|
|
|
|
_PQADD_R0($t1, _C5, $_[0]); |
327
|
|
|
|
|
|
|
|
328
|
|
|
|
|
|
|
_PQMOD_R0($_[0]); |
329
|
|
|
|
|
|
|
} |
330
|
|
|
|
|
|
|
|
331
|
|
|
|
|
|
|
sub lgi_hpwd($$$$) { |
332
|
|
|
|
|
|
|
my($username, $password, $alg, $salt) = @_; |
333
|
|
|
|
|
|
|
if($alg > UAI_C_PURDY_S) { |
334
|
|
|
|
|
|
|
die "algorithm value $alg is not recognised"; |
335
|
|
|
|
|
|
|
} |
336
|
|
|
|
|
|
|
$salt = uint_and($salt, 0xffff); |
337
|
|
|
|
|
|
|
# This string downgrading is necessary for correct behaviour on |
338
|
|
|
|
|
|
|
# perl 5.6 and 5.8. It is not necessary on 5.10, but will still |
339
|
|
|
|
|
|
|
# slightly improve performance. |
340
|
|
|
|
|
|
|
$username = sclstr_downgraded($username, 1); |
341
|
|
|
|
|
|
|
$password = sclstr_downgraded($password, 1); |
342
|
|
|
|
|
|
|
die "input must contain only octets" |
343
|
|
|
|
|
|
|
unless sclstr_is_downgraded($username) && |
344
|
|
|
|
|
|
|
sclstr_is_downgraded($password); |
345
|
|
|
|
|
|
|
if($alg == UAI_C_AD_II) { |
346
|
|
|
|
|
|
|
return pack("VV", Digest::CRC::crc32($password)^0xffffffff, 0); |
347
|
|
|
|
|
|
|
} |
348
|
|
|
|
|
|
|
my $isPurdyS = $alg == UAI_C_PURDY_S; |
349
|
|
|
|
|
|
|
my $output = pack("VV", 0, 0); |
350
|
|
|
|
|
|
|
if($alg == UAI_C_PURDY) { |
351
|
|
|
|
|
|
|
$username .= " " x 12; |
352
|
|
|
|
|
|
|
$username = substr($username, 0, _PURDY_USERNAME_LENGTH); |
353
|
|
|
|
|
|
|
} elsif($alg == UAI_C_PURDY_S) { |
354
|
|
|
|
|
|
|
_addUnalignedWord(substr($output, 0, 2), length($password)); |
355
|
|
|
|
|
|
|
} |
356
|
|
|
|
|
|
|
_COLLAPSE_R2($password, $output, $isPurdyS); |
357
|
|
|
|
|
|
|
_addUnalignedWord(substr($output, 3, 2), $salt); |
358
|
|
|
|
|
|
|
_COLLAPSE_R2($username, $output, $isPurdyS); |
359
|
|
|
|
|
|
|
_Purdy($output); |
360
|
|
|
|
|
|
|
return $output; |
361
|
|
|
|
|
|
|
} |
362
|
|
|
|
|
|
|
|
363
|
|
|
|
|
|
|
1; |
364
|
|
|
|
|
|
|
|
365
|
|
|
|
|
|
|
}; } die $@ if $@ ne "" } |
366
|
|
|
|
|
|
|
|
367
|
|
|
|
|
|
|
=item vms_username(USERNAME) |
368
|
|
|
|
|
|
|
|
369
|
|
|
|
|
|
|
Checks whether the USERNAME string matches VMS username syntax, and |
370
|
|
|
|
|
|
|
canonicalises it. VMS username syntax is 1 to 31 characters from |
371
|
|
|
|
|
|
|
case-insensitive alphanumerics, "B<_>", and "B<$>". If the string has |
372
|
|
|
|
|
|
|
correct username syntax then the username is returned in canonical form |
373
|
|
|
|
|
|
|
(uppercase). If the string is not a username then C is returned. |
374
|
|
|
|
|
|
|
|
375
|
|
|
|
|
|
|
=cut |
376
|
|
|
|
|
|
|
|
377
|
|
|
|
|
|
|
sub vms_username($) { |
378
|
15
|
100
|
|
15
|
1
|
648
|
return $_[0] =~ /\A[_\$0-9A-Za-z]{1,31}\z/ ? uc("$_[0]") : undef; |
379
|
|
|
|
|
|
|
} |
380
|
|
|
|
|
|
|
|
381
|
|
|
|
|
|
|
=item vms_password(PASSWORD) |
382
|
|
|
|
|
|
|
|
383
|
|
|
|
|
|
|
Checks whether the PASSWORD string is an acceptable VMS password, |
384
|
|
|
|
|
|
|
and canonicalises it. VMS password syntax is 1 to 32 characters from |
385
|
|
|
|
|
|
|
case-insensitive alphanumerics, "B<_>", and "B<$>". If the string is |
386
|
|
|
|
|
|
|
an acceptable password then the password is returned in canonical form |
387
|
|
|
|
|
|
|
(uppercase). If the string is not an acceptable password then C |
388
|
|
|
|
|
|
|
is returned. |
389
|
|
|
|
|
|
|
|
390
|
|
|
|
|
|
|
=cut |
391
|
|
|
|
|
|
|
|
392
|
|
|
|
|
|
|
sub vms_password($) { |
393
|
16
|
100
|
|
16
|
1
|
180
|
return $_[0] =~ /\A[_\$0-9A-Za-z]{1,32}\z/ ? uc("$_[0]") : undef; |
394
|
|
|
|
|
|
|
} |
395
|
|
|
|
|
|
|
|
396
|
|
|
|
|
|
|
=back |
397
|
|
|
|
|
|
|
|
398
|
|
|
|
|
|
|
=head1 SEE ALSO |
399
|
|
|
|
|
|
|
|
400
|
|
|
|
|
|
|
L |
401
|
|
|
|
|
|
|
|
402
|
|
|
|
|
|
|
=head1 AUTHOR |
403
|
|
|
|
|
|
|
|
404
|
|
|
|
|
|
|
The original C implementation of C was written by Shawn Clifford. |
405
|
|
|
|
|
|
|
The code has since been developed by Davide Casale, Mario Ambrogetti, |
406
|
|
|
|
|
|
|
Terence Lee, Jean-loup Gailly, Solar Designer, and Andrew Main (Zefram). |
407
|
|
|
|
|
|
|
|
408
|
|
|
|
|
|
|
Mike McCauley created the first version of |
409
|
|
|
|
|
|
|
C, establishing the Perl interface. This was based on |
410
|
|
|
|
|
|
|
Shawn Clifford's code without the later developments. |
411
|
|
|
|
|
|
|
|
412
|
|
|
|
|
|
|
Andrew Main (Zefram) created a new C |
413
|
|
|
|
|
|
|
based on the more developed C code presently used, and added ancillary |
414
|
|
|
|
|
|
|
functions. |
415
|
|
|
|
|
|
|
|
416
|
|
|
|
|
|
|
=head1 COPYRIGHT |
417
|
|
|
|
|
|
|
|
418
|
|
|
|
|
|
|
Copyright (C) 2002 Jean-loup Gailly |
419
|
|
|
|
|
|
|
|
420
|
|
|
|
|
|
|
Based in part on code from John the Ripper, Copyright (C) 1996-2002 |
421
|
|
|
|
|
|
|
Solar Designer |
422
|
|
|
|
|
|
|
|
423
|
|
|
|
|
|
|
Copyright (C) 2006, 2007, 2009, 2010, 2011 |
424
|
|
|
|
|
|
|
Andrew Main (Zefram) |
425
|
|
|
|
|
|
|
|
426
|
|
|
|
|
|
|
=head1 LICENSE |
427
|
|
|
|
|
|
|
|
428
|
|
|
|
|
|
|
This module is free software; you can redistribute it and/or modify it |
429
|
|
|
|
|
|
|
under the terms of the GNU General Public License as published by the |
430
|
|
|
|
|
|
|
Free Software Foundation; either version 2 of the License, or (at your |
431
|
|
|
|
|
|
|
option) any later version. |
432
|
|
|
|
|
|
|
|
433
|
|
|
|
|
|
|
=cut |
434
|
|
|
|
|
|
|
|
435
|
|
|
|
|
|
|
1; |