pkcs11 0.2.4-x64-mingw32

Sign up to get free protection for your applications and to get access to all the features.
Files changed (55) hide show
  1. data.tar.gz.sig +0 -0
  2. data/.autotest +23 -0
  3. data/.gemtest +0 -0
  4. data/.yardopts +1 -0
  5. data/History.txt +57 -0
  6. data/MIT-LICENSE +22 -0
  7. data/Manifest.txt +57 -0
  8. data/README.rdoc +205 -0
  9. data/Rakefile +111 -0
  10. data/ext/extconf.rb +7 -0
  11. data/ext/generate_constants.rb +57 -0
  12. data/ext/generate_structs.rb +206 -0
  13. data/ext/generate_thread_funcs.rb +72 -0
  14. data/ext/include/cryptoki.h +66 -0
  15. data/ext/include/ct-kip.h +50 -0
  16. data/ext/include/otp-pkcs11.h +125 -0
  17. data/ext/include/pkcs-11v2-20a3.h +124 -0
  18. data/ext/include/pkcs11.h +299 -0
  19. data/ext/include/pkcs11f.h +912 -0
  20. data/ext/include/pkcs11t.h +1885 -0
  21. data/ext/pk11.c +1675 -0
  22. data/ext/pk11.h +81 -0
  23. data/ext/pk11_const.c +205 -0
  24. data/ext/pk11_const_def.inc +452 -0
  25. data/ext/pk11_const_macros.h +38 -0
  26. data/ext/pk11_struct.doc +792 -0
  27. data/ext/pk11_struct_def.inc +302 -0
  28. data/ext/pk11_struct_impl.inc +302 -0
  29. data/ext/pk11_struct_macros.h +435 -0
  30. data/ext/pk11_thread_funcs.c +411 -0
  31. data/ext/pk11_thread_funcs.h +482 -0
  32. data/ext/pk11_version.h +6 -0
  33. data/lib/2.0/pkcs11_ext.so +0 -0
  34. data/lib/pkcs11.rb +9 -0
  35. data/lib/pkcs11/extensions.rb +68 -0
  36. data/lib/pkcs11/helper.rb +144 -0
  37. data/lib/pkcs11/library.rb +140 -0
  38. data/lib/pkcs11/object.rb +171 -0
  39. data/lib/pkcs11/session.rb +765 -0
  40. data/lib/pkcs11/slot.rb +102 -0
  41. data/pkcs11_protect_server/Manifest.txt +14 -0
  42. data/pkcs11_protect_server/README_PROTECT_SERVER.rdoc +89 -0
  43. data/test/fixtures/softokn/cert8.db +0 -0
  44. data/test/fixtures/softokn/key3.db +0 -0
  45. data/test/fixtures/softokn/secmod.db +0 -0
  46. data/test/helper.rb +58 -0
  47. data/test/test_pkcs11.rb +71 -0
  48. data/test/test_pkcs11_crypt.rb +220 -0
  49. data/test/test_pkcs11_object.rb +122 -0
  50. data/test/test_pkcs11_session.rb +123 -0
  51. data/test/test_pkcs11_slot.rb +78 -0
  52. data/test/test_pkcs11_structs.rb +166 -0
  53. data/test/test_pkcs11_thread.rb +44 -0
  54. metadata +213 -0
  55. metadata.gz.sig +0 -0
