yubikey 1.1.1 → 1.2.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -45,6 +45,7 @@ A library to verify, decode, decrypt and parse Yubikey[http://www.yubico.com/hom
45
45
  The MIT License. See LICENSE.
46
46
 
47
47
  === Contributors
48
+ Carl Byström
48
49
  Erik Ruwalder
49
50
 
50
51
  === AES and CRC code
@@ -2,9 +2,11 @@ $:.unshift(File.dirname(__FILE__)) unless
2
2
  $:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))
3
3
 
4
4
  require 'net/http'
5
+ require 'crypt/rijndael'
5
6
  require 'openssl'
6
7
 
7
- require 'yubikey_ext'
8
+ module Yubikey; end;
9
+
8
10
  require 'yubikey/hex'
9
11
  require 'yubikey/modhex'
10
12
  require 'yubikey/otp'
@@ -4,36 +4,26 @@ module Yubikey::ModHex
4
4
 
5
5
  # Decode a ModHex string into binary data
6
6
  def self.decode(modhex_string)
7
- out = ''
8
- flag = true # to switch between first and last nibble
9
- byte = 0
10
-
11
7
  raise ArgumentError, "ModHex string length is not even" unless modhex_string.length % 2 == 0
12
8
 
13
- modhex_string.each_byte do |b|
14
- x = TRANS.index(b.chr) # lookup occurrence in table
15
- if flag
16
- byte = x
17
- else
18
- byte = (byte << 4) | x
19
- out <<= byte.chr
20
- end
21
- flag = !flag
9
+ chars = 'cbdefghijklnrtuv'
10
+ result = ""
11
+ modhex_string.scan(/../).each do |c|
12
+ result += (chars.index(c[0]) * 16 + chars.index(c[1])).chr
22
13
  end
23
-
24
- out
14
+ result
25
15
  end
26
16
 
27
17
  # Encode a binary string into ModHex
28
18
  def self.encode(string)
29
- out = ''
19
+ result = ''
30
20
 
31
21
  string.each_byte do |b|
32
- out <<= TRANS[(b >> 4) & 0xF]
33
- out <<= TRANS[b & 0xF]
22
+ result <<= TRANS[(b >> 4) & 0xF]
23
+ result <<= TRANS[b & 0xF]
34
24
  end
35
25
 
36
- out
26
+ result
37
27
  end
38
28
 
39
29
  end # Yubikey::ModHex
@@ -22,7 +22,7 @@ class Yubikey::OTP
22
22
  # [+otp+] ModHex encoded Yubikey OTP (at least 32 characters)
23
23
  # [+key+] 32-character hex AES key
24
24
  def initialize(otp, key)
25
- raise InvalidOTPError, 'OTP must be at least 32 characters of modhex' unless otp.modhex? && otp.length >= 32
25
+ raise InvalidOTPError, 'OTP must be at least 32 characters of modhex' unless otp.modhex? && otp.length >= 32
26
26
  raise InvalidKeyError, 'Key must be 32 hex characters' unless key.hex? && key.length == 32
27
27
 
28
28
  @public_id = otp[0,otp.length-32] if otp.length > 32
@@ -30,24 +30,27 @@ class Yubikey::OTP
30
30
  @token = Yubikey::ModHex.decode(otp[-32,32])
31
31
  @aes_key = key.to_bin
32
32
 
33
- decrypt
34
- parse
33
+ @token = Crypt::Rijndael.new(@aes_key, 128).decrypt_block(@token)
34
+
35
+ raise BadCRCError unless crc_valid?
36
+
37
+ @secret_id, @insert_counter, @timestamp, @timestamp_lo, @session_counter, @random_number, @crc = @token.unpack('H12vvCCvv')
38
+ @timestamp += @timestamp_lo * 65536
35
39
  end
36
40
 
37
41
  private
38
42
 
