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