/*
 * Copyright (C) 2018 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.ipsec.ike.message;

import static android.net.ipsec.ike.IkeManager.getIkeLog;
import static android.net.ipsec.ike.SaProposal.DhGroup;
import static android.net.ipsec.ike.SaProposal.EncryptionAlgorithm;
import static android.net.ipsec.ike.SaProposal.IntegrityAlgorithm;
import static android.net.ipsec.ike.SaProposal.PseudorandomFunction;

import android.annotation.IntDef;
import android.annotation.NonNull;
import android.net.IpSecManager.ResourceUnavailableException;
import android.net.IpSecManager.SecurityParameterIndex;
import android.net.IpSecManager.SpiUnavailableException;
import android.net.ipsec.ike.ChildSaProposal;
import android.net.ipsec.ike.IkeSaProposal;
import android.net.ipsec.ike.SaProposal;
import android.net.ipsec.ike.exceptions.IkeProtocolException;
import android.util.ArraySet;
import android.util.Pair;

import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.net.ipsec.ike.exceptions.InvalidSyntaxException;
import com.android.internal.net.ipsec.ike.exceptions.NoValidProposalChosenException;
import com.android.internal.net.ipsec.ike.utils.IkeSecurityParameterIndex;
import com.android.internal.net.ipsec.ike.utils.IkeSpiGenerator;
import com.android.internal.net.ipsec.ike.utils.IpSecSpiGenerator;

import java.io.IOException;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.net.InetAddress;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Objects;
import java.util.Set;

/**
 * IkeSaPayload represents a Security Association payload. It contains one or more {@link Proposal}.
 *
 * @see <a href="https://tools.ietf.org/html/rfc7296#section-3.3">RFC 7296, Internet Key Exchange
 *     Protocol Version 2 (IKEv2)</a>
 */
public final class IkeSaPayload extends IkePayload {
    private static final String TAG = "IkeSaPayload";

    public final boolean isSaResponse;
    public final List<Proposal> proposalList;
    /**
     * Construct an instance of IkeSaPayload for decoding an inbound packet.
     *
     * @param critical indicates if this payload is critical. Ignored in supported payload as
     *     instructed by the RFC 7296.
     * @param isResp indicates if this payload is in a response message.
     * @param payloadBody the encoded payload body in byte array.
     */
    IkeSaPayload(boolean critical, boolean isResp, byte[] payloadBody) throws IkeProtocolException {
        super(IkePayload.PAYLOAD_TYPE_SA, critical);

        ByteBuffer inputBuffer = ByteBuffer.wrap(payloadBody);
        proposalList = new LinkedList<>();
        while (inputBuffer.hasRemaining()) {
            Proposal proposal = Proposal.readFrom(inputBuffer);
            proposalList.add(proposal);
        }

        if (proposalList.isEmpty()) {
            throw new InvalidSyntaxException("Found no SA Proposal in this SA Payload.");
        }

        // An SA response must have exactly one SA proposal.
        if (isResp && proposalList.size() != 1) {
            throw new InvalidSyntaxException(
                    "Expected only one negotiated proposal from SA response: "
                            + "Multiple negotiated proposals found.");
        }
        isSaResponse = isResp;

        boolean firstIsIkeProposal = (proposalList.get(0).protocolId == PROTOCOL_ID_IKE);
        for (int i = 1; i < proposalList.size(); i++) {
            boolean isIkeProposal = (proposalList.get(i).protocolId == PROTOCOL_ID_IKE);
            if (firstIsIkeProposal != isIkeProposal) {
                getIkeLog()
                        .w(TAG, "Found both IKE proposals and Child proposals in this SA Payload.");
                break;
            }
        }

        getIkeLog().d(TAG, "Receive " + toString());
    }

    /** Package private constructor for building a request for IKE SA initial creation or rekey */
    @VisibleForTesting
    IkeSaPayload(
            boolean isResp,
            byte spiSize,
            IkeSaProposal[] saProposals,
            IkeSpiGenerator ikeSpiGenerator,
            InetAddress localAddress)
            throws IOException {
        this(isResp, spiSize, localAddress);

        if (saProposals.length < 1 || isResp && (saProposals.length > 1)) {
            throw new IllegalArgumentException("Invalid SA payload.");
        }

        for (int i = 0; i < saProposals.length; i++) {
            // Proposal number must start from 1.
            proposalList.add(
                    IkeProposal.createIkeProposal(
                            (byte) (i + 1) /* number */,
                            spiSize,
                            saProposals[i],
                            ikeSpiGenerator,
                            localAddress));
        }

        getIkeLog().d(TAG, "Generate " + toString());
    }

    /** Package private constructor for building an response SA Payload for IKE SA rekeys. */
    @VisibleForTesting
    IkeSaPayload(
            boolean isResp,
            byte spiSize,
            byte proposalNumber,
            IkeSaProposal saProposal,
            IkeSpiGenerator ikeSpiGenerator,
            InetAddress localAddress)
            throws IOException {
        this(isResp, spiSize, localAddress);

        proposalList.add(
                IkeProposal.createIkeProposal(
                        proposalNumber /* number */,
                        spiSize,
                        saProposal,
                        ikeSpiGenerator,
                        localAddress));

        getIkeLog().d(TAG, "Generate " + toString());
    }

    private IkeSaPayload(boolean isResp, byte spiSize, InetAddress localAddress)
            throws IOException {
        super(IkePayload.PAYLOAD_TYPE_SA, false);

        // TODO: Check that proposals.length <= 255 in IkeSessionParams and ChildSessionParams
        isSaResponse = isResp;

        // TODO: Allocate IKE SPI and pass to IkeProposal.createIkeProposal()

        // ProposalList populated in other constructors
        proposalList = new ArrayList<Proposal>();
    }

    /**
     * Package private constructor for building an outbound request SA Payload for Child SA
     * negotiation.
     */
    @VisibleForTesting
    IkeSaPayload(
            ChildSaProposal[] saProposals,
            IpSecSpiGenerator ipSecSpiGenerator,
            InetAddress localAddress)
            throws SpiUnavailableException, ResourceUnavailableException {
        this(false /* isResp */, ipSecSpiGenerator, localAddress);

        if (saProposals.length < 1) {
            throw new IllegalArgumentException("Invalid SA payload.");
        }

        // TODO: Check that saProposals.length <= 255 in IkeSessionParams and ChildSessionParams

        for (int i = 0; i < saProposals.length; i++) {
            // Proposal number must start from 1.
            proposalList.add(
                    ChildProposal.createChildProposal(
                            (byte) (i + 1) /* number */,
                            saProposals[i],
                            ipSecSpiGenerator,
                            localAddress));
        }

        getIkeLog().d(TAG, "Generate " + toString());
    }

    /**
     * Package private constructor for building an outbound response SA Payload for Child SA
     * negotiation.
     */
    @VisibleForTesting
    IkeSaPayload(
            byte proposalNumber,
            ChildSaProposal saProposal,
            IpSecSpiGenerator ipSecSpiGenerator,
            InetAddress localAddress)
            throws SpiUnavailableException, ResourceUnavailableException {
        this(true /* isResp */, ipSecSpiGenerator, localAddress);

        proposalList.add(
                ChildProposal.createChildProposal(
                        proposalNumber /* number */, saProposal, ipSecSpiGenerator, localAddress));

        getIkeLog().d(TAG, "Generate " + toString());
    }

    /** Constructor for building an outbound SA Payload for Child SA negotiation. */
    private IkeSaPayload(
            boolean isResp, IpSecSpiGenerator ipSecSpiGenerator, InetAddress localAddress) {
        super(IkePayload.PAYLOAD_TYPE_SA, false);

        isSaResponse = isResp;

        // TODO: Allocate Child SPI and pass to ChildProposal.createChildProposal()

        // ProposalList populated in other constructors
        proposalList = new ArrayList<Proposal>();
    }

