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
|
|
259050
|
{ use 5.006; } |
|
12
|
|
|
|
|
50
|
|
33
|
12
|
|
|
12
|
|
78
|
use warnings; |
|
12
|
|
|
|
|
31
|
|
|
12
|
|
|
|
|
392
|
|
34
|
12
|
|
|
12
|
|
75
|
use strict; |
|
12
|
|
|
|
|
37
|
|
|
12
|
|
|
|
|
452
|
|
35
|
|
|
|
|
|
|
|
36
|
12
|
|
|
12
|
|
7245
|
use Digest::CRC 0.14 qw(crc32); |
|
12
|
|
|
|
|
30826
|
|
|
12
|
|
|
|
|
1196
|
|
37
|
|
|
|
|
|
|
|
38
|
|
|
|
|
|
|
our $VERSION = "2.007"; |
39
|
|
|
|
|
|
|
|
40
|
12
|
|
|
12
|
|
2127
|
use parent "Exporter"; |
|
12
|
|
|
|
|
1088
|
|
|
12
|
|
|
|
|
84
|
|
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
|
|
1450
|
use constant UAI_C_AD_II => 0; |
|
12
|
|
|
|
|
35
|
|
|
12
|
|
|
|
|
1029
|
|
89
|
12
|
|
|
12
|
|
81
|
use constant UAI_C_PURDY => 1; |
|
12
|
|
|
|
|
34
|
|
|
12
|
|
|
|
|
565
|
|
90
|
12
|
|
|
12
|
|
77
|
use constant UAI_C_PURDY_V => 2; |
|
12
|
|
|
|
|
29
|
|
|
12
|
|
|
|
|
617
|
|
91
|
12
|
|
|
12
|
|
73
|
use constant UAI_C_PURDY_S => 3; |
|
12
|
|
|
|
|
35
|
|
|
12
|
|
|
|
|
3627
|
|
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
|
41
|
unless(defined &lgi_hpwd) { { local $SIG{__DIE__}; eval q{ |
|
5
|
100
|
33
|
5
|
|
17
|
|
|
5
|
100
|
100
|
5
|
|
233
|
|
|
5
|
100
|
|
5
|
|
47
|
|
|
5
|
50
|
|
5
|
|
14
|
|
|
5
|
50
|
|
5
|
|
218
|
|
|
5
|
50
|
|
5
|
|
3187
|
|
|
5
|
100
|
|
5
|
|
57831
|
|
|
5
|
100
|
|
5
|
|
875
|
|
|
5
|
100
|
|
5
|
|
767
|
|
|
5
|
100
|
|
5
|
|
1101
|
|
|
5
|
|
|
5
|
|
2147
|
|
|
5
|
|
|
5
|
|
47
|
|
|
5
|
|
|
5
|
|
13
|
|
|
5
|
|
|
5
|
|
447
|
|
|
5
|
|
|
5
|
|
37
|
|
|
5
|
|
|
5
|
|
15
|
|
|
5
|
|
|
5
|
|
269
|
|
|
5
|
|
|
5
|
|
33
|
|
|
5
|
|
|
2400
|
|
15
|
|
|
5
|
|
|
302400
|
|
313
|
|
|
5
|
|
|
258000
|
|
37
|
|
|
5
|
|
|
3600
|
|
15
|
|
|
5
|
|
|
100800
|
|
256
|
|
|
5
|
|
|
1200
|
|
143
|
|
|
5
|
|
|
50400
|
|
16
|
|
|
5
|
|
|
1200
|
|
231
|
|
|
5
|
|
|
1206
|
|
33
|
|
|
5
|
|
|
2412
|
|
13
|
|
|
5
|
|
|
1600
|
|
246
|
|
|
5
|
|
|
1600
|
|
33
|
|
|
5
|
|
|
1819304
|
|
13
|
|
|
5
|
|
|
0
|
|
302
|
|
|
5
|
|
|
2412
|
|
35
|
|
|
5
|
|
|
604800
|
|
16
|
|
|
5
|
|
|
33390
|
|
242
|
|
|
5
|
|
|
1602
|
|
32
|
|
|
5
|
|
|
|
|
13
|
|
|
5
|
|
|
|
|
244
|
|
|
5
|
|
|
|
|
32
|
|
|
5
|
|
|
|
|
12
|
|
|
5
|
|
|
|
|
341
|
|
|
5
|
|
|
|
|
39
|
|
|
5
|
|
|
|
|
15
|
|
|
5
|
|
|
|
|
292
|
|
|
5
|
|
|
|
|
34
|
|
|
5
|
|
|
|
|
13
|
|
|
5
|
|
|
|
|
279
|
|
|
5
|
|
|
|
|
33
|
|
|
5
|
|
|
|
|
13
|
|
|
5
|
|
|
|
|
277
|
|
|
5
|
|
|
|
|
36
|
|
|
5
|
|
|
|
|
13
|
|
|
5
|
|
|
|
|
290
|
|
|
5
|
|
|
|
|
34
|
|
|
5
|
|
|
|
|
13
|
|
|
5
|
|
|
|
|
7825
|
|
|
2400
|
|
|
|
|
7232
|
|
|
2400
|
|
|
|
|
9043
|
|
|
33390
|
|
|
|
|
163444
|
|
|
33390
|
|
|
|
|
115225
|
|
|
33390
|
|
|
|
|
1766442
|
|
|
1206
|
|
|
|
|
3408
|
|
|
302400
|
|
|
|
|
598353
|
|
|
302400
|
|
|
|
|
765387
|
|
|
302400
|
|
|
|
|
17090802
|
|
|
302400
|
|
|
|
|
14379850
|
|
|
302400
|
|
|
|
|
755337
|
|
|
302400
|
|
|
|
|
15744340
|
|
|
302400
|
|
|
|
|
20360026
|
|
|
302400
|
|
|
|
|
20393160
|
|
|
302400
|
|
|
|
|
15742207
|
|
|
302400
|
|
|
|
|
20458585
|
|
|
302400
|
|
|
|
|
20550382
|
|
|
258000
|
|
|
|
|
556908
|
|
|
258000
|
|
|
|
|
722208
|
|
|
258000
|
|
|
|
|
563311
|
|
|
258000
|
|
|
|
|
475519
|
|
|
258000
|
|
|
|
|
548424
|
|
|
258000
|
|
|
|
|
17445755
|
|
|
258000
|
|
|
|
|
17405811
|
|
|
46852
|
|
|
|
|
117263
|
|
|
46852
|
|
|
|
|
3168798
|
|
|
258000
|
|
|
|
|
4032232
|
|
|
3600
|
|
|
|
|
11739
|
|
|
3600
|
|
|
|
|
8597
|
|
|
3600
|
|
|
|
|
8724
|
|
|
3600
|
|
|
|
|
7276
|
|
|
3600
|
|
|
|
|
7400
|
|
|
3600
|
|
|
|
|
8724
|
|
|
3600
|
|
|
|
|
12199
|
|
|
37200
|
|
|
|
|
126522
|
|
|
15600
|
|
|
|
|
52580
|
|
|
12000
|
|
|
|
|
40445
|
|
|
3600
|
|
|
|
|
9470
|
|
|
3600
|
|
|
|
|
7710
|
|
|
15600
|
|
|
|
|
56217
|
|
|
3600
|
|
|
|
|
12283
|
|
|
12000
|
|
|
|
|
27317
|
|
|
33600
|
|
|
|
|
76199
|
|
|
33600
|
|
|
|
|
65292
|
|
|
33600
|
|
|
|
|
96139
|
|
|
0
|
|
|
|
|
0
|
|
|
100800
|
|
|
|
|
225103
|
|
|
100800
|
|
|
|
|
293025
|
|
|
100800
|
|
|
|
|
208507
|
|
|
100800
|
|
|
|
|
184883
|
|
|
100800
|
|
|
|
|
271916
|
|
|
100800
|
|
|
|
|
248624
|
|
|
100800
|
|
|
|
|
274636
|
|
|
1200
|
|
|
|
|
4799
|
|
|
1200
|
|
|
|
|
7237
|
|
|
0
|
|
|
|
|
0
|
|
|
50400
|
|
|
|
|
131874
|
|
|
50400
|
|
|
|
|
161576
|
|
|
50400
|
|
|
|
|
139190
|
|
|
50400
|
|
|
|
|
105942
|
|
|
50400
|
|
|
|
|
90408
|
|
|
50400
|
|
|
|
|
98232
|
|
|
50400
|
|
|
|
|
95107
|
|
|
50400
|
|
|
|
|
143717
|
|
|
50400
|
|
|
|
|
162812
|
|
|
50400
|
|
|
|
|
146266
|
|
|
50400
|
|
|
|
|
156539
|
|
|
50400
|
|
|
|
|
160625
|
|
|
50400
|
|
|
|
|
149954
|
|
|
50400
|
|
|
|
|
165858
|
|
|
50400
|
|
|
|
|
165962
|
|
|
50400
|
|
|
|
|
162322
|
|
|
1200
|
|
|
|
|
2864
|
|
|
1200
|
|
|
|
|
2507
|
|
|
1200
|
|
|
|
|
2440
|
|
|
1200
|
|
|
|
|
4747
|
|
|
1200
|
|
|
|
|
4664
|
|
|
1200
|
|
|
|
|
5751
|
|
|
1200
|
|
|
|
|
4737
|
|
|
1200
|
|
|
|
|
4930
|
|
|
1200
|
|
|
|
|
5104
|
|
|
1200
|
|
|
|
|
5301
|
|
|
1200
|
|
|
|
|
5147
|
|
|
1200
|
|
|
|
|
4568
|
|
|
1200
|
|
|
|
|
4198
|
|
|
1200
|
|
|
|
|
4840
|
|
|
1200
|
|
|
|
|
4667
|
|
|
1200
|
|
|
|
|
5444
|
|
|
1206
|
|
|
|
|
4350
|
|
|
1206
|
|
|
|
|
107108
|
|
|
2412
|
|
|
|
|
9208
|
|
|
1600
|
|
|
|
|
10211
|
|
|
1600
|
|
|
|
|
5001
|
|
|
1819304
|
|
|
|
|
54757888
|
|
|
1819304
|
|
|
|
|
4864090
|
|
|
1819304
|
|
|
|
|
102422619
|
|
|
0
|
|
|
|
|
0
|
|
|
2412
|
|
|
|
|
4357
|
|
|
2412
|
|
|
|
|
6101
|
|
|
2412
|
|
|
|
|
6897
|
|
|
604800
|
|
|
|
|
1089780
|
|
|
604800
|
|
|
|
|
1429651
|
|
|
33390
|
|
|
|
|
80920
|
|
|
1602
|
|
|
|
|
1014278
|
|
|
1602
|
|
|
|
|
14981
|
|
|
0
|
|
|
|
|
0
|
|
|
1602
|
|
|
|
|
6982
|
|
|
1602
|
|
|
|
|
75669
|
|
|
1602
|
|
|
|
|
5789
|
|
|
1602
|
|
|
|
|
14224
|
|
|
1600
|
|
|
|
|
6126
|
|
|
400
|
|
|
|
|
7783
|
|
|
1200
|
|
|
|
|
3208
|
|
|
1200
|
|
|
|
|
2913
|
|
|
1200
|
|
|
|
|
5038
|
|
|
400
|
|
|
|
|
1251
|
|
|
400
|
|
|
|
|
1284
|
|
|
400
|
|
|
|
|
2131
|
|
|
1200
|
|
|
|
|
27754
|
|
|
1200
|
|
|
|
|
6013
|
|
|
1200
|
|
|
|
|
66566
|
|
|
1200
|
|
|
|
|
4572
|
|
|
1200
|
|
|
|
|
10294
|
|
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
|
132
|
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
|
108
|
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, 2017 |
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; |