pkcs11 0.1.0 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.yardopts +2 -0
- data/History.txt +23 -0
- data/Manifest.txt +6 -0
- data/README.rdoc +28 -15
- data/Rakefile +51 -2
- data/ext/extconf.rb +1 -0
- data/ext/generate_structs.rb +157 -0
- data/ext/generate_thread_funcs.rb +72 -0
- data/ext/pk11.c +482 -252
- data/ext/pk11.h +4 -1
- data/ext/pk11_const.c +25 -476
- data/ext/pk11_const_def.inc +452 -0
- data/ext/pk11_struct_def.inc +304 -0
- data/ext/pk11_struct_impl.inc +304 -0
- data/ext/pk11_thread_funcs.c +411 -0
- data/ext/pk11_thread_funcs.h +482 -0
- data/lib/pkcs11.rb +5 -8
- data/lib/pkcs11/extensions.rb +17 -109
- data/lib/pkcs11/helper.rb +151 -0
- data/lib/pkcs11/library.rb +44 -13
- data/lib/pkcs11/object.rb +73 -17
- data/lib/pkcs11/session.rb +318 -121
- data/lib/pkcs11/slot.rb +30 -9
- data/test/helper.rb +13 -6
- data/test/test_pkcs11.rb +13 -2
- data/test/test_pkcs11_crypt.rb +38 -3
- data/test/test_pkcs11_object.rb +18 -4
- data/test/test_pkcs11_session.rb +28 -2
- data/test/test_pkcs11_slot.rb +9 -6
- data/test/test_pkcs11_structs.rb +134 -0
- data/test/test_pkcs11_thread.rb +45 -0
- metadata +40 -7
data/lib/pkcs11.rb
CHANGED
@@ -1,12 +1,9 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
|
3
|
-
#
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
require "#{major_minor}/pkcs11_ext"
|
8
|
-
else
|
9
|
-
require 'pkcs11_ext'
|
10
|
-
end
|
3
|
+
# Extend the search path for Windows binary gem, depending of the current ruby version
|
4
|
+
major_minor = RUBY_VERSION[ /^(\d+\.\d+)/ ] or
|
5
|
+
raise "Oops, can't extract the major/minor version from #{RUBY_VERSION.dump}"
|
6
|
+
$: << File.join(File.dirname(__FILE__), major_minor)
|
11
7
|
|
8
|
+
require 'pkcs11_ext'
|
12
9
|
require 'pkcs11/extensions'
|
data/lib/pkcs11/extensions.rb
CHANGED
@@ -7,14 +7,13 @@ require 'pkcs11/object'
|
|
7
7
|
#
|
8
8
|
# This library allowes to use PKCS#11 librarys in Ruby MRI.
|
9
9
|
#
|
10
|
-
#
|
11
|
-
#
|
10
|
+
# @example
|
12
11
|
# pkcs11 = PKCS11.open("/path/to/pkcs11.so")
|
13
12
|
# slot = pkcs11.active_slots.first
|
14
13
|
# p slot.info
|
15
14
|
# session = slot.open(PKCS11::CKF_SERIAL_SESSION|PKCS11::CKF_RW_SESSION)
|
16
15
|
# session.login(:USER, "1234")
|
17
|
-
# ...
|
16
|
+
# # ... crypto operations
|
18
17
|
# session.logout
|
19
18
|
# session.close
|
20
19
|
#
|
@@ -25,136 +24,45 @@ module PKCS11
|
|
25
24
|
# Open a PKCS#11 library file.
|
26
25
|
alias new open
|
27
26
|
end
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
(self.methods - ::Object.new.methods - InspectableStruct.instance_methods).grep(/[^=]$/).sort
|
33
|
-
end
|
34
|
-
# Array of the InspectableStruct's attribute values.
|
27
|
+
|
28
|
+
# Base class of all PKCS#11 structs.
|
29
|
+
class CStruct
|
30
|
+
# @return [Array<String>] attribute names
|
35
31
|
def values
|
36
32
|
members.inject([]){|a,v| a << send(v) }
|
37
33
|
end
|
38
|
-
# Hash with
|
34
|
+
# @return [Hash] with attribute names and current values
|
39
35
|
def to_hash
|
40
36
|
members.inject({}){|h,v| h[v.intern] = send(v); h }
|
41
37
|
end
|
42
|
-
def inspect
|
38
|
+
def inspect
|
43
39
|
"#<#{self.class} #{to_hash.map{|k,v| "#{k}=#{v.inspect}"}.join(", ") }>"
|
44
40
|
end
|
45
41
|
end
|
46
42
|
|
47
|
-
|
48
|
-
|
43
|
+
# Struct to hold an attribute type and it's value.
|
44
|
+
#
|
45
|
+
# @see PKCS11::Object
|
46
|
+
class CK_ATTRIBUTE
|
47
|
+
# @return [Array<String>] attribute names
|
49
48
|
def members
|
50
49
|
['type', 'value']
|
51
50
|
end
|
52
|
-
# Array
|
51
|
+
# @return [Array<String, Boolean, Integer>] attribute values
|
53
52
|
def values
|
54
53
|
members.inject([]){|a,v| a << send(v) }
|
55
54
|
end
|
56
|
-
# Hash with
|
55
|
+
# @return [Hash] with attribute names and current values
|
57
56
|
def to_hash
|
58
57
|
members.inject({}){|h,v| h[v.intern] = send(v); h }
|
59
58
|
end
|
60
59
|
# Get the constant name as String of the given value.
|
61
|
-
# Returns <tt>nil</tt> if value is unknown
|
60
|
+
# @return [String, nil] Returns <tt>nil</tt> if value is unknown
|
62
61
|
def to_s
|
63
62
|
ATTRIBUTES[type]
|
64
63
|
end
|
65
|
-
def inspect # :nodoc:
|
66
|
-
"#<#{self.class} #{ to_s ? "#{to_s} (#{type})" : type} value=#{value.inspect}>"
|
67
|
-
end
|
68
|
-
end
|
69
|
-
|
70
|
-
# See InspectableStruct.
|
71
|
-
class CK_INFO
|
72
|
-
include InspectableStruct
|
73
|
-
end
|
74
|
-
# See InspectableStruct.
|
75
|
-
class CK_C_INITIALIZE_ARGS
|
76
|
-
include InspectableStruct
|
77
|
-
end
|
78
|
-
# See InspectableStruct.
|
79
|
-
class CK_ATTRIBUTE
|
80
|
-
include InspectableAttribute
|
81
|
-
end
|
82
|
-
# See InspectableStruct.
|
83
|
-
class CK_TOKEN_INFO
|
84
|
-
include InspectableStruct
|
85
|
-
end
|
86
|
-
# See InspectableStruct.
|
87
|
-
class CK_SLOT_INFO
|
88
|
-
include InspectableStruct
|
89
|
-
end
|
90
|
-
# See InspectableStruct.
|
91
|
-
class CK_MECHANISM_INFO
|
92
|
-
include InspectableStruct
|
93
|
-
end
|
94
|
-
# See InspectableStruct.
|
95
|
-
class CK_SESSION_INFO
|
96
|
-
include InspectableStruct
|
97
|
-
end
|
98
|
-
# See InspectableStruct.
|
99
|
-
class CK_MECHANISM
|
100
|
-
include InspectableStruct
|
101
|
-
end
|
102
|
-
|
103
|
-
class ConstValue
|
104
|
-
def initialize(enum_hash, value) # :nodoc:
|
105
|
-
@enum_hash, @value = enum_hash, value
|
106
|
-
end
|
107
|
-
|
108
|
-
# Get the constant name as String of the given value.
|
109
|
-
# Returns <tt>nil</tt> if value is unknown.
|
110
|
-
def to_s
|
111
|
-
@enum_hash[@value]
|
112
|
-
end
|
113
64
|
def inspect
|
114
|
-
|
115
|
-
@value.inspect
|
116
|
-
end
|
117
|
-
|
118
|
-
# The value of the constant.
|
119
|
-
def to_int
|
120
|
-
@value
|
121
|
-
end
|
122
|
-
alias to_i to_int
|
123
|
-
end
|
124
|
-
|
125
|
-
module ConstValueHash # :nodoc:
|
126
|
-
def [](value)
|
127
|
-
super(value.to_int)
|
128
|
-
end
|
129
|
-
end
|
130
|
-
|
131
|
-
class << self
|
132
|
-
def extend_ConstValueHash(hash_symb) # :nodoc:
|
133
|
-
# The MECHANISMS, ATTRIBUTES, etc. Hashs are freezed.
|
134
|
-
# So, we have make a copy, to extend the class.
|
135
|
-
my_HASH = const_get(hash_symb).dup
|
136
|
-
my_HASH.extend ConstValueHash
|
137
|
-
my_HASH.freeze
|
138
|
-
const_set("UNWRAPPED_#{hash_symb}", hash_symb)
|
139
|
-
remove_const(hash_symb)
|
140
|
-
const_set(hash_symb, my_HASH)
|
65
|
+
"#<#{self.class} #{ to_s ? "#{to_s} (#{type})" : type} value=#{value.inspect}>"
|
141
66
|
end
|
142
|
-
private :extend_ConstValueHash
|
143
|
-
end
|
144
|
-
|
145
|
-
extend_ConstValueHash(:OBJECT_CLASSES)
|
146
|
-
class ObjectClass < ConstValue
|
147
67
|
end
|
148
|
-
|
149
|
-
extend_ConstValueHash(:ATTRIBUTES)
|
150
|
-
class Attribute < ConstValue
|
151
|
-
end
|
152
|
-
|
153
|
-
extend_ConstValueHash(:MECHANISMS)
|
154
|
-
class Mechanism < ConstValue
|
155
|
-
end
|
156
|
-
|
157
|
-
# extend_ConstValueHash(:RETURN_VALUES)
|
158
|
-
# class ReturnValue < ConstValue
|
159
|
-
# end
|
160
68
|
end
|
@@ -0,0 +1,151 @@
|
|
1
|
+
module PKCS11
|
2
|
+
# Some functions internaly used to make the API more convenient.
|
3
|
+
# @private
|
4
|
+
module Helper # :nodoc:
|
5
|
+
private
|
6
|
+
|
7
|
+
MechanismParameters = {
|
8
|
+
CKM_RSA_PKCS_OAEP => CK_RSA_PKCS_OAEP_PARAMS,
|
9
|
+
CKM_RSA_PKCS_PSS => CK_RSA_PKCS_PSS_PARAMS,
|
10
|
+
CKM_SHA1_RSA_PKCS_PSS => CK_RSA_PKCS_PSS_PARAMS,
|
11
|
+
CKM_SHA256_RSA_PKCS_PSS => CK_RSA_PKCS_PSS_PARAMS,
|
12
|
+
CKM_SHA384_RSA_PKCS_PSS => CK_RSA_PKCS_PSS_PARAMS,
|
13
|
+
CKM_SHA512_RSA_PKCS_PSS => CK_RSA_PKCS_PSS_PARAMS,
|
14
|
+
CKM_ECDH1_DERIVE => CK_ECDH1_DERIVE_PARAMS,
|
15
|
+
CKM_ECDH1_COFACTOR_DERIVE => CK_ECDH1_DERIVE_PARAMS,
|
16
|
+
CKM_ECMQV_DERIVE => CK_ECMQV_DERIVE_PARAMS,
|
17
|
+
CKM_X9_42_DH_DERIVE => CK_X9_42_DH1_DERIVE_PARAMS,
|
18
|
+
# CKM_X9_42_MQV_DERIVE => CK_X9_42_DH2_DERIVE_PARAMS,
|
19
|
+
CKM_X9_42_DH_HYBRID_DERIVE => CK_X9_42_DH2_DERIVE_PARAMS,
|
20
|
+
CKM_X9_42_MQV_DERIVE => CK_X9_42_MQV_DERIVE_PARAMS,
|
21
|
+
CKM_KEA_KEY_DERIVE => CK_KEA_DERIVE_PARAMS,
|
22
|
+
CKM_RC2_CBC => CK_RC2_CBC_PARAMS,
|
23
|
+
CKM_RC2_CBC_PAD => CK_RC2_CBC_PARAMS,
|
24
|
+
CKM_RC2_MAC_GENERAL => CK_RC2_MAC_GENERAL_PARAMS,
|
25
|
+
CKM_RC5_MAC => CK_RC5_PARAMS,
|
26
|
+
CKM_RC5_ECB => CK_RC5_PARAMS,
|
27
|
+
CKM_RC5_CBC => CK_RC5_CBC_PARAMS,
|
28
|
+
CKM_RC5_CBC_PAD => CK_RC5_CBC_PARAMS,
|
29
|
+
CKM_RC5_MAC_GENERAL => CK_RC5_MAC_GENERAL_PARAMS,
|
30
|
+
|
31
|
+
CKM_SKIPJACK_PRIVATE_WRAP => CK_SKIPJACK_PRIVATE_WRAP_PARAMS,
|
32
|
+
CKM_SKIPJACK_RELAYX => CK_SKIPJACK_RELAYX_PARAMS,
|
33
|
+
CKM_PBE_MD2_DES_CBC => CK_PBE_PARAMS,
|
34
|
+
CKM_PBE_MD5_DES_CBC => CK_PBE_PARAMS,
|
35
|
+
CKM_PBE_MD5_CAST_CBC => CK_PBE_PARAMS,
|
36
|
+
CKM_PBE_MD5_CAST3_CBC => CK_PBE_PARAMS,
|
37
|
+
CKM_PBE_MD5_CAST5_CBC => CK_PBE_PARAMS,
|
38
|
+
CKM_PBE_MD5_CAST128_CBC => CK_PBE_PARAMS,
|
39
|
+
CKM_PBE_SHA1_CAST5_CBC => CK_PBE_PARAMS,
|
40
|
+
CKM_PBE_SHA1_CAST128_CBC => CK_PBE_PARAMS,
|
41
|
+
CKM_PBE_SHA1_RC4_128 => CK_PBE_PARAMS,
|
42
|
+
CKM_PBE_SHA1_RC4_40 => CK_PBE_PARAMS,
|
43
|
+
CKM_PBE_SHA1_DES3_EDE_CBC => CK_PBE_PARAMS,
|
44
|
+
CKM_PBE_SHA1_DES2_EDE_CBC => CK_PBE_PARAMS,
|
45
|
+
CKM_PBE_SHA1_RC2_128_CBC => CK_PBE_PARAMS,
|
46
|
+
CKM_PBE_SHA1_RC2_40_CBC => CK_PBE_PARAMS,
|
47
|
+
CKM_PBA_SHA1_WITH_SHA1_HMAC => CK_PBE_PARAMS,
|
48
|
+
CKM_PKCS5_PBKD2 => CK_PKCS5_PBKD2_PARAMS,
|
49
|
+
CKM_KEY_WRAP_SET_OAEP => CK_KEY_WRAP_SET_OAEP_PARAMS,
|
50
|
+
CKM_SSL3_MASTER_KEY_DERIVE => CK_SSL3_RANDOM_DATA,
|
51
|
+
CKM_SSL3_KEY_AND_MAC_DERIVE => CK_SSL3_RANDOM_DATA,
|
52
|
+
CKM_SSL3_MASTER_KEY_DERIVE => CK_SSL3_MASTER_KEY_DERIVE_PARAMS,
|
53
|
+
CKM_SSL3_KEY_AND_MAC_DERIVE => CK_SSL3_KEY_MAT_OUT,
|
54
|
+
CKM_SSL3_KEY_AND_MAC_DERIVE => CK_SSL3_KEY_MAT_PARAMS,
|
55
|
+
CKM_TLS_MASTER_KEY_DERIVE => CK_SSL3_MASTER_KEY_DERIVE_PARAMS,
|
56
|
+
CKM_TLS_PRF => CK_TLS_PRF_PARAMS,
|
57
|
+
CKM_WTLS_MASTER_KEY_DERIVE => CK_WTLS_RANDOM_DATA,
|
58
|
+
CKM_WTLS_MASTER_KEY_DERIVE => CK_WTLS_MASTER_KEY_DERIVE_PARAMS,
|
59
|
+
CKM_WTLS_PRF => CK_WTLS_PRF_PARAMS,
|
60
|
+
CKM_WTLS_SERVER_KEY_AND_MAC_DERIVE => CK_WTLS_KEY_MAT_PARAMS,
|
61
|
+
CKM_WTLS_CLIENT_KEY_AND_MAC_DERIVE => CK_WTLS_KEY_MAT_PARAMS,
|
62
|
+
CKM_CMS_SIG => CK_CMS_SIG_PARAMS,
|
63
|
+
|
64
|
+
CKM_DES_ECB_ENCRYPT_DATA => CK_KEY_DERIVATION_STRING_DATA,
|
65
|
+
CKM_DES_CBC_ENCRYPT_DATA => CK_DES_CBC_ENCRYPT_DATA_PARAMS,
|
66
|
+
CKM_DES3_ECB_ENCRYPT_DATA => CK_KEY_DERIVATION_STRING_DATA,
|
67
|
+
CKM_DES3_CBC_ENCRYPT_DATA => CK_DES_CBC_ENCRYPT_DATA_PARAMS,
|
68
|
+
CKM_AES_ECB_ENCRYPT_DATA => CK_KEY_DERIVATION_STRING_DATA,
|
69
|
+
CKM_AES_CBC_ENCRYPT_DATA => CK_AES_CBC_ENCRYPT_DATA_PARAMS,
|
70
|
+
CKM_CONCATENATE_BASE_AND_DATA => CK_KEY_DERIVATION_STRING_DATA,
|
71
|
+
CKM_CONCATENATE_DATA_AND_BASE => CK_KEY_DERIVATION_STRING_DATA,
|
72
|
+
CKM_XOR_BASE_AND_DATA => CK_KEY_DERIVATION_STRING_DATA,
|
73
|
+
|
74
|
+
CKM_ARIA_ECB_ENCRYPT_DATA => CK_KEY_DERIVATION_STRING_DATA,
|
75
|
+
CKM_ARIA_CBC_ENCRYPT_DATA => CK_ARIA_CBC_ENCRYPT_DATA_PARAMS,
|
76
|
+
|
77
|
+
CKM_SSL3_PRE_MASTER_KEY_GEN => CK_VERSION,
|
78
|
+
CKM_TLS_PRE_MASTER_KEY_GEN => CK_VERSION,
|
79
|
+
=begin
|
80
|
+
# for PKCS#11 v2.30
|
81
|
+
CKM_SEED_ECB_ENCRYPT_DATA => CK_KEY_DERIVATION_STRING_DATA,
|
82
|
+
CKM_SEED_CBC_ENCRYPT_DATA => CK_CBC_ENCRYPT_DATA_PARAMS,
|
83
|
+
CKM_GOSTR3410_KEY_WRAP => CK_GOSTR3410_KEY_WRAP_PARAMS,
|
84
|
+
CKM_GOSTR3410_DERIVE => CK_GOSTR3410_DERIVE_PARAMS,
|
85
|
+
CKM_GOSTR3410_KEY_WRAP => CK_GOSTR3410_KEY_WRAP_PARAMS,
|
86
|
+
=end
|
87
|
+
}
|
88
|
+
|
89
|
+
def to_attributes(template)
|
90
|
+
case template
|
91
|
+
when Array
|
92
|
+
template.map{|v| PKCS11::CK_ATTRIBUTE.new(string_to_handle('CKA_', v), nil) }
|
93
|
+
when Hash
|
94
|
+
template.map{|k,v| PKCS11::CK_ATTRIBUTE.new(string_to_handle('CKA_', k), v) }
|
95
|
+
when String, Symbol
|
96
|
+
[PKCS11::CK_ATTRIBUTE.new(string_to_handle('CKA_', template), nil)]
|
97
|
+
when Integer
|
98
|
+
[PKCS11::CK_ATTRIBUTE.new(template, nil)]
|
99
|
+
else
|
100
|
+
template
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
def string_to_handle(prefix, attribute) # :nodoc:
|
105
|
+
case attribute
|
106
|
+
when String, Symbol
|
107
|
+
PKCS11.const_get("#{prefix}#{attribute}")
|
108
|
+
else
|
109
|
+
attribute
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
def to_mechanism(mechanism) # :nodoc:
|
114
|
+
case mechanism
|
115
|
+
when String, Symbol
|
116
|
+
PKCS11::CK_MECHANISM.new(string_to_handle('CKM_', mechanism))
|
117
|
+
when Hash
|
118
|
+
raise "only one mechanism allowed" unless mechanism.length==1
|
119
|
+
|
120
|
+
mech = string_to_handle('CKM_', mechanism.keys.first)
|
121
|
+
param = mechanism.values.first
|
122
|
+
case param
|
123
|
+
when Hash
|
124
|
+
param_class = MechanismParameters[mech]
|
125
|
+
raise ArgumentError, "unknown mechanism - please use mechanism parameter as String" unless param_class
|
126
|
+
|
127
|
+
pa = param_class.new
|
128
|
+
param.each do |k, v|
|
129
|
+
pa.send "#{k}=", v
|
130
|
+
end
|
131
|
+
param = pa
|
132
|
+
end
|
133
|
+
|
134
|
+
PKCS11::CK_MECHANISM.new(mech, param)
|
135
|
+
when Fixnum
|
136
|
+
PKCS11::CK_MECHANISM.new(mechanism)
|
137
|
+
else
|
138
|
+
mechanism
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
def to_mechanism_int(mechanism) # :nodoc:
|
143
|
+
case mechanism
|
144
|
+
when String, Symbol
|
145
|
+
PKCS11::MECHANISMS[string_to_handle('CKM_', mechanism)]
|
146
|
+
else
|
147
|
+
mechanism
|
148
|
+
end
|
149
|
+
end
|
150
|
+
end
|
151
|
+
end
|
data/lib/pkcs11/library.rb
CHANGED
@@ -1,13 +1,40 @@
|
|
1
1
|
module PKCS11
|
2
2
|
# A Library instance holds a handle to the opened PKCS#11 - dll or so file.
|
3
|
+
#
|
4
|
+
# == Low layer API
|
5
|
+
# The API of the binding consists of a lower layer, which
|
6
|
+
# is near to the PKCS#11 C interface, and a higher layer, which
|
7
|
+
# is more Ruby like and more comfortable. The low layer is currently
|
8
|
+
# not explicitly documented and is not recommented to use.
|
9
|
+
#
|
10
|
+
# All low layer PKCS#11 functions can be called on the {PKCS11::Library} object.
|
11
|
+
# Example for starting a session:
|
12
|
+
# pkcs11 = PKCS11.open("/path/to/pkcs11.so")
|
13
|
+
# slot = pkcs11.C_GetSlotList(true).first
|
14
|
+
# session = pkcs11.C_OpenSession(slot, PKCS11::CKF_SERIAL_SESSION | PKCS11::CKF_RW_SESSION)
|
15
|
+
# pkcs11.C_Login(session, PKCS11::CKU_USER, "password")
|
16
|
+
#
|
17
|
+
# The same on the high layer:
|
18
|
+
# pkcs11 = PKCS11.open("/path/to/pkcs11.so")
|
19
|
+
# session = pkcs11.active_slots.first.open
|
20
|
+
# session.login(:USER, "password")
|
3
21
|
class Library
|
22
|
+
# @private
|
4
23
|
alias unwrapped_initialize initialize # :nodoc:
|
5
24
|
|
6
25
|
# Load and initialize a pkcs11 dynamic library.
|
7
26
|
#
|
8
|
-
# so_path
|
9
|
-
# args
|
10
|
-
|
27
|
+
# @param [String, nil] so_path Path to the *.so or *.dll file to load.
|
28
|
+
# @param [Hash, CK_C_INITIALIZE_ARGS] args A Hash or CK_C_INITIALIZE_ARGS instance with load params.
|
29
|
+
#
|
30
|
+
# If so_path is +nil+ no library is loaded or initialized.
|
31
|
+
# In this case the calls to {#load_library}, {#C_GetFunctionList} and
|
32
|
+
# {#C_Initialize} have to be done manually, before using other methods:
|
33
|
+
# pkcs11 = PKCS11::Library.new
|
34
|
+
# pkcs11.load_library(so_path)
|
35
|
+
# pkcs11.C_GetFunctionList
|
36
|
+
# pkcs11.C_Initialize(args)
|
37
|
+
def initialize(so_path=nil, args={})
|
11
38
|
case args
|
12
39
|
when Hash
|
13
40
|
pargs = CK_C_INITIALIZE_ARGS.new
|
@@ -20,6 +47,7 @@ module PKCS11
|
|
20
47
|
|
21
48
|
alias unwrapped_C_GetInfo C_GetInfo
|
22
49
|
# Returns general information about Cryptoki.
|
50
|
+
# @return [CK_INFO]
|
23
51
|
def C_GetInfo
|
24
52
|
unwrapped_C_GetInfo
|
25
53
|
end
|
@@ -27,9 +55,12 @@ module PKCS11
|
|
27
55
|
|
28
56
|
alias unwrapped_C_GetSlotList C_GetSlotList
|
29
57
|
|
30
|
-
# Obtain an array of Slot objects in the system.
|
31
|
-
#
|
32
|
-
#
|
58
|
+
# Obtain an array of Slot objects in the system.
|
59
|
+
#
|
60
|
+
# @param [true, false] tokenPresent indicates whether the list
|
61
|
+
# obtained includes only those slots with a token present (true), or
|
62
|
+
# all slots (false);
|
63
|
+
# @return [Array<Slot>]
|
33
64
|
def C_GetSlotList(tokenPresent=true)
|
34
65
|
slots = unwrapped_C_GetSlotList(tokenPresent)
|
35
66
|
slots.map{|slot|
|
@@ -39,25 +70,25 @@ module PKCS11
|
|
39
70
|
alias slots C_GetSlotList
|
40
71
|
|
41
72
|
# Obtain an array of Slot objects in the system with a token present.
|
73
|
+
# @return [Array<Slot>]
|
42
74
|
def active_slots
|
43
75
|
slots(true)
|
44
76
|
end
|
45
77
|
|
46
78
|
# Obtain an array of Slot objects in the system regardless if a token is present.
|
79
|
+
# @return [Array<Slot>]
|
47
80
|
def all_slots
|
48
81
|
slots(false)
|
49
82
|
end
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
83
|
+
|
84
|
+
# Finalize and unload the library. If not called explicit, the library is freed by the GC.
|
85
|
+
def close
|
86
|
+
self.C_Finalize
|
87
|
+
self.unload_library
|
55
88
|
end
|
56
|
-
alias close C_Finalize
|
57
89
|
|
58
90
|
private :unwrapped_initialize
|
59
91
|
private :unwrapped_C_GetSlotList
|
60
|
-
private :unwrapped_C_Finalize
|
61
92
|
private :unwrapped_C_GetInfo
|
62
93
|
end
|
63
94
|
end
|
data/lib/pkcs11/object.rb
CHANGED
@@ -1,33 +1,47 @@
|
|
1
|
+
require 'pkcs11/helper'
|
2
|
+
|
1
3
|
module PKCS11
|
2
|
-
# Cryptoki
|
4
|
+
# Cryptoki's logical view of a token is a device that stores objects and can perform
|
3
5
|
# cryptographic functions. Cryptoki defines three classes of object: data, certificates, and
|
4
6
|
# keys.
|
5
7
|
#
|
6
8
|
# Attributes are characteristics that distinguish an instance of an object.
|
7
9
|
class Object
|
10
|
+
include Helper
|
11
|
+
|
12
|
+
# @private
|
8
13
|
def initialize(pkcs11, session, object) # :nodoc:
|
9
14
|
@pk, @sess, @obj = pkcs11, session, object
|
10
15
|
end
|
11
16
|
|
12
17
|
# The object handle.
|
18
|
+
# @return [Integer]
|
13
19
|
def to_int
|
14
20
|
@obj
|
15
21
|
end
|
16
22
|
alias to_i to_int
|
17
23
|
|
24
|
+
# @private
|
18
25
|
def inspect # :nodoc:
|
19
26
|
"#<#{self.class} #{@obj.inspect}>"
|
20
27
|
end
|
21
28
|
|
22
|
-
#
|
29
|
+
# Get the value of one attribute of the object.
|
23
30
|
#
|
24
|
-
# attribute
|
31
|
+
# @param [String, Symbol, Integer] attribute can be String or Symbol of the attribute constant
|
25
32
|
# or the attribute number as Integer.
|
26
33
|
#
|
27
|
-
#
|
28
|
-
#
|
29
|
-
# Unknown attributes (out of PKCS#11 v2.2) are not converted
|
34
|
+
# @return [String, Integer, Boolean, nil] the attribute value as String, Integer or true/false
|
35
|
+
# depending on the attribute type.
|
36
|
+
# Unknown attributes (out of PKCS#11 v2.2) are not converted to adequate
|
37
|
+
# ruby objects but returned as String.
|
30
38
|
# That is true/false will be returned as "\\001" respectively "\\000".
|
39
|
+
#
|
40
|
+
# @example
|
41
|
+
# object[:VALUE] # => "\000\000\000\000\000\000\000\000"
|
42
|
+
# object[:MODULUS_BITS] # => 768
|
43
|
+
#
|
44
|
+
# See PKCS#11 for attribute definitions.
|
31
45
|
def [](attribute)
|
32
46
|
attrs = C_GetAttributeValue( [attribute] )
|
33
47
|
attrs.first.value unless attrs.empty?
|
@@ -35,39 +49,52 @@ module PKCS11
|
|
35
49
|
|
36
50
|
# Modifies the value of one attribute the object.
|
37
51
|
#
|
38
|
-
# attribute
|
52
|
+
# @param [String, Symbol, Integer] attribute can be String or Symbol of the attribute constant
|
39
53
|
# or the attribute value as Integer.
|
40
|
-
#
|
54
|
+
# @param [String, Integer, Boolean, nil] value value the attribute will be set to.
|
41
55
|
#
|
42
|
-
# Following value conversations are done:
|
56
|
+
# Following value conversations are done from Ruby to C:
|
43
57
|
# true -> 0x01
|
44
58
|
# false -> 0x00
|
45
59
|
# nil -> NULL pointer
|
46
60
|
# Fixnum -> binary encoded unsigned long
|
61
|
+
#
|
62
|
+
# @example
|
63
|
+
# object[:VALUE] = "\000\000\000\000\000\000\000\000"
|
64
|
+
# object[:MODULUS_BITS] = 768
|
65
|
+
#
|
66
|
+
# See PKCS#11 for attribute definitions.
|
67
|
+
# @return value
|
47
68
|
def []=(attribute, value)
|
48
69
|
C_SetAttributeValue( attribute => value )
|
70
|
+
value
|
49
71
|
end
|
50
72
|
|
51
73
|
# Modifies the value of one or more attributes of the object in a single call.
|
52
74
|
#
|
53
|
-
#
|
75
|
+
# @example
|
54
76
|
# object.attributes = {:SUBJECT => cert_subject, PKCS11::CKA_VALUE => cert_data}
|
77
|
+
# @return template
|
55
78
|
def C_SetAttributeValue(template={})
|
56
|
-
|
57
|
-
|
79
|
+
@pk.C_SetAttributeValue(@sess, @obj, to_attributes(template))
|
80
|
+
template
|
58
81
|
end
|
59
82
|
alias attributes= C_SetAttributeValue
|
60
83
|
|
61
84
|
# Obtains the value of one or more attributes of the object in a single call.
|
62
85
|
#
|
86
|
+
# @param [Array<String, Symbol, Integer>, Hash, String, Integer] attribute attribute names
|
87
|
+
# whose values should be returned
|
88
|
+
#
|
63
89
|
# Without params all known attributes are tried to read from the Object.
|
64
90
|
# This is significant slower then naming the needed attributes and should
|
65
91
|
# be used for debug purposes only.
|
66
92
|
#
|
67
|
-
#
|
93
|
+
# @return [Array<PKCS11::CK_ATTRIBUTE>] Requested attributes with values.
|
68
94
|
#
|
69
|
-
#
|
70
|
-
# certificate.attributes :
|
95
|
+
# @example
|
96
|
+
# certificate.attributes :VALUE, :CLASS
|
97
|
+
# => [#<PKCS11::CK_ATTRIBUTE CKA_VALUE (17) value="0\x82...">, #<PKCS11::CK_ATTRIBUTE CKA_CLASS (0) value=1>]
|
71
98
|
def C_GetAttributeValue(*template)
|
72
99
|
case template.length
|
73
100
|
when 0
|
@@ -80,21 +107,50 @@ module PKCS11
|
|
80
107
|
when 1
|
81
108
|
template = template[0]
|
82
109
|
end
|
83
|
-
template =
|
110
|
+
template = to_attributes template
|
84
111
|
@pk.C_GetAttributeValue(@sess, @obj, template)
|
85
112
|
end
|
86
113
|
alias attributes C_GetAttributeValue
|
87
|
-
|
114
|
+
|
115
|
+
# Copies an object, creating a new object for the copy.
|
116
|
+
#
|
117
|
+
# @param [Hash] template
|
118
|
+
#
|
119
|
+
# The template may specify new values for any attributes of the object that can ordinarily
|
120
|
+
# be modified (e.g., in the course of copying a secret key, a key's CKA_EXTRACTABLE
|
121
|
+
# attribute may be changed from true to false, but not the other way around.
|
122
|
+
# If this change is made, the new key's CKA_NEVER_EXTRACTABLE attribute will
|
123
|
+
# have the value false. Similarly, the template may specify that the new key's
|
124
|
+
# CKA_SENSITIVE attribute be true; the new key will have the same value for its
|
125
|
+
# CKA_ALWAYS_SENSITIVE attribute as the original key). It may also specify new
|
126
|
+
# values of the CKA_TOKEN and CKA_PRIVATE attributes (e.g., to copy a session
|
127
|
+
# object to a token object). If the template specifies a value of an attribute which is
|
128
|
+
# incompatible with other existing attributes of the object, the call fails with exception
|
129
|
+
# CKR_TEMPLATE_INCONSISTENT.
|
130
|
+
#
|
131
|
+
# Only session objects can be created during a read-only session. Only public objects can
|
132
|
+
# be created unless the normal user is logged in.
|
133
|
+
#
|
134
|
+
# @return [PKCS11::Object] the newly created object
|
135
|
+
def C_CopyObject(template={})
|
136
|
+
handle = @pk.C_CopyObject(@sess, @obj, to_attributes(template))
|
137
|
+
Object.new @pk, @sess, handle
|
138
|
+
end
|
139
|
+
alias copy C_CopyObject
|
140
|
+
|
88
141
|
# Destroys the object.
|
89
142
|
#
|
90
143
|
# Only session objects can be destroyed during a read-only session. Only public objects
|
91
144
|
# can be destroyed unless the normal user is logged in.
|
145
|
+
# @return [PKCS11::Object]
|
92
146
|
def C_DestroyObject()
|
93
147
|
@pk.C_DestroyObject(@sess, @obj)
|
148
|
+
self
|
94
149
|
end
|
95
150
|
alias destroy C_DestroyObject
|
96
151
|
|
97
152
|
# Gets the size of an object in bytes.
|
153
|
+
# @return [Integer]
|
98
154
|
def C_GetObjectSize()
|
99
155
|
@pk.C_GetObjectSize(@sess, @obj)
|
100
156
|
end
|