/*
 * Copyright (C) 2019 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.internal.net.eap.test;

import static com.android.internal.net.TestUtils.hexStringToByteArray;
import static com.android.internal.net.eap.test.message.EapTestMessageDefinitions.EAP_REQUEST_AKA_IDENTITY_PACKET;

import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;

import android.net.eap.test.EapSessionConfig;

import com.android.internal.net.eap.test.statemachine.EapStateMachine;

import org.junit.Before;
import org.junit.Test;

public class EapMsChapV2Test extends EapMethodEndToEndTest {
    private static final long AUTHENTICATOR_TIMEOUT_MILLIS = 250L;

    private static final String USERNAME = "User";
    private static final String PASSWORD = "clientPass";

    private static final byte[] PEER_CHALLENGE =
            hexStringToByteArray("21402324255E262A28295F2B3A337C7E");
    private static final byte[] MSK =
            hexStringToByteArray(
                    "D5F0E9521E3EA9589645E86051C822268B7CDC149B993A1BA118CB153F56DCCB"
                            + "0000000000000000000000000000000000000000000000000000000000000000");
    private static final int EMSK_LEN = 64;
    private static final byte[] EMSK = new byte[EMSK_LEN];

    // Server-Name = hex("authenticator@android.net")
    private static final byte[] EAP_MSCHAP_V2_CHALLENGE_REQUEST =
            hexStringToByteArray("01110033" // EAP-Request | ID | length in bytes
                    + "1A0142" // EAP-MSCHAPv2 | Request | MSCHAPv2 ID
                    + "002E10" // MS length | Value Size (0x10)
                    + "5B5D7C7D7B3F2F3E3C2C602132262628" // Authenticator-Challenge
                    + "61757468656E74696361746F7240616E64726F69642E6E6574"); // Server-Name
    private static final byte[] EAP_MSCHAP_V2_CHALLENGE_RESPONSE =
            hexStringToByteArray("0211003F" // EAP-Response | ID | length in bytes
                    + "1A0242" // EAP-MSCHAPv2 | Response | MSCHAPv2 ID
                    + "003A31" // MS length | Value Size (0x31)
                    + "21402324255E262A28295F2B3A337C7E" // Peer-Challenge
                    + "0000000000000000" // 8B (reserved)
                    + "82309ECD8D708B5EA08FAA3981CD83544233114A3D85D6DF" // NT-Response
                    + "00" // Flags
                    + "55736572"); // hex(USERNAME)
    private static final byte[] EAP_MSCHAP_V2_SUCCESS_REQUEST =
            hexStringToByteArray("01120047" // EAP-Request | ID | length in bytes
                    + "1A03420042" // EAP-MSCHAPv2 | Success | MSCHAPv2 ID | MS length
                    + "533D" // hex("S=")
                    + "3430374135353839313135464430443632303946"
                            + "3531304645394330343536363933324344413536" // hex("<auth_string>")
                    + "204D3D" // hex(" M=")
                            + "7465737420416E64726F69642031323334"); // hex("test Android 1234")
    private static final byte[] EAP_MSCHAP_V2_SUCCESS_RESPONSE =
            hexStringToByteArray("02120006" // EAP-Response | ID | length in bytes
                    + "1A03"); // EAP-MSCHAPv2 | Success
    private static final byte[] EAP_MSCHAP_V2_FAILURE_REQUEST =
            hexStringToByteArray("01130049" // EAP-Request | ID | length in bytes
                    + "1A04420044" // EAP-MSCHAPv2 | Failure | MSCHAPv2 ID | MS length
                    + "453D363437" // hex("E=647")
                    + "20523D31" // hex(" R=1")
                    + "20433D" // hex(" C=")
                            + "30303031303230333034303530363037"
                            + "30383039304130423043304430453046" // hex("<authenticator challenge>")
                    + "20563D33" // hex(" V=3")
                    + "204D3D" // hex(" M=")
                    + "7465737420416E64726F69642031323334"); // hex("test Android 1234")
    private static final byte[] EAP_MSCHAP_V2_FAILURE_RESPONSE =
            hexStringToByteArray("02130006" // EAP-Response | ID | length in bytes
                    + "1A04"); // EAP-MSCHAPv2 | Failure

    private static final byte[] EAP_RESPONSE_NAK_PACKET = hexStringToByteArray("02100006031A");

    @Before
    @Override
    public void setUp() {
        super.setUp();

        mEapSessionConfig =
                new EapSessionConfig.Builder().setEapMsChapV2Config(USERNAME, PASSWORD).build();
        mEapAuthenticator =
                new EapAuthenticator(
                        mTestLooper.getLooper(),
                        mMockCallback,
                        new EapStateMachine(mMockContext, mEapSessionConfig, mMockSecureRandom),
                        (runnable) -> runnable.run(),
                        AUTHENTICATOR_TIMEOUT_MILLIS);
    }

    @Test
    public void testEapMsChapV2EndToEndSuccess() {
        verifyEapMsChapV2Challenge();
        verifyEapMsChapV2SuccessRequest();
        verifyEapSuccess(MSK, EMSK);
    }

    @Test
    public void testEapMsChapV2EndToEndFailure() {
        verifyEapMsChapV2Challenge();
        verifyEapMsChapV2FailureRequest();
        verifyEapFailure();
    }

    @Test
    public void testEapMsChapV2UnsupportedType() {
        verifyUnsupportedType(EAP_REQUEST_AKA_IDENTITY_PACKET, EAP_RESPONSE_NAK_PACKET);

        verifyEapMsChapV2Challenge();
        verifyEapMsChapV2SuccessRequest();
        verifyEapSuccess(MSK, EMSK);
    }

    @Test
    public void verifyEapMsChapV2WithEapNotifications() {
        verifyEapNotification(1);

        verifyEapMsChapV2Challenge();
        verifyEapNotification(2);

        verifyEapMsChapV2SuccessRequest();
        verifyEapNotification(3);

        verifyEapSuccess(MSK, EMSK);
    }

    private void verifyEapMsChapV2Challenge() {
        doAnswer(invocation -> {
            byte[] dst = invocation.getArgument(0);
            System.arraycopy(PEER_CHALLENGE, 0, dst, 0, PEER_CHALLENGE.length);
            return null;
        }).when(mMockSecureRandom).nextBytes(eq(new byte[PEER_CHALLENGE.length]));

        mEapAuthenticator.processEapMessage(EAP_MSCHAP_V2_CHALLENGE_REQUEST);
        mTestLooper.dispatchAll();

        verify(mMockCallback).onResponse(eq(EAP_MSCHAP_V2_CHALLENGE_RESPONSE));
        verify(mMockSecureRandom).nextBytes(any(byte[].class));
        verifyNoMoreInteractions(mMockCallback);
    }

    private void verifyEapMsChapV2SuccessRequest() {
        mEapAuthenticator.processEapMessage(EAP_MSCHAP_V2_SUCCESS_REQUEST);
        mTestLooper.dispatchAll();

        verify(mMockCallback).onResponse(eq(EAP_MSCHAP_V2_SUCCESS_RESPONSE));
        verifyNoMoreInteractions(mMockCallback);
    }

    private void verifyEapMsChapV2FailureRequest() {
        mEapAuthenticator.processEapMessage(EAP_MSCHAP_V2_FAILURE_REQUEST);
        mTestLooper.dispatchAll();

        verify(mMockCallback).onResponse(eq(EAP_MSCHAP_V2_FAILURE_RESPONSE));
        verifyNoMoreInteractions(mMockCallback);
    }
}
