Skip to content

Commit

Permalink
integrate pkcs11-safenet into pkcs11 repository as it depends heavily…
Browse files Browse the repository at this point in the history
… on it

moreover this allowes generation of combined yard documentation and allowes synchronized VERSION numbers
  • Loading branch information
larskanis committed Apr 29, 2011
1 parent ce41dac commit e955bd4
Show file tree
Hide file tree
Showing 14 changed files with 674 additions and 1 deletion.
2 changes: 1 addition & 1 deletion Rakefile
Expand Up @@ -65,7 +65,7 @@ file 'ext/pk11.h' => 'ext/pk11_thread_funcs.h'

desc "Generate static HTML documentation with YARD"
task :yardoc do
sh "yardoc"
sh "yardoc --title \"PKCS#11/Ruby Interface\" --no-private lib/**/*.rb ext/*.c ext/*.doc pkcs11-safenet/lib/**/*.rb pkcs11-safenet/ext/*.c pkcs11-safenet/ext/*.doc"
end

desc "Publish YARD to wherever you want."
Expand Down
1 change: 1 addition & 0 deletions pkcs11-safenet/.yardopts
@@ -0,0 +1 @@
--title "PKCS#11-Safenet/Ruby Interface" --no-private lib/**/*.rb ext/*.c ext/*.doc
14 changes: 14 additions & 0 deletions pkcs11-safenet/Manifest.txt
@@ -0,0 +1,14 @@
.yardopts
Manifest.txt
README.rdoc
Rakefile
ext/Makefile
ext/extconf.rb
ext/generate_constants.rb
ext/generate_structs.rb
ext/pk11s.c
lib/pkcs11_safenet.rb
lib/pkcs11_safenet/extensions.rb
test/helper.rb
test/test_pkcs11_safenet.rb
test/test_pkcs11_safenet_crypt.rb
89 changes: 89 additions & 0 deletions pkcs11-safenet/README.rdoc
@@ -0,0 +1,89 @@
= PKCS #11/Ruby Interface for Safenet Protect Server HSM

* Homepage: http://github.com/larskanis/pkcs11-safenet
* API documentation: http://pkcs11.rubyforge.org/pkcs11-safenet/
* API documentation of Ruby-PKCS#11: http://pkcs11.rubyforge.org/pkcs11/
* Safenet[http://www.safenet-inc.com] - Protect Server HSM

This ruby gem is an add-on to ruby-pkcs11[http://github.com/larskanis/pkcs11] .
It allowes to use Protect Server specific extensions, which are beyond the PKCS#11 standard.
That means CKA_EXPORT, CKM_DES3_DERIVE_CBC, structs like CK_DES3_CBC_PARAMS, special functions and so on.
The module works on the Unix like operating systems and win32.

== Requirements

* Safenet PTKC-SDK to compile the module
* pkcs11 gem installed (use: <tt>gem install pkcs11</tt> )

== Installation

gem install pkcs11-safenet -- --with-safenet-sdk-dir=/path/to/ETcpsdk

This installs the Safenet-PKCS#11 extension along with pkcs11-gem either by compiling (Unix)
or by using the precompiled gem for Win32.

git clone git://github.com/larskanis/pkcs11-safenet.git
cd pkcs11-safenet
rake gem SAFENET_SDK_DIR=/path/to/ETcpsdk
gem install -l pkg/pkcs11-safenet -- --with-safenet-sdk-dir=/path/to/ETcpsdk

Downloads and installs the gem from git source.

== Usage

Open the software emulation library and login to a session:

require "rubygems"
require "pkcs11_safenet"

pkcs11 = PKCS11::Safenet::Library.new(:sw)
p pkcs11.info
session = pkcs11.active_slots.last.open
session.login(:USER, "1234")
# ... crypto operations
session.logout
session.close

{PKCS11::Safenet::Library#initialize} tries to find the library file in
the standard installation directory on Windows or Linux.

== Cross compiling for mswin32

Using rake-compiler a cross compiled pkcs11-safenet-gem can be build on a linux host for
the win32 platform. There are no runtime dependencies to any but the standard Windows DLLs.

Install mingw32. On a debian based system this should work:

apt-get install mingw32

On MacOS X, if you have MacPorts installed:

port install i386-mingw32-gcc

Install the rake-compiler:

gem install rake-compiler

Download and cross compile ruby for win32:

rake-compiler cross-ruby VERSION=1.8.6-p287

Download and cross compile pkcs11-safenet for win32:

rake cross native gem SAFENET_SDK_DIR=/path/to/ETcpsdk

If everything works, there should be pkcs11-safenet-VERSION-x86-mswin32.gem in the pkg
directory.


== ToDo

* implement Safenet specific function calls
* implement possibility to use callbacks
* add all structs and constants

== Authors
* Lars Kanis <kanis@comcard.de>

== Copying
See MIT-LICENSE included in the package.
81 changes: 81 additions & 0 deletions pkcs11-safenet/Rakefile
@@ -0,0 +1,81 @@
# -*- coding: utf-8 -*-
# -*- ruby -*-

require 'rubygems'
require 'hoe'
require 'rake/extensiontask'
require 'rbconfig'

SAFENET_SDK_DIR = ENV['SAFENET_SDK_DIR'] || '/opt/ETcpsdk'
RUBY_PKCS11_EXT_DIR = File.expand_path('../ext')

CLEAN.include 'ext/pk11s_struct_def.inc'
CLEAN.include 'ext/pk11s_struct_impl.inc'
CLEAN.include 'ext/pk11s_const_def.inc'
CLEAN.include 'lib/pkcs11_ext.so'
CLEAN.include 'tmp'

def pkcs11_version
file = File.join(RUBY_PKCS11_EXT_DIR, 'pk11_version.h')
version_re = /VERSION += +([\"\'])([\d][\d\w\.]+)\1/
File.read_utf(file)[version_re, 2]
end

hoe = Hoe.spec 'pkcs11-safenet' do
developer('Lars Kanis', 'kanis@comcard.de')
extra_deps << ['pkcs11', "= #{pkcs11_version}"]
extra_dev_deps << ['yard', '>= 0.6']
extra_dev_deps << ['rake-compiler', '>= 0.7']

self.url = 'http://github.com/larskanis/pkcs11-safenet'
self.summary = 'Safenet extensions for PKCS#11-Ruby'
self.description = 'This module allows Ruby programs to use vendor extensions for Safenet Protect Server.'
self.version = pkcs11_version

self.readme_file = 'README.rdoc'
self.history_file = '../History.txt'
self.extra_rdoc_files << self.readme_file << 'ext/pk11s.c'
spec_extras[:extensions] = 'ext/extconf.rb'
spec_extras[:files] = File.read_utf("Manifest.txt").split(/\r?\n\r?/)
spec_extras[:files] << 'ext/pk11s_struct_impl.inc'
spec_extras[:files] << 'ext/pk11s_struct_def.inc'
spec_extras[:files] << 'ext/pk11s_const_def.inc'
spec_extras[:files] << 'ext/pk11s_struct.doc'
spec_extras[:files] << 'ext/pk11_struct_macros.h'
spec_extras[:files] << 'ext/pk11_const_macros.h'
spec_extras[:files] << 'ext/pk11_version.h'
spec_extras[:has_rdoc] = 'yard'
end

ENV['RUBY_CC_VERSION'] ||= '1.8.6:1.9.2'

Rake::ExtensionTask.new('pkcs11_safenet_ext', hoe.spec) do |ext|
ext.ext_dir = 'ext'
ext.cross_compile = true # enable cross compilation (requires cross compile toolchain)
ext.cross_platform = ['i386-mswin32', 'i386-mingw32'] # forces the Windows platform instead of the default one

ext.config_options << "--with-safenet-sdk-dir=#{SAFENET_SDK_DIR.inspect}"
ext.config_options << "--with-ruby-pkcs11-include=#{RUBY_PKCS11_EXT_DIR}"
end

file 'ext/pk11_struct_macros.h' do |t|
cp File.join(RUBY_PKCS11_EXT_DIR, 'pk11_struct_macros.h'), t.name
end
file 'ext/pk11_const_macros.h' do |t|
cp File.join(RUBY_PKCS11_EXT_DIR, 'pk11_const_macros.h'), t.name
end
file 'ext/pk11_version.h' do |t|
cp File.join(RUBY_PKCS11_EXT_DIR, 'pk11_version.h'), t.name
end

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']
file 'ext/pk11s_struct_def.inc' => 'ext/generate_structs.rb' do
sh "#{Config::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(SAFENET_SDK_DIR, 'include/ctvdef.h').inspect}"
end
file 'ext/pk11s_struct_impl.inc' => 'ext/pk11s_struct_def.inc'
file 'ext/pk11s_const_def.inc' => 'ext/generate_constants.rb' do
sh "#{Config::CONFIG['ruby_install_name']} ext/generate_constants.rb --const ext/pk11s_const_def.inc #{File.join(SAFENET_SDK_DIR, 'include/ctvdef.h').inspect}"
end
file 'ext/pk11s.c' => ['ext/pk11s_struct_def.inc', 'ext/pk11s_struct_impl.inc', 'ext/pk11s_const_def.inc']

# vim: syntax=ruby
16 changes: 16 additions & 0 deletions pkcs11-safenet/ext/extconf.rb
@@ -0,0 +1,16 @@
require "mkmf"
require "rubygems"

inc, lib = dir_config('safenet-sdk', '/opt/ETcpsdk/include', '/opt/ETcpsdk/lib')
puts "using Safenet-SDK include:#{inc} lib:#{lib}"

# inc, lib = dir_config('ruby-pkcs11')
# inc ||= Gem.required_location('pkcs11', '../ext')
# puts "using ruby-pkcs11 include:#{inc} lib:#{lib}"
# raise "path to ruby-pkcs11/ext could not be found (use --with-ruby-pkcs11-include=my_path)" unless inc
# $INCFLAGS << " -I"+inc

find_header('pk11_struct_macros.h')
find_header('pk11_const_macros.h')

create_makefile("pkcs11_safenet_ext");
42 changes: 42 additions & 0 deletions pkcs11-safenet/ext/generate_constants.rb
@@ -0,0 +1,42 @@
#!/usr/bin/env ruby
# Quick and dirty parser for PKCS#11 constants and
# generator for Ruby wrapper classes.

require 'rubygems'
require Gem.required_location('pkcs11', '../ext/generate_constants.rb')

module PKCS11
module Safenet
class ConstantParser < PKCS11::ConstantParser
ConstGroups = [
ConstTemplate.new(/#define\s+(CKM_[A-Z_0-9]+)\s+(.+)/, 'PKCS11_DEFINE_MECHANISM'),
ConstTemplate.new(/#define\s+(CKA_[A-Z_0-9]+)\s+(.+)/, 'PKCS11_DEFINE_ATTRIBUTE'),
ConstTemplate.new(/#define\s+(CKO_[A-Z_0-9]+)\s+(.+)/, 'PKCS11_DEFINE_OBJECT_CLASS'),
ConstTemplate.new(/#define\s+(CKR_[A-Z_0-9]+)\s+(.+)/, 'PKCS11_DEFINE_RETURN_VALUE'),
]

IgnoreConstants = %w[CKR_CERTIFICATE_NOT_YET_ACTIVE CKR_CERTIFICATE_EXPIRED]

def start!
File.open(options.const, "w") do |fd_const|
options.files.each do |file_h|
c_src = IO.read(file_h)
ConstGroups.each do |const_group|
c_src.scan(const_group.regexp) do
const_name, const_value = $1, $2
next if IgnoreConstants.include?(const_name)

fd_const.puts "#{const_group.def}(#{const_name}); /* #{const_value} */"
end
end
end
end
end
end
end
end


