Module Smartcard::Gp::CapLoader
In: lib/smartcard/gp/cap_loader.rb

Logic for loading JavaCard CAP files.

Methods

Constants

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   Maps numeric tags to tag names.
HEADER_FLAGS = [[:int_support, 1], [:has_exports, 2], [:has_applets, 4]]   Masks for flags in the Header section.

Public Class methods

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)

[Source]

     # File lib/smartcard/gp/cap_loader.rb, line 107
107:   def self.cap_load_data(cap_file)
108:     components = load_cap cap_file
109:     { :data => serialize_components(components),
110:       :applets => parse_applets(components),
111:       :header => parse_header(components) } 
112:   end

Loads a CAP file.

Returns a hash mapping component names to component data.

[Source]

    # File lib/smartcard/gp/cap_loader.rb, line 19
19:   def self.load_cap(cap_file)
20:     components = {}    
21:     Zip::ZipFile.open(cap_file) do |file|
22:       file.each do |entry|
23:         data = entry.get_input_stream { |io| io.read }
24:         offset = 0
25:         while offset < data.length          
26:           tag = TAG_NAMES[data[offset, 1].unpack('C').first]
27:           length = data[offset + 1, 2].unpack('n').first
28:           value = data[offset + 3, length]
29:           components[tag] = value
30:           offset += 3 + length
31:         end
32:       end
33:     end    
34:     components
35:   end

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.

[Source]

    # File lib/smartcard/gp/cap_loader.rb, line 58
58:   def self.parse_applets(components)    
59:     applets = []
60:     return applets unless section = components[:applet]
61:     offset = 1
62:     section[0].ord.times do
63:       aid_length = section[offset].ord
64:       install_method = section[offset + 1 + aid_length, 2].unpack('n').first
65:       applets << { :aid => section[offset + 1, aid_length].unpack('C*'),
66:                    :install_method => install_method }
67:       offset += 3 + aid_length
68:     end
69:     applets
70:   end

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)

[Source]

    # File lib/smartcard/gp/cap_loader.rb, line 82
82:   def self.parse_header(components)
83:     component = components[:header]
84:     header = { :magic => component[0, 4].unpack('N').first,
85:         :version => { :minor => component[4].ord,
86:                       :major => component[5].ord } }    
87:     header[:flags] = Set.new(HEADER_FLAGS.select { |flag, mask|
88:         (component[6].ord & mask) == mask }.map { |flag, mask| flag })
89:     header[:package] = { :version => { :minor => component[7].ord,
90:                                        :major => component[8].ord }}
91:     aid_length = component[9].ord
92:     header[:package][:aid] = component[10, aid_length].unpack('C*')
93:     if component.length > 10 + aid_length
94:       name_length = component[10 + aid_length].ord
95:       header[:package][:name] = component[11 + aid_length, name_length]
96:     end
97:     header
98:   end

Serializes CAP components for on-card loading.

Returns an array of bytes.

[Source]

    # File lib/smartcard/gp/cap_loader.rb, line 40
40:   def self.serialize_components(components)
41:     [:header, :directory, :import, :applet, :class, :method, :static_field,
42:      :export, :constant_pool, :reference_location].map { |name|
43:       tag = TAG_NAMES.keys.find { |k| TAG_NAMES[k] == name }
44:       if components[name]
45:         length = [components[name].length].pack('n').unpack('C*')
46:         data = components[name].unpack('C*')
47:         [tag, length, data]
48:       else
49:         []
50:       end
51:     }.flatten
52:   end

[Validate]