pkcs11 0.2.0-x86-mswin32 → 0.2.1-x86-mswin32

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/.yardopts CHANGED
@@ -1,2 +1 @@
1
- --no-private lib/**/*.rb ext/*.c ext/*.doc
2
-
1
+ --title "PKCS#11/Ruby Interface" --no-private lib/**/*.rb ext/*.c ext/*.doc
@@ -1,3 +1,13 @@
1
+ === 0.2.1 / 2011-04-21
2
+
3
+ * add some more CK_ULONG and CK_BOOL attributes
4
+ * add array of structs accessor used in CK_OTP_PARAMS
5
+ * refactured inc-file generation
6
+ * bit more documentation
7
+ * bugfix: print CKR-values as unsigned long
8
+ * bugfix: Slot#mechanism_info didn't work with Symbol
9
+
10
+
1
11
  === 0.2.0 / 2011-01-18
2
12
 
3
13
  * switch API documentation to YARD instead of RDOC
@@ -6,6 +6,7 @@ Manifest.txt
6
6
  README.rdoc
7
7
  Rakefile
8
8
  ext/extconf.rb
9
+ ext/generate_constants.rb
9
10
  ext/generate_structs.rb
10
11
  ext/generate_thread_funcs.rb
11
12
  ext/include/cryptoki.h
@@ -18,6 +19,8 @@ ext/include/pkcs11t.h
18
19
  ext/pk11.c
19
20
  ext/pk11.h
20
21
  ext/pk11_const.c
22
+ ext/pk11_const_macros.h
23
+ ext/pk11_struct_macros.h
21
24
  lib/pkcs11.rb
22
25
  lib/pkcs11/extensions.rb
23
26
  lib/pkcs11/helper.rb
@@ -6,7 +6,7 @@
6
6
  This module allows Ruby programs to interface with "RSA Security Inc.
7
7
  PKCS #11 Cryptographic Token Interface (Cryptoki)".
8
8
  PKCS #11 is the de-facto standard to access cryptographic devices.
9
- You must have the PKCS #11 v2.20 implementation library installed in
9
+ You must have a PKCS #11 v2.20 implementation library installed in
10
10
  order to use this module. Tested implementations of PKCS#11 librarys
11
11
  include:
12
12
  * OpenSC[http://www.opensc-project.org] supported Smart Cards
@@ -23,11 +23,20 @@ This installs the PKCS#11 extension either by compiling (Unix) or by using the p
23
23
 
24
24
  == Usage
25
25
  Cryptoki has a reputation to be complicated to implement and use.
26
- While this seems to be true for C it shouldn't for Ruby.
27
-
28
- {PKCS11.open} opens a PKCS#11 Unix *.so file or Windows-DLL. It requires
29
- a suitable PKCS #11 implementation.
30
-
26
+ While this seems to be true for C, it shouldn't for Ruby.
27
+
28
+ * {PKCS11.open} opens a PKCS#11 Unix *.so file or Windows-DLL with a suitable PKCS #11 implementation
29
+ and returns a {PKCS11::Library}.
30
+ * {PKCS11::Library#slots} returns a list of {PKCS11::Slot} for all slots accessable by the library.
31
+ * {PKCS11::Slot#open} opens a {PKCS11::Session} which is used for object handling
32
+ and cryptographic operations.
33
+ * {PKCS11::Object} represents a key, data or certificate object.
34
+ * all constants defined in PKCS#11 v2.20 are available in the module {PKCS11}
35
+ and contain the associated Integer value (CKA_KEY_TYPE, CKK_AES, CKM_SHA_1 etc.)
36
+ * also all structs are available in the module {PKCS11} as proper ruby classes
37
+ ({PKCS11::CK_VERSION}, {PKCS11::CK_OTP_PARAMS} etc.)
38
+
39
+ === Example
31
40
  require "rubygems"
32
41
  require "pkcs11"
33
42
  include PKCS11
@@ -36,20 +45,25 @@ a suitable PKCS #11 implementation.
36
45
  p pkcs11.info
37
46
  session = pkcs11.active_slots.first.open
38
47
  session.login(:USER, "1234")
39
- # ... crypto operations
48
+ secret_key = session.generate_key(:DES2_KEY_GEN,
49
+ :ENCRYPT=>true, :DECRYPT=>true, :SENSITIVE=>true, :TOKEN=>true, :LABEL=>'my key')
50
+ cryptogram = session.encrypt( {:DES3_CBC_PAD=>"\0"*8}, secret_key, "some plaintext")
40
51
  session.logout
41
52
  session.close
42
53
 
43
- This opens a {PKCS11::Session} to the first active slot of the device.
44
- A {PKCS11::Session} can be used for all cryptographic operations
45
- on the device.
46
-
47
- Detail information for the API specification is provided by RSA Security Inc.
48
- Please refer the URL: http://www.rsa.com/rsalabs/node.asp?id=2133.
54
+ This opens a PKCS#11 library and prints it's information block.
55
+ Then a {PKCS11::Session} to the first active slot of the device is opened and
56
+ a login is done on the user account. Now, a 112 bit DES3 key is generated and
57
+ some plaintext is encrypted with it. A 8-byte zero IV is used. In many cases method parameters
58
+ can be Integer (like CKA_LABEL) or, as in the sample, Symbol (:LABEL) which is internally
59
+ converted.
49
60
 
50
- Many usage examples can be found in the unit tests of the <tt>test</tt>
61
+ Many more usage examples can be found in the unit tests of the <tt>test</tt>
51
62
  directory of the project or gem.
52
63
 
64
+ Detail information for the API specification is provided by RSA Security Inc.
65
+ Please refer the URL: http://www.rsa.com/rsalabs/node.asp?id=2133. Browsable HTML
66
+ can be found at http://www.cryptsoft.com/pkcs11doc.
53
67
 
54
68
 
55
69
  == Cross compiling for mswin32
@@ -89,6 +103,9 @@ directory.
89
103
 
90
104
  == Development Status
91
105
 
106
+ Any operation that is possible with PKCS#11 in C, should be likewise possible in Ruby.
107
+ Otherwise it is considered as a bug in the binding.
108
+
92
109
  STATE FUNCTION NOTE
93
110
  ------ --------------------- ----------------------------------------
94
111
  DONE C_Initialize
data/Rakefile CHANGED
@@ -47,11 +47,14 @@ end
47
47
 
48
48
  file 'ext/extconf.rb' => ['ext/pk11_struct_def.inc', 'ext/pk11_thread_funcs.c']
49
49
  file 'ext/pk11_struct_def.inc' => 'ext/generate_structs.rb' do
50
- sh "#{Config::CONFIG['ruby_install_name']} ext/generate_structs.rb --def ext/pk11_struct_def.inc --impl ext/pk11_struct_impl.inc --const ext/pk11_const_def.inc --doc ext/pk11_struct.doc ext/include/pkcs11t.h"
50
+ sh "#{Config::CONFIG['ruby_install_name']} ext/generate_structs.rb --def ext/pk11_struct_def.inc --impl ext/pk11_struct_impl.inc --doc ext/pk11_struct.doc ext/include/pkcs11t.h"
51
51
  end
52
52
  file 'ext/pk11_struct_impl.inc' => 'ext/pk11_struct_def.inc'
53
- file 'ext/pk11.c' => 'ext/pk11_struct_def.inc'
54
- file 'ext/pk11_const.c' => 'ext/pk11_struct_def.inc'
53
+ file 'ext/pk11_const_def.inc' => 'ext/generate_constants.rb' do
54
+ sh "#{Config::CONFIG['ruby_install_name']} ext/generate_constants.rb --const ext/pk11_const_def.inc ext/include/pkcs11t.h"
55
+ end
56
+ file 'ext/pk11.c' => ['ext/pk11_struct_def.inc', 'ext/pk11_struct_impl.inc', 'ext/pk11_struct_macros.h']
57
+ file 'ext/pk11_const.c' => ['ext/pk11_const_def.inc', 'ext/pk11_const_macros.h']
55
58
 
56
59
  file 'ext/pk11_thread_funcs.h' => 'ext/generate_thread_funcs.rb' do
57
60
  sh "#{Config::CONFIG['ruby_install_name']} ext/generate_thread_funcs.rb --impl ext/pk11_thread_funcs.c --decl ext/pk11_thread_funcs.h ext/include/pkcs11f.h"
@@ -0,0 +1,57 @@
1
+ #!/usr/bin/env ruby
2
+ # Quick and dirty parser for PKCS#11 constants and
3
+ # generator for Ruby wrapper classes.
4
+
5
+ require 'optparse'
6
+
7
+ module PKCS11
8
+ class ConstantParser
9
+
10
+ attr_accessor :options
11
+
12
+ def self.run(argv)
13
+ s = self.new
14
+ options = Struct.new(:verbose, :const, :files).new
15
+ OptionParser.new(argv) do |opts|
16
+ opts.banner = "Usage: #{$0} [options] <header-file.h>*"
17
+
18
+ opts.on("-v", "--[no-]verbose", "Run verbosely", &options.method(:verbose=))
19
+ opts.on("--const FILE", "Write const implementations to this file", &options.method(:const=))
20
+ opts.on_tail("-h", "--help", "Show this message") do
21
+ puts opts
22
+ exit
23
+ end
24
+ end.parse!
25
+ options.files = argv
26
+ s.options = options
27
+ s.start!
28
+ end
29
+
30
+ ConstTemplate = Struct.new :regexp, :def
31
+ ConstGroups = [
32
+ ConstTemplate.new(/#define\s+(CKM_[A-Z_0-9]+)\s+(\w+)/, 'PKCS11_DEFINE_MECHANISM'),
33
+ ConstTemplate.new(/#define\s+(CKA_[A-Z_0-9]+)\s+(\w+)/, 'PKCS11_DEFINE_ATTRIBUTE'),
34
+ ConstTemplate.new(/#define\s+(CKO_[A-Z_0-9]+)\s+(\w+)/, 'PKCS11_DEFINE_OBJECT_CLASS'),
35
+ ConstTemplate.new(/#define\s+(CKR_[A-Z_0-9]+)\s+(\w+)/, 'PKCS11_DEFINE_RETURN_VALUE'),
36
+ ]
37
+
38
+ def start!
39
+ File.open(options.const, "w") do |fd_const|
40
+ options.files.each do |file_h|
41
+ c_src = IO.read(file_h)
42
+ ConstGroups.each do |const_group|
43
+ c_src.scan(const_group.regexp) do
44
+ const_name, const_value = $1, $2
45
+
46
+ fd_const.puts "#{const_group.def}(#{const_name}); /* #{const_value} */"
47
+ end
48
+ end
49
+ end
50
+ end
51
+ end
52
+ end
53
+ end
54
+
55
+ if $0==__FILE__
56
+ PKCS11::ConstantParser.run(ARGV)
57
+ end
@@ -4,154 +4,191 @@
4
4
 
