costan-tem_ruby 0.10.2

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.
Files changed (76) hide show
  1. data/CHANGELOG +45 -0
  2. data/LICENSE +21 -0
  3. data/Manifest +75 -0
  4. data/README +8 -0
  5. data/Rakefile +23 -0
  6. data/bin/tem_bench +9 -0
  7. data/bin/tem_ca +13 -0
  8. data/bin/tem_irb +11 -0
  9. data/bin/tem_proxy +65 -0
  10. data/bin/tem_stat +35 -0
  11. data/dev_ca/ca_cert.cer +0 -0
  12. data/dev_ca/ca_cert.pem +32 -0
  13. data/dev_ca/ca_key.pem +27 -0
  14. data/dev_ca/config.yml +14 -0
  15. data/lib/tem/_cert.rb +158 -0
  16. data/lib/tem/apdus/buffers.rb +89 -0
  17. data/lib/tem/apdus/keys.rb +64 -0
  18. data/lib/tem/apdus/lifecycle.rb +13 -0
  19. data/lib/tem/apdus/tag.rb +38 -0
  20. data/lib/tem/auto_conf.rb +25 -0
  21. data/lib/tem/builders/abi.rb +482 -0
  22. data/lib/tem/builders/assembler.rb +314 -0
  23. data/lib/tem/builders/crypto.rb +124 -0
  24. data/lib/tem/builders/isa.rb +120 -0
  25. data/lib/tem/ca.rb +114 -0
  26. data/lib/tem/definitions/abi.rb +65 -0
  27. data/lib/tem/definitions/assembler.rb +23 -0
  28. data/lib/tem/definitions/isa.rb +188 -0
  29. data/lib/tem/ecert.rb +77 -0
  30. data/lib/tem/hive.rb +18 -0
  31. data/lib/tem/keys/asymmetric.rb +116 -0
  32. data/lib/tem/keys/key.rb +48 -0
  33. data/lib/tem/keys/symmetric.rb +47 -0
  34. data/lib/tem/sec_exec_error.rb +63 -0
  35. data/lib/tem/seclosures.rb +81 -0
  36. data/lib/tem/secpack.rb +107 -0
  37. data/lib/tem/tem.rb +31 -0
  38. data/lib/tem/toolkit.rb +101 -0
  39. data/lib/tem/transport/auto_configurator.rb +87 -0
  40. data/lib/tem/transport/java_card_mixin.rb +99 -0
  41. data/lib/tem/transport/jcop_remote_protocol.rb +59 -0
  42. data/lib/tem/transport/jcop_remote_server.rb +171 -0
  43. data/lib/tem/transport/jcop_remote_transport.rb +65 -0
  44. data/lib/tem/transport/pcsc_transport.rb +87 -0
  45. data/lib/tem/transport/transport.rb +10 -0
  46. data/lib/tem_ruby.rb +47 -0
  47. data/tem_ruby.gemspec +35 -0
  48. data/test/_test_cert.rb +70 -0
  49. data/test/builders/test_abi_builder.rb +298 -0
  50. data/test/tem_test_case.rb +26 -0
  51. data/test/tem_unit/test_tem_alu.rb +33 -0
  52. data/test/tem_unit/test_tem_bound_secpack.rb +51 -0
  53. data/test/tem_unit/test_tem_branching.rb +56 -0
  54. data/test/tem_unit/test_tem_crypto_asymmetric.rb +123 -0
  55. data/test/tem_unit/test_tem_crypto_hash.rb +35 -0
  56. data/test/tem_unit/test_tem_crypto_pstore.rb +53 -0
  57. data/test/tem_unit/test_tem_crypto_random.rb +25 -0
  58. data/test/tem_unit/test_tem_emit.rb +23 -0
  59. data/test/tem_unit/test_tem_memory.rb +48 -0
  60. data/test/tem_unit/test_tem_memory_compare.rb +65 -0
  61. data/test/tem_unit/test_tem_output.rb +32 -0
  62. data/test/tem_unit/test_tem_yaml_secpack.rb +47 -0
  63. data/test/test_driver.rb +108 -0
  64. data/test/test_exceptions.rb +35 -0
  65. data/test/transport/test_auto_configurator.rb +114 -0
  66. data/test/transport/test_java_card_mixin.rb +90 -0
  67. data/test/transport/test_jcop_remote.rb +82 -0
  68. data/timings/blank_bound_secpack.rb +18 -0
  69. data/timings/blank_sec.rb +14 -0
  70. data/timings/devchip_decrypt.rb +9 -0
  71. data/timings/post_buffer.rb +10 -0
  72. data/timings/simple_apdu.rb +5 -0
  73. data/timings/timings.rb +64 -0
  74. data/timings/vm_perf.rb +140 -0
  75. data/timings/vm_perf_bound.rb +141 -0
  76. metadata +201 -0
