tem_ruby 0.14.1 → 0.15.1

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.
data/CHANGELOG CHANGED
@@ -1,3 +1,7 @@
1
+ v0.15.1. SECpack migrations.
2
+
3
+ v0.15.0. Opcode for computing the size of encrypted data (fw 1.15).
4
+
1
5
  v0.14.1. Benchmarks for symmetric encryption.
2
6
 
3
7
  v0.14.0. Finalized symmetric encryption (fw 1.14).
data/Manifest CHANGED
@@ -14,6 +14,8 @@ dev_ca/ca_cert.pem
14
14
  dev_ca/ca_key.pem
15
15
  dev_ca/config.yml
16
16
  lib/tem/_cert.rb
17
+ lib/tem/admin/emit.rb
18
+ lib/tem/admin/migrate.rb
17
19
  lib/tem/apdus/buffers.rb
18
20
  lib/tem/apdus/keys.rb
19
21
  lib/tem/apdus/lifecycle.rb
@@ -62,9 +64,11 @@ test/tem_unit/test_tem_crypto_random.rb
62
64
  test/tem_unit/test_tem_emit.rb
63
65
  test/tem_unit/test_tem_memory.rb
64
66
  test/tem_unit/test_tem_memory_compare.rb
67
+ test/tem_unit/test_tem_migrate.rb
65
68
  test/tem_unit/test_tem_output.rb
66
69
  test/tem_unit/test_tem_yaml_secpack.rb
67
70
  test/test_auto_conf.rb
68
71
  test/test_crypto_engine.rb
69
72
  test/test_driver.rb
70
73
  test/test_exceptions.rb
74
+ test/test_tag.rb
data/dev_ca/config.yml CHANGED
@@ -1,5 +1,5 @@
1
1
  ---
2
- # the development CA is valid for 10 years
2
+ # The development CA is valid for 10 years.
3
3
  :ca_validity_days: 3652
4
4
  :issuer:
5
5
  CN: Trusted Execution Module Development CA
@@ -8,7 +8,7 @@
8
8
  C: US
9
9
  O: Massachusetts Insitute of Technology
10
10
  OU: Computer Science and Artificial Intelligence Laboratory
11
- # a TEM is valid for two days
11
+ # A TEM is valid for two years.
12
12
  :ecert_validity_days: 730
13
13
  :subject:
14
14
  CN: Trusted Execution Module DevChip