5
5
  require 'optparse'
6
6
 
7
- options = Struct.new(:verbose, :def, :impl, :const, :doc).new
8
- OptionParser.new do |opts|
9
- opts.banner = "Usage: #{$0} [options] <header-file.h>*"
10
-
11
- opts.on("-v", "--[no-]verbose", "Run verbosely", &options.method(:verbose=))
12
- opts.on("--def FILE", "Write struct definitions to this file", &options.method(:def=))
13
- opts.on("--impl FILE", "Write struct implementations to this file", &options.method(:impl=))
14
- opts.on("--const FILE", "Write const implementations to this file", &options.method(:const=))
15
- opts.on("--doc FILE", "Write documentation to this file", &options.method(:doc=))
16
- opts.on_tail("-h", "--help", "Show this message") do
17
- puts opts
18
- exit
19
- end
20
- end.parse!
21
-
22
- Attribute = Struct.new(:type, :name, :qual)
23
- IgnoreStructs = %w[CK_ATTRIBUTE CK_MECHANISM]
24
- OnlyAllocatorStructs = %w[CK_MECHANISM_INFO CK_C_INITIALIZE_ARGS CK_INFO CK_SLOT_INFO CK_TOKEN_INFO CK_SESSION_INFO]
25
-
26
- structs = {}
27
- File.open(options.def, "w") do |fd_def|
28
- File.open(options.impl, "w") do |fd_impl|
29
- File.open(options.doc, "w") do |fd_doc|
30
- ARGV.each do |file_h|
31
- c_src = IO.read(file_h)
32
- c_src.scan(/struct\s+([A-Z_0-9]+)\s*\{(.*?)\}/m) do |struct|
33
- struct_name, struct_text = $1, $2
34
-
35
- attrs = {}
36
- struct_text.scan(/^\s+([A-Z_0-9]+)\s+([\w_]+)\s*(\[\s*(\d+)\s*\])?/) do |elem|
37
- attr = Attribute.new($1, $2, $4)
38
- attrs[$1+" "+$2] = attr
39
- # puts attr.inspect
40
- end
41
- structs[struct_name] = attrs
42
-
43
- next if IgnoreStructs.include?(struct_name)
44
-
45
- if OnlyAllocatorStructs.include?(struct_name)
46
- fd_impl.puts "PKCS11_IMPLEMENT_ALLOCATOR(#{struct_name});"
47
- else
48
- fd_impl.puts "PKCS11_IMPLEMENT_STRUCT_WITH_ALLOCATOR(#{struct_name});"
7
+ module PKCS11
8
+ class StructParser
9
+
10
+ attr_accessor :options
11
+ attr_accessor :structs
12
+ attr_accessor :structs_by_name
13
+ attr_accessor :std_structs_by_name
14
+
15
+ def self.run(argv)
16
+ s = self.new
17
+ options = Struct.new(:verbose, :def, :impl, :doc, :files).new
18
+ OptionParser.new(argv) do |opts|
19
+ opts.banner = "Usage: #{$0} [options] <header-file.h>*"
20
+
21
+ opts.on("-v", "--[no-]verbose", "Run verbosely", &options.method(:verbose=))
22
+ opts.on("--def FILE", "Write struct definitions to this file", &options.method(:def=))
23
+ opts.on("--impl FILE", "Write struct implementations to this file", &options.method(:impl=))
24
+ opts.on("--doc FILE", "Write documentation to this file", &options.method(:doc=))
25
+ opts.on_tail("-h", "--help", "Show this message") do
26
+ puts opts
27
+ exit
28
+ end
29
+ end.parse!
30
+ options.files = argv
31
+ s.options = options
32
+ s.start!
33
+ end
34
+
35
+ CStruct = Struct.new(:name, :attrs)
36
+ Attribute = Struct.new(:type, :name, :qual, :mark)
37
+ IgnoreStructs = %w[CK_ATTRIBUTE CK_MECHANISM]
38
+ OnlyAllocatorStructs = %w[CK_MECHANISM_INFO CK_C_INITIALIZE_ARGS CK_INFO CK_SLOT_INFO CK_TOKEN_INFO CK_SESSION_INFO]
39
+ STRUCT_MODULE = 'PKCS11'
40
+
41
+ class CStruct
42
+ def attr_by_sign(key)
43
+ attrs.find{|a| a.type+" "+a.name==key }
49
44
  end
