diff options
Diffstat (limited to 'src/java/android/net/ipsec/ike/exceptions/IkeProtocolException.java')
-rw-r--r-- | src/java/android/net/ipsec/ike/exceptions/IkeProtocolException.java | 182 |
1 files changed, 182 insertions, 0 deletions
diff --git a/src/java/android/net/ipsec/ike/exceptions/IkeProtocolException.java b/src/java/android/net/ipsec/ike/exceptions/IkeProtocolException.java new file mode 100644 index 00000000..f589a267 --- /dev/null +++ b/src/java/android/net/ipsec/ike/exceptions/IkeProtocolException.java @@ -0,0 +1,182 @@ +/* + * 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.exceptions; + +import android.annotation.IntDef; + +import com.android.internal.net.ipsec.ike.message.IkeNotifyPayload; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.nio.ByteBuffer; + +/** + * IkeProtocolException is an abstract class that represents the common information for all IKE + * protocol errors. + * + * @see <a href="https://tools.ietf.org/html/rfc7296#section-3.10.1">RFC 7296, Internet Key Exchange + * Protocol Version 2 (IKEv2)</a> + */ +public abstract class IkeProtocolException extends IkeException { + @Retention(RetentionPolicy.SOURCE) + @IntDef({ + ERROR_TYPE_UNSUPPORTED_CRITICAL_PAYLOAD, + ERROR_TYPE_INVALID_IKE_SPI, + ERROR_TYPE_INVALID_MAJOR_VERSION, + ERROR_TYPE_INVALID_SYNTAX, + ERROR_TYPE_INVALID_MESSAGE_ID, + ERROR_TYPE_NO_PROPOSAL_CHOSEN, + ERROR_TYPE_INVALID_KE_PAYLOAD, + ERROR_TYPE_AUTHENTICATION_FAILED, + ERROR_TYPE_SINGLE_PAIR_REQUIRED, + ERROR_TYPE_NO_ADDITIONAL_SAS, + ERROR_TYPE_INTERNAL_ADDRESS_FAILURE, + ERROR_TYPE_FAILED_CP_REQUIRED, + ERROR_TYPE_TS_UNACCEPTABLE, + ERROR_TYPE_INVALID_SELECTORS, + ERROR_TYPE_TEMPORARY_FAILURE, + ERROR_TYPE_CHILD_SA_NOT_FOUND, + }) + public @interface ErrorType {} + + public static final int ERROR_TYPE_UNSUPPORTED_CRITICAL_PAYLOAD = 1; + public static final int ERROR_TYPE_INVALID_IKE_SPI = 4; + public static final int ERROR_TYPE_INVALID_MAJOR_VERSION = 5; + public static final int ERROR_TYPE_INVALID_SYNTAX = 7; + public static final int ERROR_TYPE_INVALID_MESSAGE_ID = 9; + public static final int ERROR_TYPE_NO_PROPOSAL_CHOSEN = 14; + public static final int ERROR_TYPE_INVALID_KE_PAYLOAD = 17; + public static final int ERROR_TYPE_AUTHENTICATION_FAILED = 24; + public static final int ERROR_TYPE_SINGLE_PAIR_REQUIRED = 34; + public static final int ERROR_TYPE_NO_ADDITIONAL_SAS = 35; + public static final int ERROR_TYPE_INTERNAL_ADDRESS_FAILURE = 36; + public static final int ERROR_TYPE_FAILED_CP_REQUIRED = 37; + public static final int ERROR_TYPE_TS_UNACCEPTABLE = 38; + public static final int ERROR_TYPE_INVALID_SELECTORS = 39; + public static final int ERROR_TYPE_TEMPORARY_FAILURE = 43; + public static final int ERROR_TYPE_CHILD_SA_NOT_FOUND = 44; + + public static final byte[] ERROR_DATA_NOT_INCLUDED = new byte[0]; + + private static final int INTEGER_BYTE_SIZE = 4; + + @ErrorType private final int mErrorType; + private final byte[] mErrorData; + + protected IkeProtocolException(@ErrorType int code) { + super(); + mErrorType = code; + mErrorData = ERROR_DATA_NOT_INCLUDED; + } + + protected IkeProtocolException(@ErrorType int code, String message) { + super(message); + mErrorType = code; + mErrorData = ERROR_DATA_NOT_INCLUDED; + } + + protected IkeProtocolException(@ErrorType int code, Throwable cause) { + super(cause); + mErrorType = code; + mErrorData = ERROR_DATA_NOT_INCLUDED; + } + + protected IkeProtocolException(@ErrorType int code, String message, Throwable cause) { + super(message, cause); + mErrorType = code; + mErrorData = ERROR_DATA_NOT_INCLUDED; + } + + // Construct an instance from a notify Payload. + protected IkeProtocolException(@ErrorType int code, byte[] notifyData) { + super(); + + if (!isValidDataLength(notifyData.length)) { + throw new IllegalArgumentException( + "Invalid error data for error type: " + + code + + " Received error data size: " + + notifyData.length); + } + + mErrorType = code; + mErrorData = notifyData; + } + + protected abstract boolean isValidDataLength(int dataLen); + + protected static byte[] integerToByteArray(int integer, int arraySize) { + if (arraySize > INTEGER_BYTE_SIZE) { + throw new IllegalArgumentException( + "Cannot convert integer to a byte array of length: " + arraySize); + } + + ByteBuffer dataBuffer = ByteBuffer.allocate(INTEGER_BYTE_SIZE); + dataBuffer.putInt(integer); + dataBuffer.rewind(); + + byte[] zeroPad = new byte[INTEGER_BYTE_SIZE - arraySize]; + byte[] byteData = new byte[arraySize]; + dataBuffer.get(zeroPad).get(byteData); + + return byteData; + } + + protected static int byteArrayToInteger(byte[] byteArray) { + if (byteArray == null || byteArray.length > INTEGER_BYTE_SIZE) { + throw new IllegalArgumentException("Cannot convert the byte array to integer"); + } + + ByteBuffer dataBuffer = ByteBuffer.allocate(INTEGER_BYTE_SIZE); + byte[] zeroPad = new byte[INTEGER_BYTE_SIZE - byteArray.length]; + dataBuffer.put(zeroPad).put(byteArray); + dataBuffer.rewind(); + + return dataBuffer.getInt(); + } + + /** + * Returns the IKE standard protocol error type of this {@link IkeProtocolException} instance. + * + * @return the IKE standard protocol error type. + */ + @ErrorType + public int getErrorType() { + return mErrorType; + } + + /** + * Returns the included error data of this {@link IkeProtocolException} instance. + * + * <p>Note that only few error types will go with an error data. This data has different meaning + * with different error types. Users should first check if an error data is included before they + * call this method. + * + * @return the included error data in byte array. + */ + public byte[] getErrorData() { + return mErrorData; + } + + /** + * Build an IKE Notification Payload for this {@link IkeProtocolException} instance. + * + * @return the notification payload. + */ + public IkeNotifyPayload buildNotifyPayload() { + return new IkeNotifyPayload(mErrorType, mErrorData); + } +} |