Yubico Forum

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

All times are UTC + 1 hour




Post new topic Reply to topic  [ 11 posts ]  Go to page 1, 2  Next
Author Message
 Post subject: OTP validation cookbook
PostPosted: Sun Jun 15, 2008 9:37 pm 
Offline
Site Admin
Site Admin

Joined: Wed May 28, 2008 7:04 pm
Posts: 263
Location: Yubico base camp in Sweden - Now in Palo Alto
Questions regarding how a minimal OTP validation routine should be implemented comes in every now and then. It therefore seems like a good idea to keep a basic "cookbook" here involving the necessary steps involved.

"There are may ways to skin a cat" and the same thing apply here. It is somewhat up to each individual implementation to decide which steps are to be included and how the exact implementation is done.

I'll try to keep it reasonably brief for clarity reasons.


Step 1: Basic decoding and sanity validation

1. Convert the received modhex string into binary

2. Split the data in two parts – the last 16 bytes is the OTP part and the first, i.e. len – 16 bytes is the fixed id

3. Use the fixed id to look up the AES key for the id in question.

4. Decrypt the 16 bytes (128 bits) using AES-128 decryption

5. Calculate a ISO13239 checksum over the 16 bytes and verify that the residual is 0xf0b8. If not, abort

6. Check if the 6-byte private ID matches the value in the database. If the private id is not used, ensure that it is set to all zeroes and at verification, verify that all bytes are zero. If it does not match, abort

7. If any of the two last stages fail, it is most likely due to an invalid AES key, i.e. the decryption creates garbage.


Step 2: Check for "static OTP" (if used)

1. If (useCtr & 0x7fff) == 0x7fff and sessionCtr == 0xff and rnd = 0xffff the OTP is a "static OTP". If this matches, accept without further checks


Step 3: Basic (simple) counter validation

1. Set ctr32 = ((useCtr & 0x7fff) << 8) + sessionCtr

2. Verify that ctr32 > lastCtr32. If not, it is a fair guess that the OTP is subject to a replay

3. If successful, store ctr32 in the database to be lastCtr32


Step 4: Optional/alteranative: Detect lost OTPs

1. Verify that lastUseCtr > (useCtr & 0x7fff) || (lastUseCtr == (useCtr & 0x7fff) && lastSessionCtr > sessionCtr). If not, it is a fair guess that the OTP is subject to a replay

2. If lastUseCtr == (useCtr & 0x7fff), check that sessionCtr == (lastSessionCtr + 1). If not (at least) one OTP has been lost

3. If lastUseCtr != (useCtr & 0x7fff), check that (useCtr & 0x7fff) == (lastUseCtr + 1) and that sessionCtr == 0. If not (at least) one OTP has been lost

4. If not failing at step 1, store (useCtr & 0x7fff) as lastUseCtr and sessionCtr as lastSessionCtr

5. Depending on policy, accounts may be locked if more than one OTP is lost. Alternatively, the user may be informed by this and decide himself.


Step 5: In-session timer validation

Each Yubikey has a slightly varying "fingerprint" in terms of timestamp variation. The nominal frequency is 8Hz, but can vary +/- 30% between devices and over temperature.

1. For the sake of simplicitly, calculate tstp32 = tstpl + (tstph << 16)

2. When a new session is detected, i.e. lastUseCtr != (useCtr & 0x7fff), set tstpBase = tstp32 and store current time as timeBase

3. After the first OTP verification within a session, check (tstp32 - tstpBase) vs. (currentTime - timeBase). This value shall be fairly constant for each individual device.

4. Remember that the tstpl/tstph is 24 bits wide and therefore wraps after approx 24 days. An appropriate "fixup" routine will be needed.

5. A sophisticated application can store the calculated (expected) frequency for each individual device. At reasonable room temperature bounds (10-40 degrees C), it will stay within +/- 10%.



All feedback is appreciated,

Regards,

JakobE
Hardware- and firmware guy @ Yubico


Top
 Profile  
Reply with quote  

Share On:

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

PostPosted: Mon Jun 16, 2008 6:57 am 
Offline

Joined: Mon Jun 09, 2008 12:54 pm
Posts: 13
Location: Pennsylvania, U.S.A.
JakobE wrote:
Step 5: In-session timer validation

Each Yubikey has a slightly varying "fingerprint" in terms of timestamp variation. The nominal frequency is 8Hz, but can vary +/- 30% between devices and over temperature.

1. For the sake of simplicitly, calculate tstp32 = tstpl + (tstph << 16)

2. When a new session is detected, i.e. lastUseCtr != (useCtr & 0x7fff), set tstpBase = tstp32 and store current time as timeBase

3. After the first OTP verification within a session, check (tstp32 - tstpBase) vs. (currentTime - timeBase). This value shall be fairly constant for each individual device.

4. Remember that the tstpl/tstph is 24 bits wide and therefore wraps after approx 24 days. An appropriate "fixup" routine will be needed.

5. A sophisticated application can store the calculated (expected) frequency for each individual device. At reasonable room temperature bounds (10-40 degrees C), it will stay within +/- 10%.


First, thanks a lot for posting this Jakob, it was very helpful. I have question about the timing code: I'm allowing a deviation of 20% in my code before the server denies a key. Is this reasonable? When I'm testing the code on my own computer, the yubikey timer gets about that far away from the computer's timer. Do you have any recommendations for what is acceptable?


Top
 Profile  
Reply with quote  
PostPosted: Mon Jun 16, 2008 3:08 pm 
Offline