50
- fd_def.puts "PKCS11_DEFINE_STRUCT(#{struct_name});"
51
- fd_doc.puts"class PKCS11::#{struct_name} < PKCS11::CStruct"
52
- fd_doc.puts"# Size of corresponding C struct in bytes\nSIZEOF_STRUCT=Integer"
53
- fd_doc.puts"# @return [String] Binary copy of the C struct\ndef to_s; end"
54
- fd_doc.puts"# @return [Array<String>] Attributes of this struct\ndef members; end"
55
-
56
- # try to find attributes belonging together
57
- attrs.select{|key, attr| ['CK_BYTE_PTR', 'CK_VOID_PTR', 'CK_UTF8CHAR_PTR'].include?(attr.type) }.each do |key, attr|
58
- if len_attr=attrs["CK_ULONG #{attr.name.gsub(/^p/, "ul")}Len"]
59
- fd_impl.puts "PKCS11_IMPLEMENT_STRING_PTR_LEN_ACCESSOR(#{struct_name}, #{attr.name}, #{len_attr.name});"
60
- fd_def.puts "PKCS11_DEFINE_MEMBER(#{struct_name}, #{attr.name});"
61
- fd_doc.puts"# @return [String, nil] accessor for #{attr.name} and #{len_attr.name}\nattr_accessor :#{attr.name}"
62
- attrs.delete_if{|k,v| v==len_attr}
63
- elsif attr.name=='pData' && (len_attr = attrs["CK_ULONG length"] || attrs["CK_ULONG ulLen"])
64
- fd_impl.puts "PKCS11_IMPLEMENT_STRING_PTR_LEN_ACCESSOR(#{struct_name}, #{attr.name}, #{len_attr.name});"
65
- fd_def.puts "PKCS11_DEFINE_MEMBER(#{struct_name}, #{attr.name});"
66
- fd_doc.puts"# @return [String, nil] accessor for #{attr.name} and #{len_attr.name}\nattr_accessor :#{attr.name}"
67
- attrs.delete_if{|k,v| v==len_attr}
68
- else
69
- fd_impl.puts "PKCS11_IMPLEMENT_STRING_PTR_ACCESSOR(#{struct_name}, #{attr.name});"
70
- fd_def.puts "PKCS11_DEFINE_MEMBER(#{struct_name}, #{attr.name});"
71
- fd_doc.puts"# @return [String, nil] accessor for #{attr.name}\nattr_accessor :#{attr.name}"
72
- end
73
- attrs.delete_if{|k,v| v==attr}
74
- end
75
-
76
- # standalone attributes
77
- attrs.each do |key, attr|
78
- if attr.qual
79
- # Attributes with qualifier
80
- case attr.type
81
- when 'CK_BYTE', 'CK_UTF8CHAR', 'CK_CHAR'
82
- fd_impl.puts "PKCS11_IMPLEMENT_STRING_ACCESSOR(#{struct_name}, #{attr.name});"
83
- fd_def.puts "PKCS11_DEFINE_MEMBER(#{struct_name}, #{attr.name});"
84
- fd_doc.puts"# @return [String] accessor for #{attr.name} (max #{attr.qual} bytes)\nattr_accessor :#{attr.name}"
85
- else
86
- fd_impl.puts "/* unimplemented attr #{attr.type} #{attr.name} #{attr.qual} */"
87
- fd_def.puts "/* unimplemented attr #{attr.type} #{attr.name} #{attr.qual} */"
45
+ end
46
+
47
+ def parse_files(files)
48
+ structs = []
49
+ files.each do |file_h|
50
+ c_src = IO.read(file_h)
51
+ c_src.scan(/struct\s+([A-Z_0-9]+)\s*\{(.*?)\}/m) do |struct|
52
+ struct_text = $2
53
+ struct = CStruct.new( $1, [] )
54
+
55
+ struct_text.scan(/^\s+([A-Z_0-9]+)\s+([\w_]+)\s*(\[\s*(\d+)\s*\])?/) do |elem|
56
+ struct.attrs << Attribute.new($1, $2, $4)
88
57
  end
