• 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 com.android.internal.net.ipsec.ike;
17 
18 import static android.net.ipsec.ike.IkeManager.getIkeLog;
19 
20 import android.annotation.Nullable;
21 import android.content.Context;
22 import android.net.IpSecManager;
23 import android.net.IpSecManager.ResourceUnavailableException;
24 import android.net.IpSecManager.SecurityParameterIndex;
25 import android.net.IpSecManager.SpiUnavailableException;
26 import android.net.IpSecManager.UdpEncapsulationSocket;
27 import android.net.IpSecTransform;
28 import android.util.CloseGuard;
29 
30 import com.android.internal.annotations.VisibleForTesting;
31 import com.android.internal.net.ipsec.ike.crypto.IkeCipher;
32 import com.android.internal.net.ipsec.ike.crypto.IkeMacIntegrity;
33 import com.android.internal.net.ipsec.ike.crypto.IkeMacPrf;
34 import com.android.internal.net.ipsec.ike.message.IkeKePayload;
35 import com.android.internal.net.ipsec.ike.message.IkeMessage;
36 import com.android.internal.net.ipsec.ike.message.IkeMessage.DecodeResultPartial;
37 import com.android.internal.net.ipsec.ike.message.IkeNoncePayload;
38 import com.android.internal.net.ipsec.ike.message.IkePayload;
39 import com.android.internal.net.ipsec.ike.utils.IkeAlarm;
40 import com.android.internal.net.ipsec.ike.utils.IkeAlarm.IkeAlarmConfig;
41 import com.android.internal.net.ipsec.ike.utils.IkeSecurityParameterIndex;
42 
43 import java.io.IOException;
44 import java.net.Inet4Address;
45 import java.net.Inet6Address;
46 import java.net.InetAddress;
47 import java.nio.ByteBuffer;
48 import java.security.GeneralSecurityException;
49 import java.util.Arrays;
50 import java.util.List;
51 
52 /**
53  * SaRecord represents common information of an IKE SA and a Child SA.
54  *
55  * <p>When doing rekey, there can be multiple SAs in the same IkeSessionStateMachine or
56  * ChildSessionStateMachine, where they use same cryptographic algorithms but with different keys.
57  * We store cryptographic algorithms and unchanged SA configurations in IkeSessionParams or
58  * ChildSessionParams and store changed information including keys, SPIs, and nonces in SaRecord.
59  *
60  * <p>All keys are named by the key type plus the source of the traffic this key is protecting. For
61  * example, "mSkAi" represents the integrity key that protects traffic from the SA initiator to the
62  * SA responder.
63  *
64  * <p>Except for keys, all other paramters (SPIs, nonces and messages) are named by the creator. For
65  * example, "initSPI" represents a SPI that is created by the SA initiator.
66  */
67 public abstract class SaRecord implements AutoCloseable {
68     private static ISaRecordHelper sSaRecordHelper = new SaRecordHelper();
69     private static IIpSecTransformHelper sIpSecTransformHelper = new IpSecTransformHelper();
70 
71     /** Flag indicates if this SA is locally initiated */
72     public final boolean isLocalInit;
73 
74     public final byte[] nonceInitiator;
75     public final byte[] nonceResponder;
76 
77     private final byte[] mSkAi;
78     private final byte[] mSkAr;
79     private final byte[] mSkEi;
80     private final byte[] mSkEr;
81 
82     @VisibleForTesting final SaLifetimeAlarmScheduler mSaLifetimeAlarmScheduler;
83 
84     private final CloseGuard mCloseGuard = new CloseGuard();
85 
86     /** Package private */
SaRecord( boolean localInit, byte[] nonceInit, byte[] nonceResp, byte[] skAi, byte[] skAr, byte[] skEi, byte[] skEr, SaLifetimeAlarmScheduler saLifetimeAlarmScheduler)87     SaRecord(
88             boolean localInit,
89             byte[] nonceInit,
90             byte[] nonceResp,
91             byte[] skAi,
92             byte[] skAr,
93             byte[] skEi,
94             byte[] skEr,
95             SaLifetimeAlarmScheduler saLifetimeAlarmScheduler) {
96         isLocalInit = localInit;
97         nonceInitiator = nonceInit;
98         nonceResponder = nonceResp;
99 
100         mSkAi = skAi;
101         mSkAr = skAr;
102         mSkEi = skEi;
103         mSkEr = skEr;
104 
105         logKey("SK_ai", skAi);
106         logKey("SK_ar", skAr);
107         logKey("SK_ei", skEi);
108         logKey("SK_er", skEr);
109 
110         mSaLifetimeAlarmScheduler = saLifetimeAlarmScheduler;
111         mSaLifetimeAlarmScheduler.scheduleLifetimeExpiryAlarm(getTag());
112 
113         mCloseGuard.open("close");
114     }
115 
logKey(String type, byte[] key)116     private void logKey(String type, byte[] key) {
117         getIkeLog().d(getTag(), type + ": " + getIkeLog().pii(key));
118     }
119 
getTag()120     protected abstract String getTag();
121 
122     /**
123      * Get the integrity key for calculate integrity checksum for an outbound packet.
124      *
125      * @return the integrity key in a byte array, which will be empty if integrity algorithm is not
126      *     used in this SA.
127      */
getOutboundIntegrityKey()128     public byte[] getOutboundIntegrityKey() {
129         return isLocalInit ? mSkAi : mSkAr;
130     }
131 
132     /**
133      * Get the integrity key to authenticate an inbound packet.
134      *
135      * @return the integrity key in a byte array, which will be empty if integrity algorithm is not
136      *     used in this SA.
137      */
getInboundIntegrityKey()138     public byte[] getInboundIntegrityKey() {
139         return isLocalInit ? mSkAr : mSkAi;
140     }
141 
142     /**
143      * Get the encryption key for protecting an outbound packet.
144      *
145      * @return the encryption key in a byte array.
146      */
getOutboundEncryptionKey()147     public byte[] getOutboundEncryptionKey() {
148         return isLocalInit ? mSkEi : mSkEr;
149     }
150 
151     /**
152      * Get the decryption key for an inbound packet.
153      *
154      * @return the decryption key in a byte array.
155      */
getInboundDecryptionKey()156     public byte[] getInboundDecryptionKey() {
157         return isLocalInit ? mSkEr : mSkEi;
158     }
159 
160     /** Reschedule rekey */
rescheduleRekey(long retryDelayMs)161     public void rescheduleRekey(long retryDelayMs) {
162         mSaLifetimeAlarmScheduler.rescheduleRekey(retryDelayMs);
163     }
164 
165     /** Check that the SaRecord was closed properly. */
166     @Override
finalize()167     protected void finalize() throws Throwable {
168         if (mCloseGuard != null) {
169             mCloseGuard.warnIfOpen();
170         }
171         close();
172     }
173 
174     @Override
close()175     public void close() {
176         mSaLifetimeAlarmScheduler.cancelLifetimeExpiryAlarm(getTag());
177     }
178 
179     /** Package private */
180     @VisibleForTesting
setSaRecordHelper(ISaRecordHelper helper)181     static void setSaRecordHelper(ISaRecordHelper helper) {
182         sSaRecordHelper = helper;
183     }
184 
185     /** Package private */
186     @VisibleForTesting
setIpSecTransformHelper(IIpSecTransformHelper helper)187     static void setIpSecTransformHelper(IIpSecTransformHelper helper) {
188         sIpSecTransformHelper = helper;
189     }
190 
191     /**
192      * SaRecordHelper implements methods for constructing SaRecord.
193      *
194      * <p>Package private
195      */
196     static class SaRecordHelper implements ISaRecordHelper {
197         @Override
makeFirstIkeSaRecord( IkeMessage initRequest, IkeMessage initResponse, IkeSaRecordConfig ikeSaRecordConfig)198         public IkeSaRecord makeFirstIkeSaRecord(
199                 IkeMessage initRequest,
200                 IkeMessage initResponse,
201                 IkeSaRecordConfig ikeSaRecordConfig)
202                 throws GeneralSecurityException {
203             // Extract nonces
204             byte[] nonceInit =
205                     initRequest.getPayloadForType(
206                                     IkePayload.PAYLOAD_TYPE_NONCE, IkeNoncePayload.class)
207                             .nonceData;
208             byte[] nonceResp =
209                     initResponse.getPayloadForType(
210                                     IkePayload.PAYLOAD_TYPE_NONCE, IkeNoncePayload.class)
211                             .nonceData;
212 
213             // Get SKEYSEED
214             byte[] sharedDhKey = getSharedKey(initRequest, initResponse);
215             byte[] sKeySeed =
216                     ikeSaRecordConfig.prf.generateSKeySeed(nonceInit, nonceResp, sharedDhKey);
217 
218             return makeIkeSaRecord(sKeySeed, nonceInit, nonceResp, ikeSaRecordConfig);
219         }
220 
221         @Override
makeRekeyedIkeSaRecord( IkeSaRecord oldSaRecord, IkeMacPrf oldPrf, IkeMessage rekeyRequest, IkeMessage rekeyResponse, IkeSaRecordConfig ikeSaRecordConfig)222         public IkeSaRecord makeRekeyedIkeSaRecord(
223                 IkeSaRecord oldSaRecord,
224                 IkeMacPrf oldPrf,
225                 IkeMessage rekeyRequest,
226                 IkeMessage rekeyResponse,
227                 IkeSaRecordConfig ikeSaRecordConfig)
228                 throws GeneralSecurityException {
229             // Extract nonces
230             byte[] nonceInit =
231                     rekeyRequest.getPayloadForType(
232                                     IkePayload.PAYLOAD_TYPE_NONCE, IkeNoncePayload.class)
233                             .nonceData;
234             byte[] nonceResp =
235                     rekeyResponse.getPayloadForType(
236                                     IkePayload.PAYLOAD_TYPE_NONCE, IkeNoncePayload.class)
237                             .nonceData;
238 
239             // Get SKEYSEED
240             IkeMessage localMsg = ikeSaRecordConfig.isLocalInit ? rekeyRequest : rekeyResponse;
241             IkeMessage remoteMsg = ikeSaRecordConfig.isLocalInit ? rekeyResponse : rekeyRequest;
242 
243             byte[] sharedDhKey = getSharedKey(localMsg, remoteMsg);
244             byte[] sKeySeed =
245                     oldPrf.generateRekeyedSKeySeed(
246                             oldSaRecord.mSkD, nonceInit, nonceResp, sharedDhKey);
247 
248             return makeIkeSaRecord(sKeySeed, nonceInit, nonceResp, ikeSaRecordConfig);
249         }
250 
getSharedKey(IkeMessage keLocalMessage, IkeMessage keRemoteMessage)251         private byte[] getSharedKey(IkeMessage keLocalMessage, IkeMessage keRemoteMessage)
252                 throws GeneralSecurityException {
253             IkeKePayload keLocalPayload =
254                     keLocalMessage.getPayloadForType(
255                             IkePayload.PAYLOAD_TYPE_KE, IkeKePayload.class);
256             IkeKePayload keRemotePayload =
257                     keRemoteMessage.getPayloadForType(
258                             IkePayload.PAYLOAD_TYPE_KE, IkeKePayload.class);
259 
260             return IkeKePayload.getSharedKey(
261                     keLocalPayload.localPrivateKey,
262                     keRemotePayload.keyExchangeData,
263                     keRemotePayload.dhGroup);
264         }
265 
266         /**
267          * Package private method for calculating keys and construct IkeSaRecord.
268          *
269          * @see <a href="https://tools.ietf.org/html/rfc7296#section-2.13">RFC 7296, Internet Key
270          *     Exchange Protocol Version 2 (IKEv2), Generating Keying Material</a>
271          */
272         @VisibleForTesting
makeIkeSaRecord( byte[] sKeySeed, byte[] nonceInit, byte[] nonceResp, IkeSaRecordConfig ikeSaRecordConfig)273         IkeSaRecord makeIkeSaRecord(
274                 byte[] sKeySeed,
275                 byte[] nonceInit,
276                 byte[] nonceResp,
277                 IkeSaRecordConfig ikeSaRecordConfig) {
278             // Build data to sign for generating the keying material.
279             ByteBuffer bufferToSign =
280                     ByteBuffer.allocate(
281                             nonceInit.length + nonceResp.length + 2 * IkePayload.SPI_LEN_IKE);
282 
283             IkeSecurityParameterIndex initSpi = ikeSaRecordConfig.initSpi;
284             IkeSecurityParameterIndex respSpi = ikeSaRecordConfig.respSpi;
285             IkeMacPrf prf = ikeSaRecordConfig.prf;
286             int integrityKeyLength = ikeSaRecordConfig.integrityKeyLength;
287             int encryptionKeyLength = ikeSaRecordConfig.encryptionKeyLength;
288 
289             bufferToSign
290                     .put(nonceInit)
291                     .put(nonceResp)
292                     .putLong(initSpi.getSpi())
293                     .putLong(respSpi.getSpi());
294 
295             // Get length of the keying material according to RFC 7296, 2.13 and 2.14. The length of
296             // SK_D is always equal to the length of PRF key.
297             int skDLength = prf.getKeyLength();
298             int keyMaterialLen =
299                     skDLength
300                             + 2 * integrityKeyLength
301                             + 2 * encryptionKeyLength
302                             + 2 * prf.getKeyLength();
303             byte[] keyMat = prf.generateKeyMat(sKeySeed, bufferToSign.array(), keyMaterialLen);
304 
305             // Extract keys.
306             byte[] skD = new byte[skDLength];
307             byte[] skAi = new byte[integrityKeyLength];
308             byte[] skAr = new byte[integrityKeyLength];
309             byte[] skEi = new byte[encryptionKeyLength];
310             byte[] skEr = new byte[encryptionKeyLength];
311             byte[] skPi = new byte[prf.getKeyLength()];
312             byte[] skPr = new byte[prf.getKeyLength()];
313 
314             ByteBuffer keyMatBuffer = ByteBuffer.wrap(keyMat);
315             keyMatBuffer.get(skD).get(skAi).get(skAr).get(skEi).get(skEr).get(skPi).get(skPr);
316             return new IkeSaRecord(
317                     initSpi,
318                     respSpi,
319                     ikeSaRecordConfig.isLocalInit,
320                     nonceInit,
321                     nonceResp,
322                     skD,
323                     skAi,
324                     skAr,
325                     skEi,
326                     skEr,
327                     skPi,
328                     skPr,
329                     ikeSaRecordConfig.saLifetimeAlarmScheduler);
330         }
331 
332         @Override
makeChildSaRecord( List<IkePayload> reqPayloads, List<IkePayload> respPayloads, ChildSaRecordConfig childSaRecordConfig)333         public ChildSaRecord makeChildSaRecord(
334                 List<IkePayload> reqPayloads,
335                 List<IkePayload> respPayloads,
336                 ChildSaRecordConfig childSaRecordConfig)
337                 throws GeneralSecurityException, ResourceUnavailableException,
338                         SpiUnavailableException, IOException {
339             // Extract nonces. Encoding/Decoding of payload list guarantees that there is only one
340             // nonce payload in the reqPayloads and respPayloads lists
341             byte[] nonceInit =
342                     IkePayload.getPayloadForTypeInProvidedList(
343                                     IkePayload.PAYLOAD_TYPE_NONCE,
344                                     IkeNoncePayload.class,
345                                     reqPayloads)
346                             .nonceData;
347             byte[] nonceResp =
348                     IkePayload.getPayloadForTypeInProvidedList(
349                                     IkePayload.PAYLOAD_TYPE_NONCE,
350                                     IkeNoncePayload.class,
351                                     respPayloads)
352                             .nonceData;
353             byte[] sharedDhKey =
354                     getChildSharedKey(reqPayloads, respPayloads, childSaRecordConfig.isLocalInit);
355 
356             return makeChildSaRecord(sharedDhKey, nonceInit, nonceResp, childSaRecordConfig);
357         }
358 
359         @VisibleForTesting
getChildSharedKey( List<IkePayload> reqPayloads, List<IkePayload> respPayloads, boolean isLocalInit)360         static byte[] getChildSharedKey(
361                 List<IkePayload> reqPayloads, List<IkePayload> respPayloads, boolean isLocalInit)
362                 throws GeneralSecurityException {
363             // Check if KE Payload exists and get DH shared key. Encoding/Decoding of payload list
364             // guarantees that there is either no KE payload in the reqPayloads and respPayloads
365             // lists, or only one KE payload in each list.
366             IkeKePayload keInitPayload =
367                     IkePayload.getPayloadForTypeInProvidedList(
368                             IkePayload.PAYLOAD_TYPE_KE, IkeKePayload.class, reqPayloads);
369 
370             if (keInitPayload == null) {
371                 return new byte[0];
372             }
373 
374             IkeKePayload keRespPayload =
375                     IkePayload.getPayloadForTypeInProvidedList(
376                             IkePayload.PAYLOAD_TYPE_KE, IkeKePayload.class, respPayloads);
377             IkeKePayload localKePayload = isLocalInit ? keInitPayload : keRespPayload;
378             IkeKePayload remoteKePayload = isLocalInit ? keRespPayload : keInitPayload;
379             return IkeKePayload.getSharedKey(
380                     localKePayload.localPrivateKey,
381                     remoteKePayload.keyExchangeData,
382                     remoteKePayload.dhGroup);
383         }
384 
385         /**
386          * Package private method for calculating keys, build IpSecTransforms and construct
387          * ChildSaRecord.
388          *
389          * @see <a href="https://tools.ietf.org/html/rfc7296#section-2.17">RFC 7296, Internet Key
390          *     Exchange Protocol Version 2 (IKEv2), Generating Keying Material for Child SAs</a>
391          */
392         @VisibleForTesting
makeChildSaRecord( byte[] sharedKey, byte[] nonceInit, byte[] nonceResp, ChildSaRecordConfig childSaRecordConfig)393         ChildSaRecord makeChildSaRecord(
394                 byte[] sharedKey,
395                 byte[] nonceInit,
396                 byte[] nonceResp,
397                 ChildSaRecordConfig childSaRecordConfig)
398                 throws ResourceUnavailableException, SpiUnavailableException, IOException {
399             // Build data to sign for generating the keying material.
400             ByteBuffer bufferToSign =
401                     ByteBuffer.allocate(sharedKey.length + nonceInit.length + nonceResp.length);
402             bufferToSign.put(sharedKey).put(nonceInit).put(nonceResp);
403 
404             // Get length of the keying material according to RFC 7296, 2.17.
405             int encryptionKeyLength = childSaRecordConfig.encryptionAlgo.getKeyLength();
406             int integrityKeyLength =
407                     childSaRecordConfig.hasIntegrityAlgo
408                             ? childSaRecordConfig.integrityAlgo.getKeyLength()
409                             : 0;
410             int keyMaterialLen = 2 * encryptionKeyLength + 2 * integrityKeyLength;
411             byte[] keyMat =
412                     childSaRecordConfig.ikePrf.generateKeyMat(
413                             childSaRecordConfig.skD, bufferToSign.array(), keyMaterialLen);
414 
415             // Extract keys according to the order that keys carrying data from initiator to
416             // responder are taken before keys for the other direction and encryption keys are taken
417             // before integrity keys.
418             byte[] skEi = new byte[encryptionKeyLength];
419             byte[] skAi = new byte[integrityKeyLength];
420             byte[] skEr = new byte[encryptionKeyLength];
421             byte[] skAr = new byte[integrityKeyLength];
422 
423             ByteBuffer keyMatBuffer = ByteBuffer.wrap(keyMat);
424             keyMatBuffer.get(skEi).get(skAi).get(skEr).get(skAr);
425 
426             // IpSecTransform for traffic from the initiator
427             IpSecTransform initTransform = null;
428             // IpSecTransform for traffic from the responder
429             IpSecTransform respTransform = null;
430             try {
431                 // Build IpSecTransform
432                 initTransform =
433                         sIpSecTransformHelper.makeIpSecTransform(
434                                 childSaRecordConfig.context,
435                                 childSaRecordConfig.initAddress /*source address*/,
436                                 childSaRecordConfig.udpEncapSocket,
437                                 childSaRecordConfig.respSpi /*destination SPI*/,
438                                 childSaRecordConfig.integrityAlgo,
439                                 childSaRecordConfig.encryptionAlgo,
440                                 skAi,
441                                 skEi,
442                                 childSaRecordConfig.isTransport);
443                 respTransform =
444                         sIpSecTransformHelper.makeIpSecTransform(
445                                 childSaRecordConfig.context,
446                                 childSaRecordConfig.respAddress /*source address*/,
447                                 childSaRecordConfig.udpEncapSocket,
448                                 childSaRecordConfig.initSpi /*destination SPI*/,
449                                 childSaRecordConfig.integrityAlgo,
450                                 childSaRecordConfig.encryptionAlgo,
451                                 skAr,
452                                 skEr,
453                                 childSaRecordConfig.isTransport);
454 
455                 int initSpi = childSaRecordConfig.initSpi.getSpi();
456                 int respSpi = childSaRecordConfig.respSpi.getSpi();
457 
458                 boolean isLocalInit = childSaRecordConfig.isLocalInit;
459                 int inSpi = isLocalInit ? initSpi : respSpi;
460                 int outSpi = isLocalInit ? respSpi : initSpi;
461                 IpSecTransform inTransform = isLocalInit ? respTransform : initTransform;
462                 IpSecTransform outTransform = isLocalInit ? initTransform : respTransform;
463 
464                 return new ChildSaRecord(
465                         inSpi,
466                         outSpi,
467                         isLocalInit,
468                         nonceInit,
469                         nonceResp,
470                         skAi,
471                         skAr,
472                         skEi,
473                         skEr,
474                         inTransform,
475                         outTransform,
476                         childSaRecordConfig.saLifetimeAlarmScheduler);
477 
478             } catch (Exception e) {
479                 if (initTransform != null) initTransform.close();
480                 if (respTransform != null) respTransform.close();
481                 throw e;
482             }
483         }
484     }
485 
486     /**
487      * IpSecTransformHelper implements the IIpSecTransformHelper interface for constructing {@link
488      * IpSecTransform}}.
489      *
490      * <p>Package private
491      */
492     static class IpSecTransformHelper implements IIpSecTransformHelper {
493         private static final String TAG = "IpSecTransformHelper";
494 
495         @Override
makeIpSecTransform( Context context, InetAddress sourceAddress, UdpEncapsulationSocket udpEncapSocket, IpSecManager.SecurityParameterIndex spi, @Nullable IkeMacIntegrity integrityAlgo, IkeCipher encryptionAlgo, byte[] integrityKey, byte[] encryptionKey, boolean isTransport)496         public IpSecTransform makeIpSecTransform(
497                 Context context,
498                 InetAddress sourceAddress,
499                 UdpEncapsulationSocket udpEncapSocket,
500                 IpSecManager.SecurityParameterIndex spi,
501                 @Nullable IkeMacIntegrity integrityAlgo,
502                 IkeCipher encryptionAlgo,
503                 byte[] integrityKey,
504                 byte[] encryptionKey,
505                 boolean isTransport)
506                 throws ResourceUnavailableException, SpiUnavailableException, IOException {
507             IpSecTransform.Builder builder = new IpSecTransform.Builder(context);
508 
509             if (encryptionAlgo.isAead()) {
510                 builder.setAuthenticatedEncryption(
511                         encryptionAlgo.buildIpSecAlgorithmWithKey(encryptionKey));
512             } else {
513                 builder.setEncryption(encryptionAlgo.buildIpSecAlgorithmWithKey(encryptionKey));
514                 builder.setAuthentication(integrityAlgo.buildIpSecAlgorithmWithKey(integrityKey));
515             }
516 
517             if (udpEncapSocket != null && sourceAddress instanceof Inet6Address) {
518                 getIkeLog().wtf(TAG, "Kernel does not support UDP encapsulation for IPv6 SAs");
519             }
520             if (udpEncapSocket != null && sourceAddress instanceof Inet4Address) {
521                 builder.setIpv4Encapsulation(
522                         udpEncapSocket, IkeSocket.SERVER_PORT_UDP_ENCAPSULATED);
523             }
524 
525             if (isTransport) {
526                 return builder.buildTransportModeTransform(sourceAddress, spi);
527             } else {
528                 return builder.buildTunnelModeTransform(sourceAddress, spi);
529             }
530         }
531     }
532 
533     /** This class provides methods to schedule and cancel SA lifetime expiry alarm */
534     static class SaLifetimeAlarmScheduler {
535         private final long mDeleteDelayMs;
536         private final long mRekeyDelayMs;
537         private final IkeAlarm mDeleteAlarm;
538         private final IkeAlarm mRekeyAlarm;
539 
SaLifetimeAlarmScheduler( IkeAlarmConfig deleteAlarmConfig, IkeAlarmConfig rekeyAlarmConfig)540         SaLifetimeAlarmScheduler(
541                 IkeAlarmConfig deleteAlarmConfig, IkeAlarmConfig rekeyAlarmConfig) {
542             mDeleteDelayMs = deleteAlarmConfig.delayMs;
543             mRekeyDelayMs = rekeyAlarmConfig.delayMs;
544 
545             // Hard lifetime expiry alarm needs to be "setExact" considering the hard lifetime
546             // minimum value is 5 minutes and the inexact alarm might cause at most 75% of the
547             // scheduled interval delay because batching alarms. It is not necessay to wake up
548             // the alarm during doze mode because even the SA expires at that time, the device
549             // can not get access to network and won't expose more vulnerabilities.
550             mDeleteAlarm = IkeAlarm.newExactAlarm(deleteAlarmConfig);
551             mRekeyAlarm = IkeAlarm.newExactAndAllowWhileIdleAlarm(rekeyAlarmConfig);
552         }
553 
scheduleLifetimeExpiryAlarm(String tag)554         public void scheduleLifetimeExpiryAlarm(String tag) {
555             mDeleteAlarm.schedule();
556             mRekeyAlarm.schedule();
557             getIkeLog()
558                     .d(
559                             tag,
560                             "Lifetime alarm set: Hard lifetime ("
561                                     + mDeleteDelayMs
562                                     + "ms) Soft lifetime ("
563                                     + mRekeyDelayMs
564                                     + "ms)");
565         }
566 
rescheduleRekey(long retryDelayMs)567         public void rescheduleRekey(long retryDelayMs) {
568             mRekeyAlarm.schedule();
569         }
570 
cancelLifetimeExpiryAlarm(String tag)571         public void cancelLifetimeExpiryAlarm(String tag) {
572             mDeleteAlarm.cancel();
573             mRekeyAlarm.cancel();
574 
575             getIkeLog().d(tag, "Hard and soft lifetime alarm cancelled");
576         }
577     }
578 
579     /** Package private class to group parameters for building a ChildSaRecord. */
580     @VisibleForTesting
581     static final class ChildSaRecordConfig {
582         public final Context context;
583         public final SecurityParameterIndex initSpi;
584         public final SecurityParameterIndex respSpi;
585         public final InetAddress initAddress;
586         public final InetAddress respAddress;
587         @Nullable public final UdpEncapsulationSocket udpEncapSocket;
588         public final IkeMacPrf ikePrf;
589         @Nullable public final IkeMacIntegrity integrityAlgo;
590         public final IkeCipher encryptionAlgo;
591         public final byte[] skD;
592         public final boolean isTransport;
593         public final boolean isLocalInit;
594         public final boolean hasIntegrityAlgo;
595         public final SaLifetimeAlarmScheduler saLifetimeAlarmScheduler;
596 
ChildSaRecordConfig( Context context, SecurityParameterIndex initSpi, SecurityParameterIndex respSpi, InetAddress localAddress, InetAddress remoteAddress, @Nullable UdpEncapsulationSocket udpEncapSocket, IkeMacPrf ikePrf, @Nullable IkeMacIntegrity integrityAlgo, IkeCipher encryptionAlgo, byte[] skD, boolean isTransport, boolean isLocalInit, SaLifetimeAlarmScheduler saLifetimeAlarmScheduler)597         ChildSaRecordConfig(
598                 Context context,
599                 SecurityParameterIndex initSpi,
600                 SecurityParameterIndex respSpi,
601                 InetAddress localAddress,
602                 InetAddress remoteAddress,
603                 @Nullable UdpEncapsulationSocket udpEncapSocket,
604                 IkeMacPrf ikePrf,
605                 @Nullable IkeMacIntegrity integrityAlgo,
606                 IkeCipher encryptionAlgo,
607                 byte[] skD,
608                 boolean isTransport,
609                 boolean isLocalInit,
610                 SaLifetimeAlarmScheduler saLifetimeAlarmScheduler) {
611             this.context = context;
612             this.initSpi = initSpi;
613             this.respSpi = respSpi;
614             this.initAddress = isLocalInit ? localAddress : remoteAddress;
615             this.respAddress = isLocalInit ? remoteAddress : localAddress;
616             this.udpEncapSocket = udpEncapSocket;
617             this.ikePrf = ikePrf;
618             this.integrityAlgo = integrityAlgo;
619             this.encryptionAlgo = encryptionAlgo;
620             this.skD = skD;
621             this.isTransport = isTransport;
622             this.isLocalInit = isLocalInit;
623             hasIntegrityAlgo = (integrityAlgo != null);
624             this.saLifetimeAlarmScheduler = saLifetimeAlarmScheduler;
625         }
626     }
627 
628     /** IkeSaRecord represents an IKE SA. */
629     public static class IkeSaRecord extends SaRecord implements Comparable<IkeSaRecord> {
630         private static final String TAG = "IkeSaRecord";
631 
632         /** SPI of IKE SA initiator */
633         private final IkeSecurityParameterIndex mInitiatorSpiResource;
634         /** SPI of IKE SA responder */
635         private final IkeSecurityParameterIndex mResponderSpiResource;
636 
637         private final byte[] mSkD;
638         private final byte[] mSkPi;
639         private final byte[] mSkPr;
640 
641         private int mLocalRequestMessageId;
642         private int mRemoteRequestMessageId;
643         private int mLastSentRespMsgId;
644 
645         private DecodeResultPartial mCollectedReqFragments;
646         private DecodeResultPartial mCollectedRespFragments;
647 
648         private byte[] mLastRecivedReqFirstPacket;
649         private List<byte[]> mLastSentRespAllPackets;
650 
651         /** Package private */
IkeSaRecord( IkeSecurityParameterIndex initSpi, IkeSecurityParameterIndex respSpi, boolean localInit, byte[] nonceInit, byte[] nonceResp, byte[] skD, byte[] skAi, byte[] skAr, byte[] skEi, byte[] skEr, byte[] skPi, byte[] skPr, SaLifetimeAlarmScheduler saLifetimeAlarmScheduler)652         IkeSaRecord(
653                 IkeSecurityParameterIndex initSpi,
654                 IkeSecurityParameterIndex respSpi,
655                 boolean localInit,
656                 byte[] nonceInit,
657                 byte[] nonceResp,
658                 byte[] skD,
659                 byte[] skAi,
660                 byte[] skAr,
661                 byte[] skEi,
662                 byte[] skEr,
663                 byte[] skPi,
664                 byte[] skPr,
665                 SaLifetimeAlarmScheduler saLifetimeAlarmScheduler) {
666             super(
667                     localInit,
668                     nonceInit,
669                     nonceResp,
670                     skAi,
671                     skAr,
672                     skEi,
673                     skEr,
674                     saLifetimeAlarmScheduler);
675 
676             mInitiatorSpiResource = initSpi;
677             mResponderSpiResource = respSpi;
678             mInitiatorSpiResource.bindToIkeSaRecord();
679             mResponderSpiResource.bindToIkeSaRecord();
680 
681             mSkD = skD;
682             mSkPi = skPi;
683             mSkPr = skPr;
684 
685             mLocalRequestMessageId = 0;
686             mRemoteRequestMessageId = 0;
687             mLastSentRespMsgId = -1;
688 
689             mCollectedReqFragments = null;
690             mCollectedRespFragments = null;
691 
692             logKey("SK_d", skD);
693             logKey("SK_pi", skPi);
694             logKey("SK_pr", skPr);
695         }
696 
697         /**
698          * Package private interface for IkeSessionStateMachien to construct an IkeSaRecord
699          * instance.
700          */
makeFirstIkeSaRecord( IkeMessage initRequest, IkeMessage initResponse, IkeSecurityParameterIndex initSpi, IkeSecurityParameterIndex respSpi, IkeMacPrf prf, int integrityKeyLength, int encryptionKeyLength, SaLifetimeAlarmScheduler saLifetimeAlarmScheduler)701         static IkeSaRecord makeFirstIkeSaRecord(
702                 IkeMessage initRequest,
703                 IkeMessage initResponse,
704                 IkeSecurityParameterIndex initSpi,
705                 IkeSecurityParameterIndex respSpi,
706                 IkeMacPrf prf,
707                 int integrityKeyLength,
708                 int encryptionKeyLength,
709                 SaLifetimeAlarmScheduler saLifetimeAlarmScheduler)
710                 throws GeneralSecurityException {
711             return sSaRecordHelper.makeFirstIkeSaRecord(
712                     initRequest,
713                     initResponse,
714                     new IkeSaRecordConfig(
715                             initSpi,
716                             respSpi,
717                             prf,
718                             integrityKeyLength,
719                             encryptionKeyLength,
720                             true /*isLocalInit*/,
721                             saLifetimeAlarmScheduler));
722         }
723 
724         /** Package private */
makeRekeyedIkeSaRecord( IkeSaRecord oldSaRecord, IkeMacPrf oldPrf, IkeMessage rekeyRequest, IkeMessage rekeyResponse, IkeSecurityParameterIndex initSpi, IkeSecurityParameterIndex respSpi, IkeMacPrf prf, int integrityKeyLength, int encryptionKeyLength, boolean isLocalInit, SaLifetimeAlarmScheduler saLifetimeAlarmScheduler)725         static IkeSaRecord makeRekeyedIkeSaRecord(
726                 IkeSaRecord oldSaRecord,
727                 IkeMacPrf oldPrf,
728                 IkeMessage rekeyRequest,
729                 IkeMessage rekeyResponse,
730                 IkeSecurityParameterIndex initSpi,
731                 IkeSecurityParameterIndex respSpi,
732                 IkeMacPrf prf,
733                 int integrityKeyLength,
734                 int encryptionKeyLength,
735                 boolean isLocalInit,
736                 SaLifetimeAlarmScheduler saLifetimeAlarmScheduler)
737                 throws GeneralSecurityException {
738             return sSaRecordHelper.makeRekeyedIkeSaRecord(
739                     oldSaRecord,
740                     oldPrf,
741                     rekeyRequest,
742                     rekeyResponse,
743                     new IkeSaRecordConfig(
744                             initSpi,
745                             respSpi,
746                             prf,
747                             integrityKeyLength,
748                             encryptionKeyLength,
749                             isLocalInit,
750                             saLifetimeAlarmScheduler));
751         }
752 
logKey(String type, byte[] key)753         private void logKey(String type, byte[] key) {
754             getIkeLog().d(TAG, type + ": " + getIkeLog().pii(key));
755         }
756 
757         @Override
getTag()758         protected String getTag() {
759             return TAG;
760         }
761 
762         /** Package private */
getInitiatorSpi()763         long getInitiatorSpi() {
764             return mInitiatorSpiResource.getSpi();
765         }
766 
767         @VisibleForTesting
getInitiatorIkeSecurityParameterIndex()768         IkeSecurityParameterIndex getInitiatorIkeSecurityParameterIndex() {
769             return mInitiatorSpiResource;
770         }
771 
772         /** Package private */
getResponderSpi()773         long getResponderSpi() {
774             return mResponderSpiResource.getSpi();
775         }
776 
777         @VisibleForTesting
getResponderIkeSecurityParameterIndex()778         IkeSecurityParameterIndex getResponderIkeSecurityParameterIndex() {
779             return mResponderSpiResource;
780         }
781 
782         /** Get the locally generated IKE SPI */
getLocalSpi()783         public long getLocalSpi() {
784             return isLocalInit ? mInitiatorSpiResource.getSpi() : mResponderSpiResource.getSpi();
785         }
786 
787         /** Get the remotely generated IKE SPI */
getRemoteSpi()788         public long getRemoteSpi() {
789             return isLocalInit ? mResponderSpiResource.getSpi() : mInitiatorSpiResource.getSpi();
790         }
791 
792         /** Package private */
getSkD()793         byte[] getSkD() {
794             return mSkD;
795         }
796 
797         /**
798          * Get the PRF key of IKE initiator for building an outbound Auth Payload.
799          *
800          * @return the PRF key in a byte array.
801          */
getSkPi()802         public byte[] getSkPi() {
803             return mSkPi;
804         }
805 
806         /**
807          * Get the PRF key of IKE responder for validating an inbound Auth Payload.
808          *
809          * @return the PRF key in a byte array.
810          */
getSkPr()811         public byte[] getSkPr() {
812             return mSkPr;
813         }
814 
815         /**
816          * Compare with a specific IkeSaRecord
817          *
818          * @param record IkeSaRecord to be compared.
819          * @return a negative integer if input IkeSaRecord contains lowest nonce; a positive integer
820          *     if this IkeSaRecord has lowest nonce; return zero if lowest nonces of two
821          *     IkeSaRecords match.
822          */
compareTo(IkeSaRecord record)823         public int compareTo(IkeSaRecord record) {
824             // TODO: Implement it b/122924815.
825             return 1;
826         }
827 
828         /**
829          * Get current message ID for the local requesting window.
830          *
831          * <p>Called for building an outbound request or for validating the message ID of an inbound
832          * response.
833          *
834          * @return the local request message ID.
835          */
getLocalRequestMessageId()836         public int getLocalRequestMessageId() {
837             return mLocalRequestMessageId;
838         }
839 
840         /**
841          * Get current message ID for the remote requesting window.
842          *
843          * <p>Called for validating the message ID of an inbound request. If the message ID of the
844          * inbound request is smaller than the current remote message ID by one, it means the
845          * message is a retransmitted request.
846          *
847          * @return the remote request message ID
848          */
getRemoteRequestMessageId()849         public int getRemoteRequestMessageId() {
850             return mRemoteRequestMessageId;
851         }
852 
853         /**
854          * Increment the local request message ID by one.
855          *
856          * <p>It should be called when IKE library has received an authenticated and protected
857          * response with the correct local request message ID.
858          */
incrementLocalRequestMessageId()859         public void incrementLocalRequestMessageId() {
860             mLocalRequestMessageId++;
861         }
862 
863         /**
864          * Increment the remote request message ID by one.
865          *
866          * <p>It should be called when IKE library has received an authenticated and protected
867          * request with the correct remote request message ID.
868          */
incrementRemoteRequestMessageId()869         public void incrementRemoteRequestMessageId() {
870             mRemoteRequestMessageId++;
871         }
872 
873         /** Return all collected IKE fragments that have been collected. */
getCollectedFragments(boolean isResp)874         public DecodeResultPartial getCollectedFragments(boolean isResp) {
875             return isResp ? mCollectedRespFragments : mCollectedReqFragments;
876         }
877 
878         /**
879          * Update collected IKE fragments when receiving new IKE fragment.
880          *
881          * <p>TODO: b/140264067 Investigate if we need to support reassembling timeout. It is safe
882          * to do not support it because as an initiator, we will re-transmit the request anyway. As
883          * a responder, caching these fragments until getting a complete message won't affect
884          * anything.
885          */
updateCollectedFragments( DecodeResultPartial updatedFragments, boolean isResp)886         public void updateCollectedFragments(
887                 DecodeResultPartial updatedFragments, boolean isResp) {
888             if (isResp) {
889                 mCollectedRespFragments = updatedFragments;
890             } else {
891                 mCollectedReqFragments = updatedFragments;
892             }
893         }
894 
895         /** Reset collected IKE fragemnts */
resetCollectedFragments(boolean isResp)896         public void resetCollectedFragments(boolean isResp) {
897             updateCollectedFragments(null, isResp);
898         }
899 
900         /** Update first packet of last received request. */
updateLastReceivedReqFirstPacket(byte[] reqPacket)901         public void updateLastReceivedReqFirstPacket(byte[] reqPacket) {
902             mLastRecivedReqFirstPacket = reqPacket;
903         }
904 
905         /** Update all packets of last sent response. */
updateLastSentRespAllPackets(List<byte[]> respPacketList, int msgId)906         public void updateLastSentRespAllPackets(List<byte[]> respPacketList, int msgId) {
907             mLastSentRespAllPackets = respPacketList;
908             mLastSentRespMsgId = msgId;
909         }
910 
911         /** Return the message ID of the last sent out response. */
getLastSentRespMsgId()912         public int getLastSentRespMsgId() {
913             return mLastSentRespMsgId;
914         }
915 
916         /** Returns if received IKE packet is the first packet of a re-transmistted request. */
isRetransmittedRequest(byte[] request)917         public boolean isRetransmittedRequest(byte[] request) {
918             return Arrays.equals(mLastRecivedReqFirstPacket, request);
919         }
920 
921         /** Get all encoded packets of last sent response. */
getLastSentRespAllPackets()922         public List<byte[]> getLastSentRespAllPackets() {
923             return mLastSentRespAllPackets;
924         }
925 
926         /** Release IKE SPI resource. */
927         @Override
close()928         public void close() {
929             super.close();
930             mInitiatorSpiResource.unbindFromIkeSaRecord();
931             mResponderSpiResource.unbindFromIkeSaRecord();
932             mInitiatorSpiResource.close();
933             mResponderSpiResource.close();
934         }
935 
936         /** Migrate this IKE SA to the specified address pair. */
migrate(InetAddress initiatorAddress, InetAddress responderAddress)937         public void migrate(InetAddress initiatorAddress, InetAddress responderAddress)
938                 throws IOException {
939             mInitiatorSpiResource.migrate(initiatorAddress);
940             mResponderSpiResource.migrate(responderAddress);
941         }
942     }
943 
944     /** Package private class that groups parameters to construct an IkeSaRecord instance. */
945     @VisibleForTesting
946     static class IkeSaRecordConfig {
947         public final IkeSecurityParameterIndex initSpi;
948         public final IkeSecurityParameterIndex respSpi;
949         public final IkeMacPrf prf;
950         public final int integrityKeyLength;
951         public final int encryptionKeyLength;
952         public final boolean isLocalInit;
953         public final SaLifetimeAlarmScheduler saLifetimeAlarmScheduler;
954 
IkeSaRecordConfig( IkeSecurityParameterIndex initSpi, IkeSecurityParameterIndex respSpi, IkeMacPrf prf, int integrityKeyLength, int encryptionKeyLength, boolean isLocalInit, SaLifetimeAlarmScheduler saLifetimeAlarmScheduler)955         IkeSaRecordConfig(
956                 IkeSecurityParameterIndex initSpi,
957                 IkeSecurityParameterIndex respSpi,
958                 IkeMacPrf prf,
959                 int integrityKeyLength,
960                 int encryptionKeyLength,
961                 boolean isLocalInit,
962                 SaLifetimeAlarmScheduler saLifetimeAlarmScheduler) {
963             this.initSpi = initSpi;
964             this.respSpi = respSpi;
965             this.prf = prf;
966             this.integrityKeyLength = integrityKeyLength;
967             this.encryptionKeyLength = encryptionKeyLength;
968             this.isLocalInit = isLocalInit;
969             this.saLifetimeAlarmScheduler = saLifetimeAlarmScheduler;
970         }
971     }
972 
973     /** ChildSaRecord represents an Child SA. */
974     public static class ChildSaRecord extends SaRecord implements Comparable<ChildSaRecord> {
975         private static final String TAG = "ChildSaRecord";
976 
977         /** Locally generated SPI for receiving IPsec Packet. */
978         private final int mInboundSpi;
979         /** Remotely generated SPI for sending IPsec Packet. */
980         private final int mOutboundSpi;
981 
982         /** IPsec Transform applied to traffic towards the host. */
983         private final IpSecTransform mInboundTransform;
984         /** IPsec Transform applied to traffic from the host. */
985         private final IpSecTransform mOutboundTransform;
986 
987         /** Package private */
ChildSaRecord( int inSpi, int outSpi, boolean localInit, byte[] nonceInit, byte[] nonceResp, byte[] skAi, byte[] skAr, byte[] skEi, byte[] skEr, IpSecTransform inTransform, IpSecTransform outTransform, SaLifetimeAlarmScheduler saLifetimeAlarmScheduler)988         ChildSaRecord(
989                 int inSpi,
990                 int outSpi,
991                 boolean localInit,
992                 byte[] nonceInit,
993                 byte[] nonceResp,
994                 byte[] skAi,
995                 byte[] skAr,
996                 byte[] skEi,
997                 byte[] skEr,
998                 IpSecTransform inTransform,
999                 IpSecTransform outTransform,
1000                 SaLifetimeAlarmScheduler saLifetimeAlarmScheduler) {
1001             super(
1002                     localInit,
1003                     nonceInit,
1004                     nonceResp,
1005                     skAi,
1006                     skAr,
1007                     skEi,
1008                     skEr,
1009                     saLifetimeAlarmScheduler);
1010 
1011             mInboundSpi = inSpi;
1012             mOutboundSpi = outSpi;
1013             mInboundTransform = inTransform;
1014             mOutboundTransform = outTransform;
1015         }
1016 
1017         /**
1018          * Package private interface for ChildSessionStateMachine to construct a ChildSaRecord
1019          * instance.
1020          */
makeChildSaRecord( Context context, List<IkePayload> reqPayloads, List<IkePayload> respPayloads, SecurityParameterIndex initSpi, SecurityParameterIndex respSpi, InetAddress localAddress, InetAddress remoteAddress, @Nullable UdpEncapsulationSocket udpEncapSocket, IkeMacPrf prf, @Nullable IkeMacIntegrity integrityAlgo, IkeCipher encryptionAlgo, byte[] skD, boolean isTransport, boolean isLocalInit, SaLifetimeAlarmScheduler saLifetimeAlarmScheduler)1021         static ChildSaRecord makeChildSaRecord(
1022                 Context context,
1023                 List<IkePayload> reqPayloads,
1024                 List<IkePayload> respPayloads,
1025                 SecurityParameterIndex initSpi,
1026                 SecurityParameterIndex respSpi,
1027                 InetAddress localAddress,
1028                 InetAddress remoteAddress,
1029                 @Nullable UdpEncapsulationSocket udpEncapSocket,
1030                 IkeMacPrf prf,
1031                 @Nullable IkeMacIntegrity integrityAlgo,
1032                 IkeCipher encryptionAlgo,
1033                 byte[] skD,
1034                 boolean isTransport,
1035                 boolean isLocalInit,
1036                 SaLifetimeAlarmScheduler saLifetimeAlarmScheduler)
1037                 throws GeneralSecurityException, ResourceUnavailableException,
1038                         SpiUnavailableException, IOException {
1039             return sSaRecordHelper.makeChildSaRecord(
1040                     reqPayloads,
1041                     respPayloads,
1042                     new ChildSaRecordConfig(
1043                             context,
1044                             initSpi,
1045                             respSpi,
1046                             localAddress,
1047                             remoteAddress,
1048                             udpEncapSocket,
1049                             prf,
1050                             integrityAlgo,
1051                             encryptionAlgo,
1052                             skD,
1053                             isTransport,
1054                             isLocalInit,
1055                             saLifetimeAlarmScheduler));
1056         }
1057 
1058         @Override
getTag()1059         protected String getTag() {
1060             return TAG;
1061         }
1062 
1063         /** Package private */
getLocalSpi()1064         int getLocalSpi() {
1065             return mInboundSpi;
1066         }
1067 
1068         /** Package private */
getRemoteSpi()1069         int getRemoteSpi() {
1070             return mOutboundSpi;
1071         }
1072 
1073         /** Package private */
getInboundIpSecTransform()1074         IpSecTransform getInboundIpSecTransform() {
1075             return mInboundTransform;
1076         }
1077 
1078         /** Package private */
getOutboundIpSecTransform()1079         IpSecTransform getOutboundIpSecTransform() {
1080             return mOutboundTransform;
1081         }
1082 
1083         /**
1084          * Compare with a specific ChildSaRecord
1085          *
1086          * @param record ChildSaRecord to be compared.
1087          * @return a negative integer if input ChildSaRecord contains lowest nonce; a positive
1088          *     integer if this ChildSaRecord has lowest nonce; return zero if lowest nonces of two
1089          *     ChildSaRecord match.
1090          */
compareTo(ChildSaRecord record)1091         public int compareTo(ChildSaRecord record) {
1092             // TODO: Implement it b/122924815
1093             return 1;
1094         }
1095 
1096         /** Release IpSecTransform pair. */
1097         @Override
close()1098         public void close() {
1099             super.close();
1100             mInboundTransform.close();
1101             mOutboundTransform.close();
1102         }
1103     }
1104 
1105     /**
1106      * ISaRecordHelper provides a package private interface for constructing SaRecord.
1107      *
1108      * <p>ISaRecordHelper exists so that the interface is injectable for testing.
1109      */
1110     interface ISaRecordHelper {
1111         /**
1112          * Construct IkeSaRecord as results of IKE initial exchange.
1113          *
1114          * @param initRequest IKE_INIT request.
1115          * @param initResponse IKE_INIT request.
1116          * @param ikeSaRecordConfig that contains IKE SPI resources and negotiated algorithm
1117          *     information for constructing an IkeSaRecord instance.
1118          * @return ikeSaRecord for initial IKE SA.
1119          * @throws GeneralSecurityException if the DH public key in the response is invalid.
1120          */
makeFirstIkeSaRecord( IkeMessage initRequest, IkeMessage initResponse, IkeSaRecordConfig ikeSaRecordConfig)1121         IkeSaRecord makeFirstIkeSaRecord(
1122                 IkeMessage initRequest,
1123                 IkeMessage initResponse,
1124                 IkeSaRecordConfig ikeSaRecordConfig)
1125                 throws GeneralSecurityException;
1126 
1127         /**
1128          * Construct new IkeSaRecord when doing rekey.
1129          *
1130          * @param oldSaRecord old IKE SA
1131          * @param oldPrf the PRF function from the old SA
1132          * @param rekeyRequest Rekey IKE request.
1133          * @param rekeyResponse Rekey IKE response.
1134          * @param ikeSaRecordConfig that contains IKE SPI resources and negotiated algorithm
1135          *     information for constructing an IkeSaRecord instance.
1136          * @return ikeSaRecord for new IKE SA.
1137          */
makeRekeyedIkeSaRecord( IkeSaRecord oldSaRecord, IkeMacPrf oldPrf, IkeMessage rekeyRequest, IkeMessage rekeyResponse, IkeSaRecordConfig ikeSaRecordConfig)1138         IkeSaRecord makeRekeyedIkeSaRecord(
1139                 IkeSaRecord oldSaRecord,
1140                 IkeMacPrf oldPrf,
1141                 IkeMessage rekeyRequest,
1142                 IkeMessage rekeyResponse,
1143                 IkeSaRecordConfig ikeSaRecordConfig)
1144                 throws GeneralSecurityException;
1145 
1146         /**
1147          * Construct ChildSaRecord and generate IpSecTransform pairs.
1148          *
1149          * @param reqPayloads payload list in request.
1150          * @param respPayloads payload list in response.
1151          * @param childSaRecordConfig the grouped parameters for constructing ChildSaRecord.
1152          * @return new Child SA.
1153          */
makeChildSaRecord( List<IkePayload> reqPayloads, List<IkePayload> respPayloads, ChildSaRecordConfig childSaRecordConfig)1154         ChildSaRecord makeChildSaRecord(
1155                 List<IkePayload> reqPayloads,
1156                 List<IkePayload> respPayloads,
1157                 ChildSaRecordConfig childSaRecordConfig)
1158                 throws GeneralSecurityException, ResourceUnavailableException,
1159                         SpiUnavailableException, IOException;
1160     }
1161 
1162     /**
1163      * IIpSecTransformHelper provides a package private interface to construct {@link
1164      * IpSecTransform}
1165      *
1166      * <p>IIpSecTransformHelper exists so that the interface is injectable for testing.
1167      */
1168     @VisibleForTesting
1169     interface IIpSecTransformHelper {
1170         /**
1171          * Construct an instance of {@link IpSecTransform}
1172          *
1173          * @param context current context
1174          * @param sourceAddress the source {@code InetAddress} of traffic on sockets of interfaces
1175          *     that will use this transform
1176          * @param udpEncapSocket the UDP-Encap socket that allows IpSec traffic to pass through a
1177          *     NAT. Null if no NAT exists.
1178          * @param spi a unique {@link IpSecManager.SecurityParameterIndex} to identify transformed
1179          *     traffic
1180          * @param integrityAlgo specifying the authentication algorithm to be applied.
1181          * @param encryptionAlgo specifying the encryption algorithm or authenticated encryption
1182          *     algorithm to be applied.
1183          * @param integrityKey the negotiated authentication key to be applied.
1184          * @param encryptionKey the negotiated encryption key to be applied.
1185          * @param isTransport the flag indicates if a transport or a tunnel mode transform will be
1186          *     built.
1187          * @return an instance of {@link IpSecTransform}
1188          * @throws ResourceUnavailableException indicating that too many transforms are active
1189          * @throws SpiUnavailableException indicating the rare case where an SPI collides with an
1190          *     existing transform
1191          * @throws IOException indicating other errors
1192          */
makeIpSecTransform( Context context, InetAddress sourceAddress, UdpEncapsulationSocket udpEncapSocket, IpSecManager.SecurityParameterIndex spi, @Nullable IkeMacIntegrity integrityAlgo, IkeCipher encryptionAlgo, byte[] integrityKey, byte[] encryptionKey, boolean isTransport)1193         IpSecTransform makeIpSecTransform(
1194                 Context context,
1195                 InetAddress sourceAddress,
1196                 UdpEncapsulationSocket udpEncapSocket,
1197                 IpSecManager.SecurityParameterIndex spi,
1198                 @Nullable IkeMacIntegrity integrityAlgo,
1199                 IkeCipher encryptionAlgo,
1200                 byte[] integrityKey,
1201                 byte[] encryptionKey,
1202                 boolean isTransport)
1203                 throws ResourceUnavailableException, SpiUnavailableException, IOException;
1204     }
1205 }
1206