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