pkcs11 0.1.0-x86-mswin32 → 0.2.0-x86-mswin32

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.
@@ -1,71 +1,90 @@
1
+ require 'pkcs11/helper'
2
+
1
3
  module PKCS11
2
4
  # Each slot corresponds to a physical reader or other device interface.
3
5
  # It may contain a token.
4
6
  class Slot
7
+ include Helper
8
+
9
+ # @private
5
10
  def initialize(pkcs11, slot) # :nodoc:
6
11
  @pk, @slot = pkcs11, slot
7
12
  end
8
13
 
9
14
  # The slot handle.
15
+ # @return [Integer]
10
16
  def to_int
11
17
  @slot
12
18
  end
13
19
  alias to_i to_int
14
20
 
21
+ # @private
15
22
  def inspect # :nodoc:
16
23
  "#<#{self.class} #{@slot.inspect}>"
17
24
  end
18
25
 
19
26
  # Obtains information about a particular slot in the system.
27
+ # @return [PKCS11::CK_SLOT_INFO]
20
28
  def C_GetSlotInfo
21
29
  @pk.C_GetSlotInfo(@slot)
22
30
  end
23
31
  alias info C_GetSlotInfo
24
32
 
25
33
  # Obtains information about a particular token in the system.
34
+ # @return [PKCS11::CK_TOKEN_INFO]
26
35
  def C_GetTokenInfo
27
36
  @pk.C_GetTokenInfo(@slot)
28
37
  end
29
38
  alias token_info C_GetTokenInfo
30
39
 
31
40
  # Waits for a slot event, such as token insertion or token removal, to
32
- # occur. flags determines whether or not the C_WaitForSlotEvent call blocks (i.e., waits
33
- # for a slot event to occur);
41
+ # occur.
42
+ # @param flags determines whether or not the C_WaitForSlotEvent call blocks (i.e., waits
43
+ # for a slot event to occur);
34
44
  def C_WaitForSlotEvent(flags)
35
45
  @pk.C_WaitForSlotEvent(@slot, flags)
36
46
  end
37
47
  alias wait_for_event C_WaitForSlotEvent
38
48
 
39
49
  # C_GetMechanismList is used to obtain a list of mechanism types supported by a token.
50
+ # @return [Array<PKCS11::CKM_*>]
40
51
  def C_GetMechanismList
41
- @pk.C_GetMechanismList(@slot).map{|mech|
42
- Mechanism.new MECHANISMS, mech
43
- }
52
+ @pk.C_GetMechanismList(@slot)
44
53
  end
45
54
  alias mechanisms C_GetMechanismList
46
55
 
47
56
  # Obtains information about a particular mechanism possibly
48
57
  # supported by a token.
58
+ #
59
+ # @param [Integer, Symbol] mechanism
60
+ # @return [CK_MECHANISM_INFO]
49
61
  def C_GetMechanismInfo(mechanism)
50
- @pk.C_GetMechanismInfo(@slot, Session.hash_to_mechanism(mechanism))
62
+ @pk.C_GetMechanismInfo(@slot, to_mechanism_int(mechanism))
51
63
  end
52
64
  alias mechanism_info C_GetMechanismInfo
53
65
 
54
- # Initializes a token. pin is the SO’s initial PIN; label is the label of the token (max 32-byte). This standard allows PIN
66
+ # Initializes a token.
67
+ # @param [String] pin is the SO's initial PIN
68
+ # @param [String] label is the label of the token (max 32-byte).
69
+ #
70
+ # The standard allows PIN
55
71
  # values to contain any valid UTF8 character, but the token may impose subset restrictions.
72
+ # @return [PKCS11::Slot]
56
73
  def C_InitToken(pin, label)
57
74
  @pk.C_InitToken(@slot, pin, label.ljust(32, " "))
75
+ self
58
76
  end
59
77
  alias init_token C_InitToken
60
78
 