if $0==__FILE__
PKCS11::Safenet::ConstantParser.run(ARGV)
end
75 changes: 75 additions & 0 deletions pkcs11-safenet/ext/generate_structs.rb
@@ -0,0 +1,75 @@
#!/usr/bin/env ruby
# Quick and dirty parser for PKCS#11 structs and
# generator for Ruby wrapper classes.

require 'rubygems'
require 'pkcs11'
require '../ext/generate_structs.rb'

module PKCS11
module Safenet
class StructParser < PKCS11::StructParser

SIZE_CONSTANTS = {
'CK_MANUFACTURER_SIZE' => 32,
'CK_SERIAL_NUMBER_SIZE' => 16,
'CK_TIME_SIZE' => 16,
'CK_LIB_DESC_SIZE' => 32,
'CK_SLOT_DESCRIPTION_SIZE' => 64,
'CK_SLOT_MANUFACTURER_SIZE' => 32,
'CK_MAX_PIN_LEN' => 32,
'CK_TOKEN_LABEL_SIZE' => 32,
'CK_TOKEN_MANUFACTURER_SIZE' => 32,
'CK_TOKEN_MODEL_SIZE' => 16,
'CK_TOKEN_SERIAL_NUMBER_SIZE' => 16,
'CK_TOKEN_TIME_SIZE' => 16,
'CK_MAX_PBE_IV_SIZE' => 8,
'CK_MAX_PAD_SIZE' => 16,
}