58
+ structs << struct
59
+ end
60
+ end
61
+ return structs
62
+ end
63
+
64
+ def start!
65
+ @structs = parse_files(options.files)
66
+ @structs_by_name = @structs.inject({}){|sum, v| sum[v.name]=v; sum }
67
+ @std_structs_by_name = @structs_by_name.dup
68
+
69
+ write_files
70
+ end
71
+
72
+ def write_files
73
+ File.open(options.def, "w") do |fd_def|
74
+ File.open(options.impl, "w") do |fd_impl|
75
+ File.open(options.doc, "w") do |fd_doc|
76
+ structs.each do |struct|
77
+ next if IgnoreStructs.include?(struct.name)
78
+
79
+ if OnlyAllocatorStructs.include?(struct.name)
80
+ fd_impl.puts "PKCS11_IMPLEMENT_ALLOCATOR(#{struct.name});"
89
81
  else
90
- case attr.type
91
- when 'CK_BYTE'
92
- fd_impl.puts "PKCS11_IMPLEMENT_BYTE_ACCESSOR(#{struct_name}, #{attr.name});"
93
- fd_def.puts "PKCS11_DEFINE_MEMBER(#{struct_name}, #{attr.name});"
94
- fd_doc.puts"# @return [Integer] accessor for #{attr.name} (CK_BYTE)\nattr_accessor :#{attr.name}"
95
- when 'CK_ULONG', 'CK_FLAGS', 'CK_SLOT_ID', 'CK_STATE', /CK_[A-Z_0-9]+_TYPE/
96
- fd_impl.puts "PKCS11_IMPLEMENT_ULONG_ACCESSOR(#{struct_name}, #{attr.name});"
97
- fd_def.puts "PKCS11_DEFINE_MEMBER(#{struct_name}, #{attr.name});"
98
- fd_doc.puts"# @return [Integer] accessor for #{attr.name} (CK_ULONG)\nattr_accessor :#{attr.name}"
99
- when 'CK_OBJECT_HANDLE'
100
- fd_impl.puts "PKCS11_IMPLEMENT_HANDLE_ACCESSOR(#{struct_name}, #{attr.name});"
101
- fd_def.puts "PKCS11_DEFINE_MEMBER(#{struct_name}, #{attr.name});"
102
- fd_doc.puts"# @return [Integer, PKCS11::Object] Object handle (CK_ULONG)\nattr_accessor :#{attr.name}"
103
- when 'CK_BBOOL'
104
- fd_impl.puts "PKCS11_IMPLEMENT_BOOL_ACCESSOR(#{struct_name}, #{attr.name});"
105
- fd_def.puts "PKCS11_DEFINE_MEMBER(#{struct_name}, #{attr.name});"
106
- fd_doc.puts"# @return [Boolean] Bool value\nattr_accessor :#{attr.name}"
107
- when 'CK_ULONG_PTR'
108
- fd_impl.puts "PKCS11_IMPLEMENT_ULONG_PTR_ACCESSOR(#{struct_name}, #{attr.name});"
109
- fd_def.puts "PKCS11_DEFINE_MEMBER(#{struct_name}, #{attr.name});"
110
- fd_doc.puts"# @return [Integer, nil] accessor for #{attr.name} (CK_ULONG_PTR)\nattr_accessor :#{attr.name}"
82
+ fd_impl.puts "PKCS11_IMPLEMENT_STRUCT_WITH_ALLOCATOR(#{struct.name});"
83
+ end
84
+ fd_def.puts "PKCS11_DEFINE_STRUCT(#{struct.name});"
85
+ fd_doc.puts"class #{STRUCT_MODULE}::#{struct.name} < #{STRUCT_MODULE}::CStruct"
86
+ fd_doc.puts"# Size of corresponding C struct in bytes\nSIZEOF_STRUCT=Integer"
87
+ fd_doc.puts"# @return [String] Binary copy of the C struct\ndef to_s; end"
88
+ fd_doc.puts"# @return [Array<String>] Attributes of this struct\ndef members; end"
89
+
90
+ # find attributes belonging together for array of struct
91
+ struct.attrs.select{|attr| structs_by_name[attr.type.gsub(/_PTR$/,'')] }.each do |attr|
92
+ if attr.name=='pParams' && (len_attr = struct.attr_by_sign("CK_ULONG ulCount"))
93
+ fd_impl.puts "PKCS11_IMPLEMENT_STRUCT_PTR_ARRAY_ACCESSOR(#{struct.name}, #{attr.type.gsub(/_PTR$/,'')}, #{attr.name}, #{len_attr.name});"
94
+ fd_def.puts "PKCS11_DEFINE_MEMBER(#{struct.name}, #{attr.name});"
95
+ fd_doc.puts"# @return [Array<PKCS11::#{attr.type.gsub(/_PTR$/,'')}>] accessor for #{attr.name} and #{len_attr.name}\nattr_accessor :#{attr.name}"
96
+ len_attr.mark = true
97
+ attr.mark = true
98
+ end
99
+ end
100
+ # find string attributes belonging together
101
+ struct.attrs.select{|attr| ['CK_BYTE_PTR', 'CK_VOID_PTR', 'CK_UTF8CHAR_PTR', 'CK_CHAR_PTR'].include?(attr.type) }.each do |attr|
102
+ if len_attr=struct.attr_by_sign("CK_ULONG #{attr.name.gsub(/^p/, "ul")}Len")
103
+ fd_impl.puts "PKCS11_IMPLEMENT_STRING_PTR_LEN_ACCESSOR(#{struct.name}, #{attr.name}, #{len_attr.name});"
104
+ fd_def.puts "PKCS11_DEFINE_MEMBER(#{struct.name}, #{attr.name});"
105
+ fd_doc.puts"# @return [String, nil] accessor for #{attr.name} and #{len_attr.name}\nattr_accessor :#{attr.name}"
106
+ len_attr.mark = true
107
+ elsif attr.name=='pData' && (len_attr = struct.attr_by_sign("CK_ULONG length") || struct.attr_by_sign("CK_ULONG ulLen"))
108
+ fd_impl.puts "PKCS11_IMPLEMENT_STRING_PTR_LEN_ACCESSOR(#{struct.name}, #{attr.name}, #{len_attr.name});"
109
+ fd_def.puts "PKCS11_DEFINE_MEMBER(#{struct.name}, #{attr.name});"
110
+ fd_doc.puts"# @return [String, nil] accessor for #{attr.name} and #{len_attr.name}\nattr_accessor :#{attr.name}"
111
+ len_attr.mark = true
111
112
  else
