pkcs11_protect_server 0.2.2

Sign up to get free protection for your applications and to get access to all the features.
data/.gemtest ADDED
File without changes
data/.yardopts ADDED
@@ -0,0 +1 @@
1
+ --title "PKCS#11-ProtectServer/Ruby Interface" --no-private lib/**/*.rb ext/*.c ext/*.doc
data/Manifest.txt ADDED
@@ -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.
data/Rakefile ADDED
@@ -0,0 +1,86 @@
1
+ # -*- coding: utf-8 -*-
2
+ # -*- ruby -*-
3
+
4
+ require 'rubygems'
5
+ require 'hoe'
6
+ require 'rake/extensiontask'
7
+ require 'rbconfig'
8
+
9
+ PROTECT_SERVER_SDK_DIR = ENV['PROTECT_SERVER_SDK_DIR'] || '/opt/ETcpsdk'
10
+ RUBY_PKCS11_EXT_DIR = File.expand_path('../ext')
11
+
12
+ GENERATED_FILES = [
13
+ 'ext/pk11s_struct_impl.inc',
14
+ 'ext/pk11s_struct_def.inc',
15
+ 'ext/pk11s_const_def.inc',
16
+ 'ext/pk11s_struct.doc',
17
+ 'ext/pk11_struct_macros.h',
18
+ 'ext/pk11_const_macros.h',
19
+ 'ext/pk11_version.h',
20
+ ]
21
+
22
+ CLEAN.include GENERATED_FILES
23
+ CLEAN.include 'lib/pkcs11_protect_server_ext.so'
24
+ CLEAN.include 'tmp'
25
+
26
+ def pkcs11_version
27
+ file = File.join(RUBY_PKCS11_EXT_DIR, 'pk11_version.h')
28
+ version_re = /VERSION += +([\"\'])([\d][\d\w\.]+)\1/
29
+ File.read_utf(file)[version_re, 2]
30
+ end
31
+
32
+ hoe = Hoe.spec 'pkcs11_protect_server' do
33
+ developer('Lars Kanis', 'kanis@comcard.de')
34
+ extra_deps << ['pkcs11', "= #{pkcs11_version}"]
35
+ extra_dev_deps << ['yard', '>= 0.6']
36
+ extra_dev_deps << ['rake-compiler', '>= 0.7']
37
+
38
+ self.url = 'http://github.com/larskanis/pkcs11'
39
+ self.summary = 'Safenet-ProtectServer extensions for PKCS#11-Ruby'
40
+ self.description = 'This module allows Ruby programs to use vendor extensions for Safenet Protect Server.'
41
+ self.version = pkcs11_version
42
+
43
+ self.readme_file = 'README_PROTECT_SERVER.rdoc'
44
+ self.history_file = '../History.txt'
45
+ self.extra_rdoc_files << self.readme_file << 'ext/pk11s.c'
46
+ spec_extras[:extensions] = 'ext/extconf.rb'
47
+ spec_extras[:files] = File.read_utf("Manifest.txt").split(/\r?\n\r?/)
48
+ spec_extras[:files] += GENERATED_FILES
49
+ spec_extras[:has_rdoc] = 'yard'
50
+ end
51
+
52
+ ENV['RUBY_CC_VERSION'] ||= '1.8.7:1.9.2'
53
+
54
+ Rake::ExtensionTask.new('pkcs11_protect_server_ext', hoe.spec) do |ext|
55
+ ext.ext_dir = 'ext'
56
+ ext.cross_compile = true # enable cross compilation (requires cross compile toolchain)
57
+ ext.cross_platform = ['i386-mingw32'] # forces the Windows platform instead of the default one
58
+
59
+ ext.config_options << "--with-protect-server-sdk-dir=#{PROTECT_SERVER_SDK_DIR.inspect}"
60
+ end
61
+
62
+ def copy_from_base_task(filename)
63
+ file File.join('ext', filename) => File.join(RUBY_PKCS11_EXT_DIR, filename) do |t|
64
+ cp t.prerequisites.first, t.name, :verbose=>true
65
+ end
66
+ end
67
+
68
+ copy_from_base_task 'pk11_struct_macros.h'
69
+ copy_from_base_task 'pk11_const_macros.h'
70
+ copy_from_base_task 'pk11_version.h'
71
+
72
+ file 'ext/extconf.rb' => ['ext/pk11s_struct_def.inc', 'ext/pk11s_const_def.inc', 'ext/pk11_struct_macros.h', 'ext/pk11_const_macros.h', 'ext/pk11_version.h']
73
+ file 'ext/pk11s_struct_def.inc' => 'ext/generate_structs.rb' do
74
+ sh "#{RbConfig::CONFIG['ruby_install_name']} ext/generate_structs.rb --def ext/pk11s_struct_def.inc --impl ext/pk11s_struct_impl.inc --doc ext/pk11s_struct.doc #{File.join(PROTECT_SERVER_SDK_DIR, 'include/ctvdef.h').inspect}"
75
+ end
76
+ file 'ext/pk11s_struct_impl.inc' => 'ext/pk11s_struct_def.inc'
77
+ file 'ext/pk11s_struct.doc' => 'ext/pk11s_struct_def.inc'
78
+
79
+ file 'ext/pk11s_const_def.inc' => 'ext/generate_constants.rb' do
80
+ sh "#{RbConfig::CONFIG['ruby_install_name']} ext/generate_constants.rb --const ext/pk11s_const_def.inc #{File.join(PROTECT_SERVER_SDK_DIR, 'include/ctvdef.h').inspect}"
81
+ end
82
+ file 'ext/pk11s.c' => ['ext/pk11s_struct_def.inc', 'ext/pk11s_struct_impl.inc', 'ext/pk11s_const_def.inc']
83
+
84
+ task :doc_files => 'ext/pk11s_struct.doc'
85
+
86
+ # vim: syntax=ruby
data/ext/extconf.rb ADDED
@@ -0,0 +1,16 @@
1
+ require "mkmf"
2
+ require "rubygems"
3
+
4
+ inc, lib = dir_config('protect-server-sdk', '/opt/ETcpsdk/include', '/opt/ETcpsdk/lib')
5
+ puts "using ProtectServer-SDK include:#{inc} lib:#{lib}"
6
+
7
+ # inc, lib = dir_config('ruby-pkcs11')
8
+ # inc ||= Gem.required_location('pkcs11', '../ext')
9
+ # puts "using ruby-pkcs11 include:#{inc} lib:#{lib}"
10
+ # raise "path to ruby-pkcs11/ext could not be found (use --with-ruby-pkcs11-include=my_path)" unless inc
11
+ # $INCFLAGS << " -I"+inc
12
+
13
+ find_header('pk11_struct_macros.h')
14
+ find_header('pk11_const_macros.h')
15
+
16
+ create_makefile("pkcs11_protect_server_ext");
@@ -0,0 +1,41 @@
1
+ #!/usr/bin/env ruby
2
+ # Quick and dirty parser for PKCS#11 constants and
3
+ # generator for Ruby wrapper classes.
4
+
5
+ require File.expand_path(File.join(File.dirname(__FILE__), '../../ext/generate_constants'))
6
+
7
+ module PKCS11
8
+ module ProtectServer
9
+ class ConstantParser < PKCS11::ConstantParser
10
+ ConstGroups = [
11
+ ConstTemplate.new(/#define\s+(CKM_[A-Z_0-9]+)\s+(.+)/, 'PKCS11_DEFINE_MECHANISM'),
12
+ ConstTemplate.new(/#define\s+(CKA_[A-Z_0-9]+)\s+(.+)/, 'PKCS11_DEFINE_ATTRIBUTE'),
13
+ ConstTemplate.new(/#define\s+(CKO_[A-Z_0-9]+)\s+(.+)/, 'PKCS11_DEFINE_OBJECT_CLASS'),
14
+ ConstTemplate.new(/#define\s+(CKR_[A-Z_0-9]+)\s+(.+)/, 'PKCS11_DEFINE_RETURN_VALUE'),
15
+ ]
16
+
17
+ IgnoreConstants = %w[CKR_CERTIFICATE_NOT_YET_ACTIVE CKR_CERTIFICATE_EXPIRED]
18
+
19
+ def start!
20
+ File.open(options.const, "w") do |fd_const|
21
+ options.files.each do |file_h|
22
+ c_src = IO.read(file_h)
23
+ ConstGroups.each do |const_group|
24
+ c_src.scan(const_group.regexp) do
25
+ const_name, const_value = $1, $2
26
+ next if IgnoreConstants.include?(const_name)
27
+
28
+ fd_const.puts "#{const_group.def}(#{const_name}); /* #{const_value} */"
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
37
+
38
+
39
+ if $0==__FILE__
40
+ PKCS11::ProtectServer::ConstantParser.run(ARGV)
41
+ end
@@ -0,0 +1,75 @@
1
+ #!/usr/bin/env ruby
2
+ # Quick and dirty parser for PKCS#11 structs and
3
+ # generator for Ruby wrapper classes.
4
+
5
+ require 'rubygems'
6
+ require 'pkcs11'
7
+ require File.expand_path(File.join(File.dirname(__FILE__), '../../ext/generate_structs'))
8
+
9
+ module PKCS11
10
+ module ProtectServer
11
+ class StructParser < PKCS11::StructParser
12
+
13
+ SIZE_CONSTANTS = {
14
+ 'CK_MANUFACTURER_SIZE' => 32,
15
+ 'CK_SERIAL_NUMBER_SIZE' => 16,
16
+ 'CK_TIME_SIZE' => 16,
17
+ 'CK_LIB_DESC_SIZE' => 32,
18
+ 'CK_SLOT_DESCRIPTION_SIZE' => 64,
19
+ 'CK_SLOT_MANUFACTURER_SIZE' => 32,
20
+ 'CK_MAX_PIN_LEN' => 32,
21
+ 'CK_TOKEN_LABEL_SIZE' => 32,
22
+ 'CK_TOKEN_MANUFACTURER_SIZE' => 32,
23
+ 'CK_TOKEN_MODEL_SIZE' => 16,
24
+ 'CK_TOKEN_SERIAL_NUMBER_SIZE' => 16,
25
+ 'CK_TOKEN_TIME_SIZE' => 16,
26
+ 'CK_MAX_PBE_IV_SIZE' => 8,
27
+ 'CK_MAX_PAD_SIZE' => 16,
28
+ }
29
+
30
+ ULONG_TYPES = %w[CK_COUNT CK_SIZE CK_TIMESTAMP_FORMAT]
31
+ ULONG_PTR_TYPES = %w[CK_COUNT_PTR]
32
+
33
+ def struct_module
34
+ 'PKCS11::ProtectServer'
35
+ end
36
+
37
+ def array_attribute_names; %w[attributes mechanism certAttr hCert]; end
38
+
39
+ def parse_files(files)
40
+ structs = []
41
+ files.each do |file_h|
42
+ c_src = IO.read(file_h)
43
+ c_src.scan(/struct\s+([A-Z_0-9]+)\s*\{(.*?)\}/m) do |struct|
44
+ struct_text = $2
45
+ struct = PKCS11::StructParser::CStruct.new( $1, [] )
46
+
47
+ struct_text.scan(/^\s+([A-Z_0-9]+)([\*\s]+)([\w_]+)\s*(\[\s*(\w+)\s*\])?/) do |elem|
48
+ type, name = $1, $3
49
+ qual = SIZE_CONSTANTS[$5] || $5
50
+ ptr = $2.include?('*')
51
+ type = "CK_ULONG" if ULONG_TYPES.include?(type)
52
+ type = "CK_ULONG_PTR" if ULONG_PTR_TYPES.include?(type)
53
+ struct.attrs << Attribute.new(ptr ? type+"_PTR" : type, name, qual)
54
+ end
55
+ structs << struct
56
+ end
57
+ end
58
+ return structs
59
+ end
60
+
61
+ def start!
62
+ @structs = parse_files(options.files)
63
+ @structs_by_name = @structs.inject({}){|sum, v| sum[v.name]=v; sum }
64
+ @std_structs_by_name = PKCS11.constants.select{|c| PKCS11.const_get(c).respond_to?(:ancestors) && !(PKCS11.const_get(c).ancestors & [PKCS11::CStruct, PKCS11::CK_ATTRIBUTE]).empty? }.inject({}){|sum, v| sum[v.to_s]=true; sum }
65
+
66
+ write_files
67
+ end
68
+ end
69
+ end
70
+ end
71
+
72
+
73
+ if $0==__FILE__
74
+ PKCS11::ProtectServer::StructParser.run(ARGV)
75
+ end
@@ -0,0 +1,38 @@
1
+ #ifndef PK11_CONST_MACROS_INCLUDED
2
+ #define PK11_CONST_MACROS_INCLUDED
3
+
4
+ /**************************************************/
5
+ /* constant definition */
6
+ /**************************************************/
7
+
8
+ #define PKCS11_DEFINE_CONST(constant) \
9
+ rb_define_const(MODULE_FOR_CONSTS, #constant, INT2NUM(constant))
10
+
11
+ #define PKCS11_DEFINE_CONST_GROUP(group, name, value) \
12
+ do { \
13
+ VALUE rvalue, str, old; \
14
+ rvalue = ULONG2NUM(value); \
15
+ rb_define_const(MODULE_FOR_CONSTS, name, rvalue); \
16
+ str = rb_obj_freeze(rb_str_new2(name)); \
17
+ old = rb_hash_aref(group, rvalue); \
18
+ if (!NIL_P(old)) rb_warning("%s is equal to %s", RSTRING_PTR(old), name); \
19
+ rb_hash_aset(group, rvalue, str); \
20
+ } while(0)
21
+
22
+ #define PKCS11_DEFINE_OBJECT_CLASS(constant) \
23
+ PKCS11_DEFINE_CONST_GROUP(vOBJECT_CLASSES, #constant, constant)
24
+ #define PKCS11_DEFINE_ATTRIBUTE(constant) \
25
+ PKCS11_DEFINE_CONST_GROUP(vATTRIBUTES, #constant, constant)
26
+ #define PKCS11_DEFINE_MECHANISM(constant) \
27
+ PKCS11_DEFINE_CONST_GROUP(vMECHANISMS, #constant, constant)
28
+ #define PKCS11_DEFINE_RETURN_VALUE(constant) \
29
+ do { \
30
+ VALUE eError = rb_define_class_under(MODULE_FOR_CONSTS, #constant, BASECLASS_FOR_ERRORS); \
31
+ VALUE rvalue = ULONG2NUM(constant); \
32
+ VALUE old = rb_hash_aref(vRETURN_VALUES, rvalue); \
33
+ if (!NIL_P(old)) rb_warning("%s is equal to %s", RSTRING_PTR(old), #constant); \
34
+ rb_hash_aset(vRETURN_VALUES, rvalue, eError); \
35
+ } while(0)
36
+
37
+
38
+ #endif
@@ -0,0 +1,435 @@
1
+ #ifndef PK11_STRUCT_MACROS_INCLUDED
2
+ #define PK11_STRUCT_MACROS_INCLUDED
3
+
4
+ /**************************************************/
5
+ /* struct/attribute implementation */
6
+ /**************************************************/
7
+
8
+ #define HANDLE2NUM(n) ULONG2NUM(n)
9
+ #define NUM2HANDLE(n) PKNUM2ULONG(n)
10
+ #define PKNUM2ULONG(n) pkcs11_num2ulong(n)
11
+
12
+ static VALUE
13
+ pkcs11_num2ulong(VALUE val)
14
+ {
15
+ if (TYPE(val) == T_BIGNUM || TYPE(val) == T_FIXNUM) {
16
+ return NUM2ULONG(val);
17
+ }
18
+ return NUM2ULONG(rb_to_int(val));
19
+ }
20
+
21
+ static VALUE
22
+ get_string(VALUE obj, off_t offset, size_t size)
23
+ {
24
+ char *ptr = (char*)DATA_PTR(obj);
25
+ return rb_str_new(ptr+offset, size);
26
+ }
27
+
28
+ static VALUE
29
+ set_string(VALUE obj, VALUE value, off_t offset, size_t size)
30
+ {
31
+ char *ptr = (char*)DATA_PTR(obj);
32
+ int len = size;
33
+ StringValue(value);
34
+ if (RSTRING_LEN(value) < len) len = RSTRING_LEN(value);
35
+ memset(ptr+offset, 0, size);
36
+ memcpy(ptr+offset, RSTRING_PTR(value), len);
37
+ return value;
38
+ }
39
+
40
+ static VALUE
41
+ get_ulong(VALUE obj, off_t offset)
42
+ {
43
+ char *ptr = (char*)DATA_PTR(obj);
44
+ return ULONG2NUM(*(CK_ULONG_PTR)(ptr+offset));
45
+ }
46
+
47
+ static VALUE
48
+ set_ulong(VALUE obj, VALUE value, off_t offset)
49
+ {
50
+ char *ptr = (char*)DATA_PTR(obj);
51
+ *(CK_ULONG_PTR)(ptr+offset) = NUM2ULONG(value);
52
+ return value;
53
+ }
54
+
55
+ static VALUE
56
+ get_byte(VALUE obj, off_t offset)
57
+ {
58
+ char *ptr = (char*)DATA_PTR(obj);
59
+ return ULONG2NUM(*(CK_BYTE_PTR)(ptr+offset));
60
+ }
61
+
62
+ static VALUE
63
+ set_byte(VALUE obj, VALUE value, off_t offset)
64
+ {
65
+ char *ptr = (char*)DATA_PTR(obj);
66
+ *(CK_BYTE_PTR)(ptr+offset) = NUM2ULONG(value);
67
+ return value;
68
+ }
69
+
70
+ static VALUE
71
+ get_ulong_ptr(VALUE obj, off_t offset)
72
+ {
73
+ char *ptr = (char*)DATA_PTR(obj);
74
+ CK_ULONG_PTR p = *(CK_ULONG_PTR *)(ptr+offset);
75
+ if (!p) return Qnil;
76
+ return ULONG2NUM(*p);
77
+ }
78
+
79
+ static VALUE
80
+ set_ulong_ptr(VALUE obj, VALUE value, const char *name, off_t offset)
81
+ {
82
+ VALUE new_obj;
83
+ CK_ULONG_PTR *ptr = (CK_ULONG_PTR *)((char*)DATA_PTR(obj) + offset);
84
+ if (NIL_P(value)){
85
+ rb_iv_set(obj, name, value);
86
+ *ptr = NULL_PTR;
87
+ return value;
88
+ }
89
+ new_obj = Data_Make_Struct(rb_cInteger, CK_ULONG, 0, free, *ptr);
90
+ rb_iv_set(obj, name, new_obj);
91
+ **ptr = NUM2ULONG(value);
92
+ return value;
93
+ }
94
+
95
+ static VALUE
96
+ get_handle(VALUE obj, off_t offset)
97
+ {
98
+ char *ptr = (char*)DATA_PTR(obj);
99
+ return HANDLE2NUM(*(CK_OBJECT_HANDLE_PTR)(ptr+offset));
100
+ }
101
+
102
+ static VALUE
103
+ set_handle(VALUE obj, VALUE value, off_t offset)
104
+ {
105
+ char *ptr = (char*)DATA_PTR(obj);
106
+ *(CK_OBJECT_HANDLE_PTR)(ptr+offset) = NUM2HANDLE(value);
107
+ return value;
108
+ }
109
+
110
+ static VALUE
111
+ get_bool(VALUE obj, off_t offset)
112
+ {
113
+ char *ptr = (char*)DATA_PTR(obj);
114
+ if(*(CK_BBOOL*)(ptr+offset)) return Qtrue;
115
+ else return Qfalse;
116
+ }
117
+
118
+ static VALUE
119
+ set_bool(VALUE obj, VALUE value, off_t offset)
120
+ {
121
+ char *ptr = (char*)DATA_PTR(obj);
122
+ if(value == Qfalse) *(CK_BBOOL*)(ptr+offset) = 0;
123
+ else if(value == Qtrue) *(CK_BBOOL*)(ptr+offset) = 1;
124
+ else rb_raise(rb_eArgError, "arg must be true or false");
125
+ return value;
126
+ }
127
+
128
+ static VALUE
129
+ get_string_ptr(VALUE obj, const char *name, off_t offset)
130
+ {
131
+ char *ptr = (char*)DATA_PTR(obj);
132
+ char *p = *(char**)(ptr+offset);
133
+ if (!p) return Qnil;
134
+ return rb_str_new2(p);
135
+ }
136
+
137
+ static VALUE
138
+ set_string_ptr(VALUE obj, VALUE value, const char *name, off_t offset)
139
+ {
140
+ char *ptr = (char*)DATA_PTR(obj);
141
+ if (NIL_P(value)){
142
+ rb_iv_set(obj, name, value);
143
+ *(CK_VOID_PTR*)(ptr+offset) = NULL_PTR;
144
+ return value;
145
+ }
146
+ StringValue(value);
147
+ value = rb_obj_freeze(rb_str_dup(value));
148
+ rb_iv_set(obj, name, value);
149
+ *(CK_VOID_PTR*)(ptr+offset) = RSTRING_PTR(value);
150
+ return value;
151
+ }
152
+
153
+ static VALUE
154
+ get_string_ptr_len(VALUE obj, const char *name, off_t offset, off_t offset_len)
155
+ {
156
+ unsigned long l;
157
+ char *ptr = (char*)DATA_PTR(obj);
158
+ char *p = *(char**)(ptr+offset);
159
+ if (!p) return Qnil;
160
+ l = *(unsigned long*)(ptr+offset_len);
161
+ return rb_str_new(p, l);
162
+ }
163
+
164
+ static VALUE
165
+ set_string_ptr_len(VALUE obj, VALUE value, const char *name, off_t offset, off_t offset_len)
166
+ {
167
+ char *ptr = (char*)DATA_PTR(obj);
168
+ if (NIL_P(value)){
169
+ rb_iv_set(obj, name, value);
170
+ *(CK_VOID_PTR*)(ptr+offset) = NULL_PTR;
171
+ *(unsigned long*)(ptr+offset_len) = 0;
172
+ return value;
173
+ }
174
+ StringValue(value);
175
+ value = rb_obj_freeze(rb_str_dup(value));
176
+ rb_iv_set(obj, name, value);
177
+ *(CK_VOID_PTR*)(ptr+offset) = RSTRING_PTR(value);
178
+ *(unsigned long*)(ptr+offset_len) = RSTRING_LEN(value);
179
+ return value;
180
+ }
181
+
182
+ static VALUE
183
+ get_struct_inline(VALUE obj, VALUE klass, const char *name, off_t offset)
184
+ {
185
+ char *ptr = (char*)DATA_PTR(obj) + offset;
186
+ VALUE inline_obj = Data_Wrap_Struct(klass, 0, 0, ptr);
187
+ rb_iv_set(inline_obj, name, obj);
188
+ return inline_obj;
189
+ }
190
+
191
+ static VALUE
192
+ set_struct_inline(VALUE obj, VALUE klass, const char *struct_name, VALUE value, const char *name, off_t offset, int sizeofstruct)
193
+ {
194
+ char *ptr = (char*)DATA_PTR(obj) + offset;
195
+ if (!rb_obj_is_kind_of(value, klass))
196
+ rb_raise(rb_eArgError, "arg must be a PKCS11::%s", struct_name);
197
+ memcpy(ptr, DATA_PTR(value), sizeofstruct);
198
+ return value;
199
+ }
200
+
201
+ static VALUE
202
+ get_struct_ptr(VALUE obj, VALUE klass, const char *name, off_t offset, int sizeofstruct)
203
+ {
204
+ char *ptr = (char*)DATA_PTR(obj);
205
+ char *p = *(char**)(ptr+offset);
206
+ void *mem;
207
+ VALUE new_obj;
208
+ if (!p) return Qnil;
209
+ mem = xmalloc(sizeofstruct);
210
+ memcpy(mem, p, sizeofstruct);
211
+ new_obj = Data_Wrap_Struct(klass, 0, -1, mem);
212
+ return new_obj;
213
+ }
214
+
215
+ static VALUE
216
+ set_struct_ptr(VALUE obj, VALUE klass, const char *struct_name, VALUE value, const char *name, off_t offset)
217
+ {
218
+ char *ptr = (char*)DATA_PTR(obj) + offset;
219
+ if (NIL_P(value)){
220
+ rb_iv_set(obj, name, value);
221
+ *(CK_VOID_PTR*)ptr = NULL_PTR;
222
+ return value;
223
+ }
224
+ if (!rb_obj_is_kind_of(value, klass))
225
+ rb_raise(rb_eArgError, "arg must be a PKCS11::%s", struct_name);
226
+ *(CK_VOID_PTR*)ptr = DATA_PTR(value);
227
+ rb_iv_set(obj, name, value);
228
+ return value;
229
+ }
230
+
231
+ static VALUE
232
+ get_struct_ptr_array(VALUE obj, VALUE klass, off_t offset, off_t offset_len, int sizeofstruct)
233
+ {
234
+ unsigned long i;
235
+ char *ptr = DATA_PTR(obj);
236
+ char *p = *(char **)(ptr+offset);
237
+ unsigned long l = *(unsigned long*)(ptr+offset_len);
238
+ VALUE ary = rb_ary_new();
239
+ for (i = 0; i < l; i++){
240
+ VALUE new_obj;
241
+ void *mem = xmalloc(sizeofstruct);
242
+ memcpy(mem, p + sizeofstruct * i, sizeofstruct);
243
+ new_obj = Data_Wrap_Struct(klass, 0, -1, mem);
244
+ rb_ary_push(ary, new_obj);
245
+ }
246
+ return ary;
247
+ }
248
+
249
+ static VALUE
250
+ set_struct_ptr_array(VALUE obj, VALUE klass, const char *struct_name, VALUE value, const char *name, off_t offset, off_t offset_len, int sizeofstruct)
251
+ {
252
+ int i;
253
+ VALUE str_buf;
254
+ char *ptr = DATA_PTR(obj);
255
+ Check_Type(value, T_ARRAY);
256
+
257
+ str_buf = rb_str_buf_new(sizeofstruct * RARRAY_LEN(value));
258
+
259
+ for (i = 0; i < RARRAY_LEN(value); i++){
260
+ VALUE entry = rb_ary_entry(value, i);
261
+ if (!rb_obj_is_kind_of(entry, klass))
262
+ rb_raise(rb_eArgError, "arg must be array of PKCS11::%s", struct_name);
263
+ memcpy(RSTRING_PTR(str_buf) + sizeofstruct * i, DATA_PTR(entry), sizeofstruct);
264
+ }
265
+ *(CK_VOID_PTR*)(ptr+offset) = RSTRING_PTR(str_buf);
266
+ *(unsigned long*)(ptr+offset_len) = RARRAY_LEN(value);
267
+ rb_iv_set(obj, name, str_buf);
268
+ return value;
269
+ }
270
+
271
+
272
+ #define OFFSET_OF(s, f) ((off_t)((char*)&(((s*)0)->f) - (char*)0))
273
+ #define SIZE_OF(s, f) (sizeof(((s*)0)->f))
274
+
275
+ #define PKCS11_IMPLEMENT_ALLOCATOR(s) \
276
+ static VALUE s##_s_alloc(VALUE self){ \
277
+ s *info; \
278
+ VALUE obj = Data_Make_Struct(self, s, 0, -1, info); \
279
+ return obj; \
280
+ } \
281
+ static VALUE c##s##_to_s(VALUE self){ \
282
+ return rb_str_new(DATA_PTR(self), sizeof(s)); \
283
+ } \
284
+ static VALUE c##s##_members(VALUE self){ \
285
+ return a##s##_members; \
286
+ }
287
+
288
+ #define PKCS11_IMPLEMENT_STRUCT_WITH_ALLOCATOR(s) \
289
+ static VALUE c##s;\
290
+ static VALUE a##s##_members;\
291
+ PKCS11_IMPLEMENT_ALLOCATOR(s);
292
+
293
+ #define PKCS11_IMPLEMENT_STRING_ACCESSOR(s, f) \
294
+ static VALUE c##s##_get_##f(VALUE o){ \
295
+ return get_string(o, OFFSET_OF(s, f), SIZE_OF(s, f)); \
296
+ } \
297
+ static VALUE c##s##_set_##f(VALUE o, VALUE v){ \
298
+ return set_string(o, v, OFFSET_OF(s, f), SIZE_OF(s, f)); \
299
+ }
300
+
301
+ #define PKCS11_IMPLEMENT_ULONG_ACCESSOR(s, f) \
302
+ static VALUE c##s##_get_##f(VALUE o){ \
303
+ return get_ulong(o, OFFSET_OF(s, f)); \
304
+ } \
305
+ static VALUE c##s##_set_##f(VALUE o, VALUE v){ \
306
+ return set_ulong(o, v, OFFSET_OF(s, f)); \
307
+ }
308
+
309
+ #define PKCS11_IMPLEMENT_BYTE_ACCESSOR(s, f) \
310
+ static VALUE c##s##_get_##f(VALUE o){ \
311
+ return get_byte(o, OFFSET_OF(s, f)); \
312
+ } \
313
+ static VALUE c##s##_set_##f(VALUE o, VALUE v){ \
314
+ return set_byte(o, v, OFFSET_OF(s, f)); \
315
+ }
316
+
317
+ #define PKCS11_IMPLEMENT_ULONG_PTR_ACCESSOR(s, f) \
318
+ static VALUE c##s##_get_##f(VALUE o){ \
319
+ return get_ulong_ptr(o, OFFSET_OF(s, f)); \
320
+ } \
321
+ static VALUE c##s##_set_##f(VALUE o, VALUE v){ \
322
+ return set_ulong_ptr(o, v, #f, OFFSET_OF(s, f)); \
323
+ }
324
+
325
+ #define PKCS11_IMPLEMENT_HANDLE_ACCESSOR(s, f) \
326
+ static VALUE c##s##_get_##f(VALUE o){ \
327
+ return get_handle(o, OFFSET_OF(s, f)); \
328
+ } \
329
+ static VALUE c##s##_set_##f(VALUE o, VALUE v){ \
330
+ return set_handle(o, v, OFFSET_OF(s, f)); \
331
+ }
332
+
333
+ #define PKCS11_IMPLEMENT_BOOL_ACCESSOR(s, f) \
334
+ static VALUE c##s##_get_##f(VALUE o){ \
335
+ return get_bool(o, OFFSET_OF(s, f)); \
336
+ } \
337
+ static VALUE c##s##_set_##f(VALUE o, VALUE v){ \
338
+ return set_bool(o, v, OFFSET_OF(s, f)); \
339
+ }
340
+
341
+ #define PKCS11_IMPLEMENT_STRING_PTR_ACCESSOR(s, f) \
342
+ static VALUE c##s##_get_##f(VALUE o){ \
343
+ return get_string_ptr(o, #f, OFFSET_OF(s, f)); \
344
+ } \
345
+ static VALUE c##s##_set_##f(VALUE o, VALUE v){ \
346
+ return set_string_ptr(o, v, #f, OFFSET_OF(s, f)); \
347
+ }
348
+
349
+ #define PKCS11_IMPLEMENT_STRING_PTR_LEN_ACCESSOR(s, f, l) \
350
+ static VALUE c##s##_get_##f(VALUE o){ \
351
+ return get_string_ptr_len(o, #f, OFFSET_OF(s, f), OFFSET_OF(s, l)); \
352
+ } \
353
+ static VALUE c##s##_set_##f(VALUE o, VALUE v){ \
354
+ return set_string_ptr_len(o, v, #f, OFFSET_OF(s, f), OFFSET_OF(s, l)); \
355
+ }
356
+
357
+ #define PKCS11_IMPLEMENT_STRUCT_ACCESSOR(s, k, f) \
358
+ static VALUE c##s##_get_##f(VALUE o){ \
359
+ return get_struct_inline(o, c##k, #f, OFFSET_OF(s, f)); \
360
+ } \
361
+ static VALUE c##s##_set_##f(VALUE o, VALUE v){ \
362
+ return set_struct_inline(o, c##k, #k, v, #f, OFFSET_OF(s, f), sizeof(k)); \
363
+ }
364
+
365
+ #define PKCS11_IMPLEMENT_PKCS11_STRUCT_ACCESSOR(s, k, f) \
366
+ static VALUE c##s##_get_##f(VALUE o){ \
367
+ VALUE klass = rb_const_get(rb_const_get(rb_cObject, rb_intern("PKCS11")), rb_intern(#k)); \
368
+ return get_struct_inline(o, klass, #f, OFFSET_OF(s, f)); \
369
+ } \
370
+ static VALUE c##s##_set_##f(VALUE o, VALUE v){ \
371
+ VALUE klass = rb_const_get(rb_const_get(rb_cObject, rb_intern("PKCS11")), rb_intern(#k)); \
372
+ return set_struct_inline(o, klass, #k, v, #f, OFFSET_OF(s, f), sizeof(k)); \
373
+ }
374
+
375
+ #define PKCS11_IMPLEMENT_STRUCT_PTR_ACCESSOR(s, k, f) \
376
+ static VALUE c##s##_get_##f(VALUE o){ \
377
+ return get_struct_ptr(o, c##k, #f, OFFSET_OF(s, f), sizeof(k)); \
378
+ } \
379
+ static VALUE c##s##_set_##f(VALUE o, VALUE v){ \
380
+ return set_struct_ptr(o, c##k, #k, v, #f, OFFSET_OF(s, f)); \
381
+ }
382
+
383
+ #define PKCS11_IMPLEMENT_PKCS11_STRUCT_PTR_ACCESSOR(s, k, f) \
384
+ static VALUE c##s##_get_##f(VALUE o){ \
385
+ VALUE klass = rb_const_get(rb_const_get(rb_cObject, rb_intern("PKCS11")), rb_intern(#k)); \
386
+ return get_struct_ptr(o, klass, #f, OFFSET_OF(s, f), sizeof(k)); \
387
+ } \
388
+ static VALUE c##s##_set_##f(VALUE o, VALUE v){ \
389
+ VALUE klass = rb_const_get(rb_const_get(rb_cObject, rb_intern("PKCS11")), rb_intern(#k)); \
390
+ return set_struct_ptr(o, klass, #k, v, #f, OFFSET_OF(s, f)); \
391
+ }
392
+
393
+ #define PKCS11_IMPLEMENT_STRUCT_PTR_ARRAY_ACCESSOR(s, k, f, l) \
394
+ static VALUE c##s##_get_##f(VALUE o){ \
395
+ return get_struct_ptr_array(o, c##k, OFFSET_OF(s, f), OFFSET_OF(s, l), sizeof(k)); \
396
+ } \
397
+ static VALUE c##s##_set_##f(VALUE o, VALUE v){ \
398
+ return set_struct_ptr_array(o, c##k, #k, v, #f, OFFSET_OF(s, f), OFFSET_OF(s, l), sizeof(k)); \
399
+ }
400
+
401
+ #define PKCS11_IMPLEMENT_PKCS11_STRUCT_PTR_ARRAY_ACCESSOR(s, k, f, l) \
402
+ static VALUE c##s##_get_##f(VALUE o){ \
403
+ VALUE klass = rb_const_get(rb_const_get(rb_cObject, rb_intern("PKCS11")), rb_intern(#k)); \
404
+ return get_struct_ptr_array(o, klass, OFFSET_OF(s, f), OFFSET_OF(s, l), sizeof(k)); \
405
+ } \
406
+ static VALUE c##s##_set_##f(VALUE o, VALUE v){ \
407
+ VALUE klass = rb_const_get(rb_const_get(rb_cObject, rb_intern("PKCS11")), rb_intern(#k)); \
408
+ return set_struct_ptr_array(o, klass, #k, v, #f, OFFSET_OF(s, f), OFFSET_OF(s, l), sizeof(k)); \
409
+ }
410
+
411
+
412
+ /**************************************************/
413
+ /* struct/attribute definition */
414
+ /**************************************************/
415
+
416
+ #define PKCS11_DEFINE_STRUCT(s) \
417
+ do { \
418
+ c##s = rb_define_class_under(MODULE_FOR_STRUCTS, #s, BASECLASS_FOR_STRUCTS); \
419
+ a##s##_members = rb_ary_new(); \
420
+ rb_define_alloc_func(c##s, s##_s_alloc); \
421
+ rb_define_const(c##s, "SIZEOF_STRUCT", ULONG2NUM(sizeof(s))); \
422
+ rb_define_method(c##s, "to_s", c##s##_to_s, 0); \
423
+ rb_define_method(c##s, "members", c##s##_members, 0); \
424
+ rb_iv_set(c##s, "members", a##s##_members); \
425
+ } while(0)
426
+
427
+ #define PKCS11_DEFINE_MEMBER(s, f) \
428
+ do { \
429
+ rb_define_method(c##s, #f, c##s##_get_##f, 0); \
430
+ rb_define_method(c##s, #f "=", c##s##_set_##f, 1); \
431
+ rb_ary_push(a##s##_members, rb_str_new2(#f)); \
432
+ } while(0)
433
+
434
+
435
+ #endif