ULONG_TYPES = %w[CK_COUNT CK_SIZE CK_TIMESTAMP_FORMAT]
ULONG_PTR_TYPES = %w[CK_COUNT_PTR]

def struct_module
'PKCS11::Safenet'
end

def array_attribute_names; %w[attributes mechanism certAttr hCert]; end

def parse_files(files)
structs = []
files.each do |file_h|
c_src = IO.read(file_h)
c_src.scan(/struct\s+([A-Z_0-9]+)\s*\{(.*?)\}/m) do |struct|
struct_text = $2
struct = PKCS11::StructParser::CStruct.new( $1, [] )

struct_text.scan(/^\s+([A-Z_0-9]+)([\*\s]+)([\w_]+)\s*(\[\s*(\w+)\s*\])?/) do |elem|
type, name = $1, $3
qual = SIZE_CONSTANTS[$5] || $5
ptr = $2.include?('*')
type = "CK_ULONG" if ULONG_TYPES.include?(type)
type = "CK_ULONG_PTR" if ULONG_PTR_TYPES.include?(type)
struct.attrs << Attribute.new(ptr ? type+"_PTR" : type, name, qual)
end
structs << struct
end
end
return structs
end

def start!
@structs = parse_files(options.files)
@structs_by_name = @structs.inject({}){|sum, v| sum[v.name]=v; sum }
@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]=true; sum }

write_files
end
end
end
end


if $0==__FILE__
PKCS11::Safenet::StructParser.run(ARGV)
end

0 comments on commit e955bd4

Please sign in to comment.