tem_ruby 0.14.1 → 0.15.1

Sign up to get free protection for your applications and to get access to all the features.
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