tem_ruby 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,81 @@
1
+ # Victor Costan:
2
+ # dropped because it wasn't hooked up to the rest of the code
3
+ # preserved to move all the features into the new ca.rb / ecert.rb
4
+
5
+ require 'tem_ruby'
6
+ require 'test/unit'
7
+ require 'openssl'
8
+
9
+ # Integration work by Victor Costan
10
+
11
+
12
+ #Author: Jorge de la Garza (MIT '08), mongoose08@alum.mit.edu
13
+ #This unit test does the following:
14
+ #1. Makes issuer's (manufacturer's) X.509 certificate, which is self-signed.
15
+ #2. Makes subject's (TEM's) X.509 certificate, which is signed with the issuers private key.
16
+ #3. Constructs the TEMTag from the subject's:
17
+ # -Serial number (4 bytes)
18
+ # -Not before date (4 bytes)
19
+ # -Not after date (4 bytes)
20
+ # -Modulus (256 bytes)
21
+ # -Public key exp (3 bytes)
22
+ # -Signature (256 bytes)
23
+ #4. Sets the TEMTag on the TEM
24
+ #5. Reads back the TEMTag
25
+ #6. Constructs a new X.509 certificate from the TEMTag and asserts that this is equal to the original certificate
26
+
27
+ class CertTest < Test::Unit::TestCase
28
+ def setup
29
+ @terminal = Tem::SCard::JCOPRemoteTerminal.new
30
+ unless @terminal.connect
31
+ @terminal.disconnect
32
+ @terminal = Tem::SCard::PCSCTerminal.new
33
+ @terminal.connect
34
+ end
35
+ @javacard = Tem::SCard::JavaCard.new(@terminal)
36
+ @tem = Tem::Session.new(@javacard)
37
+
38
+ @tem.kill
39
+ @tem.activate
40
+
41
+
42
+ end
43
+
44
+ def teardown
45
+ @terminal.disconnect unless @terminal.nil?
46
+ end
47
+
48
+ def test_cert
49
+ #Create issuer's (manufacturer's) certificate
50
+ issuer_key = OpenSSL::PKey::RSA.new 2048, 0x10001
51
+ issuer_cert = Tem::Cert.create_issuer_cert(issuer_key)
52
+
53
+ #Create subject's (TEM's) certificate
54
+ subject_key = OpenSSL::PKey::RSA.new 2048, 0x10001
55
+ subject_cert = Tem::Cert.create_subject_cert(subject_key, issuer_key, issuer_cert)
56
+
57
+ #Create the tag that will go on the TEM from it's certificate
58
+ written_tag = Tem::Cert.create_tag_from_cert(subject_cert)
59
+
60
+ #Set the tag on the TEM, assert that tag read = tag written
61
+ @tem.set_tag(written_tag)
62
+ read_tag = @tem.get_tag[2..-1] #chop off first two bytes, TEM puts firmware version on front of written tag
63
+ assert_equal written_tag, read_tag, 'error in posted tag data'
64
+
65
+ #Now reconstruct original certificate from tag data
66
+ read_cert = Tem::Cert.create_cert_from_tag(read_tag, issuer_cert)
67
+ read_cert.sign issuer_key, OpenSSL::Digest::SHA1.new
68
+
69
+ assert_equal Tem::Cert.extract_sig_from_cert(subject_cert), Tem::Cert.extract_sig_from_cert(read_cert), 'signatures do not match'
70
+ #If the signature of the original certificate matches the signature of the reconstructed certificate,
71
+ #we can be pretty much certain that the certificates are identical
72
+
73
+ #TODO: PROBLEM:
74
+ #There is no way to set the signature to a known value.
75
+ #The only way to set the signature is to sign the certificate, and only the issuer (manufacturer) can do this.
76
+ #This means that the manufacturer has to be contacted every time the user wants to verify the TEM's certificate,
77
+ #and this may not be practical.
78
+
79
+
80
+ end
81
+ end
@@ -0,0 +1,127 @@
1
+ require 'tem_ruby'
2
+ require 'test/unit'
3
+
4
+ class DriverTest < Test::Unit::TestCase
5
+ def setup
6
+ @terminal = Tem::SCard::JCOPRemoteTerminal.new
7
+ unless @terminal.connect
8
+ @terminal.disconnect
9
+ @terminal = Tem::SCard::PCSCTerminal.new
10
+ @terminal.connect
11
+ end
12
+ @javacard = Tem::SCard::JavaCard.new(@terminal)
13
+ @tem = Tem::Session.new(@javacard)
14
+
15
+ @tem.kill
16
+ @tem.activate
17
+ end
18
+
19
+ def teardown
20
+ @terminal.disconnect unless @terminal.nil?
21
+ end
22
+
23
+ def test_buffers_io
24
+ garbage = (1...569).map { |i| (i * i * 217 + i * 661 + 393) % 256 }
25
+
26
+ bid = @tem.post_buffer garbage
27
+ assert_equal garbage.length, @tem.get_buffer_length(bid), 'error in posted buffer length'
28
+ assert_equal garbage, @tem.read_buffer(bid), 'error in posted buffer data'
29
+
30
+ garbage.reverse!
31
+ @tem.write_buffer bid, garbage
32
+ assert_equal garbage, @tem.read_buffer(bid), 'error in (reverted) posted buffer data'
33
+ @tem.release_buffer bid
34
+
35
+ @tem.post_buffer [1]
36
+ @tem.post_buffer [2]
37
+ @tem.flush_buffers
38
+ assert_equal 0, @tem.stat_buffers[:buffers].reject { |b| b[:free] }.length, 'flush_buffers left allocated buffers'
39
+ end
40
+
41
+ def test_buffers_alloc
42
+ b_lengths = [569, 231, 455, 18, 499, 332, 47]
43
+ b_ids = b_lengths.map { |len| @tem.alloc_buffer(len) }
44
+ bstat = @tem.stat_buffers
45
+
46
+ assert bstat[:free], 'buffer stat does not contain free memory information'
47
+ assert bstat[:free][:persistent].kind_of?(Numeric), 'buffer stat does not show free persistent memory'
48
+ assert bstat[:free][:persistent] >= 0, 'buffer stat shows negative free persistent memory'
49
+ assert bstat[:free][:clear_on_reset].kind_of?(Numeric), 'buffer stat does not show free clear_on_reset memory'
50
+ assert bstat[:free][:clear_on_reset] >= 0, 'buffer stat shows negative free clear_on_reset memory'
51
+ assert bstat[:free][:clear_on_deselect].kind_of?(Numeric), 'buffer stat does not show free clear_on_deselect memory'
52
+ assert bstat[:free][:clear_on_deselect] >= 0, 'buffer stat shows negative free clear_on_deselect memory'
53
+
54
+ b_lengths.each_index do |i|
55
+ assert bstat[:buffers][b_ids[i]], "buffer stat does not show an entry for a #{b_lengths[i]}-bytes buffer"
56
+ assert bstat[:buffers][b_ids[i]][:type].kind_of?(Symbol), "buffer stat does not show the memory type for a #{b_lengths[i]}-bytes buffer"
57
+ assert_equal b_lengths[i], bstat[:buffers][b_ids[i]][:length], "bad length in buffer stat entry for a #{b_lengths[i]}-bytes buffer"
58
+ assert_equal false, bstat[:buffers][b_ids[i]][:pinned], "bad pinned flag in buffer stat entry for a #{b_lengths[i]}-bytes buffer"
59
+ end
60
+
61
+ b_ids.each { |bid| @tem.release_buffer(bid) }
62
+ end
63
+
64
+ def test_tag
65
+ garbage = (1...569).map { |i| (i * i * 217 + i * 661 + 393) % 256 }
66
+
67
+ assert_raise(RuntimeError, 'tag returned before being set') { @tem.get_tag }
68
+
69
+ @tem.set_tag(garbage)
70
+ assert_equal garbage, @tem.get_tag[2..-1], 'error in posted tag data'
71
+
72
+ fwver = @tem.tk_firmware_ver
73
+ assert fwver[:major].kind_of?(Numeric) && fwver[:minor].kind_of?(Numeric), 'error in tag-backed firmware version'
74
+ end
75
+
76
+ def test_crypto
77
+ garbage = (1...415).map { |i| (i * i * 217 + i * 661 + 393) % 256 }
78
+ key_pair = @tem.devchip_generate_key_pair
79
+ pubkey = @tem.devchip_save_key key_pair[:pubkey_id]
80
+
81
+ encrypted_garbage = @tem.devchip_encrypt garbage, key_pair[:privkey_id]
82
+ decrypted_garbage = pubkey.decrypt encrypted_garbage
83
+ assert_equal garbage, decrypted_garbage, 'priv-encryption+pub-decryption messed up the data'
84
+
85
+ encrypted_garbage = pubkey.encrypt garbage
86
+ decrypted_garbage = @tem.devchip_decrypt encrypted_garbage, key_pair[:privkey_id]
87
+ assert_equal garbage, decrypted_garbage, 'pub-encryption+priv-decryption messed up the data'
88
+
89
+ key_stat = @tem.stat_keys
90
+ assert key_stat[:keys], 'key stat does not contain key information'
91
+ assert_equal :public, key_stat[:keys][key_pair[:pubkey_id]][:type], 'key stat reports wrong type for public key'
92
+ assert_equal :private, key_stat[:keys][key_pair[:privkey_id]][:type], 'key stat reports wrong type for private key'
93
+ assert_in_delta 2, 2048, key_stat[:keys][key_pair[:pubkey_id]][:bits], 'key stat reports wrong size for public key'
94
+ assert_in_delta 2, 2048, key_stat[:keys][key_pair[:privkey_id]][:bits], 'key stat reports wrong size for private key'
95
+
96
+ [:pubkey_id, :privkey_id].each { |ki| @tem.devchip_release_key key_pair[ki] }
97
+ end
98
+
99
+ def test_crypto_abi
100
+ ekey = OpenSSL::PKey::RSA.generate(2048, 65537)
101
+ pubk = @tem.new_key_from_ssl ekey, true
102
+ privk = @tem.new_key_from_ssl ekey, false
103
+
104
+ # array and string encryption/decryption
105
+ garbage = (1...569).map { |i| (i * i * 217 + i * 661 + 393) % 256 }
106
+ [garbage, garbage.pack('C*')].each do |g|
107
+ encrypted_garbage = pubk.encrypt g
108
+ decrypted_garbage = privk.decrypt encrypted_garbage
109
+ assert_equal g, decrypted_garbage, 'pub-encryption+priv-decryption messed up the data'
110
+ encrypted_garbage = privk.encrypt g
111
+ decrypted_garbage = pubk.decrypt encrypted_garbage
112
+ assert_equal g, decrypted_garbage, 'priv-encryption+pub-decryption messed up the data'
113
+ end
114
+
115
+ # test key serialization/deserialization through encryption/decryption
116
+ pubk_ys = pubk.to_yaml_str
117
+ pubk2 = Tem::CryptoAbi::AsymmetricKey.new_from_yaml_str(pubk_ys)
118
+ privk_ys = privk.to_yaml_str
119
+ privk2 = Tem::CryptoAbi::AsymmetricKey.new_from_yaml_str(privk_ys)
120
+ encrypted_garbage = pubk.encrypt garbage
121
+ decrypted_garbage = privk2.decrypt encrypted_garbage
122
+ assert_equal garbage, decrypted_garbage, 'pub-encryption+priv-decryption messed up the data'
123
+ encrypted_garbage = privk.encrypt garbage
124
+ decrypted_garbage = pubk2.decrypt encrypted_garbage
125
+ assert_equal garbage, decrypted_garbage, 'priv-encryption+pub-decryption messed up the data'
126
+ end
127
+ end
@@ -0,0 +1,55 @@
1
+ require 'tem_ruby'
2
+ require 'test/unit'
3
+
4
+ class ExceptionsTest < Test::Unit::TestCase
5
+ def setup
6
+ @terminal = Tem::SCard::JCOPRemoteTerminal.new
7
+ unless @terminal.connect
8
+ @terminal.disconnect
9
+ @terminal = Tem::SCard::PCSCTerminal.new
10
+ @terminal.connect
11
+ end
12
+ @javacard = Tem::SCard::JavaCard.new(@terminal)
13
+ @tem = Tem::Session.new(@javacard)
14
+
15
+ @tem.kill
16
+ @tem.activate
17
+ end
18
+
19
+ def teardown
20
+ @terminal.disconnect unless @terminal.nil?
21
+ end
22
+
23
+ def test_trace
24
+ # test the exception handling mechanism
25
+ bad_sec = @tem.assemble { |s|
26
+ s.ldbc 2
27
+ s.outnew
28
+ s.ldbc 6
29
+ s.outw
30
+ # this exceeds the address space, so it should make the TEM die
31
+ s.ldwc 0x7fff
32
+ s.ldbv
33
+ s.label :bad_code
34
+ s.halt
35
+ s.label :stack
36
+ s.stack
37
+ s.extra 10
38
+ }
39
+ assert_raise(Tem::SecExecError) { @tem.execute bad_sec }
40
+
41
+ caught = false
42
+ begin
43
+ @tem.execute bad_sec
44
+ rescue Tem::SecExecError => e
45
+ caught = true
46
+ assert_equal Hash, e.trace.class, "TEM exception does not have a TEM trace"
47
+ assert_equal 2, e.trace[:out], "Bad output buffer position in TEM trace"
48
+ assert_equal bad_sec.label_address(:bad_code), e.trace[:ip], "Bad instruction pointer in TEM trace"
49
+ assert_equal bad_sec.label_address(:stack), e.trace[:sp], "Bad instruction pointer in TEM trace"
50
+ assert_equal Hash, e.buffer_state.class, "TEM exception does not have buffer state information"
51
+ assert_equal Hash, e.key_state.class, "TEM exception does not have key state information"
52
+ end
53
+ assert caught, "Executing a bad SECpack did not raise a SecExecError"
54
+ end
55
+ end