@@ -0,0 +1,115 @@
1
+ # Logic for the TEM emission process.
2
+ #
3
+ # Author:: Victor Costan
4
+ # Copyright:: Copyright (C) 2009 Massachusetts Institute of Technology
5
+ # License:: MIT
6
+
7
+ # :nodoc: namespace
8
+ module Tem::Admin
9
+
10
+
11
+ # Logic for the TEM emission process.
12
+ module Emit
13
+ # The SEClosure that performs key generation for the TEM.
14
+ def self.emit_keygen_seclosure
15
+ Tem::Assembler.assemble { |s|
16
+ # Generate Endorsement Key pair, should end up in slots (0, 1).
17
+ s.genkp :type => 0
18
+ s.ldbc 1
19
+ s.sub
20
+ s.jne :to => :not_ok
21
+ s.ldbc 0
22
+ s.sub
23
+ s.jne :to => :not_ok
24
+
25
+ # Generate and output random authorization for PrivEK.
26
+ s.ldbc 20
27
+ s.dupn :n => 1
28
+ s.outnew
29
+ s.ldwc :privek_auth
30
+ s.dupn :n => 2
31
+ s.rnd
32
+ s.outvb
33
+ # Set authorizations for PrivEK and PubkEK.
34
+ s.ldbc 0
35
+ s.authk :auth => :privek_auth
36
+ s.ldbc 1 # PubEK always has its initial authorization be all zeroes.
37
+ s.authk :auth => :pubek_auth
38
+ s.halt
39
+
40
+ # Emitting didn't go well, return nothing and leave.
41
+ s.label :not_ok
42
+ s.ldbc 0
43
+ s.outnew
44
+ s.halt
45
+
46
+ s.label :privek_auth
47
+ s.zeros :tem_ubyte, 20
48
+ s.label :pubek_auth
49
+ s.zeros :tem_ubyte, 20
50
+ s.stack 4
51
+ }
52
+ end
53
+
54
+ # Performs the key generation step of the TEM emitting process.
55
+ #
56
+ # Args:
57
+ # tem:: session to the TEM that will be emitted
58
+ #
59
+ # Returns nil if key generation fails. In case of success, a hash with the
60
+ # following keys is returned.
61
+ # :pubek:: the public Endorsement Key (PubEK) -- not stored on the TEM
62
+ # :privek_auth:: the authentication key for the private Endorsement Key
63
+ # (PrivEK), which will always be stored on the chip
64
+ def self.emit_keygen(tem)
65
+ sec = emit_keygen_seclosure
66
+ r = tem.execute sec
67
+ return nil if r.empty?
68
+
69
+ privek_auth = r[0...20]
70
+ pubek_auth = (0...20).map {|i| 0}
71
+ pubek = tem.tk_read_key 1, pubek_auth
72
+ tem.tk_delete_key 1, pubek_auth
73
+ { :privek_auth => privek_auth, :pubek => pubek }
74
+ end
75
+
76
+ # Drives a TEM though the emit process.
77
+ #
78
+ # Args:
79
+ # tem:: session to the TEM that will be emitted.
80
+ #
81
+ # Returns nil if the emit process fails (most likely, the TEM was already
82
+ # emitted). If the process completes, a hash with the following keys is
83
+ # returned.
84
+ # :privek_auth:: the authorization token for the private Endorsement Key
85
+ # (PrivEK) -- this value should be handled with care
86
+ def self.emit(tem)
87
+ tag = {}
88
+
89
+ return nil unless key_data = emit_keygen(tem)
90
+
91
+ # Build the Endorsement Certificate.
92
+ ecert = Tem::CA.new_ecert key_data[:pubek].ssl_key
93
+ tag.merge! Tem::ECert.ecert_tag ecert
94
+
95
+ # Build administrative SECpacks.
96
+ tag.merge! Tem::Admin::Migrate.tag_data key_data[:pubek],
97
+ key_data[:privek_auth]
98
+
99
+ tem.set_tag tag
100
+ key_data
101
+ end
102
+
103
+ # Emits the TEM.
104
+ #
105
+ # Returns nil if the emit process fails (most likely, the TEM was already
106
+ # emitted). If the process completes, it returns the authorization token for
107
+ # the private Endorsement Key (PrivEK). This value is very sensitive and its
108
+ # disclosure will compromise the TEM.
109
+ def emit
110
+ emit_data = Tem::Admin::Emit.emit self
111
+ emit_data and emit_data[:privek_auth]
112
+ end
113
+ end # module Tem::Admin::Emit
114
+
115
+ end # namespace Tem::Admin
@@ -0,0 +1,219 @@
1
+ # Logic for SECpack migration.
2
+ #
3
+ # Author:: Victor Costan
4
+ # Copyright:: Copyright (C) 2009 Massachusetts Institute of Technology
5
+ # License:: MIT
6
+
7
+ require 'openssl'
8
+
9
+ # :nodoc: namespace
10
+ module Tem::Admin
11
+
12
+
13
+ # Logic for migrating SECpacks.
14
+ module Migrate
15
+ # SEClosure that verifies the destination TEM's ECert.
16
+ #
17
+ # Args:
18
+ # key_ps_addr:: the PStore address used to store the TEM key's ID
19
+ # authz:: the authentication secret for the TEM's PrivEK
20
+ def self.ecert_verify_seclosure(key_ps_addr, authz)
21
+ Tem::Assembler.assemble { |s|
22
+ # TODO: some actual verification, jump to :failure if it doesn't work
23
+
24
+ s.ldwc :const => :pubek
25
+ s.rdk
26
+ s.authk :auth => :authz
27
+ s.stw :to => :key_id
28
+ s.pswrfxb :addr => :pstore_addr, :from => :key_id
29
+ s.label :success
30
+ s.ldbc :const => 1
31
+ s.dupn :n => 1
32
+ s.outnew
33
+ s.outb
34
+ s.halt
35
+
36
+ s.label :failure
37
+ s.ldbc :const => 1
38
+ s.outnew
39
+ s.ldbc :const => 0
40
+ s.outb
41
+ s.halt
42
+
43
+ s.label :key_id
44
+ s.zeros :tem_ps_value # Will hold the ID of the loaded PubEK.
45
+
46
+ s.label :secret
47
+ s.label :authz # The authentication key for the PrivEK.
48
+ s.data :tem_ubyte, authz
49
+ s.label :pstore_addr
50
+ s.data :tem_ps_addr, key_ps_addr
51
+ s.label :plain
52
+ # ARG: the target TEM's public endorsement key.
53
+ s.label :pubek
54
+ s.zeros :tem_ubyte, 300
55
+ # ARG: the target TEM's endorsement certificate.
56
+ s.label :ecert
57
+ s.stack 10
58
+ }
59
+ end
60
+
61
+ # Blank version of the SEClosure that verifies the destination TEM's ECert.
62
+ #
63
+ # The returned SEClosure is not suitable for execution. Its encrypted bytes
64
+ # should be replaced with the bytes from a SECpack generated with live data.
65
+ def self.blank_ecert_verify_seclosure
66
+ ecert_verify_seclosure [0] * Tem::Abi.tem_ps_addr_length,
67
+ [0] * Tem::Abi.tem_hash_length
68
+ end
69
+
70
+ # SEClosure that migrates a SECpack.
71
+ #
72
+ # Args:
73
+ # key_ps_addr:: the PStore address used to store the TEM key's ID
74
+ # authz:: the authentication secret for the TEM's PrivEK
75
+ def self.migrate_seclosure(key_ps_addr, authz)
76
+ Tem::Assembler.assemble { |s|
77
+ s.ldbc :const => 0 # Authorize PrivEK.
78
+ s.authk :auth => :authz
79
+ s.dupn :n => 1 # Compute the size of the encrypted blob.
80
+ s.ldw :from => :secpack_secret_size
81
+ s.ldkel
82
+
83
+ # Decrypt secpack.
84
+ s.ldwc :const => :secpack_encrypted
85
+ s.ldwc :const => :secpack_encrypted
86
+ s.kdvb
87
+ s.ldw :from => :secpack_secret_size # Fail for wrong blob size.
88
+ s.sub
89
+ s.jnz :failure
90
+
91
+ # Authorize target PubEK.
92
+ s.psrdfxb :addr => :pstore_addr, :to => :key_id
93
+ s.ldw :from => :key_id
94
+ s.authk :auth => :authz
95
+
96
+ s.dupn :n => 1 # Prepare output buffer.
97
+ s.ldw :from => :secpack_secret_size
98
+ s.ldkel
99
+ s.outnew
100
+
101
+ s.ldw :from => :secpack_secret_size # Re-encrypt the blob.
102
+ s.ldwc :const => :secpack_encrypted
103
+ s.ldwc :const => -1
104
+ s.kevb
105
+
106
+ s.ldw :from => :key_id # Clean up.
107
+ s.relk
108
+ s.ldbc :const => -1
109
+ s.stw :to => :key_id
110
+ s.pswrfxb :addr => :pstore_addr, :from => :key_id
111
+ s.halt
112
+
113
+ s.label :failure # Communicate some failure.
114
+ s.ldbc :const => 0
115
+ s.outnew
116
+ s.halt
117
+
118
+ s.label :key_id
119
+ s.zeros :tem_ps_value # Will hold the ID of the loaded PubEK.
120
+
121
+ s.label :secret
122
+ s.label :authz # The authentication key for the PrivEK.
123
+ s.data :tem_ubyte, authz
124
+ s.label :pstore_addr
125
+ s.data :tem_ps_addr, key_ps_addr
126
+ s.label :plain
127
+ s.stack 20
128
+ # ARG: the 'encrypted size' field in the SECpack header.
129
+ s.label :secpack_secret_size
130
+ s.zeros :tem_short, 1
131
+ # ARG: the encrypted blob in the SECpack.
132
+ s.label :secpack_encrypted
133
+ s.zeros :tem_ubyte, 1
134
+ s.label :secpack_encrypted_end
135
+ }
136
+ end
137
+
138
+ # Blank version of the SEClosure that verifies the destination TEM's ECert.
139
+ #
140
+ # The returned SEClosure is not suitable for execution. Its encrypted bytes
141
+ # should be replaced with the bytes from a SECpack generated with live data.
142
+ def self.blank_migrate_seclosure
143
+ migrate_seclosure [0] * Tem::Abi.tem_ps_addr_length,
144
+ [0] * Tem::Abi.tem_hash_length
145
+ end
146
+
147
+ # The key storing the encrypted bytes of the ecert_verify SECpack in the
148
+ # TEM's tag.
149
+ def self.ecert_verify_bytes_tag_key
150
+ 0x11
151
+ end
152
+
153
+ # The key storing the encrypted bytes of the migrate SECpack in the TEM's tag.
154
+ def self.migrate_bytes_tag_key
155
+ 0x12
156
+ end
157
+
158
+ # Data to be included in a TEM's tag to support migration.
159
+ #
160
+ # Returns a hash of tag key-values to be included in the TEM's tag during
161
+ # emission.
162
+ def self.tag_data(pubek, privek_authz)
163
+ ps_addr = OpenSSL::Random.random_bytes(Tem::Abi.tem_ps_addr_length).
164
+ unpack('C*')
165
+ ev_sec = ecert_verify_seclosure ps_addr, privek_authz
166
+ ev_sec.bind pubek
167
+
168
+ m_sec = migrate_seclosure ps_addr, privek_authz
169
+ m_sec.bind pubek
170
+
171
+ {
172
+ ecert_verify_bytes_tag_key => ev_sec.encrypted_data,
173
+ migrate_bytes_tag_key => m_sec.encrypted_data
174
+ }
175
+ end
176
+
177
+ # Recovers the migration-related SECpacks from the TEM's tag data.
178
+ def self.seclosures_from_tag_data(tem)
179
+ tag_data = tem.tag
180
+
181
+ ecert_verify = blank_ecert_verify_seclosure
182
+ ecert_verify.fake_bind
183
+ ecert_verify.encrypted_data = tag_data[ecert_verify_bytes_tag_key]
184
+
185
+ migrate = blank_migrate_seclosure
186
+ migrate.fake_bind
187
+ migrate.encrypted_data = tag_data[migrate_bytes_tag_key]
188
+
189
+ { :ecert_verify => ecert_verify, :migrate => migrate }
190
+ end
191
+
192
+ # Migrates a SECpack to another TEM.
193
+ #
194
+ # Args:
195
+ # secpack:: the SECpack to be migrated
196
+ # ecert:: the Endorsement Certificate of the destination TEM
197
+ #
198
+ # Returns the migrated SECpack, or nil if the Endorsement Certificate was
199
+ # rejected.
200
+ def migrate(secpack, ecert)
201
+ migrated = secpack.copy
202
+ secpacks = Tem::Admin::Migrate.seclosures_from_tag_data self
203
+
204
+ verify = secpacks[:ecert_verify]
205
+ verify.set_bytes :pubek,
206
+ Tem::Key.new_from_ssl_key(ecert.public_key).to_tem_key
207
+ return nil if execute(verify) != [1]
208
+
209
+ migrate = secpacks[:migrate]
210
+ migrate.set_value :secpack_secret_size, :tem_short, secpack.secret_bytes +
211
+ Tem::Abi.tem_hash_length
212
+ migrate.set_bytes :secpack_encrypted, migrated.encrypted_data
213
+ return nil unless new_encrypted_data = execute(migrate)
214
+ migrated.encrypted_data = new_encrypted_data
215
+ migrated
216
+ end
217
+ end # module Tem::Admin::Migrate
218
+
219
+ end # namespace Tem::Admin
data/lib/tem/apdus/tag.rb CHANGED
@@ -9,7 +9,15 @@ module Tem::Apdus
9
9
 
10
10
 
11
11
  module Tag
12
- def set_tag(tag_data)
12
+ # Writes an array of bytes to the TEM's tag.
13
+ #
14
+ # The TEM's tag can only be written once, when the TEM is emitted.
15
+ #
16
+ # Args:
17
+ # tag_data:: the array of bytes to write to the TEM's tag
18
+ #
19
+ # The return value is unspecified.
20
+ def set_raw_tag_data(tag_data)
13
21
  buffer_id = post_buffer tag_data
