Module: Smartcard::Gp::CapLoader
- Defined in:
- lib/smartcard/gp/cap_loader.rb
Overview
Logic for loading JavaCard CAP files.
Constant Summary collapse
- TAG_NAMES =
Maps numeric tags to tag names.
{ 1 => :header, 2 => :directory, 3 => :applet, 4 => :import, 5 => :constant_pool, 6 => :class, 7 => :method, 8 => :static_field, 9 => :reference_location, 10 => :export, 11 => :descriptor, 12 => :debug }
- HEADER_FLAGS =
Masks for flags in the Header section.
[[:int_support, 1], [:has_exports, 2], [:has_applets, 4]]
Class Method Summary collapse
-
.cap_load_data(cap_file) ⇒ Object
Loads a CAP file and serializes its components for on-card loading.
-
.load_cap(cap_file) ⇒ Object
Loads a CAP file.
-
.parse_applets(components) ⇒ Object
Parses the Applet section in a CAP file, obtaining applet AIDs.
-
.parse_header(components) ⇒ Object
Parses the Header section in a CAP file, obtaining package AIDs.
-
.serialize_components(components) ⇒ Object
Serializes CAP components for on-card loading.
Class Method Details
.cap_load_data(cap_file) ⇒ Object
Loads a CAP file and serializes its components for on-card loading.
Returns a hash with the following keys:
:data:: array of bytes containing the executable load file for the CAP
:applets:: array of hashes, one for each applet in the CAP
(see parse_applets)
:header:: information about the CAP's header (see parse_header)
107 108 109 110 111 112 |
# File 'lib/smartcard/gp/cap_loader.rb', line 107 def self.cap_load_data(cap_file) components = load_cap cap_file { :data => serialize_components(components), :applets => parse_applets(components), :header => parse_header(components) } end |
.load_cap(cap_file) ⇒ Object
Loads a CAP file.
Returns a hash mapping component names to component data.
19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
# File 'lib/smartcard/gp/cap_loader.rb', line 19 def self.load_cap(cap_file) components = {} Zip::ZipFile.open(cap_file) do |file| file.each do |entry| data = entry.get_input_stream { |io| io.read } offset = 0 while offset < data.length tag = TAG_NAMES[data[offset, 1].unpack('C').first] length = data[offset + 1, 2].unpack('n').first value = data[offset + 3, length] components[tag] = value offset += 3 + length end end end components end |
.parse_applets(components) ⇒ Object
Parses the Applet section in a CAP file, obtaining applet AIDs.
Returns an array of hashes, one hash per applet. The hash has a key :aid
that contains the applet’s AID.
58 59 60 61 62 63 64 65 66 67 68 69 70 |
# File 'lib/smartcard/gp/cap_loader.rb', line 58 def self.parse_applets(components) applets = [] return applets unless section = components[:applet] offset = 1 section[0].ord.times do aid_length = section[offset].ord install_method = section[offset + 1 + aid_length, 2].unpack('n').first applets << { :aid => section[offset + 1, aid_length].unpack('C*'), :install_method => install_method } offset += 3 + aid_length end applets end |
.parse_header(components) ⇒ Object
Parses the Header section in a CAP file, obtaining package AIDs.
Returns a hash with the following keys:
:magic:: the header magic value
:version:: the CAP specification version (has :minor and :major keys)
:flags:: Set of package flags (see HEADER_FLAGS)
:package:: package information, has the following keys:
:version:: package version (has :minor and :major keys)
:aid:: the package's AID
:name:: the package's name (may be absent)
82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 |
# File 'lib/smartcard/gp/cap_loader.rb', line 82 def self.parse_header(components) component = components[:header] header = { :magic => component[0, 4].unpack('N').first, :version => { :minor => component[4].ord, :major => component[5].ord } } header[:flags] = Set.new(HEADER_FLAGS.select { |flag, mask| (component[6].ord & mask) == mask }.map { |flag, mask| flag }) header[:package] = { :version => { :minor => component[7].ord, :major => component[8].ord }} aid_length = component[9].ord header[:package][:aid] = component[10, aid_length].unpack('C*') if component.length > 10 + aid_length name_length = component[10 + aid_length].ord header[:package][:name] = component[11 + aid_length, name_length] end header end |
.serialize_components(components) ⇒ Object
Serializes CAP components for on-card loading.
Returns an array of bytes.
40 41 42 43 44 45 46 47 48 49 50 51 52 |
# File 'lib/smartcard/gp/cap_loader.rb', line 40 def self.serialize_components(components) [:header, :directory, :import, :applet, :class, :method, :static_field, :export, :constant_pool, :reference_location].map { |name| tag = TAG_NAMES.keys.find { |k| TAG_NAMES[k] == name } if components[name] length = [components[name].length].pack('n').unpack('C*') data = components[name].unpack('C*') [tag, length, data] else [] end }.flatten end |