    /**
     * Construct an instance of IkeSaPayload for building an outbound IKE initial setup request.
     *
     * <p>According to RFC 7296, for an initial IKE SA negotiation, no SPI is included in SA
     * Proposal. IKE library, as a client, only supports requesting this initial negotiation.
     *
     * @param saProposals the array of all SA Proposals.
     */
    public static IkeSaPayload createInitialIkeSaPayload(IkeSaProposal[] saProposals)
            throws IOException {
        return new IkeSaPayload(
                false /* isResp */,
                SPI_LEN_NOT_INCLUDED,
                saProposals,
                null /* ikeSpiGenerator unused */,
                null /* localAddress unused */);
    }

    /**
     * Construct an instance of IkeSaPayload for building an outbound request for Rekey IKE.
     *
     * @param saProposals the array of all IKE SA Proposals.
     * @param ikeSpiGenerator the IKE SPI generator.
     * @param localAddress the local address assigned on-device.
     */
    public static IkeSaPayload createRekeyIkeSaRequestPayload(
            IkeSaProposal[] saProposals, IkeSpiGenerator ikeSpiGenerator, InetAddress localAddress)
            throws IOException {
        return new IkeSaPayload(
                false /* isResp */, SPI_LEN_IKE, saProposals, ikeSpiGenerator, localAddress);
    }

    /**
     * Construct an instance of IkeSaPayload for building an outbound response for Rekey IKE.
     *
     * @param respProposalNumber the selected proposal's number.
     * @param saProposal the expected selected IKE SA Proposal.
     * @param ikeSpiGenerator the IKE SPI generator.
     * @param localAddress the local address assigned on-device.
     */
    public static IkeSaPayload createRekeyIkeSaResponsePayload(
            byte respProposalNumber,
            IkeSaProposal saProposal,
            IkeSpiGenerator ikeSpiGenerator,
            InetAddress localAddress)
            throws IOException {
        return new IkeSaPayload(
                true /* isResp */,
                SPI_LEN_IKE,
                respProposalNumber,
                saProposal,
                ikeSpiGenerator,
                localAddress);
    }

    /**
     * Construct an instance of IkeSaPayload for building an outbound request for Child SA
     * negotiation.
     *
     * @param saProposals the array of all Child SA Proposals.
     * @param ipSecSpiGenerator the IPsec SPI generator.
     * @param localAddress the local address assigned on-device.
     * @throws ResourceUnavailableException if too many SPIs are currently allocated for this user.
     */
    public static IkeSaPayload createChildSaRequestPayload(
            ChildSaProposal[] saProposals,
            IpSecSpiGenerator ipSecSpiGenerator,
            InetAddress localAddress)
            throws SpiUnavailableException, ResourceUnavailableException {

        return new IkeSaPayload(saProposals, ipSecSpiGenerator, localAddress);
    }

    /**
     * Construct an instance of IkeSaPayload for building an outbound response for Child SA
     * negotiation.
     *
     * @param respProposalNumber the selected proposal's number.
     * @param saProposal the expected selected Child SA Proposal.
     * @param ipSecSpiGenerator the IPsec SPI generator.
     * @param localAddress the local address assigned on-device.
     */
    public static IkeSaPayload createChildSaResponsePayload(
            byte respProposalNumber,
            ChildSaProposal saProposal,
            IpSecSpiGenerator ipSecSpiGenerator,
            InetAddress localAddress)
            throws SpiUnavailableException, ResourceUnavailableException {
        return new IkeSaPayload(respProposalNumber, saProposal, ipSecSpiGenerator, localAddress);
    }

    /**
     * Finds the proposal in this (request) payload that matches the response proposal.
     *
     * @param respProposal the Proposal to match against.
     * @return the byte-value proposal number of the selected proposal
     * @throws NoValidProposalChosenException if no matching proposal was found.
     */
    public byte getNegotiatedProposalNumber(SaProposal respProposal)
            throws NoValidProposalChosenException {
        for (int i = 0; i < proposalList.size(); i++) {
            Proposal reqProposal = proposalList.get(i);
            if (respProposal.isNegotiatedFrom(reqProposal.getSaProposal())
                    && reqProposal.getSaProposal().getProtocolId()
                            == respProposal.getProtocolId()) {
                return reqProposal.number;
            }
        }
        throw new NoValidProposalChosenException("No remotely proposed protocol acceptable");
    }

    /**
     * Validate the IKE SA Payload pair (request/response) and return the IKE SA negotiation result.
     *
     * <p>Caller is able to extract the negotiated IKE SA Proposal from the response Proposal and
     * the IKE SPI pair generated by both sides.
     *
     * <p>In a locally-initiated case all IKE SA proposals (from users in initial creation or from
     * previously negotiated proposal in rekey creation) in the locally generated reqSaPayload have
     * been validated during building and are unmodified. All Transform combinations in these SA
     * proposals are valid for IKE SA negotiation. It means each IKE SA request proposal MUST have
     * Encryption algorithms, DH group configurations and PRFs. Integrity algorithms can only be
     * omitted when AEAD is used.
     *
     * <p>In a remotely-initiated case the locally generated respSaPayload has exactly one SA
     * proposal. It is validated during building and are unmodified. This proposal has a valid
     * Transform combination for an IKE SA and has at most one value for each Transform type.
     *
     * <p>The response IKE SA proposal is validated against one of the request IKE SA proposals. It
     * is guaranteed that for each Transform type that the request proposal has provided options,
     * the response proposal has exact one Transform value.
     *
     * @param reqSaPayload the request payload.
     * @param respSaPayload the response payload.
     * @param remoteAddress the address of the remote IKE peer.
     * @return the Pair of selected IkeProposal in request and the IkeProposal in response.
     * @throws NoValidProposalChosenException if the response SA Payload cannot be negotiated from
     *     the request SA Payload.
     */
    public static Pair<IkeProposal, IkeProposal> getVerifiedNegotiatedIkeProposalPair(
            IkeSaPayload reqSaPayload,
            IkeSaPayload respSaPayload,
            IkeSpiGenerator ikeSpiGenerator,
            InetAddress remoteAddress)
            throws NoValidProposalChosenException, IOException {
        Pair<Proposal, Proposal> proposalPair =
                getVerifiedNegotiatedProposalPair(reqSaPayload, respSaPayload);
        IkeProposal reqProposal = (IkeProposal) proposalPair.first;
        IkeProposal respProposal = (IkeProposal) proposalPair.second;

        try {
            // Allocate initiator's inbound SPI as needed for remotely initiated IKE SA creation
            if (reqProposal.spiSize != SPI_NOT_INCLUDED
                    && reqProposal.getIkeSpiResource() == null) {
                reqProposal.allocateResourceForRemoteIkeSpi(ikeSpiGenerator, remoteAddress);
            }
            // Allocate responder's inbound SPI as needed for locally initiated IKE SA creation
            if (respProposal.spiSize != SPI_NOT_INCLUDED
                    && respProposal.getIkeSpiResource() == null) {
                respProposal.allocateResourceForRemoteIkeSpi(ikeSpiGenerator, remoteAddress);
            }

            return new Pair(reqProposal, respProposal);
        } catch (Exception e) {
            reqProposal.releaseSpiResourceIfExists();
            respProposal.releaseSpiResourceIfExists();
            throw e;
        }
    }