Joined: Mon May 26, 2008 5:16 am
Posts: 27
Hy,
I think it would be a nice idea to make a manual that really describe all the step that are require to check a yubikey.
because if we add explanation on each step on this forum it will start to be confusing as post come trying to explain this step or this one in more description (the post could be a start thought)

You could wait a bit to have question from a lot a person then have a better idea for the FAQ ;-)

or make a wiki, but i would make it read only for now (then why call it a wiki :-) ) as only maker wright now are mostly answering question and poster (user) asking them. But a least you could easily modify your cookbook as step needs clarification

My two cents

_________________
Patgadget
Montreal


Top
 Profile  
Reply with quote  
PostPosted: Mon Jun 16, 2008 3:19 pm 
Offline

Joined: Mon May 26, 2008 5:16 am
Posts: 27
Step 1.1 Modhex
http://forum.yubico.com/viewtopic.php?f=6&t=96

_________________
Patgadget
Montreal


Top
 Profile  
Reply with quote  
PostPosted: Tue Jun 17, 2008 12:44 pm 
Offline

Joined: Wed Jun 04, 2008 6:33 pm
Posts: 12
Location: Bergen, Norway
Is it a (good?) idea to make a reference implementation of the validation cookbook i the various language currently being hacked in?

Any particular server would of course depend on some specific database schema and API for retrieval of key information, but cookbook implementation could be written independent of such with a interface like:

ValidationResult YubiKeyValidation.validate(Token t, KeyData kd)

So this would be invoked after OTP is decrypted and parsed. KeyData contains information of last OTP received from YubiKey in question.

Speaking as a Java programmer, the Java reference cookbook could perhaps fit in the yubico-j library?


Top
 Profile  
Reply with quote  
PostPosted: Tue Jun 17, 2008 10:56 pm 
Offline

Joined: Mon Jun 09, 2008 12:54 pm
Posts: 13
Location: Pennsylvania, U.S.A.
aha42 wrote:
Is it a (good?) idea to make a reference implementation of the validation cookbook i the various language currently being hacked in?

ValidationResult YubiKeyValidation.validate(Token t, KeyData kd)

So this would be invoked after OTP is decrypted and parsed. KeyData contains information of last OTP received from YubiKey in question.


I think this is a great idea. That's what I'm trying to accomplish with the PHP version. If you or anyone else has any input, please let me know.

My method (YubiAuthenticator::authenticate) takes the exact same parameters as your sample ValidationResult. :)


Top
 Profile  
Reply with quote  
PostPosted: Wed Sep 17, 2008 5:03 am 
Offline

Joined: Sat Aug 30, 2008 3:08 pm
Posts: 3
JakobE wrote:
4. Decrypt the 16 bytes (128 bits) using AES-128 decryption


Hi

I've been searching for the specific layout of the decrypted 128 bits. Some of the fields are referenced in various posts, but I've not seen it "all in one place", offsets etc

I'm sure it must be somewhere but I'm not finding it - can someone give the link

TIA


Top
 Profile  
Reply with quote  
PostPosted: Wed Sep 17, 2008 3:26 pm 
Offline
User avatar

Joined: Wed May 07, 2008 5:25 pm
Posts: 110
Location: Sunnyvale, California
merlin wrote:
JakobE wrote:
4. Decrypt the 16 bytes (128 bits) using AES-128 decryption


Hi

I've been searching for the specific layout of the decrypted 128 bits. Some of the fields are referenced in various posts, but I've not seen it "all in one place", offsets etc

I'm sure it must be somewhere but I'm not finding it - can someone give the link

TIA


Page 2 in this doc explains it well: http://yubico.com/files/YubiKey_Security_Review.pdf

If you like to find the code that decrypts the OTP, you can find them here:
http://yubico.com/developers/library/

and http://yubico.com/developers/srv/

_________________
The YubiKey Server Guy


Top
 Profile  
Reply with quote  
PostPosted: Sat Jan 10, 2009 2:39 am 
Offline

Joined: Wed Jan 07, 2009 4:15 am
Posts: 6
JakobE wrote:
Step 3: Basic (simple) counter validation

1. Set ctr32 = ((useCtr & 0x7fff) << 8) + sessionCtr

2. Verify that ctr32 > lastCtr32. If not, it is a fair guess that the OTP is subject to a replay

3. If successful, store ctr32 in the database to be lastCtr32


OK...what happens when the 1 byte sessionCtr rolls over from 255 to 0, as in if a user kept their key plugged in for 256 invocations?

The PDF says that that the sessionCtr rolls to zero, but no mention if the 2 byte useCtr is incremented....I'm assuming that the useCtr does not increment during the rollover.

In which case the validation will fail according to the algorithm set out in Step 3.

So....do we just live with this and tell the user to remove and re-insert their key and try again?

Or is there a better way?

Thx!


Top
 Profile  
Reply with quote  
PostPosted: Sat Jan 10, 2009 6:00 pm 
Offline
Site Admin
Site Admin

Joined: Wed May 28, 2008 7:04 pm
Posts: 263
Location: Yubico base camp in Sweden - Now in Palo Alto
The usage counter is incremented when the session counter wraps from 255 to 0. Just like if the key was unplugged and inserted again.

With the best regards,

JakobE
Hardware- and firmware guy @ Yubico


Top
 Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 11 posts ]  Go to page 1, 2  Next

All times are UTC + 1 hour


Who is online

Users browsing this forum: No registered users and 3 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