/* * Copyright (C) 2024 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 android.crypto.hpke; import java.security.GeneralSecurityException; import java.security.InvalidKeyException; import java.security.PrivateKey; import java.security.PublicKey; import libcore.util.NonNull; import libcore.util.Nullable; /** * Service Provider Interface for HPKE client API classes to communicate with implementations * of HPKE as described in RFC 9180. *

* There are no standard Java Cryptography Architecture names or interface classes for HPKE, * but instances of this class can be obtained by calling * {@code Provider.getService("ConscryptHpke", String SuiteName)} where {@code suiteName} * is the name of the HPKE suite, e.g. * {@code "DHKEM_X25519_HKDF_SHA256/HKDF_SHA256/AES_128_GCM"}. */ public interface HpkeSpi { /** * Initialises an HPKE SPI in one of the sender modes described in RFC 9180. *

* If {@code psk} and {@code psk_id} are supplied then Pre-Shared Key Authentication * will be used. *

* If {@code senderKey} is supplied then Asymmetric Key Authentication will be used. *

* If neither is supplied then "base" mode (no sender authentication) will be used. *

* Note that only base mode is currently supported on Android. *

* Public and private keys must be supplied in a format that can be used by the * implementation. An instance of the {@code "XDH"} {@link java.security.KeyFactory} can * be used to translate {@code KeySpecs} or keys from another {@link java.security.Provider} * * @param recipientKey public key of the recipient * @param info application-supplied information, may be null or empty * @param senderKey private key of the sender, for symmetric auth modes only, else null * @param psk pre-shared key, for PSK auth modes only, else null * @param psk_id pre-shared key ID, for PSK auth modes only, else null * @throws InvalidKeyException if recipientKey is null or an unsupported key format * @throws UnsupportedOperationException if mode is not a supported HPKE mode * @throws IllegalStateException if this SPI has already been initialised */ void engineInitSender( @NonNull PublicKey recipientKey, @Nullable byte[] info, @Nullable PrivateKey senderKey, @Nullable byte[] psk, @Nullable byte[] psk_id) throws InvalidKeyException; /** * Initialises an HPKE SPI in one of the sender modes described in RFC 9180 with * a predefined random seed to allow testing against known test vectors. *

* This mode provides absolutely no security and should only be used for testing * purposes. *

* If {@code psk} and {@code psk_id} are supplied then Pre-Shared Key Authentication * will be used. *

* If {@code senderKey} is supplied then Asymmetric Key Authentication will be used. *

* If neither is supplied then "base" mode (no sender authentication) will be used. *

* Note that only base mode is currently supported on Android. *

* Public and private keys must be supplied in a format that can be used by the * implementation. An instance of the {@code "XDH"} {@link java.security.KeyFactory} can * be used to translate {@code KeySpecs} or keys from another {@link java.security.Provider} * * * @param recipientKey public key of the recipient * @param info application-supplied information, may be null or empty * @param senderKey private key of the sender, for symmetric auth modes only, else null * @param psk pre-shared key, for PSK auth modes only, else null * @param psk_id pre-shared key ID, for PSK auth modes only, else null * @param sKe Predetermined random seed, should only be usesd for validation against * known test vectors * @throws InvalidKeyException if recipientKey is null or an unsupported key format or senderKey * is an unsupported key format * @throws UnsupportedOperationException if mode is not a supported HPKE mode * @throws IllegalStateException if this SPI has already been initialised */ void engineInitSenderWithSeed( @NonNull PublicKey recipientKey, @Nullable byte[] info, @Nullable PrivateKey senderKey, @Nullable byte[] psk, @Nullable byte[] psk_id, @NonNull byte[] sKe) throws InvalidKeyException; /** * Initialises an HPKE SPI in one of the sender modes described in RFC 9180. *

* If {@code psk} and {@code psk_id} are supplied then Pre-Shared Key Authentication * will be used. *

* If {@code senderKey} is supplied then Asymmetric Key Authentication will be used. *

* If neither is supplied then "base" mode (no sender authentication) will be used. *

* Note that only base mode is currently supported on Android. *

* Public and private keys must be supplied in a format that can be used by the * implementation. An instance of the {@code "XDH"} {@link java.security.KeyFactory} can * be used to translate {@code KeySpecs} or keys from another {@link java.security.Provider} * * @param encapsulated encapsulated ephemeral key from a sender * @param recipientKey private key of the recipient * @param info application-supplied information, may be null or empty * @param senderKey public key of sender, for asymmetric auth modes only, else null * @param psk pre-shared key, for PSK auth modes only, else null * @param psk_id pre-shared key ID, for PSK auth modes only, else null * @throws InvalidKeyException if recipientKey is null or an unsupported key format or senderKey * is an unsupported key format * @throws UnsupportedOperationException if mode is not a supported HPKE mode * @throws IllegalStateException if this SPI has already been initialised */ void engineInitRecipient( @NonNull byte[] encapsulated, @NonNull PrivateKey recipientKey, @Nullable byte[] info, @Nullable PublicKey senderKey, @Nullable byte[] psk, @Nullable byte[] psk_id) throws InvalidKeyException; /** * Seals a message, using the internal key schedule maintained by an HPKE sender SPI. * * @param plaintext the plaintext * @param aad optional associated data, may be null or empty * @return the ciphertext * @throws NullPointerException if the plaintext is null * @throws IllegalStateException if this SPI has not been initialised or if it was initialised * as a recipient */ @NonNull byte[] engineSeal(@NonNull byte[] plaintext, @Nullable byte[] aad); /** * Opens a message, using the internal key schedule maintained by an HPKE recipient SPI. * * @param ciphertext the ciphertext * @param aad optional associated data, may be null or empty * @return the plaintext * @throws IllegalStateException if this SPI has not been initialised or if it was initialised * as a sender * @throws GeneralSecurityException on decryption failures */ @NonNull byte[] engineOpen(@NonNull byte[] ciphertext, @Nullable byte[] aad) throws GeneralSecurityException; /** * Exports secret key material from this SPI as described in RFC 9180. * * @param length expected output length * @param context optional context string, may be null or empty * @return exported value * @throws IllegalArgumentException if the length is not valid for the KDF in use * @throws IllegalStateException if this SPI has not been initialised * */ @NonNull byte[] engineExport(int length, @Nullable byte[] context); /** * Returns the encapsulated key material for an HPKE sender. * * @return the key material * @throws IllegalStateException if this SPI has not been initialised or if it was initialised * as a recipient */ @NonNull byte[] getEncapsulated(); }