tem_ruby 0.9.0

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.
@@ -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