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