aboutsummaryrefslogtreecommitdiff
path: root/src/java/android/net/ipsec/ike/exceptions/IkeProtocolException.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/java/android/net/ipsec/ike/exceptions/IkeProtocolException.java')
-rw-r--r--src/java/android/net/ipsec/ike/exceptions/IkeProtocolException.java182
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);
+ }
+}