14
22
  begin
15
23
  @transport.iso_apdu! :ins => 0x30, :p1 => buffer_id
@@ -18,12 +26,22 @@ module Tag
18
26
  end
19
27
  end
20
28
 
21
- def get_tag_length
29
+ # The number of bytes in the TEM's tag.
30
+ #
31
+ # This method issues an APDU when it's called (i.e. no caching is done).
32
+ def get_raw_tag_length
22
33
  response = @transport.iso_apdu! :ins => 0x31
23
34
  return read_tem_short(response, 0)
24
35
  end
25
36
 
26
- def get_tag_data(offset, length)
37
+ # Reads raw bytes in the TEM's tag.
38
+ #
39
+ # Args:
40
+ # offset:: the offset of the first byte to be read from the TEM's tag
41
+ # length:: the number of bytes to be read from the TEM's tag.
42
+ #
43
+ # Returns an array of bytes containing the requested TEM tag data.
44
+ def get_raw_tag_data(offset, length)
27
45
  buffer_id = alloc_buffer length
28
46
  begin
29
47
  @transport.iso_apdu! :ins => 0x32, :p1 => buffer_id,
@@ -36,9 +54,63 @@ module Tag
36
54
  tag_data
37
55
  end
38
56
 
39
- def get_tag
40
- tag_length = self.get_tag_length
41
- get_tag_data 0, tag_length
57
+ # Encodes structured tag data into raw TLV tag data.
58
+ #
59
+ # Args:
60
+ # data:: a hash whose keys are numbers (tag keys), and whose values are
61
+ # arrays of bytes (values associated with the tag keys)
62
+ #
63
+ # Returns an array of bytes with the raw data.
64
+ def self.encode_tag(data)
65
+ data.keys.sort.map { |key|
66
+ value = data[key]
67
+ [Tem::Abi.to_tem_ubyte(key), Tem::Abi.to_tem_short(value.length), value]
68
+ }.flatten
69
+ end
70
+
71
+ # Decodes raw TLV tag data into its structured form.
72
+ #
73
+ # Args:
74
+ # raw_data:: an array of bytes containing the raw data in the TEM tag
75
+ #
76
+ # Returns a hash whose keys are numbers (tag keys), and whose values are
77
+ # arrays of bytes (values associated with the tag keys).
78
+ def self.decode_tag(raw_data)
79
+ data = {}
80
+ index = 0
81
+ while index < raw_data.length
82
+ key = Tem::Abi.read_tem_ubyte raw_data, index
83
+ value_length = Tem::Abi.read_tem_short raw_data, index + 1
84
+ data[key] = raw_data[index + 3, value_length]
85
+ index += 3 + value_length
86
+ end
87
+ data
88
+ end
89
+
90
+ # Writes an structured data to the TEM's tag.
91
+ #
92
+ # The TEM's tag can only be written once, when the TEM is emitted.
93
+ #
94
+ # Args:
95
+ # tag_data:: the array of bytes to write to the TEM's tag
96
+ #
97
+ # The return value is unspecified.
98
+ def set_tag(data)
99
+ raw_data = Tem::Apdus::Tag.encode_tag data
100
+ set_raw_tag_data raw_data
101
+ icache[:tag] = Tem::Apdus::Tag.decode_tag raw_data
102
+ end
103
+
104
+ # The TEM's tag data.
105
+ #
106
+ # Returns a hash whose keys are numbers (tag keys), and whose values are
107
+ # arrays of bytes (values associated with the tag keys). The result of this
108
+ # method is cached.
109
+ def tag
110
+ return icache[:tag] if icache[:tag]
111
+
112
+ raw_tag_data = get_raw_tag_data 0, get_raw_tag_length
113
+ icache[:tag] = Tem::Apdus::Tag.decode_tag raw_tag_data
42
114
  end
43
115
  end
44
116
 
@@ -64,7 +64,7 @@ class Tem::Benchmarks
64
64
  benchmarks = {}
65
65
  t = Tem::Benchmarks.new
66
66
  t.setup
67
- t.methods.select { |m| m =~ /time_/ }.each do |m|
67
+ t.methods.select { |m| m =~ /time_/ }.sort.each do |m|
68
68
  print "Timing: #{m[5..-1]}...\n"
69
69
  t.send m.to_sym
70
70
  benchmarks[m] = t.timing
data/lib/tem/ca.rb CHANGED
@@ -4,7 +4,7 @@ require 'yaml'
4
4
  # Certificate Authority (CA) functionality for TEM manufacturers
5
5
  module Tem::CA
6
6
  # Creates an Endorsement Certificate for a TEM's Public Endorsement Key.
7
- def new_ecert(pubek)
7
+ def self.new_ecert(pubek)
8
8
  ca_cert = Tem::CA.ca_cert
9
9
  ca_key = Tem::CA.ca_key
10
10
  conf = Tem::CA.config
@@ -190,13 +190,16 @@ module Tem::Isa
190
190
  isa.instruction 0x46, :halt
191
191
  # 1 ST -> 0 ST
192
192
  isa.instruction 0x47, :psrm
193
-
193
+
194
+ # 2 ST -> 1 ST
195
+ isa.instruction 0x58, :ldkel
194
196
  # 1 ST -> 1 ST
195
- isa.instruction 0x5A, :rdk
197
+ isa.instruction 0x5A, :rdk
196
198
  # 1 ST -> 0 ST
197
199
  isa.instruction 0x5C, :relk
198
-
200
+ # 1 ST -> 1 ST
199
201
  isa.instruction 0x5D, :ldkl
202
+
200
203
  # 1 IM_B -> 2 ST
201
204
  isa.instruction 0x5E, :genkp, {:name => :type, :type => :tem_ubyte }
202
205
  # 1 ST, 1 IM -> 1 ST
data/lib/tem/ecert.rb CHANGED
@@ -1,14 +1,20 @@
1
1
  require 'openssl'
2
2
 
3
3
  module Tem::ECert
4
- # Writes an Endorsement Certificate to the TEM's tag.
5
- def set_ecert(ecert)
6
- set_tag ecert.to_der.unpack('C*')
4
+ # The key storing the Endorsement Certificate in the TEM's tag.
5
+ def self.ecert_tag_key
6
+ 0x01
7
+ end
8
+
9
+ # The tag contents for an endorsement certificate.
10
+ def self.ecert_tag(ecert)
11
+ { ecert_tag_key => ecert.to_der.unpack('C*') }
7
12
  end
8
13
 
9
14
  # Retrieves the TEM's Endorsement Certificate.
10
15
  def endorsement_cert
11
- OpenSSL::X509::Certificate.new get_tag.pack('C*')
16
+ raw_cert = tag[Tem::ECert.ecert_tag_key].pack('C*')
17
+ OpenSSL::X509::Certificate.new raw_cert
12
18
  end
13
19
 
14
20
  # Retrieves the certificate of the TEM's Manfacturer (CA).
@@ -19,59 +25,5 @@ module Tem::ECert
19
25
  # Retrieves the TEM's Public Endorsement Key.
20
26
  def pubek
21
27
  Tem::Key.new_from_ssl_key endorsement_cert.public_key
22
- end
23
-
24
- # Drives a TEM though the emitting process.
25
- def emit
26
- emit_sec = assemble do |s|
27
- # Generate Endorsement Key pair, should end up in slots (0, 1).
28
- s.genkp :type => 0
29
- s.ldbc 1
30
- s.sub
31
- s.jne :to => :not_ok
32
- s.ldbc 0
33
- s.sub
34
- s.jne :to => :not_ok
35
-
36
- # Generate and output random authorization for PrivEK.
37
- s.ldbc 20
38
- s.dupn :n => 1
39
- s.outnew
40
- s.ldwc :privek_auth
41
- s.dupn :n => 2
42
- s.rnd
43
- s.outvb
44
- # Set authorizations for PrivEK and PubkEK.
45
- s.ldbc 0
46
- s.authk :auth => :privek_auth
47
- s.ldbc 1 # PubEK always has its initial authorization be all zeroes.
48
- s.authk :auth => :pubek_auth
49
- s.halt
50
-
51
- # Emitting didn't go well, return nothing and leave.
52
- s.label :not_ok
53
- s.ldbc 0
54
- s.outnew
55
- s.halt
56
-
57
- s.label :privek_auth
58
- s.zeros :tem_ubyte, 20
59
- s.label :pubek_auth
60
- s.zeros :tem_ubyte, 20
61
- s.stack 4
62
- end
63
-
64
- r = execute emit_sec
65
- if r.length == 0
66
- return nil
67
- else
68
- privk_auth = r[0...20]
69
- pubek_auth = (0...20).map {|i| 0}
70
- pubek = tk_read_key 1, pubek_auth
71
- tk_delete_key 1, pubek_auth
72
- ecert = new_ecert pubek.ssl_key
73
- set_ecert ecert
74
- return { :privek_auth => privk_auth }
75
- end
76
- end
28
+ end
77
29
  end