39
- def decrypt
40
- @token = Yubikey::AES.decrypt(@token, @aes_key)
41
- end
42
-
43
- def parse
44
- raise BadCRCError unless Yubikey::CRC.valid?(@token)
45
-
46
- @secret_id = @token[0,6].to_hex
47
- @insert_counter = @token[7] * 256 + @token[6]
48
- @timestamp = @token[10] * 65536 + @token[9] * 256 + @token[8]
49
- @session_counter = @token[11]
50
- @random_number = @token[13] * 256 + @token[12]
43
+ def crc_valid?
44
+ crc = 0xffff
45
+ @token.each_byte do |b|
46
+ crc ^= b & 0xff
47
+ 8.times do
48
+ test = (crc & 1) == 1
49
+ crc >>= 1
50
+ crc ^= 0x8408 if test
51
+ end
52
+ end
53
+ crc == 0xf0b8
51
54
  end
52
55
 
53
56
  # :stopdoc:
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: yubikey
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.1
4
+ version: 1.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jonathan Rudenberg
@@ -9,27 +9,30 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-06-04 00:00:00 -04:00
12
+ date: 2009-08-08 00:00:00 -04:00
13
13
  default_executable:
14
- dependencies: []
15
-
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: crypt
17
+ type: :runtime
18
+ version_requirement:
19
+ version_requirements: !ruby/object:Gem::Requirement
20
+ requirements:
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
23
+ version: "0"
24
+ version:
16
25
  description: A library to verify, decode, decrypt and parse Yubikey one-time passwords.
17
26
  email: jon335@gmail.com
18
27
  executables: []
19
28
 
20
- extensions:
21
- - ext/yubikey_ext/extconf.rb
29
+ extensions: []
30
+
22
31
  extra_rdoc_files:
23
32
  - LICENSE
24
33
  - README.rdoc
25
- - ext/yubikey_ext/yubikey_ext.c
26
34
  files:
27
35
  - examples/otp.rb
28
- - ext/yubikey_ext/extconf.rb
29
- - ext/yubikey_ext/ykaes.c
30
- - ext/yubikey_ext/ykcrc.c
31
- - ext/yubikey_ext/yubikey.h
32
- - ext/yubikey_ext/yubikey_ext.c
33
36
  - lib/yubikey.rb
34
37
  - lib/yubikey/hex.rb
35
38
  - lib/yubikey/modhex.rb
@@ -38,7 +41,6 @@ files:
38
41
  - spec/hex_spec.rb
39
42
  - spec/spec.opts
40
43
  - spec/spec_helper.rb
41
- - spec/yubikey_ext_spec.rb
42
44
  - spec/yubikey_modhex_spec.rb
43
45
  - spec/yubikey_otp_spec.rb
44
46
  - spec/yubikey_otp_verify_spec.rb
@@ -72,14 +74,13 @@ required_rubygems_version: !ruby/object:Gem::Requirement
72
74
  requirements: []
73
75
 
74
76
  rubyforge_project: yubikey
75
- rubygems_version: 1.3.4
77
+ rubygems_version: 1.3.5
76
78
  signing_key:
77
79
  specification_version: 3
78
80
  summary: A library to verify, decode, decrypt and parse Yubikey one-time passwords.
79
81
  test_files:
80
82
  - spec/hex_spec.rb
81
83
  - spec/spec_helper.rb
82
- - spec/yubikey_ext_spec.rb
83
84
  - spec/yubikey_modhex_spec.rb
84
85
  - spec/yubikey_otp_spec.rb
85
86
  - spec/yubikey_otp_verify_spec.rb
