# HG changeset patch # User Alessio Caiazza # Date 1264864723 -3600 # Node ID 9d98ed26d4d004b3b811dc82f68dcea89b890b91 # Parent 0000000000000000000000000000000000000000 Gem Setup. ModHex binding diff -r 0000000000000000000000000000000000000000 -r 9d98ed26d4d004b3b811dc82f68dcea89b890b91 .hgignore --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/.hgignore Sat Jan 30 16:18:43 2010 +0100 @@ -0,0 +1,20 @@ +syntax: glob +*.orig +*.rej +*~ +*.o +tests/*.err +.DS_Store +build +.svn +(*) +*.perspectivev3 +*.mode1v3 +*.mode2v3 +*.mpkg +*.framework +*.pbxuser +*.gem + +syntax: regexp +.*\#.*\#$ \ No newline at end of file diff -r 0000000000000000000000000000000000000000 -r 9d98ed26d4d004b3b811dc82f68dcea89b890b91 Rakefile --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Rakefile Sat Jan 30 16:18:43 2010 +0100 @@ -0,0 +1,25 @@ +require 'rubygems' +require 'rubygems/gem_runner' + +require 'rake/gempackagetask' + +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://abisso.org' + s.platform = Gem::Platform::RUBY + s.summary = 'Yubikey integration' + s.files = FileList["{tests,lib,docs,ext}/**/*"].exclude("rdoc").to_a + s.require_paths = ['lib', 'ext'] + 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 + +Rake::GemPackageTask.new(spec) do |pkg| + pkg.need_tar = true +end \ No newline at end of file diff -r 0000000000000000000000000000000000000000 -r 9d98ed26d4d004b3b811dc82f68dcea89b890b91 ext/extconf.rb --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ext/extconf.rb Sat Jan 30 16:18:43 2010 +0100 @@ -0,0 +1,3 @@ +require 'mkmf' +#dir_config("libyubikey") +create_makefile('libyubikey') \ No newline at end of file diff -r 0000000000000000000000000000000000000000 -r 9d98ed26d4d004b3b811dc82f68dcea89b890b91 ext/libyubikey.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ext/libyubikey.c Sat Jan 30 16:18:43 2010 +0100 @@ -0,0 +1,82 @@ +#include +#include +#include "yubikey.h" +//#include "ykmodhex.c" + +#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; + + +/* ModHex */ +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); +} + +static VALUE modhex_encode(VALUE self) { + ID method = rb_intern(MODHEX_SING_ENCODE); + + return rb_funcall(mModHex, method, 1, self); +} + +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); +} + +static VALUE modhex_decode(VALUE self) { + ID method = rb_intern(MODHEX_SING_DECODE); + + return rb_funcall(mModHex, method, 1, self); +} + +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; +} + +static VALUE modhex_is_modhex(VALUE self) { + ID method = rb_intern(MODHEX_VALID); + + return rb_funcall(mModHex, method, 1, self); +} +/* ModHex END */ + +void Init_libyubikey() { + mYubiRuby = rb_define_module("YubiRuby"); + + mModHex = rb_define_module_under(mYubiRuby, "ModHex"); + rb_define_singleton_method(mModHex, MODHEX_SING_ENCODE, modhex_sing_encode, 1); + rb_define_method(mModHex, MODHEX_ENCODE, modhex_encode, 0); + rb_define_singleton_method(mModHex, MODHEX_SING_DECODE, modhex_sing_decode, 1); + rb_define_method(mModHex, MODHEX_DECODE, modhex_decode, 0); + rb_define_singleton_method(mModHex, MODHEX_VALID, modhex_sing_is_modhex, 1); + rb_define_method(mModHex, MODHEX_VALID, modhex_is_modhex, 0); + + //extends String with ModHex + rb_include_module(rb_cString, mModHex); +} \ No newline at end of file diff -r 0000000000000000000000000000000000000000 -r 9d98ed26d4d004b3b811dc82f68dcea89b890b91 ext/ykmodhex.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ext/ykmodhex.c Sat Jan 30 16:18: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 0000000000000000000000000000000000000000 -r 9d98ed26d4d004b3b811dc82f68dcea89b890b91 ext/yubikey.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ext/yubikey.h Sat Jan 30 16:18: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 0000000000000000000000000000000000000000 -r 9d98ed26d4d004b3b811dc82f68dcea89b890b91 lib/yubiruby.rb --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/lib/yubiruby.rb Sat Jan 30 16:18:43 2010 +0100 @@ -0,0 +1,6 @@ +require 'libyubikey' + +module YubiRuby + # C code version + LIBYUBIKEY_VERSION = '1.5' +end \ No newline at end of file