1 /* 2 * Copyright (C) 2018 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 17 package com.android.internal.net.ipsec.ike.message; 18 19 import android.annotation.Nullable; 20 import android.net.ipsec.ike.exceptions.IkeProtocolException; 21 22 import com.android.internal.annotations.VisibleForTesting; 23 import com.android.internal.net.ipsec.ike.crypto.IkeCipher; 24 import com.android.internal.net.ipsec.ike.crypto.IkeMacIntegrity; 25 26 import java.nio.ByteBuffer; 27 import java.security.GeneralSecurityException; 28 29 /** 30 * IkeSkPayload represents the common information of an Encrypted and Authenticated Payload and an 31 * Encrypted and Authenticated Fragment Payload. 32 * 33 * <p>It contains other payloads in encrypted form. It is must be the last payload in the message. 34 * It should be the only payload in this implementation. 35 * 36 * <p>Critical bit must be ignored when doing decoding. 37 * 38 * @see <a href="https://tools.ietf.org/html/rfc7296#page-105">RFC 7296, Internet Key Exchange 39 * Protocol Version 2 (IKEv2)</a> 40 */ 41 public class IkeSkPayload extends IkePayload { 42 43 protected final IkeEncryptedPayloadBody mIkeEncryptedPayloadBody; 44 45 /** 46 * Construct an instance of IkeSkPayload from decrypting an incoming packet. 47 * 48 * @param critical indicates if it is a critical payload. 49 * @param message the byte array contains the whole IKE message. 50 * @param integrityMac the negotiated integrity algorithm. 51 * @param decryptCipher the negotiated encryption algorithm. 52 * @param integrityKey the negotiated integrity algorithm key. 53 * @param decryptionKey the negotiated decryption key. 54 */ 55 @VisibleForTesting IkeSkPayload( boolean critical, byte[] message, @Nullable IkeMacIntegrity integrityMac, IkeCipher decryptCipher, byte[] integrityKey, byte[] decryptionKey)56 IkeSkPayload( 57 boolean critical, 58 byte[] message, 59 @Nullable IkeMacIntegrity integrityMac, 60 IkeCipher decryptCipher, 61 byte[] integrityKey, 62 byte[] decryptionKey) 63 throws IkeProtocolException, GeneralSecurityException { 64 65 this( 66 false /*isSkf*/, 67 critical, 68 IkeHeader.IKE_HEADER_LENGTH + GENERIC_HEADER_LENGTH, 69 message, 70 integrityMac, 71 decryptCipher, 72 integrityKey, 73 decryptionKey); 74 } 75 76 /** Construct an instance of IkeSkPayload for testing.*/ 77 @VisibleForTesting IkeSkPayload(boolean isSkf, IkeEncryptedPayloadBody encryptedPayloadBody)78 IkeSkPayload(boolean isSkf, IkeEncryptedPayloadBody encryptedPayloadBody) { 79 super(isSkf ? PAYLOAD_TYPE_SKF : PAYLOAD_TYPE_SK, false/*critical*/); 80 mIkeEncryptedPayloadBody = encryptedPayloadBody; 81 } 82 83 /** Construct an instance of IkeSkPayload from decrypting an incoming packet. */ IkeSkPayload( boolean isSkf, boolean critical, int encryptedBodyOffset, byte[] message, @Nullable IkeMacIntegrity integrityMac, IkeCipher decryptCipher, byte[] integrityKey, byte[] decryptionKey)84 protected IkeSkPayload( 85 boolean isSkf, 86 boolean critical, 87 int encryptedBodyOffset, 88 byte[] message, 89 @Nullable IkeMacIntegrity integrityMac, 90 IkeCipher decryptCipher, 91 byte[] integrityKey, 92 byte[] decryptionKey) 93 throws IkeProtocolException, GeneralSecurityException { 94 super(isSkf ? PAYLOAD_TYPE_SKF : PAYLOAD_TYPE_SK, critical); 95 96 // TODO: Support constructing IkeEncryptedPayloadBody using AEAD. 97 98 mIkeEncryptedPayloadBody = 99 new IkeEncryptedPayloadBody( 100 message, 101 encryptedBodyOffset, 102 integrityMac, 103 decryptCipher, 104 integrityKey, 105 decryptionKey); 106 } 107 108 /** 109 * Construct an instance of IkeSkPayload for building outbound packet. 110 * 111 * @param ikeHeader the IKE header. 112 * @param firstPayloadType the type of first payload nested in SkPayload. 113 * @param unencryptedPayloads the encoded payload list to protect. 114 * @param integrityMac the negotiated integrity algorithm. 115 * @param encryptCipher the negotiated encryption algorithm. 116 * @param integrityKey the negotiated integrity algorithm key. 117 * @param encryptionKey the negotiated encryption key. 118 */ 119 @VisibleForTesting IkeSkPayload( IkeHeader ikeHeader, @PayloadType int firstPayloadType, byte[] unencryptedPayloads, @Nullable IkeMacIntegrity integrityMac, IkeCipher encryptCipher, byte[] integrityKey, byte[] encryptionKey)120 IkeSkPayload( 121 IkeHeader ikeHeader, 122 @PayloadType int firstPayloadType, 123 byte[] unencryptedPayloads, 124 @Nullable IkeMacIntegrity integrityMac, 125 IkeCipher encryptCipher, 126 byte[] integrityKey, 127 byte[] encryptionKey) { 128 129 this( 130 ikeHeader, 131 firstPayloadType, 132 new byte[0] /*skfHeaderBytes*/, 133 unencryptedPayloads, 134 integrityMac, 135 encryptCipher, 136 integrityKey, 137 encryptionKey); 138 } 139 140 /** Construct an instance of IkeSkPayload for building outbound packet. */ 141 @VisibleForTesting IkeSkPayload( IkeHeader ikeHeader, @PayloadType int firstPayloadType, byte[] skfHeaderBytes, byte[] unencryptedPayloads, @Nullable IkeMacIntegrity integrityMac, IkeCipher encryptCipher, byte[] integrityKey, byte[] encryptionKey)142 protected IkeSkPayload( 143 IkeHeader ikeHeader, 144 @PayloadType int firstPayloadType, 145 byte[] skfHeaderBytes, 146 byte[] unencryptedPayloads, 147 @Nullable IkeMacIntegrity integrityMac, 148 IkeCipher encryptCipher, 149 byte[] integrityKey, 150 byte[] encryptionKey) { 151 super(skfHeaderBytes.length == 0 ? PAYLOAD_TYPE_SK : PAYLOAD_TYPE_SKF, false); 152 153 // TODO: Support constructing IkeEncryptedPayloadBody using AEAD. 154 155 mIkeEncryptedPayloadBody = 156 new IkeEncryptedPayloadBody( 157 ikeHeader, 158 firstPayloadType, 159 skfHeaderBytes, 160 unencryptedPayloads, 161 integrityMac, 162 encryptCipher, 163 integrityKey, 164 encryptionKey); 165 } 166 167 /** 168 * Return unencrypted data. 169 * 170 * @return unencrypted data in a byte array. 171 */ getUnencryptedData()172 public byte[] getUnencryptedData() { 173 return mIkeEncryptedPayloadBody.getUnencryptedData(); 174 } 175 176 /** 177 * Encode this payload to a ByteBuffer. 178 * 179 * @param nextPayload type of payload that follows this payload. 180 * @param byteBuffer destination ByteBuffer that stores encoded payload. 181 */ 182 @Override encodeToByteBuffer(@ayloadType int nextPayload, ByteBuffer byteBuffer)183 protected void encodeToByteBuffer(@PayloadType int nextPayload, ByteBuffer byteBuffer) { 184 encodePayloadHeaderToByteBuffer(nextPayload, getPayloadLength(), byteBuffer); 185 byteBuffer.put(mIkeEncryptedPayloadBody.encode()); 186 } 187 188 /** 189 * Get entire payload length. 190 * 191 * @return entire payload length. 192 */ 193 @Override getPayloadLength()194 protected int getPayloadLength() { 195 return GENERIC_HEADER_LENGTH + mIkeEncryptedPayloadBody.getLength(); 196 } 197 198 /** 199 * Return the payload type as a String. 200 * 201 * @return the payload type as a String. 202 */ 203 @Override getTypeString()204 public String getTypeString() { 205 return "SK"; 206 } 207 } 208