61
79
  # Opens a Session between an application and a token in a particular slot.
62
80
  #
63
- # flags:: indicates the type of session. Default is read-only,
81
+ # @param [Integer] flags indicates the type of session. Default is read-only,
64
82
  # use <tt>CKF_SERIAL_SESSION | CKF_RW_SESSION</tt> for read-write session.
65
83
  #
66
84
  # * If called with block, yields the block with the session and closes the session
67
- # when the is finished.
85
+ # when the is finished.
68
86
  # * If called without block, returns the session object.
87
+ # @return [PKCS11::Session]
69
88
  def C_OpenSession(flags=CKF_SERIAL_SESSION)
70
89
  nr = @pk.C_OpenSession(@slot, flags)
71
90
  sess = Session.new @pk, nr
@@ -82,8 +101,10 @@ module PKCS11
82
101
  alias open C_OpenSession
83
102
 
84
103
  # Closes all sessions an application has with a token.
104
+ # @return [PKCS11::Slot]
85
105
  def C_CloseAllSessions
86
106
  @pk.C_CloseAllSessions(@slot)
107
+ self
87
108
  end
88
109
  alias close_all_sessions C_CloseAllSessions
89
110
  end
@@ -1,10 +1,9 @@
1
1
  require "openssl"
2
2
 
3
- def open_softokn
4
-
5
- if RUBY_PLATFORM =~ /win32/
3
+ def find_softokn
4
+ if RUBY_PLATFORM =~ /mswin|mingw/
6
5
  lLIBSOFTOKEN3_SO = "softokn3.dll"
7
-
6
+
8
7
  # Try to find the firefox path.
9
8
  unless ENV['SOFTOKN_PATH']
10
9
  require 'win32/registry'
@@ -31,13 +30,21 @@ def open_softokn
31
30
  end
32
31
 
33
32
  raise "#{lLIBSOFTOKEN3_SO} not found - please install firefox or set ENV['SOFTOKN_PATH']" unless so_path
33
+ so_path
34
+ end
34
35
 
36
+ def softokn_params
35
37
  dir = File.join(File.dirname(__FILE__), 'fixtures/softokn')
