• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2019 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 package android.net.ipsec.ike.exceptions;
17 
18 import android.annotation.IntDef;
19 import android.annotation.Nullable;
20 import android.annotation.SystemApi;
21 
22 import com.android.internal.net.ipsec.ike.message.IkeNotifyPayload;
23 
24 import java.lang.annotation.Retention;
25 import java.lang.annotation.RetentionPolicy;
26 import java.nio.ByteBuffer;
27 
28 /**
29  * IkeProtocolException is an abstract class that represents the common information for all IKE
30  * protocol errors.
31  *
32  * <p>Error types are as defined by RFC 7296.
33  *
34  * @see <a href="https://tools.ietf.org/html/rfc7296#section-3.10.1">RFC 7296, Internet Key Exchange
35  *     Protocol Version 2 (IKEv2)</a>
36  */
37 public abstract class IkeProtocolException extends IkeException {
38     /** @hide */
39     @Retention(RetentionPolicy.SOURCE)
40     @IntDef({
41         ERROR_TYPE_UNSUPPORTED_CRITICAL_PAYLOAD,
42         ERROR_TYPE_INVALID_IKE_SPI,
43         ERROR_TYPE_INVALID_MAJOR_VERSION,
44         ERROR_TYPE_INVALID_SYNTAX,
45         ERROR_TYPE_INVALID_MESSAGE_ID,
46         ERROR_TYPE_NO_PROPOSAL_CHOSEN,
47         ERROR_TYPE_INVALID_KE_PAYLOAD,
48         ERROR_TYPE_AUTHENTICATION_FAILED,
49         ERROR_TYPE_SINGLE_PAIR_REQUIRED,
50         ERROR_TYPE_NO_ADDITIONAL_SAS,
51         ERROR_TYPE_INTERNAL_ADDRESS_FAILURE,
52         ERROR_TYPE_FAILED_CP_REQUIRED,
53         ERROR_TYPE_TS_UNACCEPTABLE,
54         ERROR_TYPE_INVALID_SELECTORS,
55         ERROR_TYPE_TEMPORARY_FAILURE,
56         ERROR_TYPE_CHILD_SA_NOT_FOUND,
57     })
58     public @interface ErrorType {}
59 
60     /** Unsupported critical payload */
61     public static final int ERROR_TYPE_UNSUPPORTED_CRITICAL_PAYLOAD = 1;
62     /** Unrecognized destination IKE SPI */
63     public static final int ERROR_TYPE_INVALID_IKE_SPI = 4;
64     /** Invalid major version */
65     public static final int ERROR_TYPE_INVALID_MAJOR_VERSION = 5;
66     /** Invalid syntax */
67     public static final int ERROR_TYPE_INVALID_SYNTAX = 7;
68     /** Invalid message ID */
69     public static final int ERROR_TYPE_INVALID_MESSAGE_ID = 9;
70     /** No SA Proposal Chosen is acceptable */
71     public static final int ERROR_TYPE_NO_PROPOSAL_CHOSEN = 14;
72     /** Invalid Key Exchaneg Payload */
73     public static final int ERROR_TYPE_INVALID_KE_PAYLOAD = 17;
74     /** IKE authentication failed */
75     public static final int ERROR_TYPE_AUTHENTICATION_FAILED = 24;
76     /** Only Traffic Selectors specifying a single pair of addresses are acceptable */
77     public static final int ERROR_TYPE_SINGLE_PAIR_REQUIRED = 34;
78     /** No additional SAa are acceptable */
79     public static final int ERROR_TYPE_NO_ADDITIONAL_SAS = 35;
80     /** No internal addresses can be assigned */
81     public static final int ERROR_TYPE_INTERNAL_ADDRESS_FAILURE = 36;
82     /** Configuration Payload required but not found in IKE setup */
83     public static final int ERROR_TYPE_FAILED_CP_REQUIRED = 37;
84     /** No Traffic Selectors are acceptable */
85     public static final int ERROR_TYPE_TS_UNACCEPTABLE = 38;
86     /**
87      * An IPsec Packet was found to have mismatched Traffic Selectors of the IPsec SA on which it
88      * was delivered
89      */
90     public static final int ERROR_TYPE_INVALID_SELECTORS = 39;
91     /** Temporary failure */
92     public static final int ERROR_TYPE_TEMPORARY_FAILURE = 43;
93     /** Child SA in the received packet does not exist */
94     public static final int ERROR_TYPE_CHILD_SA_NOT_FOUND = 44;
95 
96     /** @hide */
97     public static final byte[] ERROR_DATA_NOT_INCLUDED = new byte[0];
98 
99     private static final int INTEGER_BYTE_SIZE = 4;
100 
101     @ErrorType private final int mErrorType;
102     private final byte[] mErrorData;
103 
104     /** @hide */
IkeProtocolException(@rrorType int code)105     protected IkeProtocolException(@ErrorType int code) {
106         super();
107         mErrorType = code;
108         mErrorData = ERROR_DATA_NOT_INCLUDED;
109     }
110 
111     /** @hide */
IkeProtocolException(@rrorType int code, String message)112     protected IkeProtocolException(@ErrorType int code, String message) {
113         super(message);
114         mErrorType = code;
115         mErrorData = ERROR_DATA_NOT_INCLUDED;
116     }
117 
118     /** @hide */
IkeProtocolException(@rrorType int code, Throwable cause)119     protected IkeProtocolException(@ErrorType int code, Throwable cause) {
120         super(cause);
121         mErrorType = code;
122         mErrorData = ERROR_DATA_NOT_INCLUDED;
123     }
124 
125     /** @hide */
IkeProtocolException(@rrorType int code, String message, Throwable cause)126     protected IkeProtocolException(@ErrorType int code, String message, Throwable cause) {
127         super(message, cause);
128         mErrorType = code;
129         mErrorData = ERROR_DATA_NOT_INCLUDED;
130     }
131 
132     /**
133      * Construct an instance from a notify Payload.
134      *
135      * @hide
136      */
IkeProtocolException(@rrorType int code, byte[] notifyData)137     protected IkeProtocolException(@ErrorType int code, byte[] notifyData) {
138         super();
139 
140         if (!isValidDataLength(notifyData.length)) {
141             throw new IllegalArgumentException(
142                     "Invalid error data for error type: "
143                             + code
144                             + " Received error data size: "
145                             + notifyData.length);
146         }
147 
148         mErrorType = code;
149         mErrorData = notifyData.clone();
150     }
151 
152     /** @hide */
isValidDataLength(int dataLen)153     protected abstract boolean isValidDataLength(int dataLen);
154 
155     /** @hide */
integerToByteArray(int integer, int arraySize)156     protected static byte[] integerToByteArray(int integer, int arraySize) {
157         if (arraySize > INTEGER_BYTE_SIZE) {
158             throw new IllegalArgumentException(
159                     "Cannot convert integer to a byte array of length: " + arraySize);
160         }
161 
162         ByteBuffer dataBuffer = ByteBuffer.allocate(INTEGER_BYTE_SIZE);
163         dataBuffer.putInt(integer);
164         dataBuffer.rewind();
165 
166         byte[] zeroPad = new byte[INTEGER_BYTE_SIZE - arraySize];
167         byte[] byteData = new byte[arraySize];
168         dataBuffer.get(zeroPad).get(byteData);
169 
170         return byteData;
171     }
172 
173     /** @hide */
byteArrayToInteger(byte[] byteArray)174     protected static int byteArrayToInteger(byte[] byteArray) {
175         if (byteArray == null || byteArray.length > INTEGER_BYTE_SIZE) {
176             throw new IllegalArgumentException("Cannot convert the byte array to integer");
177         }
178 
179         ByteBuffer dataBuffer = ByteBuffer.allocate(INTEGER_BYTE_SIZE);
180         byte[] zeroPad = new byte[INTEGER_BYTE_SIZE - byteArray.length];
181         dataBuffer.put(zeroPad).put(byteArray);
182         dataBuffer.rewind();
183 
184         return dataBuffer.getInt();
185     }
186 
187     /**
188      * Returns the IKE standard protocol error type of this {@link IkeProtocolException} instance.
189      *
190      * @return the IKE standard protocol error type.
191      */
192     @ErrorType
getErrorType()193     public int getErrorType() {
194         return mErrorType;
195     }
196 
197     /**
198      * Returns the included error data of this {@link IkeProtocolException} instance.
199      *
200      * <p>Note that only few error types will go with an error data. This data has different meaning
201      * with different error types. Callers should first check if an error data is included before
202      * they call this method.
203      *
204      * @return the included error data in byte array, or {@code null} if no error data is available.
205      * @hide
206      */
207     @SystemApi
208     @Nullable
getErrorData()209     public byte[] getErrorData() {
210         return mErrorData;
211     }
212 
213     /**
214      * Build an IKE Notification Payload for this {@link IkeProtocolException} instance.
215      *
216      * @return the notification payload.
217      * @hide
218      */
buildNotifyPayload()219     public IkeNotifyPayload buildNotifyPayload() {
220         return new IkeNotifyPayload(mErrorType, mErrorData);
221     }
222 }
223