@@ -6,38 +6,154 @@ function _JS2ANSI(str/*:string*/)/*:Array<number>*/ {
6
6
}
7
7
8
8
/* [MS-OFFCRYPTO] 2.1.4 Version */
9
- function parse_Version ( blob , length /*:number*/ ) {
9
+ function parse_CRYPTOVersion ( blob , length /*:number*/ ) {
10
10
var o = { } ;
11
11
o . Major = blob . read_shift ( 2 ) ;
12
12
o . Minor = blob . read_shift ( 2 ) ;
13
13
return o ;
14
14
}
15
- /* [MS-OFFCRYPTO] 2.3.2 Encryption Header */
16
- function parse_EncryptionHeader ( blob , length /*:number*/ ) {
15
+
16
+ /* [MS-OFFCRYPTO] 2.1.5 DataSpaceVersionInfo */
17
+ function parse_DataSpaceVersionInfo ( blob , length ) {
17
18
var o = { } ;
18
- o . Flags = blob . read_shift ( 4 ) ;
19
+ o . id = blob . read_shift ( 0 , 'lpp4' ) ;
20
+ o . R = parse_CRYPTOVersion ( blob , 4 ) ;
21
+ o . U = parse_CRYPTOVersion ( blob , 4 ) ;
22
+ o . W = parse_CRYPTOVersion ( blob , 4 ) ;
23
+ return o ;
24
+ }
25
+
26
+ /* [MS-OFFCRYPTO] 2.1.6.1 DataSpaceMapEntry Structure */
27
+ function parse_DataSpaceMapEntry ( blob ) {
28
+ var len = blob . read_shift ( 4 ) ;
29
+ var end = blob . l + len - 4 ;
30
+ var o = { } ;
31
+ var cnt = blob . read_shift ( 4 ) ;
32
+ var comps = [ ] ;
33
+ while ( cnt -- > 0 ) {
34
+ /* [MS-OFFCRYPTO] 2.1.6.2 DataSpaceReferenceComponent Structure */
35
+ var rc = { } ;
36
+ rc . t = blob . read_shift ( 4 ) ;
37
+ rc . v = blob . read_shift ( 0 , 'lpp4' ) ;
38
+ comps . push ( rc ) ;
39
+ }
40
+ o . name = blob . read_shift ( 0 , 'lpp4' ) ;
41
+ o . comps = comps ;
42
+ return o ;
43
+ }
19
44
20
- // Check if SizeExtra is 0x00000000
21
- var tmp = blob . read_shift ( 4 ) ;
22
- if ( tmp !== 0 ) throw 'Unrecognized SizeExtra: ' + tmp ;
45
+ /* [MS-OFFCRYPTO] 2.1.6 DataSpaceMap */
46
+ function parse_DataSpaceMap ( blob , length ) {
47
+ var o = [ ] ;
48
+ blob . l += 4 ; // must be 0x8
49
+ var cnt = blob . read_shift ( 4 ) ;
50
+ while ( cnt -- > 0 ) o . push ( parse_DataSpaceMapEntry ( blob ) ) ;
51
+ return o ;
52
+ }
23
53
54
+ /* [MS-OFFCRYPTO] 2.1.7 DataSpaceDefinition */
55
+ function parse_DataSpaceDefinition ( blob , length ) {
56
+ var o = [ ] ;
57
+ blob . l += 4 ; // must be 0x8
58
+ var cnt = blob . read_shift ( 4 ) ;
59
+ while ( cnt -- > 0 ) o . push ( blob . read_shift ( 0 , 'lpp4' ) ) ;
60
+ return o ;
61
+ }
62
+
63
+ /* [MS-OFFCRYPTO] 2.1.8 DataSpaceDefinition */
64
+ function parse_TransformInfoHeader ( blob , length ) {
65
+ var o = { } ;
66
+ var len = blob . read_shift ( 4 ) ;
67
+ var tgt = blob . l + len - 4 ;
68
+ blob . l += 4 ; // must be 0x1
69
+ o . id = blob . read_shift ( 0 , 'lpp4' ) ;
70
+ // tgt == len
71
+ o . name = blob . read_shift ( 0 , 'lpp4' ) ;
72
+ o . R = parse_CRYPTOVersion ( blob , 4 ) ;
73
+ o . U = parse_CRYPTOVersion ( blob , 4 ) ;
74
+ o . W = parse_CRYPTOVersion ( blob , 4 ) ;
75
+ return o ;
76
+ }
77
+
78
+ function parse_Primary ( blob , length ) {
79
+ /* [MS-OFFCRYPTO] 2.2.6 IRMDSTransformInfo */
80
+ var hdr = parse_TransformInfoHeader ( blob ) ;
81
+ /* [MS-OFFCRYPTO] 2.1.9 EncryptionTransformInfo */
82
+ hdr . ename = blob . read_shift ( 0 , '8lpp4' ) ;
83
+ hdr . blksz = blob . read_shift ( 4 ) ;
84
+ hdr . cmode = blob . read_shift ( 4 ) ;
85
+ if ( blob . read_shift ( 4 ) != 0x04 ) throw new Error ( "Bad !Primary record" ) ;
86
+ return hdr ;
87
+ }
88
+
89
+ /* [MS-OFFCRYPTO] 2.3.2 Encryption Header */
90
+ function parse_EncryptionHeader ( blob , length /*:number*/ ) {
91
+ var tgt = blob . l + length ;
92
+ var o = { } ;
93
+ o . Flags = ( blob . read_shift ( 4 ) & 0x3F ) ;
94
+ blob . l += 4 ;
24
95
o . AlgID = blob . read_shift ( 4 ) ;
96
+ var valid = false ;
25
97
switch ( o . AlgID ) {
26
- case 0 : case 0x6801 : case 0x660E : case 0x660F : case 0x6610 : break ;
98
+ case 0x660E : case 0x660F : case 0x6610 : valid = ( o . Flags == 0x24 ) ; break ;
99
+ case 0x6801 : valid = ( o . Flags == 0x04 ) ; break ;
100
+ case 0 : valid = ( o . Flags == 0x10 || o . Flags == 0x04 || o . Flags == 0x24 ) ; break ;
27
101
default : throw 'Unrecognized encryption algorithm: ' + o . AlgID ;
28
102
}
29
- parsenoop ( blob , length - 12 ) ;
103
+ if ( ! valid ) throw new Error ( "Encryption Flags/AlgID mismatch" ) ;
104
+ o . AlgIDHash = blob . read_shift ( 4 ) ;
105
+ o . KeySize = blob . read_shift ( 4 ) ;
106
+ o . ProviderType = blob . read_shift ( 4 ) ;
107
+ blob . l += 8 ;
108
+ o . CSPName = blob . read_shift ( ( tgt - blob . l ) >> 1 , 'utf16le' ) . slice ( 0 , - 1 ) ;
109
+ blob . l = tgt ;
30
110
return o ;
31
111
}
32
112
33
113
/* [MS-OFFCRYPTO] 2.3.3 Encryption Verifier */
34
114
function parse_EncryptionVerifier ( blob , length /*:number*/ ) {
35
- return parsenoop ( blob , length ) ;
115
+ var o = { } ;
116
+ blob . l += 4 ; // SaltSize must be 0x10
117
+ o . Salt = blob . slice ( blob . l , blob . l + 16 ) ; blob . l += 16 ;
118
+ o . Verifier = blob . slice ( blob . l , blob . l + 16 ) ; blob . l += 16 ;
119
+ var sz = blob . read_shift ( 4 ) ;
120
+ o . VerifierHash = blob . slice ( blob . l , blob . l + sz ) ; blob . l += sz ;
121
+ return o ;
36
122
}
123
+
124
+ /* [MS-OFFCRYPTO] 2.3.4.* EncryptionInfo Stream */
125
+ function parse_EncryptionInfo ( blob , length ) {
126
+ var vers = parse_CRYPTOVersion ( blob ) ;
127
+ switch ( vers . Minor ) {
128
+ case 0x02 : return parse_EncInfoStd ( blob , vers ) ;
129
+ case 0x03 : return parse_EncInfoExt ( blob , vers ) ;
130
+ case 0x04 : return parse_EncInfoAgl ( blob , vers ) ;
131
+ }
132
+ throw new Error ( "ECMA-376 Encryped file unrecognized Version: " + vers . Minor ) ;
133
+ }
134
+
135
+ /* [MS-OFFCRYPTO] 2.3.4.5 EncryptionInfo Stream (Standard Encryption) */
136
+ function parse_EncInfoStd ( blob , vers ) {
137
+ var flags = blob . read_shift ( 4 ) ;
138
+ if ( ( flags & 0x3F ) != 0x24 ) throw new Error ( "EncryptionInfo mismatch" ) ;
139
+ var sz = blob . read_shift ( 4 ) ;
140
+ var tgt = blob . l + sz ;
141
+ var hdr = parse_EncryptionHeader ( blob , sz ) ;
142
+ var verifier = parse_EncryptionVerifier ( blob , blob . length - blob . l ) ;
143
+ return { t :"Std" , h :hdr , v :verifier } ;
144
+ }
145
+ /* [MS-OFFCRYPTO] 2.3.4.6 EncryptionInfo Stream (Extensible Encryption) */
146
+ function parse_EncInfoExt ( blob , vers ) { throw new Error ( "File is password-protected: ECMA-376 Extensible" ) ; }
147
+ /* [MS-OFFCRYPTO] 2.3.4.10 EncryptionInfo Stream (Agile Encryption) */
148
+ function parse_EncInfoAgl ( blob , vers ) { throw new Error ( "File is password-protected: ECMA-376 Agile" ) ; }
149
+
150
+
151
+
152
+
37
153
/* [MS-OFFCRYPTO] 2.3.5.1 RC4 CryptoAPI Encryption Header */
38
154
function parse_RC4CryptoHeader ( blob , length /*:number*/ ) {
39
155
var o = { } ;
40
- var vers = o . EncryptionVersionInfo = parse_Version ( blob , 4 ) ; length -= 4 ;
156
+ var vers = o . EncryptionVersionInfo = parse_CRYPTOVersion ( blob , 4 ) ; length -= 4 ;
41
157
if ( vers . Minor != 2 ) throw 'unrecognized minor version code: ' + vers . Minor ;
42
158
if ( vers . Major > 4 || vers . Major < 2 ) throw 'unrecognized major version code: ' + vers . Major ;
43
159
o . Flags = blob . read_shift ( 4 ) ; length -= 4 ;
@@ -49,7 +165,7 @@ function parse_RC4CryptoHeader(blob, length/*:number*/) {
49
165
/* [MS-OFFCRYPTO] 2.3.6.1 RC4 Encryption Header */
50
166
function parse_RC4Header ( blob , length /*:number*/ ) {
51
167
var o = { } ;
52
- var vers = o . EncryptionVersionInfo = parse_Version ( blob , 4 ) ; length -= 4 ;
168
+ var vers = o . EncryptionVersionInfo = parse_CRYPTOVersion ( blob , 4 ) ; length -= 4 ;
53
169
if ( vers . Major != 1 || vers . Minor != 1 ) throw 'unrecognized version code ' + vers . Major + ' : ' + vers . Minor ;
54
170
o . Salt = blob . read_shift ( 16 ) ;
55
171
o . EncryptedVerifier = blob . read_shift ( 16 ) ;
0 commit comments