36
- nNSS_INIT_ARGS = [
38
+ [
37
39
  "configDir='#{dir}'",
38
40
  "secmod='secmod.db'",
39
41
  "flags='readWrite'",
40
42
  ]
43
+ end
44
+
45
+ def open_softokn
46
+ so_path = find_softokn
47
+ nNSS_INIT_ARGS = softokn_params
41
48
 
42
- pk11 = PKCS11.open(so_path, :flags=>0, :pReserved=>nNSS_INIT_ARGS.join(" "))
49
+ PKCS11.open(so_path, :flags=>0, :pReserved=>nNSS_INIT_ARGS.join(" "))
43
50
  end
@@ -29,8 +29,19 @@ class TestPkcs11 < Test::Unit::TestCase
29
29
 
30
30
  def test_close
31
31
  pk.close
32
+ pk.unload_library
32
33
  assert_raise(PKCS11::Error){ pk.info }
33
- pk.close
34
- assert_raise(PKCS11::Error){ pk.active_slots }
34
+
35
+ @pk = PKCS11.open
36
+ pk.load_library(find_softokn)
37
+
38
+ pk.C_GetFunctionList
39
+
40
+ pargs = PKCS11::CK_C_INITIALIZE_ARGS.new
41
+ pargs.flags = 0
42
+ pargs.pReserved = softokn_params.join(" ")
43
+ pk.C_Initialize(pargs)
44
+
45
+ pk.info
35
46
  end
36
47
  end
@@ -18,7 +18,7 @@ class TestPkcs11Crypt < Test::Unit::TestCase
18
18
  @slots = pk.active_slots
19
19
  @slot = slots.last
20
20
  @session = slot.open
21
- session.login(:USER, "")
21
+ # session.login(:USER, "")
22
22
 
23
23
  @rsa_pub_key = session.find_objects(:CLASS => CKO_PUBLIC_KEY,
24
24
  :KEY_TYPE => CKK_RSA).first
@@ -34,7 +34,7 @@ class TestPkcs11Crypt < Test::Unit::TestCase
34
34
 
35
35
  def teardown
36
36
  @secret_key.destroy
37
- @session.logout
37
+ # @session.logout
38
38
  @session.close
39
39
  end
40
40
 
@@ -66,7 +66,7 @@ class TestPkcs11Crypt < Test::Unit::TestCase
66
66
  valid = session.verify( :SHA1_RSA_PKCS, rsa_pub_key, signature, plaintext)
67
67
  assert valid, 'The signature should be correct'
68
68
 
69
- assert_raise(PKCS11::Error, 'The signature should be invalid on different text') do
69
+ assert_raise(CKR_SIGNATURE_INVALID, 'The signature should be invalid on different text') do
70
70
  session.verify( :SHA1_RSA_PKCS, rsa_pub_key, signature, "modified text")
71
71
  end
72
72
  end
@@ -132,6 +132,15 @@ class TestPkcs11Crypt < Test::Unit::TestCase
132
132
  key = session.generate_key(:DES2_KEY_GEN,
133
133
  {:ENCRYPT=>true, :WRAP=>true, :DECRYPT=>true, :UNWRAP=>true, :TOKEN=>false, :LOCAL=>true})
134
134
  assert_equal true, key[:LOCAL], 'Keys created on the token should be marked as local'
135
+ assert_equal CKK_DES2, key[:KEY_TYPE], 'Should be a 2 key 3des key'
136
+
137
+ # other ways to use mechanisms
138
+ key = session.generate_key(CKM_DES2_KEY_GEN,
139
+ {:ENCRYPT=>true, :WRAP=>true, :DECRYPT=>true, :UNWRAP=>true, :TOKEN=>false, :LOCAL=>true})
140
+ assert_equal CKK_DES2, key[:KEY_TYPE], 'Should be a 2 key 3des key'
141
+ key = session.generate_key(CK_MECHANISM.new(CKM_DES2_KEY_GEN, nil),
142
+ {:ENCRYPT=>true, :WRAP=>true, :DECRYPT=>true, :UNWRAP=>true, :TOKEN=>false, :LOCAL=>true})
143
+ assert_equal CKK_DES2, key[:KEY_TYPE], 'Should be a 2 key 3des key'
135
144
  end
136
145
 
137
146
  def test_generate_key_pair
@@ -164,4 +173,30 @@ class TestPkcs11Crypt < Test::Unit::TestCase
164
173
 
165
174
  assert_equal new_key1[0,16], new_key2[:VALUE], 'Exchanged session key should be equal'
166
175
  end
176
+
177
+ def test_derive_key2
178
+ deriv_data = "\0"*16
179
+ new_key1 = session.derive_key( {CKM_XOR_BASE_AND_DATA => {:pData => deriv_data}}, secret_key,
180
+ :CLASS=>CKO_SECRET_KEY, :KEY_TYPE=>CKK_AES, :VALUE_LEN=>16, :ENCRYPT=>true, :DECRYPT=>true, :SENSITIVE=>false )
181
+
182
+ assert_equal secret_key[:VALUE], new_key1[:VALUE], 'Derived key should have equal key value'
183
+ end
184
+
185
+ def test_ssl3
186
+ pm_key = session.generate_key({:SSL3_PRE_MASTER_KEY_GEN => {:major=>3, :minor=>0}},
187
+ {:TOKEN=>false})
188
+ assert_equal 48, pm_key[:VALUE_LEN], "SSL3 pre master key should be 48 bytes long"
189
+
190
+ dp = CK_SSL3_MASTER_KEY_DERIVE_PARAMS.new
191
+ dp.RandomInfo.pServerRandom = 'srandom ' * 4
192
+ dp.RandomInfo.pClientRandom = 'crandom ' * 4
193
+ dp.pVersion = CK_VERSION.new
194
+ dp.pVersion.major = 3
195
+ dp.pVersion.minor = 1
196
+ ms_key = session.derive_key( {CKM_SSL3_MASTER_KEY_DERIVE => dp}, pm_key )
197
+
198
+ assert_equal 48, ms_key[:VALUE_LEN], "SSL3 master secret key should be 48 bytes long"
199
+ assert_equal 0, dp.pVersion.minor, 'SSL3 version number should have changed'
200
+ end
201
+
167
202
  end
@@ -18,7 +18,7 @@ class TestPkcs11Object < Test::Unit::TestCase
18
18
 
19
19
  flags = CKF_SERIAL_SESSION #| CKF_RW_SESSION
20
20
  @session = slot.C_OpenSession(flags)
21
- @session.login(:USER, "")
21
+ # @session.login(:USER, "")
22
22
 
23
23
  # Create session object for tests.
24
24
  @object = session.create_object(
@@ -29,7 +29,7 @@ class TestPkcs11Object < Test::Unit::TestCase
29
29
  end
30
30
 
31
31
  def teardown
32
- @session.logout
32
+ # @session.logout
33
33
  @session.close
34
34
  end
35
35
 
@@ -84,10 +84,24 @@ class TestPkcs11Object < Test::Unit::TestCase
84
84
  assert object.size, 'There should be an object size'
85
85
  end
86
86
 
87
+ def test_copy_without_params
88
+ new_obj = object.copy
89
+ new_obj[:APPLICATION] = 'Copied object'
90
+ assert_equal 'Copied object', new_obj[:APPLICATION], "Application should be changed"
91
+ assert_equal 'My Application', object[:APPLICATION], "Original object should be unchanged"
92
+ end
93
+
94
+ def test_copy_with_params
95
+ new_obj = object.copy :APPLICATION=>'Copied object'
96
+ assert_equal 'value', new_obj[:VALUE], "Value should be copied"
97
+ assert_equal 'Copied object', new_obj[:APPLICATION], "Application should be changed"
98
+ assert_equal 'My Application', object[:APPLICATION], "Original object should be unchanged"
99
+ end
100
+
87
101
  def test_destroy
88
102
  object.destroy
89
-
90
- assert_raise(PKCS11::Error, 'destroyed object shouldn\'t have any attributes') do
103
+
104
+ assert_raise(CKR_OBJECT_HANDLE_INVALID, 'destroyed object shouldn\'t have any attributes') do
91
105
  object[:VALUE]
92
106
  end
93
107
  end
@@ -19,11 +19,11 @@ class TestPkcs11Session < Test::Unit::TestCase
19
19
 
20
20
  flags = CKF_SERIAL_SESSION #| CKF_RW_SESSION
21
21
  @session = slot.C_OpenSession(flags)
22
- @session.login(:USER, "")
22
+ # @session.login(:USER, "")
23
23
  end
24
24
 
25
25
  def teardown
26
- @session.logout
26
+ # @session.logout
27
27
  @session.close
28
28
  end
29
29
 
@@ -94,4 +94,30 @@ class TestPkcs11Session < Test::Unit::TestCase
94
94
 
95
95
  assert_equal 'test_create_public_key_object', obj[:LABEL], 'Value as created'
96
96
  end
97
+
98
+ def test_get_set_operation_state
99
+ plaintext = "secret text"
100
+
101
+ # Start a digest operation
102
+ session.C_DigestInit(:SHA_1)
103
+ session.C_DigestUpdate(plaintext[0..3])
104
+
105
+ # Save the current state and close the session
106
+ state = session.get_operation_state
107
+ @session.close
108
+
109
+ assert state.length >= 4, 'There should be at least some bytes for the first part of plaintext in the state'
110
+
111
+ # Open a new session and restore the previous state
112
+ @session = @slot.open
113
+ session.login(:USER, "")
114
+ session.set_operation_state(state)
115
+
116
+ # Finish the digest
117
+ session.C_DigestUpdate(plaintext[4..-1])
118
+ digest1 = session.C_DigestFinal
119
+ digest2 = OpenSSL::Digest::SHA1.new(plaintext).digest
120
+
121
+ assert_equal digest2, digest1, 'Digests should be equal'
122
+ end
97
123
  end
@@ -23,13 +23,16 @@ class TestPkcs11Slot < Test::Unit::TestCase
23
23
 
24
24
  def test_info
25
25
  sinfo = slot.info
26
-
26
+
27
27
  assert sinfo.inspect =~ /manufacturerID=/, 'Slot info should tell about manufacturerID'
28
-
29
- [
30
- sinfo.slotDescription, sinfo.manufacturerID, sinfo.flags,
31
- sinfo.hardwareVersion, sinfo.firmwareVersion
32
- ]
28
+
29
+ assert_equal Fixnum, sinfo.flags.class
30
+ assert sinfo.manufacturerID =~ /Mozilla/i, "It's the mozilla libaray we test against"
31
+ assert sinfo.slotDescription =~ /Private Key/i, "It's the slot with users private keys"
32
+ assert_equal Fixnum, sinfo.hardwareVersion.major.class, "Version should be a number"
33
+ assert_equal Fixnum, sinfo.hardwareVersion.minor.class, "Version should be a number"
34
+ assert_equal Fixnum, sinfo.firmwareVersion.major.class, "Version should be a number"
35
+ assert_equal Fixnum, sinfo.firmwareVersion.minor.class, "Version should be a number"
33
36
  end
34
37
 
35
38
  def test_token_info
@@ -0,0 +1,134 @@
1
+ require "test/unit"
2
+ require "pkcs11"
3
+ require "test/helper"
4
+
5
+ class TestPkcs11Structs < Test::Unit::TestCase
6
+ include PKCS11
7
+
8
+ def setup
9
+ end
10
+
11
+ def teardown
12
+ end
13
+
14
+ def test_STRING_ACCESSOR
15
+ s = CK_DATE.new
16
+ assert_equal "\0\0", s.day
17
+ assert_equal "\0\0\0\0", s.year
18
+ s.day = "12345"
19
+ assert_equal "12", s.day
20
+ s.day = "9"
21
+ assert_equal "9\0", s.day
22
+ assert_raise(TypeError){ s.day = nil }
23
+ end
24
+
25
+ def test_ULONG_ACCESSOR
26
+ s = CK_SSL3_KEY_MAT_PARAMS.new
27
+ assert_equal 0, s.ulIVSizeInBits
28
+ s.ulIVSizeInBits = 1234567890
29
+ assert_equal 1234567890, s.ulIVSizeInBits
30
+ s.ulIVSizeInBits = 2345678901
31
+ assert_equal 2345678901, s.ulIVSizeInBits
32
+ assert_raise(TypeError){ s.ulIVSizeInBits = nil }
33
+ end
34
+
35
+ def test_BOOL_ACCESSOR
36
+ s = CK_SSL3_KEY_MAT_PARAMS.new
37
+ assert_equal false, s.bIsExport
38
+ s.bIsExport = true
39
+ assert_equal true, s.bIsExport
40
+ s.bIsExport = false
41
+ assert_equal false, s.bIsExport
42
+ assert_raise(ArgumentError){ s.bIsExport = nil }
43
+ end
44
+
45
+ def test_STRING_PTR_ACCESSOR
46
+ s = CK_WTLS_MASTER_KEY_DERIVE_PARAMS.new
47
+ assert_nil s.pVersion
48
+ s.pVersion = "1.2.3"
49
+ assert_equal "1.2.3", s.pVersion
50
+ s.pVersion = nil
51
+ assert_nil s.pVersion
52
+ end
53
+
54
+ def test_STRUCT_ACCESSOR
55
+ s = CK_SSL3_KEY_MAT_PARAMS.new
56
+ ri = s.RandomInfo
57
+ ro = s.RandomInfo
58
+ assert_nil ri.pClientRandom
59
+ assert_nil ro.pServerRandom
60
+ GC.start
61
+ ri.pServerRandom = 'serv'
62
+ ro.pClientRandom = 'client'
63
+ GC.start
64
+ assert_equal 'client', ri.pClientRandom
65
+ assert_equal 'serv', ro.pServerRandom
66
+
67
+ ro = CK_SSL3_RANDOM_DATA.new
68
+ ro.pClientRandom = 'clrnd'
69
+ s.RandomInfo = ro
70
+ assert_equal 'clrnd', ri.pClientRandom
71
+ assert_nil ri.pServerRandom
72
+
73
+ assert_raise(ArgumentError){ s.RandomInfo = nil }
74
+ end
75
+
76
+ def test_gc_STRUCT_ACCESSOR
77
+ ri = CK_SSL3_KEY_MAT_PARAMS.new.RandomInfo
78
+ ro = CK_SSL3_KEY_MAT_PARAMS.new.RandomInfo
79
+ ri.pServerRandom = 'serv'
80
+ ro.pServerRandom = '_serv'
81
+ GC.start
82
+ assert_equal '_serv', ro.pServerRandom
83
+ assert_equal 'serv', ri.pServerRandom
84
+ assert_nil ro.pClientRandom
85
+ assert_nil ri.pClientRandom
86
+ end
87
+
88
+ def test_STRING_PTR_LEN_ACCESSOR
89
+ s = CK_SSL3_RANDOM_DATA.new
90
+ assert_nil s.pServerRandom
91
+ GC.start
92
+ s.pServerRandom = 'serv'
93
+ s.pClientRandom = 'client'
94
+ GC.start
95
+ assert_equal 'client', s.pClientRandom
96
+ assert_equal 'serv', s.pServerRandom
97
+ GC.start
98
+ s.pServerRandom = nil
99
+ assert_nil s.pServerRandom
100
+ end
101
+
102
+ def test_STRUCT_PTR_ACCESSOR
103
+ s = CK_SSL3_KEY_MAT_PARAMS.new
104
+ assert_nil s.pReturnedKeyMaterial
105
+ ri = s.pReturnedKeyMaterial = CK_SSL3_KEY_MAT_OUT.new
106
+ assert_nil ri.pIVClient
107
+ ri.pIVClient = 'cli'
108
+ GC.start
109
+ assert_equal 'cli', ri.pIVClient
110
+ assert_equal 'cli', s.pReturnedKeyMaterial.pIVClient
111
+ s.pReturnedKeyMaterial = nil
112
+ assert_nil s.pReturnedKeyMaterial
113
+ end
114
+
115
+ def test_ULONG_PTR_ACCESSOR
116
+ s = CK_WTLS_PRF_PARAMS.new
117
+ assert_nil s.pulOutputLen
118
+ s.pulOutputLen = 123
119
+ GC.start
120
+ assert_equal 123, s.pulOutputLen
121
+ s.pulOutputLen = nil
122
+ assert_nil s.pulOutputLen
123
+ end
124
+
125
+ def test_CStruct
126
+ s = CK_DATE.new
127
+ s.day, s.month, s.year = "31", "12", "2010"
128
+
129
+ assert s.inspect =~ /year="2010"/, 'There should be a year in CK_DATE'
130
+ assert_equal ["day", "month", "year"], s.members, 'CK_DATE should contain some attributes'
131
+ assert_equal ["31", "12", "2010"], s.values, 'values of CK_DATE'
132
+ assert_equal( {:day=>"31", :month=>"12", :year=>"2010"}, s.to_hash, 'CK_DATE as hash' )
133
+ end
134
+ end