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, keRemotePayload.keyExchangeData);
263         }
264 
265         /**
266          * Package private method for calculating keys and construct IkeSaRecord.
267          *
268          * @see <a href="https://tools.ietf.org/html/rfc7296#section-2.13">RFC 7296, Internet Key
269          *     Exchange Protocol Version 2 (IKEv2), Generating Keying Material</a>
270          */
271         @VisibleForTesting
makeIkeSaRecord( byte[] sKeySeed, byte[] nonceInit, byte[] nonceResp, IkeSaRecordConfig ikeSaRecordConfig)272         IkeSaRecord makeIkeSaRecord(
273                 byte[] sKeySeed,
274                 byte[] nonceInit,
275                 byte[] nonceResp,
276                 IkeSaRecordConfig ikeSaRecordConfig) {
277             // Build data to sign for generating the keying material.
278             ByteBuffer bufferToSign =
279                     ByteBuffer.allocate(
280                             nonceInit.length + nonceResp.length + 2 * IkePayload.SPI_LEN_IKE);
281 
282             IkeSecurityParameterIndex initSpi = ikeSaRecordConfig.initSpi;
283             IkeSecurityParameterIndex respSpi = ikeSaRecordConfig.respSpi;
284             IkeMacPrf prf = ikeSaRecordConfig.prf;
285             int integrityKeyLength = ikeSaRecordConfig.integrityKeyLength;
286             int encryptionKeyLength = ikeSaRecordConfig.encryptionKeyLength;
287 
288             bufferToSign
289                     .put(nonceInit)
290                     .put(nonceResp)
291                     .putLong(initSpi.getSpi())
292                     .putLong(respSpi.getSpi());
293 
294             // Get length of the keying material according to RFC 7296, 2.13 and 2.14. The length of
295             // SK_D is always equal to the length of PRF key.
296             int skDLength = prf.getKeyLength();
297             int keyMaterialLen =
298                     skDLength
299                             + 2 * integrityKeyLength
300                             + 2 * encryptionKeyLength
301                             + 2 * prf.getKeyLength();
302             byte[] keyMat = prf.generateKeyMat(sKeySeed, bufferToSign.array(), keyMaterialLen);
303 
304             // Extract keys.
305             byte[] skD = new byte[skDLength];
306             byte[] skAi = new byte[integrityKeyLength];
307             byte[] skAr = new byte[integrityKeyLength];
308             byte[] skEi = new byte[encryptionKeyLength];
309             byte[] skEr = new byte[encryptionKeyLength];
310             byte[] skPi = new byte[prf.getKeyLength()];
311             byte[] skPr = new byte[prf.getKeyLength()];
312 
313             ByteBuffer keyMatBuffer = ByteBuffer.wrap(keyMat);
314             keyMatBuffer.get(skD).get(skAi).get(skAr).get(skEi).get(skEr).get(skPi).get(skPr);
315             return new IkeSaRecord(
316                     initSpi,
317                     respSpi,
318                     ikeSaRecordConfig.isLocalInit,
319                     nonceInit,
320                     nonceResp,
321                     skD,
322                     skAi,
323                     skAr,
324                     skEi,
325                     skEr,
326                     skPi,
327                     skPr,
328                     ikeSaRecordConfig.saLifetimeAlarmScheduler);
329         }
330 
331         @Override
makeChildSaRecord( List<IkePayload> reqPayloads, List<IkePayload> respPayloads, ChildSaRecordConfig childSaRecordConfig)332         public ChildSaRecord makeChildSaRecord(
333                 List<IkePayload> reqPayloads,
334                 List<IkePayload> respPayloads,
335                 ChildSaRecordConfig childSaRecordConfig)
336                 throws GeneralSecurityException, ResourceUnavailableException,
337                         SpiUnavailableException, IOException {
338             // Extract nonces. Encoding/Decoding of payload list guarantees that there is only one
339             // nonce payload in the reqPayloads and respPayloads lists
340             byte[] nonceInit =
341                     IkePayload.getPayloadForTypeInProvidedList(
342                                     IkePayload.PAYLOAD_TYPE_NONCE,
343                                     IkeNoncePayload.class,
344                                     reqPayloads)
345                             .nonceData;
346             byte[] nonceResp =
347                     IkePayload.getPayloadForTypeInProvidedList(
348                                     IkePayload.PAYLOAD_TYPE_NONCE,
349                                     IkeNoncePayload.class,
350                                     respPayloads)
351                             .nonceData;
352 
353             // Check if KE Payload exists and get DH shared key. Encoding/Decoding of payload list
354             // guarantees that there is either no KE payload in the reqPayloads and respPayloads
355             // lists, or only one KE payload in each list.
356             byte[] sharedDhKey = new byte[0];
357             IkeKePayload keInitPayload =
358                     IkePayload.getPayloadForTypeInProvidedList(
359                             IkePayload.PAYLOAD_TYPE_KE, IkeKePayload.class, reqPayloads);
360             if (keInitPayload != null) {
361                 IkeKePayload keRespPayload =
362                         IkePayload.getPayloadForTypeInProvidedList(
363                                 IkePayload.PAYLOAD_TYPE_KE, IkeKePayload.class, respPayloads);
364                 sharedDhKey =
365                         IkeKePayload.getSharedKey(
366                                 keInitPayload.localPrivateKey, keRespPayload.keyExchangeData);
367             }
368 
369             return makeChildSaRecord(sharedDhKey, nonceInit, nonceResp, childSaRecordConfig);
370         }
371         /**
372          * Package private method for calculating keys, build IpSecTransforms and construct
373          * ChildSaRecord.
374          *
375          * @see <a href="https://tools.ietf.org/html/rfc7296#section-2.17">RFC 7296, Internet Key
376          *     Exchange Protocol Version 2 (IKEv2), Generating Keying Material for Child SAs</a>
377          */
378         @VisibleForTesting
makeChildSaRecord( byte[] sharedKey, byte[] nonceInit, byte[] nonceResp, ChildSaRecordConfig childSaRecordConfig)379         ChildSaRecord makeChildSaRecord(
380                 byte[] sharedKey,
381                 byte[] nonceInit,
382                 byte[] nonceResp,
383                 ChildSaRecordConfig childSaRecordConfig)
384                 throws ResourceUnavailableException, SpiUnavailableException, IOException {
385             // Build data to sign for generating the keying material.
386             ByteBuffer bufferToSign =
387                     ByteBuffer.allocate(sharedKey.length + nonceInit.length + nonceResp.length);
388             bufferToSign.put(sharedKey).put(nonceInit).put(nonceResp);
389 
390             // Get length of the keying material according to RFC 7296, 2.17.
391             int encryptionKeyLength = childSaRecordConfig.encryptionAlgo.getKeyLength();
392             int integrityKeyLength =
393                     childSaRecordConfig.hasIntegrityAlgo
394                             ? childSaRecordConfig.integrityAlgo.getKeyLength()
395                             : 0;
396             int keyMaterialLen = 2 * encryptionKeyLength + 2 * integrityKeyLength;
397             byte[] keyMat =
398                     childSaRecordConfig.ikePrf.generateKeyMat(
399                             childSaRecordConfig.skD, bufferToSign.array(), keyMaterialLen);
400 
401             // Extract keys according to the order that keys carrying data from initiator to
402             // responder are taken before keys for the other direction and encryption keys are taken
403             // before integrity keys.
404             byte[] skEi = new byte[encryptionKeyLength];
405             byte[] skAi = new byte[integrityKeyLength];
406             byte[] skEr = new byte[encryptionKeyLength];
407             byte[] skAr = new byte[integrityKeyLength];
408 
409             ByteBuffer keyMatBuffer = ByteBuffer.wrap(keyMat);
410             keyMatBuffer.get(skEi).get(skAi).get(skEr).get(skAr);
411 
412             // IpSecTransform for traffic from the initiator
413             IpSecTransform initTransform = null;
414             // IpSecTransform for traffic from the responder
415             IpSecTransform respTransform = null;
416             try {
417                 // Build IpSecTransform
418                 initTransform =
419                         sIpSecTransformHelper.makeIpSecTransform(
420                                 childSaRecordConfig.context,
421                                 childSaRecordConfig.initAddress /*source address*/,
422                                 childSaRecordConfig.udpEncapSocket,
423                                 childSaRecordConfig.respSpi /*destination SPI*/,
424                                 childSaRecordConfig.integrityAlgo,
425                                 childSaRecordConfig.encryptionAlgo,
426                                 skAi,
427                                 skEi,
428                                 childSaRecordConfig.isTransport);
429                 respTransform =
430                         sIpSecTransformHelper.makeIpSecTransform(
431                                 childSaRecordConfig.context,
432                                 childSaRecordConfig.respAddress /*source address*/,
433                                 childSaRecordConfig.udpEncapSocket,
434                                 childSaRecordConfig.initSpi /*destination SPI*/,
435                                 childSaRecordConfig.integrityAlgo,
436                                 childSaRecordConfig.encryptionAlgo,
437                                 skAr,
438                                 skEr,
439                                 childSaRecordConfig.isTransport);
440 
441                 int initSpi = childSaRecordConfig.initSpi.getSpi();
442                 int respSpi = childSaRecordConfig.respSpi.getSpi();
443 
444                 boolean isLocalInit = childSaRecordConfig.isLocalInit;
445                 int inSpi = isLocalInit ? initSpi : respSpi;
446                 int outSpi = isLocalInit ? respSpi : initSpi;
447                 IpSecTransform inTransform = isLocalInit ? respTransform : initTransform;
448                 IpSecTransform outTransform = isLocalInit ? initTransform : respTransform;
449 
450                 return new ChildSaRecord(
451                         inSpi,
452                         outSpi,
453                         isLocalInit,
454                         nonceInit,
455                         nonceResp,
456                         skAi,
457                         skAr,
458                         skEi,
459                         skEr,
460                         inTransform,
461                         outTransform,
462                         childSaRecordConfig.saLifetimeAlarmScheduler);
463 
464             } catch (Exception e) {
465                 if (initTransform != null) initTransform.close();
466                 if (respTransform != null) respTransform.close();
467                 throw e;
468             }
469         }
470     }
471 
472     /**
473      * IpSecTransformHelper implements the IIpSecTransformHelper interface for constructing {@link
474      * IpSecTransform}}.
475      *
476      * <p>Package private
477      */
478     static class IpSecTransformHelper implements IIpSecTransformHelper {
479         private static final String TAG = "IpSecTransformHelper";
480 
481         @Override
makeIpSecTransform( Context context, InetAddress sourceAddress, UdpEncapsulationSocket udpEncapSocket, IpSecManager.SecurityParameterIndex spi, @Nullable IkeMacIntegrity integrityAlgo, IkeCipher encryptionAlgo, byte[] integrityKey, byte[] encryptionKey, boolean isTransport)482         public IpSecTransform makeIpSecTransform(
483                 Context context,
484                 InetAddress sourceAddress,
485                 UdpEncapsulationSocket udpEncapSocket,
486                 IpSecManager.SecurityParameterIndex spi,
487                 @Nullable IkeMacIntegrity integrityAlgo,
488                 IkeCipher encryptionAlgo,
489                 byte[] integrityKey,
490                 byte[] encryptionKey,
491                 boolean isTransport)
492                 throws ResourceUnavailableException, SpiUnavailableException, IOException {
493             IpSecTransform.Builder builder = new IpSecTransform.Builder(context);
494 
495             if (encryptionAlgo.isAead()) {
496                 builder.setAuthenticatedEncryption(
497                         encryptionAlgo.buildIpSecAlgorithmWithKey(encryptionKey));
498             } else {
499                 builder.setEncryption(encryptionAlgo.buildIpSecAlgorithmWithKey(encryptionKey));
500                 builder.setAuthentication(integrityAlgo.buildIpSecAlgorithmWithKey(integrityKey));
501             }
502 
503             if (udpEncapSocket != null && sourceAddress instanceof Inet6Address) {
504                 getIkeLog().wtf(TAG, "Kernel does not support UDP encapsulation for IPv6 SAs");
505             }
506             if (udpEncapSocket != null && sourceAddress instanceof Inet4Address) {
507                 builder.setIpv4Encapsulation(
508                         udpEncapSocket, IkeSocket.SERVER_PORT_UDP_ENCAPSULATED);
509             }
510 
511             if (isTransport) {
512                 return builder.buildTransportModeTransform(sourceAddress, spi);
513             } else {
514                 return builder.buildTunnelModeTransform(sourceAddress, spi);
515             }
516         }
517     }
518 
519     /** This class provides methods to schedule and cancel SA lifetime expiry alarm */
520     static class SaLifetimeAlarmScheduler {
521         private final long mDeleteDelayMs;
522         private final long mRekeyDelayMs;
523         private final PendingIntent mDeleteSaIntent;
524         private final PendingIntent mRekeySaIntent;
525         private final AlarmManager mAlarmManager;
526 
SaLifetimeAlarmScheduler( long deleteDelayMs, long rekeyDelayMs, PendingIntent deleteSaIntent, PendingIntent rekeySaIntent, AlarmManager alarmManager)527         SaLifetimeAlarmScheduler(
528                 long deleteDelayMs,
529                 long rekeyDelayMs,
530                 PendingIntent deleteSaIntent,
531                 PendingIntent rekeySaIntent,
532                 AlarmManager alarmManager) {
533             mDeleteDelayMs = deleteDelayMs;
534             mRekeyDelayMs = rekeyDelayMs;
535             mAlarmManager = alarmManager;
536             mDeleteSaIntent = deleteSaIntent;
537             mRekeySaIntent = rekeySaIntent;
538         }
539 
scheduleLifetimeExpiryAlarm(String tag)540         public void scheduleLifetimeExpiryAlarm(String tag) {
541             // Hard lifetime expiry alarm needs to be "setExact" considering the hard lifetime
542             // minimum value is 5 minutes and the inexact alarm might cause at most 75% of the
543             // scheduled interval delay because batching alarms. It is not necessay to wake up the
544             // alarm during doze mode because even the SA expires at that time, the device can not
545             // get access to network and won't expose more vulnerabilities.
546             mAlarmManager.setExact(
547                     AlarmManager.ELAPSED_REALTIME_WAKEUP,
548                     SystemClock.elapsedRealtime() + mDeleteDelayMs,
549                     mDeleteSaIntent);
550             mAlarmManager.setExactAndAllowWhileIdle(
551                     AlarmManager.ELAPSED_REALTIME_WAKEUP,
552                     SystemClock.elapsedRealtime() + mRekeyDelayMs,
553                     mRekeySaIntent);
554 
555             getIkeLog()
556                     .d(
557                             tag,
558                             "Lifetime alarm set: Hard lifetime ("
559                                     + mDeleteDelayMs
560                                     + "ms) Soft lifetime ("
561                                     + mRekeyDelayMs
562                                     + "ms)");
563         }
564 
rescheduleRekey(long retryDelayMs)565         public void rescheduleRekey(long retryDelayMs) {
566             mAlarmManager.setExactAndAllowWhileIdle(
567                     AlarmManager.ELAPSED_REALTIME_WAKEUP,
568                     SystemClock.elapsedRealtime() + retryDelayMs,
569                     mRekeySaIntent);
570         }
571 
cancelLifetimeExpiryAlarm(String tag)572         public void cancelLifetimeExpiryAlarm(String tag) {
573             mAlarmManager.cancel(mDeleteSaIntent);
574             mAlarmManager.cancel(mRekeySaIntent);
575             mDeleteSaIntent.cancel();
576             mRekeySaIntent.cancel();
577 
578             getIkeLog().d(tag, "Hard and soft lifetime alarm cancelled");
579         }
580     }
581 
582     /** Package private class to group parameters for building a ChildSaRecord. */
583     @VisibleForTesting
584     static final class ChildSaRecordConfig {
585         public final Context context;
586         public final SecurityParameterIndex initSpi;
587         public final SecurityParameterIndex respSpi;
588         public final InetAddress initAddress;
589         public final InetAddress respAddress;
590         @Nullable public final UdpEncapsulationSocket udpEncapSocket;
591         public final IkeMacPrf ikePrf;
592         @Nullable public final IkeMacIntegrity integrityAlgo;
593         public final IkeCipher encryptionAlgo;
594         public final byte[] skD;
595         public final boolean isTransport;
596         public final boolean isLocalInit;
597         public final boolean hasIntegrityAlgo;
598         public final SaLifetimeAlarmScheduler saLifetimeAlarmScheduler;
599 
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)600         ChildSaRecordConfig(
601                 Context context,
602                 SecurityParameterIndex initSpi,
603                 SecurityParameterIndex respSpi,
604                 InetAddress localAddress,
605                 InetAddress remoteAddress,
606                 @Nullable UdpEncapsulationSocket udpEncapSocket,
607                 IkeMacPrf ikePrf,
608                 @Nullable IkeMacIntegrity integrityAlgo,
609                 IkeCipher encryptionAlgo,
610                 byte[] skD,
611                 boolean isTransport,
612                 boolean isLocalInit,
613                 SaLifetimeAlarmScheduler saLifetimeAlarmScheduler) {
614             this.context = context;
615             this.initSpi = initSpi;
616             this.respSpi = respSpi;
617             this.initAddress = isLocalInit ? localAddress : remoteAddress;
618             this.respAddress = isLocalInit ? remoteAddress : localAddress;
619             this.udpEncapSocket = udpEncapSocket;
620             this.ikePrf = ikePrf;
621             this.integrityAlgo = integrityAlgo;
622             this.encryptionAlgo = encryptionAlgo;
623             this.skD = skD;
624             this.isTransport = isTransport;
625             this.isLocalInit = isLocalInit;
626             hasIntegrityAlgo = (integrityAlgo != null);
627             this.saLifetimeAlarmScheduler = saLifetimeAlarmScheduler;
628         }
629     }
630 
631     /** IkeSaRecord represents an IKE SA. */
632     public static class IkeSaRecord extends SaRecord implements Comparable<IkeSaRecord> {
633         private static final String TAG = "IkeSaRecord";
634 
635         /** SPI of IKE SA initiator */
636         private final IkeSecurityParameterIndex mInitiatorSpiResource;
637         /** SPI of IKE SA responder */
638         private final IkeSecurityParameterIndex mResponderSpiResource;
639 
640         private final byte[] mSkD;
641         private final byte[] mSkPi;
642         private final byte[] mSkPr;
643 
644         private int mLocalRequestMessageId;
645         private int mRemoteRequestMessageId;
646 
647         private DecodeResultPartial mCollectedReqFragments;
648         private DecodeResultPartial mCollectedRespFragments;
649 
650         private byte[] mLastRecivedReqFirstPacket;
651         private List<byte[]> mLastSentRespAllPackets;
652 
653         /** 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)654         IkeSaRecord(
655                 IkeSecurityParameterIndex initSpi,
656                 IkeSecurityParameterIndex respSpi,
657                 boolean localInit,
658                 byte[] nonceInit,
659                 byte[] nonceResp,
660                 byte[] skD,
661                 byte[] skAi,
662                 byte[] skAr,
663                 byte[] skEi,
664                 byte[] skEr,
665                 byte[] skPi,
666                 byte[] skPr,
667                 SaLifetimeAlarmScheduler saLifetimeAlarmScheduler) {
668             super(
669                     localInit,
670                     nonceInit,
671                     nonceResp,
672                     skAi,
673                     skAr,
674                     skEi,
675                     skEr,
676                     saLifetimeAlarmScheduler);
677 
678             mInitiatorSpiResource = initSpi;
679             mResponderSpiResource = respSpi;
680 
681             mSkD = skD;
682             mSkPi = skPi;
683             mSkPr = skPr;
684 
685             mLocalRequestMessageId = 0;
686             mRemoteRequestMessageId = 0;
687 
688             mCollectedReqFragments = null;
689             mCollectedRespFragments = null;
690 
691             logKey("SK_d", skD);
692             logKey("SK_pi", skPi);
693             logKey("SK_pr", skPr);
694         }
695 
696         /**
697          * Package private interface for IkeSessionStateMachien to construct an IkeSaRecord
698          * instance.
699          */
makeFirstIkeSaRecord( IkeMessage initRequest, IkeMessage initResponse, IkeSecurityParameterIndex initSpi, IkeSecurityParameterIndex respSpi, IkeMacPrf prf, int integrityKeyLength, int encryptionKeyLength, SaLifetimeAlarmScheduler saLifetimeAlarmScheduler)700         static IkeSaRecord makeFirstIkeSaRecord(
701                 IkeMessage initRequest,
702                 IkeMessage initResponse,
703                 IkeSecurityParameterIndex initSpi,
704                 IkeSecurityParameterIndex respSpi,
705                 IkeMacPrf prf,
706                 int integrityKeyLength,
707                 int encryptionKeyLength,
708                 SaLifetimeAlarmScheduler saLifetimeAlarmScheduler)
709                 throws GeneralSecurityException {
710             return sSaRecordHelper.makeFirstIkeSaRecord(
711                     initRequest,
712                     initResponse,
713                     new IkeSaRecordConfig(
714                             initSpi,
715                             respSpi,
716                             prf,
717                             integrityKeyLength,
718                             encryptionKeyLength,
719                             true /*isLocalInit*/,
720                             saLifetimeAlarmScheduler));
721         }
722 
723         /** 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)724         static IkeSaRecord makeRekeyedIkeSaRecord(
725                 IkeSaRecord oldSaRecord,
726                 IkeMacPrf oldPrf,
727                 IkeMessage rekeyRequest,
728                 IkeMessage rekeyResponse,
729                 IkeSecurityParameterIndex initSpi,
730                 IkeSecurityParameterIndex respSpi,
731                 IkeMacPrf prf,
732                 int integrityKeyLength,
733                 int encryptionKeyLength,
734                 boolean isLocalInit,
735                 SaLifetimeAlarmScheduler saLifetimeAlarmScheduler)
736                 throws GeneralSecurityException {
737             return sSaRecordHelper.makeRekeyedIkeSaRecord(
738                     oldSaRecord,
739                     oldPrf,
740                     rekeyRequest,
741                     rekeyResponse,
742                     new IkeSaRecordConfig(
743                             initSpi,
744                             respSpi,
745                             prf,
746                             integrityKeyLength,
747                             encryptionKeyLength,
748                             isLocalInit,
749                             saLifetimeAlarmScheduler));
750         }
751 
logKey(String type, byte[] key)752         private void logKey(String type, byte[] key) {
753             getIkeLog().d(TAG, type + ": " + getIkeLog().pii(key));
754         }
755 
756         @Override
getTag()757         protected String getTag() {
758             return TAG;
759         }
760 
761         /** Package private */
getInitiatorSpi()762         long getInitiatorSpi() {
763             return mInitiatorSpiResource.getSpi();
764         }
765 
766         /** Package private */
getResponderSpi()767         long getResponderSpi() {
768             return mResponderSpiResource.getSpi();
769         }
770 
771         /** Package private */
getLocalSpi()772         long getLocalSpi() {
773             return isLocalInit ? mInitiatorSpiResource.getSpi() : mResponderSpiResource.getSpi();
774         }
775 
776         /** Package private */
getRemoteSpi()777         long getRemoteSpi() {
778             return isLocalInit ? mResponderSpiResource.getSpi() : mInitiatorSpiResource.getSpi();
779         }
780 
781         /** Package private */
getSkD()782         byte[] getSkD() {
783             return mSkD;
784         }
785 
786         /**
787          * Get the PRF key of IKE initiator for building an outbound Auth Payload.
788          *
789          * @return the PRF key in a byte array.
790          */
getSkPi()791         public byte[] getSkPi() {
792             return mSkPi;
793         }
794 
795         /**
796          * Get the PRF key of IKE responder for validating an inbound Auth Payload.
797          *
798          * @return the PRF key in a byte array.
799          */
getSkPr()800         public byte[] getSkPr() {
801             return mSkPr;
802         }
803 
804         /**
805          * Compare with a specific IkeSaRecord
806          *
807          * @param record IkeSaRecord to be compared.
808          * @return a negative integer if input IkeSaRecord contains lowest nonce; a positive integer
809          *     if this IkeSaRecord has lowest nonce; return zero if lowest nonces of two
810          *     IkeSaRecords match.
811          */
compareTo(IkeSaRecord record)812         public int compareTo(IkeSaRecord record) {
813             // TODO: Implement it b/122924815.
814             return 1;
815         }
816 
817         /**
818          * Get current message ID for the local requesting window.
819          *
820          * <p>Called for building an outbound request or for validating the message ID of an inbound
821          * response.
822          *
823          * @return the local request message ID.
824          */
getLocalRequestMessageId()825         public int getLocalRequestMessageId() {
826             return mLocalRequestMessageId;
827         }
828 
829         /**
830          * Get current message ID for the remote requesting window.
831          *
832          * <p>Called for validating the message ID of an inbound request. If the message ID of the
833          * inbound request is smaller than the current remote message ID by one, it means the
834          * message is a retransmitted request.
835          *
836          * @return the remote request message ID
837          */
getRemoteRequestMessageId()838         public int getRemoteRequestMessageId() {
839             return mRemoteRequestMessageId;
840         }
841 
842         /**
843          * Increment the local request message ID by one.
844          *
845          * <p>It should be called when IKE library has received an authenticated and protected
846          * response with the correct local request message ID.
847          */
incrementLocalRequestMessageId()848         public void incrementLocalRequestMessageId() {
849             mLocalRequestMessageId++;
850         }
851 
852         /**
853          * Increment the remote request message ID by one.
854          *
855          * <p>It should be called when IKE library has received an authenticated and protected
856          * request with the correct remote request message ID.
857          */
incrementRemoteRequestMessageId()858         public void incrementRemoteRequestMessageId() {
859             mRemoteRequestMessageId++;
860         }
861 
862         /** Return all collected IKE fragments that have been collected. */
getCollectedFragments(boolean isResp)863         public DecodeResultPartial getCollectedFragments(boolean isResp) {
864             return isResp ? mCollectedRespFragments : mCollectedReqFragments;
865         }
866 
867         /**
868          * Update collected IKE fragments when receiving new IKE fragment.
869          *
870          * <p>TODO: b/140264067 Investigate if we need to support reassembling timeout. It is safe
871          * to do not support it because as an initiator, we will re-transmit the request anyway. As
872          * a responder, caching these fragments until getting a complete message won't affect
873          * anything.
874          */
updateCollectedFragments( DecodeResultPartial updatedFragments, boolean isResp)875         public void updateCollectedFragments(
876                 DecodeResultPartial updatedFragments, boolean isResp) {
877             if (isResp) {
878                 mCollectedRespFragments = updatedFragments;
879             } else {
880                 mCollectedReqFragments = updatedFragments;
881             }
882         }
883 
884         /** Reset collected IKE fragemnts */
resetCollectedFragments(boolean isResp)885         public void resetCollectedFragments(boolean isResp) {
886             updateCollectedFragments(null, isResp);
887         }
888 
889         /** Update first packet of last received request. */
updateLastReceivedReqFirstPacket(byte[] reqPacket)890         public void updateLastReceivedReqFirstPacket(byte[] reqPacket) {
891             mLastRecivedReqFirstPacket = reqPacket;
892         }
893 
894         /** Update all packets of last sent response. */
updateLastSentRespAllPackets(List<byte[]> respPacketList)895         public void updateLastSentRespAllPackets(List<byte[]> respPacketList) {
896             mLastSentRespAllPackets = respPacketList;
897         }
898 
899         /** Returns if received IKE packet is the first packet of a re-transmistted request. */
isRetransmittedRequest(byte[] request)900         public boolean isRetransmittedRequest(byte[] request) {
901             return Arrays.equals(mLastRecivedReqFirstPacket, request);
902         }
903 
904         /** Get all encoded packets of last sent response. */
getLastSentRespAllPackets()905         public List<byte[]> getLastSentRespAllPackets() {
906             return mLastSentRespAllPackets;
907         }
908 
909         /** Release IKE SPI resource. */
910         @Override
close()911         public void close() {
912             super.close();
913             mInitiatorSpiResource.close();
914             mResponderSpiResource.close();
915         }
916     }
917 
918     /** Package private class that groups parameters to construct an IkeSaRecord instance. */
919     @VisibleForTesting
920     static class IkeSaRecordConfig {
921         public final IkeSecurityParameterIndex initSpi;
922         public final IkeSecurityParameterIndex respSpi;
923         public final IkeMacPrf prf;
924         public final int integrityKeyLength;
925         public final int encryptionKeyLength;
926         public final boolean isLocalInit;
927         public final SaLifetimeAlarmScheduler saLifetimeAlarmScheduler;
928 
IkeSaRecordConfig( IkeSecurityParameterIndex initSpi, IkeSecurityParameterIndex respSpi, IkeMacPrf prf, int integrityKeyLength, int encryptionKeyLength, boolean isLocalInit, SaLifetimeAlarmScheduler saLifetimeAlarmScheduler)929         IkeSaRecordConfig(
930                 IkeSecurityParameterIndex initSpi,
931                 IkeSecurityParameterIndex respSpi,
932                 IkeMacPrf prf,
933                 int integrityKeyLength,
934                 int encryptionKeyLength,
935                 boolean isLocalInit,
936                 SaLifetimeAlarmScheduler saLifetimeAlarmScheduler) {
937             this.initSpi = initSpi;
938             this.respSpi = respSpi;
939             this.prf = prf;
940             this.integrityKeyLength = integrityKeyLength;
941             this.encryptionKeyLength = encryptionKeyLength;
942             this.isLocalInit = isLocalInit;
943             this.saLifetimeAlarmScheduler = saLifetimeAlarmScheduler;
944         }
945     }
946 
947     /** ChildSaRecord represents an Child SA. */
948     public static class ChildSaRecord extends SaRecord implements Comparable<ChildSaRecord> {
949         private static final String TAG = "ChildSaRecord";
950 
951         /** Locally generated SPI for receiving IPsec Packet. */
952         private final int mInboundSpi;
953         /** Remotely generated SPI for sending IPsec Packet. */
954         private final int mOutboundSpi;
955 
956         /** IPsec Transform applied to traffic towards the host. */
957         private final IpSecTransform mInboundTransform;
958         /** IPsec Transform applied to traffic from the host. */
959         private final IpSecTransform mOutboundTransform;
960 
961         /** 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)962         ChildSaRecord(
963                 int inSpi,
964                 int outSpi,
965                 boolean localInit,
966                 byte[] nonceInit,
967                 byte[] nonceResp,
968                 byte[] skAi,
969                 byte[] skAr,
970                 byte[] skEi,
971                 byte[] skEr,
972                 IpSecTransform inTransform,
973                 IpSecTransform outTransform,
974                 SaLifetimeAlarmScheduler saLifetimeAlarmScheduler) {
975             super(
976                     localInit,
977                     nonceInit,
978                     nonceResp,
979                     skAi,
980                     skAr,
981                     skEi,
982                     skEr,
983                     saLifetimeAlarmScheduler);
984 
985             mInboundSpi = inSpi;
986             mOutboundSpi = outSpi;
987             mInboundTransform = inTransform;
988             mOutboundTransform = outTransform;
989         }
990 
991         /**
992          * Package private interface for ChildSessionStateMachine to construct a ChildSaRecord
993          * instance.
994          */
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)995         static ChildSaRecord makeChildSaRecord(
996                 Context context,
997                 List<IkePayload> reqPayloads,
998                 List<IkePayload> respPayloads,
999                 SecurityParameterIndex initSpi,
1000                 SecurityParameterIndex respSpi,
1001                 InetAddress localAddress,
1002                 InetAddress remoteAddress,
1003                 @Nullable UdpEncapsulationSocket udpEncapSocket,
1004                 IkeMacPrf prf,
1005                 @Nullable IkeMacIntegrity integrityAlgo,
1006                 IkeCipher encryptionAlgo,
1007                 byte[] skD,
1008                 boolean isTransport,
1009                 boolean isLocalInit,
1010                 SaLifetimeAlarmScheduler saLifetimeAlarmScheduler)
1011                 throws GeneralSecurityException, ResourceUnavailableException,
1012                         SpiUnavailableException, IOException {
1013             return sSaRecordHelper.makeChildSaRecord(
1014                     reqPayloads,
1015                     respPayloads,
1016                     new ChildSaRecordConfig(
1017                             context,
1018                             initSpi,
1019                             respSpi,
1020                             localAddress,
1021                             remoteAddress,
1022                             udpEncapSocket,
1023                             prf,
1024                             integrityAlgo,
1025                             encryptionAlgo,
1026                             skD,
1027                             isTransport,
1028                             isLocalInit,
1029                             saLifetimeAlarmScheduler));
1030         }
1031 
1032         @Override
getTag()1033         protected String getTag() {
1034             return TAG;
1035         }
1036 
1037         /** Package private */
getLocalSpi()1038         int getLocalSpi() {
1039             return mInboundSpi;
1040         }
1041 
1042         /** Package private */
getRemoteSpi()1043         int getRemoteSpi() {
1044             return mOutboundSpi;
1045         }
1046 
1047         /** Package private */
getInboundIpSecTransform()1048         IpSecTransform getInboundIpSecTransform() {
1049             return mInboundTransform;
1050         }
1051 
1052         /** Package private */
getOutboundIpSecTransform()1053         IpSecTransform getOutboundIpSecTransform() {
1054             return mOutboundTransform;
1055         }
1056 
1057         /**
1058          * Compare with a specific ChildSaRecord
1059          *
1060          * @param record ChildSaRecord to be compared.
1061          * @return a negative integer if input ChildSaRecord contains lowest nonce; a positive
1062          *     integer if this ChildSaRecord has lowest nonce; return zero if lowest nonces of two
1063          *     ChildSaRecord match.
1064          */
compareTo(ChildSaRecord record)1065         public int compareTo(ChildSaRecord record) {
1066             // TODO: Implement it b/122924815
1067             return 1;
1068         }
1069 
1070         /** Release IpSecTransform pair. */
1071         @Override
close()1072         public void close() {
1073             super.close();
1074             mInboundTransform.close();
1075             mOutboundTransform.close();
1076         }
1077     }
1078 
1079     /**
1080      * ISaRecordHelper provides a package private interface for constructing SaRecord.
1081      *
1082      * <p>ISaRecordHelper exists so that the interface is injectable for testing.
1083      */
1084     interface ISaRecordHelper {
1085         /**
1086          * Construct IkeSaRecord as results of IKE initial exchange.
1087          *
1088          * @param initRequest IKE_INIT request.
1089          * @param initResponse IKE_INIT request.
1090          * @param ikeSaRecordConfig that contains IKE SPI resources and negotiated algorithm
1091          *     information for constructing an IkeSaRecord instance.
1092          * @return ikeSaRecord for initial IKE SA.
1093          * @throws GeneralSecurityException if the DH public key in the response is invalid.
1094          */
makeFirstIkeSaRecord( IkeMessage initRequest, IkeMessage initResponse, IkeSaRecordConfig ikeSaRecordConfig)1095         IkeSaRecord makeFirstIkeSaRecord(
1096                 IkeMessage initRequest,
1097                 IkeMessage initResponse,
1098                 IkeSaRecordConfig ikeSaRecordConfig)
1099                 throws GeneralSecurityException;
1100 
1101         /**
1102          * Construct new IkeSaRecord when doing rekey.
1103          *
1104          * @param oldSaRecord old IKE SA
1105          * @param oldPrf the PRF function from the old SA
1106          * @param rekeyRequest Rekey IKE request.
1107          * @param rekeyResponse Rekey IKE response.
1108          * @param ikeSaRecordConfig that contains IKE SPI resources and negotiated algorithm
1109          *     information for constructing an IkeSaRecord instance.
1110          * @return ikeSaRecord for new IKE SA.
1111          */
makeRekeyedIkeSaRecord( IkeSaRecord oldSaRecord, IkeMacPrf oldPrf, IkeMessage rekeyRequest, IkeMessage rekeyResponse, IkeSaRecordConfig ikeSaRecordConfig)1112         IkeSaRecord makeRekeyedIkeSaRecord(
1113                 IkeSaRecord oldSaRecord,
1114                 IkeMacPrf oldPrf,
1115                 IkeMessage rekeyRequest,
1116                 IkeMessage rekeyResponse,
1117                 IkeSaRecordConfig ikeSaRecordConfig)
1118                 throws GeneralSecurityException;
1119 
1120         /**
1121          * Construct ChildSaRecord and generate IpSecTransform pairs.
1122          *
1123          * @param reqPayloads payload list in request.
1124          * @param respPayloads payload list in response.
1125          * @param childSaRecordConfig the grouped parameters for constructing ChildSaRecord.
1126          * @return new Child SA.
1127          */
makeChildSaRecord( List<IkePayload> reqPayloads, List<IkePayload> respPayloads, ChildSaRecordConfig childSaRecordConfig)1128         ChildSaRecord makeChildSaRecord(
1129                 List<IkePayload> reqPayloads,
1130                 List<IkePayload> respPayloads,
1131                 ChildSaRecordConfig childSaRecordConfig)
1132                 throws GeneralSecurityException, ResourceUnavailableException,
1133                         SpiUnavailableException, IOException;
1134     }
1135 
1136     /**
1137      * IIpSecTransformHelper provides a package private interface to construct {@link
1138      * IpSecTransform}
1139      *
1140      * <p>IIpSecTransformHelper exists so that the interface is injectable for testing.
1141      */
1142     @VisibleForTesting
1143     interface IIpSecTransformHelper {
1144         /**
1145          * Construct an instance of {@link IpSecTransform}
1146          *
1147          * @param context current context
1148          * @param sourceAddress the source {@code InetAddress} of traffic on sockets of interfaces
1149          *     that will use this transform
1150          * @param udpEncapSocket the UDP-Encap socket that allows IpSec traffic to pass through a
1151          *     NAT. Null if no NAT exists.
1152          * @param spi a unique {@link IpSecManager.SecurityParameterIndex} to identify transformed
1153          *     traffic
1154          * @param integrityAlgo specifying the authentication algorithm to be applied.
1155          * @param encryptionAlgo specifying the encryption algorithm or authenticated encryption
1156          *     algorithm to be applied.
1157          * @param integrityKey the negotiated authentication key to be applied.
1158          * @param encryptionKey the negotiated encryption key to be applied.
1159          * @param isTransport the flag indicates if a transport or a tunnel mode transform will be
1160          *     built.
1161          * @return an instance of {@link IpSecTransform}
1162          * @throws ResourceUnavailableException indicating that too many transforms are active
1163          * @throws SpiUnavailableException indicating the rare case where an SPI collides with an
1164          *     existing transform
1165          * @throws IOException indicating other errors
1166          */
makeIpSecTransform( Context context, InetAddress sourceAddress, UdpEncapsulationSocket udpEncapSocket, IpSecManager.SecurityParameterIndex spi, @Nullable IkeMacIntegrity integrityAlgo, IkeCipher encryptionAlgo, byte[] integrityKey, byte[] encryptionKey, boolean isTransport)1167         IpSecTransform makeIpSecTransform(
1168                 Context context,
1169                 InetAddress sourceAddress,
1170                 UdpEncapsulationSocket udpEncapSocket,
1171                 IpSecManager.SecurityParameterIndex spi,
1172                 @Nullable IkeMacIntegrity integrityAlgo,
1173                 IkeCipher encryptionAlgo,
1174                 byte[] integrityKey,
1175                 byte[] encryptionKey,
1176                 boolean isTransport)
1177                 throws ResourceUnavailableException, SpiUnavailableException, IOException;
1178     }
1179 }
1180