112
- # Struct attributes
113
- if structs[attr.type]
114
- fd_impl.puts "PKCS11_IMPLEMENT_STRUCT_ACCESSOR(#{struct_name}, #{attr.type}, #{attr.name});"
115
- fd_def.puts "PKCS11_DEFINE_MEMBER(#{struct_name}, #{attr.name});"
116
- fd_doc.puts"# @return [PKCS11::#{attr.type}] inline struct\nattr_accessor :#{attr.name}"
117
- elsif structs[attr.type.gsub(/_PTR$/,'')]
118
- fd_impl.puts "PKCS11_IMPLEMENT_STRUCT_PTR_ACCESSOR(#{struct_name}, #{attr.type.gsub(/_PTR$/,'')}, #{attr.name});"
119
- fd_def.puts "PKCS11_DEFINE_MEMBER(#{struct_name}, #{attr.name});"
120
- fd_doc.puts"# @return [PKCS11::#{attr.type.gsub(/_PTR$/,'')}, nil] pointer to struct\nattr_accessor :#{attr.name}"
113
+ fd_impl.puts "PKCS11_IMPLEMENT_STRING_PTR_ACCESSOR(#{struct.name}, #{attr.name});"
114
+ fd_def.puts "PKCS11_DEFINE_MEMBER(#{struct.name}, #{attr.name});"
115
+ fd_doc.puts"# @return [String, nil] accessor for #{attr.name}\nattr_accessor :#{attr.name}"
116
+ end
117
+ attr.mark = true
118
+ end
119
+
120
+ # standalone attributes
121
+ struct.attrs.reject{|a| a.mark }.each do |attr|
122
+ if attr.qual
123
+ # Attributes with qualifier
124
+ case attr.type
125
+ when 'CK_BYTE', 'CK_UTF8CHAR', 'CK_CHAR'
126
+ fd_impl.puts "PKCS11_IMPLEMENT_STRING_ACCESSOR(#{struct.name}, #{attr.name});"
127
+ fd_def.puts "PKCS11_DEFINE_MEMBER(#{struct.name}, #{attr.name});"
128
+ fd_doc.puts"# @return [String] accessor for #{attr.name} (max #{attr.qual} bytes)\nattr_accessor :#{attr.name}"
121
129
  else
