• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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