    /**
     * Validate the SA Payload pair (request/response) and return the Child SA negotiation result.
     *
     * <p>Caller is able to extract the negotiated SA Proposal from the response Proposal and the
     * IPsec SPI pair generated by both sides.
     *
     * <p>In a locally-initiated case all Child SA proposals (from users in initial creation or from
     * previously negotiated proposal in rekey creation) in the locally generated reqSaPayload have
     * been validated during building and are unmodified. All Transform combinations in these SA
     * proposals are valid for Child SA negotiation. It means each request SA proposal MUST have
     * Encryption algorithms and ESN configurations.
     *
     * <p>In a remotely-initiated case the locally generated respSapayload has exactly one SA
     * proposal. It is validated during building and are unmodified. This proposal has a valid
     * Transform combination for an Child SA and has at most one value for each Transform type.
     *
     * <p>The response Child SA proposal is validated against one of the request SA proposals. It is
     * guaranteed that for each Transform type that the request proposal has provided options, the
     * response proposal has exact one Transform value.
     *
     * @param reqSaPayload the request payload.
     * @param respSaPayload the response payload.
     * @param ipSecSpiGenerator the SPI generator to allocate SPI resource for the Proposal in this
     *     inbound SA Payload.
     * @param remoteAddress the address of the remote IKE peer.
     * @return the Pair of selected ChildProposal in the locally generated request and the
     *     ChildProposal in this response.
     * @throws NoValidProposalChosenException if the response SA Payload cannot be negotiated from
     *     the request SA Payload.
     * @throws ResourceUnavailableException if too many SPIs are currently allocated for this user.
     * @throws SpiUnavailableException if the remotely generated SPI is in use.
     */
    public static Pair<ChildProposal, ChildProposal> getVerifiedNegotiatedChildProposalPair(
            IkeSaPayload reqSaPayload,
            IkeSaPayload respSaPayload,
            IpSecSpiGenerator ipSecSpiGenerator,
            InetAddress remoteAddress)
            throws NoValidProposalChosenException, ResourceUnavailableException,
                    SpiUnavailableException {
        Pair<Proposal, Proposal> proposalPair =
                getVerifiedNegotiatedProposalPair(reqSaPayload, respSaPayload);
        ChildProposal reqProposal = (ChildProposal) proposalPair.first;
        ChildProposal respProposal = (ChildProposal) proposalPair.second;

        try {
            // Allocate initiator's inbound SPI as needed for remotely initiated Child SA creation
            if (reqProposal.getChildSpiResource() == null) {
                reqProposal.allocateResourceForRemoteChildSpi(ipSecSpiGenerator, remoteAddress);
            }
            // Allocate responder's inbound SPI as needed for locally initiated Child SA creation
            if (respProposal.getChildSpiResource() == null) {
                respProposal.allocateResourceForRemoteChildSpi(ipSecSpiGenerator, remoteAddress);
            }

            return new Pair(reqProposal, respProposal);
        } catch (Exception e) {
            reqProposal.releaseSpiResourceIfExists();
            respProposal.releaseSpiResourceIfExists();
            throw e;
        }
    }

    private static Pair<Proposal, Proposal> getVerifiedNegotiatedProposalPair(
            IkeSaPayload reqSaPayload, IkeSaPayload respSaPayload)
            throws NoValidProposalChosenException {
        try {
            // If negotiated proposal has an unrecognized Transform, throw an exception.
            Proposal respProposal = respSaPayload.proposalList.get(0);
            if (respProposal.hasUnrecognizedTransform) {
                throw new NoValidProposalChosenException(
                        "Negotiated proposal has unrecognized Transform.");
            }

            // In SA request payload, the first proposal MUST be 1, and subsequent proposals MUST be
            // one more than the previous proposal. In SA response payload, the negotiated proposal
            // number MUST match the selected proposal number in SA request Payload.
            int negotiatedProposalNum = respProposal.number;
            List<Proposal> reqProposalList = reqSaPayload.proposalList;
            if (negotiatedProposalNum < 1 || negotiatedProposalNum > reqProposalList.size()) {
                throw new NoValidProposalChosenException(
                        "Negotiated proposal has invalid proposal number.");
            }

            Proposal reqProposal = reqProposalList.get(negotiatedProposalNum - 1);
            if (!respProposal.isNegotiatedFrom(reqProposal)) {
                throw new NoValidProposalChosenException("Invalid negotiated proposal.");
            }

            // In a locally-initiated creation, release locally generated SPIs in unselected request
            // Proposals. In remotely-initiated SA creation, unused proposals do not have SPIs, and
            // will silently succeed.
            for (Proposal p : reqProposalList) {
                if (reqProposal != p) p.releaseSpiResourceIfExists();
            }

            return new Pair<Proposal, Proposal>(reqProposal, respProposal);
        } catch (Exception e) {
            // In a locally-initiated case, release all locally generated SPIs in the SA request
            // payload.
            for (Proposal p : reqSaPayload.proposalList) p.releaseSpiResourceIfExists();
            throw e;
        }
    }

    @VisibleForTesting
    interface TransformDecoder {
        Transform[] decodeTransforms(int count, ByteBuffer inputBuffer) throws IkeProtocolException;
    }

    // TODO: Add another constructor for building outbound message.

    /**
     * This class represents the common information of an IKE Proposal and a Child Proposal.
     *
     * <p>Proposal represents a set contains cryptographic algorithms and key generating materials.
     * It contains multiple {@link Transform}.
     *
     * @see <a href="https://tools.ietf.org/html/rfc7296#section-3.3.1">RFC 7296, Internet Key
     *     Exchange Protocol Version 2 (IKEv2)</a>
     *     <p>Proposals with an unrecognized Protocol ID, containing an unrecognized Transform Type
     *     or lacking a necessary Transform Type shall be ignored when processing a received SA
     *     Payload.
     */
    public abstract static class Proposal {
        private static final byte LAST_PROPOSAL = 0;
        private static final byte NOT_LAST_PROPOSAL = 2;

        private static final int PROPOSAL_RESERVED_FIELD_LEN = 1;
        private static final int PROPOSAL_HEADER_LEN = 8;

        @VisibleForTesting
        static TransformDecoder sTransformDecoder =
                new TransformDecoder() {
                    @Override
                    public Transform[] decodeTransforms(int count, ByteBuffer inputBuffer)
                            throws IkeProtocolException {
                        Transform[] transformArray = new Transform[count];
                        for (int i = 0; i < count; i++) {
                            Transform transform = Transform.readFrom(inputBuffer);
                            if (transform.isSupported) {
                                transformArray[i] = transform;
                            }
                        }
                        return transformArray;
                    }
                };

        public final byte number;
        /** All supported protocol will fall into {@link ProtocolId} */
        public final int protocolId;

        public final byte spiSize;
        public final long spi;

        public final boolean hasUnrecognizedTransform;

        @VisibleForTesting
        Proposal(
                byte number,
                int protocolId,
                byte spiSize,
                long spi,
                boolean hasUnrecognizedTransform) {
            this.number = number;
            this.protocolId = protocolId;
            this.spiSize = spiSize;
            this.spi = spi;
            this.hasUnrecognizedTransform = hasUnrecognizedTransform;
        }

