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.IkeProtocolException;
20 
21 import com.android.internal.net.ipsec.ike.exceptions.InvalidSyntaxException;
22 import com.android.internal.net.ipsec.ike.utils.RandomnessFactory;
23 
24 import java.nio.ByteBuffer;
25 import java.security.SecureRandom;
26 
27 /**
28  * IkeNoncePayload represents a Nonce payload.
29  *
30  * <p>Length of nonce data must be at least half the key size of negotiated PRF. It must be between
31  * 16 and 256 octets. IKE library always generates nonce of GENERATED_NONCE_LEN octets which is long
32  * enough for all currently known PRFs.
33  *
34  * <p>Critical bit must be ignored when doing decoding and must not be set when doing encoding for
35  * this payload.
36  *
37  * @see <a href="https://tools.ietf.org/html/rfc7296">RFC 7296, Internet Key Exchange Protocol
38  *     Version 2 (IKEv2).
39  */
40 public final class IkeNoncePayload extends IkePayload {
41     // The longest key size of all currently known PRFs is 512 bits (64 bytes). Since we are
42     // required to generate nonce that is long enough for all proposed PRFs, it is simple that we
43     // always generate 32 bytes nonce, which is enough for all known PRFs.
44     private static final int GENERATED_NONCE_LEN = 32;
45 
46     private static final int MIN_NONCE_LEN = 16;
47     private static final int MAX_NONCE_LEN = 256;
48 
49     public final byte[] nonceData;
50 
51     /**
52      * Construct an instance of IkeNoncePayload in the context of {@link IkePayloadFactory}.
53      *
54      * @param critical indicates if it is a critical payload.
55      * @param payloadBody the nonce data
56      */
IkeNoncePayload(boolean critical, byte[] payloadBody)57     IkeNoncePayload(boolean critical, byte[] payloadBody) throws IkeProtocolException {
58         super(PAYLOAD_TYPE_NONCE, critical);
59         if (payloadBody.length < MIN_NONCE_LEN || payloadBody.length > MAX_NONCE_LEN) {
60             throw new InvalidSyntaxException(
61                     "Invalid nonce data with length of: " + payloadBody.length);
62         }
63         // Check that the length of payloadBody satisfies the "half the key size of negotiated PRF"
64         // condition when processing IKE Message in upper layer. Cannot do this check here for
65         // lacking PRF information.
66         nonceData = payloadBody;
67     }
68 
69     /** Generate Nonce data and construct an instance of IkeNoncePayload. */
IkeNoncePayload(RandomnessFactory randomnessFactory)70     public IkeNoncePayload(RandomnessFactory randomnessFactory) {
71         super(PAYLOAD_TYPE_NONCE, false);
72         nonceData = new byte[GENERATED_NONCE_LEN];
73 
74         SecureRandom random = randomnessFactory.getRandom();
75         random = random == null ? new SecureRandom() : random;
76         random.nextBytes(nonceData);
77     }
78 
79     /**
80      * Encode Nonce payload to ByteBuffer.
81      *
82      * @param nextPayload type of payload that follows this payload.
83      * @param byteBuffer destination ByteBuffer that stores encoded payload.
84      */
85     @Override
encodeToByteBuffer(@ayloadType int nextPayload, ByteBuffer byteBuffer)86     protected void encodeToByteBuffer(@PayloadType int nextPayload, ByteBuffer byteBuffer) {
87         int payloadLength = GENERIC_HEADER_LENGTH + nonceData.length;
88 
89         encodePayloadHeaderToByteBuffer(nextPayload, payloadLength, byteBuffer);
90         byteBuffer.put(nonceData);
91     }
92 
93     /**
94      * Get entire payload length.
95      *
96      * @return entire payload length.
97      */
98     @Override
getPayloadLength()99     protected int getPayloadLength() {
100         return GENERIC_HEADER_LENGTH + nonceData.length;
101     }
102 
103     /**
104      * Return the payload type as a String.
105      *
106      * @return the payload type as a String.
107      */
108     @Override
getTypeString()109     public String getTypeString() {
110         return "Nonce";
111     }
112 }
113