aboutsummaryrefslogtreecommitdiff
path: root/src/java/com/android/internal/net/crypto/KeyGenerationUtils.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/java/com/android/internal/net/crypto/KeyGenerationUtils.java')
-rw-r--r--src/java/com/android/internal/net/crypto/KeyGenerationUtils.java81
1 files changed, 81 insertions, 0 deletions
diff --git a/src/java/com/android/internal/net/crypto/KeyGenerationUtils.java b/src/java/com/android/internal/net/crypto/KeyGenerationUtils.java
new file mode 100644
index 00000000..c9ade7d5
--- /dev/null
+++ b/src/java/com/android/internal/net/crypto/KeyGenerationUtils.java
@@ -0,0 +1,81 @@
+/*
+ * 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.crypto;
+
+import java.nio.ByteBuffer;
+
+/**
+ * KeyGenerationUtils is a util class that contains utils for key generation needed by IKEv2 and
+ * EAP.
+ */
+public class KeyGenerationUtils {
+ /**
+ * Returns the derived pseudorandom number with the specified length by iteratively applying a
+ * PRF.
+ *
+ * <p>prf+(K, S) outputs a pseudorandom stream by using the PRF iteratively. In this way it can
+ * generate long enough keying material containing all the keys.
+ *
+ * @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 byteSigner the PRF used to sign the given data using the given key.
+ * @param keyBytes the key to sign data.
+ * @param dataToSign the data to be signed.
+ * @param keyMaterialLen the length of keying materials to be generated.
+ * @return the byte array of keying materials
+ */
+ public static byte[] prfPlus(
+ ByteSigner byteSigner, byte[] keyBytes, byte[] dataToSign, int keyMaterialLen) {
+ ByteBuffer keyMatBuffer = ByteBuffer.allocate(keyMaterialLen);
+
+ byte[] previousMac = new byte[0];
+ final int padLen = 1;
+ byte padValue = 1;
+
+ while (keyMatBuffer.remaining() > 0) {
+ ByteBuffer dataToSignBuffer =
+ ByteBuffer.allocate(previousMac.length + dataToSign.length + padLen);
+ dataToSignBuffer.put(previousMac).put(dataToSign).put(padValue);
+
+ previousMac = byteSigner.signBytes(keyBytes, dataToSignBuffer.array());
+
+ keyMatBuffer.put(
+ previousMac, 0, Math.min(previousMac.length, keyMatBuffer.remaining()));
+
+ padValue++;
+ }
+
+ return keyMatBuffer.array();
+ }
+
+ /**
+ * ByteSigner is an interface to be used for implementing the byte-signing for generating keys
+ * using {@link KeyGenerationUtils#prfPlus(ByteSigner, byte[], byte[], int)}.
+ */
+ public interface ByteSigner {
+ /**
+ * Signs the given data using the key given.
+ *
+ * <p>Caller is responsible for providing a valid key according to their use cases.
+ *
+ * @param keyBytes the key to sign data.
+ * @param dataToSign the data to be signed.
+ * @return the signed value.
+ */
+ byte[] signBytes(byte[] keyBytes, byte[] dataToSign);
+ }
+}