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