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.net.ipsec.ike.exceptions.AuthenticationFailedException; 20 21 import com.android.internal.net.ipsec.ike.crypto.IkeMacPrf; 22 23 import java.nio.ByteBuffer; 24 import java.util.Arrays; 25 26 /** 27 * IkeAuthPskPayload represents an Authentication Payload using Pre-Shared Key to do authentication. 28 * 29 * @see <a href="https://tools.ietf.org/html/rfc7296#section-3.8">RFC 7296, Internet Key Exchange 30 * Protocol Version 2 (IKEv2)</a> 31 */ 32 public final class IkeAuthPskPayload extends IkeAuthPayload { 33 // Hex of ASCII characters "Key Pad for IKEv2" for calculating PSK signature. 34 private static final byte[] IKE_KEY_PAD_STRING_ASCII_HEX_BYTES = { 35 (byte) 0x4b, (byte) 0x65, (byte) 0x79, (byte) 0x20, 36 (byte) 0x50, (byte) 0x61, (byte) 0x64, (byte) 0x20, 37 (byte) 0x66, (byte) 0x6f, (byte) 0x72, (byte) 0x20, 38 (byte) 0x49, (byte) 0x4b, (byte) 0x45, (byte) 0x76, 39 (byte) 0x32 40 }; 41 42 public final byte[] signature; 43 44 /** 45 * Construct IkeAuthPskPayload for received IKE packet in the context of {@link 46 * IkePayloadFactory}. 47 */ IkeAuthPskPayload(boolean critical, byte[] authData)48 protected IkeAuthPskPayload(boolean critical, byte[] authData) { 49 super(critical, IkeAuthPayload.AUTH_METHOD_PRE_SHARED_KEY); 50 signature = authData; 51 } 52 53 /** 54 * Construct IkeAuthPskPayload for an outbound IKE packet. 55 * 56 * <p>Since IKE library is always a client, outbound IkeAuthPskPayload always signs IKE 57 * initiator's SignedOctets, which is concatenation of the IKE_INIT request message, the Nonce 58 * of IKE responder and the signed ID-Initiator payload body. 59 * 60 * @param psk locally stored pre-shared key 61 * @param ikeInitBytes IKE_INIT request for calculating IKE initiator's SignedOctets. 62 * @param nonce nonce of IKE responder for calculating IKE initiator's SignedOctets. 63 * @param idPayloadBodyBytes ID-Initiator payload body for calculating IKE initiator's 64 * SignedOctets. 65 * @param ikePrf the negotiated PRF. 66 * @param prfKeyBytes the negotiated PRF key. 67 */ IkeAuthPskPayload( byte[] psk, byte[] ikeInitBytes, byte[] nonce, byte[] idPayloadBodyBytes, IkeMacPrf ikePrf, byte[] prfKeyBytes)68 public IkeAuthPskPayload( 69 byte[] psk, 70 byte[] ikeInitBytes, 71 byte[] nonce, 72 byte[] idPayloadBodyBytes, 73 IkeMacPrf ikePrf, 74 byte[] prfKeyBytes) { 75 super(false, IkeAuthPayload.AUTH_METHOD_PRE_SHARED_KEY); 76 signature = 77 calculatePskSignature( 78 psk, ikeInitBytes, nonce, idPayloadBodyBytes, ikePrf, prfKeyBytes); 79 } 80 calculatePskSignature( byte[] psk, byte[] ikeInitBytes, byte[] nonce, byte[] idPayloadBodyBytes, IkeMacPrf ikePrf, byte[] prfKeyBytes)81 private static byte[] calculatePskSignature( 82 byte[] psk, 83 byte[] ikeInitBytes, 84 byte[] nonce, 85 byte[] idPayloadBodyBytes, 86 IkeMacPrf ikePrf, 87 byte[] prfKeyBytes) { 88 byte[] signingKeyBytes = ikePrf.signBytes(psk, IKE_KEY_PAD_STRING_ASCII_HEX_BYTES); 89 byte[] dataToSignBytes = 90 getSignedOctets(ikeInitBytes, nonce, idPayloadBodyBytes, ikePrf, prfKeyBytes); 91 92 return ikePrf.signBytes(signingKeyBytes, dataToSignBytes); 93 } 94 95 /** 96 * Verify received signature in inbound IKE packet. 97 * 98 * <p>Since IKE library is always a client, inbound IkeAuthPskPayload always signs IKE 99 * responder's SignedOctets, which is concatenation of the IKE_INIT response message, the Nonce 100 * of IKE initiator and the signed ID-Responder payload body. 101 * 102 * @param psk locally stored pre-shared key 103 * @param ikeInitBytes IKE_INIT response for calculating IKE responder's SignedOctets. 104 * @param nonce nonce of IKE initiator for calculating IKE responder's SignedOctets. 105 * @param idPayloadBodyBytes ID-Responder payload body for calculating IKE responder's 106 * SignedOctets. 107 * @param ikePrf the negotiated PRF. 108 * @param prfKeyBytes the negotiated PRF key. 109 * @throws AuthenticationFailedException if received signature is not equal to calculated 110 * signature. 111 */ verifyInboundSignature( byte[] psk, byte[] ikeInitBytes, byte[] nonce, byte[] idPayloadBodyBytes, IkeMacPrf ikePrf, byte[] prfKeyBytes)112 public void verifyInboundSignature( 113 byte[] psk, 114 byte[] ikeInitBytes, 115 byte[] nonce, 116 byte[] idPayloadBodyBytes, 117 IkeMacPrf ikePrf, 118 byte[] prfKeyBytes) 119 throws AuthenticationFailedException { 120 byte[] calculatedSignature = 121 calculatePskSignature( 122 psk, ikeInitBytes, nonce, idPayloadBodyBytes, ikePrf, prfKeyBytes); 123 if (!Arrays.equals(signature, calculatedSignature)) { 124 throw new AuthenticationFailedException("Signature verification failed."); 125 } 126 } 127 128 @Override encodeAuthDataToByteBuffer(ByteBuffer byteBuffer)129 protected void encodeAuthDataToByteBuffer(ByteBuffer byteBuffer) { 130 byteBuffer.put(signature); 131 } 132 133 @Override getAuthDataLength()134 protected int getAuthDataLength() { 135 return signature.length; 136 } 137 138 @Override getTypeString()139 public String getTypeString() { 140 return "Auth(PSK)"; 141 } 142 } 143