aboutsummaryrefslogtreecommitdiff
path: root/src/java/com/android/internal/net/ipsec/ike/crypto/IkeMacPrf.java
blob: 1d81aaed355035155b9308e70b678b86eab5ce9d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
/*
 * Copyright (C) 2019 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.internal.net.ipsec.ike.crypto;

import android.net.ipsec.ike.SaProposal;

import com.android.internal.net.crypto.KeyGenerationUtils;
import com.android.internal.net.ipsec.ike.message.IkeSaPayload.PrfTransform;

import java.nio.ByteBuffer;
import java.security.Provider;

import javax.crypto.Cipher;
import javax.crypto.Mac;

/**
 * IkeMacPrf represents a negotiated pseudorandom function.
 *
 * <p>Pseudorandom function is usually used for IKE SA authentication and generating keying
 * materials.
 *
 * <p>For pseudorandom functions based on integrity algorithms, all operations will be done by a
 * {@link Mac}. For pseudorandom functions based on encryption algorithms, all operations will be
 * done by a {@link Cipher}.
 *
 * @see <a href="https://tools.ietf.org/html/rfc7296#section-3.3.2">RFC 7296, Internet Key Exchange
 *     Protocol Version 2 (IKEv2)</a>
 */
public class IkeMacPrf extends IkeMac {
    // STOPSHIP: b/130190639 Catch unchecked exceptions, notify users and close the IKE session.

    private IkeMacPrf(
            @SaProposal.PseudorandomFunction int algorithmId,
            int keyLength,
            String algorithmName,
            boolean isEncryptAlgo,
            Provider provider) {
        super(algorithmId, keyLength, algorithmName, isEncryptAlgo, provider);
    }

    /**
     * Construct an instance of IkeMacPrf.
     *
     * @param prfTransform the valid negotiated PrfTransform.
     * @param provider the security provider.
     * @return an instance of IkeMacPrf.
     */
    public static IkeMacPrf create(PrfTransform prfTransform, Provider provider) {
        int algorithmId = prfTransform.id;

        int keyLength = 0;
        String algorithmName = "";
        boolean isEncryptAlgo = false;

        switch (algorithmId) {
            case SaProposal.PSEUDORANDOM_FUNCTION_HMAC_SHA1:
                keyLength = 20;
                algorithmName = "HmacSHA1";
                break;
            case SaProposal.PSEUDORANDOM_FUNCTION_AES128_XCBC:
                keyLength = 16;
                isEncryptAlgo = true;

                // TODO:Set mAlgorithmName
                throw new UnsupportedOperationException(
                        "Do not support PSEUDORANDOM_FUNCTION_AES128_XCBC.");
            default:
                throw new IllegalArgumentException("Unrecognized PRF ID: " + algorithmId);
        }

        return new IkeMacPrf(algorithmId, keyLength, algorithmName, isEncryptAlgo, provider);
    }

    /**
     * Generates SKEYSEED based on the nonces and shared DH secret.
     *
     * @param nonceInit the IKE initiator nonce.
     * @param nonceResp the IKE responder nonce.
     * @param sharedDhKey the DH shared key.
     * @return the byte array of SKEYSEED.
     */
    public byte[] generateSKeySeed(byte[] nonceInit, byte[] nonceResp, byte[] sharedDhKey) {
        // TODO: If it is PSEUDORANDOM_FUNCTION_AES128_XCBC, only use first 8 bytes of each nonce.

        ByteBuffer keyBuffer = ByteBuffer.allocate(nonceInit.length + nonceResp.length);
        keyBuffer.put(nonceInit).put(nonceResp);

        return signBytes(keyBuffer.array(), sharedDhKey);
    }

    /**
     * Generates a rekey SKEYSEED based on the nonces and shared DH secret.
     *
     * @param skD the secret for deriving new keys
     * @param nonceInit the IKE initiator nonce.
     * @param nonceResp the IKE responder nonce.
     * @param sharedDhKey the DH shared key.
     * @return the byte array of SKEYSEED.
     */
    public byte[] generateRekeyedSKeySeed(
            byte[] skD, byte[] nonceInit, byte[] nonceResp, byte[] sharedDhKey) {
        // TODO: If it is PSEUDORANDOM_FUNCTION_AES128_XCBC, only use first 8 bytes of each nonce.

        ByteBuffer dataToSign =
                ByteBuffer.allocate(sharedDhKey.length + nonceInit.length + nonceResp.length);
        dataToSign.put(sharedDhKey).put(nonceInit).put(nonceResp);

        return signBytes(skD, dataToSign.array());
    }

    /**
     * Derives keying materials from IKE/Child SA negotiation.
     *
     * <p>prf+(K, S) outputs a pseudorandom stream by using negotiated PRF iteratively. In this way
     * it can generate long enough keying material containing all the keys for this IKE/Child SA.
     *
     * @see <a href="https://tools.ietf.org/html/rfc7296#section-2.13">RFC 7296 Internet Key
     *     Exchange Protocol Version 2 (IKEv2) 2.13. Generating Keying Material </a>
     * @param keyBytes the key to sign data. SKEYSEED is used for generating KEYMAT for IKE SA. SK_d
     *     is used for generating KEYMAT for Child SA.
     * @param dataToSign the data to be signed.
     * @param keyMaterialLen the length of keying materials.
     * @return the byte array of keying materials
     */
    public byte[] generateKeyMat(byte[] keyBytes, byte[] dataToSign, int keyMaterialLen) {
        return KeyGenerationUtils.prfPlus(this, keyBytes, dataToSign, keyMaterialLen);
    }

    /**
     * Returns algorithm type as a String.
     *
     * @return the algorithm type as a String.
     */
    @Override
    public String getTypeString() {
        return "Pseudorandom Function";
    }
}