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

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