        @VisibleForTesting
        static Proposal readFrom(ByteBuffer inputBuffer) throws IkeProtocolException {
            byte isLast = inputBuffer.get();
            if (isLast != LAST_PROPOSAL && isLast != NOT_LAST_PROPOSAL) {
                throw new InvalidSyntaxException(
                        "Invalid value of Last Proposal Substructure: " + isLast);
            }
            // Skip RESERVED byte
            inputBuffer.get(new byte[PROPOSAL_RESERVED_FIELD_LEN]);

            int length = Short.toUnsignedInt(inputBuffer.getShort());
            byte number = inputBuffer.get();
            int protocolId = Byte.toUnsignedInt(inputBuffer.get());

            byte spiSize = inputBuffer.get();
            int transformCount = Byte.toUnsignedInt(inputBuffer.get());

            // TODO: Add check: spiSize must be 0 in initial IKE SA negotiation
            // spiSize should be either 8 for IKE or 4 for IPsec.
            long spi = SPI_NOT_INCLUDED;
            switch (spiSize) {
                case SPI_LEN_NOT_INCLUDED:
                    // No SPI attached for IKE initial exchange.
                    break;
                case SPI_LEN_IPSEC:
                    spi = Integer.toUnsignedLong(inputBuffer.getInt());
                    break;
                case SPI_LEN_IKE:
                    spi = inputBuffer.getLong();
                    break;
                default:
                    throw new InvalidSyntaxException(
                            "Invalid value of spiSize in Proposal Substructure: " + spiSize);
            }

            Transform[] transformArray =
                    sTransformDecoder.decodeTransforms(transformCount, inputBuffer);
            // TODO: Validate that sum of all Transforms' lengths plus Proposal header length equals
            // to Proposal's length.

            List<EncryptionTransform> encryptAlgoList = new LinkedList<>();
            List<PrfTransform> prfList = new LinkedList<>();
            List<IntegrityTransform> integAlgoList = new LinkedList<>();
            List<DhGroupTransform> dhGroupList = new LinkedList<>();
            List<EsnTransform> esnList = new LinkedList<>();

            boolean hasUnrecognizedTransform = false;

            for (Transform transform : transformArray) {
                switch (transform.type) {
                    case Transform.TRANSFORM_TYPE_ENCR:
                        encryptAlgoList.add((EncryptionTransform) transform);
                        break;
                    case Transform.TRANSFORM_TYPE_PRF:
                        prfList.add((PrfTransform) transform);
                        break;
                    case Transform.TRANSFORM_TYPE_INTEG:
                        integAlgoList.add((IntegrityTransform) transform);
                        break;
                    case Transform.TRANSFORM_TYPE_DH:
                        dhGroupList.add((DhGroupTransform) transform);
                        break;
                    case Transform.TRANSFORM_TYPE_ESN:
                        esnList.add((EsnTransform) transform);
                        break;
                    default:
                        hasUnrecognizedTransform = true;
                }
            }

            if (protocolId == PROTOCOL_ID_IKE) {
                IkeSaProposal saProposal =
                        new IkeSaProposal(
                                encryptAlgoList.toArray(
                                        new EncryptionTransform[encryptAlgoList.size()]),
                                prfList.toArray(new PrfTransform[prfList.size()]),
                                integAlgoList.toArray(new IntegrityTransform[integAlgoList.size()]),
                                dhGroupList.toArray(new DhGroupTransform[dhGroupList.size()]));
                return new IkeProposal(number, spiSize, spi, saProposal, hasUnrecognizedTransform);
            } else {
                ChildSaProposal saProposal =
                        new ChildSaProposal(
                                encryptAlgoList.toArray(
                                        new EncryptionTransform[encryptAlgoList.size()]),
                                integAlgoList.toArray(new IntegrityTransform[integAlgoList.size()]),
                                dhGroupList.toArray(new DhGroupTransform[dhGroupList.size()]),
                                esnList.toArray(new EsnTransform[esnList.size()]));
                return new ChildProposal(number, spi, saProposal, hasUnrecognizedTransform);
            }
        }

        /** Package private */
        boolean isNegotiatedFrom(Proposal reqProposal) {
            if (protocolId != reqProposal.protocolId || number != reqProposal.number) {
                return false;
            }
            return getSaProposal().isNegotiatedFrom(reqProposal.getSaProposal());
        }

        protected void encodeToByteBuffer(boolean isLast, ByteBuffer byteBuffer) {
            Transform[] allTransforms = getSaProposal().getAllTransforms();
            byte isLastIndicator = isLast ? LAST_PROPOSAL : NOT_LAST_PROPOSAL;

            byteBuffer
                    .put(isLastIndicator)
                    .put(new byte[PROPOSAL_RESERVED_FIELD_LEN])
                    .putShort((short) getProposalLength())
                    .put(number)
                    .put((byte) protocolId)
                    .put(spiSize)
                    .put((byte) allTransforms.length);

            switch (spiSize) {
                case SPI_LEN_NOT_INCLUDED:
                    // No SPI attached for IKE initial exchange.
                    break;
                case SPI_LEN_IPSEC:
                    byteBuffer.putInt((int) spi);
                    break;
                case SPI_LEN_IKE:
                    byteBuffer.putLong((long) spi);
                    break;
                default:
                    throw new IllegalArgumentException(
                            "Invalid value of spiSize in Proposal Substructure: " + spiSize);
            }

            // Encode all Transform.
            for (int i = 0; i < allTransforms.length; i++) {
                // The last transform has the isLast flag set to true.
                allTransforms[i].encodeToByteBuffer(i == allTransforms.length - 1, byteBuffer);
            }
        }

        protected int getProposalLength() {
            int len = PROPOSAL_HEADER_LEN + spiSize;

            Transform[] allTransforms = getSaProposal().getAllTransforms();
            for (Transform t : allTransforms) len += t.getTransformLength();
            return len;
        }

        @Override
        @NonNull
        public String toString() {
            return "Proposal(" + number + ") " + getSaProposal().toString();
        }

        /** Package private method for releasing SPI resource in this unselected Proposal. */
        abstract void releaseSpiResourceIfExists();

        /** Package private method for getting SaProposal */
        abstract SaProposal getSaProposal();
    }

    /** This class represents a Proposal for IKE SA negotiation. */
    public static final class IkeProposal extends Proposal {
        private IkeSecurityParameterIndex mIkeSpiResource;

        public final IkeSaProposal saProposal;

        /**
         * Construct IkeProposal from a decoded inbound message for IKE negotiation.
         *
         * <p>Package private
         */
        IkeProposal(
                byte number,
                byte spiSize,
                long spi,
                IkeSaProposal saProposal,
                boolean hasUnrecognizedTransform) {
            super(number, PROTOCOL_ID_IKE, spiSize, spi, hasUnrecognizedTransform);
            this.saProposal = saProposal;
        }

        /** Construct IkeProposal for an outbound message for IKE negotiation. */
        private IkeProposal(
                byte number,
                byte spiSize,
                IkeSecurityParameterIndex ikeSpiResource,
                IkeSaProposal saProposal) {
            super(
                    number,
                    PROTOCOL_ID_IKE,
                    spiSize,
                    ikeSpiResource == null ? SPI_NOT_INCLUDED : ikeSpiResource.getSpi(),
                    false /* hasUnrecognizedTransform */);
            mIkeSpiResource = ikeSpiResource;
            this.saProposal = saProposal;
        }

        /**
         * Construct IkeProposal for an outbound message for IKE negotiation.
         *
         * <p>Package private
         */
        @VisibleForTesting
        static IkeProposal createIkeProposal(
                byte number,
                byte spiSize,
                IkeSaProposal saProposal,
                IkeSpiGenerator ikeSpiGenerator,
                InetAddress localAddress)
                throws IOException {
            // IKE_INIT uses SPI_LEN_NOT_INCLUDED, while rekeys use SPI_LEN_IKE
            IkeSecurityParameterIndex spiResource =
                    (spiSize == SPI_LEN_NOT_INCLUDED
                            ? null
                            : ikeSpiGenerator.allocateSpi(localAddress));
            return new IkeProposal(number, spiSize, spiResource, saProposal);
        }

        /** Package private method for releasing SPI resource in this unselected Proposal. */
        void releaseSpiResourceIfExists() {
            // mIkeSpiResource is null when doing IKE initial exchanges.
            if (mIkeSpiResource == null) return;
            mIkeSpiResource.close();
            mIkeSpiResource = null;
        }

        /**
         * Package private method for allocating SPI resource for a validated remotely generated IKE
         * SA proposal.
         */
        void allocateResourceForRemoteIkeSpi(
                IkeSpiGenerator ikeSpiGenerator, InetAddress remoteAddress) throws IOException {
            mIkeSpiResource = ikeSpiGenerator.allocateSpi(remoteAddress, spi);
        }

        @Override
        public SaProposal getSaProposal() {
            return saProposal;
        }

        /**
         * Get the IKE SPI resource.
         *
         * @return the IKE SPI resource or null for IKE initial exchanges.
         */
        public IkeSecurityParameterIndex getIkeSpiResource() {
            return mIkeSpiResource;
        }
    }

    /** This class represents a Proposal for Child SA negotiation. */
    public static final class ChildProposal extends Proposal {
        private SecurityParameterIndex mChildSpiResource;

        public final ChildSaProposal saProposal;

        /**
         * Construct ChildProposal from a decoded inbound message for Child SA negotiation.
         *
         * <p>Package private
         */
        ChildProposal(
                byte number,
                long spi,
                ChildSaProposal saProposal,
                boolean hasUnrecognizedTransform) {
            super(
                    number,
                    PROTOCOL_ID_ESP,
                    SPI_LEN_IPSEC,
                    spi,
                    hasUnrecognizedTransform);
            this.saProposal = saProposal;
        }

