# HG changeset patch # User Alessio Caiazza # Date 1265234143 -3600 # Node ID 213b7c4cf03a2a160878d17fbfcfd1d1111e1185 # Parent 06159c254c19f16abc3a0095047c6f064291ff45 restyled for echoe usage. Now modhex is provided ad binary application diff -r 06159c254c19f16abc3a0095047c6f064291ff45 -r 213b7c4cf03a2a160878d17fbfcfd1d1111e1185 CHANGELOG --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/CHANGELOG Wed Feb 03 22:55:43 2010 +0100 @@ -0,0 +1,1 @@ +v0.0.1. First release \ No newline at end of file diff -r 06159c254c19f16abc3a0095047c6f064291ff45 -r 213b7c4cf03a2a160878d17fbfcfd1d1111e1185 Manifest --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Manifest Wed Feb 03 22:55:43 2010 +0100 @@ -0,0 +1,18 @@ +CHANGELOG +LICENSE +Manifest +README +Rakefile +bin/modhex +ext/libyubikey/extconf.rb +ext/libyubikey/libyubikey.c +ext/libyubikey/ykaes.c +ext/libyubikey/ykcrc.c +ext/libyubikey/ykhex.c +ext/libyubikey/ykmodhex.c +ext/libyubikey/ykparse.c +ext/libyubikey/yubikey.h +lib/hex.rb +lib/yubiruby.rb +tests/tc_modhex.rb +tests/ts_yubiruby.rb diff -r 06159c254c19f16abc3a0095047c6f064291ff45 -r 213b7c4cf03a2a160878d17fbfcfd1d1111e1185 Rakefile --- a/Rakefile Tue Feb 02 19:54:28 2010 +0100 +++ b/Rakefile Wed Feb 03 22:55:43 2010 +0100 @@ -1,63 +1,48 @@ +# Rakefile require 'rubygems' -require 'rubygems/gem_runner' +require 'rake' +require 'echoe' -require 'rake/gempackagetask' -require 'rake/rdoctask' +Echoe.new('YubiRuby') do |p| + p.description = <<-EOF +Yubikey integration - -load 'yubiruby.gemspec' +Includes Prototypes for low-level Yubikey OTP functions +witten by Simon Josefsson . +Copyright (c) 2006, 2007, 2008, 2009 Yubico AB +All rights reserved. -Rake::GemPackageTask.new($spec) do |pkg| - pkg.need_tar = true +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +EOF + p.url = "http://bitbucket.org/nolith/yubiruby" + p.author = "Alessio Caiazza" + p.email = "nolith@abisso.org" + p.platform = Gem::Platform::RUBY + p.ignore_pattern = ["tmp/*", "script/*"] + p.development_dependencies = [] end -task :compile do - spec.extensions.each do |e| - file = File.basename e - dir = File.dirname e - %x{cd #{dir}; ruby #{file}; make} - end -end +Dir["#{File.dirname(__FILE__)}/tasks/*.rake"].sort.each { |ext| load ext } -task :test => :compile do -# %w{ lib ext tests }.each do |dir| -# path = File.expand_path(File.join(File.dirname(__FILE__), dir)) -# $LOAD_PATH.unshift(path) -# end - require spec.test_file -end - -# Rake RDocTask with all of the options stubbed out. -Rake::RDocTask.new(:rdoc) do |rd| -# rd.external # run the rdoc process as an external shell -# rd.main = "name" # 'name' will be the initial page displayed - rd.rdoc_dir = "doc" # set the output directory - rd.rdoc_files = FileList["{lib}/**/*"] + ['ext/libyubikey.c'] # List of files to include in the rdoc generation -# rd.template = "html" # Name of the template to be used by rdoc -# rd.title = "" # Title of the RDoc documentation -# rd.options << "--accessor accessorname[,..]" # comma separated list of additional class methods that should be treated like 'attr_reader' and friends. -# rd.options << "--all" # include all methods (not just public) in the output -# rd.options << "--charset charset" # specifies HTML character-set -# rd.options << "--debug" # displays lots on internal stuff -# rd.options << "--diagram" # Generate diagrams showing modules and classes using dot. -# rd.options << "--exclude pattern" # do not process files or directories matching pattern unless they're explicitly included -# rd.options << "--extension new=old" # Treat files ending with .new as if they ended with .old -# rd.options << "--fileboxes" # classes are put in boxes which represents files, where these classes reside. -# rd.options << "--force-update" # forces to scan all sources even if newer than the flag file. -# rd.options << "--fmt format name" # set the output formatter (html, chm, ri, xml) -# rd.options << "--image-format gif/png/jpg/jpeg" # Sets output image format for diagrams. Default is png. -# rd.options << "--include dir[,dir...]" # set (or add to) the list of directories to be searched. -# rd.options << "--inline-source" # Show method source code inline, rather than via a popup link -# rd.options << "--line-numbers" # Include line numbers in the source code -# rd.options << "--merge" # when creating ri output, merge processed classes into previously documented classes of the name name -# rd.options << "--one-file" # put all the output into a single file -# rd.options << "--opname name" # Set the 'name' of the output. Has no effect for HTML format. -# rd.options << "--promiscuous" # Show module/class in the files page. -# rd.options << "--quiet" # don't show progress as we parse -# rd.options << "--ri" # generate output for use by 'ri.' local -# rd.options << "--ri-site" # generate output for use by 'ri.' sitewide -# rd.options << "--ri-system" # generate output for use by 'ri.' system wide, for Ruby installs. -# rd.options << "--show-hash" # A name of the form #name in a comment is a possible hyperlink to an instance method name. When displayed, the '#' is removed unless this option is specified -# rd.options << "--style stylesheet url" # specifies the URL of a separate stylesheet. -# rd.options << "--tab-width n" # Set the width of tab characters (default 8) -# rd.options << "--webcvs url" # Specify a URL for linking to a web frontend to CVS. - end \ No newline at end of file diff -r 06159c254c19f16abc3a0095047c6f064291ff45 -r 213b7c4cf03a2a160878d17fbfcfd1d1111e1185 YubiRuby.gemspec --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/YubiRuby.gemspec Wed Feb 03 22:55:43 2010 +0100 @@ -0,0 +1,63 @@ +# -*- encoding: utf-8 -*- + +Gem::Specification.new do |s| + s.name = %q{YubiRuby} + s.version = "0.0.1" + + s.required_rubygems_version = Gem::Requirement.new(">= 1.2") if s.respond_to? :required_rubygems_version= + s.authors = ["Alessio Caiazza"] + s.date = %q{2010-02-03} + s.default_executable = %q{modhex} + s.description = %q{Yubikey integration - + +Includes Prototypes for low-level Yubikey OTP functions +witten by Simon Josefsson . +Copyright (c) 2006, 2007, 2008, 2009 Yubico AB +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +} + s.email = %q{nolith@abisso.org} + s.executables = ["modhex"] + s.extensions = ["ext/libyubikey/extconf.rb"] + s.extra_rdoc_files = ["CHANGELOG", "LICENSE", "README", "bin/modhex", "ext/libyubikey/extconf.rb", "ext/libyubikey/libyubikey.c", "ext/libyubikey/ykaes.c", "ext/libyubikey/ykcrc.c", "ext/libyubikey/ykhex.c", "ext/libyubikey/ykmodhex.c", "ext/libyubikey/ykparse.c", "ext/libyubikey/yubikey.h", "lib/hex.rb", "lib/yubiruby.rb"] + s.files = ["CHANGELOG", "LICENSE", "Manifest", "README", "Rakefile", "bin/modhex", "ext/libyubikey/extconf.rb", "ext/libyubikey/libyubikey.c", "ext/libyubikey/ykaes.c", "ext/libyubikey/ykcrc.c", "ext/libyubikey/ykhex.c", "ext/libyubikey/ykmodhex.c", "ext/libyubikey/ykparse.c", "ext/libyubikey/yubikey.h", "lib/hex.rb", "lib/yubiruby.rb", "tests/tc_modhex.rb", "tests/ts_yubiruby.rb", "YubiRuby.gemspec"] + s.homepage = %q{http://bitbucket.org/nolith/yubiruby} + s.rdoc_options = ["--line-numbers", "--inline-source", "--title", "YubiRuby", "--main", "README"] + s.require_paths = ["lib", "ext"] + s.rubyforge_project = %q{yubiruby} + s.rubygems_version = %q{1.3.5} + s.summary = %q{Yubikey integration - Includes Prototypes for low-level Yubikey OTP functions witten by Simon Josefsson . Copyright (c) 2006, 2007, 2008, 2009 Yubico AB All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.} + + if s.respond_to? :specification_version then + current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION + s.specification_version = 3 + + if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then + else + end + else + end +end diff -r 06159c254c19f16abc3a0095047c6f064291ff45 -r 213b7c4cf03a2a160878d17fbfcfd1d1111e1185 bin/modhex --- a/bin/modhex Tue Feb 02 19:54:28 2010 +0100 +++ b/bin/modhex Wed Feb 03 22:55:43 2010 +0100 @@ -1,48 +1,45 @@ #!/usr/bin/env ruby -wKU -$:.unshift File.join(File.dirname(__FILE__),'..','lib') -$:.unshift File.join(File.dirname(__FILE__),'..','ext') require 'yubiruby' -if __FILE__ == $PROGRAM_NAME - if ARGV.length < 1 - msg=<<-EOF + +if ARGV.length < 1 + msg=<<-EOF Usage: #{$PROGRAM_NAME} [-dh] - + Convert input DATA as specified and print output to STDOUT. - -d: Decode data (the default is to encode data). - -h: Use hex encoding for all non-modhex data. - DATA: string with data to encode +-d: Decode data (the default is to encode data). +-h: Use hex encoding for all non-modhex data. +DATA: string with data to encode Examples: - ModHex encode ASCII-string \"test\": - #{$PROGRAM_NAME} test +ModHex encode ASCII-string \"test\": + #{$PROGRAM_NAME} test - Decode ModHex data \"ifhgieif\" into ASCII string: - #{$PROGRAM_NAME} -d ifhgieif +Decode ModHex data \"ifhgieif\" into ASCII string: + #{$PROGRAM_NAME} -d ifhgieif - ModHex encode hex-encoded data \"b565716f\": - #{$PROGRAM_NAME} -h b565716f +ModHex encode hex-encoded data \"b565716f\": + #{$PROGRAM_NAME} -h b565716f - Decode ModHex data \"nghgibhv\" and print hex-encode data: - #{$PROGRAM_NAME} -d -h nghgibhv +Decode ModHex data \"nghgibhv\" and print hex-encode data: + #{$PROGRAM_NAME} -d -h nghgibhv EOF - abort msg - end + abort msg +end + +hex = ARGV.include? "-h" +decode = ARGV.include? "-d" +data = ARGV.last + +if decode + out = data.modhex_decode + out = YubiRuby::HEX.encode(out) if hex + puts out +else + data = YubiRuby::HEX.decode(data) if hex + puts data.modhex_encode +end - hex = ARGV.include? "-h" - decode = ARGV.include? "-d" - data = ARGV.last - - if decode - out = data.modhex_decode - out = YubiRuby::HEX.encode(out) if hex - puts out - else - data = YubiRuby::HEX.decode(data) if hex - puts data.modhex_encode - end - -end \ No newline at end of file diff -r 06159c254c19f16abc3a0095047c6f064291ff45 -r 213b7c4cf03a2a160878d17fbfcfd1d1111e1185 ext/extconf.rb --- a/ext/extconf.rb Tue Feb 02 19:54:28 2010 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,14 +0,0 @@ -require 'mkmf' -#dir_config("libyubikey") -if ARGV.include?('-h') - abort <<-EOF -Usage: #{$PROGRAM_NAME} [options] - -Options: - -d debug mode - -h print this help -EOF -end - -$CFLAGS << " -DNDEBUG" unless ARGV.include?('-d') -create_makefile('libyubikey') \ No newline at end of file diff -r 06159c254c19f16abc3a0095047c6f064291ff45 -r 213b7c4cf03a2a160878d17fbfcfd1d1111e1185 ext/libyubikey.c --- a/ext/libyubikey.c Tue Feb 02 19:54:28 2010 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,534 +0,0 @@ -/* libyubikey.c --- Ruby wrapper for low-level Yubikey OTP functions. - * - * Written by Alessio Caiazza . - * Copyright (c) 2010 Alessio Caiazza - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials provided - * with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -#include -#include -#include "yubikey.h" - -#define MODHEX_SING_ENCODE "encode" -#define MODHEX_SING_DECODE "decode" -#define MODHEX_ENCODE "modhex_encode" -#define MODHEX_DECODE "modhex_decode" -#define MODHEX_VALID "modhex?" - -static VALUE mYubiRuby; -static VALUE mModHex; -static VALUE cYubikey; - - -/* ModHex */ - -/* - * call-seq: - * YubyRuby::ModHex.encode(obj) -> "modhex string" - * - * Encodes obj.to_str into a modhex string. - */ -static VALUE modhex_sing_encode(VALUE self, VALUE obj) -{ - VALUE str = StringValue(obj); - int src_size = RSTRING(str)->len; - char *dst = (char*) malloc((2*src_size+1)*sizeof(char)); - /* ModHex encode input string SRC of length SRCSIZE and put the zero - terminated output string in DST. The size of the output string DST - must be at least 2*SRCSIZE+1. The output string is always - 2*SRCSIZE large plus the terminating zero. */ - yubikey_modhex_encode(dst, RSTRING(str)->ptr, src_size); - - return rb_str_new2(dst); -} - -/* - * call-seq: - * str.modhex_encode -> "modhex string" - * - * Invokes YubyRuby::ModHex.encode on +self+. - */ -static VALUE modhex_encode(VALUE self) -{ - ID method = rb_intern(MODHEX_SING_ENCODE); - - return rb_funcall(mModHex, method, 1, self); -} - -/* - * call-seq: - * YubyRuby::ModHex.decode(obj) -> "string" - * - * Decodes obj.to_str into a string. - * - * No validatition of format in provided, use YubyRuby::ModHex.modhex? - * for checking. - */ -static VALUE modhex_sing_decode(VALUE self, VALUE obj) -{ - VALUE str = StringValue(obj); - int src_size = RSTRING(str)->len; - char *dst = (char*) malloc(((src_size/2)+1)*sizeof(char)); - /* ModHex decode input string SRC of length DSTSIZE/2 into output - string DST. The output string DST is always DSTSIZE/2 large plus - the terminating zero. */ - yubikey_modhex_decode(dst, RSTRING(str)->ptr, src_size); - - return rb_str_new2(dst); -} - -/* - * call-seq: - * str.modhec_decode -> "string" - * - * Invokes YubyRuby::ModHex.decode on +self+. - */ -static VALUE modhex_decode(VALUE self) -{ - ID method = rb_intern(MODHEX_SING_DECODE); - - return rb_funcall(mModHex, method, 1, self); -} - -/* - * call-seq: - * YubyRuby::ModHex.modhex?(obj) -> true or false - * - * Checks if obj.to_str is a valid modhex string. - */ -static VALUE modhex_sing_is_modhex(VALUE self, VALUE obj) -{ - VALUE str = StringValue(obj); - if (yubikey_modhex_p(RSTRING(str)->ptr) != 0) - return Qtrue; - else - return Qfalse; -} - -/* - * call-seq: - * str.modhex? -> true or false - * - * Invokes YubyRuby::ModHex.modhex? on +self+ - */ -static VALUE modhex_is_modhex(VALUE self) -{ - ID method = rb_intern(MODHEX_VALID); - - return rb_funcall(mModHex, method, 1, self); -} -/* ModHex END */ - -/* Yubikey */ - -typedef struct { - uint8_t key[YUBIKEY_KEY_SIZE]; - yubikey_token_t token; -} yubikey_data; - -static void yubikey_free(void *p) -{ - free(((yubikey_data*)p)->token); - free(p); -} - -// allocate space for internal structures -static VALUE yubikey_alloc(VALUE klass) -{ - yubikey_data* data; - VALUE obj; - - data = (yubikey_data*) malloc(sizeof(yubikey_data)); - data->token = (yubikey_token_t)malloc(sizeof(yubikey_token_st)); - - obj = Data_Wrap_Struct(klass, 0, yubikey_free, data); - - return obj; -} - -/* call-seq: - * yubikey.key = "hex string" - * - * Sets the AES key to the hex string. - */ -static VALUE yubikey_set_key(VALUE self, VALUE key) -{ - yubikey_data* data; - - Data_Get_Struct(self, yubikey_data, data); - VALUE sKey = StringValue(key); - - if (sKey == Qnil) - rb_raise(rb_eTypeError, "wrong parameter type."); - - if (RSTRING(sKey)->len == YUBIKEY_KEY_SIZE*2) { - /* Hex */ - if (yubikey_hex_p(RSTRING(sKey)->ptr) == 0) - rb_raise(rb_eTypeError, "not an HEX string."); //TODO:ArgumentError - char* buff = (char*) malloc(sizeof(char)*(YUBIKEY_KEY_SIZE +1)); - yubikey_hex_decode( buff, RSTRING(sKey)->ptr, YUBIKEY_KEY_SIZE ); - MEMCPY(&data->key, buff, uint8_t, YUBIKEY_KEY_SIZE); - } - - return key; -} - -/* call-seq: - * yubikey.key -> "hex string" - * - * Gets the AES key as an hex string. - */ -static VALUE yubikey_get_key(VALUE self) -{ - yubikey_data* data; - - Data_Get_Struct(self, yubikey_data, data); - - char key[YUBIKEY_KEY_SIZE*2 + 1]; - char* buff = (char*) malloc(sizeof(char)*(YUBIKEY_KEY_SIZE +1)); - MEMCPY(buff, &data->key, uint8_t, YUBIKEY_KEY_SIZE); - buff[YUBIKEY_KEY_SIZE] = '\0'; - - yubikey_hex_encode( key, buff, YUBIKEY_KEY_SIZE ); - - return rb_str_new2(key); -} - -/* call-seq: - * Yubikey.new(aes_key) -> new_yubikey - * - * Creates a yubikey parser whith +aes_key+ ad AES key. - * - * +aes_key+ musb be encoded with YubiRuby::HEX.encode. - */ -static VALUE yubikey_initialize(VALUE self, VALUE key) -{ - yubikey_data* data; - - Data_Get_Struct(self, yubikey_data, data); - - yubikey_set_key(self, key); - - return self; -} - -static VALUE yubikey_init_copy(VALUE copy, VALUE orig) -{ - yubikey_data *t_orig, *t_copy; - - if (copy == orig) - return copy; - - if (TYPE(orig) != T_DATA || - RDATA(orig)->dfree != (RUBY_DATA_FUNC)yubikey_free) { - rb_raise(rb_eTypeError, "wrong argument type."); - } - - Data_Get_Struct(orig, yubikey_data, t_orig); - Data_Get_Struct(copy, yubikey_data, t_copy); - MEMCPY(&t_copy->key, &t_orig->key, uint8_t, YUBIKEY_KEY_SIZE); - MEMCPY(t_copy->token, t_orig->token, yubikey_token_st, 1); - - return copy; -} - -/* call-seq: - * yubikey.parse(otp) -> true or false - * - * Checks the +otp+ for a valid SSO. - */ -static VALUE yubikey_check(VALUE self, VALUE otp) -{ - yubikey_data *data; - - VALUE str = StringValue(otp); - if (str == Qnil) - rb_raise(rb_eTypeError, "wrong argument type."); - - int start = RSTRING(str)->len - 32; - - if (start < 0) - rb_raise(rb_eTypeError, "OTP too short."); //Argument error - - Data_Get_Struct(self, yubikey_data, data); - -#ifndef NDEBUG - /* Debug. */ - char *buff = (char*)malloc(YUBIKEY_KEY_SIZE+1); - yubikey_modhex_decode ((char*)buff, - (RSTRING(str)->ptr+start), - YUBIKEY_KEY_SIZE); - printf ("Input:\n"); - printf (" token: %s\n", (RSTRING(str)->ptr+start)); - - { - size_t i; - printf (" "); - for (i = 0; i < YUBIKEY_KEY_SIZE; i++) - printf ("%02x ", buff[i] & 0xFF); - printf ("\n"); - } - - printf (" aeskey: %s\n", RSTRING(yubikey_get_key(self))->ptr); - - { - size_t i; - printf (" "); - for (i = 0; i < YUBIKEY_KEY_SIZE; i++) - printf ("%02x ", data->key[i] & 0xFF); - printf ("\n"); - } -#endif - - /* Decrypt TOKEN using KEY and store output in OUT structure. Note - that there is no error checking whether the output data is valid or - not, use yubikey_check_* for that. */ - yubikey_parse ((uint8_t*)(RSTRING(str)->ptr+start), data->key, data->token); - -#ifndef NDEBUG - printf ("Output:\n"); - { - size_t i; - printf (" "); - for (i = 0; i < YUBIKEY_BLOCK_SIZE; i++) - printf ("%02x ", ((uint8_t*)data->token)[i] & 0xFF); - printf ("\n"); - } - - yubikey_token_st tok = *data->token; - printf ("\nStruct:\n"); - /* Debug */ - { - size_t i; - printf (" uid: "); - for (i = 0; i < YUBIKEY_UID_SIZE; i++) - printf ("%02x ", data->token->uid[i] & 0xFF); - printf ("\n"); - } - printf (" counter: %d (0x%04x)\n", tok.ctr, tok.ctr); - printf (" timestamp (low): %d (0x%04x)\n", tok.tstpl, tok.tstpl); - printf (" timestamp (high): %d (0x%02x)\n", tok.tstph, tok.tstph); - printf (" session use: %d (0x%02x)\n", tok.use, tok.use); - printf (" random: %d (0x%02x)\n", tok.rnd, tok.rnd); - printf (" crc: %d (0x%04x)\n", tok.crc, tok.crc); - - printf ("\nDerived:\n"); - printf (" cleaned counter: %d (0x%04x)\n", - yubikey_counter (tok.ctr), yubikey_counter (tok.ctr)); - yubikey_modhex_encode ((char*)buff, (char*)tok.uid, YUBIKEY_UID_SIZE); - printf (" modhex uid: %s\n", buff); - printf (" triggered by caps lock: %s\n", - yubikey_capslock(tok.ctr) ? "yes" : "no"); - printf (" crc: %04X\n", yubikey_crc16 ((void*)&tok, YUBIKEY_KEY_SIZE)); - - printf (" crc check: "); - if (yubikey_crc_ok_p ((uint8_t*)&tok)) - printf("ok\n"); - else - printf ("fail\n"); -#endif - if (yubikey_crc_ok_p ((uint8_t*)data->token)) - return Qtrue; - else - return Qfalse; -} - -/* call-seq: - * yubikey.to_str -> String - * - * Gets the decoded token as hex string representation. - */ -static VALUE yubikey_to_str(VALUE self) -{ - size_t i; - yubikey_data *data; - Data_Get_Struct(self, yubikey_data, data); - - VALUE ary = rb_ary_new2(YUBIKEY_BLOCK_SIZE); - for (i = 0; i < YUBIKEY_BLOCK_SIZE; i++) { - VALUE num = INT2FIX(((uint8_t*)data->token)[i]); - //invoke .to_s 16 on each number - rb_ary_store(ary, i, rb_funcall(num, rb_intern("to_s"), 1, INT2FIX(16) )); - } - - return rb_funcall(ary, rb_intern("join"), 0); -} - -/* call-seq: - * yubikey.uid -> "hex string" - * - * Gets the decoded token UID field as hex string representation. - */ -static VALUE yubikey_get_uid(VALUE self) -{ - VALUE out = yubikey_to_str(self); - - // *2 becaouse of hex - return rb_str_new(RSTRING(out)->ptr, YUBIKEY_UID_SIZE*2 ); -} - -/* call-seq: - * yubikey.counter -> Fixnum - * - * Gets the decoded token counter field. - */ -static VALUE yubikey_get_counter(VALUE self) -{ - yubikey_data *data; - Data_Get_Struct(self, yubikey_data, data); - - return INT2FIX(yubikey_counter(data->token->ctr)); -} - -/* call-seq: - * yubikey.triggered_by_capslock? -> true or false - * - */ -static VALUE yubikey_get_triggered_by_capslock(VALUE self) -{ - yubikey_data *data; - Data_Get_Struct(self, yubikey_data, data); - - if (yubikey_capslock(data->token->ctr)) - return Qtrue; - else - return Qfalse; -} - -static VALUE yubikey_get_tsl(VALUE self) -{ - yubikey_data *data; - Data_Get_Struct(self, yubikey_data, data); - - return INT2FIX(data->token->tstpl); -} - -static VALUE yubikey_get_tsh(VALUE self) -{ - yubikey_data *data; - Data_Get_Struct(self, yubikey_data, data); - - return INT2FIX(data->token->tstph); -} - -static VALUE yubikey_get_session(VALUE self) -{ - yubikey_data *data; - Data_Get_Struct(self, yubikey_data, data); - - return INT2FIX(data->token->use); -} - -static VALUE yubikey_get_random(VALUE self) -{ - yubikey_data *data; - Data_Get_Struct(self, yubikey_data, data); - - return INT2FIX(data->token->rnd); -} - -static VALUE yubikey_get_crc(VALUE self) -{ - yubikey_data *data; - Data_Get_Struct(self, yubikey_data, data); - - return INT2FIX(data->token->crc); -} - -static VALUE yubikey_calc_crc(VALUE self) -{ - yubikey_data *data; - Data_Get_Struct(self, yubikey_data, data); - - return INT2FIX(yubikey_crc16 ((void*)data->token, YUBIKEY_KEY_SIZE)); -} - -static VALUE yubikey_check_crc(VALUE self) -{ - yubikey_data *data; - Data_Get_Struct(self, yubikey_data, data); - - if (yubikey_crc_ok_p ((uint8_t*)data->token)) - return Qtrue; - else - return Qfalse; -} -/* Yubikey END */ - -/* Implementation of Yubikey OTP functions. - * This Module may be used to interact with a Yubikey - */ -void Init_libyubikey() { - mYubiRuby = rb_define_module("YubiRuby"); - - /* ModHex string encoder/decoder - * - * The YubiKey uses a special data encoding format known as "modhex" rather - * than normal hex encoding or base64 encoding. - * Modhex is similar to hex encoding but with a different encoding alphabet. - * The reason is to achieve a keyboard layout independent encoding. - * - * The String class in extended with this module. - */ - mModHex = rb_define_module_under(mYubiRuby, "ModHex"); - rb_define_singleton_method(mModHex, "encode", modhex_sing_encode, 1); - rb_define_method(mModHex, "modhex_encode", modhex_encode, 0); - rb_define_singleton_method(mModHex, "decode", modhex_sing_decode, 1); - rb_define_method(mModHex, "modhex_decode", modhex_decode, 0); - rb_define_singleton_method(mModHex, "modhex?", modhex_sing_is_modhex, 1); - rb_define_method(mModHex, "modhex?", modhex_is_modhex, 0); - /* lists of allowed char in MODHEX enconding */ - rb_define_const(mModHex, "MODHEX_MAP", rb_str_new2(YUBIKEY_MODHEX_MAP)); - - //extends String with ModHex - rb_include_module(rb_cString, mModHex); - - /* Prototypes for low-level Yubikey OTP functions. - * - */ - cYubikey = rb_define_class_under(mYubiRuby, "Yubikey", rb_cObject); - rb_define_alloc_func(cYubikey, yubikey_alloc); - rb_define_method(cYubikey, "initialize", yubikey_initialize, 1); - rb_define_method(cYubikey, "initialize_copy", yubikey_init_copy, 1); - /* CRC value for a valid token */ - rb_define_const(cYubikey, "CRC_OK_RESIDUE", INT2FIX(YUBIKEY_CRC_OK_RESIDUE)); - rb_define_method(cYubikey, "key", yubikey_get_key, 0); - rb_define_method(cYubikey, "key=", yubikey_set_key, 1); - rb_define_method(cYubikey, "parse", yubikey_check, 1); - rb_define_method(cYubikey, "to_str", yubikey_to_str, 0); - rb_define_alias(cYubikey, "to_s", "to_str"); - rb_define_method(cYubikey, "uid", yubikey_get_uid, 0); - rb_define_method(cYubikey, "counter", yubikey_get_counter, 0); - rb_define_method(cYubikey, "triggered_by_capslock?", yubikey_get_triggered_by_capslock, 0); - rb_define_method(cYubikey, "timestamp_low", yubikey_get_tsl, 0); - rb_define_method(cYubikey, "timestamp_high", yubikey_get_tsh, 0); - rb_define_method(cYubikey, "session", yubikey_get_session, 0); - rb_define_method(cYubikey, "random", yubikey_get_random, 0); - rb_define_method(cYubikey, "crc", yubikey_get_crc, 0); - rb_define_method(cYubikey, "crc_residue", yubikey_calc_crc, 0); - rb_define_method(cYubikey, "crc?", yubikey_check_crc, 0); -} \ No newline at end of file diff -r 06159c254c19f16abc3a0095047c6f064291ff45 -r 213b7c4cf03a2a160878d17fbfcfd1d1111e1185 ext/libyubikey/extconf.rb --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ext/libyubikey/extconf.rb Wed Feb 03 22:55:43 2010 +0100 @@ -0,0 +1,14 @@ +require 'mkmf' +#dir_config("libyubikey") +if ARGV.include?('-h') + abort <<-EOF +Usage: #{$PROGRAM_NAME} [options] + +Options: + -d debug mode + -h print this help +EOF +end + +$CFLAGS << " -DNDEBUG" unless ARGV.include?('-d') +create_makefile('libyubikey') \ No newline at end of file diff -r 06159c254c19f16abc3a0095047c6f064291ff45 -r 213b7c4cf03a2a160878d17fbfcfd1d1111e1185 ext/libyubikey/libyubikey.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ext/libyubikey/libyubikey.c Wed Feb 03 22:55:43 2010 +0100 @@ -0,0 +1,534 @@ +/* libyubikey.c --- Ruby wrapper for low-level Yubikey OTP functions. + * + * Written by Alessio Caiazza . + * Copyright (c) 2010 Alessio Caiazza + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include "yubikey.h" + +#define MODHEX_SING_ENCODE "encode" +#define MODHEX_SING_DECODE "decode" +#define MODHEX_ENCODE "modhex_encode" +#define MODHEX_DECODE "modhex_decode" +#define MODHEX_VALID "modhex?" + +static VALUE mYubiRuby; +static VALUE mModHex; +static VALUE cYubikey; + + +/* ModHex */ + +/* + * call-seq: + * YubyRuby::ModHex.encode(obj) -> "modhex string" + * + * Encodes obj.to_str into a modhex string. + */ +static VALUE modhex_sing_encode(VALUE self, VALUE obj) +{ + VALUE str = StringValue(obj); + int src_size = RSTRING(str)->len; + char *dst = (char*) malloc((2*src_size+1)*sizeof(char)); + /* ModHex encode input string SRC of length SRCSIZE and put the zero + terminated output string in DST. The size of the output string DST + must be at least 2*SRCSIZE+1. The output string is always + 2*SRCSIZE large plus the terminating zero. */ + yubikey_modhex_encode(dst, RSTRING(str)->ptr, src_size); + + return rb_str_new2(dst); +} + +/* + * call-seq: + * str.modhex_encode -> "modhex string" + * + * Invokes YubyRuby::ModHex.encode on +self+. + */ +static VALUE modhex_encode(VALUE self) +{ + ID method = rb_intern(MODHEX_SING_ENCODE); + + return rb_funcall(mModHex, method, 1, self); +} + +/* + * call-seq: + * YubyRuby::ModHex.decode(obj) -> "string" + * + * Decodes obj.to_str into a string. + * + * No validatition of format in provided, use YubyRuby::ModHex.modhex? + * for checking. + */ +static VALUE modhex_sing_decode(VALUE self, VALUE obj) +{ + VALUE str = StringValue(obj); + int src_size = RSTRING(str)->len; + char *dst = (char*) malloc(((src_size/2)+1)*sizeof(char)); + /* ModHex decode input string SRC of length DSTSIZE/2 into output + string DST. The output string DST is always DSTSIZE/2 large plus + the terminating zero. */ + yubikey_modhex_decode(dst, RSTRING(str)->ptr, src_size); + + return rb_str_new2(dst); +} + +/* + * call-seq: + * str.modhec_decode -> "string" + * + * Invokes YubyRuby::ModHex.decode on +self+. + */ +static VALUE modhex_decode(VALUE self) +{ + ID method = rb_intern(MODHEX_SING_DECODE); + + return rb_funcall(mModHex, method, 1, self); +} + +/* + * call-seq: + * YubyRuby::ModHex.modhex?(obj) -> true or false + * + * Checks if obj.to_str is a valid modhex string. + */ +static VALUE modhex_sing_is_modhex(VALUE self, VALUE obj) +{ + VALUE str = StringValue(obj); + if (yubikey_modhex_p(RSTRING(str)->ptr) != 0) + return Qtrue; + else + return Qfalse; +} + +/* + * call-seq: + * str.modhex? -> true or false + * + * Invokes YubyRuby::ModHex.modhex? on +self+ + */ +static VALUE modhex_is_modhex(VALUE self) +{ + ID method = rb_intern(MODHEX_VALID); + + return rb_funcall(mModHex, method, 1, self); +} +/* ModHex END */ + +/* Yubikey */ + +typedef struct { + uint8_t key[YUBIKEY_KEY_SIZE]; + yubikey_token_t token; +} yubikey_data; + +static void yubikey_free(void *p) +{ + free(((yubikey_data*)p)->token); + free(p); +} + +// allocate space for internal structures +static VALUE yubikey_alloc(VALUE klass) +{ + yubikey_data* data; + VALUE obj; + + data = (yubikey_data*) malloc(sizeof(yubikey_data)); + data->token = (yubikey_token_t)malloc(sizeof(yubikey_token_st)); + + obj = Data_Wrap_Struct(klass, 0, yubikey_free, data); + + return obj; +} + +/* call-seq: + * yubikey.key = "hex string" + * + * Sets the AES key to the hex string. + */ +static VALUE yubikey_set_key(VALUE self, VALUE key) +{ + yubikey_data* data; + + Data_Get_Struct(self, yubikey_data, data); + VALUE sKey = StringValue(key); + + if (sKey == Qnil) + rb_raise(rb_eTypeError, "wrong parameter type."); + + if (RSTRING(sKey)->len == YUBIKEY_KEY_SIZE*2) { + /* Hex */ + if (yubikey_hex_p(RSTRING(sKey)->ptr) == 0) + rb_raise(rb_eTypeError, "not an HEX string."); //TODO:ArgumentError + char* buff = (char*) malloc(sizeof(char)*(YUBIKEY_KEY_SIZE +1)); + yubikey_hex_decode( buff, RSTRING(sKey)->ptr, YUBIKEY_KEY_SIZE ); + MEMCPY(&data->key, buff, uint8_t, YUBIKEY_KEY_SIZE); + } + + return key; +} + +/* call-seq: + * yubikey.key -> "hex string" + * + * Gets the AES key as an hex string. + */ +static VALUE yubikey_get_key(VALUE self) +{ + yubikey_data* data; + + Data_Get_Struct(self, yubikey_data, data); + + char key[YUBIKEY_KEY_SIZE*2 + 1]; + char* buff = (char*) malloc(sizeof(char)*(YUBIKEY_KEY_SIZE +1)); + MEMCPY(buff, &data->key, uint8_t, YUBIKEY_KEY_SIZE); + buff[YUBIKEY_KEY_SIZE] = '\0'; + + yubikey_hex_encode( key, buff, YUBIKEY_KEY_SIZE ); + + return rb_str_new2(key); +} + +/* call-seq: + * Yubikey.new(aes_key) -> new_yubikey + * + * Creates a yubikey parser whith +aes_key+ ad AES key. + * + * +aes_key+ musb be encoded with YubiRuby::HEX.encode. + */ +static VALUE yubikey_initialize(VALUE self, VALUE key) +{ + yubikey_data* data; + + Data_Get_Struct(self, yubikey_data, data); + + yubikey_set_key(self, key); + + return self; +} + +static VALUE yubikey_init_copy(VALUE copy, VALUE orig) +{ + yubikey_data *t_orig, *t_copy; + + if (copy == orig) + return copy; + + if (TYPE(orig) != T_DATA || + RDATA(orig)->dfree != (RUBY_DATA_FUNC)yubikey_free) { + rb_raise(rb_eTypeError, "wrong argument type."); + } + + Data_Get_Struct(orig, yubikey_data, t_orig); + Data_Get_Struct(copy, yubikey_data, t_copy); + MEMCPY(&t_copy->key, &t_orig->key, uint8_t, YUBIKEY_KEY_SIZE); + MEMCPY(t_copy->token, t_orig->token, yubikey_token_st, 1); + + return copy; +} + +/* call-seq: + * yubikey.parse(otp) -> true or false + * + * Checks the +otp+ for a valid SSO. + */ +static VALUE yubikey_check(VALUE self, VALUE otp) +{ + yubikey_data *data; + + VALUE str = StringValue(otp); + if (str == Qnil) + rb_raise(rb_eTypeError, "wrong argument type."); + + int start = RSTRING(str)->len - 32; + + if (start < 0) + rb_raise(rb_eTypeError, "OTP too short."); //Argument error + + Data_Get_Struct(self, yubikey_data, data); + +#ifndef NDEBUG + /* Debug. */ + char *buff = (char*)malloc(YUBIKEY_KEY_SIZE+1); + yubikey_modhex_decode ((char*)buff, + (RSTRING(str)->ptr+start), + YUBIKEY_KEY_SIZE); + printf ("Input:\n"); + printf (" token: %s\n", (RSTRING(str)->ptr+start)); + + { + size_t i; + printf (" "); + for (i = 0; i < YUBIKEY_KEY_SIZE; i++) + printf ("%02x ", buff[i] & 0xFF); + printf ("\n"); + } + + printf (" aeskey: %s\n", RSTRING(yubikey_get_key(self))->ptr); + + { + size_t i; + printf (" "); + for (i = 0; i < YUBIKEY_KEY_SIZE; i++) + printf ("%02x ", data->key[i] & 0xFF); + printf ("\n"); + } +#endif + + /* Decrypt TOKEN using KEY and store output in OUT structure. Note + that there is no error checking whether the output data is valid or + not, use yubikey_check_* for that. */ + yubikey_parse ((uint8_t*)(RSTRING(str)->ptr+start), data->key, data->token); + +#ifndef NDEBUG + printf ("Output:\n"); + { + size_t i; + printf (" "); + for (i = 0; i < YUBIKEY_BLOCK_SIZE; i++) + printf ("%02x ", ((uint8_t*)data->token)[i] & 0xFF); + printf ("\n"); + } + + yubikey_token_st tok = *data->token; + printf ("\nStruct:\n"); + /* Debug */ + { + size_t i; + printf (" uid: "); + for (i = 0; i < YUBIKEY_UID_SIZE; i++) + printf ("%02x ", data->token->uid[i] & 0xFF); + printf ("\n"); + } + printf (" counter: %d (0x%04x)\n", tok.ctr, tok.ctr); + printf (" timestamp (low): %d (0x%04x)\n", tok.tstpl, tok.tstpl); + printf (" timestamp (high): %d (0x%02x)\n", tok.tstph, tok.tstph); + printf (" session use: %d (0x%02x)\n", tok.use, tok.use); + printf (" random: %d (0x%02x)\n", tok.rnd, tok.rnd); + printf (" crc: %d (0x%04x)\n", tok.crc, tok.crc); + + printf ("\nDerived:\n"); + printf (" cleaned counter: %d (0x%04x)\n", + yubikey_counter (tok.ctr), yubikey_counter (tok.ctr)); + yubikey_modhex_encode ((char*)buff, (char*)tok.uid, YUBIKEY_UID_SIZE); + printf (" modhex uid: %s\n", buff); + printf (" triggered by caps lock: %s\n", + yubikey_capslock(tok.ctr) ? "yes" : "no"); + printf (" crc: %04X\n", yubikey_crc16 ((void*)&tok, YUBIKEY_KEY_SIZE)); + + printf (" crc check: "); + if (yubikey_crc_ok_p ((uint8_t*)&tok)) + printf("ok\n"); + else + printf ("fail\n"); +#endif + if (yubikey_crc_ok_p ((uint8_t*)data->token)) + return Qtrue; + else + return Qfalse; +} + +/* call-seq: + * yubikey.to_str -> String + * + * Gets the decoded token as hex string representation. + */ +static VALUE yubikey_to_str(VALUE self) +{ + size_t i; + yubikey_data *data; + Data_Get_Struct(self, yubikey_data, data); + + VALUE ary = rb_ary_new2(YUBIKEY_BLOCK_SIZE); + for (i = 0; i < YUBIKEY_BLOCK_SIZE; i++) { + VALUE num = INT2FIX(((uint8_t*)data->token)[i]); + //invoke .to_s 16 on each number + rb_ary_store(ary, i, rb_funcall(num, rb_intern("to_s"), 1, INT2FIX(16) )); + } + + return rb_funcall(ary, rb_intern("join"), 0); +} + +/* call-seq: + * yubikey.uid -> "hex string" + * + * Gets the decoded token UID field as hex string representation. + */ +static VALUE yubikey_get_uid(VALUE self) +{ + VALUE out = yubikey_to_str(self); + + // *2 becaouse of hex + return rb_str_new(RSTRING(out)->ptr, YUBIKEY_UID_SIZE*2 ); +} + +/* call-seq: + * yubikey.counter -> Fixnum + * + * Gets the decoded token counter field. + */ +static VALUE yubikey_get_counter(VALUE self) +{ + yubikey_data *data; + Data_Get_Struct(self, yubikey_data, data); + + return INT2FIX(yubikey_counter(data->token->ctr)); +} + +/* call-seq: + * yubikey.triggered_by_capslock? -> true or false + * + */ +static VALUE yubikey_get_triggered_by_capslock(VALUE self) +{ + yubikey_data *data; + Data_Get_Struct(self, yubikey_data, data); + + if (yubikey_capslock(data->token->ctr)) + return Qtrue; + else + return Qfalse; +} + +static VALUE yubikey_get_tsl(VALUE self) +{ + yubikey_data *data; + Data_Get_Struct(self, yubikey_data, data); + + return INT2FIX(data->token->tstpl); +} + +static VALUE yubikey_get_tsh(VALUE self) +{ + yubikey_data *data; + Data_Get_Struct(self, yubikey_data, data); + + return INT2FIX(data->token->tstph); +} + +static VALUE yubikey_get_session(VALUE self) +{ + yubikey_data *data; + Data_Get_Struct(self, yubikey_data, data); + + return INT2FIX(data->token->use); +} + +static VALUE yubikey_get_random(VALUE self) +{ + yubikey_data *data; + Data_Get_Struct(self, yubikey_data, data); + + return INT2FIX(data->token->rnd); +} + +static VALUE yubikey_get_crc(VALUE self) +{ + yubikey_data *data; + Data_Get_Struct(self, yubikey_data, data); + + return INT2FIX(data->token->crc); +} + +static VALUE yubikey_calc_crc(VALUE self) +{ + yubikey_data *data; + Data_Get_Struct(self, yubikey_data, data); + + return INT2FIX(yubikey_crc16 ((void*)data->token, YUBIKEY_KEY_SIZE)); +} + +static VALUE yubikey_check_crc(VALUE self) +{ + yubikey_data *data; + Data_Get_Struct(self, yubikey_data, data); + + if (yubikey_crc_ok_p ((uint8_t*)data->token)) + return Qtrue; + else + return Qfalse; +} +/* Yubikey END */ + +/* Implementation of Yubikey OTP functions. + * This Module may be used to interact with a Yubikey + */ +void Init_libyubikey() { + mYubiRuby = rb_define_module("YubiRuby"); + + /* ModHex string encoder/decoder + * + * The YubiKey uses a special data encoding format known as "modhex" rather + * than normal hex encoding or base64 encoding. + * Modhex is similar to hex encoding but with a different encoding alphabet. + * The reason is to achieve a keyboard layout independent encoding. + * + * The String class in extended with this module. + */ + mModHex = rb_define_module_under(mYubiRuby, "ModHex"); + rb_define_singleton_method(mModHex, "encode", modhex_sing_encode, 1); + rb_define_method(mModHex, "modhex_encode", modhex_encode, 0); + rb_define_singleton_method(mModHex, "decode", modhex_sing_decode, 1); + rb_define_method(mModHex, "modhex_decode", modhex_decode, 0); + rb_define_singleton_method(mModHex, "modhex?", modhex_sing_is_modhex, 1); + rb_define_method(mModHex, "modhex?", modhex_is_modhex, 0); + /* lists of allowed char in MODHEX enconding */ + rb_define_const(mModHex, "MODHEX_MAP", rb_str_new2(YUBIKEY_MODHEX_MAP)); + + //extends String with ModHex + rb_include_module(rb_cString, mModHex); + + /* Prototypes for low-level Yubikey OTP functions. + * + */ + cYubikey = rb_define_class_under(mYubiRuby, "Yubikey", rb_cObject); + rb_define_alloc_func(cYubikey, yubikey_alloc); + rb_define_method(cYubikey, "initialize", yubikey_initialize, 1); + rb_define_method(cYubikey, "initialize_copy", yubikey_init_copy, 1); + /* CRC value for a valid token */ + rb_define_const(cYubikey, "CRC_OK_RESIDUE", INT2FIX(YUBIKEY_CRC_OK_RESIDUE)); + rb_define_method(cYubikey, "key", yubikey_get_key, 0); + rb_define_method(cYubikey, "key=", yubikey_set_key, 1); + rb_define_method(cYubikey, "parse", yubikey_check, 1); + rb_define_method(cYubikey, "to_str", yubikey_to_str, 0); + rb_define_alias(cYubikey, "to_s", "to_str"); + rb_define_method(cYubikey, "uid", yubikey_get_uid, 0); + rb_define_method(cYubikey, "counter", yubikey_get_counter, 0); + rb_define_method(cYubikey, "triggered_by_capslock?", yubikey_get_triggered_by_capslock, 0); + rb_define_method(cYubikey, "timestamp_low", yubikey_get_tsl, 0); + rb_define_method(cYubikey, "timestamp_high", yubikey_get_tsh, 0); + rb_define_method(cYubikey, "session", yubikey_get_session, 0); + rb_define_method(cYubikey, "random", yubikey_get_random, 0); + rb_define_method(cYubikey, "crc", yubikey_get_crc, 0); + rb_define_method(cYubikey, "crc_residue", yubikey_calc_crc, 0); + rb_define_method(cYubikey, "crc?", yubikey_check_crc, 0); +} \ No newline at end of file diff -r 06159c254c19f16abc3a0095047c6f064291ff45 -r 213b7c4cf03a2a160878d17fbfcfd1d1111e1185 ext/libyubikey/ykaes.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ext/libyubikey/ykaes.c Wed Feb 03 22:55:43 2010 +0100 @@ -0,0 +1,214 @@ +/* ykaes.c --- Implementation of AES-128. + * + * Copyright (c) 2006, 2007, 2008, 2009 Yubico AB + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "yubikey.h" + +#define NUMBER_OF_ROUNDS 10 + +static const uint8_t RC[] = + { 0x1, 0x2, 0x4, 0x8, 0x10, 0x20, 0x40, 0x80, 0x1B, 0x36 }; + +static const uint8_t rijndael_sbox[] = { + 0x63, 0x7C, 0x77, 0x7B, 0xF2, 0x6B, 0x6F, 0xC5, + 0x30, 0x01, 0x67, 0x2B, 0xFE, 0xD7, 0xAB, 0x76, + 0xCA, 0x82, 0xC9, 0x7D, 0xFA, 0x59, 0x47, 0xF0, + 0xAD, 0xD4, 0xA2, 0xAF, 0x9C, 0xA4, 0x72, 0xC0, + 0xB7, 0xFD, 0x93, 0x26, 0x36, 0x3F, 0xF7, 0xCC, + 0x34, 0xA5, 0xE5, 0xF1, 0x71, 0xD8, 0x31, 0x15, + 0x04, 0xC7, 0x23, 0xC3, 0x18, 0x96, 0x05, 0x9A, + 0x07, 0x12, 0x80, 0xE2, 0xEB, 0x27, 0xB2, 0x75, + 0x09, 0x83, 0x2C, 0x1A, 0x1B, 0x6E, 0x5A, 0xA0, + 0x52, 0x3B, 0xD6, 0xB3, 0x29, 0xE3, 0x2F, 0x84, + 0x53, 0xD1, 0x00, 0xED, 0x20, 0xFC, 0xB1, 0x5B, + 0x6A, 0xCB, 0xBE, 0x39, 0x4A, 0x4C, 0x58, 0xCF, + 0xD0, 0xEF, 0xAA, 0xFB, 0x43, 0x4D, 0x33, 0x85, + 0x45, 0xF9, 0x02, 0x7F, 0x50, 0x3C, 0x9F, 0xA8, + 0x51, 0xA3, 0x40, 0x8F, 0x92, 0x9D, 0x38, 0xF5, + 0xBC, 0xB6, 0xDA, 0x21, 0x10, 0xFF, 0xF3, 0xD2, + 0xCD, 0x0C, 0x13, 0xEC, 0x5F, 0x97, 0x44, 0x17, + 0xC4, 0xA7, 0x7E, 0x3D, 0x64, 0x5D, 0x19, 0x73, + 0x60, 0x81, 0x4F, 0xDC, 0x22, 0x2A, 0x90, 0x88, + 0x46, 0xEE, 0xB8, 0x14, 0xDE, 0x5E, 0x0B, 0xDB, + 0xE0, 0x32, 0x3A, 0x0A, 0x49, 0x06, 0x24, 0x5C, + 0xC2, 0xD3, 0xAC, 0x62, 0x91, 0x95, 0xE4, 0x79, + 0xE7, 0xC8, 0x37, 0x6D, 0x8D, 0xD5, 0x4E, 0xA9, + 0x6C, 0x56, 0xF4, 0xEA, 0x65, 0x7A, 0xAE, 0x08, + 0xBA, 0x78, 0x25, 0x2E, 0x1C, 0xA6, 0xB4, 0xC6, + 0xE8, 0xDD, 0x74, 0x1F, 0x4B, 0xBD, 0x8B, 0x8A, + 0x70, 0x3E, 0xB5, 0x66, 0x48, 0x03, 0xF6, 0x0E, + 0x61, 0x35, 0x57, 0xB9, 0x86, 0xC1, 0x1D, 0x9E, + 0xE1, 0xF8, 0x98, 0x11, 0x69, 0xD9, 0x8E, 0x94, + 0x9B, 0x1E, 0x87, 0xE9, 0xCE, 0x55, 0x28, 0xDF, + 0x8C, 0xA1, 0x89, 0x0D, 0xBF, 0xE6, 0x42, 0x68, + 0x41, 0x99, 0x2D, 0x0F, 0xB0, 0x54, 0xBB, 0x16 +}; + +static const uint8_t rijndael_inv_sbox[] = { + 0x52, 0x09, 0x6A, 0xD5, 0x30, 0x36, 0xA5, 0x38, + 0xBF, 0x40, 0xA3, 0x9E, 0x81, 0xF3, 0xD7, 0xFB, + 0x7C, 0xE3, 0x39, 0x82, 0x9B, 0x2F, 0xFF, 0x87, + 0x34, 0x8E, 0x43, 0x44, 0xC4, 0xDE, 0xE9, 0xCB, + 0x54, 0x7B, 0x94, 0x32, 0xA6, 0xC2, 0x23, 0x3D, + 0xEE, 0x4C, 0x95, 0x0B, 0x42, 0xFA, 0xC3, 0x4E, + 0x08, 0x2E, 0xA1, 0x66, 0x28, 0xD9, 0x24, 0xB2, + 0x76, 0x5B, 0xA2, 0x49, 0x6D, 0x8B, 0xD1, 0x25, + 0x72, 0xF8, 0xF6, 0x64, 0x86, 0x68, 0x98, 0x16, + 0xD4, 0xA4, 0x5C, 0xCC, 0x5D, 0x65, 0xB6, 0x92, + 0x6C, 0x70, 0x48, 0x50, 0xFD, 0xED, 0xB9, 0xDA, + 0x5E, 0x15, 0x46, 0x57, 0xA7, 0x8D, 0x9D, 0x84, + 0x90, 0xD8, 0xAB, 0x00, 0x8C, 0xBC, 0xD3, 0x0A, + 0xF7, 0xE4, 0x58, 0x05, 0xB8, 0xB3, 0x45, 0x06, + 0xD0, 0x2C, 0x1E, 0x8F, 0xCA, 0x3F, 0x0F, 0x02, + 0xC1, 0xAF, 0xBD, 0x03, 0x01, 0x13, 0x8A, 0x6B, + 0x3A, 0x91, 0x11, 0x41, 0x4F, 0x67, 0xDC, 0xEA, + 0x97, 0xF2, 0xCF, 0xCE, 0xF0, 0xB4, 0xE6, 0x73, + 0x96, 0xAC, 0x74, 0x22, 0xE7, 0xAD, 0x35, 0x85, + 0xE2, 0xF9, 0x37, 0xE8, 0x1C, 0x75, 0xDF, 0x6E, + 0x47, 0xF1, 0x1A, 0x71, 0x1D, 0x29, 0xC5, 0x89, + 0x6F, 0xB7, 0x62, 0x0E, 0xAA, 0x18, 0xBE, 0x1B, + 0xFC, 0x56, 0x3E, 0x4B, 0xC6, 0xD2, 0x79, 0x20, + 0x9A, 0xDB, 0xC0, 0xFE, 0x78, 0xCD, 0x5A, 0xF4, + 0x1F, 0xDD, 0xA8, 0x33, 0x88, 0x07, 0xC7, 0x31, + 0xB1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xEC, 0x5F, + 0x60, 0x51, 0x7F, 0xA9, 0x19, 0xB5, 0x4A, 0x0D, + 0x2D, 0xE5, 0x7A, 0x9F, 0x93, 0xC9, 0x9C, 0xEF, + 0xA0, 0xE0, 0x3B, 0x4D, 0xAE, 0x2A, 0xF5, 0xB0, + 0xC8, 0xEB, 0xBB, 0x3C, 0x83, 0x53, 0x99, 0x61, + 0x17, 0x2B, 0x04, 0x7E, 0xBA, 0x77, 0xD6, 0x26, + 0xE1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0C, 0x7D +}; + +static inline uint8_t +xtime (uint8_t b) +{ + return (b & 0x80) ? ((b << 1) ^ 0x1b) : (b << 1); +} + +void +yubikey_aes_decrypt (uint8_t * state, const uint8_t * key) +{ + uint8_t i, j, round_key[0x10]; + uint8_t a02x, a13x; + uint8_t a02xx, a13xx; + uint8_t k1, k2; + + memcpy (round_key, key, sizeof (round_key)); + for (i = 0; i < NUMBER_OF_ROUNDS; i++) + { + round_key[0] ^= RC[i]; + + round_key[0] ^= rijndael_sbox[round_key[13]]; + round_key[1] ^= rijndael_sbox[round_key[14]]; + round_key[2] ^= rijndael_sbox[round_key[15]]; + round_key[3] ^= rijndael_sbox[round_key[12]]; + + for (j = 4; j < 16; j++) + round_key[j] ^= round_key[j - 4]; + } + for (i = 0; i < 0x10; i++) + state[i] ^= round_key[i]; + + for (i = 1; i <= NUMBER_OF_ROUNDS; i++) + { + // inv_byte_sub_shift_row(); + + /* First row: 0 shift, 0 4 8 12 */ + state[0] = rijndael_inv_sbox[state[0]]; + state[4] = rijndael_inv_sbox[state[4]]; + state[8] = rijndael_inv_sbox[state[8]]; + state[12] = rijndael_inv_sbox[state[12]]; + + /* Second row: -1 shift, 1 5 9 13 */ + j = state[13]; + state[13] = rijndael_inv_sbox[state[9]]; + state[9] = rijndael_inv_sbox[state[5]]; + state[5] = rijndael_inv_sbox[state[1]]; + state[1] = rijndael_inv_sbox[j]; + + /* Third row: -2 shift, 2 6 10 14 */ + j = state[2]; + state[2] = rijndael_inv_sbox[state[10]]; + state[10] = rijndael_inv_sbox[j]; + j = state[6]; + state[6] = rijndael_inv_sbox[state[14]]; + state[14] = rijndael_inv_sbox[j]; + + /* Fourth row: -3 shift, 3 7 11 15 */ + j = state[3]; + state[3] = rijndael_inv_sbox[state[7]]; + state[7] = rijndael_inv_sbox[state[11]]; + state[11] = rijndael_inv_sbox[state[15]]; + state[15] = rijndael_inv_sbox[j]; + +// get_inv_round_key(i); + + for (j = 15; j > 3; j--) + round_key[j] ^= round_key[j - 4]; + + round_key[0] ^= + (RC[NUMBER_OF_ROUNDS - i] ^ rijndael_sbox[round_key[13]]); + + round_key[1] ^= rijndael_sbox[round_key[14]]; + round_key[2] ^= rijndael_sbox[round_key[15]]; + round_key[3] ^= rijndael_sbox[round_key[12]]; + + for (j = 0; j < 16; j++) + state[j] ^= round_key[j]; + if (i != NUMBER_OF_ROUNDS) + { + + //inv_mix_column(); + + for (j = 0; j < 16; j += 4) + { + k1 = state[j] ^ state[j + 2]; + a02x = xtime (k1); + k2 = state[j + 1] ^ state[j + 3]; + a13x = xtime (k2); + + k1 ^= (k2 ^ xtime (state[j + 1] ^ state[j + 2])); + k2 = k1; + + a02xx = xtime (a02x); + a13xx = xtime (a13x); + + k1 ^= (xtime (a02xx ^ a13xx) ^ a02xx); + k2 ^= (xtime (a02xx ^ a13xx) ^ a13xx); + + state[j] ^= (k1 ^ a02x); + state[j + 1] ^= k2; + state[j + 2] ^= (k1 ^ a13x); + state[j + 3] ^= (k2 ^ a02x ^ a13x); + } + } + + } +} diff -r 06159c254c19f16abc3a0095047c6f064291ff45 -r 213b7c4cf03a2a160878d17fbfcfd1d1111e1185 ext/libyubikey/ykcrc.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ext/libyubikey/ykcrc.c Wed Feb 03 22:55:43 2010 +0100 @@ -0,0 +1,54 @@ +/* ykcrc.c --- Implementation of Yubikey CRC-16 function. + * + * Written by Simon Josefsson . + * Copyright (c) 2006, 2007, 2008, 2009 Yubico AB + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "yubikey.h" + +uint16_t +yubikey_crc16 (const uint8_t *buf, size_t buf_size) +{ + uint16_t m_crc = 0xffff; + + while (buf_size--) + { + int i, j; + m_crc ^= (uint8_t) * buf++ & 0xFF; + for (i = 0; i < 8; i++) + { + j = m_crc & 1; + m_crc >>= 1; + if (j) + m_crc ^= 0x8408; + } + } + + return m_crc; +} diff -r 06159c254c19f16abc3a0095047c6f064291ff45 -r 213b7c4cf03a2a160878d17fbfcfd1d1111e1185 ext/libyubikey/ykhex.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ext/libyubikey/ykhex.c Wed Feb 03 22:55:43 2010 +0100 @@ -0,0 +1,86 @@ +/* ykhex.c --- Implementation of hex encoding/decoding + * + * Written by Simon Josefsson . + * Copyright (c) 2006, 2007, 2008, 2009 Yubico AB + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "yubikey.h" + +#include + +static const char trans[] = "0123456789abcdef"; + +void +yubikey_hex_encode (char *dst, const char *src, size_t srcSize) +{ + while (srcSize--) + { + *dst++ = trans[(*src >> 4) & 0xf]; + *dst++ = trans[*src++ & 0xf]; + } + + *dst = '\0'; +} + +void +yubikey_hex_decode (char *dst, const char *src, size_t dstSize) +{ + char b; + bool flag = false; + char *p1; + + for (; *src && dstSize > 0; src++) + { + if ((p1 = strchr (trans, *src)) == NULL) + b = 0; + else + b = (char) (p1 - trans); + + if ((flag = !flag)) + *dst = b; + else + { + *dst = (*dst << 4) | b; + dst++; + dstSize--; + } + } + while (dstSize--) + *dst++ = 0; +} + +int +yubikey_hex_p (const char *str) +{ + for (; *str; str++) + if (strchr (trans, *str) == NULL) + return 0; + + return 1; +} diff -r 06159c254c19f16abc3a0095047c6f064291ff45 -r 213b7c4cf03a2a160878d17fbfcfd1d1111e1185 ext/libyubikey/ykmodhex.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ext/libyubikey/ykmodhex.c Wed Feb 03 22:55:43 2010 +0100 @@ -0,0 +1,86 @@ +/* ykmodhex.c --- Implementation of modhex encoding/decoding + * + * Written by Simon Josefsson . + * Copyright (c) 2006, 2007, 2008, 2009 Yubico AB + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "yubikey.h" + +#include + +static const char trans[] = YUBIKEY_MODHEX_MAP; + +void +yubikey_modhex_encode (char *dst, const char *src, size_t srcSize) +{ + while (srcSize--) + { + *dst++ = trans[(*src >> 4) & 0xf]; + *dst++ = trans[*src++ & 0xf]; + } + + *dst = '\0'; +} + +void +yubikey_modhex_decode (char *dst, const char *src, size_t dstSize) +{ + char b; + bool flag = false; + char *p1; + + for (; *src && dstSize > 0; src++) + { + if ((p1 = strchr (trans, *src)) == NULL) + b = 0; + else + b = (char) (p1 - trans); + + if ((flag = !flag)) + *dst = b; + else + { + *dst = (*dst << 4) | b; + dst++; + dstSize--; + } + } + while (dstSize--) + *dst++ = 0; +} + +int +yubikey_modhex_p (const char *str) +{ + for (; *str; str++) + if (strchr (trans, *str) == NULL) + return 0; + + return 1; +} diff -r 06159c254c19f16abc3a0095047c6f064291ff45 -r 213b7c4cf03a2a160878d17fbfcfd1d1111e1185 ext/libyubikey/ykparse.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ext/libyubikey/ykparse.c Wed Feb 03 22:55:43 2010 +0100 @@ -0,0 +1,45 @@ +/* ykparse.c --- Implementation of Yubikey token parser. + * + * Written by Simon Josefsson . + * Copyright (c) 2006, 2007, 2008, 2009 Yubico AB + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "yubikey.h" + +#include +#include + +void +yubikey_parse (const uint8_t token[32], + const uint8_t key[16], yubikey_token_t out) +{ + memset (out, 0, sizeof (*out)); + yubikey_modhex_decode ((void *) out, (char *) token, sizeof (*out)); + yubikey_aes_decrypt ((void *) out, key); +} diff -r 06159c254c19f16abc3a0095047c6f064291ff45 -r 213b7c4cf03a2a160878d17fbfcfd1d1111e1185 ext/libyubikey/yubikey.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ext/libyubikey/yubikey.h Wed Feb 03 22:55:43 2010 +0100 @@ -0,0 +1,121 @@ +/* yubikey.h --- Prototypes for low-level Yubikey OTP functions. + * + * Written by Simon Josefsson . + * Copyright (c) 2006, 2007, 2008, 2009 Yubico AB + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef YUBIKEY_H +# define YUBIKEY_H + +# include +# include + +# define YUBIKEY_BLOCK_SIZE 16 +# define YUBIKEY_KEY_SIZE 16 +# define YUBIKEY_UID_SIZE 6 + +typedef struct +{ + /* Unique (secret) ID. */ + uint8_t uid[YUBIKEY_UID_SIZE]; + /* Session counter (incremented by 1 at each startup). High bit + indicates whether caps-lock triggered the token. */ + uint16_t ctr; + /* Timestamp incremented by approx 8Hz (low part). */ + uint16_t tstpl; + /* Timestamp (high part). */ + uint8_t tstph; + /* Number of times used within session + activation flags. */ + uint8_t use; + /* Pseudo-random value. */ + uint16_t rnd; + /* CRC16 value of all fields. */ + uint16_t crc; +} yubikey_token_st; + +typedef yubikey_token_st *yubikey_token_t; + +/* High-level functions. */ + +/* Decrypt TOKEN using KEY and store output in OUT structure. Note + that there is no error checking whether the output data is valid or + not, use yubikey_check_* for that. */ +extern void yubikey_parse (const uint8_t token[YUBIKEY_BLOCK_SIZE], + const uint8_t key[YUBIKEY_KEY_SIZE], + yubikey_token_t out); + +# define yubikey_counter(ctr) ((ctr) & 0x7FFF) +# define yubikey_capslock(ctr) ((ctr) & 0x8000) +# define yubikey_crc_ok_p(tok) \ + (yubikey_crc16 ((tok), YUBIKEY_BLOCK_SIZE) == YUBIKEY_CRC_OK_RESIDUE) + +/* + * Low-level functions; ModHex. + */ + +# define YUBIKEY_MODHEX_MAP "cbdefghijklnrtuv" + +/* ModHex encode input string SRC of length SRCSIZE and put the zero + terminated output string in DST. The size of the output string DST + must be at least 2*SRCSIZE+1. The output string is always + 2*SRCSIZE large plus the terminating zero. */ +extern void yubikey_modhex_encode (char *dst, + const char *src, + size_t srcsize); + +/* ModHex decode input string SRC of length DSTSIZE/2 into output + string DST. The output string DST is always DSTSIZE/2 large plus + the terminating zero. */ +extern void yubikey_modhex_decode (char *dst, + const char *src, + size_t dstsize); + +/* Hex encode/decode data, same interface as modhex functions. */ +extern void yubikey_hex_encode (char *dst, const char *src, size_t srcsize); +extern void yubikey_hex_decode (char *dst, const char *src, size_t dstsize); + +/* Return non-zero if zero-terminated input STR is a valid (mod)hex + string, and zero if any non-alphabetic characters are found. */ +extern int yubikey_modhex_p (const char *str); +extern int yubikey_hex_p (const char *str); + +/* + * Low-level functions; CRC. + */ + +# define YUBIKEY_CRC_OK_RESIDUE 0xf0b8 +extern uint16_t yubikey_crc16 (const uint8_t * buf, size_t buf_size); + +/* Low-level functions; AES. */ + +/* AES-decrypt one 16-byte block STATE using the 128-bit KEY, leaving + the decrypted output in the STATE buffer. */ +extern void yubikey_aes_decrypt (uint8_t * state, const uint8_t * key); + +#endif diff -r 06159c254c19f16abc3a0095047c6f064291ff45 -r 213b7c4cf03a2a160878d17fbfcfd1d1111e1185 ext/ykaes.c --- a/ext/ykaes.c Tue Feb 02 19:54:28 2010 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,214 +0,0 @@ -/* ykaes.c --- Implementation of AES-128. - * - * Copyright (c) 2006, 2007, 2008, 2009 Yubico AB - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials provided - * with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#include "yubikey.h" - -#define NUMBER_OF_ROUNDS 10 - -static const uint8_t RC[] = - { 0x1, 0x2, 0x4, 0x8, 0x10, 0x20, 0x40, 0x80, 0x1B, 0x36 }; - -static const uint8_t rijndael_sbox[] = { - 0x63, 0x7C, 0x77, 0x7B, 0xF2, 0x6B, 0x6F, 0xC5, - 0x30, 0x01, 0x67, 0x2B, 0xFE, 0xD7, 0xAB, 0x76, - 0xCA, 0x82, 0xC9, 0x7D, 0xFA, 0x59, 0x47, 0xF0, - 0xAD, 0xD4, 0xA2, 0xAF, 0x9C, 0xA4, 0x72, 0xC0, - 0xB7, 0xFD, 0x93, 0x26, 0x36, 0x3F, 0xF7, 0xCC, - 0x34, 0xA5, 0xE5, 0xF1, 0x71, 0xD8, 0x31, 0x15, - 0x04, 0xC7, 0x23, 0xC3, 0x18, 0x96, 0x05, 0x9A, - 0x07, 0x12, 0x80, 0xE2, 0xEB, 0x27, 0xB2, 0x75, - 0x09, 0x83, 0x2C, 0x1A, 0x1B, 0x6E, 0x5A, 0xA0, - 0x52, 0x3B, 0xD6, 0xB3, 0x29, 0xE3, 0x2F, 0x84, - 0x53, 0xD1, 0x00, 0xED, 0x20, 0xFC, 0xB1, 0x5B, - 0x6A, 0xCB, 0xBE, 0x39, 0x4A, 0x4C, 0x58, 0xCF, - 0xD0, 0xEF, 0xAA, 0xFB, 0x43, 0x4D, 0x33, 0x85, - 0x45, 0xF9, 0x02, 0x7F, 0x50, 0x3C, 0x9F, 0xA8, - 0x51, 0xA3, 0x40, 0x8F, 0x92, 0x9D, 0x38, 0xF5, - 0xBC, 0xB6, 0xDA, 0x21, 0x10, 0xFF, 0xF3, 0xD2, - 0xCD, 0x0C, 0x13, 0xEC, 0x5F, 0x97, 0x44, 0x17, - 0xC4, 0xA7, 0x7E, 0x3D, 0x64, 0x5D, 0x19, 0x73, - 0x60, 0x81, 0x4F, 0xDC, 0x22, 0x2A, 0x90, 0x88, - 0x46, 0xEE, 0xB8, 0x14, 0xDE, 0x5E, 0x0B, 0xDB, - 0xE0, 0x32, 0x3A, 0x0A, 0x49, 0x06, 0x24, 0x5C, - 0xC2, 0xD3, 0xAC, 0x62, 0x91, 0x95, 0xE4, 0x79, - 0xE7, 0xC8, 0x37, 0x6D, 0x8D, 0xD5, 0x4E, 0xA9, - 0x6C, 0x56, 0xF4, 0xEA, 0x65, 0x7A, 0xAE, 0x08, - 0xBA, 0x78, 0x25, 0x2E, 0x1C, 0xA6, 0xB4, 0xC6, - 0xE8, 0xDD, 0x74, 0x1F, 0x4B, 0xBD, 0x8B, 0x8A, - 0x70, 0x3E, 0xB5, 0x66, 0x48, 0x03, 0xF6, 0x0E, - 0x61, 0x35, 0x57, 0xB9, 0x86, 0xC1, 0x1D, 0x9E, - 0xE1, 0xF8, 0x98, 0x11, 0x69, 0xD9, 0x8E, 0x94, - 0x9B, 0x1E, 0x87, 0xE9, 0xCE, 0x55, 0x28, 0xDF, - 0x8C, 0xA1, 0x89, 0x0D, 0xBF, 0xE6, 0x42, 0x68, - 0x41, 0x99, 0x2D, 0x0F, 0xB0, 0x54, 0xBB, 0x16 -}; - -static const uint8_t rijndael_inv_sbox[] = { - 0x52, 0x09, 0x6A, 0xD5, 0x30, 0x36, 0xA5, 0x38, - 0xBF, 0x40, 0xA3, 0x9E, 0x81, 0xF3, 0xD7, 0xFB, - 0x7C, 0xE3, 0x39, 0x82, 0x9B, 0x2F, 0xFF, 0x87, - 0x34, 0x8E, 0x43, 0x44, 0xC4, 0xDE, 0xE9, 0xCB, - 0x54, 0x7B, 0x94, 0x32, 0xA6, 0xC2, 0x23, 0x3D, - 0xEE, 0x4C, 0x95, 0x0B, 0x42, 0xFA, 0xC3, 0x4E, - 0x08, 0x2E, 0xA1, 0x66, 0x28, 0xD9, 0x24, 0xB2, - 0x76, 0x5B, 0xA2, 0x49, 0x6D, 0x8B, 0xD1, 0x25, - 0x72, 0xF8, 0xF6, 0x64, 0x86, 0x68, 0x98, 0x16, - 0xD4, 0xA4, 0x5C, 0xCC, 0x5D, 0x65, 0xB6, 0x92, - 0x6C, 0x70, 0x48, 0x50, 0xFD, 0xED, 0xB9, 0xDA, - 0x5E, 0x15, 0x46, 0x57, 0xA7, 0x8D, 0x9D, 0x84, - 0x90, 0xD8, 0xAB, 0x00, 0x8C, 0xBC, 0xD3, 0x0A, - 0xF7, 0xE4, 0x58, 0x05, 0xB8, 0xB3, 0x45, 0x06, - 0xD0, 0x2C, 0x1E, 0x8F, 0xCA, 0x3F, 0x0F, 0x02, - 0xC1, 0xAF, 0xBD, 0x03, 0x01, 0x13, 0x8A, 0x6B, - 0x3A, 0x91, 0x11, 0x41, 0x4F, 0x67, 0xDC, 0xEA, - 0x97, 0xF2, 0xCF, 0xCE, 0xF0, 0xB4, 0xE6, 0x73, - 0x96, 0xAC, 0x74, 0x22, 0xE7, 0xAD, 0x35, 0x85, - 0xE2, 0xF9, 0x37, 0xE8, 0x1C, 0x75, 0xDF, 0x6E, - 0x47, 0xF1, 0x1A, 0x71, 0x1D, 0x29, 0xC5, 0x89, - 0x6F, 0xB7, 0x62, 0x0E, 0xAA, 0x18, 0xBE, 0x1B, - 0xFC, 0x56, 0x3E, 0x4B, 0xC6, 0xD2, 0x79, 0x20, - 0x9A, 0xDB, 0xC0, 0xFE, 0x78, 0xCD, 0x5A, 0xF4, - 0x1F, 0xDD, 0xA8, 0x33, 0x88, 0x07, 0xC7, 0x31, - 0xB1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xEC, 0x5F, - 0x60, 0x51, 0x7F, 0xA9, 0x19, 0xB5, 0x4A, 0x0D, - 0x2D, 0xE5, 0x7A, 0x9F, 0x93, 0xC9, 0x9C, 0xEF, - 0xA0, 0xE0, 0x3B, 0x4D, 0xAE, 0x2A, 0xF5, 0xB0, - 0xC8, 0xEB, 0xBB, 0x3C, 0x83, 0x53, 0x99, 0x61, - 0x17, 0x2B, 0x04, 0x7E, 0xBA, 0x77, 0xD6, 0x26, - 0xE1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0C, 0x7D -}; - -static inline uint8_t -xtime (uint8_t b) -{ - return (b & 0x80) ? ((b << 1) ^ 0x1b) : (b << 1); -} - -void -yubikey_aes_decrypt (uint8_t * state, const uint8_t * key) -{ - uint8_t i, j, round_key[0x10]; - uint8_t a02x, a13x; - uint8_t a02xx, a13xx; - uint8_t k1, k2; - - memcpy (round_key, key, sizeof (round_key)); - for (i = 0; i < NUMBER_OF_ROUNDS; i++) - { - round_key[0] ^= RC[i]; - - round_key[0] ^= rijndael_sbox[round_key[13]]; - round_key[1] ^= rijndael_sbox[round_key[14]]; - round_key[2] ^= rijndael_sbox[round_key[15]]; - round_key[3] ^= rijndael_sbox[round_key[12]]; - - for (j = 4; j < 16; j++) - round_key[j] ^= round_key[j - 4]; - } - for (i = 0; i < 0x10; i++) - state[i] ^= round_key[i]; - - for (i = 1; i <= NUMBER_OF_ROUNDS; i++) - { - // inv_byte_sub_shift_row(); - - /* First row: 0 shift, 0 4 8 12 */ - state[0] = rijndael_inv_sbox[state[0]]; - state[4] = rijndael_inv_sbox[state[4]]; - state[8] = rijndael_inv_sbox[state[8]]; - state[12] = rijndael_inv_sbox[state[12]]; - - /* Second row: -1 shift, 1 5 9 13 */ - j = state[13]; - state[13] = rijndael_inv_sbox[state[9]]; - state[9] = rijndael_inv_sbox[state[5]]; - state[5] = rijndael_inv_sbox[state[1]]; - state[1] = rijndael_inv_sbox[j]; - - /* Third row: -2 shift, 2 6 10 14 */ - j = state[2]; - state[2] = rijndael_inv_sbox[state[10]]; - state[10] = rijndael_inv_sbox[j]; - j = state[6]; - state[6] = rijndael_inv_sbox[state[14]]; - state[14] = rijndael_inv_sbox[j]; - - /* Fourth row: -3 shift, 3 7 11 15 */ - j = state[3]; - state[3] = rijndael_inv_sbox[state[7]]; - state[7] = rijndael_inv_sbox[state[11]]; - state[11] = rijndael_inv_sbox[state[15]]; - state[15] = rijndael_inv_sbox[j]; - -// get_inv_round_key(i); - - for (j = 15; j > 3; j--) - round_key[j] ^= round_key[j - 4]; - - round_key[0] ^= - (RC[NUMBER_OF_ROUNDS - i] ^ rijndael_sbox[round_key[13]]); - - round_key[1] ^= rijndael_sbox[round_key[14]]; - round_key[2] ^= rijndael_sbox[round_key[15]]; - round_key[3] ^= rijndael_sbox[round_key[12]]; - - for (j = 0; j < 16; j++) - state[j] ^= round_key[j]; - if (i != NUMBER_OF_ROUNDS) - { - - //inv_mix_column(); - - for (j = 0; j < 16; j += 4) - { - k1 = state[j] ^ state[j + 2]; - a02x = xtime (k1); - k2 = state[j + 1] ^ state[j + 3]; - a13x = xtime (k2); - - k1 ^= (k2 ^ xtime (state[j + 1] ^ state[j + 2])); - k2 = k1; - - a02xx = xtime (a02x); - a13xx = xtime (a13x); - - k1 ^= (xtime (a02xx ^ a13xx) ^ a02xx); - k2 ^= (xtime (a02xx ^ a13xx) ^ a13xx); - - state[j] ^= (k1 ^ a02x); - state[j + 1] ^= k2; - state[j + 2] ^= (k1 ^ a13x); - state[j + 3] ^= (k2 ^ a02x ^ a13x); - } - } - - } -} diff -r 06159c254c19f16abc3a0095047c6f064291ff45 -r 213b7c4cf03a2a160878d17fbfcfd1d1111e1185 ext/ykcrc.c --- a/ext/ykcrc.c Tue Feb 02 19:54:28 2010 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,54 +0,0 @@ -/* ykcrc.c --- Implementation of Yubikey CRC-16 function. - * - * Written by Simon Josefsson . - * Copyright (c) 2006, 2007, 2008, 2009 Yubico AB - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials provided - * with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#include "yubikey.h" - -uint16_t -yubikey_crc16 (const uint8_t *buf, size_t buf_size) -{ - uint16_t m_crc = 0xffff; - - while (buf_size--) - { - int i, j; - m_crc ^= (uint8_t) * buf++ & 0xFF; - for (i = 0; i < 8; i++) - { - j = m_crc & 1; - m_crc >>= 1; - if (j) - m_crc ^= 0x8408; - } - } - - return m_crc; -} diff -r 06159c254c19f16abc3a0095047c6f064291ff45 -r 213b7c4cf03a2a160878d17fbfcfd1d1111e1185 ext/ykhex.c --- a/ext/ykhex.c Tue Feb 02 19:54:28 2010 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,86 +0,0 @@ -/* ykhex.c --- Implementation of hex encoding/decoding - * - * Written by Simon Josefsson . - * Copyright (c) 2006, 2007, 2008, 2009 Yubico AB - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials provided - * with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#include "yubikey.h" - -#include - -static const char trans[] = "0123456789abcdef"; - -void -yubikey_hex_encode (char *dst, const char *src, size_t srcSize) -{ - while (srcSize--) - { - *dst++ = trans[(*src >> 4) & 0xf]; - *dst++ = trans[*src++ & 0xf]; - } - - *dst = '\0'; -} - -void -yubikey_hex_decode (char *dst, const char *src, size_t dstSize) -{ - char b; - bool flag = false; - char *p1; - - for (; *src && dstSize > 0; src++) - { - if ((p1 = strchr (trans, *src)) == NULL) - b = 0; - else - b = (char) (p1 - trans); - - if ((flag = !flag)) - *dst = b; - else - { - *dst = (*dst << 4) | b; - dst++; - dstSize--; - } - } - while (dstSize--) - *dst++ = 0; -} - -int -yubikey_hex_p (const char *str) -{ - for (; *str; str++) - if (strchr (trans, *str) == NULL) - return 0; - - return 1; -} diff -r 06159c254c19f16abc3a0095047c6f064291ff45 -r 213b7c4cf03a2a160878d17fbfcfd1d1111e1185 ext/ykmodhex.c --- a/ext/ykmodhex.c Tue Feb 02 19:54:28 2010 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,86 +0,0 @@ -/* ykmodhex.c --- Implementation of modhex encoding/decoding - * - * Written by Simon Josefsson . - * Copyright (c) 2006, 2007, 2008, 2009 Yubico AB - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials provided - * with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#include "yubikey.h" - -#include - -static const char trans[] = YUBIKEY_MODHEX_MAP; - -void -yubikey_modhex_encode (char *dst, const char *src, size_t srcSize) -{ - while (srcSize--) - { - *dst++ = trans[(*src >> 4) & 0xf]; - *dst++ = trans[*src++ & 0xf]; - } - - *dst = '\0'; -} - -void -yubikey_modhex_decode (char *dst, const char *src, size_t dstSize) -{ - char b; - bool flag = false; - char *p1; - - for (; *src && dstSize > 0; src++) - { - if ((p1 = strchr (trans, *src)) == NULL) - b = 0; - else - b = (char) (p1 - trans); - - if ((flag = !flag)) - *dst = b; - else - { - *dst = (*dst << 4) | b; - dst++; - dstSize--; - } - } - while (dstSize--) - *dst++ = 0; -} - -int -yubikey_modhex_p (const char *str) -{ - for (; *str; str++) - if (strchr (trans, *str) == NULL) - return 0; - - return 1; -} diff -r 06159c254c19f16abc3a0095047c6f064291ff45 -r 213b7c4cf03a2a160878d17fbfcfd1d1111e1185 ext/ykparse.c --- a/ext/ykparse.c Tue Feb 02 19:54:28 2010 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,45 +0,0 @@ -/* ykparse.c --- Implementation of Yubikey token parser. - * - * Written by Simon Josefsson . - * Copyright (c) 2006, 2007, 2008, 2009 Yubico AB - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials provided - * with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#include "yubikey.h" - -#include -#include - -void -yubikey_parse (const uint8_t token[32], - const uint8_t key[16], yubikey_token_t out) -{ - memset (out, 0, sizeof (*out)); - yubikey_modhex_decode ((void *) out, (char *) token, sizeof (*out)); - yubikey_aes_decrypt ((void *) out, key); -} diff -r 06159c254c19f16abc3a0095047c6f064291ff45 -r 213b7c4cf03a2a160878d17fbfcfd1d1111e1185 ext/yubikey.h --- a/ext/yubikey.h Tue Feb 02 19:54:28 2010 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,121 +0,0 @@ -/* yubikey.h --- Prototypes for low-level Yubikey OTP functions. - * - * Written by Simon Josefsson . - * Copyright (c) 2006, 2007, 2008, 2009 Yubico AB - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following - * disclaimer in the documentation and/or other materials provided - * with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - */ - -#ifndef YUBIKEY_H -# define YUBIKEY_H - -# include -# include - -# define YUBIKEY_BLOCK_SIZE 16 -# define YUBIKEY_KEY_SIZE 16 -# define YUBIKEY_UID_SIZE 6 - -typedef struct -{ - /* Unique (secret) ID. */ - uint8_t uid[YUBIKEY_UID_SIZE]; - /* Session counter (incremented by 1 at each startup). High bit - indicates whether caps-lock triggered the token. */ - uint16_t ctr; - /* Timestamp incremented by approx 8Hz (low part). */ - uint16_t tstpl; - /* Timestamp (high part). */ - uint8_t tstph; - /* Number of times used within session + activation flags. */ - uint8_t use; - /* Pseudo-random value. */ - uint16_t rnd; - /* CRC16 value of all fields. */ - uint16_t crc; -} yubikey_token_st; - -typedef yubikey_token_st *yubikey_token_t; - -/* High-level functions. */ - -/* Decrypt TOKEN using KEY and store output in OUT structure. Note - that there is no error checking whether the output data is valid or - not, use yubikey_check_* for that. */ -extern void yubikey_parse (const uint8_t token[YUBIKEY_BLOCK_SIZE], - const uint8_t key[YUBIKEY_KEY_SIZE], - yubikey_token_t out); - -# define yubikey_counter(ctr) ((ctr) & 0x7FFF) -# define yubikey_capslock(ctr) ((ctr) & 0x8000) -# define yubikey_crc_ok_p(tok) \ - (yubikey_crc16 ((tok), YUBIKEY_BLOCK_SIZE) == YUBIKEY_CRC_OK_RESIDUE) - -/* - * Low-level functions; ModHex. - */ - -# define YUBIKEY_MODHEX_MAP "cbdefghijklnrtuv" - -/* ModHex encode input string SRC of length SRCSIZE and put the zero - terminated output string in DST. The size of the output string DST - must be at least 2*SRCSIZE+1. The output string is always - 2*SRCSIZE large plus the terminating zero. */ -extern void yubikey_modhex_encode (char *dst, - const char *src, - size_t srcsize); - -/* ModHex decode input string SRC of length DSTSIZE/2 into output - string DST. The output string DST is always DSTSIZE/2 large plus - the terminating zero. */ -extern void yubikey_modhex_decode (char *dst, - const char *src, - size_t dstsize); - -/* Hex encode/decode data, same interface as modhex functions. */ -extern void yubikey_hex_encode (char *dst, const char *src, size_t srcsize); -extern void yubikey_hex_decode (char *dst, const char *src, size_t dstsize); - -/* Return non-zero if zero-terminated input STR is a valid (mod)hex - string, and zero if any non-alphabetic characters are found. */ -extern int yubikey_modhex_p (const char *str); -extern int yubikey_hex_p (const char *str); - -/* - * Low-level functions; CRC. - */ - -# define YUBIKEY_CRC_OK_RESIDUE 0xf0b8 -extern uint16_t yubikey_crc16 (const uint8_t * buf, size_t buf_size); - -/* Low-level functions; AES. */ - -/* AES-decrypt one 16-byte block STATE using the 128-bit KEY, leaving - the decrypted output in the STATE buffer. */ -extern void yubikey_aes_decrypt (uint8_t * state, const uint8_t * key); - -#endif diff -r 06159c254c19f16abc3a0095047c6f064291ff45 -r 213b7c4cf03a2a160878d17fbfcfd1d1111e1185 yubiruby.gemspec --- a/yubiruby.gemspec Tue Feb 02 19:54:28 2010 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,51 +0,0 @@ -$spec = Gem::Specification.new do |s| - s.name = 'YubiRuby' - s.version = '0.0.1' - s.author = 'Alessio \"nolith\" Caiazza' - s.email = 'nolith@abisso.org' - s.homepage = 'http://bitbucket.org/nolith/yubiruby/' - s.platform = Gem::Platform::RUBY - s.summary = "Yubikey integration - Based on Prototypes for low-level Yubikey OTP functions witten " + - " by Simon Josefsson .\nCopyright (c) 2006, 2007, 2008, 2009 Yubico AB" - s.description = <<-EOF -Yubikey integration - - -Includes Prototypes for low-level Yubikey OTP functions -witten by Simon Josefsson . -Copyright (c) 2006, 2007, 2008, 2009 Yubico AB -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - - * Redistributions in binary form must reproduce the above - copyright notice, this list of conditions and the following - disclaimer in the documentation and/or other materials provided - with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -EOF - s.files = FileList["{tests,lib,docs,bin}/**/*"].exclude("rdoc").to_a + - FileList["ext/*.{c,h}"] + ['ext/extconf.rb'] - s.require_paths = ['lib', 'ext'] - s.bindir = 'bin' - s.autorequire = 'yubiruby' - s.test_file = 'tests/ts_yubiruby.rb' - s.has_rdoc = true - s.extra_rdoc_files = ['README'] - s.extensions = ['ext/extconf.rb'] -end \ No newline at end of file