1 /*
2  * Copyright (C) 2023 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.adservices.ohttp.algorithms;
18 
19 import com.android.adservices.ohttp.KemNativeRef;
20 
21 import com.google.auto.value.AutoValue;
22 
23 import java.util.function.Supplier;
24 
25 /** Specifies the algorithm spec of a Key Encapsulation Mechanism algorithm */
26 @AutoValue
27 public abstract class KemAlgorithmSpec {
28     // As defined in https://www.rfc-editor.org/rfc/rfc9180#name-key-encapsulation-mechanism
29     public static final int DHKEM_X25519_HKDF_SHA256_IDENTIFIER = 0x0020;
30 
31     private static final String DHKEM_X25519_HKDF_SHA256 = "DHKEM_X25519_HKDF_SHA256";
32 
33     /** The variables as defined in : https://www.rfc-editor.org/rfc/rfc9180#section-11.1-1 */
34 
35     /** Get the identifier for the algorithm */
identifier()36     public abstract int identifier();
37 
38     /** Get the name of the algorithm */
name()39     public abstract String name();
40 
41     /** Get the length in bytes of a KEM shared secret produced by the algorithm */
secretLength()42     public abstract int secretLength();
43 
44     /** Get the length in bytes of an encoded encapsulated key produced by the algorithm */
encapsulatedKeyLength()45     public abstract int encapsulatedKeyLength();
46 
47     /** Get the length in bytes of an encoded public key for the algorithm */
publicKeyLength()48     public abstract int publicKeyLength();
49 
50     /** Get the length in bytes of an encoded private key for the algorithm */
privateKeyLength()51     public abstract int privateKeyLength();
52 
53     /**
54      * Get the length in bytes of the seed that will be used by Hpke Setup Base Operation
55      *
56      * <p>The Hpke Setup Base operation uses a seed. That seed should always be random unless
57      * testing. The length of the seed depends on the KEM algorithm being used. For example, for KEM
58      * X25519, it is equal to the length of the private key.
59      */
seedLength()60     public abstract int seedLength();
61 
62     /** Gets the supplier of the KEM algorithm native reference */
kemNativeRefSupplier()63     public abstract Supplier<KemNativeRef> kemNativeRefSupplier();
64 
dhkemX25519HkdfSha256()65     private static KemAlgorithmSpec dhkemX25519HkdfSha256() {
66         // Spec taken from https://www.rfc-editor.org/rfc/rfc9180#name-key-encapsulation-mechanism
67         return new AutoValue_KemAlgorithmSpec(
68                 /* identifier= */ DHKEM_X25519_HKDF_SHA256_IDENTIFIER,
69                 DHKEM_X25519_HKDF_SHA256,
70                 /* secretLength= */ 32,
71                 /* encapsulatedKeyLength= */ 32,
72                 /* publicKeyLength= */ 32,
73                 /* privateKeyLength= */ 32,
74                 /* seedLength= */ 32,
75                 () -> KemNativeRef.getHpkeKemDhkemX25519HkdfSha256Reference());
76     }
77 
78     /**
79      * Gets the KEM algorithm corresponding to the identifier
80      *
81      * <p>As specified in https://www.rfc-editor.org/rfc/rfc9180#name-key-encapsulation-mechanism
82      */
get(int identifier)83     public static KemAlgorithmSpec get(int identifier) throws UnsupportedHpkeAlgorithmException {
84         if (identifier == DHKEM_X25519_HKDF_SHA256_IDENTIFIER) {
85             return dhkemX25519HkdfSha256();
86         }
87 
88         throw new UnsupportedHpkeAlgorithmException("Only Kem ID = 0X0020 supported");
89     }
90 }
91