data/lib/tem/ca.rb ADDED
@@ -0,0 +1,114 @@
1
+ require 'openssl'
2
+ require 'yaml'
3
+
4
+ # Certificate Authority (CA) functionality for TEM manufacturers
5
+ module Tem::CA
6
+ # creates an Endorsement Certificate for a TEM's Public Endorsement Key
7
+ def new_ecert(pubek)
8
+ ca_cert = Tem::CA.ca_cert
9
+ ca_key = Tem::CA.ca_key
10
+ conf = Tem::CA.config
11
+
12
+ dn = OpenSSL::X509::Name.new conf[:issuer].merge(conf[:subject]).to_a
13
+ now = Time.now
14
+ ecert = OpenSSL::X509::Certificate.new
15
+ ecert.issuer = ca_cert.subject
16
+ ecert.subject = dn
17
+ ecert.not_before = now;
18
+ ecert.not_after = now + conf[:ecert_validity_days] * 60 * 60 * 24;
19
+ ecert.public_key = pubek
20
+ ecert.version = 2
21
+ cf = OpenSSL::X509::ExtensionFactory.new
22
+ cf.subject_certificate = ecert
23
+ cf.issuer_certificate = ca_cert
24
+ ecert.add_extension cf.create_extension("basicConstraints", "CA:true", true)
25
+ ecert.add_extension cf.create_extension("authorityKeyIdentifier", "keyid,issuer")
26
+ ecert.add_extension cf.create_extension("keyUsage", "digitalSignature,nonRepudiation,keyEncipherment,dataEncipherment,keyAgreement,keyCertSign,cRLSign")
27
+ ecert.add_extension cf.create_extension("extendedKeyUsage", "serverAuth,clientAuth,codeSigning,emailProtection,timeStamping,msCodeInd,msCodeCom,msCTLSign,msSGC,msEFS,nsSGC")
28
+ ecert.add_extension cf.create_extension("nsCertType", "client,server,email,objsign,sslCA,emailCA,objCA")
29
+ ecert.add_extension cf.create_extension("subjectKeyIdentifier", "hash")
30
+ ecert.sign ca_key, OpenSSL::Digest::SHA1.new
31
+
32
+ return ecert
33
+ end
34
+
35
+ @@dev_dir = File.join(File.dirname(__FILE__), "..", "..", "dev_ca")
36
+
37
+ # retrieves the TEM CA configuration
38
+ def self.config
39
+ cpath = Tem::Hive.path_to 'ca/config.yml'
40
+ cpath = File.join(@@dev_dir, 'config.yml') unless File.exists? cpath
41
+
42
+ # try to open it in the base folder
43
+ scaffold_config unless File.exists? cpath
44
+ return File.open(cpath, 'r') { |f| YAML.load f }
45
+ end
46
+
47
+ # retrieves the TEM CA certificate
48
+ def self.ca_cert
49
+ cpath = Tem::Hive.path_to 'ca/ca_cert.pem'
50
+ cpath = File.join(@@dev_dir, 'ca_cert.pem') unless File.exists? cpath
51
+ return OpenSSL::X509::Certificate.new(File.open(cpath, 'r') { |f| f.read })
52
+ end
53
+
54
+ # retrieves the TEM CA key pair (needed for signing)
55
+ def self.ca_key
56
+ cpath = Tem::Hive.path_to 'ca/ca_key.pem'
57
+ cpath = File.join(@@dev_dir, 'ca_key.pem') unless File.exists? cpath
58
+ return OpenSSL::PKey::RSA.new(File.open(cpath, 'r') { |f| f.read })
59
+ end
60
+
61
+ # scaffolds the structures needed for a TEM CA
62
+ def self.scaffold_ca
63
+ conf = config
64
+
65
+ # generate and write key
66
+ ca_key = Tem::CryptoAbi.generate_ssl_kp
67
+ key_path = Tem::Hive.create 'ca/ca_key.pem'
68
+ File.open(key_path, 'w') { |f| f.write ca_key.to_pem }
69
+
70
+ # create the CA certificate
71
+ dn = OpenSSL::X509::Name.new conf[:issuer].to_a
72
+ now = Time.now
73
+ cert = OpenSSL::X509::Certificate.new
74
+ cert.subject = cert.issuer = dn
75
+ cert.not_before = now;
76
+ cert.not_after = now + conf[:ca_validity_days] * 60 * 60 * 24;
77
+ cert.public_key = ca_key.public_key
78
+ cert.version = 2
79
+ cf = OpenSSL::X509::ExtensionFactory.new
80
+ cf.subject_certificate = cf.issuer_certificate = cert
81
+ cert.add_extension cf.create_extension("basicConstraints", "CA:true", true)
82
+ cert.add_extension cf.create_extension("authorityKeyIdentifier", "keyid,issuer")
83
+ cert.add_extension cf.create_extension("keyUsage", "cRLSign,keyCertSign")
84
+ cert.add_extension cf.create_extension("nsCertType", "emailCA,sslCA")
85
+ cert.add_extension cf.create_extension("subjectKeyIdentifier", "hash")
86
+ cert.sign ca_key, OpenSSL::Digest::SHA1.new
87
+
88
+ # write the CA certificate
89
+ cert_path = Tem::Hive.create 'ca/ca_cert.pem'
90
+ File.open(cert_path, 'w') { |f| f.write cert.to_pem }
91
+ cert_path = Tem::Hive.create 'ca/ca_cert.cer'
92
+ File.open(cert_path, 'wb') { |f| f.write cert.to_der }
93
+ end
94
+
95
+ # scaffolds a TEM CA configuration
96
+ def self.scaffold_config
97
+ def_config = {
98
+ :issuer => {
99
+ 'C' => 'US', 'ST' => 'Massachusetts', 'L' => 'Cambridge',
100
+ 'O' => 'Massachusetts Insitute of Technology',
101
+ 'OU' => 'Computer Science and Artificial Intelligence Laboratory',
102
+ 'CN' => 'Trusted Execution Module Development CA'
103
+ },
104
+ :subject => {
105
+ 'CN' => 'Trusted Execution Module DevChip'
106
+ },
107
+ :ca_validity_days => 3652,
108
+ :ecert_validity_days => 365 * 2,
109
+ }
110
+
111
+ cpath = Tem::Hive.create 'ca/config.yml'
112
+ File.open(cpath, 'w') { |f| YAML.dump def_config, f }
113
+ end
114
+ end
@@ -0,0 +1,65 @@
1
+ require 'openssl'
2
+ require 'digest/sha1'
3
+
4
+
5
+ module Tem::Abi
6
+ Tem::Builders::Abi.define_abi self do |abi|
7
+ abi.fixed_length_number :tem_byte, 1, :signed => true, :big_endian => true
8
+ abi.fixed_length_number :tem_ubyte, 1, :signed => false, :big_endian => true
9
+ abi.fixed_length_number :tem_short, 2, :signed => true, :big_endian => true
10
+ abi.fixed_length_number :tem_ushort, 2, :signed => false,
11
+ :big_endian => true
12
+ abi.fixed_length_number :tem_ps_addr, 20, :signed => false,
13
+ :big_endian => true
14
+ abi.fixed_length_number :tem_ps_value, 20, :signed => false,
15
+ :big_endian => true
16
+
17
+ abi.packed_variable_length_numbers :tem_privrsa_numbers, :tem_ushort,
18
+ [:p, :q, :dmp1, :dmq1, :iqmp], :signed => false, :big_endian => true
19
+ abi.packed_variable_length_numbers :tem_pubrsa_numbers, :tem_ushort,
20
+ [:e, :n], :signed => false, :big_endian => true
21
+ abi.fixed_length_string :tem_aes_key_string, 16
22
+ end
23
+
24
+ Tem::Builders::Crypto.define_crypto self do |crypto|
25
+ crypto.crypto_hash :tem_hash, Digest::SHA1
26
+
27
+ crypto.asymmetric_key :tem_rsa, OpenSSL::PKey::RSA, :tem_privrsa_numbers,
28
+ :tem_pubrsa_numbers,
29
+ :read_private => lambda { |key|
30
+ # The TEM uses the Chinese Remainder Theorem form of RSA keys, while
31
+ # OpenSSL uses the straightforward form (n, e, d).
32
+
33
+ # Rebuild the straightforward form from the CRT form.
34
+ key.n = key.p * key.q
35
+ p1, q1 = key.p - 1, key.q - 1
36
+ p1q1 = p1 * q1
37
+ # HACK(costan): I haven't figured out how to restore d from dmp1 and
38
+ # dmq1, so I'm betting on the fact that e must be a small prime.
39
+ emp1 = key.dmp1.mod_inverse p1
40
+ emq1 = key.dmq1.mod_inverse q1
41
+ key.e = (emp1 < emq1) ? emp1 : emq1
42
+ key.d = key.e.mod_inverse p1q1
43
+ Tem::Keys::Asymmetric.new key
44
+ }
45
+
46
+ crypto.symmetric_key :tem_aes_key, OpenSSL::Cipher::AES, 'ECB',
47
+ :tem_aes_key_string
48
+
49
+ crypto.conditional_wrapper :tem_key, 1,
50
+ [{:tag => [0x99], :type => :tem_key,
51
+ :class => Tem::Keys::Symmetric },
52
+ {:tag => [0xAA], :type => :public_tem_rsa,
53
+ :class => Tem::Keys::Asymmetric,
54
+ :predicate => lambda { |k| k.ssl_key.kind_of?(OpenSSL::PKey::RSA) &&
55
+ k.is_public? } },
56
+ {:tag => [0x55], :type => :private_tem_rsa,
57
+ :class => Tem::Keys::Asymmetric,
58
+ :predicate => lambda { |k| k.ssl_key.kind_of?(OpenSSL::PKey::RSA) } }]
59
+ end
60
+
61
+ # For convenience, include the Abi methods in Tem::Session's namespace.
62
+ def self.included(klass)
63
+ klass.extend Tem::Abi
64
+ end
65
+ end # module Tem::Abi
@@ -0,0 +1,23 @@
1
+ class Tem::Assembler
2
+ Tem::Builders::Assembler.define_assembler self do |assembler|
3
+ assembler.target_isa Tem::Isa
4
+ assembler.stack_directive :stack, :label => :__stack,
5
+ :slot_type => :tem_short
6
+ assembler.label_directive :label
7
+ assembler.special_label_directive :entry, :__entry
8
+ assembler.zeros_directive :zeros
9
+ assembler.data_directive :data
10
+ end
11
+
12
+ class Builder
13
+ def done_assembling(proxy)
14
+ assembled = super
15
+ bytes = assembled[:bytes]
16
+ labels = assembled[:labels]
17
+ Tem::SecPack.new :body => bytes,
18
+ :labels => labels, :ep => labels[:__entry] || 0,
19
+ :sp => labels[:__stack] || bytes.length,
20
+ :lines => assembled[:line_info]
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,188 @@
1
+ module Tem::Isa
2
+ Tem::Builders::Isa.define_isa self, Tem::Abi,
3
+ :opcode_type => :tem_ubyte do |isa|
4
+ # 2 ST -> 1 ST
5
+ isa.instruction 0x10, :add
6
+ # 2 ST -> 1 ST
7
+ isa.instruction 0x11, :sub
8
+ # 2 ST -> 1 ST
9
+ isa.instruction 0x12, :mul
10
+ # 2 ST -> 1 ST
11
+ isa.instruction 0x13, :div
12
+ # 2 ST -> 1 ST
13
+ isa.instruction 0x14, :mod
14
+ # 2 ST -> 1 ST
15
+ isa.instruction 0x1E, :rnd
16
+
17
+
18
+ # 2 ST -> 1 ST
19
+ isa.instruction 0x3A, :stbv
20
+ # 2 ST -> 1 ST
21
+ isa.instruction 0x3B, :stwv
22
+
23
+ # 2 ST -> 1 ST
24
+ isa.instruction 0x5B, :stk
25
+
26
+
27
+ # 1 ST, 1 IM -> 1 ST
28
+ isa.instruction 0x38, :stb, {:name => :to, :type => :tem_ushort}
29
+ # 1 ST, 1 IM -> 1 ST
30
+ isa.instruction 0x39, :stw, {:name => :to, :type => :tem_ushort}
31
+
32
+
33
+ # 2 IM -> 1 ST
34
+ isa.instruction 0x48, :psupfxb, {:name => :addr, :type => :tem_ushort},
35
+ {:name => :from, :type => :tem_ushort}
36
+ # 2 ST -> 1 ST
37
+ isa.instruction 0x49, :psupvb
38
+ # 2 IM -> 1 ST
39
+ isa.instruction 0x4A, :pswrfxb, {:name => :addr, :type => :tem_ushort},
40
+ {:name => :from, :type => :tem_ushort}
41
+ # 2 ST -> 1 ST
42
+ isa.instruction 0x4B, :pswrvb
43
+ # 2 IM -> 1 ST
44
+ isa.instruction 0x4C, :psrdfxb, {:name => :addr, :type => :tem_ushort},
45
+ {:name => :to, :type => :tem_ushort}
46
+ # 2 ST -> 1 ST
47
+ isa.instruction 0x4D, :psrdvb
48
+ # 2 IM -> 1 ST
49
+ isa.instruction 0x4E, :pshkfxb, {:name => :addr, :type => :tem_ushort}
50
+ # 2 ST -> 1 ST
51
+ isa.instruction 0x4F, :pshkvb
52
+
53
+
54
+ # 3 IM -> 1 ST
55
+ isa.instruction 0x18, :mdfxb, {:name => :size, :type => :tem_ushort},
56
+ {:name => :from, :type => :tem_ushort},
57
+ {:name => :to, :type => :tem_ushort}
58
+ # 3 ST -> 1 ST
59
+ isa.instruction 0x19, :mdvb
60
+ # 3 IM -> 1 ST
61
+ isa.instruction 0x1A, :mcmpfxb, {:name => :size, :type => :tem_ushort},
62
+ {:name => :op1, :type => :tem_ushort},
63
+ {:name => :op2, :type => :tem_ushort}
64
+ # 3 ST -> 1 ST
65
+ isa.instruction 0x1B, :mcmpvb
66
+ # 3 IM -> 1 ST
67
+ isa.instruction 0x1C, :mcfxb, {:name => :size, :type => :tem_ushort},
68
+ {:name => :from, :type => :tem_ushort},
69
+ {:name => :to, :type => :tem_ushort}
70
+ # 3 ST -> 1 ST
71
+ isa.instruction 0x1D, :mcvb
72
+
73
+ # 1 ST, 3 IM -> 1 ST
74
+ isa.instruction 0x50, :kefxb, {:name => :size, :type => :tem_ushort},
75
+ {:name => :from, :type => :tem_ushort},
76
+ {:name => :to, :type => :tem_ushort}
77
+ # 4 ST -> 1 ST
78
+ isa.instruction 0x51, :kevb
79
+ # 1 ST, 3 IM -> 1 ST
80
+ isa.instruction 0x52, :kdfxb, {:name => :size, :type => :tem_ushort},
81
+ {:name => :from, :type => :tem_ushort},
82
+ {:name => :to, :type => :tem_ushort}
83
+ # 4 ST -> 1 ST
84
+ isa.instruction 0x53, :kdvb
85
+ # 1 ST, 3 IM -> 1 ST
86
+ isa.instruction 0x54, :ksfxb, {:name => :size, :type => :tem_ushort},
87
+ {:name => :from, :type => :tem_ushort},
88
+ {:name => :to, :type => :tem_ushort}
89
+ # 4 ST -> 1 ST
90
+ isa.instruction 0x55, :ksvb
91
+ # 1 ST, 3 IM -> 1 ST
92
+ isa.instruction 0x56, :kvsfxb, {:name => :size, :type => :tem_ushort},
93
+ {:name => :from, :type => :tem_ushort},
94
+ {:name => :signature, :type => :tem_ushort}
95
+ # 4 ST -> 1 ST
96
+ isa.instruction 0x57, :kvsvb
97
+
98
+
99
+ # 0 ST -> 0 ST; IP
100
+ isa.instruction 0x27, :jmp, {:name => :to, :type => :tem_ushort,
101
+ :reladdr => 2}
102
+ # 1 ST -> 0 ST; IP
103
+ isa.instruction 0x21, :jz, {:name => :to, :type => :tem_ushort,
104
+ :reladdr => 2}
105
+ isa.instruction 0x21, :je, {:name => :to, :type => :tem_ushort,
106
+ :reladdr => 2}
107
+ # 1 ST -> 0 ST; IP
108
+ isa.instruction 0x26, :jnz, {:name => :to, :type => :tem_ushort,
109
+ :reladdr => 2}
110
+ isa.instruction 0x26, :jne, {:name => :to, :type => :tem_ushort,
111
+ :reladdr => 2}
112
+ # 1 ST -> 0 ST; IP
113
+ isa.instruction 0x22, :ja, {:name => :to, :type => :tem_ushort,
114
+ :reladdr => 2}
115
+ isa.instruction 0x22, :jg, {:name => :to, :type => :tem_ushort,
116
+ :reladdr => 2}
117
+ # 1 ST -> 0 ST; IP
118
+ isa.instruction 0x23, :jae, {:name => :to, :type => :tem_ushort,
119
+ :reladdr => 2}
120
+ isa.instruction 0x23, :jge, {:name => :to, :type => :tem_ushort,
121
+ :reladdr => 2}
122
+ # 1 ST -> 0 ST; IP
123
+ isa.instruction 0x24, :jb, {:name => :to, :type => :tem_ushort,
124
+ :reladdr => 2}
125
+ isa.instruction 0x24, :jl, {:name => :to, :type => :tem_ushort,
126
+ :reladdr => 2}
127
+ # 1 ST -> 0 ST; IP
128
+ isa.instruction 0x25, :jbe, {:name => :to, :type => :tem_ushort,
129
+ :reladdr => 2}
130
+ isa.instruction 0x25, :jle, {:name => :to, :type => :tem_ushort,
131
+ :reladdr => 2}
132
+
133
+ # 1 IM_B -> 1 ST
134
+ isa.instruction 0x30, :ldbc, {:name => :const, :type => :tem_byte}
135
+ # 1 IM -> 1 ST
136
+ isa.instruction 0x31, :ldwc, {:name => :const, :type => :tem_short}
137
+ # 1 ST -> 1 ST
138
+ isa.instruction 0x32, :ldb, {:name => :from, :type => :tem_ushort}
139
+ # 1 ST -> 1 ST
140
+ isa.instruction 0x33, :ldw, {:name => :from, :type => :tem_ushort}
141
+ # 1 ST -> 1 ST
142
+ isa.instruction 0x36, :ldbv
143
+ # 1 ST -> 1 ST
144
+ isa.instruction 0x37, :ldwv
145
+
146
+ # 1 ST -> 0 ST
147
+ isa.instruction 0x42, :outnew
148
+ # 1 ST -> 0 ST
149
+ isa.instruction 0x44, :outb
150
+ # 1 ST -> 0 ST
151
+ isa.instruction 0x45, :outw
152
+
153
+ # 1 ST -> 0 ST
154
+ isa.instruction 0x34, :pop
155
+ # 2 ST -> 0 ST
156
+ isa.instruction 0x35, :pop2
157
+
158
+ # 1 IM, x ST -> 2x ST
159
+ isa.instruction 0x3C, :dupn, {:name => :n, :type => :tem_ubyte}
160
+ # 1 IM, x ST -> x ST
161
+ isa.instruction 0x3D, :flipn, {:name => :n, :type => :tem_ubyte}
162
+
163
+ # 2 IM -> 0 ST
164
+ isa.instruction 0x40, :outfxb, {:name => :size, :type => :tem_ushort},
165
+ {:name => :from, :type => :tem_ushort}
166
+ # 2 ST -> 0 ST
167
+ isa.instruction 0x41, :outvlb, {:name => :from, :type => :tem_ushort}
168
+
169
+
170
+ # 1 IM, 1 ST -> 0 ST
171
+ isa.instruction 0x43, :outvb
172
+ # 0 ST -> 0 ST;;
173
+ isa.instruction 0x46, :halt
174
+ # 1 ST -> 0 ST
175
+ isa.instruction 0x47, :psrm
176
+
177
+ # 1 ST -> 1 ST
178
+ isa.instruction 0x5A, :rdk
179
+ # 1 ST -> 0 ST
180
+ isa.instruction 0x5C, :relk
181
+
182
+ isa.instruction 0x5D, :ldkl
183
+ # 1 IM_B -> 2 ST
184
+ isa.instruction 0x5E, :genkp, {:name => :type, :type => :tem_ubyte }
185
+ # 1 ST, 1 IM -> 1 ST
186
+ isa.instruction 0x5F, :authk, {:name => :auth, :type => :tem_ushort }
187
+ end
188
+ end
data/lib/tem/ecert.rb ADDED
@@ -0,0 +1,77 @@
1
+ require 'openssl'
2
+
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*')
7
+ end
8
+
9
+ # Retrieves the TEM's Endorsement Certificate.
10
+ def endorsement_cert
11
+ OpenSSL::X509::Certificate.new get_tag[2..-1].pack('C*')
12
+ end
13
+
14
+ # Retrieves the certificate of the TEM's Manfacturer (CA).
15
+ def manufacturer_cert
16
+ Tem::CA.ca_cert
17
+ end
18
+
19
+ # Retrieves the TEM's Public Endorsement Key.
20
+ def pubek
21
+ 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
77
+ end