@@ -1,7 +0,0 @@
1
- require 'mkmf'
2
-
3
- dir_config('yubikey_ext')
4
-
5
- have_header('yubikey.h')
6
-
7
- create_makefile('yubikey_ext')
@@ -1,214 +0,0 @@
1
- /* ykaes.c --- Implementation of AES-128.
2
- *
3
- * Copyright (c) 2006, 2007, 2008, 2009 Yubico AB
4
- * All rights reserved.
5
- *
6
- * Redistribution and use in source and binary forms, with or without
7
- * modification, are permitted provided that the following conditions are
8
- * met:
9
- *
10
- * * Redistributions of source code must retain the above copyright
11
- * notice, this list of conditions and the following disclaimer.
12
- *
13
- * * Redistributions in binary form must reproduce the above
14
- * copyright notice, this list of conditions and the following
15
- * disclaimer in the documentation and/or other materials provided
16
- * with the distribution.
17
- *
18
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29
- *
30
- */
31
-
32
- #include "yubikey.h"
33
-
34
- #define NUMBER_OF_ROUNDS 10
35
-
36
- static const uint8_t RC[] =
37
- { 0x1, 0x2, 0x4, 0x8, 0x10, 0x20, 0x40, 0x80, 0x1B, 0x36 };
38
-
39
- static const uint8_t rijndael_sbox[] = {
40
- 0x63, 0x7C, 0x77, 0x7B, 0xF2, 0x6B, 0x6F, 0xC5,
41
- 0x30, 0x01, 0x67, 0x2B, 0xFE, 0xD7, 0xAB, 0x76,
42
- 0xCA, 0x82, 0xC9, 0x7D, 0xFA, 0x59, 0x47, 0xF0,
43
- 0xAD, 0xD4, 0xA2, 0xAF, 0x9C, 0xA4, 0x72, 0xC0,
44
- 0xB7, 0xFD, 0x93, 0x26, 0x36, 0x3F, 0xF7, 0xCC,
45
- 0x34, 0xA5, 0xE5, 0xF1, 0x71, 0xD8, 0x31, 0x15,
46
- 0x04, 0xC7, 0x23, 0xC3, 0x18, 0x96, 0x05, 0x9A,
47
- 0x07, 0x12, 0x80, 0xE2, 0xEB, 0x27, 0xB2, 0x75,
48
- 0x09, 0x83, 0x2C, 0x1A, 0x1B, 0x6E, 0x5A, 0xA0,
49
- 0x52, 0x3B, 0xD6, 0xB3, 0x29, 0xE3, 0x2F, 0x84,
50
- 0x53, 0xD1, 0x00, 0xED, 0x20, 0xFC, 0xB1, 0x5B,
51
- 0x6A, 0xCB, 0xBE, 0x39, 0x4A, 0x4C, 0x58, 0xCF,
52
- 0xD0, 0xEF, 0xAA, 0xFB, 0x43, 0x4D, 0x33, 0x85,
53
- 0x45, 0xF9, 0x02, 0x7F, 0x50, 0x3C, 0x9F, 0xA8,
54
- 0x51, 0xA3, 0x40, 0x8F, 0x92, 0x9D, 0x38, 0xF5,
55
- 0xBC, 0xB6, 0xDA, 0x21, 0x10, 0xFF, 0xF3, 0xD2,
56
- 0xCD, 0x0C, 0x13, 0xEC, 0x5F, 0x97, 0x44, 0x17,
57
- 0xC4, 0xA7, 0x7E, 0x3D, 0x64, 0x5D, 0x19, 0x73,
58
- 0x60, 0x81, 0x4F, 0xDC, 0x22, 0x2A, 0x90, 0x88,
59
- 0x46, 0xEE, 0xB8, 0x14, 0xDE, 0x5E, 0x0B, 0xDB,
60
- 0xE0, 0x32, 0x3A, 0x0A, 0x49, 0x06, 0x24, 0x5C,
61
- 0xC2, 0xD3, 0xAC, 0x62, 0x91, 0x95, 0xE4, 0x79,
62
- 0xE7, 0xC8, 0x37, 0x6D, 0x8D, 0xD5, 0x4E, 0xA9,
63
- 0x6C, 0x56, 0xF4, 0xEA, 0x65, 0x7A, 0xAE, 0x08,
64
- 0xBA, 0x78, 0x25, 0x2E, 0x1C, 0xA6, 0xB4, 0xC6,
65
- 0xE8, 0xDD, 0x74, 0x1F, 0x4B, 0xBD, 0x8B, 0x8A,
66
- 0x70, 0x3E, 0xB5, 0x66, 0x48, 0x03, 0xF6, 0x0E,
67
- 0x61, 0x35, 0x57, 0xB9, 0x86, 0xC1, 0x1D, 0x9E,
68
- 0xE1, 0xF8, 0x98, 0x11, 0x69, 0xD9, 0x8E, 0x94,
69
- 0x9B, 0x1E, 0x87, 0xE9, 0xCE, 0x55, 0x28, 0xDF,
70
- 0x8C, 0xA1, 0x89, 0x0D, 0xBF, 0xE6, 0x42, 0x68,
71
- 0x41, 0x99, 0x2D, 0x0F, 0xB0, 0x54, 0xBB, 0x16
72
- };
73
-
74
- static const uint8_t rijndael_inv_sbox[] = {
75
- 0x52, 0x09, 0x6A, 0xD5, 0x30, 0x36, 0xA5, 0x38,
76
- 0xBF, 0x40, 0xA3, 0x9E, 0x81, 0xF3, 0xD7, 0xFB,
77
- 0x7C, 0xE3, 0x39, 0x82, 0x9B, 0x2F, 0xFF, 0x87,
78
- 0x34, 0x8E, 0x43, 0x44, 0xC4, 0xDE, 0xE9, 0xCB,
79
- 0x54, 0x7B, 0x94, 0x32, 0xA6, 0xC2, 0x23, 0x3D,
80
- 0xEE, 0x4C, 0x95, 0x0B, 0x42, 0xFA, 0xC3, 0x4E,
81
- 0x08, 0x2E, 0xA1, 0x66, 0x28, 0xD9, 0x24, 0xB2,
82
- 0x76, 0x5B, 0xA2, 0x49, 0x6D, 0x8B, 0xD1, 0x25,
83
- 0x72, 0xF8, 0xF6, 0x64, 0x86, 0x68, 0x98, 0x16,
84
- 0xD4, 0xA4, 0x5C, 0xCC, 0x5D, 0x65, 0xB6, 0x92,
85
- 0x6C, 0x70, 0x48, 0x50, 0xFD, 0xED, 0xB9, 0xDA,
86
- 0x5E, 0x15, 0x46, 0x57, 0xA7, 0x8D, 0x9D, 0x84,
87
- 0x90, 0xD8, 0xAB, 0x00, 0x8C, 0xBC, 0xD3, 0x0A,
88
- 0xF7, 0xE4, 0x58, 0x05, 0xB8, 0xB3, 0x45, 0x06,
89
- 0xD0, 0x2C, 0x1E, 0x8F, 0xCA, 0x3F, 0x0F, 0x02,
90
- 0xC1, 0xAF, 0xBD, 0x03, 0x01, 0x13, 0x8A, 0x6B,
91
- 0x3A, 0x91, 0x11, 0x41, 0x4F, 0x67, 0xDC, 0xEA,
92
- 0x97, 0xF2, 0xCF, 0xCE, 0xF0, 0xB4, 0xE6, 0x73,
93
- 0x96, 0xAC, 0x74, 0x22, 0xE7, 0xAD, 0x35, 0x85,
94
- 0xE2, 0xF9, 0x37, 0xE8, 0x1C, 0x75, 0xDF, 0x6E,
95
- 0x47, 0xF1, 0x1A, 0x71, 0x1D, 0x29, 0xC5, 0x89,
96
- 0x6F, 0xB7, 0x62, 0x0E, 0xAA, 0x18, 0xBE, 0x1B,
97
- 0xFC, 0x56, 0x3E, 0x4B, 0xC6, 0xD2, 0x79, 0x20,
98
- 0x9A, 0xDB, 0xC0, 0xFE, 0x78, 0xCD, 0x5A, 0xF4,
99
- 0x1F, 0xDD, 0xA8, 0x33, 0x88, 0x07, 0xC7, 0x31,
100
- 0xB1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xEC, 0x5F,
101
- 0x60, 0x51, 0x7F, 0xA9, 0x19, 0xB5, 0x4A, 0x0D,
102
- 0x2D, 0xE5, 0x7A, 0x9F, 0x93, 0xC9, 0x9C, 0xEF,
103
- 0xA0, 0xE0, 0x3B, 0x4D, 0xAE, 0x2A, 0xF5, 0xB0,
104
- 0xC8, 0xEB, 0xBB, 0x3C, 0x83, 0x53, 0x99, 0x61,
105
- 0x17, 0x2B, 0x04, 0x7E, 0xBA, 0x77, 0xD6, 0x26,
106
- 0xE1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0C, 0x7D
107
- };
108
-
109
- static inline uint8_t
110
- xtime (uint8_t b)
111
- {
112
- return (b & 0x80) ? ((b << 1) ^ 0x1b) : (b << 1);
113
- }
114
-
115
- void
116
- yubikey_aes_decrypt (uint8_t * state, const uint8_t * key)
117
- {
118
- uint8_t i, j, round_key[0x10];
119
- uint8_t a02x, a13x;
120
- uint8_t a02xx, a13xx;
121
- uint8_t k1, k2;
122
-
123
- memcpy (round_key, key, sizeof (round_key));
124
- for (i = 0; i < NUMBER_OF_ROUNDS; i++)
125
- {
126
- round_key[0] ^= RC[i];
127
-
128
- round_key[0] ^= rijndael_sbox[round_key[13]];
129
- round_key[1] ^= rijndael_sbox[round_key[14]];
130
- round_key[2] ^= rijndael_sbox[round_key[15]];
131
- round_key[3] ^= rijndael_sbox[round_key[12]];
132
-
133
- for (j = 4; j < 16; j++)
134
- round_key[j] ^= round_key[j - 4];
135
- }
136
- for (i = 0; i < 0x10; i++)
137
- state[i] ^= round_key[i];
138
-
139
- for (i = 1; i <= NUMBER_OF_ROUNDS; i++)
140
- {
141
- // inv_byte_sub_shift_row();
142
-
143
- /* First row: 0 shift, 0 4 8 12 */
144
- state[0] = rijndael_inv_sbox[state[0]];
145
- state[4] = rijndael_inv_sbox[state[4]];
146
- state[8] = rijndael_inv_sbox[state[8]];
147
- state[12] = rijndael_inv_sbox[state[12]];
148
-
149
- /* Second row: -1 shift, 1 5 9 13 */
150
- j = state[13];
151
- state[13] = rijndael_inv_sbox[state[9]];
152
- state[9] = rijndael_inv_sbox[state[5]];
153
- state[5] = rijndael_inv_sbox[state[1]];
154
- state[1] = rijndael_inv_sbox[j];
155
-
156
- /* Third row: -2 shift, 2 6 10 14 */
157
- j = state[2];
158
- state[2] = rijndael_inv_sbox[state[10]];
159
- state[10] = rijndael_inv_sbox[j];
160
- j = state[6];
161
- state[6] = rijndael_inv_sbox[state[14]];
162
- state[14] = rijndael_inv_sbox[j];
163
-
164
- /* Fourth row: -3 shift, 3 7 11 15 */
165
- j = state[3];
166
- state[3] = rijndael_inv_sbox[state[7]];
167
- state[7] = rijndael_inv_sbox[state[11]];
168
- state[11] = rijndael_inv_sbox[state[15]];
169
- state[15] = rijndael_inv_sbox[j];
170
-
171
- // get_inv_round_key(i);
172
-
173
- for (j = 15; j > 3; j--)
174
- round_key[j] ^= round_key[j - 4];
175
-
176
- round_key[0] ^=
177
- (RC[NUMBER_OF_ROUNDS - i] ^ rijndael_sbox[round_key[13]]);
178
-
179
- round_key[1] ^= rijndael_sbox[round_key[14]];
180
- round_key[2] ^= rijndael_sbox[round_key[15]];
181
- round_key[3] ^= rijndael_sbox[round_key[12]];
182
-
183
- for (j = 0; j < 16; j++)
184
- state[j] ^= round_key[j];
185
- if (i != NUMBER_OF_ROUNDS)
186
- {
187
-
188
- //inv_mix_column();
189
-
190
- for (j = 0; j < 16; j += 4)
191
- {
192
- k1 = state[j] ^ state[j + 2];
193
- a02x = xtime (k1);
194
- k2 = state[j + 1] ^ state[j + 3];
195
- a13x = xtime (k2);
196
-
197
- k1 ^= (k2 ^ xtime (state[j + 1] ^ state[j + 2]));
198
- k2 = k1;
199
-
200
- a02xx = xtime (a02x);
201
- a13xx = xtime (a13x);
202
-
203
- k1 ^= (xtime (a02xx ^ a13xx) ^ a02xx);
204
- k2 ^= (xtime (a02xx ^ a13xx) ^ a13xx);
205
-
206
- state[j] ^= (k1 ^ a02x);
207
- state[j + 1] ^= k2;
208
- state[j + 2] ^= (k1 ^ a13x);
209
- state[j + 3] ^= (k2 ^ a02x ^ a13x);
210
- }
211
- }
212
-
213
- }
214
- }
@@ -1,54 +0,0 @@
1
- /* ykcrc.c --- Implementation of Yubikey CRC-16 function.
2
- *
3
- * Written by Simon Josefsson <simon@josefsson.org>.
4
- * Copyright (c) 2006, 2007, 2008, 2009 Yubico AB
5
- * All rights reserved.
6
- *
7
- * Redistribution and use in source and binary forms, with or without
8
- * modification, are permitted provided that the following conditions are
9
- * met:
10
- *
11
- * * Redistributions of source code must retain the above copyright
12
- * notice, this list of conditions and the following disclaimer.
13
- *
14
- * * Redistributions in binary form must reproduce the above
15
- * copyright notice, this list of conditions and the following
16
- * disclaimer in the documentation and/or other materials provided
17
- * with the distribution.
18
- *
19
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30
- *
31
- */
32
-
33
- #include "yubikey.h"
34
-
35
- uint16_t
36
- yubikey_crc16 (const uint8_t *buf, size_t buf_size)
37
- {
38
- uint16_t m_crc = 0xffff;
39
-
40
- while (buf_size--)
41
- {
42
- int i, j;
43
- m_crc ^= (uint8_t) * buf++ & 0xFF;
44
- for (i = 0; i < 8; i++)
45
- {
46
- j = m_crc & 1;
47
- m_crc >>= 1;
48
- if (j)
49
- m_crc ^= 0x8408;
50
- }
51
- }
52
-
53
- return m_crc;
54
- }
@@ -1,58 +0,0 @@
1
- /* yubikey.h --- Prototypes for low-level Yubikey OTP functions.
2
- *
3
- * Written by Simon Josefsson <simon@josefsson.org>.
4
- * Copyright (c) 2006, 2007, 2008, 2009 Yubico AB
5
- * All rights reserved.
6
- *
7
- * Redistribution and use in source and binary forms, with or without
8
- * modification, are permitted provided that the following conditions are
9
- * met:
10
- *
11
- * * Redistributions of source code must retain the above copyright
12
- * notice, this list of conditions and the following disclaimer.
13
- *
14
- * * Redistributions in binary form must reproduce the above
15
- * copyright notice, this list of conditions and the following
16
- * disclaimer in the documentation and/or other materials provided
17
- * with the distribution.
18
- *
19
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30
- *
31
- */
32
-
33
- #ifndef YUBIKEY_H
34
- #define YUBIKEY_H
35
-
36
- #include <stdint.h>
37
- #include <string.h>
38
-
39
- #define YUBIKEY_BLOCK_SIZE 16
40
- #define YUBIKEY_KEY_SIZE 16
41
- #define YUBIKEY_UID_SIZE 6
42
-
43
- #define YUBIKEY_CRC_OK_RESIDUE 0xf0b8
44
-
45
- #define yubikey_crc_ok_p(tok) (yubikey_crc16 ((tok), YUBIKEY_BLOCK_SIZE) == YUBIKEY_CRC_OK_RESIDUE)
46
-
47
- /* Low-level functions; AES. */
48
-
49
- /* AES-decrypt one 16-byte block STATE using the 128-bit KEY, leaving
50
- the decrypted output in the STATE buffer. */
51
- void yubikey_aes_decrypt(uint8_t *state, const uint8_t *key);
52
-
53
- /*
54
- * Low-level functions; CRC.
55
- */
56
- uint16_t yubikey_crc16 (const uint8_t *buf, size_t buf_size);
57
-
58
- #endif
@@ -1,53 +0,0 @@
1
- #include "ruby.h"
2
- #include "yubikey.h"
3
-
4
- /*
5
- * call-seq:
6
- * decrypt(state, key) -> plaintext
7
- *
8
- * Decrypt 16 bytes of binary AES ciphertext to binary plaintext with the Yubico implementation of AES-128 ECB
9
- *
10
- * [+state+] 16 bytes of binary ciphertext
11
- * [+key+] 16-byte binary key
12
- *
13
- */
14
- static VALUE
15
- aes_decrypt(VALUE self, VALUE state, VALUE key) {
16
- char* state_ptr = StringValuePtr(state);
17
- char* key_ptr = StringValuePtr(key);
18
-
19
- if (RSTRING(state)->len != YUBIKEY_BLOCK_SIZE || RSTRING(key)->len != YUBIKEY_KEY_SIZE)
20
- rb_raise(rb_eArgError, "key and state must be 16 bytes");
21
-
22
- yubikey_aes_decrypt((uint8_t*)state_ptr, (uint8_t*)key_ptr);
23
-
24
- return rb_str_new(state_ptr, YUBIKEY_BLOCK_SIZE);
25
- }
26
-
27
- /*
28
- * call-seq:
29
- * valid?(token)
30
- *
31
- * Check the CRC of a decrypted Yubikey OTP
32
- *
33
- * [+token+] 16-byte binary token
34
- */
35
- static VALUE
36
- crc_check(VALUE self, VALUE token) {
37
- char* token_ptr = StringValuePtr(token);
38
-
39
- if (RSTRING(token)->len != YUBIKEY_BLOCK_SIZE)
40
- rb_raise(rb_eArgError, "token must be 16 bytes");
41
-
42
- return yubikey_crc_ok_p((uint8_t*)token_ptr) ? Qtrue : Qfalse;
43
- }
44
-
45
- void
46
- Init_yubikey_ext() {
47
- VALUE rb_mYubikey = rb_define_module("Yubikey");
48
- VALUE rb_mYubikeyAES = rb_define_module_under(rb_mYubikey, "AES");
49
- VALUE rb_mYubikeyCRC = rb_define_module_under(rb_mYubikey, "CRC");
50
-
51
- rb_define_module_function(rb_mYubikeyAES, "decrypt", aes_decrypt, 2);
52
- rb_define_module_function(rb_mYubikeyCRC, "valid?", crc_check, 1);
53
- }
@@ -1,32 +0,0 @@
1
- require File.dirname(__FILE__) + '/spec_helper'
2
-
3
- $:.unshift File.dirname(__FILE__) + '/../ext/yubikey_ext'
4
- require 'yubikey_ext.so'
5
-
6
- describe 'yubikey_ext' do
7
- it 'should decrypt aes' do
8
- key = '72992427a3b8ccd20697493b5532561f'.to_bin
9
- state = 'ddf43aec57366784e061a12f767e728a'.to_bin
10
- plain = '619dd70df3b30300de1bdb00ffbf6f26'.to_bin
11
-
12
- Yubikey::AES.decrypt(state, key).should == plain
13
- end
14
-
15
- it 'should raise if aes key or state length is not 16' do
16
- lambda { Yubikey::AES.decrypt("i\266H\034\213\253\242\266\016\217\"\027\233X\315V", 'test') }.
17
- should raise_error(ArgumentError)
18
-
19
- lambda { Yubikey::AES.decrypt('test', "\354\336\030\333\347o\275\f33\017\0345Hq\333") }.
20
- should raise_error(ArgumentError)
21
- end
22
-
23
- it 'should check a crc' do
24
- Yubikey::CRC.valid?('619dd70df3b30300de1bdb00ffbf6f26'.to_bin).should == true
25
- Yubikey::CRC.valid?('ddf43aec57366784e061a12f767e728a'.to_bin).should == false
26
- end
27
-
28
- it 'should raise if crc token length not 16' do
29
- lambda { Yubikey::CRC.valid?('619dd70df3b30300de1bdb00ffbf6f'.to_bin) }.
30
- should raise_error(ArgumentError)
31
- end
32
- end