packetgen-plugin-ipsec 1.0.2 → 1.0.3
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 +4 -4
- data/.github/workflows/specs.yml +28 -0
- data/.rubocop.yml +8 -1
- data/.travis.yml +1 -1
- data/Gemfile +11 -0
- data/Rakefile +10 -4
- data/lib/packetgen/plugin/crypto.rb +6 -4
- data/lib/packetgen/plugin/esp.rb +373 -370
- data/lib/packetgen/plugin/ike.rb +218 -217
- data/lib/packetgen/plugin/ike/auth.rb +141 -141
- data/lib/packetgen/plugin/ike/cert.rb +61 -62
- data/lib/packetgen/plugin/ike/certreq.rb +51 -52
- data/lib/packetgen/plugin/ike/id.rb +80 -80
- data/lib/packetgen/plugin/ike/ke.rb +64 -66
- data/lib/packetgen/plugin/ike/nonce.rb +29 -31
- data/lib/packetgen/plugin/ike/notify.rb +135 -139
- data/lib/packetgen/plugin/ike/payload.rb +58 -57
- data/lib/packetgen/plugin/ike/sa.rb +515 -452
- data/lib/packetgen/plugin/ike/sk.rb +219 -221
- data/lib/packetgen/plugin/ike/ts.rb +223 -223
- data/lib/packetgen/plugin/ike/vendor_id.rb +28 -30
- data/lib/packetgen/plugin/ipsec_version.rb +8 -1
- data/packetgen-plugin-ipsec.gemspec +3 -9
- metadata +8 -77
@@ -5,75 +5,76 @@
|
|
5
5
|
|
6
6
|
# frozen_string_literal: true
|
7
7
|
|
8
|
-
module PacketGen
|
9
|
-
|
10
|
-
class IKE
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
return @protocol_name if defined? @protocol_name
|
8
|
+
module PacketGen::Plugin
|
9
|
+
class IKE
|
10
|
+
# PacketGen::Header::Base class for IKE payloads. This class may also be used for unknown payloads.
|
11
|
+
#
|
12
|
+
# This class handles generic IKE payload Plugin:
|
13
|
+
# 1 2 3
|
14
|
+
# 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
|
15
|
+
# +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
16
|
+
# | Next Payload |C| RESERVED | Payload Length |
|
17
|
+
# +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
18
|
+
# to which a {#content} field is added to handle content of unknown payload types.
|
19
|
+
# @author Sylvain Daubert
|
20
|
+
class Payload < PacketGen::Header::Base
|
21
|
+
# Give protocol name
|
22
|
+
# @return [String]
|
23
|
+
def self.protocol_name
|
24
|
+
return @protocol_name if defined? @protocol_name
|
26
25
|
|
27
|
-
|
28
|
-
|
29
|
-
|
26
|
+
basename = to_s.sub(/.*::/, '')
|
27
|
+
@protocol_name = "IKE::#{basename}"
|
28
|
+
end
|
30
29
|
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
30
|
+
# @!attribute next
|
31
|
+
# 8-bit next payload
|
32
|
+
# @return [Integer]
|
33
|
+
define_field :next, PacketGen::Types::Int8
|
34
|
+
# @!attribute flags
|
35
|
+
# 8-bit flags
|
36
|
+
# @return [Integer]
|
37
|
+
define_field :flags, PacketGen::Types::Int8
|
38
|
+
# @!attribute length
|
39
|
+
# 16-bit payload total length, including generic payload Plugin
|
40
|
+
# @return [Integer]
|
41
|
+
define_field :length, PacketGen::Types::Int16
|
42
|
+
# @!attribute content
|
43
|
+
# Payload content. Depends on payload. Variable length.
|
44
|
+
# @return [String]
|
45
|
+
define_field :content, PacketGen::Types::String, builder: ->(h, t) { t.new(length_from: -> { h.length - h.offset_of(:content) }) }
|
47
46
|
|
48
|
-
|
49
|
-
|
47
|
+
# Defining a body permits using Packet#parse to parse next IKE payloads.
|
48
|
+
define_field :body, PacketGen::Types::String
|
50
49
|
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
50
|
+
# @!attribute critical
|
51
|
+
# critical flag
|
52
|
+
# @return [Boolean]
|
53
|
+
# @!attribute hreserved
|
54
|
+
# reserved part of {#flags} field
|
55
|
+
# @return [Integer]
|
56
|
+
define_bit_fields_on :flags, :critical, :hreserved, 7
|
58
57
|
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
58
|
+
def initialize(options={})
|
59
|
+
super
|
60
|
+
if options[:content]
|
61
|
+
self[:content] = PacketGen::Types::String.new
|
62
|
+
self[:content].read options[:content]
|
63
63
|
end
|
64
|
+
calc_length unless options[:length]
|
65
|
+
end
|
64
66
|
|
65
67
|
# Compute length and set {#length} field
|
66
68
|
# @return [Integer] new length
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
end
|
69
|
+
def calc_length
|
70
|
+
# Here, #body is next payload, so body size should not be taken in
|
71
|
+
# account (payload's real body is #content).
|
72
|
+
self.length = sz - self[:body].sz
|
72
73
|
end
|
73
74
|
end
|
74
|
-
|
75
|
-
Header.add_class IKE::Payload
|
76
75
|
end
|
76
|
+
|
77
|
+
PacketGen::Header.add_class IKE::Payload
|
77
78
|
end
|
78
79
|
|
79
80
|
require_relative 'sa'
|
@@ -1,494 +1,557 @@
|
|
1
1
|
# coding: utf-8
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
2
4
|
# This file is part of IPsec packetgen plugin.
|
3
5
|
# See https://github.com/sdaubert/packetgen-plugin-ipsec for more informations
|
4
6
|
# Copyright (c) 2018 Sylvain Daubert <sylvain.daubert@laposte.net>
|
5
7
|
# This program is published under MIT license.
|
6
8
|
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
#
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
else
|
46
|
-
self[:length].value = 8 unless options[:length]
|
47
|
-
end
|
9
|
+
module PacketGen::Plugin
|
10
|
+
class IKE
|
11
|
+
# Transform attribute.
|
12
|
+
# 1 2 3
|
13
|
+
# 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
|
14
|
+
# +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
15
|
+
# |A| Attribute Type | AF=0 Attribute Length |
|
16
|
+
# |F| | AF=1 Attribute Value |
|
17
|
+
# +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
18
|
+
# | AF=0 Attribute Value |
|
19
|
+
# | AF=1 Not Transmitted |
|
20
|
+
# +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
21
|
+
# Such an attribute may have a TLV (Type/length/value) format if AF=0,
|
22
|
+
# or a TV format (AF=1).
|
23
|
+
# @author Sylvain Daubert
|
24
|
+
class Attribute < PacketGen::Types::Fields
|
25
|
+
# KeyLength attribute type
|
26
|
+
TYPE_KEY_LENGTH = 14
|
27
|
+
|
28
|
+
# @!attribute type
|
29
|
+
# attribute type
|
30
|
+
# @return [Integer]
|
31
|
+
define_field :type, PacketGen::Types::Int16
|
32
|
+
# @!attribute length
|
33
|
+
# attribute length
|
34
|
+
# @return [Integer]
|
35
|
+
define_field :length, PacketGen::Types::Int16
|
36
|
+
# @!attribute value
|
37
|
+
# attribute value
|
38
|
+
# @return [Integer]
|
39
|
+
define_field :value, PacketGen::Types::Int32, optional: ->(h) { !h.tv_format? }
|
40
|
+
|
41
|
+
def initialize(options={})
|
42
|
+
super
|
43
|
+
if tv_format?
|
44
|
+
self[:length].value = (options[:value] & 0xffff)
|
45
|
+
else
|
46
|
+
self[:length].value = 8 unless options[:length]
|
48
47
|
end
|
48
|
+
end
|
49
49
|
|
50
|
-
|
50
|
+
undef length, value
|
51
51
|
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
# @return [Integer]
|
58
|
-
def value
|
59
|
-
tv_format? ? self[:length].to_i : self[:value].to_i
|
60
|
-
end
|
52
|
+
# @return [Integer]
|
53
|
+
def length
|
54
|
+
tv_format? ? 4 : self[:length].to_i
|
55
|
+
end
|
61
56
|
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
.detect { |c| self.class.const_get(c) == (type & 0x7fff) } || "attr[#{type & 0x7fff}]"
|
67
|
-
name = name.to_s.sub(/TYPE_/, '')
|
68
|
-
"#{name}=#{value}"
|
69
|
-
end
|
57
|
+
# @return [Integer]
|
58
|
+
def value
|
59
|
+
tv_format? ? self[:length].to_i : self[:value].to_i
|
60
|
+
end
|
70
61
|
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
62
|
+
# Get a human readable string
|
63
|
+
# @return [String]
|
64
|
+
def to_human
|
65
|
+
name = self.class.constants.grep(/TYPE_/)
|
66
|
+
.detect { |c| self.class.const_get(c) == (type & 0x7fff) } || "attr[#{type & 0x7fff}]"
|
67
|
+
name = name.to_s.sub(/TYPE_/, '')
|
68
|
+
"#{name}=#{value}"
|
76
69
|
end
|
77
70
|
|
78
|
-
#
|
79
|
-
# @
|
80
|
-
|
81
|
-
|
71
|
+
# Say if attribute use TV format (+true+) or TLV one (+false+)
|
72
|
+
# @return [Boolean]
|
73
|
+
def tv_format?
|
74
|
+
type & 0x8000 == 0x8000
|
82
75
|
end
|
76
|
+
end
|
83
77
|
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
# +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
90
|
-
# |Transform Type | RESERVED | Transform ID |
|
91
|
-
# +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
92
|
-
# | |
|
93
|
-
# ~ Transform Attributes ~
|
94
|
-
# | |
|
95
|
-
# +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
96
|
-
#
|
97
|
-
# == Create a Transform
|
98
|
-
# # using type and id names
|
99
|
-
# trans = PacketGen::Plugin::IKE::Transform.new(type: 'ENCR', id: 'AES_CBC')
|
100
|
-
# # using integer values
|
101
|
-
# trans = PacketGen::Plugin::IKE::Transform.new(type: 1, id: 12)
|
102
|
-
# == Add attributes to a transform
|
103
|
-
# # using an Attribute object
|
104
|
-
# attr = PacketGen::Plugin::IKE::Attribute.new(type: 14, value: 128)
|
105
|
-
# trans.attributes << attr
|
106
|
-
# # using a hash
|
107
|
-
# trans.attributes << { type: 14, value: 128 }
|
108
|
-
# @author Sylvain Daubert
|
109
|
-
class Transform < PacketGen::Types::Fields
|
110
|
-
TYPES = {
|
111
|
-
'ENCR' => 1,
|
112
|
-
'PRF' => 2,
|
113
|
-
'INTG' => 3,
|
114
|
-
'DH' => 4,
|
115
|
-
'ESN' => 5
|
116
|
-
}.freeze
|
117
|
-
|
118
|
-
ENCR_DES_IV64 = 1
|
119
|
-
ENCR_DES = 2
|
120
|
-
ENCR_3DES = 3
|
121
|
-
ENCR_RC5 = 4
|
122
|
-
ENCR_IDEA = 5
|
123
|
-
ENCR_CAST = 6
|
124
|
-
ENCR_BLOWFISH = 7
|
125
|
-
ENCR_3IDEA = 8
|
126
|
-
ENCR_DES_IV32 = 9
|
127
|
-
ENCR_AES_CBC = 12
|
128
|
-
ENCR_AES_CTR = 13
|
129
|
-
ENCR_AES_CCM8 = 14
|
130
|
-
ENCR_AES_CCM12 = 15
|
131
|
-
ENCR_AES_CCM16 = 16
|
132
|
-
ENCR_AES_GCM8 = 18
|
133
|
-
ENCR_AES_GCM12 = 19
|
134
|
-
ENCR_AES_GCM16 = 20
|
135
|
-
ENCR_CAMELLIA_CBC = 23
|
136
|
-
ENCR_CAMELLIA_CTR = 24
|
137
|
-
ENCR_CAMELLIA_CCM8 = 25
|
138
|
-
ENCR_CAMELLIA_CCM12 = 26
|
139
|
-
ENCR_CAMELLIA_CCM16 = 27
|
140
|
-
ENCR_CHACHA20_POLY1305 = 28
|
141
|
-
|
142
|
-
PRF_HMAC_MD5 = 1
|
143
|
-
PRF_HMAC_SHA1 = 2
|
144
|
-
PRF_AES128_XCBC = 4
|
145
|
-
PRF_HMAC_SHA2_256 = 5
|
146
|
-
PRF_HMAC_SHA2_384 = 6
|
147
|
-
PRF_HMAC_SHA2_512 = 7
|
148
|
-
PRF_AES128_CMAC = 8
|
149
|
-
|
150
|
-
INTG_NONE = 0
|
151
|
-
INTG_HMAC_MD5_96 = 1
|
152
|
-
INTG_HMAC_SHA1_96 = 2
|
153
|
-
INTG_AES_XCBC_96 = 5
|
154
|
-
INTG_HMAC_MD5_128 = 6
|
155
|
-
INTG_HMAC_SHA1_160 = 7
|
156
|
-
INTG_AES_CMAC_96 = 8
|
157
|
-
INTG_AES128_GMAC = 9
|
158
|
-
INTG_AES192_GMAC = 10
|
159
|
-
INTG_AES256_GMAC = 11
|
160
|
-
INTG_HMAC_SHA2_256_128 = 12
|
161
|
-
INTG_HMAC_SHA2_384_192 = 13
|
162
|
-
INTG_HMAC_SHA2_512_256 = 14
|
163
|
-
|
164
|
-
DH_NONE = 0
|
165
|
-
DH_MODP768 = 1
|
166
|
-
DH_MODP1024 = 2
|
167
|
-
DH_MODP1536 = 5
|
168
|
-
DH_MODP2048 = 14
|
169
|
-
DH_MODP3072 = 15
|
170
|
-
DH_MODP4096 = 16
|
171
|
-
DH_MODP6144 = 17
|
172
|
-
DH_MODP8192 = 18
|
173
|
-
DH_ECP256 = 19
|
174
|
-
DH_ECP384 = 20
|
175
|
-
DH_ECP521 = 21
|
176
|
-
DH_BRAINPOOLP224 = 27
|
177
|
-
DH_BRAINPOOLP256 = 28
|
178
|
-
DH_BRAINPOOLP384 = 29
|
179
|
-
DH_BRAINPOOLP512 = 30
|
180
|
-
DH_CURVE25519 = 31
|
181
|
-
DH_CURVE448 = 32
|
182
|
-
|
183
|
-
ESN_NO_ESN = 0
|
184
|
-
ESN_ESN = 1
|
185
|
-
|
186
|
-
# @!attribute last
|
187
|
-
# 8-bit last substructure. Specifies whether or not this is the
|
188
|
-
# last Transform Substructure in the Proposal. This field has a value of 0
|
189
|
-
# if this was the last Transform Substructure, and a value of 3 if
|
190
|
-
# there are more Transform Substructures.
|
191
|
-
# @return [Integer]
|
192
|
-
define_field :last, PacketGen::Types::Int8
|
193
|
-
# @!attribute rsv1
|
194
|
-
# 8-bit reserved field
|
195
|
-
# @return [Integer]
|
196
|
-
define_field :rsv1, PacketGen::Types::Int8
|
197
|
-
# @!attribute length
|
198
|
-
# 16-bit transform length
|
199
|
-
# @return [Integer]
|
200
|
-
define_field :length, PacketGen::Types::Int16
|
201
|
-
# @!attribute [r] type
|
202
|
-
# 8-bit transform type. The Transform Type is the cryptographic
|
203
|
-
# algorithm type (i.e. encryption, PRF, integrity, etc.)
|
204
|
-
# @return [Integer]
|
205
|
-
define_field :type, PacketGen::Types::Int8Enum, enum: TYPES
|
206
|
-
# @!attribute rsv2
|
207
|
-
# 8-bit reserved field
|
208
|
-
# @return [Integer]
|
209
|
-
define_field :rsv2, PacketGen::Types::Int8
|
210
|
-
# @!attribute [r] id
|
211
|
-
# 16-bit transform ID. The Transform ID is the specific instance of
|
212
|
-
# the proposed transform type.
|
213
|
-
# @return [Integer]
|
214
|
-
define_field :id, PacketGen::Types::Int16
|
215
|
-
# @!attribute attributes
|
216
|
-
# Set of attributes for this transform
|
217
|
-
# @return [Attributes]
|
218
|
-
define_field :attributes, Attributes, builder: ->(h, t) { t.new(length_from: -> { h.length - h.offset_of(:attributes) }) }
|
219
|
-
|
220
|
-
def initialize(options={})
|
221
|
-
super
|
222
|
-
self.type = options[:type] if options[:type]
|
223
|
-
self.id = options[:id] if options[:id]
|
224
|
-
self[:length].value = sz unless options[:length]
|
225
|
-
end
|
78
|
+
# Set of {Attribute} in a {Transform}
|
79
|
+
# @author Sylvain Daubert
|
80
|
+
class Attributes < PacketGen::Types::Array
|
81
|
+
set_of Attribute
|
82
|
+
end
|
226
83
|
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
84
|
+
# SA Tranform substructure, as defined in RFC 7296 §3.3.2
|
85
|
+
# 1 2 3
|
86
|
+
# 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
|
87
|
+
# +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
88
|
+
# | Last Substruc | RESERVED | Transform Length |
|
89
|
+
# +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
90
|
+
# |Transform Type | RESERVED | Transform ID |
|
91
|
+
# +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
92
|
+
# | |
|
93
|
+
# ~ Transform Attributes ~
|
94
|
+
# | |
|
95
|
+
# +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
96
|
+
#
|
97
|
+
# == Create a Transform
|
98
|
+
# # using type and id names
|
99
|
+
# trans = PacketGen::Plugin::IKE::Transform.new(type: 'ENCR', id: 'AES_CBC')
|
100
|
+
# # using integer values
|
101
|
+
# trans = PacketGen::Plugin::IKE::Transform.new(type: 1, id: 12)
|
102
|
+
# == Add attributes to a transform
|
103
|
+
# # using an Attribute object
|
104
|
+
# attr = PacketGen::Plugin::IKE::Attribute.new(type: 14, value: 128)
|
105
|
+
# trans.attributes << attr
|
106
|
+
# # using a hash
|
107
|
+
# trans.attributes << { type: 14, value: 128 }
|
108
|
+
# @author Sylvain Daubert
|
109
|
+
class Transform < PacketGen::Types::Fields
|
110
|
+
# Transform types
|
111
|
+
TYPES = {
|
112
|
+
'ENCR' => 1,
|
113
|
+
'PRF' => 2,
|
114
|
+
'INTG' => 3,
|
115
|
+
'DH' => 4,
|
116
|
+
'ESN' => 5
|
117
|
+
}.freeze
|
118
|
+
|
119
|
+
# DES encryption with 64-bit IV
|
120
|
+
ENCR_DES_IV64 = 1
|
121
|
+
# DES encryption
|
122
|
+
ENCR_DES = 2
|
123
|
+
# 3DES encryption
|
124
|
+
ENCR_3DES = 3
|
125
|
+
# RC5 integrity
|
126
|
+
ENCR_RC5 = 4
|
127
|
+
# IDEA encryption
|
128
|
+
ENCR_IDEA = 5
|
129
|
+
# Cast encryption
|
130
|
+
ENCR_CAST = 6
|
131
|
+
# Blowfish encryption
|
132
|
+
ENCR_BLOWFISH = 7
|
133
|
+
# 3IDEA encryption
|
134
|
+
ENCR_3IDEA = 8
|
135
|
+
# DES encryption with 32-bit IV
|
136
|
+
ENCR_DES_IV32 = 9
|
137
|
+
# AES with CBC mode encryption
|
138
|
+
ENCR_AES_CBC = 12
|
139
|
+
# AES with CTR mode encryption
|
140
|
+
ENCR_AES_CTR = 13
|
141
|
+
# AES with CCM mode encryption/authentication, 8-bytes ICV
|
142
|
+
ENCR_AES_CCM8 = 14
|
143
|
+
# AES with CCM mode encryption/authentication, 12-bytes ICV
|
144
|
+
ENCR_AES_CCM12 = 15
|
145
|
+
# AES with CCM mode encryption/authentication, 16-bytes ICV
|
146
|
+
ENCR_AES_CCM16 = 16
|
147
|
+
# AES with GCM mode encryption/authentication, 8-bytes ICV
|
148
|
+
ENCR_AES_GCM8 = 18
|
149
|
+
# AES with GCM mode encryption/authentication, 12-bytes ICV
|
150
|
+
ENCR_AES_GCM12 = 19
|
151
|
+
# AES with GCM mode encryption/authentication, 16-bytes ICV
|
152
|
+
ENCR_AES_GCM16 = 20
|
153
|
+
# CAMELLIA with CBC mode encryption
|
154
|
+
ENCR_CAMELLIA_CBC = 23
|
155
|
+
# CAMELLIA with CTR mode encryption
|
156
|
+
ENCR_CAMELLIA_CTR = 24
|
157
|
+
# CAMELLIA with CCM mode encryption/authentication, 8-bytes ICV
|
158
|
+
ENCR_CAMELLIA_CCM8 = 25
|
159
|
+
# CAMELLIA with CCM mode encryption/authentication, 12-bytes ICV
|
160
|
+
ENCR_CAMELLIA_CCM12 = 26
|
161
|
+
# CAMELLIA with CCM mode encryption/authentication, 16-bytes ICV
|
162
|
+
ENCR_CAMELLIA_CCM16 = 27
|
163
|
+
# CHACHA20 encryption with POLY1035 authentication
|
164
|
+
ENCR_CHACHA20_POLY1305 = 28
|
165
|
+
|
166
|
+
# PRF with HMAC on MD5
|
167
|
+
PRF_HMAC_MD5 = 1
|
168
|
+
# PRF with HMAC on SHA-1
|
169
|
+
PRF_HMAC_SHA1 = 2
|
170
|
+
# PRF with AES-128 with XCBC mode
|
171
|
+
PRF_AES128_XCBC = 4
|
172
|
+
# PRF with HMAC on SHA-256
|
173
|
+
PRF_HMAC_SHA2_256 = 5
|
174
|
+
# PRF with HMAC on SHA-384
|
175
|
+
PRF_HMAC_SHA2_384 = 6
|
176
|
+
# PRF with HMAC on SHA-512
|
177
|
+
PRF_HMAC_SHA2_512 = 7
|
178
|
+
# PRF with AES-128 withg CMAC mode
|
179
|
+
PRF_AES128_CMAC = 8
|
180
|
+
|
181
|
+
# No integrity
|
182
|
+
INTG_NONE = 0
|
183
|
+
# Integrity with HMAC on MD5, 96-bit ICV
|
184
|
+
INTG_HMAC_MD5_96 = 1
|
185
|
+
# Integrity with HMAC on SHA-1, 96-bit ICV
|
186
|
+
INTG_HMAC_SHA1_96 = 2
|
187
|
+
# Integrity with AES with XCBC mode, 96-bit ICV
|
188
|
+
INTG_AES_XCBC_96 = 5
|
189
|
+
# Integrity with HMAC on MD5, 128-bit ICV
|
190
|
+
INTG_HMAC_MD5_128 = 6
|
191
|
+
# Integrity with HMAC on SHA-1, 128-bit ICV
|
192
|
+
INTG_HMAC_SHA1_160 = 7
|
193
|
+
# Integrity with AES with CMAC mode, 96-bit ICV
|
194
|
+
INTG_AES_CMAC_96 = 8
|
195
|
+
# Integrity with AES-128 with GMAC mode, 128-bit ICV
|
196
|
+
INTG_AES128_GMAC = 9
|
197
|
+
# Integrity with AES-192 with GMAC mode, 128-bit ICV
|
198
|
+
INTG_AES192_GMAC = 10
|
199
|
+
# Integrity with AES-256 with GMAC mode, 128-bit ICV
|
200
|
+
INTG_AES256_GMAC = 11
|
201
|
+
# Integrity with HMAC on SHA-256, 128-bit ICV
|
202
|
+
INTG_HMAC_SHA2_256_128 = 12
|
203
|
+
# Integrity with HMAC on SHA-384, 192-bit ICV
|
204
|
+
INTG_HMAC_SHA2_384_192 = 13
|
205
|
+
# Integrity with HMAC on SHA-512, 256-bit ICV
|
206
|
+
INTG_HMAC_SHA2_512_256 = 14
|
207
|
+
|
208
|
+
# No key-exchange
|
209
|
+
DH_NONE = 0
|
210
|
+
# Key exchange with Diffie-Hellman on modp-768 group
|
211
|
+
DH_MODP768 = 1
|
212
|
+
# Key exchange with Diffie-Hellman on modp-1024 group
|
213
|
+
DH_MODP1024 = 2
|
214
|
+
# Key exchange with Diffie-Hellman on modp-1536 group
|
215
|
+
DH_MODP1536 = 5
|
216
|
+
# Key exchange with Diffie-Hellman on modp-2048 group
|
217
|
+
DH_MODP2048 = 14
|
218
|
+
# Key exchange with Diffie-Hellman on modp-3072 group
|
219
|
+
DH_MODP3072 = 15
|
220
|
+
# Key exchange with Diffie-Hellman on modp-4096 group
|
221
|
+
DH_MODP4096 = 16
|
222
|
+
# Key exchange with Diffie-Hellman on modp-6144 group
|
223
|
+
DH_MODP6144 = 17
|
224
|
+
# Key exchange with Diffie-Hellman on modp-8192 group
|
225
|
+
DH_MODP8192 = 18
|
226
|
+
# Key exchange with Diffie-Hellman on NIST p256 Elliptic curve
|
227
|
+
DH_ECP256 = 19
|
228
|
+
# Key exchange with Diffie-Hellman on NIST p384 Elliptic curve
|
229
|
+
DH_ECP384 = 20
|
230
|
+
# Key exchange with Diffie-Hellman on NIST p521 Elliptic curve
|
231
|
+
DH_ECP521 = 21
|
232
|
+
# Key exchange with Diffie-Hellman on Brainpool P224 Elliptic curve
|
233
|
+
DH_BRAINPOOLP224 = 27
|
234
|
+
# Key exchange with Diffie-Hellman on Brainpool P256 Elliptic curve
|
235
|
+
DH_BRAINPOOLP256 = 28
|
236
|
+
# Key exchange with Diffie-Hellman on Brainpool P384 Elliptic curve
|
237
|
+
DH_BRAINPOOLP384 = 29
|
238
|
+
# Key exchange with Diffie-Hellman on Brainpool P512 Elliptic curve
|
239
|
+
DH_BRAINPOOLP512 = 30
|
240
|
+
# Key exchange with Diffie-Hellman on curve25519 Elliptic curve
|
241
|
+
DH_CURVE25519 = 31
|
242
|
+
# Key exchange with Diffie-Hellman on curve448 Elliptic curve
|
243
|
+
DH_CURVE448 = 32
|
244
|
+
|
245
|
+
# No Extended Sequence Number
|
246
|
+
ESN_NO_ESN = 0
|
247
|
+
# Use Extended Sequence Number
|
248
|
+
ESN_ESN = 1
|
249
|
+
|
250
|
+
# @!attribute last
|
251
|
+
# 8-bit last substructure. Specifies whether or not this is the
|
252
|
+
# last Transform Substructure in the Proposal. This field has a value of 0
|
253
|
+
# if this was the last Transform Substructure, and a value of 3 if
|
254
|
+
# there are more Transform Substructures.
|
255
|
+
# @return [Integer]
|
256
|
+
define_field :last, PacketGen::Types::Int8
|
257
|
+
# @!attribute rsv1
|
258
|
+
# 8-bit reserved field
|
259
|
+
# @return [Integer]
|
260
|
+
define_field :rsv1, PacketGen::Types::Int8
|
261
|
+
# @!attribute length
|
262
|
+
# 16-bit transform length
|
263
|
+
# @return [Integer]
|
264
|
+
define_field :length, PacketGen::Types::Int16
|
265
|
+
# @!attribute [r] type
|
266
|
+
# 8-bit transform type. The Transform Type is the cryptographic
|
267
|
+
# algorithm type (i.e. encryption, PRF, integrity, etc.)
|
268
|
+
# @return [Integer]
|
269
|
+
define_field :type, PacketGen::Types::Int8Enum, enum: TYPES
|
270
|
+
# @!attribute rsv2
|
271
|
+
# 8-bit reserved field
|
272
|
+
# @return [Integer]
|
273
|
+
define_field :rsv2, PacketGen::Types::Int8
|
274
|
+
# @!attribute [r] id
|
275
|
+
# 16-bit transform ID. The Transform ID is the specific instance of
|
276
|
+
# the proposed transform type.
|
277
|
+
# @return [Integer]
|
278
|
+
define_field :id, PacketGen::Types::Int16
|
279
|
+
# @!attribute attributes
|
280
|
+
# Set of attributes for this transform
|
281
|
+
# @return [Attributes]
|
282
|
+
define_field :attributes, Attributes, builder: ->(h, t) { t.new(length_from: -> { h.length - h.offset_of(:attributes) }) }
|
283
|
+
|
284
|
+
def initialize(options={})
|
285
|
+
super
|
286
|
+
self.type = options[:type] if options[:type]
|
287
|
+
self.id = options[:id] if options[:id]
|
288
|
+
self[:length].value = sz unless options[:length]
|
289
|
+
end
|
243
290
|
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
291
|
+
undef id=
|
292
|
+
|
293
|
+
# Set transform ID
|
294
|
+
# @param [Integer,String] value
|
295
|
+
# @return [Integer]
|
296
|
+
def id=(value)
|
297
|
+
id = case value
|
298
|
+
when Integer
|
299
|
+
value
|
300
|
+
else
|
301
|
+
c = self.class.constants.grep(/#{human_type}_#{value}/).first
|
302
|
+
c ? self.class.const_get(c) : nil
|
303
|
+
end
|
304
|
+
raise ArgumentError, "unknown ID #{value.inspect}" unless id
|
305
|
+
|
306
|
+
self[:id].value = id
|
307
|
+
end
|
249
308
|
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
h << ')'
|
256
|
-
end
|
309
|
+
# Compute length and set {#length} field
|
310
|
+
# @return [Integer] new length
|
311
|
+
def calc_length
|
312
|
+
PacketGen::Header::Base.calculate_and_set_length self
|
313
|
+
end
|
257
314
|
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
else
|
264
|
-
"type[#{self.type}]"
|
265
|
-
end
|
266
|
-
end
|
315
|
+
# Get a human readable string
|
316
|
+
# @return [String]
|
317
|
+
def to_human
|
318
|
+
h = +"#{human_type}(#{human_id}"
|
319
|
+
h << ",#{attributes.to_human}" unless attributes.empty?
|
267
320
|
|
268
|
-
|
269
|
-
|
270
|
-
def human_id
|
271
|
-
name = self.class.constants.grep(/#{human_type}_/)
|
272
|
-
.detect { |c| self.class.const_get(c) == id } || "ID=#{id}"
|
273
|
-
name.to_s.sub(/#{human_type}_/, '')
|
274
|
-
end
|
321
|
+
h << ')'
|
322
|
+
end
|
275
323
|
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
false
|
284
|
-
end
|
324
|
+
# Get human-readable type
|
325
|
+
# @return [String]
|
326
|
+
def human_type
|
327
|
+
if self[:type].enum.value? self.type
|
328
|
+
self[:type].to_human
|
329
|
+
else
|
330
|
+
"type[#{self.type}]"
|
285
331
|
end
|
286
332
|
end
|
287
333
|
|
288
|
-
#
|
289
|
-
# @
|
290
|
-
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
# @see PacketGen::Types::Array#push
|
295
|
-
def push(trans)
|
296
|
-
super
|
297
|
-
self[-2].last = 3 if size > 1
|
298
|
-
self[-1].last = 0
|
299
|
-
self
|
300
|
-
end
|
334
|
+
# Get human-readable ID
|
335
|
+
# @return [String]
|
336
|
+
def human_id
|
337
|
+
name = self.class.constants.grep(/#{human_type}_/)
|
338
|
+
.detect { |c| self.class.const_get(c) == id } || "ID=#{id}"
|
339
|
+
name.to_s.sub(/#{human_type}_/, '')
|
301
340
|
end
|
302
341
|
|
303
|
-
#
|
304
|
-
#
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
# ~ SPI (variable) ~
|
312
|
-
# +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
313
|
-
# | |
|
314
|
-
# ~ <Transforms> ~
|
315
|
-
# | |
|
316
|
-
# +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
317
|
-
#
|
318
|
-
# == Create a proposal
|
319
|
-
# # using protocol name
|
320
|
-
# proposal = PacketGen::Plugin::IKE::Proposal.new(num: 1, protocol: 'IKE')
|
321
|
-
# # using integer values
|
322
|
-
# proposal = PacketGen::Plugin::IKE::Proposal.new(num: 1, protocol: 1)
|
323
|
-
# == Add transforms to a proposal
|
324
|
-
# # using a Transform object
|
325
|
-
# trans = PacketGen::Plugin::IKE::Transform.new(type: 'ENCR', id: '3DES')
|
326
|
-
# proposal.transforms << trans
|
327
|
-
# # using a hash
|
328
|
-
# proposal.transforms << { type: 'ENCR', id: '3DES' }
|
329
|
-
# @author Sylvain Daubert
|
330
|
-
class SAProposal < PacketGen::Types::Fields
|
331
|
-
# @!attribute last
|
332
|
-
# 8-bit last substructure. Specifies whether or not this is the
|
333
|
-
# last Proposal Substructure in the SA. This field has a value of 0
|
334
|
-
# if this was the last Proposal Substructure, and a value of 2 if
|
335
|
-
# there are more Proposal Substructures.
|
336
|
-
# @return [Integer]
|
337
|
-
define_field :last, PacketGen::Types::Int8
|
338
|
-
# @!attribute reserved
|
339
|
-
# 8-bit reserved field
|
340
|
-
# @return [Integer]
|
341
|
-
define_field :reserved, PacketGen::Types::Int8
|
342
|
-
# @!attribute length
|
343
|
-
# 16-bit proposal length
|
344
|
-
# @return [Integer]
|
345
|
-
define_field :length, PacketGen::Types::Int16
|
346
|
-
# @!attribute num
|
347
|
-
# 8-bit proposal number. When a proposal is made, the first
|
348
|
-
# proposal in an SA payload MUST be 1, and subsequent proposals MUST
|
349
|
-
# be one more than the previous proposal (indicating an OR of the
|
350
|
-
# two proposals). When a proposal is accepted, the proposal number
|
351
|
-
# in the SA payload MUST match the number on the proposal sent that
|
352
|
-
# was accepted.
|
353
|
-
# @return [Integer]
|
354
|
-
define_field :num, PacketGen::Types::Int8, default: 1
|
355
|
-
# @!attribute [r] protocol
|
356
|
-
# 8-bit protocol ID. Specify IPsec protocol currently negociated.
|
357
|
-
# May 1 (IKE), 2 (AH) or 3 (ESP).
|
358
|
-
# @return [Integer]
|
359
|
-
define_field :protocol, PacketGen::Types::Int8Enum, enum: PROTOCOLS
|
360
|
-
# @!attribute spi_size
|
361
|
-
# 8-bit SPI size. Give size of SPI field. Set to 0 for an initial IKE SA
|
362
|
-
# negotiation, as SPI is obtained from outer Plugin.
|
363
|
-
# @return [Integer]
|
364
|
-
define_field :spi_size, PacketGen::Types::Int8, default: 0
|
365
|
-
# @!attribute num_trans
|
366
|
-
# 8-bit number of transformations
|
367
|
-
# @return [Integer]
|
368
|
-
define_field :num_trans, PacketGen::Types::Int8, default: 0
|
369
|
-
# @!attribute spi
|
370
|
-
# the sending entity's SPI. When the {#spi_size} field is zero,
|
371
|
-
# this field is not present in the proposal.
|
372
|
-
# @return [String]
|
373
|
-
define_field :spi, PacketGen::Types::String, builder: ->(h, t) { t.new(length_from: h[:spi_size]) }
|
374
|
-
# @!attribute transforms
|
375
|
-
# 8-bit set of tranforms for this proposal
|
376
|
-
# @return [Transforms]
|
377
|
-
define_field :transforms, Transforms, builder: ->(h, t) { t.new(counter: h[:num_trans]) }
|
378
|
-
|
379
|
-
def initialize(options={})
|
380
|
-
if options[:spi] && options[:spi_size].nil?
|
381
|
-
options[:spi_size] = options[:spi].size
|
382
|
-
end
|
383
|
-
super
|
384
|
-
self.length = sz unless options[:length]
|
385
|
-
self.protocol = options[:protocol] if options[:protocol]
|
342
|
+
# Say if this transform is the last one (from {#last} field)
|
343
|
+
# @return [Boolean,nil] returns a Boolean when {#last} has defined value (+0+ => +true+, +3+ => +false+), else +nil+ is returned.
|
344
|
+
def last?
|
345
|
+
case last
|
346
|
+
when 0
|
347
|
+
true
|
348
|
+
when 3
|
349
|
+
false
|
386
350
|
end
|
351
|
+
end
|
352
|
+
end
|
387
353
|
|
388
|
-
|
389
|
-
|
390
|
-
|
391
|
-
|
392
|
-
|
393
|
-
|
354
|
+
# Set of {Transform} in a {SAProposal}
|
355
|
+
# @author Sylvain Daubert
|
356
|
+
class Transforms < PacketGen::Types::Array
|
357
|
+
set_of Transform
|
358
|
+
|
359
|
+
# Same as {PacketGen::Types::Array#push} but update previous {Transform#last} attribute
|
360
|
+
# @see PacketGen::Types::Array#push
|
361
|
+
def push(trans)
|
362
|
+
super
|
363
|
+
self[-2].last = 3 if size > 1
|
364
|
+
self[-1].last = 0
|
365
|
+
self
|
366
|
+
end
|
367
|
+
end
|
394
368
|
|
395
|
-
|
396
|
-
|
397
|
-
|
398
|
-
|
399
|
-
|
400
|
-
|
401
|
-
|
402
|
-
|
403
|
-
|
404
|
-
|
405
|
-
|
406
|
-
|
369
|
+
# SA Proposal, as defined in RFC 7296 §3.3.1
|
370
|
+
# 1 2 3
|
371
|
+
# 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
|
372
|
+
# +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
373
|
+
# | Last Substruc | RESERVED | Proposal Length |
|
374
|
+
# +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
375
|
+
# | Proposal Num | Protocol ID | SPI Size |Num Transforms|
|
376
|
+
# +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
377
|
+
# ~ SPI (variable) ~
|
378
|
+
# +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
379
|
+
# | |
|
380
|
+
# ~ <Transforms> ~
|
381
|
+
# | |
|
382
|
+
# +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
383
|
+
#
|
384
|
+
# == Create a proposal
|
385
|
+
# # using protocol name
|
386
|
+
# proposal = PacketGen::Plugin::IKE::Proposal.new(num: 1, protocol: 'IKE')
|
387
|
+
# # using integer values
|
388
|
+
# proposal = PacketGen::Plugin::IKE::Proposal.new(num: 1, protocol: 1)
|
389
|
+
# == Add transforms to a proposal
|
390
|
+
# # using a Transform object
|
391
|
+
# trans = PacketGen::Plugin::IKE::Transform.new(type: 'ENCR', id: '3DES')
|
392
|
+
# proposal.transforms << trans
|
393
|
+
# # using a hash
|
394
|
+
# proposal.transforms << { type: 'ENCR', id: '3DES' }
|
395
|
+
# @author Sylvain Daubert
|
396
|
+
class SAProposal < PacketGen::Types::Fields
|
397
|
+
# @!attribute last
|
398
|
+
# 8-bit last substructure. Specifies whether or not this is the
|
399
|
+
# last Proposal Substructure in the SA. This field has a value of 0
|
400
|
+
# if this was the last Proposal Substructure, and a value of 2 if
|
401
|
+
# there are more Proposal Substructures.
|
402
|
+
# @return [Integer]
|
403
|
+
define_field :last, PacketGen::Types::Int8
|
404
|
+
# @!attribute reserved
|
405
|
+
# 8-bit reserved field
|
406
|
+
# @return [Integer]
|
407
|
+
define_field :reserved, PacketGen::Types::Int8
|
408
|
+
# @!attribute length
|
409
|
+
# 16-bit proposal length
|
410
|
+
# @return [Integer]
|
411
|
+
define_field :length, PacketGen::Types::Int16
|
412
|
+
# @!attribute num
|
413
|
+
# 8-bit proposal number. When a proposal is made, the first
|
414
|
+
# proposal in an SA payload MUST be 1, and subsequent proposals MUST
|
415
|
+
# be one more than the previous proposal (indicating an OR of the
|
416
|
+
# two proposals). When a proposal is accepted, the proposal number
|
417
|
+
# in the SA payload MUST match the number on the proposal sent that
|
418
|
+
# was accepted.
|
419
|
+
# @return [Integer]
|
420
|
+
define_field :num, PacketGen::Types::Int8, default: 1
|
421
|
+
# @!attribute [r] protocol
|
422
|
+
# 8-bit protocol ID. Specify IPsec protocol currently negociated.
|
423
|
+
# May 1 (IKE), 2 (AH) or 3 (ESP).
|
424
|
+
# @return [Integer]
|
425
|
+
define_field :protocol, PacketGen::Types::Int8Enum, enum: PROTOCOLS
|
426
|
+
# @!attribute spi_size
|
427
|
+
# 8-bit SPI size. Give size of SPI field. Set to 0 for an initial IKE SA
|
428
|
+
# negotiation, as SPI is obtained from outer Plugin.
|
429
|
+
# @return [Integer]
|
430
|
+
define_field :spi_size, PacketGen::Types::Int8, default: 0
|
431
|
+
# @!attribute num_trans
|
432
|
+
# 8-bit number of transformations
|
433
|
+
# @return [Integer]
|
434
|
+
define_field :num_trans, PacketGen::Types::Int8, default: 0
|
435
|
+
# @!attribute spi
|
436
|
+
# the sending entity's SPI. When the {#spi_size} field is zero,
|
437
|
+
# this field is not present in the proposal.
|
438
|
+
# @return [String]
|
439
|
+
define_field :spi, PacketGen::Types::String, builder: ->(h, t) { t.new(length_from: h[:spi_size]) }
|
440
|
+
# @!attribute transforms
|
441
|
+
# 8-bit set of tranforms for this proposal
|
442
|
+
# @return [Transforms]
|
443
|
+
define_field :transforms, Transforms, builder: ->(h, t) { t.new(counter: h[:num_trans]) }
|
444
|
+
|
445
|
+
def initialize(options={})
|
446
|
+
options[:spi_size] = options[:spi].size if options[:spi] && options[:spi_size].nil?
|
447
|
+
super
|
448
|
+
self.length = sz unless options[:length]
|
449
|
+
self.protocol = options[:protocol] if options[:protocol]
|
450
|
+
end
|
407
451
|
|
408
|
-
|
409
|
-
|
410
|
-
|
411
|
-
|
412
|
-
|
452
|
+
# Compute length and set {#length} field
|
453
|
+
# @return [Integer] new length
|
454
|
+
def calc_length
|
455
|
+
transforms.each(&:calc_length)
|
456
|
+
PacketGen::Header::Base.calculate_and_set_length self
|
457
|
+
end
|
413
458
|
|
414
|
-
|
415
|
-
|
416
|
-
|
417
|
-
|
418
|
-
|
419
|
-
|
420
|
-
|
421
|
-
|
422
|
-
|
423
|
-
end
|
459
|
+
# Get a human readable string
|
460
|
+
# @return [String]
|
461
|
+
def to_human
|
462
|
+
str = +"##{num} #{human_protocol}"
|
463
|
+
case spi_size
|
464
|
+
when 4
|
465
|
+
str << '(spi:0x%08x)' % PacketGen::Types::Int32.new.read(spi).to_i
|
466
|
+
when 8
|
467
|
+
str << '(spi:0x%016x)' % PacketGen::Types::Int64.new.read(spi).to_i
|
424
468
|
end
|
469
|
+
str << ":#{transforms.to_human}"
|
425
470
|
end
|
426
471
|
|
427
|
-
#
|
428
|
-
# @
|
429
|
-
|
430
|
-
|
431
|
-
|
432
|
-
# Separator used between proposals in {#to_human}
|
433
|
-
HUMAN_SEPARATOR = '; '
|
434
|
-
|
435
|
-
# Same as {PacketGen::Types::Array#push} but update previous {SAProposal#last} attribute
|
436
|
-
# @see PacketGen::Types::Array#push
|
437
|
-
def push(prop)
|
438
|
-
super
|
439
|
-
self[-2].last = 2 if size > 1
|
440
|
-
self[-1].last = 0
|
441
|
-
self
|
442
|
-
end
|
472
|
+
# Get protocol name
|
473
|
+
# @return [String]
|
474
|
+
def human_protocol
|
475
|
+
self[:protocol].to_human
|
443
476
|
end
|
444
477
|
|
445
|
-
#
|
446
|
-
#
|
447
|
-
#
|
448
|
-
|
449
|
-
|
450
|
-
|
451
|
-
|
452
|
-
|
453
|
-
|
454
|
-
# | |
|
455
|
-
# ~ <Proposals> ~
|
456
|
-
# | |
|
457
|
-
# +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
458
|
-
#
|
459
|
-
# == Create a SA payload
|
460
|
-
# # Create a IKE packet with a SA payload
|
461
|
-
# pkt = PacketGen.gen('IP').add('UDP').add('IKE').add('IKE::SA')
|
462
|
-
# # add a proposal. Protocol name is taken from SAProposal::PROTO_* constants
|
463
|
-
# pkt.ike_sa.proposals << { num: 1, protocol: 'ESP' }
|
464
|
-
# # add a transform to this proposal.
|
465
|
-
# # type name is taken from Transform::TYPE_* constants.
|
466
|
-
# # ID is taken from Transform::<TYPE>_* constants.
|
467
|
-
# pkt.ike_sa.proposals.first.transforms << { type: 'ENCR', id: 'AES_CTR' }
|
468
|
-
# # and finally, add an attribute to this transform (here, KEY_SIZE = 128 bits)
|
469
|
-
# pkt.ike_sa.proposals[0].transforms[0].attributes << { type: 0x800e, value: 128 }
|
470
|
-
# pkt.calc_length
|
471
|
-
# @author Sylvain Daubert
|
472
|
-
class SA < Payload
|
473
|
-
# Payload type number
|
474
|
-
PAYLOAD_TYPE = 33
|
475
|
-
|
476
|
-
remove_field :content
|
477
|
-
|
478
|
-
# @!attribute proposals
|
479
|
-
# Set of SA proposals
|
480
|
-
# @return [SAProposals]
|
481
|
-
define_field_before :body, :proposals, SAProposals, builder: ->(h, t) { t.new(length_from: -> { h.length - h.offset_of(:proposals) }) }
|
482
|
-
|
483
|
-
# Compute length and set {#length} field
|
484
|
-
# @return [Integer] new length
|
485
|
-
def calc_length
|
486
|
-
proposals.each(&:calc_length)
|
487
|
-
super
|
478
|
+
# Say if this proposal is the last one (from {#last} field)
|
479
|
+
# @return [Boolean,nil] returns a Boolean when {#last} has defined value
|
480
|
+
# (+0+ => +true+, +2+ => +false+), else +nil+ is returned.
|
481
|
+
def last?
|
482
|
+
case last
|
483
|
+
when 0
|
484
|
+
true
|
485
|
+
when 2
|
486
|
+
false
|
488
487
|
end
|
489
488
|
end
|
490
489
|
end
|
491
490
|
|
492
|
-
|
491
|
+
# Set of {SAProposal}
|
492
|
+
# @author Sylvain Daubert
|
493
|
+
class SAProposals < PacketGen::Types::Array
|
494
|
+
set_of SAProposal
|
495
|
+
|
496
|
+
# Separator used between proposals in {#to_human}
|
497
|
+
HUMAN_SEPARATOR = '; '
|
498
|
+
|
499
|
+
# Same as {PacketGen::Types::Array#push} but update previous {SAProposal#last} attribute
|
500
|
+
# @see PacketGen::Types::Array#push
|
501
|
+
def push(prop)
|
502
|
+
super
|
503
|
+
self[-2].last = 2 if size > 1
|
504
|
+
self[-1].last = 0
|
505
|
+
self
|
506
|
+
end
|
507
|
+
end
|
508
|
+
|
509
|
+
# This class handles Security Assocation payloads, as defined in RFC 7296 §3.3.
|
510
|
+
#
|
511
|
+
# A SA payload contains a generic payload Plugin (see {Payload}) and a set of
|
512
|
+
# {SAProposal} ({#proposals} field, which is a {SAProposals} object):
|
513
|
+
# 1 2 3
|
514
|
+
# 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
|
515
|
+
# +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
516
|
+
# | Next Payload |C| RESERVED | Payload Length |
|
517
|
+
# +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
518
|
+
# | |
|
519
|
+
# ~ <Proposals> ~
|
520
|
+
# | |
|
521
|
+
# +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
522
|
+
#
|
523
|
+
# == Create a SA payload
|
524
|
+
# # Create a IKE packet with a SA payload
|
525
|
+
# pkt = PacketGen.gen('IP').add('UDP').add('IKE').add('IKE::SA')
|
526
|
+
# # add a proposal. Protocol name is taken from SAProposal::PROTO_* constants
|
527
|
+
# pkt.ike_sa.proposals << { num: 1, protocol: 'ESP' }
|
528
|
+
# # add a transform to this proposal.
|
529
|
+
# # type name is taken from Transform::TYPE_* constants.
|
530
|
+
# # ID is taken from Transform::<TYPE>_* constants.
|
531
|
+
# pkt.ike_sa.proposals.first.transforms << { type: 'ENCR', id: 'AES_CTR' }
|
532
|
+
# # and finally, add an attribute to this transform (here, KEY_SIZE = 128 bits)
|
533
|
+
# pkt.ike_sa.proposals[0].transforms[0].attributes << { type: 0x800e, value: 128 }
|
534
|
+
# pkt.calc_length
|
535
|
+
# @author Sylvain Daubert
|
536
|
+
class SA < Payload
|
537
|
+
# Payload type number
|
538
|
+
PAYLOAD_TYPE = 33
|
539
|
+
|
540
|
+
remove_field :content
|
541
|
+
|
542
|
+
# @!attribute proposals
|
543
|
+
# Set of SA proposals
|
544
|
+
# @return [SAProposals]
|
545
|
+
define_field_before :body, :proposals, SAProposals, builder: ->(h, t) { t.new(length_from: -> { h.length - h.offset_of(:proposals) }) }
|
546
|
+
|
547
|
+
# Compute length and set {#length} field
|
548
|
+
# @return [Integer] new length
|
549
|
+
def calc_length
|
550
|
+
proposals.each(&:calc_length)
|
551
|
+
super
|
552
|
+
end
|
553
|
+
end
|
493
554
|
end
|
555
|
+
|
556
|
+
PacketGen::Header.add_class IKE::SA
|
494
557
|
end
|