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