Class: PacketGen::Plugin::ESP
- Inherits:
-
Header::Base
- Object
- Header::Base
- PacketGen::Plugin::ESP
- Includes:
- Crypto
- Defined in:
- lib/packetgen/plugin/esp.rb
Overview
A ESP header consists of:
-
a Security Parameters Index (##spi, BinStruct::Int32 type),
-
a Sequence Number (#sn,
Int32
type), -
a #body (variable length),
-
an optional TFC padding (#tfc, variable length),
-
an optional #padding (to align ESP on 32-bit boundary, variable length),
-
a #pad_length (BinStruct::Int8),
-
a Next header field (#next,
Int8
), -
and an optional Integrity Check Value (#icv, variable length).
Create an ESP header
# standalone
esp = PacketGen::Plugin::ESP.new
# in a packet
pkt = PacketGen.gen('IP').add('ESP')
# access to ESP header
pkt.esp # => PacketGen::Plugin::ESP
Examples
Create an enciphered UDP packet (ESP transport mode), using CBC mode
icmp = PacketGen.gen('IP', src: '192.168.1.1', dst: '192.168.2.1').
add('ESP', spi: 0xff456e01, sn: 12345678).
add('UDP', dport: 4567, sport: 45362, body 'abcdef')
cipher = OpenSSL::Cipher.new('aes-128-cbc')
cipher.encrypt
cipher.key = 16bytes_key
iv = 16bytes_iv
esp.esp.encrypt! cipher, iv
Create a ESP packet tunneling a UDP one, using GCM combined mode
# create inner UDP packet
icmp = PacketGen.gen('IP', src: '192.168.1.1', dst: '192.168.2.1').
add('UDP', dport: 4567, sport: 45362, body 'abcdef')
# create outer ESP packet
esp = PacketGen.gen('IP', src '198.76.54.32', dst: '1.2.3.4').add('ESP')
esp.esp.spi = 0x87654321
esp.esp.sn = 0x123
esp.esp.icv_length = 16
# encapsulate ICMP packet in ESP one
esp.encapsulate icmp
# encrypt ESP payload
cipher = OpenSSL::Cipher.new('aes-128-gcm')
cipher.encrypt
cipher.key = 16bytes_key
iv = 8bytes_iv
esp.esp.encrypt! cipher, iv, salt: 4bytes_gcm_salt
Decrypt a ESP packet using CBC mode and HMAC-SHA-256
cipher = OpenSSL::Cipher.new('aes-128-cbc')
cipher.decrypt
cipher.key = 16bytes_key
hmac = OpenSSL::HMAC.new(hmac_key, OpenSSL::Digest::SHA256.new)
pkt.esp.decrypt! cipher, intmode: hmac # => true if ICV check OK
Constant Summary collapse
- IP_PROTOCOL =
IP protocol number for ESP
50
- UDP_PORT =
Well-known UDP port for ESP
4500
Instance Attribute Summary collapse
- #body ⇒ BinStruct::String, PacketGen::Header::Base
-
#icv ⇒ BinStruct::String, PacketGen::Header::Base
Integrity Check Value.
-
#icv_length ⇒ Integer
ICV (Integrity Check Value) length.
-
#next ⇒ Integer
8-bit next protocol value.
-
#pad_length ⇒ Integer
8-bit padding length.
-
#padding ⇒ BinStruct::String, PacketGen::Header::Base
ESP padding.
-
#sn ⇒ Integer
32-bit Sequence Number.
-
#spi ⇒ Integer
32-bit Security Parameter Index.
-
#tfc ⇒ BinStruct::String, PacketGen::Header::Base
Traffic Flow Confidentiality padding.
Instance Method Summary collapse
-
#decrypt!(cipher, options = {}) ⇒ Boolean
Decrypt in-place ESP payload and trailer.
-
#encrypt!(cipher, iv, options = {}) ⇒ self
Encrypt in-place ESP payload and trailer.
-
#initialize(options = {}) ⇒ ESP
constructor
A new instance of ESP.
-
#read(str) ⇒ self
Read a ESP packet from string.
Methods included from Crypto
#authenticate!, #authenticated?, #compute_iv_for_decrypting, #compute_iv_for_encrypting, #confidentiality_mode, #decipher, #encipher, #set_crypto
Constructor Details
#initialize(options = {}) ⇒ ESP
Returns a new instance of ESP.
128 129 130 131 |
# File 'lib/packetgen/plugin/esp.rb', line 128 def initialize(={}) @icv_length = [:icv_length] || 0 super end |
Instance Attribute Details
#body ⇒ BinStruct::String, PacketGen::Header::Base
90 |
# File 'lib/packetgen/plugin/esp.rb', line 90 define_attr :body, BinStruct::String |
#icv ⇒ BinStruct::String, PacketGen::Header::Base
Integrity Check Value
110 |
# File 'lib/packetgen/plugin/esp.rb', line 110 define_attr :icv, BinStruct::String |
#icv_length ⇒ Integer
ICV (Integrity Check Value) length
114 115 116 |
# File 'lib/packetgen/plugin/esp.rb', line 114 def icv_length @icv_length end |
#next ⇒ Integer
8-bit next protocol value
106 |
# File 'lib/packetgen/plugin/esp.rb', line 106 define_attr :next, BinStruct::Int8 |
#pad_length ⇒ Integer
8-bit padding length
102 |
# File 'lib/packetgen/plugin/esp.rb', line 102 define_attr :pad_length, BinStruct::Int8 |
#padding ⇒ BinStruct::String, PacketGen::Header::Base
ESP padding
98 |
# File 'lib/packetgen/plugin/esp.rb', line 98 define_attr :padding, BinStruct::String |
#sn ⇒ Integer
32-bit Sequence Number
87 |
# File 'lib/packetgen/plugin/esp.rb', line 87 define_attr :sn, BinStruct::Int32 |
#spi ⇒ Integer
32-bit Security Parameter Index
83 |
# File 'lib/packetgen/plugin/esp.rb', line 83 define_attr :spi, BinStruct::Int32 |
#tfc ⇒ BinStruct::String, PacketGen::Header::Base
Traffic Flow Confidentiality padding
94 |
# File 'lib/packetgen/plugin/esp.rb', line 94 define_attr :tfc, BinStruct::String |
Instance Method Details
#decrypt!(cipher, options = {}) ⇒ Boolean
Decrypt in-place ESP payload and trailer.
213 214 215 216 217 218 219 220 221 222 223 224 |
# File 'lib/packetgen/plugin/esp.rb', line 213 def decrypt!(cipher, ={}) opt = { salt: '', parse: true }.merge() set_crypto cipher, opt[:intmode] iv = compute_iv_for_decrypting(opt[:salt], self[:body]) if authenticated? && (@icv_length.zero? || opt[:icv_length]) check_icv_length(opt) decrypt_format_packet end authenticate_esp_header_if_needed , iv, icv private_decrypt opt end |
#encrypt!(cipher, iv, options = {}) ⇒ self
Encrypt in-place ESP payload and trailer.
This method removes all data from tfc
and padding
fields, as their enciphered values are concatenated into body
.
It also removes headers under ESP from packet, as they are enciphered in ESP body, and then are no more accessible.
181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 |
# File 'lib/packetgen/plugin/esp.rb', line 181 def encrypt!(cipher, iv, ={}) # rubocop:disable Naming/MethodParameterName opt = { salt: '', tfc_size: 1444 }.merge() set_crypto cipher, opt[:intmode] compute_iv_for_encrypting iv, opt[:salt] authenticate_esp_header_if_needed , iv encrypt_set_pad_length encrypt_set_padding(opt) encrypt_body(opt, iv) set_esp_icv_if_needed remove_enciphered_packets self end |
#read(str) ⇒ self
Read a ESP packet from string.
#padding and #tfc are not set as they are enciphered (impossible to guess their respective size). #pad_length and #next are also enciphered.
140 141 142 143 144 145 146 147 148 149 150 151 152 |
# File 'lib/packetgen/plugin/esp.rb', line 140 def read(str) return self if str.nil? str = str.b self[:spi].read(str[0, 4]) self[:sn].read(str[4, 4]) self[:tfc].read('') self[:padding].read('') read_icv_dependent_fields(str[8..]) read_icv(str) self end |