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.
- data/CHANGELOG +45 -0
- data/LICENSE +21 -0
- data/Manifest +75 -0
- data/README +8 -0
- data/Rakefile +23 -0
- data/bin/tem_bench +9 -0
- data/bin/tem_ca +13 -0
- data/bin/tem_irb +11 -0
- data/bin/tem_proxy +65 -0
- data/bin/tem_stat +35 -0
- data/dev_ca/ca_cert.cer +0 -0
- data/dev_ca/ca_cert.pem +32 -0
- data/dev_ca/ca_key.pem +27 -0
- data/dev_ca/config.yml +14 -0
- data/lib/tem/_cert.rb +158 -0
- data/lib/tem/apdus/buffers.rb +89 -0
- data/lib/tem/apdus/keys.rb +64 -0
- data/lib/tem/apdus/lifecycle.rb +13 -0
- data/lib/tem/apdus/tag.rb +38 -0
- data/lib/tem/auto_conf.rb +25 -0
- data/lib/tem/builders/abi.rb +482 -0
- data/lib/tem/builders/assembler.rb +314 -0
- data/lib/tem/builders/crypto.rb +124 -0
- data/lib/tem/builders/isa.rb +120 -0
- data/lib/tem/ca.rb +114 -0
- data/lib/tem/definitions/abi.rb +65 -0
- data/lib/tem/definitions/assembler.rb +23 -0
- data/lib/tem/definitions/isa.rb +188 -0
- data/lib/tem/ecert.rb +77 -0
- data/lib/tem/hive.rb +18 -0
- data/lib/tem/keys/asymmetric.rb +116 -0
- data/lib/tem/keys/key.rb +48 -0
- data/lib/tem/keys/symmetric.rb +47 -0
- data/lib/tem/sec_exec_error.rb +63 -0
- data/lib/tem/seclosures.rb +81 -0
- data/lib/tem/secpack.rb +107 -0
- data/lib/tem/tem.rb +31 -0
- data/lib/tem/toolkit.rb +101 -0
- data/lib/tem/transport/auto_configurator.rb +87 -0
- data/lib/tem/transport/java_card_mixin.rb +99 -0
- data/lib/tem/transport/jcop_remote_protocol.rb +59 -0
- data/lib/tem/transport/jcop_remote_server.rb +171 -0
- data/lib/tem/transport/jcop_remote_transport.rb +65 -0
- data/lib/tem/transport/pcsc_transport.rb +87 -0
- data/lib/tem/transport/transport.rb +10 -0
- data/lib/tem_ruby.rb +47 -0
- data/tem_ruby.gemspec +35 -0
- data/test/_test_cert.rb +70 -0
- data/test/builders/test_abi_builder.rb +298 -0
- data/test/tem_test_case.rb +26 -0
- data/test/tem_unit/test_tem_alu.rb +33 -0
- data/test/tem_unit/test_tem_bound_secpack.rb +51 -0
- data/test/tem_unit/test_tem_branching.rb +56 -0
- data/test/tem_unit/test_tem_crypto_asymmetric.rb +123 -0
- data/test/tem_unit/test_tem_crypto_hash.rb +35 -0
- data/test/tem_unit/test_tem_crypto_pstore.rb +53 -0
- data/test/tem_unit/test_tem_crypto_random.rb +25 -0
- data/test/tem_unit/test_tem_emit.rb +23 -0
- data/test/tem_unit/test_tem_memory.rb +48 -0
- data/test/tem_unit/test_tem_memory_compare.rb +65 -0
- data/test/tem_unit/test_tem_output.rb +32 -0
- data/test/tem_unit/test_tem_yaml_secpack.rb +47 -0
- data/test/test_driver.rb +108 -0
- data/test/test_exceptions.rb +35 -0
- data/test/transport/test_auto_configurator.rb +114 -0
- data/test/transport/test_java_card_mixin.rb +90 -0
- data/test/transport/test_jcop_remote.rb +82 -0
- data/timings/blank_bound_secpack.rb +18 -0
- data/timings/blank_sec.rb +14 -0
- data/timings/devchip_decrypt.rb +9 -0
- data/timings/post_buffer.rb +10 -0
- data/timings/simple_apdu.rb +5 -0
- data/timings/timings.rb +64 -0
- data/timings/vm_perf.rb +140 -0
- data/timings/vm_perf_bound.rb +141 -0
- metadata +201 -0
@@ -0,0 +1,65 @@
|
|
1
|
+
require 'socket'
|
2
|
+
|
3
|
+
# :nodoc: namespace
|
4
|
+
module Tem::Transport
|
5
|
+
|
6
|
+
# Implements the transport layer for a JCOP simulator instance.
|
7
|
+
class JcopRemoteTransport
|
8
|
+
include JavaCardMixin
|
9
|
+
include JcopRemoteProtocol
|
10
|
+
|
11
|
+
# Creates a new unconnected transport for a JCOP simulator serving TCP/IP.
|
12
|
+
#
|
13
|
+
# The options parameter must have the following keys:
|
14
|
+
# host:: the DNS name or IP of the host running the JCOP simulator
|
15
|
+
# port:: the TCP/IP port of the JCOP simulator server
|
16
|
+
def initialize(options)
|
17
|
+
@host, @port = options[:host], options[:port]
|
18
|
+
@socket = nil
|
19
|
+
end
|
20
|
+
|
21
|
+
#
|
22
|
+
def exchange_apdu(apdu)
|
23
|
+
send_message @socket, :type => 1, :node => 0, :data => apdu
|
24
|
+
recv_message(@socket)[:data]
|
25
|
+
end
|
26
|
+
|
27
|
+
# Makes a transport-level connection to the TEM.
|
28
|
+
def connect
|
29
|
+
begin
|
30
|
+
Socket.getaddrinfo(@host, @port, Socket::AF_INET,
|
31
|
+
Socket::SOCK_STREAM).each do |addr_info|
|
32
|
+
begin
|
33
|
+
@socket = Socket.new(addr_info[4], addr_info[5], addr_info[6])
|
34
|
+
@socket.connect Socket.pack_sockaddr_in(addr_info[1], addr_info[3])
|
35
|
+
break
|
36
|
+
rescue
|
37
|
+
@socket = nil
|
38
|
+
end
|
39
|
+
end
|
40
|
+
raise 'Connection refused' unless @socket
|
41
|
+
|
42
|
+
# Wait for the card to be inserted.
|
43
|
+
send_message @socket, :type => 0, :node => 0, :data => [0, 1, 0, 0]
|
44
|
+
recv_message @socket # ATR should come here, but who cares
|
45
|
+
rescue Exception
|
46
|
+
@socket = nil
|
47
|
+
raise
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
# Breaks down the transport-level connection to the TEM.
|
52
|
+
def disconnect
|
53
|
+
if @socket
|
54
|
+
@socket.close
|
55
|
+
@socket = nil
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
def to_s
|
60
|
+
"#<JCOP Remote Terminal: disconnected>" if @socket.nil?
|
61
|
+
"#<JCOP Remote Terminal: #{@host}:#{@port}>"
|
62
|
+
end
|
63
|
+
end # class JcopRemoteTransport
|
64
|
+
|
65
|
+
end # module Tem::Transport
|
@@ -0,0 +1,87 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'smartcard'
|
3
|
+
|
4
|
+
# :nodoc: namespace
|
5
|
+
module Tem::Transport
|
6
|
+
|
7
|
+
class PcscTransport
|
8
|
+
include JavaCardMixin
|
9
|
+
PCSC = Smartcard::PCSC
|
10
|
+
|
11
|
+
def initialize(options)
|
12
|
+
@options = options
|
13
|
+
@context = nil
|
14
|
+
@card = nil
|
15
|
+
end
|
16
|
+
|
17
|
+
def exchange_apdu(apdu)
|
18
|
+
xmit_apdu_string = apdu.pack('C*')
|
19
|
+
result_string = @card.transmit xmit_apdu_string, @xmit_ioreq, @recv_ioreq
|
20
|
+
return result_string.unpack('C*')
|
21
|
+
end
|
22
|
+
|
23
|
+
def connect
|
24
|
+
@context = PCSC::Context.new(PCSC::SCOPE_SYSTEM) if @context.nil?
|
25
|
+
|
26
|
+
if @options[:reader_name]
|
27
|
+
@reader_name = reader_name
|
28
|
+
else
|
29
|
+
# get the first reader
|
30
|
+
readers = @context.list_readers nil
|
31
|
+
@reader_name = readers[@options[:reader_index] || 0]
|
32
|
+
end
|
33
|
+
|
34
|
+
# get the reader's status
|
35
|
+
reader_states = PCSC::ReaderStates.new(1)
|
36
|
+
reader_states.set_reader_name_of!(0, @reader_name)
|
37
|
+
reader_states.set_current_state_of!(0, PCSC::STATE_UNKNOWN)
|
38
|
+
@context.get_status_change reader_states, 100
|
39
|
+
reader_states.acknowledge_events!
|
40
|
+
|
41
|
+
# prompt for card insertion unless that already happened
|
42
|
+
if (reader_states.current_state_of(0) & PCSC::STATE_PRESENT) == 0
|
43
|
+
puts "Please insert TEM card in reader #{@reader_name}\n"
|
44
|
+
while (reader_states.current_state_of(0) & PCSC::STATE_PRESENT) == 0 do
|
45
|
+
@context.get_status_change reader_states, PCSC::INFINITE_TIMEOUT
|
46
|
+
reader_states.acknowledge_events!
|
47
|
+
end
|
48
|
+
puts "Card detected\n"
|
49
|
+
end
|
50
|
+
|
51
|
+
# connect to card
|
52
|
+
@card = PCSC::Card.new @context, @reader_name, PCSC::SHARE_EXCLUSIVE,
|
53
|
+
PCSC::PROTOCOL_ANY
|
54
|
+
|
55
|
+
# build the transmit / receive IoRequests
|
56
|
+
status = @card.status
|
57
|
+
@xmit_ioreq = @@xmit_iorequest[status[:protocol]]
|
58
|
+
if RUBY_PLATFORM =~ /win/ and (not RUBY_PLATFORM =~ /darwin/)
|
59
|
+
@recv_ioreq = nil
|
60
|
+
else
|
61
|
+
@recv_ioreq = PCSC::IoRequest.new
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
def disconnect
|
66
|
+
unless @card.nil?
|
67
|
+
@card.disconnect PCSC::DISPOSITION_LEAVE
|
68
|
+
@card = nil
|
69
|
+
end
|
70
|
+
unless @context.nil?
|
71
|
+
@context.release
|
72
|
+
@context = nil
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
def to_s
|
77
|
+
"#<PC/SC Terminal: disconnected>" if @card.nil?
|
78
|
+
"#<PC/SC Terminal: #{@reader_name}>"
|
79
|
+
end
|
80
|
+
|
81
|
+
@@xmit_iorequest = {
|
82
|
+
Smartcard::PCSC::PROTOCOL_T0 => Smartcard::PCSC::IOREQUEST_T0,
|
83
|
+
Smartcard::PCSC::PROTOCOL_T1 => Smartcard::PCSC::IOREQUEST_T1,
|
84
|
+
}
|
85
|
+
end # class PcscTransport
|
86
|
+
|
87
|
+
end # module Tem::Transport
|
@@ -0,0 +1,10 @@
|
|
1
|
+
# The transport module contains classes responsible for transferring low-level
|
2
|
+
# commands issed by the high-level TEM methods to actual TEMs, which can be
|
3
|
+
# connected to the system in various ways.
|
4
|
+
module Tem::Transport
|
5
|
+
|
6
|
+
# Shortcut for Tem::Transport::AutoConfigurator#auto_transport
|
7
|
+
def self.auto_transport
|
8
|
+
Tem::Transport::AutoConfigurator.auto_transport
|
9
|
+
end
|
10
|
+
end
|
data/lib/tem_ruby.rb
ADDED
@@ -0,0 +1,47 @@
|
|
1
|
+
# gems
|
2
|
+
require 'rubygems'
|
3
|
+
require 'smartcard'
|
4
|
+
|
5
|
+
# :nodoc:
|
6
|
+
module Tem
|
7
|
+
end
|
8
|
+
|
9
|
+
# :nodoc:
|
10
|
+
module Tem::Transport
|
11
|
+
end
|
12
|
+
|
13
|
+
require 'tem/transport/transport.rb'
|
14
|
+
require 'tem/transport/java_card_mixin.rb'
|
15
|
+
require 'tem/transport/pcsc_transport.rb'
|
16
|
+
require 'tem/transport/jcop_remote_protocol.rb'
|
17
|
+
require 'tem/transport/jcop_remote_transport.rb'
|
18
|
+
require 'tem/transport/jcop_remote_server.rb'
|
19
|
+
require 'tem/transport/auto_configurator.rb'
|
20
|
+
|
21
|
+
require 'tem/keys/key.rb'
|
22
|
+
require 'tem/keys/asymmetric.rb'
|
23
|
+
require 'tem/keys/symmetric.rb'
|
24
|
+
|
25
|
+
require 'tem/builders/abi.rb'
|
26
|
+
require 'tem/builders/assembler.rb'
|
27
|
+
require 'tem/builders/crypto.rb'
|
28
|
+
require 'tem/builders/isa.rb'
|
29
|
+
|
30
|
+
require 'tem/definitions/abi.rb'
|
31
|
+
require 'tem/definitions/isa.rb'
|
32
|
+
require 'tem/definitions/assembler.rb'
|
33
|
+
|
34
|
+
require 'tem/auto_conf.rb'
|
35
|
+
require 'tem/apdus/buffers.rb'
|
36
|
+
require 'tem/apdus/keys.rb'
|
37
|
+
require 'tem/apdus/lifecycle.rb'
|
38
|
+
require 'tem/apdus/tag.rb'
|
39
|
+
|
40
|
+
require 'tem/ca.rb'
|
41
|
+
require 'tem/ecert.rb'
|
42
|
+
require 'tem/hive.rb'
|
43
|
+
require 'tem/sec_exec_error.rb'
|
44
|
+
require 'tem/seclosures.rb'
|
45
|
+
require 'tem/secpack.rb'
|
46
|
+
require 'tem/toolkit.rb'
|
47
|
+
require 'tem/tem.rb'
|
data/tem_ruby.gemspec
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
Gem::Specification.new do |s|
|
4
|
+
s.name = %q{tem_ruby}
|
5
|
+
s.version = "0.10.2"
|
6
|
+
|
7
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 1.2") if s.respond_to? :required_rubygems_version=
|
8
|
+
s.authors = ["Victor Costan"]
|
9
|
+
s.date = %q{2009-05-31}
|
10
|
+
s.description = %q{TEM (Trusted Execution Module) driver, written in and for ruby.}
|
11
|
+
s.email = %q{victor@costan.us}
|
12
|
+
s.executables = ["tem_bench", "tem_ca", "tem_irb", "tem_proxy", "tem_stat"]
|
13
|
+
s.extra_rdoc_files = ["bin/tem_bench", "bin/tem_ca", "bin/tem_irb", "bin/tem_proxy", "bin/tem_stat", "CHANGELOG", "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/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/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/transport/auto_configurator.rb", "lib/tem/transport/java_card_mixin.rb", "lib/tem/transport/jcop_remote_protocol.rb", "lib/tem/transport/jcop_remote_server.rb", "lib/tem/transport/jcop_remote_transport.rb", "lib/tem/transport/pcsc_transport.rb", "lib/tem/transport/transport.rb", "lib/tem_ruby.rb", "LICENSE", "README"]
|
14
|
+
s.files = ["bin/tem_bench", "bin/tem_ca", "bin/tem_irb", "bin/tem_proxy", "bin/tem_stat", "CHANGELOG", "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/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/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/transport/auto_configurator.rb", "lib/tem/transport/java_card_mixin.rb", "lib/tem/transport/jcop_remote_protocol.rb", "lib/tem/transport/jcop_remote_server.rb", "lib/tem/transport/jcop_remote_transport.rb", "lib/tem/transport/pcsc_transport.rb", "lib/tem/transport/transport.rb", "lib/tem_ruby.rb", "LICENSE", "Manifest", "Rakefile", "README", "tem_ruby.gemspec", "test/_test_cert.rb", "test/builders/test_abi_builder.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_asymmetric.rb", "test/tem_unit/test_tem_crypto_hash.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_driver.rb", "test/test_exceptions.rb", "test/transport/test_auto_configurator.rb", "test/transport/test_java_card_mixin.rb", "test/transport/test_jcop_remote.rb", "timings/blank_bound_secpack.rb", "timings/blank_sec.rb", "timings/devchip_decrypt.rb", "timings/post_buffer.rb", "timings/simple_apdu.rb", "timings/timings.rb", "timings/vm_perf.rb", "timings/vm_perf_bound.rb"]
|
15
|
+
s.homepage = %q{http://tem.rubyforge.org}
|
16
|
+
s.rdoc_options = ["--line-numbers", "--inline-source", "--title", "Tem_ruby", "--main", "README"]
|
17
|
+
s.require_paths = ["lib"]
|
18
|
+
s.rubyforge_project = %q{tem}
|
19
|
+
s.rubygems_version = %q{1.3.3}
|
20
|
+
s.summary = %q{TEM (Trusted Execution Module) driver, written in and for ruby.}
|
21
|
+
s.test_files = ["test/builders/test_abi_builder.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_asymmetric.rb", "test/tem_unit/test_tem_crypto_hash.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_driver.rb", "test/test_exceptions.rb", "test/transport/test_auto_configurator.rb", "test/transport/test_java_card_mixin.rb", "test/transport/test_jcop_remote.rb"]
|
22
|
+
|
23
|
+
if s.respond_to? :specification_version then
|
24
|
+
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
25
|
+
s.specification_version = 3
|
26
|
+
|
27
|
+
if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
|
28
|
+
s.add_runtime_dependency(%q<smartcard>, [">= 0.3.0"])
|
29
|
+
else
|
30
|
+
s.add_dependency(%q<smartcard>, [">= 0.3.0"])
|
31
|
+
end
|
32
|
+
else
|
33
|
+
s.add_dependency(%q<smartcard>, [">= 0.3.0"])
|
34
|
+
end
|
35
|
+
end
|
data/test/_test_cert.rb
ADDED
@@ -0,0 +1,70 @@
|
|
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
|
+
@tem = Tem.auto_tem
|
30
|
+
|
31
|
+
@tem.kill
|
32
|
+
@tem.activate
|
33
|
+
end
|
34
|
+
|
35
|
+
def teardown
|
36
|
+
@tem.disconnect unless @tem.nil?
|
37
|
+
end
|
38
|
+
|
39
|
+
def test_cert
|
40
|
+
#Create issuer's (manufacturer's) certificate
|
41
|
+
issuer_key = OpenSSL::PKey::RSA.new 2048, 0x10001
|
42
|
+
issuer_cert = Tem::Cert.create_issuer_cert(issuer_key)
|
43
|
+
|
44
|
+
#Create subject's (TEM's) certificate
|
45
|
+
subject_key = OpenSSL::PKey::RSA.new 2048, 0x10001
|
46
|
+
subject_cert = Tem::Cert.create_subject_cert(subject_key, issuer_key, issuer_cert)
|
47
|
+
|
48
|
+
#Create the tag that will go on the TEM from it's certificate
|
49
|
+
written_tag = Tem::Cert.create_tag_from_cert(subject_cert)
|
50
|
+
|
51
|
+
#Set the tag on the TEM, assert that tag read = tag written
|
52
|
+
@tem.set_tag(written_tag)
|
53
|
+
read_tag = @tem.get_tag[2..-1] #chop off first two bytes, TEM puts firmware version on front of written tag
|
54
|
+
assert_equal written_tag, read_tag, 'error in posted tag data'
|
55
|
+
|
56
|
+
#Now reconstruct original certificate from tag data
|
57
|
+
read_cert = Tem::Cert.create_cert_from_tag(read_tag, issuer_cert)
|
58
|
+
read_cert.sign issuer_key, OpenSSL::Digest::SHA1.new
|
59
|
+
|
60
|
+
assert_equal Tem::Cert.extract_sig_from_cert(subject_cert), Tem::Cert.extract_sig_from_cert(read_cert), 'signatures do not match'
|
61
|
+
#If the signature of the original certificate matches the signature of the reconstructed certificate,
|
62
|
+
#we can be pretty much certain that the certificates are identical
|
63
|
+
|
64
|
+
#TODO: PROBLEM:
|
65
|
+
#There is no way to set the signature to a known value.
|
66
|
+
#The only way to set the signature is to sign the certificate, and only the issuer (manufacturer) can do this.
|
67
|
+
#This means that the manufacturer has to be contacted every time the user wants to verify the TEM's certificate,
|
68
|
+
#and this may not be practical.
|
69
|
+
end
|
70
|
+
end
|
@@ -0,0 +1,298 @@
|
|
1
|
+
require 'openssl'
|
2
|
+
require 'test/unit'
|
3
|
+
|
4
|
+
require 'tem_ruby'
|
5
|
+
|
6
|
+
class AbiBuilderTest < Test::Unit::TestCase
|
7
|
+
class Wrapped
|
8
|
+
attr_accessor :p, :q, :n
|
9
|
+
attr_accessor :d # Derived value.
|
10
|
+
attr_accessor :c # Constructor value.
|
11
|
+
|
12
|
+
def initialize(ctor_value = 'ctor default')
|
13
|
+
self.c = ctor_value
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
class Multi
|
18
|
+
attr_accessor :p, :q, :n
|
19
|
+
attr_accessor :a, :b, :c
|
20
|
+
attr_accessor :str, :const
|
21
|
+
end
|
22
|
+
|
23
|
+
module Abi
|
24
|
+
Tem::Builders::Abi.define_abi self do |abi|
|
25
|
+
abi.fixed_length_number :byte, 1, :signed => true
|
26
|
+
abi.fixed_length_number :ubyte, 1, :signed => false
|
27
|
+
|
28
|
+
abi.fixed_length_number :word, 2, :signed => true, :big_endian => false
|
29
|
+
abi.fixed_length_number :netword, 2, :signed => true, :big_endian => true
|
30
|
+
|
31
|
+
abi.fixed_length_number :dword, 4, :signed => true, :big_endian => true
|
32
|
+
abi.fixed_length_number :udword, 4, :signed => false, :big_endian => false
|
33
|
+
|
34
|
+
abi.variable_length_number :vln, :word, :signed => false,
|
35
|
+
:big_endian => false
|
36
|
+
abi.variable_length_number :net_vln, :netword, :signed => false,
|
37
|
+
:big_endian => true
|
38
|
+
abi.packed_variable_length_numbers :packed, :word, [:p, :q, :n],
|
39
|
+
:signed => false,
|
40
|
+
:big_endian => false
|
41
|
+
abi.packed_variable_length_numbers :net_packed, :netword,
|
42
|
+
[:x, :y, :z, :a],
|
43
|
+
:signed => false,
|
44
|
+
:big_endian => true
|
45
|
+
abi.fixed_length_string :mac_id, 6
|
46
|
+
abi.object_wrapper :wrapped_raw, Wrapped, [:packed, nil]
|
47
|
+
abi.object_wrapper :wrapped, Wrapped, [:packed, nil],
|
48
|
+
:to => lambda { |o| w = Wrapped.new
|
49
|
+
w.p, w.q, w.n = o.p, o.q, o.n * 100
|
50
|
+
w },
|
51
|
+
:read => lambda { |o| w = Wrapped.new(o.c); w.d = o.p * o.q; w },
|
52
|
+
:new => lambda { |klass| klass.new('hook-new') }
|
53
|
+
abi.object_wrapper :multi, Multi,
|
54
|
+
[:packed, nil,:packed, { :p => :a, :q => :b, :n => :c},
|
55
|
+
:mac_id, :str, 'constant string', :const]
|
56
|
+
|
57
|
+
abi.conditional_wrapper :conditional, 2,
|
58
|
+
[{:tag => [0x59, 0xAF], :class => String, :type => :mac_id},
|
59
|
+
{:tag => [0x59, 0xAC], :class => Integer, :type => :net_vln,
|
60
|
+
:predicate => lambda { |n| n % 2 == 1 } },
|
61
|
+
{:tag => [0x59, 0xAD], :type => :dword,
|
62
|
+
:predicate => lambda { |n| n % 3 == 1 } }]
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def setup
|
67
|
+
@garbage = [0xFD, 0xFC, 0xFD, 0xFC, 0xFD] * 5
|
68
|
+
end
|
69
|
+
|
70
|
+
def test_fixed_and_variable_length_number_encoding
|
71
|
+
[
|
72
|
+
[:byte, 0, [0]], [:byte, 127, [127]],
|
73
|
+
[:byte, -1, [255]], [:byte, -127, [129]], [:byte, -128, [128]],
|
74
|
+
[:byte, 128, nil], [:byte, -129, nil],
|
75
|
+
|
76
|
+
[:word, 0, [0, 0]], [:word, 127, [127, 0]], [:word, 128, [128, 0]],
|
77
|
+
[:word, 256, [0, 1]], [:word, 32767, [255, 127]],
|
78
|
+
[:word, -1, [255, 255]], [:word, -127, [129, 255]],
|
79
|
+
[:word, -128, [128, 255]], [:word, -256, [0, 255]],
|
80
|
+
[:word, -32767, [1, 128], [:word, -32768, [0, 128]]],
|
81
|
+
[:word, 32768, nil], [:byte, -32769, nil],
|
82
|
+
|
83
|
+
[:netword, 0, [0, 0]], [:netword, 127, [0, 127]],
|
84
|
+
[:netword, 128, [0, 128]],
|
85
|
+
[:netword, 256, [1, 0]], [:netword, 32767, [127, 255]],
|
86
|
+
[:netword, -1, [255, 255]], [:netword, -127, [255, 129]],
|
87
|
+
[:netword, -128, [255, 128]], [:netword, -256, [255, 0]],
|
88
|
+
[:netword, -32767, [128, 1], [:netword, -32768, [128, 0]]],
|
89
|
+
[:netword, 32768, nil], [:netword, -32769, nil],
|
90
|
+
|
91
|
+
[:dword, 0x12345678, [0x12, 0x34, 0x56, 0x78]],
|
92
|
+
[:udword, 0x12345678, [0x78, 0x56, 0x34, 0x12]],
|
93
|
+
[:udword, 0xFFFFFFFF, [255, 255, 255, 255]],
|
94
|
+
[:udword, 0xFFFFFFFE, [254, 255, 255, 255]],
|
95
|
+
|
96
|
+
[:vln, 0, [0x01, 0x00, 0x00]], [:vln, 1, [0x01, 0x00, 0x01]],
|
97
|
+
[:vln, 256, [0x02, 0x00, 0x00, 0x01]],
|
98
|
+
[:vln, 65537, [0x03, 0x00, 0x01, 0x00, 0x01]],
|
99
|
+
[:vln, 0x12345678, [0x04, 0x00, 0x78, 0x56, 0x34, 0x12]],
|
100
|
+
[:vln, 0xFFFFFFFF, [0x04, 0x00, 255, 255, 255, 255]],
|
101
|
+
[:vln, 0xFFFFFFFE, [0x04, 0x00, 254, 255, 255, 255]],
|
102
|
+
|
103
|
+
[:net_vln, 0, [0x00, 0x01, 0x00]], [:net_vln, 1, [0x00, 0x01, 0x01]],
|
104
|
+
[:net_vln, 256, [0x00, 0x02, 0x01, 0x00]],
|
105
|
+
[:net_vln, 65537, [0x00, 0x03, 0x01, 0x00, 0x01]],
|
106
|
+
[:net_vln, 0x12345678, [0x00, 0x04, 0x12, 0x34, 0x56, 0x78]],
|
107
|
+
[:net_vln, 0xFFFFFFFF, [0x00, 0x04, 255, 255, 255, 255]],
|
108
|
+
[:net_vln, 0xFFFFFFFE, [0x00, 0x04, 255, 255, 255, 254]],
|
109
|
+
].each do |test_line|
|
110
|
+
type, number, array = *test_line
|
111
|
+
if array
|
112
|
+
assert_equal array, Abi.send(:"to_#{type}", number),
|
113
|
+
"#{type} failed on Ruby number -> array"
|
114
|
+
assert_equal array, Abi.send(:"to_#{type}",
|
115
|
+
OpenSSL::BN.new(number.to_s)),
|
116
|
+
"#{type} failed on OpenSSL number -> array"
|
117
|
+
assert_equal number, Abi.send(:"read_#{type}", @garbage + array,
|
118
|
+
@garbage.length)
|
119
|
+
if Abi.respond_to? :"#{type}_length"
|
120
|
+
assert_equal array.length, Abi.send(:"#{type}_length"),
|
121
|
+
"#{type} failed on length"
|
122
|
+
elsif Abi.respond_to? :"read_#{type}_length"
|
123
|
+
assert_equal array.length,
|
124
|
+
Abi.send(:"read_#{type}_length", @garbage + array,
|
125
|
+
@garbage.length),
|
126
|
+
"#{type} failed on read_#{type}_length"
|
127
|
+
else
|
128
|
+
flunk "#{type} does not provide _length or read_#{type}_length"
|
129
|
+
end
|
130
|
+
else
|
131
|
+
assert_raise RuntimeError do
|
132
|
+
assert_equal array, Abi.send(:"to_#{type}", number)
|
133
|
+
end
|
134
|
+
assert_raise RuntimeError do
|
135
|
+
assert_equal array, Abi.send(:"to_#{type}",
|
136
|
+
OpenSSL::BN.new(number.to_s))
|
137
|
+
end
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
assert_equal [255, 255, 255, 255], Abi.signed_to_udword(-1),
|
142
|
+
'Failed on signed_to_udword'
|
143
|
+
end
|
144
|
+
|
145
|
+
def test_packed_number_encoding
|
146
|
+
packed = { :p => 0x123, :q => 0xABCDEF, :n => 5 }
|
147
|
+
gold_packed = [0x02, 0x00, 0x03, 0x00, 0x01, 0x00, 0x23, 0x01, 0xEF, 0xCD,
|
148
|
+
0xAB, 0x05]
|
149
|
+
assert_equal gold_packed, Abi.to_packed(packed), 'packed'
|
150
|
+
assert_equal packed, Abi.read_packed(@garbage + gold_packed,
|
151
|
+
@garbage.length), 'packed'
|
152
|
+
assert_equal gold_packed.length,
|
153
|
+
Abi.read_packed_length(@garbage + gold_packed,
|
154
|
+
@garbage.length),
|
155
|
+
'read_packed_length'
|
156
|
+
|
157
|
+
net_packed = { :x => 0x271, :y => 0x314159, :z => 0, :a => 0x5AA5 }
|
158
|
+
gold_net_packed = [0x00, 0x02, 0x00, 0x03, 0x00, 0x01, 0x00, 0x02,
|
159
|
+
0x02, 0x71, 0x31, 0x41, 0x59, 0x00, 0x5A, 0xA5 ]
|
160
|
+
assert_equal gold_net_packed, Abi.to_net_packed(net_packed), 'net-packed'
|
161
|
+
assert_equal net_packed, Abi.read_net_packed(@garbage + gold_net_packed,
|
162
|
+
@garbage.length),
|
163
|
+
'net_packed'
|
164
|
+
assert_equal gold_net_packed.length,
|
165
|
+
Abi.read_net_packed_length(@garbage + gold_net_packed,
|
166
|
+
@garbage.length),
|
167
|
+
'read_net_packed_length'
|
168
|
+
components = Abi.net_packed_components
|
169
|
+
assert_equal [:x, :y, :z, :a], components,
|
170
|
+
'incorrect result from _components'
|
171
|
+
assert_raise TypeError, '_components result is mutable' do
|
172
|
+
components[0] = :w
|
173
|
+
end
|
174
|
+
end
|
175
|
+
|
176
|
+
def test_fixed_length_string_encoding
|
177
|
+
[
|
178
|
+
[:mac_id, "abcdef", nil, [?a, ?b, ?c, ?d, ?e, ?f]],
|
179
|
+
[:mac_id, "abc", "abc\0\0\0", [?a, ?b, ?c, 0, 0, 0]],
|
180
|
+
[:mac_id, "", "\0\0\0\0\0\0", [0, 0, 0, 0, 0, 0]],
|
181
|
+
[:mac_id, "abcdefg", nil, nil],
|
182
|
+
[:mac_id, [?a, ?b, ?c, ?d, ?e, ?f], "abcdef", [?a, ?b, ?c, ?d, ?e, ?f]],
|
183
|
+
[:mac_id, [?a, ?b, ?c], "abc\0\0\0", [?a, ?b, ?c, 0, 0, 0]],
|
184
|
+
[:mac_id, [], "\0\0\0\0\0\0", [0, 0, 0, 0, 0, 0]],
|
185
|
+
[:mac_id, [?a, ?b, ?c, ?d, ?e, ?f, ?g], nil, nil],
|
186
|
+
].each do |line|
|
187
|
+
type, source, string, array = *line
|
188
|
+
string ||= source
|
189
|
+
if array
|
190
|
+
assert_equal array, Abi.send(:"to_#{type}", source),
|
191
|
+
"#{type} failed on string -> array"
|
192
|
+
assert_equal string, Abi.send(:"read_#{type}", @garbage + array,
|
193
|
+
@garbage.length)
|
194
|
+
else
|
195
|
+
assert_raise RuntimeError do
|
196
|
+
assert_equal array, Abi.send(:"to_#{type}", source)
|
197
|
+
end
|
198
|
+
end
|
199
|
+
end
|
200
|
+
end
|
201
|
+
|
202
|
+
def test_object_wrapper_directs
|
203
|
+
packed = { :p => 2301, :q => 4141, :n => 60 }
|
204
|
+
gold_packed = Abi.to_packed packed
|
205
|
+
wrapped = Abi.read_wrapped_raw @garbage + gold_packed, @garbage.length
|
206
|
+
assert_equal Wrapped, wrapped.class,
|
207
|
+
'Reading wrapped object instantiated wrong class'
|
208
|
+
assert_equal [packed[:p], packed[:q], packed[:n], nil, 'ctor default'],
|
209
|
+
[wrapped.p, wrapped.q, wrapped.n, wrapped.d, wrapped.c],
|
210
|
+
'Reading wrapped object gave wrong attributes'
|
211
|
+
assert_equal gold_packed.length,
|
212
|
+
Abi.read_wrapped_raw_length(@garbage + gold_packed,
|
213
|
+
@garbage.length),
|
214
|
+
'Reading wrapped object length'
|
215
|
+
assert_equal gold_packed, Abi.to_wrapped_raw(wrapped),
|
216
|
+
'Wrapped object -> array'
|
217
|
+
end
|
218
|
+
|
219
|
+
def test_object_wrapper_schema
|
220
|
+
packed = { :p => 2301, :q => 4141, :n => 60 }
|
221
|
+
xpacked = { :p => 6996, :q => 1331, :n => 22 }
|
222
|
+
gold_multi = Abi.to_packed(packed) + Abi.to_packed(xpacked) +
|
223
|
+
Abi.to_mac_id("abc")
|
224
|
+
multi = Abi.read_multi @garbage + gold_multi, @garbage.length
|
225
|
+
assert_equal Multi, multi.class,
|
226
|
+
'Reading wrapped object instantiated wrong class'
|
227
|
+
assert_equal [packed[:p], packed[:q], packed[:n],
|
228
|
+
xpacked[:p], xpacked[:q], xpacked[:n], "abc\0\0\0",
|
229
|
+
"constant string"],
|
230
|
+
[multi.p, multi.q, multi.n, multi.a, multi.b, multi.c,
|
231
|
+
multi.str, multi.const],
|
232
|
+
'Reading wrapped object gave wrong attributes'
|
233
|
+
assert_equal gold_multi, Abi.to_multi(multi),
|
234
|
+
'Wrapped object -> array'
|
235
|
+
assert_equal gold_multi.length,
|
236
|
+
Abi.read_multi_length(@garbage + gold_multi, @garbage.length),
|
237
|
+
'Reading wrapped object length'
|
238
|
+
end
|
239
|
+
|
240
|
+
def test_object_wrapper_hooks
|
241
|
+
packed = { :p => 2301, :q => 4141, :n => 60 }
|
242
|
+
gold_packed = Abi.to_packed packed
|
243
|
+
wrapped = Abi.read_wrapped @garbage + gold_packed, @garbage.length
|
244
|
+
assert_equal Wrapped, wrapped.class,
|
245
|
+
'Reading wrapped object instantiated wrong class'
|
246
|
+
assert_equal [nil, nil, nil, packed[:p] * packed[:q], 'hook-new'],
|
247
|
+
[wrapped.p, wrapped.q, wrapped.n, wrapped.d, wrapped.c],
|
248
|
+
'Reading wrapped object with hook gave wrong attributes'
|
249
|
+
|
250
|
+
wrapped = Abi.read_wrapped_raw gold_packed, 0
|
251
|
+
packed[:n] *= 100
|
252
|
+
gold_packed = Abi.to_packed packed
|
253
|
+
assert_equal gold_packed, Abi.to_wrapped(wrapped),
|
254
|
+
'Wrapped object -> array (with hook)'
|
255
|
+
|
256
|
+
assert_equal gold_packed.length,
|
257
|
+
Abi.read_packed_length(@garbage + gold_packed,
|
258
|
+
@garbage.length),
|
259
|
+
'Reading wrapped object length'
|
260
|
+
end
|
261
|
+
|
262
|
+
def test_conditional_wrapper
|
263
|
+
[
|
264
|
+
[:conditional, "abcdef", [0x59, 0xAF, ?a, ?b, ?c, ?d, ?e, ?f]],
|
265
|
+
[:conditional, 3, [0x59, 0xAC, 0x00, 0x01, 0x03]],
|
266
|
+
[:conditional, 4, [0x59, 0xAD, 0x00, 0x00, 0x00, 0x04]],
|
267
|
+
[:conditional, OpenSSL::BN.new('7'), [0x59, 0xAD, 0x00, 0x00, 0x00, 0x07]],
|
268
|
+
[:conditional, 6, nil]
|
269
|
+
].each do |test_line|
|
270
|
+
type, object, array = *test_line
|
271
|
+
if array
|
272
|
+
assert_equal array, Abi.send(:"to_#{type}", object),
|
273
|
+
"Object #{object.inspect} -> array"
|
274
|
+
assert_equal object, Abi.send(:"read_#{type}", @garbage + array,
|
275
|
+
@garbage.length)
|
276
|
+
assert_equal array.length,
|
277
|
+
Abi.send(:"read_#{type}_length", @garbage + array,
|
278
|
+
@garbage.length),
|
279
|
+
"#{type} failed on read_#{type}_length"
|
280
|
+
else
|
281
|
+
assert_raise RuntimeError do
|
282
|
+
assert_equal array, Abi.send(:"to_#{type}", object)
|
283
|
+
end
|
284
|
+
end
|
285
|
+
end
|
286
|
+
end
|
287
|
+
|
288
|
+
def test_length
|
289
|
+
[[:byte, 1], [:ubyte, 1],
|
290
|
+
[:word, 2], [:netword, 2],
|
291
|
+
[:dword, 4], [:udword, 4],
|
292
|
+
[:mac_id, 6]
|
293
|
+
].each do |test_line|
|
294
|
+
assert_equal test_line.last, Abi.send(:"#{test_line.first}_length"),
|
295
|
+
"length failed for #{test_line.first}"
|
296
|
+
end
|
297
|
+
end
|
298
|
+
end
|