Merge "Return a port from bindToPort() in IpSecService"
diff --git a/core/java/android/net/IpSecAlgorithm.java b/core/java/android/net/IpSecAlgorithm.java
index 79310e2..16b1452 100644
--- a/core/java/android/net/IpSecAlgorithm.java
+++ b/core/java/android/net/IpSecAlgorithm.java
@@ -31,7 +31,6 @@
* RFC 4301.
*/
public final class IpSecAlgorithm implements Parcelable {
-
/**
* AES-CBC Encryption/Ciphering Algorithm.
*
@@ -68,6 +67,7 @@
* <p>Valid truncation lengths are multiples of 8 bits from 192 to (default) 384.
*/
public static final String AUTH_HMAC_SHA384 = "hmac(sha384)";
+
/**
* SHA512 HMAC Authentication/Integrity Algorithm
*
@@ -75,8 +75,24 @@
*/
public static final String AUTH_HMAC_SHA512 = "hmac(sha512)";
+ /**
+ * AES-GCM Authentication/Integrity + Encryption/Ciphering Algorithm.
+ *
+ * <p>Valid lengths for this key are {128, 192, 256}.
+ *
+ * <p>Valid ICV (truncation) lengths are {64, 96, 128}.
+ */
+ public static final String AUTH_CRYPT_AES_GCM = "rfc4106(gcm(aes))";
+
/** @hide */
- @StringDef({CRYPT_AES_CBC, AUTH_HMAC_MD5, AUTH_HMAC_SHA1, AUTH_HMAC_SHA256, AUTH_HMAC_SHA512})
+ @StringDef({
+ CRYPT_AES_CBC,
+ AUTH_HMAC_MD5,
+ AUTH_HMAC_SHA1,
+ AUTH_HMAC_SHA256,
+ AUTH_HMAC_SHA512,
+ AUTH_CRYPT_AES_GCM
+ })
@Retention(RetentionPolicy.SOURCE)
public @interface AlgorithmName {}
@@ -102,7 +118,7 @@
* @param algoName precise name of the algorithm to be used.
* @param key non-null Key padded to a multiple of 8 bits.
* @param truncLenBits the number of bits of output hash to use; only meaningful for
- * Authentication.
+ * Authentication or Authenticated Encryption (equivalent to ICV length).
*/
public IpSecAlgorithm(@AlgorithmName String algoName, byte[] key, int truncLenBits) {
if (!isTruncationLengthValid(algoName, truncLenBits)) {
@@ -175,6 +191,8 @@
return (truncLenBits >= 192 && truncLenBits <= 384);
case AUTH_HMAC_SHA512:
return (truncLenBits >= 256 && truncLenBits <= 512);
+ case AUTH_CRYPT_AES_GCM:
+ return (truncLenBits == 64 || truncLenBits == 96 || truncLenBits == 128);
default:
return false;
}
diff --git a/core/java/android/net/IpSecConfig.java b/core/java/android/net/IpSecConfig.java
index 632b7fc..61b13a9 100644
--- a/core/java/android/net/IpSecConfig.java
+++ b/core/java/android/net/IpSecConfig.java
@@ -50,6 +50,9 @@
// Authentication Algorithm
private IpSecAlgorithm mAuthentication;
+ // Authenticated Encryption Algorithm
+ private IpSecAlgorithm mAuthenticatedEncryption;
+
@Override
public String toString() {
return new StringBuilder()
@@ -59,6 +62,8 @@
.append(mEncryption)
.append(", mAuthentication=")
.append(mAuthentication)
+ .append(", mAuthenticatedEncryption=")
+ .append(mAuthenticatedEncryption)
.append("}")
.toString();
}
@@ -118,6 +123,11 @@
mFlow[direction].mAuthentication = authentication;
}
+ /** Set the authenticated encryption algorithm for a given direction */
+ public void setAuthenticatedEncryption(int direction, IpSecAlgorithm authenticatedEncryption) {
+ mFlow[direction].mAuthenticatedEncryption = authenticatedEncryption;
+ }
+
public void setNetwork(Network network) {
mNetwork = network;
}
@@ -163,6 +173,10 @@
return mFlow[direction].mAuthentication;
}
+ public IpSecAlgorithm getAuthenticatedEncryption(int direction) {
+ return mFlow[direction].mAuthenticatedEncryption;
+ }
+
public Network getNetwork() {
return mNetwork;
}
@@ -199,9 +213,11 @@
out.writeInt(mFlow[IpSecTransform.DIRECTION_IN].mSpiResourceId);
out.writeParcelable(mFlow[IpSecTransform.DIRECTION_IN].mEncryption, flags);
out.writeParcelable(mFlow[IpSecTransform.DIRECTION_IN].mAuthentication, flags);
+ out.writeParcelable(mFlow[IpSecTransform.DIRECTION_IN].mAuthenticatedEncryption, flags);
out.writeInt(mFlow[IpSecTransform.DIRECTION_OUT].mSpiResourceId);
out.writeParcelable(mFlow[IpSecTransform.DIRECTION_OUT].mEncryption, flags);
out.writeParcelable(mFlow[IpSecTransform.DIRECTION_OUT].mAuthentication, flags);
+ out.writeParcelable(mFlow[IpSecTransform.DIRECTION_OUT].mAuthenticatedEncryption, flags);
out.writeInt(mEncapType);
out.writeInt(mEncapSocketResourceId);
out.writeInt(mEncapRemotePort);
@@ -221,11 +237,15 @@
(IpSecAlgorithm) in.readParcelable(IpSecAlgorithm.class.getClassLoader());
mFlow[IpSecTransform.DIRECTION_IN].mAuthentication =
(IpSecAlgorithm) in.readParcelable(IpSecAlgorithm.class.getClassLoader());
+ mFlow[IpSecTransform.DIRECTION_IN].mAuthenticatedEncryption =
+ (IpSecAlgorithm) in.readParcelable(IpSecAlgorithm.class.getClassLoader());
mFlow[IpSecTransform.DIRECTION_OUT].mSpiResourceId = in.readInt();
mFlow[IpSecTransform.DIRECTION_OUT].mEncryption =
(IpSecAlgorithm) in.readParcelable(IpSecAlgorithm.class.getClassLoader());
mFlow[IpSecTransform.DIRECTION_OUT].mAuthentication =
(IpSecAlgorithm) in.readParcelable(IpSecAlgorithm.class.getClassLoader());
+ mFlow[IpSecTransform.DIRECTION_OUT].mAuthenticatedEncryption =
+ (IpSecAlgorithm) in.readParcelable(IpSecAlgorithm.class.getClassLoader());
mEncapType = in.readInt();
mEncapSocketResourceId = in.readInt();
mEncapRemotePort = in.readInt();
diff --git a/core/java/android/net/IpSecTransform.java b/core/java/android/net/IpSecTransform.java
index e15a2c6..48b5bd5 100644
--- a/core/java/android/net/IpSecTransform.java
+++ b/core/java/android/net/IpSecTransform.java
@@ -281,6 +281,8 @@
* <p>If encryption is set for a given direction without also providing an SPI for that
* direction, creation of an IpSecTransform will fail upon calling a build() method.
*
+ * <p>Authenticated encryption is mutually exclusive with encryption and authentication.
+ *
* @param direction either {@link #DIRECTION_IN or #DIRECTION_OUT}
* @param algo {@link IpSecAlgorithm} specifying the encryption to be applied.
*/
@@ -296,6 +298,8 @@
* <p>If authentication is set for a given direction without also providing an SPI for that
* direction, creation of an IpSecTransform will fail upon calling a build() method.
*
+ * <p>Authenticated encryption is mutually exclusive with encryption and authentication.
+ *
* @param direction either {@link #DIRECTION_IN or #DIRECTION_OUT}
* @param algo {@link IpSecAlgorithm} specifying the authentication to be applied.
*/
@@ -306,6 +310,29 @@
}
/**
+ * Add an authenticated encryption algorithm to the transform for the given direction.
+ *
+ * <p>If an authenticated encryption algorithm is set for a given direction without also
+ * providing an SPI for that direction, creation of an IpSecTransform will fail upon calling
+ * a build() method.
+ *
+ * <p>The Authenticated Encryption (AE) class of algorithms are also known as Authenticated
+ * Encryption with Associated Data (AEAD) algorithms, or Combined mode algorithms (as
+ * referred to in RFC 4301)
+ *
+ * <p>Authenticated encryption is mutually exclusive with encryption and authentication.
+ *
+ * @param direction either {@link #DIRECTION_IN or #DIRECTION_OUT}
+ * @param algo {@link IpSecAlgorithm} specifying the authenticated encryption algorithm to
+ * be applied.
+ */
+ public IpSecTransform.Builder setAuthenticatedEncryption(
+ @TransformDirection int direction, IpSecAlgorithm algo) {
+ mConfig.setAuthenticatedEncryption(direction, algo);
+ return this;
+ }
+
+ /**
* Set the SPI, which uniquely identifies a particular IPsec session from others. Because
* IPsec operates at the IP layer, this 32-bit identifier uniquely identifies packets to a
* given destination address.
diff --git a/services/core/java/com/android/server/IpSecService.java b/services/core/java/com/android/server/IpSecService.java
index 3d54ee6..a139ac4 100644
--- a/services/core/java/com/android/server/IpSecService.java
+++ b/services/core/java/com/android/server/IpSecService.java
@@ -882,8 +882,14 @@
for (int direction : DIRECTIONS) {
IpSecAlgorithm crypt = config.getEncryption(direction);
IpSecAlgorithm auth = config.getAuthentication(direction);
- if (crypt == null && auth == null) {
- throw new IllegalArgumentException("Encryption and Authentication are both null");
+ IpSecAlgorithm authenticatedEncryption = config.getAuthenticatedEncryption(direction);
+ if (authenticatedEncryption == null && crypt == null && auth == null) {
+ throw new IllegalArgumentException(
+ "No Encryption or Authentication algorithms specified");
+ } else if (authenticatedEncryption != null && (auth != null || crypt != null)) {
+ throw new IllegalArgumentException(
+ "Authenticated Encryption is mutually"
+ + " exclusive with other Authentication or Encryption algorithms");
}
if (mSpiRecords.getAndCheckOwner(config.getSpiResourceId(direction)) == null) {
@@ -922,6 +928,7 @@
for (int direction : DIRECTIONS) {
IpSecAlgorithm auth = c.getAuthentication(direction);
IpSecAlgorithm crypt = c.getEncryption(direction);
+ IpSecAlgorithm authCrypt = c.getAuthenticatedEncryption(direction);
spis[direction] = mSpiRecords.getAndCheckOwner(c.getSpiResourceId(direction));
int spi = spis[direction].getSpi();
@@ -942,6 +949,9 @@
(crypt != null) ? crypt.getName() : "",
(crypt != null) ? crypt.getKey() : null,
(crypt != null) ? crypt.getTruncationLengthBits() : 0,
+ (authCrypt != null) ? authCrypt.getName() : "",
+ (authCrypt != null) ? authCrypt.getKey() : null,
+ (authCrypt != null) ? authCrypt.getTruncationLengthBits() : 0,
encapType,
encapLocalPort,
encapRemotePort);