        /** Construct ChildProposal for an outbound message for Child SA negotiation. */
        private ChildProposal(
                byte number, SecurityParameterIndex childSpiResource, ChildSaProposal saProposal) {
            super(
                    number,
                    PROTOCOL_ID_ESP,
                    SPI_LEN_IPSEC,
                    (long) childSpiResource.getSpi(),
                    false /* hasUnrecognizedTransform */);
            mChildSpiResource = childSpiResource;
            this.saProposal = saProposal;
        }

        /**
         * Construct ChildProposal for an outbound message for Child SA negotiation.
         *
         * <p>Package private
         */
        @VisibleForTesting
        static ChildProposal createChildProposal(
                byte number,
                ChildSaProposal saProposal,
                IpSecSpiGenerator ipSecSpiGenerator,
                InetAddress localAddress)
                throws SpiUnavailableException, ResourceUnavailableException {
            return new ChildProposal(
                    number, ipSecSpiGenerator.allocateSpi(localAddress), saProposal);
        }

        /** Package private method for releasing SPI resource in this unselected Proposal. */
        void releaseSpiResourceIfExists() {
            if (mChildSpiResource ==  null) return;

            mChildSpiResource.close();
            mChildSpiResource = null;
        }

        /**
         * Package private method for allocating SPI resource for a validated remotely generated
         * Child SA proposal.
         */
        void allocateResourceForRemoteChildSpi(
                IpSecSpiGenerator ipSecSpiGenerator, InetAddress remoteAddress)
                throws ResourceUnavailableException, SpiUnavailableException {
            mChildSpiResource = ipSecSpiGenerator.allocateSpi(remoteAddress, (int) spi);
        }

        @Override
        public SaProposal getSaProposal() {
            return saProposal;
        }

        /**
         * Get the IPsec SPI resource.
         *
         * @return the IPsec SPI resource.
         */
        public SecurityParameterIndex getChildSpiResource() {
            return mChildSpiResource;
        }
    }

    @VisibleForTesting
    interface AttributeDecoder {
        List<Attribute> decodeAttributes(int length, ByteBuffer inputBuffer)
                throws IkeProtocolException;
    }

    /**
     * Transform is an abstract base class that represents the common information for all Transform
     * types. It may contain one or more {@link Attribute}.
     *
     * @see <a href="https://tools.ietf.org/html/rfc7296#section-3.3.2">RFC 7296, Internet Key
     *     Exchange Protocol Version 2 (IKEv2)</a>
     *     <p>Transforms with unrecognized Transform ID or containing unrecognized Attribute Type
     *     shall be ignored when processing received SA payload.
     */
    public abstract static class Transform {

        @Retention(RetentionPolicy.SOURCE)
        @IntDef({
            TRANSFORM_TYPE_ENCR,
            TRANSFORM_TYPE_PRF,
            TRANSFORM_TYPE_INTEG,
            TRANSFORM_TYPE_DH,
            TRANSFORM_TYPE_ESN
        })
        public @interface TransformType {}

        public static final int TRANSFORM_TYPE_ENCR = 1;
        public static final int TRANSFORM_TYPE_PRF = 2;
        public static final int TRANSFORM_TYPE_INTEG = 3;
        public static final int TRANSFORM_TYPE_DH = 4;
        public static final int TRANSFORM_TYPE_ESN = 5;

        private static final byte LAST_TRANSFORM = 0;
        private static final byte NOT_LAST_TRANSFORM = 3;

        // Length of reserved field of a Transform.
        private static final int TRANSFORM_RESERVED_FIELD_LEN = 1;

        // Length of the Transform that with no Attribute.
        protected static final int BASIC_TRANSFORM_LEN = 8;

        // TODO: Add constants for supported algorithms

        @VisibleForTesting
        static AttributeDecoder sAttributeDecoder =
                new AttributeDecoder() {
                    public List<Attribute> decodeAttributes(int length, ByteBuffer inputBuffer)
                            throws IkeProtocolException {
                        List<Attribute> list = new LinkedList<>();
                        int parsedLength = BASIC_TRANSFORM_LEN;
                        while (parsedLength < length) {
                            Pair<Attribute, Integer> pair = Attribute.readFrom(inputBuffer);
                            parsedLength += pair.second;
                            list.add(pair.first);
                        }
                        // TODO: Validate that parsedLength equals to length.
                        return list;
                    }
                };

        // Only supported type falls into {@link TransformType}
        public final int type;
        public final int id;
        public final boolean isSupported;

        /** Construct an instance of Transform for building an outbound packet. */
        protected Transform(int type, int id) {
            this.type = type;
            this.id = id;
            if (!isSupportedTransformId(id)) {
                throw new IllegalArgumentException(
                        "Unsupported " + getTransformTypeString() + " Algorithm ID: " + id);
            }
            this.isSupported = true;
        }

        /** Construct an instance of Transform for decoding an inbound packet. */
        protected Transform(int type, int id, List<Attribute> attributeList) {
            this.type = type;
            this.id = id;
            this.isSupported =
                    isSupportedTransformId(id) && !hasUnrecognizedAttribute(attributeList);
        }

        @VisibleForTesting
        static Transform readFrom(ByteBuffer inputBuffer) throws IkeProtocolException {
            byte isLast = inputBuffer.get();
            if (isLast != LAST_TRANSFORM && isLast != NOT_LAST_TRANSFORM) {
                throw new InvalidSyntaxException(
                        "Invalid value of Last Transform Substructure: " + isLast);
            }

            // Skip RESERVED byte
            inputBuffer.get(new byte[TRANSFORM_RESERVED_FIELD_LEN]);

            int length = Short.toUnsignedInt(inputBuffer.getShort());
            int type = Byte.toUnsignedInt(inputBuffer.get());

            // Skip RESERVED byte
            inputBuffer.get(new byte[TRANSFORM_RESERVED_FIELD_LEN]);

            int id = Short.toUnsignedInt(inputBuffer.getShort());

            // Decode attributes
            List<Attribute> attributeList = sAttributeDecoder.decodeAttributes(length, inputBuffer);

            validateAttributeUniqueness(attributeList);

            switch (type) {
                case TRANSFORM_TYPE_ENCR:
                    return new EncryptionTransform(id, attributeList);
                case TRANSFORM_TYPE_PRF:
                    return new PrfTransform(id, attributeList);
                case TRANSFORM_TYPE_INTEG:
                    return new IntegrityTransform(id, attributeList);
                case TRANSFORM_TYPE_DH:
                    return new DhGroupTransform(id, attributeList);
                case TRANSFORM_TYPE_ESN:
                    return new EsnTransform(id, attributeList);
                default:
                    return new UnrecognizedTransform(type, id, attributeList);
            }
        }

        // Throw InvalidSyntaxException if there are multiple Attributes of the same type
        private static void validateAttributeUniqueness(List<Attribute> attributeList)
                throws IkeProtocolException {
            Set<Integer> foundTypes = new ArraySet<>();
            for (Attribute attr : attributeList) {
                if (!foundTypes.add(attr.type)) {
                    throw new InvalidSyntaxException(
                            "There are multiple Attributes of the same type. ");
                }
            }
        }

        // Check if there is Attribute with unrecognized type.
        protected abstract boolean hasUnrecognizedAttribute(List<Attribute> attributeList);

        // Check if this Transform ID is supported.
        protected abstract boolean isSupportedTransformId(int id);

        // Encode Transform to a ByteBuffer.
        protected abstract void encodeToByteBuffer(boolean isLast, ByteBuffer byteBuffer);

        // Get entire Transform length.
        protected abstract int getTransformLength();

        protected void encodeBasicTransformToByteBuffer(boolean isLast, ByteBuffer byteBuffer) {
            byte isLastIndicator = isLast ? LAST_TRANSFORM : NOT_LAST_TRANSFORM;
            byteBuffer
                    .put(isLastIndicator)
                    .put(new byte[TRANSFORM_RESERVED_FIELD_LEN])
                    .putShort((short) getTransformLength())
                    .put((byte) type)
                    .put(new byte[TRANSFORM_RESERVED_FIELD_LEN])
                    .putShort((short) id);
        }

