/*
* Copyright (c) 2011 - 2013 United ID.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.unitedid.yhsm.internal;
import org.testng.annotations.AfterTest;
import org.testng.annotations.BeforeTest;
import org.testng.annotations.Test;
import org.unitedid.yhsm.SetupCommon;
import org.unitedid.yhsm.utility.Utils;
import java.util.ArrayList;
import java.util.List;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertTrue;
import static org.unitedid.yhsm.internal.Defines.YSM_TEMP_KEY_HANDLE;
public class OATHTest extends SetupCommon {
private String nonce = "f1f2f3f4f5f6";
private String aead;
private String aead2;
private int keyHandle = 8192;
@BeforeTest
public void setUp() throws Exception {
super.setUp();
String seed = "3132333435363738393031323334353637383930";
aead = hsm.generateOathAEAD(nonce, keyHandle, seed);
assertTrue(hsm.loadTemporaryKey(nonce, keyHandle, aead));
seed = "3132333435363738393031323334353637383931";
aead2 = hsm.generateOathAEAD(nonce, keyHandle, seed);
assertTrue(hsm.loadTemporaryKey(nonce, keyHandle, aead2));
}
@AfterTest
public void tearDown() throws Exception {
super.tearDown();
}
@Test
public void testOathHotpValues() throws YubiHSMCommandFailedException, YubiHSMErrorException, YubiHSMInputException {
List<OathHotpValueMap> testValueList = new ArrayList<OathHotpValueMap>();
testValueList.add(new OathHotpValueMap(0, "cc93cf18508d94934c64b65d8ba7667fb7cde4b0", "755224"));
testValueList.add(new OathHotpValueMap(1, "75a48a19d4cbe100644e8ac1397eea747a2d33ab", "287082"));
testValueList.add(new OathHotpValueMap(2, "0bacb7fa082fef30782211938bc1c5e70416ff44", "359152"));
testValueList.add(new OathHotpValueMap(3, "66c28227d03a2d5529262ff016a1e6ef76557ece", "969429"));
testValueList.add(new OathHotpValueMap(4, "a904c900a64b35909874b33e61c5938a8e15ed1c", "338314"));
testValueList.add(new OathHotpValueMap(30, "543c61f8f9aeb35f6dbc3a6847c3fe288cc0ee4c", "026920"));
hsm.loadTemporaryKey(nonce, keyHandle, aead);
for (OathHotpValueMap o : testValueList) {
String hmac = hsm.generateHMACSHA1(Utils.longToByteArray(o.getCounter()), YSM_TEMP_KEY_HANDLE, true, false).get("hash");
assertEquals(hmac, o.getHmac());
assertEquals(OATH.truncate(hmac, 6), o.getOtp());
}
}
@Test(threadPoolSize = 5, invocationCount = 20)
public void testOathHotpValidation() throws YubiHSMCommandFailedException, YubiHSMErrorException, YubiHSMInputException {
List<OathHotpCodeMap> testCodeList = new ArrayList<OathHotpCodeMap>();
testCodeList.add(new OathHotpCodeMap(1, 0, "755224", 1));
testCodeList.add(new OathHotpCodeMap(4, 0, "969429", 4));
testCodeList.add(new OathHotpCodeMap(0, 0, "969429", 3));
testCodeList.add(new OathHotpCodeMap(5, 3, "338314", 2));
testCodeList.add(new OathHotpCodeMap(31, 30, "026920", 1));
for (OathHotpCodeMap o : testCodeList) {
assertEquals(hsm.validateOathHOTP(keyHandle, nonce, aead, o.getCounter(), o.getOtp(), o.getLookAhead()), o.getExpectedCounter());
}
testCodeList.clear();
testCodeList.add(new OathHotpCodeMap(1, 0, "504140", 1));
testCodeList.add(new OathHotpCodeMap(4, 0, "272072", 4));
testCodeList.add(new OathHotpCodeMap(0, 0, "272072", 3));
testCodeList.add(new OathHotpCodeMap(5, 3, "030059", 2));
testCodeList.add(new OathHotpCodeMap(31, 30, "479886", 1));
for (OathHotpCodeMap o : testCodeList) {
assertEquals(hsm.validateOathHOTP(keyHandle, nonce, aead2, o.getCounter(), o.getOtp(), o.getLookAhead()), o.getExpectedCounter());
}
}
@Test(expectedExceptions = YubiHSMInputException.class)
public void testOathHotpTruncateHMACLength() throws YubiHSMInputException {
OATH.truncate("cccccccccccccccccccccccccccccccccccccccccc", 6);
}
}
class OathHotpValueMap {
private int counter;
private String hmac;
private String otp;
OathHotpValueMap(int counter, String hmac, String otp) {
this.counter = counter;
this.hmac = hmac;
this.otp = otp;
}
public int getCounter() {
return counter;
}
public String getHmac() {
return hmac;
}
public String getOtp() {
return otp;
}
}
class OathHotpCodeMap {
private int expectedCounter;
private int counter;
private String otp;
private int lookAhead;
OathHotpCodeMap(int expectedCounter, int counter, String otp, int lookAhead) {
this.expectedCounter = expectedCounter;
this.counter = counter;
this.otp = otp;
this.lookAhead = lookAhead;
}
public int getExpectedCounter() {
return expectedCounter;
}
public int getCounter() {
return counter;
}
public String getOtp() {
return otp;
}
public int getLookAhead() {
return lookAhead;
}
}