Binary file
data/lib/tem/secpack.rb CHANGED
@@ -2,7 +2,7 @@ require 'yaml'
2
2
 
3
3
  class Tem::SecPack
4
4
  @@serialized_ivars = [:body, :labels, :ep, :sp, :extra_bytes, :signed_bytes,
5
- :encrypted_bytes, :bound, :lines]
5
+ :secret_bytes, :bound, :lines]
6
6
 
7
7
  def self.new_from_array(array)
8
8
  arg_hash = { }
@@ -14,6 +14,11 @@ class Tem::SecPack
14
14
  array = YAML.load yaml_str
15
15
  new_from_array array
16
16
  end
17
+
18
+ # Creates a deep copy of the SECpack.
19
+ def copy
20
+ Tem::SecPack.new_from_array self.to_array
21
+ end
17
22
 
18
23
  def to_array
19
24
  @@serialized_ivars.map { |m| self.instance_variable_get :"@#{m}" }
@@ -23,7 +28,13 @@ class Tem::SecPack
23
28
  self.to_array.to_yaml.to_s
24
29
  end
25
30
 
26
- attr_reader :body, :bound
31
+ # The size of the secret data in the SECpack.
32
+ attr_reader :secret_bytes
33
+ # The SECpack's body.
34
+ attr_reader :body
35
+ # The size of the encrypted data, if the SECpack is bound. False otherwise.
36
+ attr_reader :bound
37
+ # Debugging information.
27
38
  attr_reader :lines
28
39
 
29
40
  def trim_extra_bytes
@@ -51,37 +62,100 @@ class Tem::SecPack
51
62
  def label_address(label_name)
52
63
  @labels[label_name.to_sym]
53
64
  end
65
+
66
+ def bind(public_key, secret_from = :secret, plain_from = :plain)
67
+ raise "SECpack is already bound" if @bound
54
68
 
55
- def bind(public_key, encrypt_from = 0, plaintext_from = 0)
56
69
  expand_extra_bytes
57
- encrypt_from = @labels[encrypt_from.to_sym] unless encrypt_from.kind_of? Numeric
58
- plaintext_from = @labels[plaintext_from.to_sym] unless plaintext_from.kind_of? Numeric
59
-
60
- @signed_bytes = encrypt_from
61
- @encrypted_bytes = plaintext_from - encrypt_from
70
+ unless secret_from.kind_of? Numeric
71
+ secret_from_label = secret_from
72
+ secret_from = @labels[secret_from.to_sym]
73
+ raise "Undefined label #{secret_from_label}" unless secret_from
74
+ end
75
+ unless plain_from.kind_of? Numeric
76
+ plain_from_label = plain_from
77
+ plain_from = @labels[plain_from.to_sym]
78
+ raise "Undefined label #{plain_from_label}" unless plain_from
79
+ end
62
80
 
63
- secpack_sig = Tem::Abi.tem_hash [tem_header, @body[0...plaintext_from]].flatten
64
- crypt = public_key.encrypt [@body[encrypt_from...plaintext_from], secpack_sig].flatten
65
- @body = [@body[0...encrypt_from], crypt, @body[plaintext_from..-1]].flatten
81
+ @signed_bytes = secret_from
82
+ @secret_bytes = plain_from - secret_from
83
+
84
+ secpack_sig = Tem::Abi.tem_hash tem_header + @body[0, plain_from]
85
+ crypt = public_key.encrypt @body[secret_from, @secret_bytes] + secpack_sig
86
+ @body = [@body[0, secret_from], crypt, @body[plain_from..-1]].flatten
66
87
 
67
- label_delta = crypt.length - @encrypted_bytes
88
+ label_delta = crypt.length - @secret_bytes
89
+ relocate_labels secret_from, plain_from, label_delta
90
+
91
+ #trim_extra_bytes
92
+ @bound = crypt.length
93
+ end
94
+
95
+ def fake_bind(secret_from = :secret, plain_from = :plain)
96
+ raise "SECpack is already bound" if @bound
97
+
98
+ expand_extra_bytes
99
+ unless secret_from.kind_of? Numeric
100
+ secret_from_label = secret_from
101
+ secret_from = @labels[secret_from.to_sym]
102
+ raise "Undefined label #{secret_from_label}" unless secret_from
103
+ end
104
+ unless plain_from.kind_of? Numeric
105
+ plain_from_label = plain_from
106
+ plain_from = @labels[plain_from.to_sym]
107
+ raise "Undefined label #{plain_from_label}" unless plain_from
108
+ end
109
+
110
+ @signed_bytes = secret_from
111
+ @secret_bytes = plain_from - secret_from
112
+
113
+ #trim_extra_bytes
114
+ @bound = @secret_bytes
115
+ end
116
+
117
+ # Relocates the labels to reflect a change in the size of encrypted bytes.
118
+ #
119
+ # Args:
120
+ # same_until:: the end of the signed area (no relocations done there)
121
+ # delete_until:: the end of the old encrypted area (labels are removed)
122
+ # delta:: the size difference between the new and the old encrypted areas
123
+ def relocate_labels(same_until, delete_until, delta)
68
124
  @labels = Hash[*(@labels.map { |k, v|
69
- if v < encrypt_from
125
+ if v <= same_until
70
126
  [k, v]
71
- elsif v < plaintext_from
127
+ elsif v < delete_until
72
128
  []
73
129
  else
74
- [k, v + label_delta]
130
+ [k, v + delta]
75
131
  end
76
- }.flatten)]
132
+ }.flatten)]
133
+ end
77
134
 
78
- #trim_extra_bytes
79
- @bound = true
135
+ # The encrypted data in a SECpack.
136
+ #
137
+ # This is useful for SECpack migration -- the encrypted bytes are the only
138
+ # part that has to be migrated.
139
+ def encrypted_data
140
+ @body[@signed_bytes, @bound]
141
+ end
142
+
143
+ # Replaces the encrypted bytes in a SECpack.
144
+ #
145
+ # This is used in SECpack migration -- the encryption bytes are the only part
146
+ # that changes during migration.
147
+ def encrypted_data=(new_encrypted_bytes)
148
+ raise "SECpack is not bound. See #bind and #fake_bind." unless @bound
149
+
150
+ @body[@signed_bytes, @bound] = new_encrypted_bytes
151
+ relocate_labels @signed_bytes, @signed_bytes + @bound,
152
+ new_encrypted_bytes.length - @bound
153
+ @bound = new_encrypted_bytes.length
80
154
  end
81
155
 
82
156
  def tem_header
83
157
  # TODO: use 0x0100 (no tracing) depending on options
