1 /*
2  * Copyright (C) 2024 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 android.crypto.hpke;
18 
19 import java.security.GeneralSecurityException;
20 import java.security.InvalidKeyException;
21 import java.security.PrivateKey;
22 import java.security.PublicKey;
23 import libcore.util.NonNull;
24 import libcore.util.Nullable;
25 
26 
27 /**
28  * Service Provider Interface for HPKE client API classes to communicate with implementations
29  * of HPKE as described in RFC 9180.
30  * <p>
31  * There are no standard Java Cryptography Architecture names or interface classes for HPKE,
32  * but instances of this class can be obtained by calling
33  * {@code Provider.getService("ConscryptHpke", String SuiteName)} where {@code suiteName}
34  * is the name of the HPKE suite, e.g.
35  * {@code "DHKEM_X25519_HKDF_SHA256/HKDF_SHA256/AES_128_GCM"}.
36  */
37 public interface HpkeSpi {
38     /**
39      * Initialises an HPKE SPI in one of the sender modes described in RFC 9180.
40      * <p>
41      * If {@code psk} and {@code psk_id} are supplied then Pre-Shared Key Authentication
42      * will be used.
43      * <p>
44      * If {@code senderKey} is supplied then Asymmetric Key Authentication will be used.
45      * <p>
46      * If neither is supplied then "base" mode (no sender authentication) will be used.
47      * <p>
48      * Note that only base mode is currently supported on Android.
49      * <p>
50      * Public and private keys must be supplied in a format that can be used by the
51      * implementation.  An instance of the {@code "XDH"} {@link java.security.KeyFactory} can
52      * be used to translate {@code KeySpecs} or keys from another {@link java.security.Provider}
53      *
54      * @param recipientKey public key of the recipient
55      * @param info application-supplied information, may be null or empty
56      * @param senderKey private key of the sender, for symmetric auth modes only, else null
57      * @param psk pre-shared key, for PSK auth modes only, else null
58      * @param psk_id pre-shared key ID, for PSK auth modes only, else null
59      * @throws InvalidKeyException if recipientKey is null or an unsupported key format
60      * @throws UnsupportedOperationException if mode is not a supported HPKE mode
61      * @throws IllegalStateException if this SPI has already been initialised
62      */
engineInitSender( @onNull PublicKey recipientKey, @Nullable byte[] info, @Nullable PrivateKey senderKey, @Nullable byte[] psk, @Nullable byte[] psk_id)63     void engineInitSender(
64             @NonNull PublicKey recipientKey,
65             @Nullable byte[] info,
66             @Nullable PrivateKey senderKey,
67             @Nullable byte[] psk,
68             @Nullable byte[] psk_id)
69             throws InvalidKeyException;
70 
71     /**
72      * Initialises an HPKE SPI in one of the sender modes described in RFC 9180 with
73      * a predefined random seed to allow testing against known test vectors.
74      * <p>
75      * This mode provides absolutely no security and should only be used for testing
76      * purposes.
77      * <p>
78      * If {@code psk} and {@code psk_id} are supplied then Pre-Shared Key Authentication
79      * will be used.
80      * <p>
81      * If {@code senderKey} is supplied then Asymmetric Key Authentication will be used.
82      * <p>
83      * If neither is supplied then "base" mode (no sender authentication) will be used.
84      * <p>
85      * Note that only base mode is currently supported on Android.
86      * <p>
87      * Public and private keys must be supplied in a format that can be used by the
88      * implementation.  An instance of the {@code "XDH"} {@link java.security.KeyFactory} can
89      * be used to translate {@code KeySpecs} or keys from another {@link java.security.Provider}
90      *
91      *
92      * @param recipientKey public key of the recipient
93      * @param info application-supplied information, may be null or empty
94      * @param senderKey private key of the sender, for symmetric auth modes only, else null
95      * @param psk pre-shared key, for PSK auth modes only, else null
96      * @param psk_id pre-shared key ID, for PSK auth modes only, else null
97      * @param sKe Predetermined random seed, should only be usesd  for validation against
98      *            known test vectors
99      * @throws InvalidKeyException if recipientKey is null or an unsupported key format or senderKey
100      *            is an unsupported key format
101      * @throws UnsupportedOperationException if mode is not a supported HPKE mode
102      * @throws IllegalStateException if this SPI has already been initialised
103      */
engineInitSenderWithSeed( @onNull PublicKey recipientKey, @Nullable byte[] info, @Nullable PrivateKey senderKey, @Nullable byte[] psk, @Nullable byte[] psk_id, @NonNull byte[] sKe)104     void engineInitSenderWithSeed(
105             @NonNull PublicKey recipientKey,
106             @Nullable byte[] info,
107             @Nullable PrivateKey senderKey,
108             @Nullable byte[] psk,
109             @Nullable byte[] psk_id,
110             @NonNull byte[] sKe)
111             throws InvalidKeyException;
112 
113     /**
114      * Initialises an HPKE SPI in one of the sender modes described in RFC 9180.
115      * <p>
116      * If {@code psk} and {@code psk_id} are supplied then Pre-Shared Key Authentication
117      * will be used.
118      * <p>
119      * If {@code senderKey} is supplied then Asymmetric Key Authentication will be used.
120      * <p>
121      * If neither is supplied then "base" mode (no sender authentication) will be used.
122      * <p>
123      * Note that only base mode is currently supported on Android.
124      * <p>
125      * Public and private keys must be supplied in a format that can be used by the
126      * implementation.  An instance of the {@code "XDH"} {@link java.security.KeyFactory} can
127      * be used to translate {@code KeySpecs} or keys from another {@link java.security.Provider}
128      *
129      * @param encapsulated encapsulated ephemeral key from a sender
130      * @param recipientKey private key of the recipient
131      * @param info application-supplied information, may be null or empty
132      * @param senderKey public key of sender, for asymmetric auth modes only, else null
133      * @param psk pre-shared key, for PSK auth modes only, else null
134      * @param psk_id pre-shared key ID, for PSK auth modes only, else null
135      * @throws InvalidKeyException if recipientKey is null or an unsupported key format or senderKey
136      *         is an unsupported key format
137      * @throws UnsupportedOperationException if mode is not a supported HPKE mode
138      * @throws IllegalStateException if this SPI has already been initialised
139      */
engineInitRecipient( @onNull byte[] encapsulated, @NonNull PrivateKey recipientKey, @Nullable byte[] info, @Nullable PublicKey senderKey, @Nullable byte[] psk, @Nullable byte[] psk_id)140     void engineInitRecipient(
141             @NonNull byte[] encapsulated,
142             @NonNull PrivateKey recipientKey,
143             @Nullable byte[] info,
144             @Nullable PublicKey senderKey,
145             @Nullable byte[] psk,
146             @Nullable byte[] psk_id)
147             throws InvalidKeyException;
148 
149     /**
150      * Seals a message, using the internal key schedule maintained by an HPKE sender SPI.
151      *
152      * @param plaintext the plaintext
153      * @param aad optional associated data, may be null or empty
154      * @return the ciphertext
155      * @throws NullPointerException if the plaintext is null
156      * @throws IllegalStateException if this SPI has not been initialised or if it was initialised
157      *         as a recipient
158      */
engineSeal(@onNull byte[] plaintext, @Nullable byte[] aad)159     @NonNull byte[] engineSeal(@NonNull byte[] plaintext, @Nullable byte[] aad);
160 
161     /**
162      * Opens a message, using the internal key schedule maintained by an HPKE recipient SPI.
163      *
164      * @param ciphertext the ciphertext
165      * @param aad optional associated data, may be null or empty
166      * @return the plaintext
167      * @throws IllegalStateException if this SPI has not been initialised or if it was initialised
168      *         as a sender
169      * @throws GeneralSecurityException on decryption failures
170      */
engineOpen(@onNull byte[] ciphertext, @Nullable byte[] aad)171     @NonNull byte[] engineOpen(@NonNull byte[] ciphertext, @Nullable byte[] aad)
172             throws GeneralSecurityException;
173 
174     /**
175      * Exports secret key material from this SPI as described in RFC 9180.
176      *
177      * @param length  expected output length
178      * @param context optional context string, may be null or empty
179      * @return exported value
180      * @throws IllegalArgumentException if the length is not valid for the KDF in use
181      * @throws IllegalStateException if this SPI has not been initialised
182      *
183      */
engineExport(int length, @Nullable byte[] context)184     @NonNull byte[] engineExport(int length, @Nullable byte[] context);
185 
186     /**
187      * Returns the encapsulated key material for an HPKE sender.
188      *
189      * @return the key material
190      * @throws IllegalStateException if this SPI has not been initialised or if it was initialised
191      *         as a recipient
192      */
getEncapsulated()193     @NonNull byte[] getEncapsulated();
194 }
195