        /**
         * Get Tranform Type as a String.
         *
         * @return Tranform Type as a String.
         */
        public abstract String getTransformTypeString();

        // TODO: Add abstract getTransformIdString() to return specific algorithm/dhGroup name
    }

    /**
     * EncryptionTransform represents an encryption algorithm. It may contain an Atrribute
     * specifying the key length.
     *
     * @see <a href="https://tools.ietf.org/html/rfc7296#section-3.3.2">RFC 7296, Internet Key
     *     Exchange Protocol Version 2 (IKEv2)</a>
     */
    public static final class EncryptionTransform extends Transform {
        public static final int KEY_LEN_UNSPECIFIED = 0;

        // When using encryption algorithm with variable-length keys, mSpecifiedKeyLength MUST be
        // set and a KeyLengthAttribute MUST be attached. Otherwise, mSpecifiedKeyLength MUST NOT be
        // set and KeyLengthAttribute MUST NOT be attached.
        private final int mSpecifiedKeyLength;

        /**
         * Contruct an instance of EncryptionTransform with fixed key length for building an
         * outbound packet.
         *
         * @param id the IKE standard Transform ID.
         */
        public EncryptionTransform(@EncryptionAlgorithm int id) {
            this(id, KEY_LEN_UNSPECIFIED);
        }

        /**
         * Contruct an instance of EncryptionTransform with variable key length for building an
         * outbound packet.
         *
         * @param id the IKE standard Transform ID.
         * @param specifiedKeyLength the specified key length of this encryption algorithm.
         */
        public EncryptionTransform(@EncryptionAlgorithm int id, int specifiedKeyLength) {
            super(Transform.TRANSFORM_TYPE_ENCR, id);

            mSpecifiedKeyLength = specifiedKeyLength;
            try {
                validateKeyLength();
            } catch (InvalidSyntaxException e) {
                throw new IllegalArgumentException(e);
            }
        }

        /**
         * Contruct an instance of EncryptionTransform for decoding an inbound packet.
         *
         * @param id the IKE standard Transform ID.
         * @param attributeList the decoded list of Attribute.
         * @throws InvalidSyntaxException for syntax error.
         */
        protected EncryptionTransform(int id, List<Attribute> attributeList)
                throws InvalidSyntaxException {
            super(Transform.TRANSFORM_TYPE_ENCR, id, attributeList);
            if (!isSupported) {
                mSpecifiedKeyLength = KEY_LEN_UNSPECIFIED;
            } else {
                if (attributeList.size() == 0) {
                    mSpecifiedKeyLength = KEY_LEN_UNSPECIFIED;
                } else {
                    KeyLengthAttribute attr = getKeyLengthAttribute(attributeList);
                    mSpecifiedKeyLength = attr.keyLength;
                }
                validateKeyLength();
            }
        }

        /**
         * Get the specified key length.
         *
         * @return the specified key length.
         */
        public int getSpecifiedKeyLength() {
            return mSpecifiedKeyLength;
        }

        @Override
        public int hashCode() {
            return Objects.hash(type, id, mSpecifiedKeyLength);
        }

        @Override
        public boolean equals(Object o) {
            if (!(o instanceof EncryptionTransform)) return false;

            EncryptionTransform other = (EncryptionTransform) o;
            return (type == other.type
                    && id == other.id
                    && mSpecifiedKeyLength == other.mSpecifiedKeyLength);
        }

        @Override
        protected boolean isSupportedTransformId(int id) {
            return SaProposal.isSupportedEncryptionAlgorithm(id);
        }

        @Override
        protected boolean hasUnrecognizedAttribute(List<Attribute> attributeList) {
            for (Attribute attr : attributeList) {
                if (attr instanceof UnrecognizedAttribute) {
                    return true;
                }
            }
            return false;
        }

        private KeyLengthAttribute getKeyLengthAttribute(List<Attribute> attributeList) {
            for (Attribute attr : attributeList) {
                if (attr.type == Attribute.ATTRIBUTE_TYPE_KEY_LENGTH) {
                    return (KeyLengthAttribute) attr;
                }
            }
            throw new IllegalArgumentException("Cannot find Attribute with Key Length type");
        }

        private void validateKeyLength() throws InvalidSyntaxException {
            switch (id) {
                case SaProposal.ENCRYPTION_ALGORITHM_3DES:
                    if (mSpecifiedKeyLength != KEY_LEN_UNSPECIFIED) {
                        throw new InvalidSyntaxException(
                                "Must not set Key Length value for this "
                                        + getTransformTypeString()
                                        + " Algorithm ID: "
                                        + id);
                    }
                    return;
                case SaProposal.ENCRYPTION_ALGORITHM_AES_CBC:
                    /* fall through */
                case SaProposal.ENCRYPTION_ALGORITHM_AES_GCM_8:
                    /* fall through */
                case SaProposal.ENCRYPTION_ALGORITHM_AES_GCM_12:
                    /* fall through */
                case SaProposal.ENCRYPTION_ALGORITHM_AES_GCM_16:
                    if (mSpecifiedKeyLength == KEY_LEN_UNSPECIFIED) {
                        throw new InvalidSyntaxException(
                                "Must set Key Length value for this "
                                        + getTransformTypeString()
                                        + " Algorithm ID: "
                                        + id);
                    }
                    if (mSpecifiedKeyLength != SaProposal.KEY_LEN_AES_128
                            && mSpecifiedKeyLength != SaProposal.KEY_LEN_AES_192
                            && mSpecifiedKeyLength != SaProposal.KEY_LEN_AES_256) {
                        throw new InvalidSyntaxException(
                                "Invalid key length for this "
                                        + getTransformTypeString()
                                        + " Algorithm ID: "
                                        + id);
                    }
                    return;
                default:
                    // Won't hit here.
                    throw new IllegalArgumentException(
                            "Unrecognized Encryption Algorithm ID: " + id);
            }
        }

        @Override
        protected void encodeToByteBuffer(boolean isLast, ByteBuffer byteBuffer) {
            encodeBasicTransformToByteBuffer(isLast, byteBuffer);

            if (mSpecifiedKeyLength != KEY_LEN_UNSPECIFIED) {
                new KeyLengthAttribute(mSpecifiedKeyLength).encodeToByteBuffer(byteBuffer);
            }
        }

        @Override
        protected int getTransformLength() {
            int len = BASIC_TRANSFORM_LEN;

            if (mSpecifiedKeyLength != KEY_LEN_UNSPECIFIED) {
                len += new KeyLengthAttribute(mSpecifiedKeyLength).getAttributeLength();
            }

            return len;
        }

        @Override
        public String getTransformTypeString() {
            return "Encryption Algorithm";
        }

        @Override
        @NonNull
        public String toString() {
            return SaProposal.getEncryptionAlgorithmString(id)
                    + "("
                    + getSpecifiedKeyLength()
                    + ")";
        }
    }

    /**
     * PrfTransform represents an pseudorandom function.
     *
     * @see <a href="https://tools.ietf.org/html/rfc7296#section-3.3.2">RFC 7296, Internet Key
     *     Exchange Protocol Version 2 (IKEv2)</a>
     */
    public static final class PrfTransform extends Transform {
        /**
         * Contruct an instance of PrfTransform for building an outbound packet.
         *
         * @param id the IKE standard Transform ID.
         */
        public PrfTransform(@PseudorandomFunction int id) {
            super(Transform.TRANSFORM_TYPE_PRF, id);
        }

        /**
         * Contruct an instance of PrfTransform for decoding an inbound packet.
         *
         * @param id the IKE standard Transform ID.
         * @param attributeList the decoded list of Attribute.
         * @throws InvalidSyntaxException for syntax error.
         */
        protected PrfTransform(int id, List<Attribute> attributeList)
                throws InvalidSyntaxException {
            super(Transform.TRANSFORM_TYPE_PRF, id, attributeList);
        }

        @Override
        public int hashCode() {
            return Objects.hash(type, id);
        }