84
- hh = [0x0101, @signed_bytes || 0, @encrypted_bytes || 0, @extra_bytes, @sp,
158
+ hh = [0x0101, @signed_bytes || 0, @secret_bytes || 0, @extra_bytes, @sp,
85
159
  @ep].map { |n| Tem::Abi.to_tem_ushort n }.flatten
86
160
  hh += Array.new((Tem::Abi.tem_hash [0]).length - hh.length, 0)
87
161
  return hh
data/lib/tem/tem.rb CHANGED
@@ -5,6 +5,9 @@ class Tem::Session
5
5
  include Tem::Apdus::Lifecycle
6
6
  include Tem::Apdus::Tag
7
7
 
8
+ include Tem::Admin::Emit
9
+ include Tem::Admin::Migrate
10
+
8
11
  include Tem::CA
9
12
  include Tem::ECert
10
13
  include Tem::SeClosures
@@ -12,20 +15,39 @@ class Tem::Session
12
15
 
13
16
  CAPPLET_AID = [0x19, 0x83, 0x12, 0x29, 0x10, 0xBA, 0xBE]
14
17
 
18
+ # The transport used for this TEM.
15
19
  attr_reader :transport
16
20
 
21
+ # The TEM instance cache.
22
+ #
23
+ # This cache stores information about the TEM connected to this session. The
24
+ # cache can be safely cleared without losing correctness.
25
+ #
26
+ # The cache should not be modified directly by client code.
27
+ attr_reader :icache
28
+
17
29
  def initialize(transport)
18
30
  @transport = transport
19
31
  @transport.extend Smartcard::Gp::GpCardMixin
20
32
  @transport.select_application CAPPLET_AID
33
+
34
+ @icache = {}
21
35
  end
22
-
36
+
23
37
  def disconnect
24
38
  return unless @transport
25
39
  @transport.disconnect
26
40
  @transport = nil
41
+ clear_icache
27
42
  end
28
43
 
44
+ # Clears the TEM instance cache.
45
+ #
46
+ # This should be called when connecting to a different TEM.
47
+ def clear_icache
48
+ @icache.clear
49
+ end
50
+
29
51
  def tem_secpack_error(response)
30
52
  raise "TEM refused the SECpack"
31
53
  end
data/lib/tem_ruby.rb CHANGED
@@ -27,6 +27,9 @@ require 'tem/apdus/tag.rb'
27
27
 
28
28
  require 'tem/firmware/uploader.rb'
29
29
 
30
+ require 'tem/admin/emit.rb'
31
+ require 'tem/admin/migrate.rb'
32
+
30
33
  require 'tem/ca.rb'
31
34
  require 'tem/ecert.rb'
32
35
  require 'tem/hive.rb'
data/tem_ruby.gemspec CHANGED
@@ -2,23 +2,23 @@
2
2
 
3
3
  Gem::Specification.new do |s|
4
4
  s.name = %q{tem_ruby}
5
- s.version = "0.14.1"
5
+ s.version = "0.15.1"
6
6
 
7
7
  s.required_rubygems_version = Gem::Requirement.new(">= 1.2") if s.respond_to? :required_rubygems_version=
8
8
  s.authors = ["Victor Costan"]
9
- s.date = %q{2009-11-16}
9
+ s.date = %q{2009-11-18}
10
10
  s.description = %q{TEM (Trusted Execution Module) driver, written in and for ruby.}
11
11
  s.email = %q{victor@costan.us}
12
12
  s.executables = ["tem_bench", "tem_ca", "tem_irb", "tem_proxy", "tem_stat", "tem_upload_fw"]
13
- s.extra_rdoc_files = ["CHANGELOG", "LICENSE", "README", "bin/tem_bench", "bin/tem_ca", "bin/tem_irb", "bin/tem_proxy", "bin/tem_stat", "bin/tem_upload_fw", "lib/tem/_cert.rb", "lib/tem/apdus/buffers.rb", "lib/tem/apdus/keys.rb", "lib/tem/apdus/lifecycle.rb", "lib/tem/apdus/tag.rb", "lib/tem/auto_conf.rb", "lib/tem/benchmarks/benchmarks.rb", "lib/tem/benchmarks/blank_bound_secpack.rb", "lib/tem/benchmarks/blank_sec.rb", "lib/tem/benchmarks/devchip_decrypt.rb", "lib/tem/benchmarks/post_buffer.rb", "lib/tem/benchmarks/simple_apdu.rb", "lib/tem/benchmarks/vm_perf.rb", "lib/tem/benchmarks/vm_perf_bound.rb", "lib/tem/builders/abi.rb", "lib/tem/builders/assembler.rb", "lib/tem/builders/crypto.rb", "lib/tem/builders/isa.rb", "lib/tem/ca.rb", "lib/tem/definitions/abi.rb", "lib/tem/definitions/assembler.rb", "lib/tem/definitions/isa.rb", "lib/tem/ecert.rb", "lib/tem/firmware/tc.cap", "lib/tem/firmware/uploader.rb", "lib/tem/hive.rb", "lib/tem/keys/asymmetric.rb", "lib/tem/keys/key.rb", "lib/tem/keys/symmetric.rb", "lib/tem/sec_exec_error.rb", "lib/tem/seclosures.rb", "lib/tem/secpack.rb", "lib/tem/tem.rb", "lib/tem/toolkit.rb", "lib/tem_ruby.rb"]
14
- s.files = ["CHANGELOG", "LICENSE", "Manifest", "README", "Rakefile", "bin/tem_bench", "bin/tem_ca", "bin/tem_irb", "bin/tem_proxy", "bin/tem_stat", "bin/tem_upload_fw", "dev_ca/ca_cert.cer", "dev_ca/ca_cert.pem", "dev_ca/ca_key.pem", "dev_ca/config.yml", "lib/tem/_cert.rb", "lib/tem/apdus/buffers.rb", "lib/tem/apdus/keys.rb", "lib/tem/apdus/lifecycle.rb", "lib/tem/apdus/tag.rb", "lib/tem/auto_conf.rb", "lib/tem/benchmarks/benchmarks.rb", "lib/tem/benchmarks/blank_bound_secpack.rb", "lib/tem/benchmarks/blank_sec.rb", "lib/tem/benchmarks/devchip_decrypt.rb", "lib/tem/benchmarks/post_buffer.rb", "lib/tem/benchmarks/simple_apdu.rb", "lib/tem/benchmarks/vm_perf.rb", "lib/tem/benchmarks/vm_perf_bound.rb", "lib/tem/builders/abi.rb", "lib/tem/builders/assembler.rb", "lib/tem/builders/crypto.rb", "lib/tem/builders/isa.rb", "lib/tem/ca.rb", "lib/tem/definitions/abi.rb", "lib/tem/definitions/assembler.rb", "lib/tem/definitions/isa.rb", "lib/tem/ecert.rb", "lib/tem/firmware/tc.cap", "lib/tem/firmware/uploader.rb", "lib/tem/hive.rb", "lib/tem/keys/asymmetric.rb", "lib/tem/keys/key.rb", "lib/tem/keys/symmetric.rb", "lib/tem/sec_exec_error.rb", "lib/tem/seclosures.rb", "lib/tem/secpack.rb", "lib/tem/tem.rb", "lib/tem/toolkit.rb", "lib/tem_ruby.rb", "test/_test_cert.rb", "test/builders/test_abi_builder.rb", "test/firmware/test_uploader.rb", "test/tem_test_case.rb", "test/tem_unit/test_tem_alu.rb", "test/tem_unit/test_tem_bound_secpack.rb", "test/tem_unit/test_tem_branching.rb", "test/tem_unit/test_tem_crypto_hash.rb", "test/tem_unit/test_tem_crypto_keys.rb", "test/tem_unit/test_tem_crypto_pstore.rb", "test/tem_unit/test_tem_crypto_random.rb", "test/tem_unit/test_tem_emit.rb", "test/tem_unit/test_tem_memory.rb", "test/tem_unit/test_tem_memory_compare.rb", "test/tem_unit/test_tem_output.rb", "test/tem_unit/test_tem_yaml_secpack.rb", "test/test_auto_conf.rb", "test/test_crypto_engine.rb", "test/test_driver.rb", "test/test_exceptions.rb", "tem_ruby.gemspec"]
13
+ s.extra_rdoc_files = ["CHANGELOG", "LICENSE", "README", "bin/tem_bench", "bin/tem_ca", "bin/tem_irb", "bin/tem_proxy", "bin/tem_stat", "bin/tem_upload_fw", "lib/tem/_cert.rb", "lib/tem/admin/emit.rb", "lib/tem/admin/migrate.rb", "lib/tem/apdus/buffers.rb", "lib/tem/apdus/keys.rb", "lib/tem/apdus/lifecycle.rb", "lib/tem/apdus/tag.rb", "lib/tem/auto_conf.rb", "lib/tem/benchmarks/benchmarks.rb", "lib/tem/benchmarks/blank_bound_secpack.rb", "lib/tem/benchmarks/blank_sec.rb", "lib/tem/benchmarks/devchip_decrypt.rb", "lib/tem/benchmarks/post_buffer.rb", "lib/tem/benchmarks/simple_apdu.rb", "lib/tem/benchmarks/vm_perf.rb", "lib/tem/benchmarks/vm_perf_bound.rb", "lib/tem/builders/abi.rb", "lib/tem/builders/assembler.rb", "lib/tem/builders/crypto.rb", "lib/tem/builders/isa.rb", "lib/tem/ca.rb", "lib/tem/definitions/abi.rb", "lib/tem/definitions/assembler.rb", "lib/tem/definitions/isa.rb", "lib/tem/ecert.rb", "lib/tem/firmware/tc.cap", "lib/tem/firmware/uploader.rb", "lib/tem/hive.rb", "lib/tem/keys/asymmetric.rb", "lib/tem/keys/key.rb", "lib/tem/keys/symmetric.rb", "lib/tem/sec_exec_error.rb", "lib/tem/seclosures.rb", "lib/tem/secpack.rb", "lib/tem/tem.rb", "lib/tem/toolkit.rb", "lib/tem_ruby.rb"]
14
+ s.files = ["CHANGELOG", "LICENSE", "Manifest", "README", "Rakefile", "bin/tem_bench", "bin/tem_ca", "bin/tem_irb", "bin/tem_proxy", "bin/tem_stat", "bin/tem_upload_fw", "dev_ca/ca_cert.cer", "dev_ca/ca_cert.pem", "dev_ca/ca_key.pem", "dev_ca/config.yml", "lib/tem/_cert.rb", "lib/tem/admin/emit.rb", "lib/tem/admin/migrate.rb", "lib/tem/apdus/buffers.rb", "lib/tem/apdus/keys.rb", "lib/tem/apdus/lifecycle.rb", "lib/tem/apdus/tag.rb", "lib/tem/auto_conf.rb", "lib/tem/benchmarks/benchmarks.rb", "lib/tem/benchmarks/blank_bound_secpack.rb", "lib/tem/benchmarks/blank_sec.rb", "lib/tem/benchmarks/devchip_decrypt.rb", "lib/tem/benchmarks/post_buffer.rb", "lib/tem/benchmarks/simple_apdu.rb", "lib/tem/benchmarks/vm_perf.rb", "lib/tem/benchmarks/vm_perf_bound.rb", "lib/tem/builders/abi.rb", "lib/tem/builders/assembler.rb", "lib/tem/builders/crypto.rb", "lib/tem/builders/isa.rb", "lib/tem/ca.rb", "lib/tem/definitions/abi.rb", "lib/tem/definitions/assembler.rb", "lib/tem/definitions/isa.rb", "lib/tem/ecert.rb", "lib/tem/firmware/tc.cap", "lib/tem/firmware/uploader.rb", "lib/tem/hive.rb", "lib/tem/keys/asymmetric.rb", "lib/tem/keys/key.rb", "lib/tem/keys/symmetric.rb", "lib/tem/sec_exec_error.rb", "lib/tem/seclosures.rb", "lib/tem/secpack.rb", "lib/tem/tem.rb", "lib/tem/toolkit.rb", "lib/tem_ruby.rb", "test/_test_cert.rb", "test/builders/test_abi_builder.rb", "test/firmware/test_uploader.rb", "test/tem_test_case.rb", "test/tem_unit/test_tem_alu.rb", "test/tem_unit/test_tem_bound_secpack.rb", "test/tem_unit/test_tem_branching.rb", "test/tem_unit/test_tem_crypto_hash.rb", "test/tem_unit/test_tem_crypto_keys.rb", "test/tem_unit/test_tem_crypto_pstore.rb", "test/tem_unit/test_tem_crypto_random.rb", "test/tem_unit/test_tem_emit.rb", "test/tem_unit/test_tem_memory.rb", "test/tem_unit/test_tem_memory_compare.rb", "test/tem_unit/test_tem_migrate.rb", "test/tem_unit/test_tem_output.rb", "test/tem_unit/test_tem_yaml_secpack.rb", "test/test_auto_conf.rb", "test/test_crypto_engine.rb", "test/test_driver.rb", "test/test_exceptions.rb", "test/test_tag.rb", "tem_ruby.gemspec"]
15
15
  s.homepage = %q{http://tem.rubyforge.org}
16
16
  s.rdoc_options = ["--line-numbers", "--inline-source", "--title", "Tem_ruby", "--main", "README"]
17
17
  s.require_paths = ["lib"]
18
18
  s.rubyforge_project = %q{tem}
19
19
  s.rubygems_version = %q{1.3.5}
20
20
  s.summary = %q{TEM (Trusted Execution Module) driver, written in and for ruby.}
21
- s.test_files = ["test/test_driver.rb", "test/firmware/test_uploader.rb", "test/test_auto_conf.rb", "test/builders/test_abi_builder.rb", "test/tem_unit/test_tem_emit.rb", "test/tem_unit/test_tem_crypto_keys.rb", "test/tem_unit/test_tem_yaml_secpack.rb", "test/tem_unit/test_tem_alu.rb", "test/tem_unit/test_tem_crypto_hash.rb", "test/tem_unit/test_tem_bound_secpack.rb", "test/tem_unit/test_tem_memory_compare.rb", "test/tem_unit/test_tem_output.rb", "test/tem_unit/test_tem_crypto_random.rb", "test/tem_unit/test_tem_memory.rb", "test/tem_unit/test_tem_branching.rb", "test/tem_unit/test_tem_crypto_pstore.rb", "test/test_exceptions.rb", "test/test_crypto_engine.rb"]
21
+ s.test_files = ["test/builders/test_abi_builder.rb", "test/firmware/test_uploader.rb", "test/tem_unit/test_tem_alu.rb", "test/tem_unit/test_tem_bound_secpack.rb", "test/tem_unit/test_tem_branching.rb", "test/tem_unit/test_tem_crypto_hash.rb", "test/tem_unit/test_tem_crypto_keys.rb", "test/tem_unit/test_tem_crypto_pstore.rb", "test/tem_unit/test_tem_crypto_random.rb", "test/tem_unit/test_tem_emit.rb", "test/tem_unit/test_tem_memory.rb", "test/tem_unit/test_tem_memory_compare.rb", "test/tem_unit/test_tem_migrate.rb", "test/tem_unit/test_tem_output.rb", "test/tem_unit/test_tem_yaml_secpack.rb", "test/test_auto_conf.rb", "test/test_crypto_engine.rb", "test/test_driver.rb", "test/test_exceptions.rb", "test/test_tag.rb"]
22
22
 
23
23
  if s.respond_to? :specification_version then
24
24
  current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
@@ -18,7 +18,7 @@ class UploaderTest < Test::Unit::TestCase
18
18
  end
19
19
 
20
20
  def test_fw_version
21
- assert_equal({:major => 1, :minor => 14}, Uploader.fw_version)
21
+ assert_equal({:major => 1, :minor => 15}, Uploader.fw_version)
22
22
  end
23
23
 
24
24
  def test_upload
@@ -1,35 +1,48 @@
1
1
  require 'test/tem_test_case.rb'
2
2
 
3
3
  class TemCryptoKeysTest < TemTestCase
4
+ def i_crypt_len(data_length, key_id, authz)
5
+ ex_sec = @tem.assemble { |s|
6
+ s.ldbc :const => 2
7
+ s.outnew
8
+ s.ldbc :const => key_id
9
+ s.authk :auth => :key_auth
10
+ s.ldwc :const => data_length
11
+ s.ldkel
12
+ s.outw
13
+ s.halt
14
+ s.label :key_auth
15
+ s.data :tem_ubyte, authz
16
+ s.stack 6
17
+ }
18
+ Tem::Abi.read_tem_short @tem.execute(ex_sec), 0
19
+ end
20
+
4
21
  def i_crypt(data, key_id, authz, mode = :encrypt, direct_io = true,
5
22
  symmetric = false)
6
- if symmetric
7
- max_output = case mode
8
- when :encrypt
9
- ((data.length + 8) / 8) * 8
10
- when :decrypt
11
- data.length
12
- when :sign
13
- 8
14
- end
15
- else
16
- max_output = case mode
17
- when :encrypt
18
- ((data.length + 239) / 240) * 256
19
- when :decrypt
20
- data.length
21
- when :sign
22
- 256
23
- end
23
+ max_output = case mode
24
+ when :encrypt
25
+ (data.length + 239) / 240 * 256
26
+ when :decrypt
27
+ data.length
28
+ when :sign
29
+ 256
24
30
  end
25
31
 
26
32
  crypt_opcode =
27
33
  {:encrypt => :kefxb, :decrypt => :kdfxb, :sign => :ksfxb}[mode]
28
34
  ex_sec = @tem.assemble { |s|
29
- s.ldwc :const => max_output
30
- s.outnew
31
35
  s.ldbc :const => key_id
32
36
  s.authk :auth => :key_auth
37
+ if mode == :encrypt # Use ldkel to get the max_output value.
38
+ s.dupn :n => 1
39
+ s.ldwc :const => data.length
40
+ s.ldkel
41
+ else
42
+ s.ldwc :const => max_output
43
+ end
44
+ s.outnew
45
+
33
46
  s.send crypt_opcode, :from => :data, :size => data.length,
34
47
  :to => (direct_io ? 0xFFFF : :outdata)
35
48
  s.outvlb :from => :outdata unless direct_io
@@ -45,7 +58,7 @@ class TemCryptoKeysTest < TemTestCase
45
58
  end
46
59
  s.stack 5
47
60
  }
48
- return @tem.execute(ex_sec)
61
+ @tem.execute ex_sec
49
62
  end
50
63
 
51
64
  def i_verify(data, signature, key_id, authz)
@@ -66,12 +79,17 @@ class TemCryptoKeysTest < TemTestCase
66
79
  s.data :tem_ubyte, signature
67
80
  s.stack 5
68
81
  }
69
- return @tem.execute(sign_sec)[0] == 1
82
+ @tem.execute(sign_sec)[0] == 1
70
83
  end
71
84
 
72
85
  def i_test_crypto_pks_ops(pubk_id, privk_id, pubk, privk, authz)
73
86
  garbage = (0...569).map { |i| (i * i * 217 + i * 661 + 393) % 256 }
74
87
 
88
+ # Obtaining the length of encrypted data.
89
+ crypt_length = i_crypt_len garbage.length, pubk_id, authz
90
+ assert_equal((garbage.length + 239) / 240 * 256, crypt_length,
91
+ 'Incorrect result from ldkel')
92
+
75
93
  # SEC/priv-sign + CPU/pub-verify, direct IO.
76
94
  signed_garbage = i_crypt garbage, privk_id, authz, :sign, true
77
95
  assert privk.verify(garbage, signed_garbage),
@@ -134,6 +152,11 @@ class TemCryptoKeysTest < TemTestCase
134
152
  def i_test_crypto_sks_ops(skey_id, skey, authz)
135
153
  garbage = (0...569).map { |i| (i * i * 217 + i * 661 + 393) % 256 }
136
154
 
155
+ # Obtaining the length of encrypted data.
156
+ crypt_length = i_crypt_len garbage.length, skey_id, authz
157
+ assert_equal((garbage.length + 8) / 8 * 8, crypt_length,
158
+ 'Incorrect result from ldkel')
159
+
137
160
  # SEC/sign + CPU/verify, direct IO.
138
161
  signed_garbage = i_crypt garbage, skey_id, authz, :sign, true, true
139
162
  assert skey.verify(garbage, signed_garbage),
@@ -2,12 +2,12 @@ require 'test/tem_test_case.rb'
2
2
 
3
3
  class TemCryptoPstoreTest < TemTestCase
4
4
  def test_crypto_pstore
5
- addr1 = (0...(@tem.tem_ps_addr_length)).map { |x| (61 * x * x + 62 * x + 10) % 256 }
5
+ addr1 = (0...(Tem::Abi.tem_ps_addr_length)).map { |x| (61 * x * x + 62 * x + 10) % 256 }
6
6
  addr2 = addr1.dup; addr2[addr2.length - 1] += 1
7
- random_value = (0...(@tem.tem_ps_value_length)).map { |x| (69 * x * x + 62 * x + 10) % 256 }
7
+ random_value = (0...(Tem::Abi.tem_ps_value_length)).map { |x| (69 * x * x + 62 * x + 10) % 256 }
8
8
 
9
9
  sec = @tem.assemble { |s|
10
- s.ldwc 3 * @tem.tem_ushort_length + @tem.tem_ps_value_length * 2
10
+ s.ldwc 2 * @tem.tem_ushort_length + @tem.tem_ps_value_length
11
11
  s.outnew
12
12
 
13
13
  # check that the location is blank
@@ -23,10 +23,39 @@ class TemCryptoPstoreTest < TemTestCase
23
23
  # re-read (should get what was written)
24
24
  s.ldwc :pstore_addr
25
25
  s.ldwc :s_value2
26
- s.psrdvb
26
+ s.psrdvb
27
27
  s.ldwc :s_value2
28
28
  s.outvb
29
+ s.halt
30
+
31
+ s.label :pstore_addr
32
+ s.data :tem_ubyte, addr1
33
+ s.label :s_value
34
+ s.data :tem_ubyte, random_value
35
+ s.label :s_value2
36
+ s.zeros :tem_ps_value
37
+ s.stack 8
38
+ }
39
+ expected = @tem.to_tem_ushort(0) + @tem.to_tem_ushort(1) + random_value
40
+ result = @tem.execute sec
41
+ assert_equal expected, result,
42
+ "Persistent store locations aren\'t working well"
29
43
 
44
+ sec = @tem.assemble { |s|
45
+ s.ldwc 2 * @tem.tem_ushort_length + @tem.tem_ps_value_length
46
+ s.outnew
47
+
48
+ # check that the location isn't blank anymore
49
+ s.pshkfxb :addr => :pstore_addr
50
+ s.outw
51
+
52
+ # re-read (should get what was written)
53
+ s.ldwc :pstore_addr
54
+ s.ldwc :s_value2
55
+ s.psrdvb
56
+ s.ldwc :s_value2
57
+ s.outvb
58
+
30
59
  # drop the location
31
60
  s.ldwc :pstore_addr
32
61
  s.dupn :n => 1
@@ -45,9 +74,9 @@ class TemCryptoPstoreTest < TemTestCase
45
74
  s.zeros :tem_ps_value
46
75
  s.stack 8
47
76
  }
48
- expected = @tem.to_tem_ushort(0) + @tem.to_tem_ushort(1) + random_value +
49
- @tem.to_tem_ushort(0)
77
+ expected = @tem.to_tem_ushort(1) + random_value + @tem.to_tem_ushort(0)
50
78
  result = @tem.execute sec
51
- assert_equal expected, result, 'persistent store locations aren\'t working well'
79
+ assert_equal expected, result,
80
+ "Persistent store data didn't survive across SECpack execution"
52
81
  end
53
82
  end
@@ -2,22 +2,21 @@ require 'test/tem_test_case.rb'
2
2
 
3
3
  class TemEmitTest < TemTestCase
4
4
  def test_emit
5
- # try to emit
6
- er = @tem.emit
7
- assert er != nil, 'TEM emitting failed'
5
+ # Try to emit the TEM.
6
+ privek_auth = @tem.emit
7
+ assert privek_auth != nil, 'TEM emitting failed'
8
8
 
9
- # now verify that the private key is good and the authorization matches
10
- privek = @tem.tk_read_key 0, er[:privek_auth]
11
- assert((not privek.is_public?), 'TEM emission failed to produce a proper PrivEK')
9
+ # Verify that the private key is good and the authorization matches.
10
+ privek = @tem.tk_read_key 0, privek_auth
11
+ assert((not privek.is_public?),
12
+ 'TEM emission failed to produce a proper PrivEK')
12
13
 
13
- # verify that the public key can be read from the ECert
14
+ # Verify that the public key can be read from the ECert.
14
15
  pubek = @tem.pubek
15
16
  assert pubek.is_public?, 'TEM emission failed to produce a proper PubEK'
16
17
 
17
- # verify the PrivEK against the ECert
18
+ # Verify the PrivEK against the ECert.
18
19
  ecert = @tem.endorsement_cert
19
20
  ecert.verify privek.ssl_key
20
-
21
- @tem.tk_delete_key 0, er[:privek_auth]
22
- end
21
+ end
23
22
  end
@@ -0,0 +1,43 @@
1
+ require 'test/tem_test_case.rb'
2
+
3
+ class TemMigrateTest < TemTestCase
4
+ def _migrate_test_secret
5
+ [0x31, 0x41, 0x59, 0x65, 0x35]
6
+ end
7
+
8
+ def _migrate_test_seclosure
9
+ Tem::Assembler.assemble { |s|
10
+ s.label :secret
11
+ s.ldbc :const => _migrate_test_secret.length
12
+ s.dupn :n => 1
13
+ s.outnew
14
+ s.outvlb :from => :dump_data
15
+ s.halt
16
+ s.label :dump_data
17
+ s.data :tem_ubyte, _migrate_test_secret
18
+ s.label :plain
19
+ }
20
+ end
21
+
22
+ def test_migrate
23
+ # Emit the TEM, bind the SECpack, and test it.
24
+ privek_auth = @tem.emit
25
+ sec = _migrate_test_seclosure
26
+ sec.bind @tem.pubek, :secret, :plain
27
+ assert_equal _migrate_test_secret, @tem.execute(sec),
28
+ 'Migration test SECpack incorrect'
29
+
30
+ # The migration target key pair.
31
+ ekey = OpenSSL::PKey::RSA.generate(2048, 65537)
32
+ privk = Tem::Key.new_from_ssl_key ekey
33
+ pubk = Tem::Key.new_from_ssl_key ekey.public_key
34
+ ecert2 = Tem::CA.new_ecert pubk.ssl_key
35
+ migrated = @tem.migrate sec, ecert2
36
+
37
+ authz = [0] * 20
38
+ privk_id = @tem.tk_post_key privk, authz
39
+ assert_equal _migrate_test_secret, @tem.execute(migrated, privk_id),
40
+ 'Migrated SECpack executed incorrectly'
41
+ @tem.tk_delete_key privk_id, authz
42
+ end
43
+ end
data/test/test_driver.rb CHANGED
@@ -49,16 +49,5 @@ class DriverTest < TemTestCase
49
49
  end
50
50
 
51
51
  b_ids.each { |bid| @tem.release_buffer(bid) }
52
- end
53
-
54
- def test_tag
55
- garbage = (1...569).map { |i| (i * i * 217 + i * 661 + 393) % 256 }
56
-
57
- assert_raise Smartcard::Iso::ApduError, 'tag returned before being set' do
58
- @tem.get_tag
59
- end
60
-
61
- @tem.set_tag garbage
62
- assert_equal garbage, @tem.get_tag, 'error in posted tag data'
63
- end
52
+ end
64
53
  end
data/test/test_tag.rb ADDED
@@ -0,0 +1,42 @@
1
+ require 'test/tem_test_case.rb'
2
+
3
+
4
+ class DriverTest < TemTestCase
5
+ def test_tag_reading_before_writing
6
+ assert_raise Smartcard::Iso::ApduError,
7
+ 'Tag length returned before being set' do
8
+ @tem.get_raw_tag_length
9
+ end
10
+
11
+ assert_raise Smartcard::Iso::ApduError,
12
+ 'Tag data returned before being set' do
13
+ @tem.get_raw_tag_data 0, 1
14
+ end
15
+ end
16
+
17
+ def test_raw_tag_io
18
+ garbage = (1...569).map { |i| (i * i * 217 + i * 661 + 393) % 256 }
19
+
20
+ @tem.set_raw_tag_data garbage
21
+ assert_equal garbage.length, @tem.get_raw_tag_length,
22
+ 'Error in raw tag length'
23
+ assert_equal garbage[19, 400], @tem.get_raw_tag_data(19, 400),
24
+ 'Error in raw tag data partial read'
25
+ assert_equal garbage, @tem.get_raw_tag_data(0, garbage.length),
26
+ 'Error in raw tag data full read'
27
+ end
28
+
29
+ def test_structured_tag
30
+ g1 = (1...569).map { |i| (i * i * 217 + i * 661 + 393) % 256 }
31
+ g2 = (570...1032).map { |i| (i * i * 217 + i * 661 + 393) % 256 }
32
+ tag_data = { 0x01 => g1, 0x11 => g2 }
33
+
34
+ encoded = Tem::Apdus::Tag.encode_tag tag_data
35
+ assert_equal tag_data, Tem::Apdus::Tag.decode_tag(encoded),
36
+ 'Inconsistency in TLV encoding / decoding'
37
+
38
+ @tem.set_tag tag_data
39
+ @tem.clear_icache
40
+ assert_equal tag_data, @tem.tag
41
+ end
42
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: tem_ruby
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.14.1
4
+ version: 0.15.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Victor Costan
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-11-16 00:00:00 -05:00
12
+ date: 2009-11-18 00:00:00 -05:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
@@ -64,6 +64,8 @@ extra_rdoc_files:
64
64
  - bin/tem_stat
65
65
  - bin/tem_upload_fw
66
66
  - lib/tem/_cert.rb
67
+ - lib/tem/admin/emit.rb
68
+ - lib/tem/admin/migrate.rb
67
69
  - lib/tem/apdus/buffers.rb
68
70
  - lib/tem/apdus/keys.rb
69
71
  - lib/tem/apdus/lifecycle.rb
@@ -115,6 +117,8 @@ files:
115
117
  - dev_ca/ca_key.pem
116
118
  - dev_ca/config.yml
117
119
  - lib/tem/_cert.rb
120
+ - lib/tem/admin/emit.rb
121
+ - lib/tem/admin/migrate.rb
118
122
  - lib/tem/apdus/buffers.rb
119
123
  - lib/tem/apdus/keys.rb
120
124
  - lib/tem/apdus/lifecycle.rb
@@ -163,12 +167,14 @@ files:
163
167
  - test/tem_unit/test_tem_emit.rb
164
168
  - test/tem_unit/test_tem_memory.rb
165
169
  - test/tem_unit/test_tem_memory_compare.rb
170
+ - test/tem_unit/test_tem_migrate.rb
166
171
  - test/tem_unit/test_tem_output.rb
167
172
  - test/tem_unit/test_tem_yaml_secpack.rb
168
173
  - test/test_auto_conf.rb
169
174
  - test/test_crypto_engine.rb
170
175
  - test/test_driver.rb
171
176
  - test/test_exceptions.rb
177
+ - test/test_tag.rb
172
178
  - tem_ruby.gemspec
173
179
  has_rdoc: true
174
180
  homepage: http://tem.rubyforge.org
@@ -204,21 +210,23 @@ signing_key:
204
210
  specification_version: 3
205
211
  summary: TEM (Trusted Execution Module) driver, written in and for ruby.
206
212
  test_files:
207
- - test/test_driver.rb
208
- - test/firmware/test_uploader.rb
209
- - test/test_auto_conf.rb
210
213
  - test/builders/test_abi_builder.rb
211
- - test/tem_unit/test_tem_emit.rb
212
- - test/tem_unit/test_tem_crypto_keys.rb
213
- - test/tem_unit/test_tem_yaml_secpack.rb
214
+ - test/firmware/test_uploader.rb
214
215
  - test/tem_unit/test_tem_alu.rb
215
- - test/tem_unit/test_tem_crypto_hash.rb
216
216
  - test/tem_unit/test_tem_bound_secpack.rb
217
- - test/tem_unit/test_tem_memory_compare.rb
218
- - test/tem_unit/test_tem_output.rb
219
- - test/tem_unit/test_tem_crypto_random.rb
220
- - test/tem_unit/test_tem_memory.rb
221
217
  - test/tem_unit/test_tem_branching.rb
218
+ - test/tem_unit/test_tem_crypto_hash.rb
219
+ - test/tem_unit/test_tem_crypto_keys.rb
222
220
  - test/tem_unit/test_tem_crypto_pstore.rb
223
- - test/test_exceptions.rb
221
+ - test/tem_unit/test_tem_crypto_random.rb
222
+ - test/tem_unit/test_tem_emit.rb
223
+ - test/tem_unit/test_tem_memory.rb
224
+ - test/tem_unit/test_tem_memory_compare.rb
225
+ - test/tem_unit/test_tem_migrate.rb
226
+ - test/tem_unit/test_tem_output.rb
227
+ - test/tem_unit/test_tem_yaml_secpack.rb
228
+ - test/test_auto_conf.rb
224
229
  - test/test_crypto_engine.rb
230
+ - test/test_driver.rb
231
+ - test/test_exceptions.rb
232
+ - test/test_tag.rb