122
130
  fd_impl.puts "/* unimplemented attr #{attr.type} #{attr.name} #{attr.qual} */"
123
131
  fd_def.puts "/* unimplemented attr #{attr.type} #{attr.name} #{attr.qual} */"
124
132
  end
133
+ else
134
+ case attr.type
135
+ when 'CK_BYTE'
136
+ fd_impl.puts "PKCS11_IMPLEMENT_BYTE_ACCESSOR(#{struct.name}, #{attr.name});"
137
+ fd_def.puts "PKCS11_DEFINE_MEMBER(#{struct.name}, #{attr.name});"
138
+ fd_doc.puts"# @return [Integer] accessor for #{attr.name} (CK_BYTE)\nattr_accessor :#{attr.name}"
139
+ when 'CK_ULONG', 'CK_FLAGS', 'CK_SLOT_ID', 'CK_STATE', 'CK_COUNT', 'CK_SIZE', /CK_[A-Z_0-9]+_TYPE/
140
+ fd_impl.puts "PKCS11_IMPLEMENT_ULONG_ACCESSOR(#{struct.name}, #{attr.name});"
141
+ fd_def.puts "PKCS11_DEFINE_MEMBER(#{struct.name}, #{attr.name});"
142
+ fd_doc.puts"# @return [Integer] accessor for #{attr.name} (CK_ULONG)\nattr_accessor :#{attr.name}"
143
+ when 'CK_OBJECT_HANDLE'
144
+ fd_impl.puts "PKCS11_IMPLEMENT_HANDLE_ACCESSOR(#{struct.name}, #{attr.name});"
145
+ fd_def.puts "PKCS11_DEFINE_MEMBER(#{struct.name}, #{attr.name});"
146
+ fd_doc.puts"# @return [Integer, PKCS11::Object] Object handle (CK_ULONG)\nattr_accessor :#{attr.name}"
147
+ when 'CK_BBOOL'
148
+ fd_impl.puts "PKCS11_IMPLEMENT_BOOL_ACCESSOR(#{struct.name}, #{attr.name});"
149
+ fd_def.puts "PKCS11_DEFINE_MEMBER(#{struct.name}, #{attr.name});"
150
+ fd_doc.puts"# @return [Boolean] Bool value\nattr_accessor :#{attr.name}"
151
+ when 'CK_ULONG_PTR', 'CK_COUNT_PTR'
152
+ fd_impl.puts "PKCS11_IMPLEMENT_ULONG_PTR_ACCESSOR(#{struct.name}, #{attr.name});"
153
+ fd_def.puts "PKCS11_DEFINE_MEMBER(#{struct.name}, #{attr.name});"
154
+ fd_doc.puts"# @return [Integer, nil] accessor for #{attr.name} (CK_ULONG_PTR)\nattr_accessor :#{attr.name}"
155
+ else
156
+ # Struct attributes
157
+ if structs_by_name[attr.type]
158
+ fd_impl.puts "PKCS11_IMPLEMENT_STRUCT_ACCESSOR(#{struct.name}, #{attr.type}, #{attr.name});"
159
+ fd_def.puts "PKCS11_DEFINE_MEMBER(#{struct.name}, #{attr.name});"
160
+ fd_doc.puts"# @return [#{STRUCT_MODULE}::#{attr.type}] inline struct\nattr_accessor :#{attr.name}"
161
+ elsif (attr_noptr=attr.type.gsub(/_PTR$/,'')) && structs_by_name[attr_noptr]
162
+ fd_impl.puts "PKCS11_IMPLEMENT_STRUCT_PTR_ACCESSOR(#{struct.name}, #{attr_noptr}, #{attr.name});"
163
+ fd_def.puts "PKCS11_DEFINE_MEMBER(#{struct.name}, #{attr.name});"
164
+ fd_doc.puts"# @return [#{STRUCT_MODULE}::#{attr_noptr}, nil] pointer to struct\nattr_accessor :#{attr.name}"
165
+ elsif std_structs_by_name[attr.type]
166
+ fd_impl.puts "PKCS11_IMPLEMENT_PKCS11_STRUCT_ACCESSOR(#{struct.name}, #{attr.type}, #{attr.name});"
167
+ fd_def.puts "PKCS11_DEFINE_MEMBER(#{struct.name}, #{attr.name});"
168
+ fd_doc.puts"# @return [PKCS11::#{attr.type}] inline struct (see pkcs11.gem)\nattr_accessor :#{attr.name}"
169
+ elsif (attr_noptr=attr.type.gsub(/_PTR$/,'')) && std_structs_by_name[attr_noptr]
170
+ fd_impl.puts "PKCS11_IMPLEMENT_PKCS11_STRUCT_PTR_ACCESSOR(#{struct.name}, #{attr_noptr}, #{attr.name});"
171
+ fd_def.puts "PKCS11_DEFINE_MEMBER(#{struct.name}, #{attr.name});"
172
+ fd_doc.puts"# @return [PKCS11::#{attr_noptr}, nil] pointer to struct (see pkcs11.gem)\nattr_accessor :#{attr.name}"
173
+ else
174
+ fd_impl.puts "/* unimplemented attr #{attr.type} #{attr.name} #{attr.qual} */"
175
+ fd_def.puts "/* unimplemented attr #{attr.type} #{attr.name} #{attr.qual} */"
176
+ end
177
+ end
125
178
  end