        @Override
        public boolean equals(Object o) {
            if (!(o instanceof PrfTransform)) return false;

            PrfTransform other = (PrfTransform) o;
            return (type == other.type && id == other.id);
        }

        @Override
        protected boolean isSupportedTransformId(int id) {
            return SaProposal.isSupportedPseudorandomFunction(id);
        }

        @Override
        protected boolean hasUnrecognizedAttribute(List<Attribute> attributeList) {
            return !attributeList.isEmpty();
        }

        @Override
        protected void encodeToByteBuffer(boolean isLast, ByteBuffer byteBuffer) {
            encodeBasicTransformToByteBuffer(isLast, byteBuffer);
        }

        @Override
        protected int getTransformLength() {
            return BASIC_TRANSFORM_LEN;
        }

        @Override
        public String getTransformTypeString() {
            return "Pseudorandom Function";
        }

        @Override
        @NonNull
        public String toString() {
            return SaProposal.getPseudorandomFunctionString(id);
        }
    }

    /**
     * IntegrityTransform represents an integrity algorithm.
     *
     * <p>Proposing integrity algorithm for ESP SA is optional. Omitting the IntegrityTransform is
     * equivalent to including it with a value of NONE. When multiple integrity algorithms are
     * provided, choosing any of them are acceptable.
     *
     * @see <a href="https://tools.ietf.org/html/rfc7296#section-3.3.2">RFC 7296, Internet Key
     *     Exchange Protocol Version 2 (IKEv2)</a>
     */
    public static final class IntegrityTransform extends Transform {
        /**
         * Contruct an instance of IntegrityTransform for building an outbound packet.
         *
         * @param id the IKE standard Transform ID.
         */
        public IntegrityTransform(@IntegrityAlgorithm int id) {
            super(Transform.TRANSFORM_TYPE_INTEG, id);
        }

        /**
         * Contruct an instance of IntegrityTransform for decoding an inbound packet.
         *
         * @param id the IKE standard Transform ID.
         * @param attributeList the decoded list of Attribute.
         * @throws InvalidSyntaxException for syntax error.
         */
        protected IntegrityTransform(int id, List<Attribute> attributeList)
                throws InvalidSyntaxException {
            super(Transform.TRANSFORM_TYPE_INTEG, id, attributeList);
        }

        @Override
        public int hashCode() {
            return Objects.hash(type, id);
        }

        @Override
        public boolean equals(Object o) {
            if (!(o instanceof IntegrityTransform)) return false;

            IntegrityTransform other = (IntegrityTransform) o;
            return (type == other.type && id == other.id);
        }

        @Override
        protected boolean isSupportedTransformId(int id) {
            return SaProposal.isSupportedIntegrityAlgorithm(id);
        }

        @Override
        protected boolean hasUnrecognizedAttribute(List<Attribute> attributeList) {
            return !attributeList.isEmpty();
        }

        @Override
        protected void encodeToByteBuffer(boolean isLast, ByteBuffer byteBuffer) {
            encodeBasicTransformToByteBuffer(isLast, byteBuffer);
        }

        @Override
        protected int getTransformLength() {
            return BASIC_TRANSFORM_LEN;
        }

        @Override
        public String getTransformTypeString() {
            return "Integrity Algorithm";
        }

        @Override
        @NonNull
        public String toString() {
            return SaProposal.getIntegrityAlgorithmString(id);
        }
    }

    /**
     * DhGroupTransform represents a Diffie-Hellman Group
     *
     * <p>Proposing DH group for non-first Child SA is optional. Omitting the DhGroupTransform is
     * equivalent to including it with a value of NONE. When multiple DH groups are provided,
     * choosing any of them are acceptable.
     *
     * @see <a href="https://tools.ietf.org/html/rfc7296#section-3.3.2">RFC 7296, Internet Key
     *     Exchange Protocol Version 2 (IKEv2)</a>
     */
    public static final class DhGroupTransform extends Transform {
        /**
         * Contruct an instance of DhGroupTransform for building an outbound packet.
         *
         * @param id the IKE standard Transform ID.
         */
        public DhGroupTransform(@DhGroup int id) {
            super(Transform.TRANSFORM_TYPE_DH, id);
        }

        /**
         * Contruct an instance of DhGroupTransform for decoding an inbound packet.
         *
         * @param id the IKE standard Transform ID.
         * @param attributeList the decoded list of Attribute.
         * @throws InvalidSyntaxException for syntax error.
         */
        protected DhGroupTransform(int id, List<Attribute> attributeList)
                throws InvalidSyntaxException {
            super(Transform.TRANSFORM_TYPE_DH, id, attributeList);
        }

        @Override
        public int hashCode() {
            return Objects.hash(type, id);
        }

        @Override
        public boolean equals(Object o) {
            if (!(o instanceof DhGroupTransform)) return false;

            DhGroupTransform other = (DhGroupTransform) o;
            return (type == other.type && id == other.id);
        }

        @Override
        protected boolean isSupportedTransformId(int id) {
            return SaProposal.isSupportedDhGroup(id);
        }

        @Override
        protected boolean hasUnrecognizedAttribute(List<Attribute> attributeList) {
            return !attributeList.isEmpty();
        }

        @Override
        protected void encodeToByteBuffer(boolean isLast, ByteBuffer byteBuffer) {
            encodeBasicTransformToByteBuffer(isLast, byteBuffer);
        }

        @Override
        protected int getTransformLength() {
            return BASIC_TRANSFORM_LEN;
        }

        @Override
        public String getTransformTypeString() {
            return "Diffie-Hellman Group";
        }

        @Override
        @NonNull
        public String toString() {
            return SaProposal.getDhGroupString(id);
        }
    }

    /**
     * EsnTransform represents ESN policy that indicates if IPsec SA uses tranditional 32-bit
     * sequence numbers or extended(64-bit) sequence numbers.
     *
     * <p>Currently IKE library only supports negotiating IPsec SA that do not use extended sequence
     * numbers. The Transform ID of EsnTransform in outbound packets is not user configurable.
     *
     * @see <a href="https://tools.ietf.org/html/rfc7296#section-3.3.2">RFC 7296, Internet Key
     *     Exchange Protocol Version 2 (IKEv2)</a>
     */
    public static final class EsnTransform extends Transform {
        @Retention(RetentionPolicy.SOURCE)
        @IntDef({ESN_POLICY_NO_EXTENDED, ESN_POLICY_EXTENDED})
        public @interface EsnPolicy {}

        public static final int ESN_POLICY_NO_EXTENDED = 0;
        public static final int ESN_POLICY_EXTENDED = 1;

        /**
         * Construct an instance of EsnTransform indicates using no-extended sequence numbers for
         * building an outbound packet.
         */
        public EsnTransform() {
            super(Transform.TRANSFORM_TYPE_ESN, ESN_POLICY_NO_EXTENDED);
        }

        /**
         * Contruct an instance of EsnTransform for decoding an inbound packet.
         *
         * @param id the IKE standard Transform ID.
         * @param attributeList the decoded list of Attribute.
         * @throws InvalidSyntaxException for syntax error.
         */
        protected EsnTransform(int id, List<Attribute> attributeList)
                throws InvalidSyntaxException {
            super(Transform.TRANSFORM_TYPE_ESN, id, attributeList);
        }

        @Override
        public int hashCode() {
            return Objects.hash(type, id);
        }

        @Override
        public boolean equals(Object o) {
            if (!(o instanceof EsnTransform)) return false;

            EsnTransform other = (EsnTransform) o;
            return (type == other.type && id == other.id);
        }

        @Override
        protected boolean isSupportedTransformId(int id) {
            return (id == ESN_POLICY_NO_EXTENDED || id == ESN_POLICY_EXTENDED);
        }

        @Override
        protected boolean hasUnrecognizedAttribute(List<Attribute> attributeList) {
            return !attributeList.isEmpty();
        }

        @Override
        protected void encodeToByteBuffer(boolean isLast, ByteBuffer byteBuffer) {
            encodeBasicTransformToByteBuffer(isLast, byteBuffer);
        }

        @Override
        protected int getTransformLength() {
            return BASIC_TRANSFORM_LEN;
        }

