pkcs11 0.2.4-x64-mingw32
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.tar.gz.sig +0 -0
- data/.autotest +23 -0
- data/.gemtest +0 -0
- data/.yardopts +1 -0
- data/History.txt +57 -0
- data/MIT-LICENSE +22 -0
- data/Manifest.txt +57 -0
- data/README.rdoc +205 -0
- data/Rakefile +111 -0
- data/ext/extconf.rb +7 -0
- data/ext/generate_constants.rb +57 -0
- data/ext/generate_structs.rb +206 -0
- data/ext/generate_thread_funcs.rb +72 -0
- data/ext/include/cryptoki.h +66 -0
- data/ext/include/ct-kip.h +50 -0
- data/ext/include/otp-pkcs11.h +125 -0
- data/ext/include/pkcs-11v2-20a3.h +124 -0
- data/ext/include/pkcs11.h +299 -0
- data/ext/include/pkcs11f.h +912 -0
- data/ext/include/pkcs11t.h +1885 -0
- data/ext/pk11.c +1675 -0
- data/ext/pk11.h +81 -0
- data/ext/pk11_const.c +205 -0
- data/ext/pk11_const_def.inc +452 -0
- data/ext/pk11_const_macros.h +38 -0
- data/ext/pk11_struct.doc +792 -0
- data/ext/pk11_struct_def.inc +302 -0
- data/ext/pk11_struct_impl.inc +302 -0
- data/ext/pk11_struct_macros.h +435 -0
- data/ext/pk11_thread_funcs.c +411 -0
- data/ext/pk11_thread_funcs.h +482 -0
- data/ext/pk11_version.h +6 -0
- data/lib/2.0/pkcs11_ext.so +0 -0
- data/lib/pkcs11.rb +9 -0
- data/lib/pkcs11/extensions.rb +68 -0
- data/lib/pkcs11/helper.rb +144 -0
- data/lib/pkcs11/library.rb +140 -0
- data/lib/pkcs11/object.rb +171 -0
- data/lib/pkcs11/session.rb +765 -0
- data/lib/pkcs11/slot.rb +102 -0
- data/pkcs11_protect_server/Manifest.txt +14 -0
- data/pkcs11_protect_server/README_PROTECT_SERVER.rdoc +89 -0
- data/test/fixtures/softokn/cert8.db +0 -0
- data/test/fixtures/softokn/key3.db +0 -0
- data/test/fixtures/softokn/secmod.db +0 -0
- data/test/helper.rb +58 -0
- data/test/test_pkcs11.rb +71 -0
- data/test/test_pkcs11_crypt.rb +220 -0
- data/test/test_pkcs11_object.rb +122 -0
- data/test/test_pkcs11_session.rb +123 -0
- data/test/test_pkcs11_slot.rb +78 -0
- data/test/test_pkcs11_structs.rb +166 -0
- data/test/test_pkcs11_thread.rb +44 -0
- metadata +213 -0
- metadata.gz.sig +0 -0
data/lib/pkcs11/slot.rb
ADDED
@@ -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.
|
Binary file
|
Binary file
|
Binary file
|
data/test/helper.rb
ADDED
@@ -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
|
data/test/test_pkcs11.rb
ADDED
@@ -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
|