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,6 @@
1
+ #ifndef RUBY_PK11_VERSION_H
2
+ #define RUBY_PK11_VERSION_H
3
+
4
+ static const char *VERSION = "0.2.4";
5
+
6
+ #endif
Binary file
@@ -0,0 +1,9 @@
1
+ #!/usr/bin/env ruby
2
+
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)
7
+
8
+ require 'pkcs11_ext'
9
+ require 'pkcs11/extensions'
@@ -0,0 +1,68 @@
1
+ require 'pkcs11/library'
2
+ require 'pkcs11/slot'
3
+ require 'pkcs11/session'
4
+ require 'pkcs11/object'
5
+
6
+ # Ruby connector to PKCS#11 libraries.
7
+ #
8
+ # This library allowes to use PKCS#11 librarys in Ruby MRI.
9
+ #
10
+ # @example
11
+ # pkcs11 = PKCS11.open("/path/to/pkcs11.so")
12
+ # slot = pkcs11.active_slots.first
13
+ # p slot.info
14
+ # session = slot.open(PKCS11::CKF_SERIAL_SESSION|PKCS11::CKF_RW_SESSION)
15
+ # session.login(:USER, "1234")
16
+ # # ... crypto operations
17
+ # session.logout
18
+ # session.close
19
+ #
20
+ # See unit tests in the <tt>test</tt> directory for further examples of the usage.
21
+ module PKCS11
22
+
23
+ class << self
24
+ # Open a PKCS#11 library file.
25
+ alias new open
26
+ end
27
+
28
+ # Base class of all PKCS#11 structs.
29
+ class CStruct
30
+ # @return [Array<String>] attribute names
31
+ def values
32
+ members.inject([]){|a,v| a << send(v) }
33
+ end
34
+ # @return [Hash] with attribute names and current values
35
+ def to_hash
36
+ members.inject({}){|h,v| h[v.intern] = send(v); h }
37
+ end
38
+ def inspect
39
+ "#<#{self.class} #{to_hash.map{|k,v| "#{k}=#{v.inspect}"}.join(", ") }>"
40
+ end
41
+ end
42
+
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
48
+ def members
49
+ ['type', 'value']
50
+ end
51
+ # @return [Array<String, Boolean, Integer>] attribute values
52
+ def values
53
+ members.inject([]){|a,v| a << send(v) }
54
+ end
55
+ # @return [Hash] with attribute names and current values
56
+ def to_hash
57
+ members.inject({}){|h,v| h[v.intern] = send(v); h }
58
+ end
59
+ # Get the constant name as String of the given value.
60
+ # @return [String, nil] Returns <tt>nil</tt> if value is unknown
61
+ def to_s
62
+ ATTRIBUTES[type]
63
+ end
64
+ def inspect
65
+ "#<#{self.class} #{ to_s ? "#{to_s} (#{type})" : type} value=#{value.inspect}>"
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,144 @@
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| @pk.vendor_class_CK_ATTRIBUTE.new(string_to_handle('CKA_', v), nil) }
93
+ when Hash
94
+ template.map{|k,v| @pk.vendor_class_CK_ATTRIBUTE.new(string_to_handle('CKA_', k), v) }
95
+ when String, Symbol
96
+ [@pk.vendor_class_CK_ATTRIBUTE.new(string_to_handle('CKA_', template), nil)]
97
+ when Integer
98
+ [@pk.vendor_class_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
+ @pk.vendor_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 = @pk.vendor_mechanism_parameter_struct(mech)
125
+ raise ArgumentError, "unknown mechanism - please use String/Int/Struct as mechanism parameter" 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
+ when Bignum
138
+ PKCS11::CK_MECHANISM.new(mechanism)
139
+ else
140
+ mechanism
141
+ end
142
+ end
143
+ end
144
+ end
@@ -0,0 +1,140 @@
1
+ module PKCS11
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")
21
+ class Library
22
+ # @private
23
+ alias unwrapped_initialize initialize # :nodoc:
24
+
25
+ # Load and initialize a pkcs11 dynamic library.
26
+ #
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={})
38
+ unwrapped_initialize(so_path, args)
39
+ end
40
+
41
+ alias unwrapped_C_Initialize C_Initialize
42
+ # Initialize a pkcs11 dynamic library.
43
+ #
44
+ # @param [Hash, CK_C_INITIALIZE_ARGS] args A Hash or CK_C_INITIALIZE_ARGS instance with load params.
45
+ def C_Initialize(args=nil)
46
+ case args
47
+ when Hash
48
+ pargs = CK_C_INITIALIZE_ARGS.new
49
+ args.each{|k,v| pargs.send("#{k}=", v) }
50
+ else
51
+ pargs = args
52
+ end
53
+ unwrapped_C_Initialize(pargs)
54
+ end
55
+
56
+ alias unwrapped_C_GetInfo C_GetInfo
57
+ # Returns general information about Cryptoki.
58
+ # @return [CK_INFO]
59
+ def C_GetInfo
60
+ unwrapped_C_GetInfo
61
+ end
62
+ alias info C_GetInfo
63
+
64
+ alias unwrapped_C_GetSlotList C_GetSlotList
65
+
66
+ # Obtain an array of Slot objects in the system.
67
+ #
68
+ # @param [true, false] tokenPresent indicates whether the list
69
+ # obtained includes only those slots with a token present (true), or
70
+ # all slots (false);
71
+ # @return [Array<Slot>]
72
+ def C_GetSlotList(tokenPresent=false)
73
+ slots = unwrapped_C_GetSlotList(tokenPresent)
74
+ slots.map{|slot|
75
+ Slot.new self, slot
76
+ }
77
+ end
78
+ alias slots C_GetSlotList
79
+
80
+ # Obtain an array of Slot objects in the system with a token present.
81
+ # @return [Array<Slot>]
82
+ def active_slots
83
+ slots(true)
84
+ end
85
+
86
+ # Obtain an array of Slot objects in the system regardless if a token is present.
87
+ # @return [Array<Slot>]
88
+ def all_slots
89
+ slots(false)
90
+ end
91
+
92
+ alias unwrapped_C_WaitForSlotEvent C_WaitForSlotEvent
93
+
94
+ # Waits for a slot event, such as token insertion or token removal, to occur.
95
+ #
96
+ # @param [Integer] flags determines whether or not the C_WaitForSlotEvent call blocks (i.e., waits
97
+ # for a slot event to occur);
98
+ # At present, the only flag defined for use in the flags argument is PKCS11::CKF_DONT_BLOCK
99
+ # @return [Slot, nil] the slot that the event occurred in; nil if no event occured (CKR_NO_EVENT)
100
+ def C_WaitForSlotEvent(flags=0)
101
+ slot = unwrapped_C_WaitForSlotEvent(flags)
102
+ slot ? Slot.new(self, slot) : nil
103
+ end
104
+ alias wait_for_slot_event C_WaitForSlotEvent
105
+
106
+ # Finalize and unload the library. If not called explicit, the library is freed by the GC.
107
+ def close
108
+ self.C_Finalize
109
+ self.unload_library
110
+ end
111
+
112
+ # Return the value of a named constant. Used for CKA_* and CKM_* .
113
+ # This method could be overloaded for vendor specific extensions.
114
+ #
115
+ # @param [String] name Name of the constant
116
+ # @return [Integer] Value of the constant
117
+ def vendor_const_get(name)
118
+ PKCS11.const_get(name)
119
+ end
120
+
121
+ # Return an array of all known CKA_* attributes as String.
122
+ # This method could be overloaded for vendor specific extensions.
123
+ def vendor_all_attribute_names
124
+ return ATTRIBUTES.values
125
+ end
126
+
127
+ # Return the parameter struct of a given mechanism.
128
+ # This method could be overloaded for vendor specific extensions.
129
+ #
130
+ # @param [Integer] mech Mechanism
131
+ # @return [PKCS11::CStruct] appropriate class as parameter for the mechanism
132
+ def vendor_mechanism_parameter_struct(mech)
133
+ Helper::MechanismParameters[mech]
134
+ end
135
+
136
+ private :unwrapped_initialize
137
+ private :unwrapped_C_GetSlotList
138
+ private :unwrapped_C_GetInfo
139
+ end
140
+ end
@@ -0,0 +1,171 @@
1
+ require 'pkcs11/helper'
2
+
3
+ module PKCS11
4
+ # Cryptoki's logical view of a token is a device that stores objects and can perform
5
+ # cryptographic functions. Cryptoki defines three classes of object: data, certificates, and
6
+ # keys.
7
+ #
8
+ # Attributes are characteristics that distinguish an instance of an object.
9
+ class Object
10
+ include Helper
11
+
12
+ # @private
13
+ def initialize(pkcs11, session, object) # :nodoc:
14
+ @pk, @sess, @obj = pkcs11, session, object
15
+ end
16
+
17
+ # The object handle.
18
+ # @return [Integer]
19
+ def to_int
20
+ @obj
21
+ end
22
+ alias to_i to_int
23
+
24
+ # @private
25
+ def inspect # :nodoc:
26
+ "#<#{self.class} #{@obj.inspect}>"
27
+ end
28
+
29
+ # Get the value of one or several attributes of the object.
30
+ #
31
+ # @param [String, Symbol, Integer, Array] attribute can be String or Symbol
32
+ # of the attribute(s) constant or the attribute(s) number as Integer.
33
+ #
34
+ # @return [String, Integer, Boolean, Array, nil] the attribute value as String,
35
+ # Integer or true/false depending on the attribute type.
36
+ # If called with more than one parameter or with an Array, a Array
37
+ # of attribute values is returned.
38
+ # Unknown attributes (out of PKCS#11 v2.2) are not converted to adequate
39
+ # ruby objects but returned as String.
40
+ # That is true/false will be returned as "\\001" respectively "\\000".
41
+ #
42
+ # @example
43
+ # object[:VALUE] # => "\000\000\000\000\000\000\000\000"
44
+ # object[:MODULUS_BITS] # => 768
45
+ # object[:MODULUS_BITS, :LABEL] # => [1024, "MyKey"]
46
+ #
47
+ # See PKCS#11 for attribute definitions.
48
+ def [](*attributes)
49
+ attrs = C_GetAttributeValue( attributes.flatten )
50
+ if attrs.length>1 || attributes.first.kind_of?(Array)
51
+ attrs.map(&:value)
52
+ else
53
+ attrs.first.value unless attrs.empty?
54
+ end
55
+ end
56
+
57
+ # Modifies the value of one or several attributes of the object.
58
+ #
59
+ # @param [String, Symbol, Integer] attribute can be String or Symbol of the attribute constant
60
+ # or the attribute value as Integer.
61
+ # @param [String, Integer, Boolean, Array, nil] value value(s) the attribute(s) will be set to.
62
+ #
63
+ # Following value conversations are done from Ruby to C:
64
+ # true -> 0x01
65
+ # false -> 0x00
66
+ # nil -> NULL pointer
67
+ # Fixnum -> binary encoded unsigned long
68
+ #
69
+ # @example
70
+ # object[:VALUE] = "\000\000\000\000\000\000\000\000"
71
+ # object[:MODULUS_BITS] = 768
72
+ # object[:MODULUS_BITS, :LABEL] = 1024, 'MyKey'
73
+ #
74
+ # See PKCS#11 for attribute definitions.
75
+ # @return value
76
+ def []=(*attributes)
77
+ values = attributes.pop
78
+ values = [values] unless values.kind_of?(Array)
79
+ raise ArgumentError, "different number of attributes to set (#{attributes.length}) and given values (#{values.length})" unless attributes.length == values.length
80
+ map = values.each.with_index.inject({}){|s, v| s[attributes[v[1]]] = v[0]; s }
81
+ C_SetAttributeValue( map )
82
+ end
83
+
84
+ # Modifies the value of one or more attributes of the object in a single call.
85
+ #
86
+ # @example
87
+ # object.attributes = {:SUBJECT => cert_subject, PKCS11::CKA_VALUE => cert_data}
88
+ # @return template
89
+ def C_SetAttributeValue(template={})
90
+ @pk.C_SetAttributeValue(@sess, @obj, to_attributes(template))
91
+ template
92
+ end
93
+ alias attributes= C_SetAttributeValue
94
+
95
+ # Obtains the value of one or more attributes of the object in a single call.
96
+ #
97
+ # @param [Array<String, Symbol, Integer>, Hash, String, Integer] attribute attribute names
98
+ # whose values should be returned
99
+ #
100
+ # Without params all known attributes are tried to read from the Object.
101
+ # This is significant slower then naming the needed attributes and should
102
+ # be used for debug purposes only.
103
+ #
104
+ # @return [Array<PKCS11::CK_ATTRIBUTE>] Requested attributes with values.
105
+ #
106
+ # @example
107
+ # certificate.attributes :VALUE, :CLASS
108
+ # => [#<PKCS11::CK_ATTRIBUTE CKA_VALUE (17) value="0\x82...">, #<PKCS11::CK_ATTRIBUTE CKA_CLASS (0) value=1>]
109
+ def C_GetAttributeValue(*template)
110
+ case template.length
111
+ when 0
112
+ return @pk.vendor_all_attribute_names.map{|attr|
113
+ begin
114
+ attributes(@pk.vendor_const_get(attr))
115
+ rescue PKCS11::Error
116
+ end
117
+ }.flatten.compact
118
+ when 1
119
+ template = template[0]
120
+ end
121
+ template = to_attributes template
122
+ @pk.C_GetAttributeValue(@sess, @obj, template)
123
+ end
124
+ alias attributes C_GetAttributeValue
125
+
126
+ # Copies an object, creating a new object for the copy.
127
+ #
128
+ # @param [Hash] template
129
+ #
130
+ # The template may specify new values for any attributes of the object that can ordinarily
131
+ # be modified (e.g., in the course of copying a secret key, a key's CKA_EXTRACTABLE
132
+ # attribute may be changed from true to false, but not the other way around.
133
+ # If this change is made, the new key's CKA_NEVER_EXTRACTABLE attribute will
134
+ # have the value false. Similarly, the template may specify that the new key's
135
+ # CKA_SENSITIVE attribute be true; the new key will have the same value for its
136
+ # CKA_ALWAYS_SENSITIVE attribute as the original key). It may also specify new
137
+ # values of the CKA_TOKEN and CKA_PRIVATE attributes (e.g., to copy a session
138
+ # object to a token object). If the template specifies a value of an attribute which is
139
+ # incompatible with other existing attributes of the object, the call fails with exception
140
+ # CKR_TEMPLATE_INCONSISTENT.
141
+ #
142
+ # Only session objects can be created during a read-only session. Only public objects can
143
+ # be created unless the normal user is logged in.
144
+ #
145
+ # @return [PKCS11::Object] the newly created object
146
+ def C_CopyObject(template={})
147
+ handle = @pk.C_CopyObject(@sess, @obj, to_attributes(template))
148
+ Object.new @pk, @sess, handle
149
+ end
150
+ alias copy C_CopyObject
151
+
152
+ # Destroys the object.
153
+ #
154
+ # Only session objects can be destroyed during a read-only session. Only public objects
155
+ # can be destroyed unless the normal user is logged in.
156
+ # @return [PKCS11::Object]
157
+ def C_DestroyObject()
158
+ @pk.C_DestroyObject(@sess, @obj)
159
+ self
160
+ end
161
+ alias destroy C_DestroyObject
162
+
163
+ # Gets the size of an object in bytes.
164
+ # @return [Integer]
165
+ def C_GetObjectSize()
166
+ @pk.C_GetObjectSize(@sess, @obj)
167
+ end
168
+ alias size C_GetObjectSize
169
+
170
+ end
171
+ end