Permalink
Browse files

Add parser for PKCS#11 structs and generator for Ruby wrapper classes

This replaces the hand coded mechanism definitions
  • Loading branch information...
1 parent a066529 commit 7b35d4b240477bc8764d5ee7d36711874cf95f21 Lars Kanis committed Sep 19, 2010
Showing with 152 additions and 48 deletions.
  1. +1 −0 Manifest.txt
  2. +13 −0 Rakefile
  3. +87 −0 ext/generate_structs.rb
  4. +51 −48 ext/pk11.c
View
@@ -5,6 +5,7 @@ Manifest.txt
README.rdoc
Rakefile
ext/extconf.rb
+ext/generate_structs.rb
ext/include/cryptoki.h
ext/include/ct-kip.h
ext/include/otp-pkcs11.h
View
@@ -5,6 +5,10 @@ require 'rubygems'
require 'hoe'
require 'rake/extensiontask'
+CLEAN.include 'ext/pk11_struct_def.c'
+CLEAN.include 'ext/pk11_struct_impl.c'
+CLEAN.include 'lib/pkcs11_ext.so'
+
hoe = Hoe.spec 'pkcs11' do
developer('Ryosuke Kutsuna', 'ryosuke@deer-n-horse.jp')
developer('GOTOU Yuuzou', 'gotoyuzo@notwork.org')
@@ -17,6 +21,9 @@ hoe = Hoe.spec 'pkcs11' do
self.readme_file = 'README.rdoc'
self.extra_rdoc_files << self.readme_file << 'ext/pk11.c'
spec_extras[:extensions] = 'ext/extconf.rb'
+ spec_extras[:files] = File.read_utf("Manifest.txt").split(/\r?\n\r?/)
+ spec_extras[:files] << 'ext/pk11_struct_impl.c'
+ spec_extras[:files] << 'ext/pk11_struct_def.c'
end
ENV['RUBY_CC_VERSION'] = '1.8.6:1.9.1'
@@ -27,6 +34,12 @@ Rake::ExtensionTask.new('pkcs11_ext', hoe.spec) do |ext|
ext.cross_platform = ['i386-mswin32', 'i386-mingw32'] # forces the Windows platform instead of the default one
end
+file 'ext/pk11_struct_def.c' => 'ext/generate_structs.rb' do
+ sh "ruby ext/generate_structs.rb --def ext/pk11_struct_def.c --impl ext/pk11_struct_impl.c ext/include/pkcs11t.h"
+end
+file 'ext/pk11_struct_impl.c' => 'ext/pk11_struct_def.c'
+task 'ext/pk11.c' => 'ext/pk11_struct_def.c'
+
# RDoc-upload task for github (currently on rubyforge)
#
# require 'grancher/task'
View
@@ -0,0 +1,87 @@
+#!/usr/bin/env ruby
+# Quick and dirty parser for PKCS#11 structs and
+# generator for Ruby wrapper classes.
+
+require 'optparse'
+
+options = Struct.new(:verbose, :def, :impl).new
+OptionParser.new do |opts|
+ opts.banner = "Usage: #{$0} [options] <header-file.h>*"
+
+ opts.on("-v", "--[no-]verbose", "Run verbosely", &options.method(:verbose=))
+ opts.on("--def FILE", "Write struct definitions to this file", &options.method(:def=))
+ opts.on("--impl FILE", "Write struct implementations to this file", &options.method(:impl=))
+ opts.on_tail("-h", "--help", "Show this message") do
+ puts opts
+ exit
+ end
+end.parse!
+
+Attribute = Struct.new(:type, :name, :qual)
+IgnoreStructs = %w[CK_MECHANISM_INFO CK_VERSION CK_C_INITIALIZE_ARGS CK_MECHANISM CK_ATTRIBUTE CK_INFO CK_SLOT_INFO CK_TOKEN_INFO CK_MECHANISM_INFO CK_SESSION_INFO]
+
+File.open(options.def, "w") do |fd_def|
+File.open(options.impl, "w") do |fd_impl|
+ARGV.each do |file_h|
+ c_src = IO.read(file_h)
+ c_src.scan(/struct\s+([A-Z_0-9]+)\s*\{(.*?)\}/m) do |struct|
+ struct_name, struct_text = $1, $2
+ next if IgnoreStructs.include?(struct_name)
+
+ fd_impl.puts "PKCS11_IMPLEMENT_STRUCT_WITH_ALLOCATOR(#{struct_name});"
+ fd_def.puts "PKCS11_DEFINE_STRUCT(#{struct_name});"
+
+ attrs = {}
+ struct_text.scan(/^\s+([A-Z_0-9]+)\s+([\w_]+)\s*(\[\s*(\d+)\s*\])?/) do |elem|
+ attr = Attribute.new($1, $2, $4)
+ attrs[$1+" "+$2] = attr
+# puts attr.inspect
+ end
+
+ # try to find attributes belonging together
+ attrs.select{|key, attr| ['CK_BYTE_PTR', 'CK_VOID_PTR', 'CK_UTF8CHAR_PTR'].include?(attr.type) }.each do |key, attr|
+ if len_attr=attrs["CK_ULONG #{attr.name.gsub(/^p/, "ul")}Len"]
+ fd_impl.puts "PKCS11_IMPLEMENT_STRING_PTR_LEN_ACCESSOR(#{struct_name}, #{attr.name}, #{len_attr.name});"
+ fd_def.puts "PKCS11_DEFINE_MEMBER(#{struct_name}, #{attr.name});"
+ attrs.delete_if{|k,v| v==len_attr}
+ elsif attr.name=='pData' && (len_attr = attrs["CK_ULONG length"] || attrs["CK_ULONG ulLen"])
+ fd_impl.puts "PKCS11_IMPLEMENT_STRING_PTR_LEN_ACCESSOR(#{struct_name}, #{attr.name}, #{len_attr.name});"
+ fd_def.puts "PKCS11_DEFINE_MEMBER(#{struct_name}, #{attr.name});"
+ attrs.delete_if{|k,v| v==len_attr}
+ else
+ fd_impl.puts "PKCS11_IMPLEMENT_STRING_PTR_ACCESSOR(#{struct_name}, #{attr.name});"
+ fd_def.puts "PKCS11_DEFINE_MEMBER(#{struct_name}, #{attr.name});"
+ end
+ attrs.delete_if{|k,v| v==attr}
+ end
+
+ # standalone attributes
+ attrs.each do |key, attr|
+ case attr.type
+ when 'CK_BYTE', 'CK_UTF8CHAR', 'CK_CHAR'
+ fd_impl.puts "PKCS11_IMPLEMENT_STRING_ACCESSOR(#{struct_name}, #{attr.name});"
+ fd_def.puts "PKCS11_DEFINE_MEMBER(#{struct_name}, #{attr.name});"
+ when 'CK_ULONG', 'CK_FLAGS', 'CK_SLOT_ID', 'CK_STATE', /CK_[A-Z_0-9]+_TYPE/
+ fd_impl.puts "PKCS11_IMPLEMENT_ULONG_ACCESSOR(#{struct_name}, #{attr.name});"
+ fd_def.puts "PKCS11_DEFINE_MEMBER(#{struct_name}, #{attr.name});"
+ when 'CK_OBJECT_HANDLE'
+ fd_impl.puts "PKCS11_IMPLEMENT_HANDLE_ACCESSOR(#{struct_name}, #{attr.name});"
+ fd_def.puts "PKCS11_DEFINE_MEMBER(#{struct_name}, #{attr.name});"
+ when 'CK_BBOOL'
+ fd_impl.puts "PKCS11_IMPLEMENT_BOOL_ACCESSOR(#{struct_name}, #{attr.name});"
+ fd_def.puts "PKCS11_DEFINE_MEMBER(#{struct_name}, #{attr.name});"
+ when 'CK_VERSION'
+ fd_impl.puts "PKCS11_IMPLEMENT_VERSION_ACCESSOR(#{struct_name}, #{attr.name});"
+ fd_def.puts "PKCS11_DEFINE_MEMBER(#{struct_name}, #{attr.name});"
+ else
+ fd_impl.puts "/* unimplemented attr #{attr.type} #{attr.name} #{attr.qual} */"
+ fd_def.puts "/* unimplemented attr #{attr.type} #{attr.name} #{attr.qual} */"
+ end
+ end
+
+ fd_impl.puts
+ fd_def.puts
+ end
+end
+end
+end
View
@@ -1436,6 +1436,39 @@ set_ulong(VALUE obj, VALUE value, off_t offset)
return value;
}
+static VALUE
+get_handle(VALUE obj, off_t offset)
+{
+ char *ptr = (char*)DATA_PTR(obj);
+ return HANDLE2NUM(*(CK_OBJECT_HANDLE_PTR)(ptr+offset));
+}
+
+static VALUE
+set_handle(VALUE obj, VALUE value, off_t offset)
+{
+ char *ptr = (char*)DATA_PTR(obj);
+ *(CK_OBJECT_HANDLE_PTR)(ptr+offset) = NUM2HANDLE(value);
+ return value;
+}
+
+static VALUE
+get_bool(VALUE obj, off_t offset)
+{
+ char *ptr = (char*)DATA_PTR(obj);
+ if(*(CK_BBOOL*)(ptr+offset)) return Qtrue;
+ else return Qfalse;
+}
+
+static VALUE
+set_bool(VALUE obj, VALUE value, off_t offset)
+{
+ char *ptr = (char*)DATA_PTR(obj);
+ if(value == Qfalse) *(CK_BBOOL*)(ptr+offset) = 0;
+ else if(value == Qtrue) *(CK_BBOOL*)(ptr+offset) = 1;
+ else rb_raise(rb_eArgError, "arg must be true or false");
+ return value;
+}
+
static VALUE
get_version(VALUE obj, off_t offset)
{
@@ -1535,6 +1568,22 @@ static VALUE c##s##_set_##f(VALUE o, VALUE v){ \
return set_ulong(o, v, OFFSET_OF(s, f)); \
}
+#define PKCS11_IMPLEMENT_HANDLE_ACCESSOR(s, f) \
+static VALUE c##s##_get_##f(VALUE o){ \
+ return get_handle(o, OFFSET_OF(s, f)); \
+} \
+static VALUE c##s##_set_##f(VALUE o, VALUE v){ \
+ return set_handle(o, v, OFFSET_OF(s, f)); \
+}
+
+#define PKCS11_IMPLEMENT_BOOL_ACCESSOR(s, f) \
+static VALUE c##s##_get_##f(VALUE o){ \
+ return get_bool(o, OFFSET_OF(s, f)); \
+} \
+static VALUE c##s##_set_##f(VALUE o, VALUE v){ \
+ return set_bool(o, v, OFFSET_OF(s, f)); \
+}
+
#define PKCS11_IMPLEMENT_VERSION_ACCESSOR(s, f) \
static VALUE c##s##_get_##f(VALUE o){ \
return get_version(o, OFFSET_OF(s, f)); \
@@ -1610,30 +1659,7 @@ PKCS11_IMPLEMENT_ULONG_ACCESSOR(CK_SESSION_INFO, state);
PKCS11_IMPLEMENT_ULONG_ACCESSOR(CK_SESSION_INFO, flags);
PKCS11_IMPLEMENT_ULONG_ACCESSOR(CK_SESSION_INFO, ulDeviceError);
-PKCS11_IMPLEMENT_STRUCT_WITH_ALLOCATOR(CK_AES_CBC_ENCRYPT_DATA_PARAMS);
-PKCS11_IMPLEMENT_STRING_ACCESSOR(CK_AES_CBC_ENCRYPT_DATA_PARAMS, iv);
-PKCS11_IMPLEMENT_STRING_PTR_LEN_ACCESSOR(CK_AES_CBC_ENCRYPT_DATA_PARAMS, pData, length);
-PKCS11_IMPLEMENT_STRUCT_WITH_ALLOCATOR(CK_DES_CBC_ENCRYPT_DATA_PARAMS);
-PKCS11_IMPLEMENT_STRING_ACCESSOR(CK_DES_CBC_ENCRYPT_DATA_PARAMS, iv);
-PKCS11_IMPLEMENT_STRING_PTR_LEN_ACCESSOR(CK_DES_CBC_ENCRYPT_DATA_PARAMS, pData, length);
-PKCS11_IMPLEMENT_STRUCT_WITH_ALLOCATOR(CK_KEY_DERIVATION_STRING_DATA);
-PKCS11_IMPLEMENT_STRING_PTR_LEN_ACCESSOR(CK_KEY_DERIVATION_STRING_DATA, pData, ulLen);
-
-PKCS11_IMPLEMENT_STRUCT_WITH_ALLOCATOR(CK_RSA_PKCS_OAEP_PARAMS);
-PKCS11_IMPLEMENT_ULONG_ACCESSOR(CK_RSA_PKCS_OAEP_PARAMS, hashAlg);
-PKCS11_IMPLEMENT_ULONG_ACCESSOR(CK_RSA_PKCS_OAEP_PARAMS, mgf);
-PKCS11_IMPLEMENT_ULONG_ACCESSOR(CK_RSA_PKCS_OAEP_PARAMS, source);
-PKCS11_IMPLEMENT_STRING_PTR_LEN_ACCESSOR(CK_RSA_PKCS_OAEP_PARAMS, pSourceData, ulSourceDataLen);
-
-PKCS11_IMPLEMENT_STRUCT_WITH_ALLOCATOR(CK_RSA_PKCS_PSS_PARAMS);
-PKCS11_IMPLEMENT_ULONG_ACCESSOR(CK_RSA_PKCS_PSS_PARAMS, hashAlg);
-PKCS11_IMPLEMENT_ULONG_ACCESSOR(CK_RSA_PKCS_PSS_PARAMS, mgf);
-PKCS11_IMPLEMENT_ULONG_ACCESSOR(CK_RSA_PKCS_PSS_PARAMS, sLen);
-
-PKCS11_IMPLEMENT_STRUCT_WITH_ALLOCATOR(CK_ECDH1_DERIVE_PARAMS);
-PKCS11_IMPLEMENT_ULONG_ACCESSOR(CK_ECDH1_DERIVE_PARAMS, kdf);
-PKCS11_IMPLEMENT_STRING_PTR_LEN_ACCESSOR(CK_ECDH1_DERIVE_PARAMS, pSharedData, ulSharedDataLen);
-PKCS11_IMPLEMENT_STRING_PTR_LEN_ACCESSOR(CK_ECDH1_DERIVE_PARAMS, pPublicData, ulPublicDataLen);
+#include "pk11_struct_impl.c"
///////////////////////////////////////
@@ -1872,30 +1898,7 @@ Init_pkcs11_ext()
PKCS11_DEFINE_MEMBER(CK_MECHANISM, mechanism);
PKCS11_DEFINE_MEMBER(CK_MECHANISM, pParameter);
- PKCS11_DEFINE_STRUCT(CK_AES_CBC_ENCRYPT_DATA_PARAMS);
- PKCS11_DEFINE_MEMBER(CK_AES_CBC_ENCRYPT_DATA_PARAMS, iv);
- PKCS11_DEFINE_MEMBER(CK_AES_CBC_ENCRYPT_DATA_PARAMS, pData);
- PKCS11_DEFINE_STRUCT(CK_DES_CBC_ENCRYPT_DATA_PARAMS);
- PKCS11_DEFINE_MEMBER(CK_DES_CBC_ENCRYPT_DATA_PARAMS, iv);
- PKCS11_DEFINE_MEMBER(CK_DES_CBC_ENCRYPT_DATA_PARAMS, pData);
- PKCS11_DEFINE_STRUCT(CK_KEY_DERIVATION_STRING_DATA);
- PKCS11_DEFINE_MEMBER(CK_KEY_DERIVATION_STRING_DATA, pData);
-
- PKCS11_DEFINE_STRUCT(CK_RSA_PKCS_OAEP_PARAMS);
- PKCS11_DEFINE_MEMBER(CK_RSA_PKCS_OAEP_PARAMS, hashAlg);
- PKCS11_DEFINE_MEMBER(CK_RSA_PKCS_OAEP_PARAMS, mgf);
- PKCS11_DEFINE_MEMBER(CK_RSA_PKCS_OAEP_PARAMS, source);
- PKCS11_DEFINE_MEMBER(CK_RSA_PKCS_OAEP_PARAMS, pSourceData);
-
- PKCS11_DEFINE_STRUCT(CK_RSA_PKCS_PSS_PARAMS);
- PKCS11_DEFINE_MEMBER(CK_RSA_PKCS_PSS_PARAMS, hashAlg);
- PKCS11_DEFINE_MEMBER(CK_RSA_PKCS_PSS_PARAMS, mgf);
- PKCS11_DEFINE_MEMBER(CK_RSA_PKCS_PSS_PARAMS, sLen);
-
- PKCS11_DEFINE_STRUCT(CK_ECDH1_DERIVE_PARAMS);
- PKCS11_DEFINE_MEMBER(CK_ECDH1_DERIVE_PARAMS, kdf);
- PKCS11_DEFINE_MEMBER(CK_ECDH1_DERIVE_PARAMS, pSharedData);
- PKCS11_DEFINE_MEMBER(CK_ECDH1_DERIVE_PARAMS, pPublicData);
+ #include "pk11_struct_def.c"
//CK_AES_CTR_PARAMS
//CK_ARIA_CBC_ENCRYPT_DATA_PARAMS

0 comments on commit 7b35d4b

Please sign in to comment.