Yubico Forum

...visit our web-store at store.yubico.com
It is currently Tue Jan 30, 2018 1:11 pm

All times are UTC + 1 hour




Post new topic Reply to topic  [ 5 posts ] 
Author Message
PostPosted: Mon Jun 03, 2013 3:37 am 
Offline

Joined: Tue May 28, 2013 2:14 am
Posts: 4
I am attempting to write some code that emulates the HMAC-SHA1 challege-response mechanism in my YubiKey so that I can use YubiKey-secured Password Safe safes on my iPhone. (For more background, see my project post in the community projects section.)

I noticed that there are a few quirks with the HMAC-SHA1 implementation on the YubiKey. So far, all but one involves some amount of truncation of the challenge prior to calculation of the HMAC. I think I've managed to find most of them, but I'm not certain that I've found all of them.

Is it possible to get some documentation on how the YubiKey prepares the data before calculating the HMAC?

Here are the cases I've found so far. All of these apply after truncating the challenge to 64 bytes and before the HMAC is calculated.
  • When the challenge is empty (zero bytes long), it is replaced with a single 0x00.
  • When the challenge ends with one or more 0x00s, these 0x00s on the end are removed.
  • When the challenge is exactly 64 bytes long and contains - but does not end with - one or more 0x00s, the challenge is truncated before the last contiguous string of (one or more) 0x00s.
  • When the challenge is exactly 64 bytes long and does not contain any 0x00s, the challenge is truncated in a location determined by a set of rules I don't fully understand.

FYI, I'm using the YkLib22 code to send the challenge and retrieve the response from the YubiKey, and I've checked in the debugger to be sure that any manipulation of the challenge happens in the YubiKey, not in this code.

Thanks in advance for any guidance.


Last edited by edutko on Sat Jun 22, 2013 1:00 pm, edited 1 time in total.

Top
 Profile  
Reply with quote  

Share On:

Share on Facebook FacebookShare on Twitter TwitterShare on Tumblr TumblrShare on Google+ Google+

PostPosted: Fri Jun 07, 2013 1:26 am 
Offline

Joined: Tue May 28, 2013 2:14 am
Posts: 4
Update: After improving my testing methodology, I was able to run through several more tests with more targeted challenges.

I'm not 100% certain that I've hit all of the cases yet, but I can say with fairly high confidence that the algorithm below will cover most - if not all - cases.

Based on my latest tests, the algorithm appears to be:
1. If the challenge is greater than 64 bytes long, truncate it to 64 bytes. (This is actually done in YkLib; I have not checked whether the hardware performs the same truncation if passed a longer challenge.)
2. Prepare the challenge:
  • If the challenge is empty (zero bytes long), replace it with a single 0x00.
  • If the challenge ends with one or more 0x00s, remove them.
  • If the challenge is exactly 64 bytes long, remove the last byte and all adjacent bytes of the same value.
3. Calculate the SHA-1 HMAC of the prepared challenge.

I'd still be interested to hear from the Yubico engineers on this. Are there any corner cases I've missed? Is this behavior by design? Can I expect it to be consistent across all types of YubiKeys?


Top
 Profile  
Reply with quote  
PostPosted: Wed Jun 12, 2013 10:37 am 
Offline
Site Admin
Site Admin

Joined: Wed Nov 14, 2012 2:59 pm
Posts: 666
1.
Input is limited to 64 bytes maximum. The processor is very slow (1 block takes about 50 ms) and the challenge-response mechanism is also
slow (low speed USB using reports). Furthermore, the input buffer is exactly 64 bytes so implementing an arbitrary mechanism would be
difficult and awkward.

2.
As there is no byte count field in the "original" Yubikey USB protocol, there is a bit of a quirk to determine the length of dynamic
input. There is a somewhat confusing (yet stringent) flag named CFGFLAG_HMAC_LT64, which determines if the input is dynamic (flag set)
or if the input is exactly 64 bytes in length

3.
Zero bytes is replaced with a binary '00' with length 1, which I think is sensible

4.
If the LT64 flag is set (input is 0-63 bytes), the last byte in the input is used as a null token to calculate the length of the input.
Assuming a "casual" use of the library, the last byte will be zero and therefore, the Yubikey will search backwards until the last non-zero
byte is found. Best for a <64 bytes input is to set the byte following the last byte to the last byte inverted, i.e. buf[len] = ~buf[len -1], this assuming len != 0.

Caveats:
The standard Yubikey had a bug where the LT64 flag does not work correctly (assumed to be cleared). Fixed in 2.2.6
The NEO had a bug where this mechanism did not worked correctly. Fixed in 3.1.5.

_________________
-Tom


Top
 Profile  
Reply with quote  
PostPosted: Sat Jun 22, 2013 1:03 pm 
Offline

Joined: Tue May 28, 2013 2:14 am
Posts: 4
Thanks for the detail, Tom. This is really helpful!


Top
 Profile  
Reply with quote  
PostPosted: Wed Mar 04, 2015 10:46 am 
Offline
Site Admin
Site Admin

Joined: Mon Dec 08, 2014 2:52 pm
Posts: 314
https://github.com/Yubico/yubikey-perso ... chalresp.c


Top
 Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 5 posts ] 

All times are UTC + 1 hour


Who is online

Users browsing this forum: Baidu [Spider] and 5 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB® Forum Software © phpBB Group