/* * 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 android.net.ipsec.ike; import static com.android.internal.net.ipsec.ike.message.IkeSaPayload.EsnTransform.ESN_POLICY_NO_EXTENDED; import android.annotation.NonNull; import android.annotation.SuppressLint; import android.net.IpSecAlgorithm; import android.os.PersistableBundle; import android.util.ArraySet; import com.android.internal.net.ipsec.ike.crypto.IkeCipher; import com.android.internal.net.ipsec.ike.crypto.IkeMacIntegrity; import com.android.internal.net.ipsec.ike.message.IkePayload; import com.android.internal.net.ipsec.ike.message.IkeSaPayload.DhGroupTransform; import com.android.internal.net.ipsec.ike.message.IkeSaPayload.EncryptionTransform; import com.android.internal.net.ipsec.ike.message.IkeSaPayload.EsnTransform; import com.android.internal.net.ipsec.ike.message.IkeSaPayload.IntegrityTransform; import com.android.internal.net.ipsec.ike.message.IkeSaPayload.Transform; import com.android.modules.utils.build.SdkLevel; import com.android.server.vcn.util.PersistableBundleUtils; import java.util.Arrays; import java.util.List; import java.util.Objects; import java.util.Set; /** * ChildSaProposal represents a proposed configuration to negotiate a Child SA. * *
ChildSaProposal will contain cryptograhic algorithms and key generation materials for the * negotiation of a Child SA. * *
User must provide at least one valid ChildSaProposal when they are creating a new Child SA.
*
* @see RFC 7296, Internet Key Exchange
* Protocol Version 2 (IKEv2)
*/
public final class ChildSaProposal extends SaProposal {
// Before SDK S, there is no API in IpSecAlgorithm to retrieve supported algorithms. Thus hard
// coded these algorithms here.
private static final Set This constructor is either called by ChildSaPayload for building an inbound proposal from
* a decoded packet, or called by the inner Builder to build an outbound proposal from user
* provided parameters
*
* @param encryptionAlgos encryption algorithms
* @param integrityAlgos integrity algorithms
* @param dhGroups Diffie-Hellman Groups
* @param esns ESN policies
* @hide
*/
public ChildSaProposal(
EncryptionTransform[] encryptionAlgos,
IntegrityTransform[] integrityAlgos,
DhGroupTransform[] dhGroups,
EsnTransform[] esns) {
super(IkePayload.PROTOCOL_ID_ESP, encryptionAlgos, integrityAlgos, dhGroups);
mEsns = esns;
}
/**
* Constructs this object by deserializing a PersistableBundle
*
* Constructed proposals are guaranteed to be valid, as checked by the
* ChildSaProposal.Builder.
*
* @hide
*/
@NonNull
public static ChildSaProposal fromPersistableBundle(@NonNull PersistableBundle in) {
Objects.requireNonNull(in, "PersistableBundle is null");
ChildSaProposal.Builder builder = new ChildSaProposal.Builder();
PersistableBundle encryptionBundle = in.getPersistableBundle(ENCRYPT_ALGO_KEY);
Objects.requireNonNull(encryptionBundle, "Encryption algo bundle is null");
List Some algorithms may not be supported on old devices.
*/
@NonNull
public static Set Some algorithms may not be supported on old devices.
*/
@NonNull
public static Set This is used to avoid negotiating DH Group for negotiating first Child SA.
*
* @hide
*/
public ChildSaProposal getCopyWithoutDhTransform() {
return new ChildSaProposal(
getEncryptionTransforms(),
getIntegrityTransforms(),
new DhGroupTransform[0],
getEsnTransforms());
}
/** @hide */
@Override
public Transform[] getAllTransforms() {
List If this ChildSaProposal will be used for the first Child SA created as part of IKE
* AUTH exchange, DH groups configured here will only apply when the Child SA is later
* rekeyed. In this case, configuring different DH groups for IKE and Child SA may cause
* Rekey Child to fail.
*
* If no DH groups are supplied here, but the server requests a DH exchange during rekey,
* the IKE SA's negotiated DH group will still be accepted.
*
* @param dhGroup to add to ChildSaProposal.
* @return Builder of ChildSaProposal.
*/
// The matching getter is defined in the super class. Please see
// {@link SaProposal#getDhGroups}
@SuppressLint("MissingGetterMatchingBuilder")
@NonNull
public Builder addDhGroup(@DhGroup int dhGroup) {
addDh(dhGroup);
return this;
}
private IntegrityTransform[] buildIntegAlgosOrThrow() {
// When building Child SA Proposal with normal-mode ciphers, there is no contraint on
// integrity algorithm. When building Child SA Proposal with combined-mode ciphers,
// mProposedIntegrityAlgos must be either empty or only have INTEGRITY_ALGORITHM_NONE.
for (IntegrityTransform transform : mProposedIntegrityAlgos) {
if (transform.id != INTEGRITY_ALGORITHM_NONE && mHasAead) {
throw new IllegalArgumentException(
ERROR_TAG
+ "Only INTEGRITY_ALGORITHM_NONE can be"
+ " proposed with combined-mode ciphers in any proposal.");
}
}
return mProposedIntegrityAlgos.toArray(
new IntegrityTransform[mProposedIntegrityAlgos.size()]);
}
/**
* Validates and builds the ChildSaProposal.
*
* @return the validated ChildSaProposal.
*/
@NonNull
public ChildSaProposal build() {
EncryptionTransform[] encryptionTransforms = buildEncryptAlgosOrThrow();
IntegrityTransform[] integrityTransforms = buildIntegAlgosOrThrow();
return new ChildSaProposal(
encryptionTransforms,
integrityTransforms,
mProposedDhGroups.toArray(new DhGroupTransform[mProposedDhGroups.size()]),
new EsnTransform[] {new EsnTransform()});
}
}
}