        @Override
        public String getTransformTypeString() {
            return "Extended Sequence Numbers";
        }

        @Override
        @NonNull
        public String toString() {
            if (id == ESN_POLICY_NO_EXTENDED) {
                return "ESN_No_Extended";
            }
            return "ESN_Extended";
        }
    }

    /**
     * UnrecognizedTransform represents a Transform with unrecognized Transform Type.
     *
     * <p>Proposals containing an UnrecognizedTransform should be ignored.
     */
    protected static final class UnrecognizedTransform extends Transform {
        protected UnrecognizedTransform(int type, int id, List<Attribute> attributeList) {
            super(type, id, attributeList);
        }

        @Override
        protected boolean isSupportedTransformId(int id) {
            return false;
        }

        @Override
        protected boolean hasUnrecognizedAttribute(List<Attribute> attributeList) {
            return !attributeList.isEmpty();
        }

        @Override
        protected void encodeToByteBuffer(boolean isLast, ByteBuffer byteBuffer) {
            throw new UnsupportedOperationException(
                    "It is not supported to encode a Transform with" + getTransformTypeString());
        }

        @Override
        protected int getTransformLength() {
            throw new UnsupportedOperationException(
                    "It is not supported to get length of a Transform with "
                            + getTransformTypeString());
        }

        /**
         * Return Tranform Type of Unrecognized Transform as a String.
         *
         * @return Tranform Type of Unrecognized Transform as a String.
         */
        @Override
        public String getTransformTypeString() {
            return "Unrecognized Transform Type.";
        }
    }

    /**
     * Attribute is an abtract base class for completing the specification of some {@link
     * Transform}.
     *
     * <p>Attribute is either in Type/Value format or Type/Length/Value format. For TV format,
     * Attribute length is always 4 bytes containing value for 2 bytes. While for TLV format,
     * Attribute length is determined by length field.
     *
     * <p>Currently only Key Length type is supported
     *
     * @see <a href="https://tools.ietf.org/html/rfc7296#section-3.3.5">RFC 7296, Internet Key
     *     Exchange Protocol Version 2 (IKEv2)</a>
     */
    public abstract static class Attribute {
        @Retention(RetentionPolicy.SOURCE)
        @IntDef({ATTRIBUTE_TYPE_KEY_LENGTH})
        public @interface AttributeType {}

        // Support only one Attribute type: Key Length. Should use Type/Value format.
        public static final int ATTRIBUTE_TYPE_KEY_LENGTH = 14;

        // Mask to extract the left most AF bit to indicate Attribute Format.
        private static final int ATTRIBUTE_FORMAT_MASK = 0x8000;
        // Mask to extract 15 bits after the AF bit to indicate Attribute Type.
        private static final int ATTRIBUTE_TYPE_MASK = 0x7fff;

        // Package private mask to indicate that Type-Value (TV) Attribute Format is used.
        static final int ATTRIBUTE_FORMAT_TV = ATTRIBUTE_FORMAT_MASK;

        // Package private
        static final int TV_ATTRIBUTE_VALUE_LEN = 2;
        static final int TV_ATTRIBUTE_TOTAL_LEN = 4;
        static final int TVL_ATTRIBUTE_HEADER_LEN = TV_ATTRIBUTE_TOTAL_LEN;

        // Only Key Length type belongs to AttributeType
        public final int type;

        /** Construct an instance of an Attribute when decoding message. */
        protected Attribute(int type) {
            this.type = type;
        }

        @VisibleForTesting
        static Pair<Attribute, Integer> readFrom(ByteBuffer inputBuffer)
                throws IkeProtocolException {
            short formatAndType = inputBuffer.getShort();
            int format = formatAndType & ATTRIBUTE_FORMAT_MASK;
            int type = formatAndType & ATTRIBUTE_TYPE_MASK;

            int length = 0;
            byte[] value = new byte[0];
            if (format == ATTRIBUTE_FORMAT_TV) {
                // Type/Value format
                length = TV_ATTRIBUTE_TOTAL_LEN;
                value = new byte[TV_ATTRIBUTE_VALUE_LEN];
            } else {
                // Type/Length/Value format
                if (type == ATTRIBUTE_TYPE_KEY_LENGTH) {
                    throw new InvalidSyntaxException("Wrong format in Transform Attribute");
                }

                length = Short.toUnsignedInt(inputBuffer.getShort());
                int valueLen = length - TVL_ATTRIBUTE_HEADER_LEN;
                // IkeMessage will catch exception if valueLen is negative.
                value = new byte[valueLen];
            }

            inputBuffer.get(value);

            switch (type) {
                case ATTRIBUTE_TYPE_KEY_LENGTH:
                    return new Pair(new KeyLengthAttribute(value), length);
                default:
                    return new Pair(new UnrecognizedAttribute(type, value), length);
            }
        }

        // Encode Attribute to a ByteBuffer.
        protected abstract void encodeToByteBuffer(ByteBuffer byteBuffer);

        // Get entire Attribute length.
        protected abstract int getAttributeLength();
    }

    /** KeyLengthAttribute represents a Key Length type Attribute */
    public static final class KeyLengthAttribute extends Attribute {
        public final int keyLength;

        protected KeyLengthAttribute(byte[] value) {
            this(Short.toUnsignedInt(ByteBuffer.wrap(value).getShort()));
        }

        protected KeyLengthAttribute(int keyLength) {
            super(ATTRIBUTE_TYPE_KEY_LENGTH);
            this.keyLength = keyLength;
        }

        @Override
        protected void encodeToByteBuffer(ByteBuffer byteBuffer) {
            byteBuffer
                    .putShort((short) (ATTRIBUTE_FORMAT_TV | ATTRIBUTE_TYPE_KEY_LENGTH))
                    .putShort((short) keyLength);
        }

        @Override
        protected int getAttributeLength() {
            return TV_ATTRIBUTE_TOTAL_LEN;
        }
    }

    /**
     * UnrecognizedAttribute represents a Attribute with unrecoginzed Attribute Type.
     *
     * <p>Transforms containing UnrecognizedAttribute should be ignored.
     */
    protected static final class UnrecognizedAttribute extends Attribute {
        protected UnrecognizedAttribute(int type, byte[] value) {
            super(type);
        }

        @Override
        protected void encodeToByteBuffer(ByteBuffer byteBuffer) {
            throw new UnsupportedOperationException(
                    "It is not supported to encode an unrecognized Attribute.");
        }

        @Override
        protected int getAttributeLength() {
            throw new UnsupportedOperationException(
                    "It is not supported to get length of an unrecognized Attribute.");
        }
    }

    /**
     * Encode SA payload to ByteBUffer.
     *
     * @param nextPayload type of payload that follows this payload.
     * @param byteBuffer destination ByteBuffer that stores encoded payload.
     */
    @Override
    protected void encodeToByteBuffer(@PayloadType int nextPayload, ByteBuffer byteBuffer) {
        encodePayloadHeaderToByteBuffer(nextPayload, getPayloadLength(), byteBuffer);

        for (int i = 0; i < proposalList.size(); i++) {
            // The last proposal has the isLast flag set to true.
            proposalList.get(i).encodeToByteBuffer(i == proposalList.size() - 1, byteBuffer);
        }
    }

    /**
     * Get entire payload length.
     *
     * @return entire payload length.
     */
    @Override
    protected int getPayloadLength() {
        int len = GENERIC_HEADER_LENGTH;

        for (Proposal p : proposalList) len += p.getProposalLength();

        return len;
    }

    /**
     * Return the payload type as a String.
     *
     * @return the payload type as a String.
     */
    @Override
    public String getTypeString() {
        return "SA";
    }

    @Override
    @NonNull
    public String toString() {
        StringBuilder sb = new StringBuilder();
        if (isSaResponse) {
            sb.append("SA Response: ");
        } else {
            sb.append("SA Request: ");
        }

        int len = proposalList.size();
        for (int i = 0; i < len; i++) {
            sb.append(proposalList.get(i).toString());
            if (i < len - 1) sb.append(", ");
        }

        return sb.toString();
    }
}