@@ -0,0 +1,102 @@
1
+ require 'pkcs11/helper'
2
+
3
+ module PKCS11
4
+ # Each slot corresponds to a physical reader or other device interface.
5
+ # It may contain a token.
6
+ class Slot
7
+ include Helper
8
+
9
+ # @private
10
+ def initialize(pkcs11, slot) # :nodoc:
11
+ @pk, @slot = pkcs11, slot
12
+ end
13
+
14
+ # The slot handle.
15
+ # @return [Integer]
16
+ def to_int
17
+ @slot
18
+ end
19
+ alias to_i to_int
20
+
21
+ # @private
22
+ def inspect # :nodoc:
23
+ "#<#{self.class} #{@slot.inspect}>"
24
+ end
25
+
26
+ # Obtains information about a particular slot in the system.
27
+ # @return [PKCS11::CK_SLOT_INFO]
28
+ def C_GetSlotInfo
29
+ @pk.C_GetSlotInfo(@slot)
30
+ end
31
+ alias info C_GetSlotInfo
32
+
33
+ # Obtains information about a particular token in the system.
34
+ # @return [PKCS11::CK_TOKEN_INFO]
35
+ def C_GetTokenInfo
36
+ @pk.C_GetTokenInfo(@slot)
37
+ end
38
+ alias token_info C_GetTokenInfo
39
+
40
+ # C_GetMechanismList is used to obtain a list of mechanism types supported by a token.
41
+ # @return [Array<PKCS11::CKM_*>]
42
+ def C_GetMechanismList
43
+ @pk.C_GetMechanismList(@slot)
44
+ end
45
+ alias mechanisms C_GetMechanismList
46
+
47
+ # Obtains information about a particular mechanism possibly
48
+ # supported by a token.
49
+ #
50
+ # @param [Integer, Symbol] mechanism
51
+ # @return [CK_MECHANISM_INFO]
52
+ def C_GetMechanismInfo(mechanism)
53
+ @pk.C_GetMechanismInfo(@slot, string_to_handle('CKM_', mechanism))
54
+ end
55
+ alias mechanism_info C_GetMechanismInfo
56
+
57
+ # Initializes a token.
58
+ # @param [String] pin is the SO's initial PIN
59
+ # @param [String] label is the label of the token (max 32-byte).
60
+ #
61
+ # The standard allows PIN
62
+ # values to contain any valid UTF8 character, but the token may impose subset restrictions.
63
+ # @return [PKCS11::Slot]
64
+ def C_InitToken(pin, label)
65
+ @pk.C_InitToken(@slot, pin, label.ljust(32, " "))
66
+ self
67
+ end
68
+ alias init_token C_InitToken
69
+
70
+ # Opens a Session between an application and a token in a particular slot.
71
+ #
72
+ # @param [Integer] flags indicates the type of session. Default is read-only,
73
+ # use <tt>CKF_SERIAL_SESSION | CKF_RW_SESSION</tt> for read-write session.
74
+ #
75
+ # * If called with block, yields the block with the session and closes the session
76
+ # when the is finished.
77
+ # * If called without block, returns the session object.
78
+ # @return [PKCS11::Session]
79
+ def C_OpenSession(flags=CKF_SERIAL_SESSION)
80
+ nr = @pk.C_OpenSession(@slot, flags)
81
+ sess = Session.new @pk, nr
82
+ if block_given?
83
+ begin
84
+ yield sess
85
+ ensure
86
+ sess.close
87
+ end
88
+ else
89
+ sess
90
+ end
91
+ end
92
+ alias open C_OpenSession
93
+
94
+ # Closes all sessions an application has with a token.
95
+ # @return [PKCS11::Slot]
96
+ def C_CloseAllSessions
97
+ @pk.C_CloseAllSessions(@slot)
98
+ self
99
+ end
100
+ alias close_all_sessions C_CloseAllSessions
101
+ end
102
+ end
@@ -0,0 +1,14 @@
1
+ .gemtest
2
+ .yardopts
3
+ Manifest.txt
4
+ README_PROTECT_SERVER.rdoc
5
+ Rakefile
6
+ ext/extconf.rb
7
+ ext/generate_constants.rb
8
+ ext/generate_structs.rb
9
+ ext/pk11s.c
10
+ lib/pkcs11_protect_server.rb
11
+ lib/pkcs11_protect_server/extensions.rb
12
+ test/helper.rb
13
+ test/test_pkcs11_protect_server.rb
14
+ test/test_pkcs11_protect_server_crypt.rb
@@ -0,0 +1,89 @@
1
+ = PKCS #11/Ruby Interface for Safenet Protect Server HSM
2
+
3
+ * Homepage: http://github.com/larskanis/pkcs11
4
+ * API documentation: http://pkcs11.rubyforge.org/pkcs11/
5
+ * Safenet[http://www.safenet-inc.com] - Protect Server HSM
6
+
7
+ This ruby gem is an add-on to ruby-pkcs11[http://github.com/larskanis/pkcs11] .
8
+ It allowes to use Protect Server specific extensions, which are beyond the PKCS#11 standard.
9
+ That means CKA_EXPORT, CKM_DES3_DERIVE_CBC, structs like CK_DES3_CBC_PARAMS, special functions and so on.
10
+ The module works on the Unix like operating systems and win32.
11
+
12
+ == Requirements
13
+
14
+ * ProtectServer PTKC-SDK to compile the module
15
+ * pkcs11 gem installed (use: <tt>gem install pkcs11</tt> )
16
+
17
+ == Installation
18
+
19
+ gem install pkcs11_protect_server -- --with-protect-server-sdk-dir=/path/to/ETcpsdk
20
+
21
+ This installs the ProtectServer-PKCS#11 extension along with pkcs11-gem either by compiling (Unix)
22
+ or by using the precompiled gem for Win32.
23
+
24
+ git clone git://github.com/larskanis/pkcs11.git
25
+ cd pkcs11_protect_server
26
+ rake gem PROTECT_SERVER_SDK_DIR=/path/to/ETcpsdk
27
+ gem install -l pkg/pkcs11_protect_server -- --with-protect-server-sdk-dir=/path/to/ETcpsdk
28
+
29
+ Downloads and installs the gem from git source.
30
+
31
+ == Usage
32
+
33
+ Open the software emulation library and login to a session:
34
+
35
+ require "rubygems"
36
+ require "pkcs11_protect_server"
37
+
38
+ pkcs11 = PKCS11::ProtectServer::Library.new(:sw)
39
+ p pkcs11.info
40
+ session = pkcs11.active_slots.last.open
41
+ session.login(:USER, "1234")
42
+ # ... crypto operations
43
+ session.logout
44
+ session.close
45
+
46
+ {PKCS11::ProtectServer::Library#initialize} tries to find the library file in
47
+ the standard installation directory on Windows or Linux.
48
+
49
+ == Cross compiling for mswin32
50
+
51
+ Using rake-compiler a cross compiled pkcs11_protect_server.gem can be build on a linux host for
52
+ the win32 platform. There are no runtime dependencies to any but the standard Windows DLLs.
53
+
54
+ Install mingw32. On a debian based system this should work:
55
+
56
+ apt-get install mingw32
57
+
58
+ On MacOS X, if you have MacPorts installed:
59
+
60
+ port install i386-mingw32-gcc
61
+
62
+ Install the rake-compiler:
63
+
64
+ gem install rake-compiler
65
+
66
+ Download and cross compile ruby for win32:
67
+
68
+ rake-compiler cross-ruby VERSION=1.8.7-p352
69
+ rake-compiler cross-ruby VERSION=1.9.2-p290
70
+
71
+ Download and cross compile pkcs11_protect_server for win32:
72
+
73
+ rake cross native gem PROTECT_SERVER_SDK_DIR=/path/to/ETcpsdk
74
+
75
+ If everything works, there should be pkcs11_protect_server-VERSION-x86-mswin32.gem in the pkg
76
+ directory.
77
+
78
+
79
+ == ToDo
80
+
81
+ * implement ProtectServer specific function calls
82
+ * implement possibility to use callbacks
83
+ * add all structs and constants
84
+
85
+ == Authors
86
+ * Lars Kanis <kanis@comcard.de>
87
+
88
+ == Copying
89
+ See MIT-LICENSE included in the package.
@@ -0,0 +1,58 @@
1
+ require "pkcs11"
2
+
3
+ def find_softokn
4
+ if RUBY_PLATFORM =~ /mswin|mingw/
5
+ lLIBSOFTOKEN3_SO = "softokn3.dll"
6
+
7
+ # Try to find the firefox path.
8
+ unless so_path = ENV['SOFTOKN_PATH']
9
+ require 'win32/registry'
10
+ begin
11
+ firefox_path = Win32::Registry::HKEY_LOCAL_MACHINE.open('SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths\firefox.exe'){|reg|
12
+ reg.read('Path')[1]
13
+ }
14
+ rescue Win32::Registry::Error
15
+ end
16
+ if firefox_path
17
+ ENV['Path'] = ENV['Path'] + ";" + firefox_path
18
+ so_path = File.join(firefox_path, lLIBSOFTOKEN3_SO)
19
+ end
20
+ end
21
+ else
22
+ lLIBSOFTOKEN3_SO = "libsoftokn3.so"
23
+ lLIBNSS_PATHS = %w(
24
+ /usr/lib64
25
+ /usr/lib
26
+ /usr/lib64/nss
27
+ /usr/lib/nss
28
+ /usr/lib/i386-linux-gnu/nss
29
+ /usr/lib/x86_64-linux-gnu/nss
30
+ )
31
+ unless so_path = ENV['SOFTOKN_PATH']
32
+ paths = lLIBNSS_PATHS.collect{|path| File.join(path, lLIBSOFTOKEN3_SO) }
33
+ so_path = paths.find do |path|
34
+ File.exist?(path) && open_softokn(path).close rescue false
35
+ end
36
+ end
37
+ end
38
+
39
+ raise "#{lLIBSOFTOKEN3_SO} not found - please install firefox or libnss3 or set ENV['SOFTOKN_PATH']" unless so_path
40
+ so_path
41
+ end
42
+
43
+ def softokn_params
44
+ dir = File.join(File.dirname(__FILE__), 'fixtures/softokn')
45
+ [
46
+ "configDir='#{dir}'",
47
+ "secmod='secmod.db'",
48
+ "flags='readWrite'",
49
+ ]
50
+ end
51
+
52
+ def softokn_params_string
53
+ softokn_params.join(" ")
54
+ end
55
+
56
+ def open_softokn(so_path=nil)
57
+ PKCS11.open(so_path || find_softokn, :flags=>0, :pReserved=>softokn_params_string)
58
+ end
@@ -0,0 +1,71 @@
1
+ require "test/unit"
2
+ require "pkcs11"
3
+ require "test/helper"
4
+
5
+ class TestPkcs11 < Test::Unit::TestCase
6
+ attr_reader :pk
7
+
8
+ def open
9
+ @pk = open_softokn
10
+ end
11
+
12
+ def close
13
+ @pk.close
14
+ @pk = nil
15
+ GC.start
16
+ end
17
+
18
+ def test_info
19
+ open
20
+ info = pk.info
21
+ assert info.inspect =~ /cryptokiVersion=/, 'There should be a version in the library info'
22
+ close
23
+ end
24
+
25
+ def test_slots
26
+ open
27
+ slots = pk.active_slots
28
+ assert slots.length>=1, 'Hope there is at least one active slot'
29
+ close
30
+ end
31
+
32
+ def test_close
33
+ open
34
+ pk.close
35
+ pk.unload_library
36
+ assert_raise(PKCS11::Error){ pk.info }
37
+
38
+ @pk = PKCS11.open
39
+ pk.load_library(find_softokn)
40
+
41
+ pk.C_GetFunctionList
42
+
43
+ pargs = PKCS11::CK_C_INITIALIZE_ARGS.new
44
+ pargs.flags = 0
45
+ pargs.pReserved = softokn_params.join(" ")
46
+ pk.C_Initialize(pargs)
47
+
48
+ pk.info
49
+ close
50
+ end
51
+
52
+ def test_C_Initialize_with_Hash
53
+ pk = PKCS11.open
54
+ pk.load_library(find_softokn)
55
+ pk.C_GetFunctionList
56
+ pk.C_Initialize(:flags=>0, :pReserved=>softokn_params_string)
57
+ pk.info
58
+ pk.close
59
+ end
60
+
61
+ def test_wait_for_slot_event
62
+ open
63
+ # Softokn's C_WaitForSlotEvent() currently raises PKCS11::CKR_FUNCTION_NOT_SUPPORTED.
64
+ # So just check, that the call goes to softokn at all.
65
+ begin
66
+ pk.wait_for_slot_event
67
+ rescue PKCS11::Error
68
+ end
69
+ close
70
+ end
71
+ end
@@ -0,0 +1,220 @@
1
+ require "test/unit"
2
+ require "pkcs11"
3
+ require "test/helper"
4
+ require "openssl"
5
+
6
+ class TestPkcs11Crypt < Test::Unit::TestCase
7
+ include PKCS11
8
+
9
+ attr_reader :slots
10
+ attr_reader :slot
11
+ attr_reader :session
12
+ attr_reader :rsa_priv_key
13
+ attr_reader :rsa_pub_key
14
+ attr_reader :secret_key
15
+
16
+ def setup
17
+ $pkcs11 ||= open_softokn
18
+ @slots = pk.active_slots
19
+ @slot = slots.last
20
+ @session = slot.open
21
+ # session.login(:USER, "")
22
+
23
+ @rsa_pub_key = session.find_objects(:CLASS => CKO_PUBLIC_KEY,
24
+ :KEY_TYPE => CKK_RSA).first
25
+ @rsa_priv_key = session.find_objects(:CLASS => CKO_PRIVATE_KEY,
26
+ :KEY_TYPE => CKK_RSA).first
27
+ @secret_key = session.create_object(
28
+ :CLASS=>CKO_SECRET_KEY,
29
+ :KEY_TYPE=>CKK_DES2,
30
+ :ENCRYPT=>true, :WRAP=>true, :DECRYPT=>true, :UNWRAP=>true, :TOKEN=>false,
31
+ :VALUE=>'0123456789abcdef',
32
+ :LABEL=>'test_secret_key')
33
+ end
34
+
35
+ def teardown
36
+ @secret_key.destroy
37
+ # @session.logout
38
+ @session.close
39
+ end
40
+
41
+ def pk
42
+ $pkcs11
43
+ end
44
+
45
+ def test_endecrypt_rsa
46
+ plaintext1 = "secret text"
47
+ cryptogram = session.encrypt( :RSA_PKCS, rsa_pub_key, plaintext1)
48
+ assert cryptogram.length>10, 'The cryptogram should contain some data'
49
+ assert_not_equal cryptogram, plaintext1, 'The cryptogram should be different to plaintext'
50
+
51
+ plaintext2 = session.decrypt( :RSA_PKCS, rsa_priv_key, cryptogram)
52
+ assert_equal plaintext1, plaintext2, 'Decrypted plaintext should be the same'
53
+ end
54
+
55
+ def test_endecrypt_des
56
+ plaintext1 = "secret message "
57
+ cryptogram = session.encrypt( {:DES3_CBC_PAD=>"\0"*8}, secret_key, plaintext1)
58
+ assert_equal 16, cryptogram.length, 'The cryptogram should contain some data'
59
+ assert_not_equal cryptogram, plaintext1, 'The cryptogram should be different to plaintext'
60
+
61
+ cryptogram2 = ''
62
+ cryptogram2 << session.encrypt( {:DES3_CBC_PAD=>"\0"*8}, secret_key ) do |cipher|
63
+ cryptogram2 << cipher.update(plaintext1[0, 8])
64
+ cryptogram2 << cipher.update(plaintext1[8..-1])
65
+ end
66
+ assert_equal cryptogram, cryptogram2, "Encrypt with and w/o block should be lead to the same result"
67
+
68
+ plaintext2 = session.decrypt( {:DES3_CBC_PAD=>"\0"*8}, secret_key, cryptogram)
69
+ assert_equal plaintext1, plaintext2, 'Decrypted plaintext should be the same'
70
+ end
71
+
72
+ def test_sign_verify
73
+ plaintext = "important text"
74
+ signature = session.sign( :SHA1_RSA_PKCS, rsa_priv_key, plaintext)
75
+ assert signature.length>10, 'The signature should contain some data'
76
+
77
+ signature2 = session.sign( :SHA1_RSA_PKCS, rsa_priv_key){|c|
78
+ c.update(plaintext[0..3])
79
+ c.update(plaintext[4..-1])
80
+ }
81
+ assert_equal signature, signature2, 'results of one-step and two-step signatures should be equal'
82
+
83
+ valid = session.verify( :SHA1_RSA_PKCS, rsa_pub_key, signature, plaintext)
84
+ assert valid, 'The signature should be correct'
85
+
86
+ assert_raise(CKR_SIGNATURE_INVALID, 'The signature should be invalid on different text') do
87
+ session.verify( :SHA1_RSA_PKCS, rsa_pub_key, signature, "modified text")
88
+ end
89
+ end
90
+
91
+ def create_openssl_cipher(pk11_key)
92
+ rsa = OpenSSL::PKey::RSA.new
93
+ rsa.n = OpenSSL::BN.new pk11_key[:MODULUS], 2
94
+ rsa.e = OpenSSL::BN.new pk11_key[:PUBLIC_EXPONENT], 2
95
+ rsa
96
+ end
97
+
98
+ def test_compare_sign_with_openssl
99
+ signature = session.sign( :SHA1_RSA_PKCS, rsa_priv_key, "important text")
100
+
101
+ osslc = create_openssl_cipher rsa_pub_key
102
+ valid = osslc.verify(OpenSSL::Digest::SHA1.new, signature, "important text")
103
+ assert valid, 'The signature should be correct'
104
+ end
105
+
106
+ def test_compare_endecrypt_with_openssl
107
+ plaintext1 = "secret text"
108
+ osslc = create_openssl_cipher rsa_pub_key
109
+ cryptogram = osslc.public_encrypt(plaintext1)
110
+
111
+ plaintext2 = session.decrypt( :RSA_PKCS, rsa_priv_key, cryptogram)
112
+ assert_equal plaintext1, plaintext2, 'Decrypted plaintext should be the same'
113
+ end
114
+
115
+ def test_digest
116
+ plaintext = "secret text"
117
+ digest1 = session.digest( :SHA_1, plaintext)
118
+ digest2 = OpenSSL::Digest::SHA1.new(plaintext).digest
119
+ assert_equal digest1, digest2, 'Digests should be equal'
120
+ digest3 = session.digest(:SHA_1){|c|
121
+ c.update(plaintext[0..3])
122
+ c.update(plaintext[4..-1])
123
+ }
124
+ assert_equal digest1, digest3, 'Digests should be equal'
125
+
126
+ digest3 = session.digest(:SHA256){|c|
127
+ c.update(plaintext)
128
+ c.digest_key(secret_key)
129
+ }
130
+ end
131
+
132
+ def test_wrap_key
133
+ wrapped_key_value = session.wrap_key(:DES3_ECB, secret_key, secret_key)
134
+ assert_equal 16, wrapped_key_value.length, '112 bit 3DES key should have same size wrapped'
135
+
136
+ unwrapped_key = session.unwrap_key(:DES3_ECB, secret_key, wrapped_key_value, :CLASS=>CKO_SECRET_KEY, :KEY_TYPE=>CKK_DES2, :ENCRYPT=>true, :DECRYPT=>true)
137
+
138
+ secret_key_kcv = session.encrypt( :DES3_ECB, secret_key, "\0"*8)
139
+ unwrapped_key_kcv = session.encrypt( :DES3_ECB, unwrapped_key, "\0"*8)
140
+ assert_equal secret_key_kcv, unwrapped_key_kcv, 'Key check values of original and wrapped/unwrapped key should be equal'
141
+ end
142
+
143
+ def test_wrap_private_key
144
+ wrapped_key_value = session.wrap_key({:DES3_CBC_PAD=>"\0"*8}, secret_key, rsa_priv_key)
145
+ assert wrapped_key_value.length>100, 'RSA private key should have bigger size wrapped'
146
+ end
147
+
148
+ def test_generate_secret_key
149
+ key = session.generate_key(:DES2_KEY_GEN,
150
+ {:ENCRYPT=>true, :WRAP=>true, :DECRYPT=>true, :UNWRAP=>true, :TOKEN=>false, :LOCAL=>true})
151
+ assert_equal true, key[:LOCAL], 'Keys created on the token should be marked as local'
152
+ assert_equal CKK_DES2, key[:KEY_TYPE], 'Should be a 2 key 3des key'
153
+
154
+ # other ways to use mechanisms
155
+ key = session.generate_key(CKM_DES2_KEY_GEN,
156
+ {:ENCRYPT=>true, :WRAP=>true, :DECRYPT=>true, :UNWRAP=>true, :TOKEN=>false, :LOCAL=>true})
157
+ assert_equal CKK_DES2, key[:KEY_TYPE], 'Should be a 2 key 3des key'
158
+ key = session.generate_key(CK_MECHANISM.new(CKM_DES2_KEY_GEN, nil),
159
+ {:ENCRYPT=>true, :WRAP=>true, :DECRYPT=>true, :UNWRAP=>true, :TOKEN=>false, :LOCAL=>true})
160
+ assert_equal CKK_DES2, key[:KEY_TYPE], 'Should be a 2 key 3des key'
161
+ end
162
+
163
+ def test_generate_key_pair
164
+ pub_key, priv_key = session.generate_key_pair(:RSA_PKCS_KEY_PAIR_GEN,
165
+ {:ENCRYPT=>true, :VERIFY=>true, :WRAP=>true, :MODULUS_BITS=>768, :PUBLIC_EXPONENT=>[3].pack("N"), :TOKEN=>false},
166
+ {:PRIVATE=>true, :SUBJECT=>'test', :ID=>[123].pack("n"),
167
+ :SENSITIVE=>true, :DECRYPT=>true, :SIGN=>true, :UNWRAP=>true, :TOKEN=>false, :LOCAL=>true})
168
+
169
+ assert_equal true, priv_key[:LOCAL], 'Private keys created on the token should be marked as local'
170
+ assert_equal priv_key[:CLASS], CKO_PRIVATE_KEY
171
+ assert_equal pub_key[:CLASS], CKO_PUBLIC_KEY
172
+ assert_equal true, priv_key[:SENSITIVE], 'Private key should be sensitive'
173
+ end
174
+
175
+ def test_derive_key
176
+ # Generate DH key for side 1
177
+ key1 = OpenSSL::PKey::DH.new(512)
178
+
179
+ # Generate key side 2 with same prime and base as side 1
180
+ pub_key2, priv_key2 = session.generate_key_pair(:DH_PKCS_KEY_PAIR_GEN,
181
+ {:PRIME=>key1.p.to_s(2), :BASE=>key1.g.to_s(2), :TOKEN=>false},
182
+ {:VALUE_BITS=>512, :DERIVE=>true, :TOKEN=>false})
183
+
184
+ # Derive secret DES key for side 1 with OpenSSL
185
+ new_key1 = key1.compute_key(OpenSSL::BN.new pub_key2[:VALUE], 2)
186
+
187
+ # Derive secret DES key for side 2 with softokn3
188
+ new_key2 = session.derive_key( {:DH_PKCS_DERIVE=>key1.pub_key.to_s(2)}, priv_key2,
189
+ :CLASS=>CKO_SECRET_KEY, :KEY_TYPE=>CKK_AES, :VALUE_LEN=>16, :ENCRYPT=>true, :DECRYPT=>true, :SENSITIVE=>false )
190
+
191
+ # Some versions of softokn3 use left- and some use rightmost bits of exchanged key
192
+ assert_operator [new_key1[0,16], new_key1[-16..-1]], :include?, new_key2[:VALUE], 'Exchanged session key should be equal'
193
+ end
194
+
195
+ def test_derive_key2
196
+ deriv_data = "\0"*16
197
+ new_key1 = session.derive_key( {CKM_XOR_BASE_AND_DATA => {:pData => deriv_data}}, secret_key,
198
+ :CLASS=>CKO_SECRET_KEY, :KEY_TYPE=>CKK_AES, :VALUE_LEN=>16, :ENCRYPT=>true, :DECRYPT=>true, :SENSITIVE=>false )
199
+
200
+ assert_equal secret_key[:VALUE], new_key1[:VALUE], 'Derived key should have equal key value'
201
+ end
202
+
203
+ def test_ssl3
204
+ pm_key = session.generate_key({:SSL3_PRE_MASTER_KEY_GEN => {:major=>3, :minor=>0}},
205
+ {:TOKEN=>false})
206
+ assert_equal 48, pm_key[:VALUE_LEN], "SSL3 pre master key should be 48 bytes long"
207
+
208
+ dp = CK_SSL3_MASTER_KEY_DERIVE_PARAMS.new
209
+ dp.RandomInfo.pServerRandom = 'srandom ' * 4
210
+ dp.RandomInfo.pClientRandom = 'crandom ' * 4
211
+ dp.pVersion = CK_VERSION.new
212
+ dp.pVersion.major = 3
213
+ dp.pVersion.minor = 1
214
+ ms_key = session.derive_key( {CKM_SSL3_MASTER_KEY_DERIVE => dp}, pm_key )
215
+
216
+ assert_equal 48, ms_key[:VALUE_LEN], "SSL3 master secret key should be 48 bytes long"
217
+ assert_equal 0, dp.pVersion.minor, 'SSL3 version number should have changed'
218
+ end
219
+
220
+ end