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 mInitiatorSpiResource.bindToIkeSaRecord(); 679 mResponderSpiResource.bindToIkeSaRecord(); 680 681 mSkD = skD; 682 mSkPi = skPi; 683 mSkPr = skPr; 684 685 mLocalRequestMessageId = 0; 686 mRemoteRequestMessageId = 0; 687 mLastSentRespMsgId = -1; 688 689 mCollectedReqFragments = null; 690 mCollectedRespFragments = null; 691 692 logKey("SK_d", skD); 693 logKey("SK_pi", skPi); 694 logKey("SK_pr", skPr); 695 } 696 697 /** 698 * Package private interface for IkeSessionStateMachien to construct an IkeSaRecord 699 * instance. 700 */ makeFirstIkeSaRecord( IkeMessage initRequest, IkeMessage initResponse, IkeSecurityParameterIndex initSpi, IkeSecurityParameterIndex respSpi, IkeMacPrf prf, int integrityKeyLength, int encryptionKeyLength, SaLifetimeAlarmScheduler saLifetimeAlarmScheduler)701 static IkeSaRecord makeFirstIkeSaRecord( 702 IkeMessage initRequest, 703 IkeMessage initResponse, 704 IkeSecurityParameterIndex initSpi, 705 IkeSecurityParameterIndex respSpi, 706 IkeMacPrf prf, 707 int integrityKeyLength, 708 int encryptionKeyLength, 709 SaLifetimeAlarmScheduler saLifetimeAlarmScheduler) 710 throws GeneralSecurityException { 711 return sSaRecordHelper.makeFirstIkeSaRecord( 712 initRequest, 713 initResponse, 714 new IkeSaRecordConfig( 715 initSpi, 716 respSpi, 717 prf, 718 integrityKeyLength, 719 encryptionKeyLength, 720 true /*isLocalInit*/, 721 saLifetimeAlarmScheduler)); 722 } 723 724 /** 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)725 static IkeSaRecord makeRekeyedIkeSaRecord( 726 IkeSaRecord oldSaRecord, 727 IkeMacPrf oldPrf, 728 IkeMessage rekeyRequest, 729 IkeMessage rekeyResponse, 730 IkeSecurityParameterIndex initSpi, 731 IkeSecurityParameterIndex respSpi, 732 IkeMacPrf prf, 733 int integrityKeyLength, 734 int encryptionKeyLength, 735 boolean isLocalInit, 736 SaLifetimeAlarmScheduler saLifetimeAlarmScheduler) 737 throws GeneralSecurityException { 738 return sSaRecordHelper.makeRekeyedIkeSaRecord( 739 oldSaRecord, 740 oldPrf, 741 rekeyRequest, 742 rekeyResponse, 743 new IkeSaRecordConfig( 744 initSpi, 745 respSpi, 746 prf, 747 integrityKeyLength, 748 encryptionKeyLength, 749 isLocalInit, 750 saLifetimeAlarmScheduler)); 751 } 752 logKey(String type, byte[] key)753 private void logKey(String type, byte[] key) { 754 getIkeLog().d(TAG, type + ": " + getIkeLog().pii(key)); 755 } 756 757 @Override getTag()758 protected String getTag() { 759 return TAG; 760 } 761 762 /** Package private */ getInitiatorSpi()763 long getInitiatorSpi() { 764 return mInitiatorSpiResource.getSpi(); 765 } 766 767 @VisibleForTesting getInitiatorIkeSecurityParameterIndex()768 IkeSecurityParameterIndex getInitiatorIkeSecurityParameterIndex() { 769 return mInitiatorSpiResource; 770 } 771 772 /** Package private */ getResponderSpi()773 long getResponderSpi() { 774 return mResponderSpiResource.getSpi(); 775 } 776 777 @VisibleForTesting getResponderIkeSecurityParameterIndex()778 IkeSecurityParameterIndex getResponderIkeSecurityParameterIndex() { 779 return mResponderSpiResource; 780 } 781 782 /** Get the locally generated IKE SPI */ getLocalSpi()783 public long getLocalSpi() { 784 return isLocalInit ? mInitiatorSpiResource.getSpi() : mResponderSpiResource.getSpi(); 785 } 786 787 /** Get the remotely generated IKE SPI */ getRemoteSpi()788 public long getRemoteSpi() { 789 return isLocalInit ? mResponderSpiResource.getSpi() : mInitiatorSpiResource.getSpi(); 790 } 791 792 /** Package private */ getSkD()793 byte[] getSkD() { 794 return mSkD; 795 } 796 797 /** 798 * Get the PRF key of IKE initiator for building an outbound Auth Payload. 799 * 800 * @return the PRF key in a byte array. 801 */ getSkPi()802 public byte[] getSkPi() { 803 return mSkPi; 804 } 805 806 /** 807 * Get the PRF key of IKE responder for validating an inbound Auth Payload. 808 * 809 * @return the PRF key in a byte array. 810 */ getSkPr()811 public byte[] getSkPr() { 812 return mSkPr; 813 } 814 815 /** 816 * Compare with a specific IkeSaRecord 817 * 818 * @param record IkeSaRecord to be compared. 819 * @return a negative integer if input IkeSaRecord contains lowest nonce; a positive integer 820 * if this IkeSaRecord has lowest nonce; return zero if lowest nonces of two 821 * IkeSaRecords match. 822 */ compareTo(IkeSaRecord record)823 public int compareTo(IkeSaRecord record) { 824 // TODO: Implement it b/122924815. 825 return 1; 826 } 827 828 /** 829 * Get current message ID for the local requesting window. 830 * 831 * <p>Called for building an outbound request or for validating the message ID of an inbound 832 * response. 833 * 834 * @return the local request message ID. 835 */ getLocalRequestMessageId()836 public int getLocalRequestMessageId() { 837 return mLocalRequestMessageId; 838 } 839 840 /** 841 * Get current message ID for the remote requesting window. 842 * 843 * <p>Called for validating the message ID of an inbound request. If the message ID of the 844 * inbound request is smaller than the current remote message ID by one, it means the 845 * message is a retransmitted request. 846 * 847 * @return the remote request message ID 848 */ getRemoteRequestMessageId()849 public int getRemoteRequestMessageId() { 850 return mRemoteRequestMessageId; 851 } 852 853 /** 854 * Increment the local request message ID by one. 855 * 856 * <p>It should be called when IKE library has received an authenticated and protected 857 * response with the correct local request message ID. 858 */ incrementLocalRequestMessageId()859 public void incrementLocalRequestMessageId() { 860 mLocalRequestMessageId++; 861 } 862 863 /** 864 * Increment the remote request message ID by one. 865 * 866 * <p>It should be called when IKE library has received an authenticated and protected 867 * request with the correct remote request message ID. 868 */ incrementRemoteRequestMessageId()869 public void incrementRemoteRequestMessageId() { 870 mRemoteRequestMessageId++; 871 } 872 873 /** Return all collected IKE fragments that have been collected. */ getCollectedFragments(boolean isResp)874 public DecodeResultPartial getCollectedFragments(boolean isResp) { 875 return isResp ? mCollectedRespFragments : mCollectedReqFragments; 876 } 877 878 /** 879 * Update collected IKE fragments when receiving new IKE fragment. 880 * 881 * <p>TODO: b/140264067 Investigate if we need to support reassembling timeout. It is safe 882 * to do not support it because as an initiator, we will re-transmit the request anyway. As 883 * a responder, caching these fragments until getting a complete message won't affect 884 * anything. 885 */ updateCollectedFragments( DecodeResultPartial updatedFragments, boolean isResp)886 public void updateCollectedFragments( 887 DecodeResultPartial updatedFragments, boolean isResp) { 888 if (isResp) { 889 mCollectedRespFragments = updatedFragments; 890 } else { 891 mCollectedReqFragments = updatedFragments; 892 } 893 } 894 895 /** Reset collected IKE fragemnts */ resetCollectedFragments(boolean isResp)896 public void resetCollectedFragments(boolean isResp) { 897 updateCollectedFragments(null, isResp); 898 } 899 900 /** Update first packet of last received request. */ updateLastReceivedReqFirstPacket(byte[] reqPacket)901 public void updateLastReceivedReqFirstPacket(byte[] reqPacket) { 902 mLastRecivedReqFirstPacket = reqPacket; 903 } 904 905 /** Update all packets of last sent response. */ updateLastSentRespAllPackets(List<byte[]> respPacketList, int msgId)906 public void updateLastSentRespAllPackets(List<byte[]> respPacketList, int msgId) { 907 mLastSentRespAllPackets = respPacketList; 908 mLastSentRespMsgId = msgId; 909 } 910 911 /** Return the message ID of the last sent out response. */ getLastSentRespMsgId()912 public int getLastSentRespMsgId() { 913 return mLastSentRespMsgId; 914 } 915 916 /** Returns if received IKE packet is the first packet of a re-transmistted request. */ isRetransmittedRequest(byte[] request)917 public boolean isRetransmittedRequest(byte[] request) { 918 return Arrays.equals(mLastRecivedReqFirstPacket, request); 919 } 920 921 /** Get all encoded packets of last sent response. */ getLastSentRespAllPackets()922 public List<byte[]> getLastSentRespAllPackets() { 923 return mLastSentRespAllPackets; 924 } 925 926 /** Release IKE SPI resource. */ 927 @Override close()928 public void close() { 929 super.close(); 930 mInitiatorSpiResource.unbindFromIkeSaRecord(); 931 mResponderSpiResource.unbindFromIkeSaRecord(); 932 mInitiatorSpiResource.close(); 933 mResponderSpiResource.close(); 934 } 935 936 /** Migrate this IKE SA to the specified address pair. */ migrate(InetAddress initiatorAddress, InetAddress responderAddress)937 public void migrate(InetAddress initiatorAddress, InetAddress responderAddress) 938 throws IOException { 939 mInitiatorSpiResource.migrate(initiatorAddress); 940 mResponderSpiResource.migrate(responderAddress); 941 } 942 } 943 944 /** Package private class that groups parameters to construct an IkeSaRecord instance. */ 945 @VisibleForTesting 946 static class IkeSaRecordConfig { 947 public final IkeSecurityParameterIndex initSpi; 948 public final IkeSecurityParameterIndex respSpi; 949 public final IkeMacPrf prf; 950 public final int integrityKeyLength; 951 public final int encryptionKeyLength; 952 public final boolean isLocalInit; 953 public final SaLifetimeAlarmScheduler saLifetimeAlarmScheduler; 954 IkeSaRecordConfig( IkeSecurityParameterIndex initSpi, IkeSecurityParameterIndex respSpi, IkeMacPrf prf, int integrityKeyLength, int encryptionKeyLength, boolean isLocalInit, SaLifetimeAlarmScheduler saLifetimeAlarmScheduler)955 IkeSaRecordConfig( 956 IkeSecurityParameterIndex initSpi, 957 IkeSecurityParameterIndex respSpi, 958 IkeMacPrf prf, 959 int integrityKeyLength, 960 int encryptionKeyLength, 961 boolean isLocalInit, 962 SaLifetimeAlarmScheduler saLifetimeAlarmScheduler) { 963 this.initSpi = initSpi; 964 this.respSpi = respSpi; 965 this.prf = prf; 966 this.integrityKeyLength = integrityKeyLength; 967 this.encryptionKeyLength = encryptionKeyLength; 968 this.isLocalInit = isLocalInit; 969 this.saLifetimeAlarmScheduler = saLifetimeAlarmScheduler; 970 } 971 } 972 973 /** ChildSaRecord represents an Child SA. */ 974 public static class ChildSaRecord extends SaRecord implements Comparable<ChildSaRecord> { 975 private static final String TAG = "ChildSaRecord"; 976 977 /** Locally generated SPI for receiving IPsec Packet. */ 978 private final int mInboundSpi; 979 /** Remotely generated SPI for sending IPsec Packet. */ 980 private final int mOutboundSpi; 981 982 /** IPsec Transform applied to traffic towards the host. */ 983 private final IpSecTransform mInboundTransform; 984 /** IPsec Transform applied to traffic from the host. */ 985 private final IpSecTransform mOutboundTransform; 986 987 /** 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)988 ChildSaRecord( 989 int inSpi, 990 int outSpi, 991 boolean localInit, 992 byte[] nonceInit, 993 byte[] nonceResp, 994 byte[] skAi, 995 byte[] skAr, 996 byte[] skEi, 997 byte[] skEr, 998 IpSecTransform inTransform, 999 IpSecTransform outTransform, 1000 SaLifetimeAlarmScheduler saLifetimeAlarmScheduler) { 1001 super( 1002 localInit, 1003 nonceInit, 1004 nonceResp, 1005 skAi, 1006 skAr, 1007 skEi, 1008 skEr, 1009 saLifetimeAlarmScheduler); 1010 1011 mInboundSpi = inSpi; 1012 mOutboundSpi = outSpi; 1013 mInboundTransform = inTransform; 1014 mOutboundTransform = outTransform; 1015 } 1016 1017 /** 1018 * Package private interface for ChildSessionStateMachine to construct a ChildSaRecord 1019 * instance. 1020 */ 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)1021 static ChildSaRecord makeChildSaRecord( 1022 Context context, 1023 List<IkePayload> reqPayloads, 1024 List<IkePayload> respPayloads, 1025 SecurityParameterIndex initSpi, 1026 SecurityParameterIndex respSpi, 1027 InetAddress localAddress, 1028 InetAddress remoteAddress, 1029 @Nullable UdpEncapsulationSocket udpEncapSocket, 1030 IkeMacPrf prf, 1031 @Nullable IkeMacIntegrity integrityAlgo, 1032 IkeCipher encryptionAlgo, 1033 byte[] skD, 1034 boolean isTransport, 1035 boolean isLocalInit, 1036 SaLifetimeAlarmScheduler saLifetimeAlarmScheduler) 1037 throws GeneralSecurityException, ResourceUnavailableException, 1038 SpiUnavailableException, IOException { 1039 return sSaRecordHelper.makeChildSaRecord( 1040 reqPayloads, 1041 respPayloads, 1042 new ChildSaRecordConfig( 1043 context, 1044 initSpi, 1045 respSpi, 1046 localAddress, 1047 remoteAddress, 1048 udpEncapSocket, 1049 prf, 1050 integrityAlgo, 1051 encryptionAlgo, 1052 skD, 1053 isTransport, 1054 isLocalInit, 1055 saLifetimeAlarmScheduler)); 1056 } 1057 1058 @Override getTag()1059 protected String getTag() { 1060 return TAG; 1061 } 1062 1063 /** Package private */ getLocalSpi()1064 int getLocalSpi() { 1065 return mInboundSpi; 1066 } 1067 1068 /** Package private */ getRemoteSpi()1069 int getRemoteSpi() { 1070 return mOutboundSpi; 1071 } 1072 1073 /** Package private */ getInboundIpSecTransform()1074 IpSecTransform getInboundIpSecTransform() { 1075 return mInboundTransform; 1076 } 1077 1078 /** Package private */ getOutboundIpSecTransform()1079 IpSecTransform getOutboundIpSecTransform() { 1080 return mOutboundTransform; 1081 } 1082 1083 /** 1084 * Compare with a specific ChildSaRecord 1085 * 1086 * @param record ChildSaRecord to be compared. 1087 * @return a negative integer if input ChildSaRecord contains lowest nonce; a positive 1088 * integer if this ChildSaRecord has lowest nonce; return zero if lowest nonces of two 1089 * ChildSaRecord match. 1090 */ compareTo(ChildSaRecord record)1091 public int compareTo(ChildSaRecord record) { 1092 // TODO: Implement it b/122924815 1093 return 1; 1094 } 1095 1096 /** Release IpSecTransform pair. */ 1097 @Override close()1098 public void close() { 1099 super.close(); 1100 mInboundTransform.close(); 1101 mOutboundTransform.close(); 1102 } 1103 } 1104 1105 /** 1106 * ISaRecordHelper provides a package private interface for constructing SaRecord. 1107 * 1108 * <p>ISaRecordHelper exists so that the interface is injectable for testing. 1109 */ 1110 interface ISaRecordHelper { 1111 /** 1112 * Construct IkeSaRecord as results of IKE initial exchange. 1113 * 1114 * @param initRequest IKE_INIT request. 1115 * @param initResponse IKE_INIT request. 1116 * @param ikeSaRecordConfig that contains IKE SPI resources and negotiated algorithm 1117 * information for constructing an IkeSaRecord instance. 1118 * @return ikeSaRecord for initial IKE SA. 1119 * @throws GeneralSecurityException if the DH public key in the response is invalid. 1120 */ makeFirstIkeSaRecord( IkeMessage initRequest, IkeMessage initResponse, IkeSaRecordConfig ikeSaRecordConfig)1121 IkeSaRecord makeFirstIkeSaRecord( 1122 IkeMessage initRequest, 1123 IkeMessage initResponse, 1124 IkeSaRecordConfig ikeSaRecordConfig) 1125 throws GeneralSecurityException; 1126 1127 /** 1128 * Construct new IkeSaRecord when doing rekey. 1129 * 1130 * @param oldSaRecord old IKE SA 1131 * @param oldPrf the PRF function from the old SA 1132 * @param rekeyRequest Rekey IKE request. 1133 * @param rekeyResponse Rekey IKE response. 1134 * @param ikeSaRecordConfig that contains IKE SPI resources and negotiated algorithm 1135 * information for constructing an IkeSaRecord instance. 1136 * @return ikeSaRecord for new IKE SA. 1137 */ makeRekeyedIkeSaRecord( IkeSaRecord oldSaRecord, IkeMacPrf oldPrf, IkeMessage rekeyRequest, IkeMessage rekeyResponse, IkeSaRecordConfig ikeSaRecordConfig)1138 IkeSaRecord makeRekeyedIkeSaRecord( 1139 IkeSaRecord oldSaRecord, 1140 IkeMacPrf oldPrf, 1141 IkeMessage rekeyRequest, 1142 IkeMessage rekeyResponse, 1143 IkeSaRecordConfig ikeSaRecordConfig) 1144 throws GeneralSecurityException; 1145 1146 /** 1147 * Construct ChildSaRecord and generate IpSecTransform pairs. 1148 * 1149 * @param reqPayloads payload list in request. 1150 * @param respPayloads payload list in response. 1151 * @param childSaRecordConfig the grouped parameters for constructing ChildSaRecord. 1152 * @return new Child SA. 1153 */ makeChildSaRecord( List<IkePayload> reqPayloads, List<IkePayload> respPayloads, ChildSaRecordConfig childSaRecordConfig)1154 ChildSaRecord makeChildSaRecord( 1155 List<IkePayload> reqPayloads, 1156 List<IkePayload> respPayloads, 1157 ChildSaRecordConfig childSaRecordConfig) 1158 throws GeneralSecurityException, ResourceUnavailableException, 1159 SpiUnavailableException, IOException; 1160 } 1161 1162 /** 1163 * IIpSecTransformHelper provides a package private interface to construct {@link 1164 * IpSecTransform} 1165 * 1166 * <p>IIpSecTransformHelper exists so that the interface is injectable for testing. 1167 */ 1168 @VisibleForTesting 1169 interface IIpSecTransformHelper { 1170 /** 1171 * Construct an instance of {@link IpSecTransform} 1172 * 1173 * @param context current context 1174 * @param sourceAddress the source {@code InetAddress} of traffic on sockets of interfaces 1175 * that will use this transform 1176 * @param udpEncapSocket the UDP-Encap socket that allows IpSec traffic to pass through a 1177 * NAT. Null if no NAT exists. 1178 * @param spi a unique {@link IpSecManager.SecurityParameterIndex} to identify transformed 1179 * traffic 1180 * @param integrityAlgo specifying the authentication algorithm to be applied. 1181 * @param encryptionAlgo specifying the encryption algorithm or authenticated encryption 1182 * algorithm to be applied. 1183 * @param integrityKey the negotiated authentication key to be applied. 1184 * @param encryptionKey the negotiated encryption key to be applied. 1185 * @param isTransport the flag indicates if a transport or a tunnel mode transform will be 1186 * built. 1187 * @return an instance of {@link IpSecTransform} 1188 * @throws ResourceUnavailableException indicating that too many transforms are active 1189 * @throws SpiUnavailableException indicating the rare case where an SPI collides with an 1190 * existing transform 1191 * @throws IOException indicating other errors 1192 */ makeIpSecTransform( Context context, InetAddress sourceAddress, UdpEncapsulationSocket udpEncapSocket, IpSecManager.SecurityParameterIndex spi, @Nullable IkeMacIntegrity integrityAlgo, IkeCipher encryptionAlgo, byte[] integrityKey, byte[] encryptionKey, boolean isTransport)1193 IpSecTransform makeIpSecTransform( 1194 Context context, 1195 InetAddress sourceAddress, 1196 UdpEncapsulationSocket udpEncapSocket, 1197 IpSecManager.SecurityParameterIndex spi, 1198 @Nullable IkeMacIntegrity integrityAlgo, 1199 IkeCipher encryptionAlgo, 1200 byte[] integrityKey, 1201 byte[] encryptionKey, 1202 boolean isTransport) 1203 throws ResourceUnavailableException, SpiUnavailableException, IOException; 1204 } 1205 } 1206