126
179
  end
127
- end
128
-
129
- fd_impl.puts
130
- fd_def.puts
131
- fd_doc.puts"end"
132
- end
133
- end
134
- end
135
- end
136
- end
137
180
 
138
- ConstTemplate = Struct.new :regexp, :def
139
- ConstGroups = [
140
- ConstTemplate.new(/#define\s+(CKM_[A-Z_0-9]+)\s+(\w+)/, 'PKCS11_DEFINE_MECHANISM'),
141
- ConstTemplate.new(/#define\s+(CKA_[A-Z_0-9]+)\s+(\w+)/, 'PKCS11_DEFINE_ATTRIBUTE'),
142
- ConstTemplate.new(/#define\s+(CKO_[A-Z_0-9]+)\s+(\w+)/, 'PKCS11_DEFINE_OBJECT_CLASS'),
143
- ConstTemplate.new(/#define\s+(CKR_[A-Z_0-9]+)\s+(\w+)/, 'PKCS11_DEFINE_RETURN_VALUE'),
144
- ]
145
-
146
- File.open(options.const, "w") do |fd_const|
147
- ARGV.each do |file_h|
148
- c_src = IO.read(file_h)
149
- ConstGroups.each do |const_group|
150
- c_src.scan(const_group.regexp) do
151
- const_name, const_value = $1, $2
152
-
153
- fd_const.puts "#{const_group.def}(#{const_name}); /* #{const_value} */"
181
+ fd_impl.puts
182
+ fd_def.puts
183
+ fd_doc.puts "end"
184
+ end
185
+ end
186
+ end
154
187
  end
155
188
  end
156
189
  end
157
190
  end
191
+
192
+ if $0==__FILE__
193
+ PKCS11::StructParser.run(ARGV)
194
+ end