Yubico Forum https://forum.yubico.com/ |
|
OTP validation cookbook https://forum.yubico.com/viewtopic.php?f=4&t=103 |
Page 1 of 2 |
Author: | Jakob [ Sun Jun 15, 2008 9:37 pm ] |
Post subject: | OTP validation cookbook |
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 |
Author: | jwoltman [ Mon Jun 16, 2008 6:57 am ] |
Post subject: | Re: OTP validation cookbook |
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? |
Author: | patgadget [ Mon Jun 16, 2008 3:08 pm ] |
Post subject: | Re: OTP validation cookbook |
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 |
Author: | patgadget [ Mon Jun 16, 2008 3:19 pm ] |
Post subject: | Re: OTP validation cookbook |
Step 1.1 Modhex http://forum.yubico.com/viewtopic.php?f=6&t=96 |
Author: | aha42 [ Tue Jun 17, 2008 12:44 pm ] |
Post subject: | Re: OTP validation cookbook |
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? |
Author: | jwoltman [ Tue Jun 17, 2008 10:56 pm ] |
Post subject: | Re: OTP validation cookbook |
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. |
Author: | merlin [ Wed Sep 17, 2008 5:03 am ] |
Post subject: | Re: OTP validation cookbook |
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 |
Author: | paul [ Wed Sep 17, 2008 3:26 pm ] |
Post subject: | Re: OTP validation cookbook |
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/ |
Author: | chaeron [ Sat Jan 10, 2009 2:39 am ] |
Post subject: | Re: OTP validation cookbook |
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! |
Author: | Jakob [ Sat Jan 10, 2009 6:00 pm ] |
Post subject: | Re: OTP validation cookbook |
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 |
Page 1 of 2 | All times are UTC + 1 hour |
Powered by phpBB® Forum Software © phpBB Group https://www.phpbb.com/ |