blob: 219737da82c9d78810fc1b31c3f60c77aa847011 [file] [log] [blame]
/*
* Copyright (C) 2021 The Android Open Source Project
*
* 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 com.android.libraries.entitlement.eapaka;
import static com.google.common.truth.Truth.assertThat;
import static org.testng.Assert.assertThrows;
import static org.testng.Assert.expectThrows;
import android.util.Base64;
import androidx.test.runner.AndroidJUnit4;
import com.android.libraries.entitlement.ServiceEntitlementException;
import com.google.common.io.BaseEncoding;
import org.junit.Test;
import org.junit.runner.RunWith;
@RunWith(AndroidJUnit4.class)
public class EapAkaSecurityContextTest {
// Base64 data : 2wjHnwKln8mjjxDzMKJvLBzMHtm0X9SNBsUWEAbEiAdD7xeqqZ7nsXzukRkIhd6SDZ4bj7s=
// RAW DATA : DB08C79F02A59FC9A38F10F330A26F2C1CCC1ED9B45FD48D06C5161006C4880743EF17AAA99EE7B17
// CEE91190885DE920D9E1B8FBB
// TAG : DB
// RES length : 08
// RES : C79F02A59FC9A38F
// CK Length : 10
// CK : F330A26F2C1CCC1ED9B45FD48D06C516
// IK Length : 10
// IK : 06C4880743EF17AAA99EE7B17CEE9119
// KC Length : 08
// KC : 85DE920D9E1B8FBB
private static final String GSM_SECURITY_CONTEXT_RESPONSE =
"2wjHnwKln8mjjxDzMKJvLBzMHtm0X9SNBsUWEAbEiAdD7xeqqZ7nsXzukRkIhd6SDZ4bj7s=";
private static final String EXPECTED_IK = "06C4880743EF17AAA99EE7B17CEE9119";
private static final String EXPECTED_CK = "F330A26F2C1CCC1ED9B45FD48D06C516";
private static final String EXPECTED_RES = "C79F02A59FC9A38F";
// Invalid data
private static final String GSM_SECURITY_CONTEXT_RESPONSE_TAG_DE = "DE08C79F02A59FC9A38F";
private static final String GSM_SECURITY_CONTEXT_RESPONSE_INVALID_RES_LENGTH =
"DC40C79F02A59FC"
+ "9A38F10F330A26F2C1CCC1ED9B45FD48D06C5161006C4880743EF17AAA99EE7B17CEE911908"
+ "85DE920D9E1B8FBB";
private static final String GSM_SECURITY_CONTEXT_RESPONSE_INVALID_CK_LENGTH =
"DB08C79F02A59FC9"
+ "A38F40F330A26F2C1CCC1ED9B45FD48D06C5161006C4880743EF17AAA99EE7B17CEE9119088"
+ "5DE920D9E1B8FBB";
private static final String GSM_SECURITY_CONTEXT_RESPONSE_INVALID_IK_LENGTH =
"DB08C79F02A59FC9"
+ "A38F10F330A26F2C1CCC1ED9B45FD48D06C5164006C4880743EF17AAA99EE7B17CEE9119088"
+ "5DE920D9E1B8FBB";
private static final String GSM_SECURITY_CONTEXT_RESPONSE_INVALID_KC_LENGTH =
"DB08C79F02A59FC9"
+ "A38F10F330A26F2C1CCC1ED9B45FD48D06C5161006C4880743EF17AAA99EE7B17CEE9119108"
+ "5DE920D9E1B8FBB";
private static final String GSM_SECURITY_CONTEXT_RESPONSE_NO_KC_KEY =
"DB08C79F02A59FC9A38F10F3"
+ "30A26F2C1CCC1ED9B45FD48D06C5161006C4880743EF17AAA99EE7B17CEE9119";
// Base64 data : 3A4z1Y05YZwhM2fjdhFTFQ==
// RAW DATA : DC0E33D58D39619C213367E376115315
// TAG : DC
// AUTS length : 0E
// AUTS : 33D58D39619C213367E376115315
private static final String RESPONSE_SYNC_FAILURE = "3A4z1Y05YZwhM2fjdhFTFQ==";
private static final String EXPECTED_AUTS = "33D58D39619C213367E376115315";
@Test
public void parseResponseData_validResponse_pass() throws Exception {
EapAkaSecurityContext securityContext =
EapAkaSecurityContext.from(GSM_SECURITY_CONTEXT_RESPONSE);
assertThat(securityContext.getIk()).isEqualTo(convertHexStringToBytes(EXPECTED_IK));
assertThat(securityContext.getCk()).isEqualTo(convertHexStringToBytes(EXPECTED_CK));
assertThat(securityContext.getRes()).isEqualTo(convertHexStringToBytes(EXPECTED_RES));
}
@Test
public void parseResponseData_invalidWithWrongTag_throwsException() {
byte[] data = convertHexStringToBytes(GSM_SECURITY_CONTEXT_RESPONSE_TAG_DE);
String encodedData = Base64.encodeToString(data, Base64.NO_WRAP).trim();
ServiceEntitlementException exception =
expectThrows(
ServiceEntitlementException.class,
() -> EapAkaSecurityContext.from(encodedData));
assertThat(exception.getErrorCode())
.isEqualTo(ServiceEntitlementException.ERROR_ICC_AUTHENTICATION_NOT_AVAILABLE);
assertThat(exception.getMessage())
.isEqualTo("Invalid SIM EAP-AKA authentication response!");
}
@Test
public void parseResponseData_invalidWithWrongResLength_throwsException() {
byte[] data = convertHexStringToBytes(GSM_SECURITY_CONTEXT_RESPONSE_INVALID_RES_LENGTH);
String encodedData = Base64.encodeToString(data, Base64.NO_WRAP).trim();
assertThrows(
ServiceEntitlementException.class, () -> EapAkaSecurityContext.from(encodedData));
}
@Test
public void parseResponseData_invalidWithWrongCkLength_throwsException() {
byte[] data = convertHexStringToBytes(GSM_SECURITY_CONTEXT_RESPONSE_INVALID_CK_LENGTH);
String encodedData = Base64.encodeToString(data, Base64.NO_WRAP).trim();
assertThrows(
ServiceEntitlementException.class, () -> EapAkaSecurityContext.from(encodedData));
}
@Test
public void parseResponseData_invalidWithWrongIkLength_throwsException() {
byte[] data = convertHexStringToBytes(GSM_SECURITY_CONTEXT_RESPONSE_INVALID_IK_LENGTH);
String encodedData = Base64.encodeToString(data, Base64.NO_WRAP).trim();
assertThrows(
ServiceEntitlementException.class, () -> EapAkaSecurityContext.from(encodedData));
}
@Test
public void parseResponseData_validWithWrongKcLength() throws Exception {
// Because we don't parse KC, invalid KC length doesn't hurt
byte[] data = convertHexStringToBytes(GSM_SECURITY_CONTEXT_RESPONSE_INVALID_KC_LENGTH);
String encodedData = Base64.encodeToString(data, Base64.NO_WRAP).trim();
EapAkaSecurityContext securityContext = EapAkaSecurityContext.from(encodedData);
assertThat(securityContext.getIk()).isEqualTo(convertHexStringToBytes(EXPECTED_IK));
assertThat(securityContext.getCk()).isEqualTo(convertHexStringToBytes(EXPECTED_CK));
assertThat(securityContext.getRes()).isEqualTo(convertHexStringToBytes(EXPECTED_RES));
}
@Test
public void parseResponseData_noKcKey() throws Exception {
byte[] data = convertHexStringToBytes(GSM_SECURITY_CONTEXT_RESPONSE_NO_KC_KEY);
String encodedData = Base64.encodeToString(data, Base64.NO_WRAP).trim();
EapAkaSecurityContext securityContext = EapAkaSecurityContext.from(encodedData);
assertThat(securityContext.getIk()).isEqualTo(convertHexStringToBytes(EXPECTED_IK));
assertThat(securityContext.getCk()).isEqualTo(convertHexStringToBytes(EXPECTED_CK));
assertThat(securityContext.getRes()).isEqualTo(convertHexStringToBytes(EXPECTED_RES));
}
@Test
public void parseResponseData_syncFailure() throws Exception {
EapAkaSecurityContext securityContext = EapAkaSecurityContext.from(RESPONSE_SYNC_FAILURE);
assertThat(securityContext.getAuts()).isEqualTo(convertHexStringToBytes(EXPECTED_AUTS));
assertThat(securityContext.getRes()).isNull();
assertThat(securityContext.getCk()).isNull();
assertThat(securityContext.getIk()).isNull();
}
private byte[] convertHexStringToBytes(String input) {
return BaseEncoding.base16().decode(input);
}
}