pkcs11 0.2.4-x64-mingw32
Sign up to get free protection for your applications and to get access to all the features.
- 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
|