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