1 // Copyright 2024 Google LLC 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 // 15 //////////////////////////////////////////////////////////////////////////////// 16 17 package com.google.crypto.tink.prf; 18 19 import com.google.crypto.tink.Configuration; 20 import com.google.crypto.tink.config.internal.TinkFipsUtil; 21 import com.google.crypto.tink.internal.InternalConfiguration; 22 import com.google.crypto.tink.internal.PrimitiveConstructor; 23 import com.google.crypto.tink.internal.PrimitiveRegistry; 24 import com.google.crypto.tink.subtle.PrfAesCmac; 25 import com.google.crypto.tink.subtle.PrfHmacJce; 26 import com.google.crypto.tink.subtle.prf.HkdfStreamingPrf; 27 import com.google.crypto.tink.subtle.prf.PrfImpl; 28 import java.security.GeneralSecurityException; 29 30 /** 31 * PrfConfigurationV0 contains the following algorithms for PrfSet: 32 * 33 * <ul> 34 * <li>HmacPrf 35 * <li>HkdfPrf 36 * <li>AesCmacPrf 37 * </ul> 38 */ 39 /* Placeholder for internally public; DO NOT CHANGE. */ class PrfConfigurationV0 { PrfConfigurationV0()40 private PrfConfigurationV0() {} 41 42 private static final InternalConfiguration INTERNAL_CONFIGURATION = create(); 43 create()44 private static InternalConfiguration create() { 45 try { 46 PrimitiveRegistry.Builder builder = PrimitiveRegistry.builder(); 47 48 // Register {@code PrfSet} wrapper and concrete primitives. 49 PrfSetWrapper.registerToInternalPrimitiveRegistry(builder); 50 builder.registerPrimitiveConstructor( 51 PrimitiveConstructor.create(PrfHmacJce::create, HmacPrfKey.class, Prf.class)); 52 builder.registerPrimitiveConstructor( 53 PrimitiveConstructor.create( 54 PrfConfigurationV0::createHkdfPrf, HkdfPrfKey.class, Prf.class)); 55 builder.registerPrimitiveConstructor( 56 PrimitiveConstructor.create( 57 PrfConfigurationV0::createAesCmacPrf, AesCmacPrfKey.class, Prf.class)); 58 59 return InternalConfiguration.createFromPrimitiveRegistry(builder.build()); 60 } catch (GeneralSecurityException e) { 61 throw new IllegalStateException(e); 62 } 63 } 64 65 /** Returns an instance of the {@code PrfConfigurationV0}. */ get()66 public static Configuration get() throws GeneralSecurityException { 67 if (TinkFipsUtil.useOnlyFips()) { 68 throw new GeneralSecurityException( 69 "Cannot use non-FIPS-compliant PrfConfigurationV0 in FIPS mode"); 70 } 71 return INTERNAL_CONFIGURATION; 72 } 73 74 // We use a somewhat larger minimum key size than usual, because PRFs might be used by many users, 75 // in which case the security can degrade by a factor depending on the number of users. (Discussed 76 // for example in https://eprint.iacr.org/2012/159) 77 private static final int MIN_HKDF_PRF_KEY_SIZE = 32; 78 createHkdfPrf(HkdfPrfKey key)79 private static Prf createHkdfPrf(HkdfPrfKey key) throws GeneralSecurityException { 80 if (key.getParameters().getKeySizeBytes() < MIN_HKDF_PRF_KEY_SIZE) { 81 throw new GeneralSecurityException( 82 "HkdfPrf key size must be at least " + MIN_HKDF_PRF_KEY_SIZE); 83 } 84 if (key.getParameters().getHashType() != HkdfPrfParameters.HashType.SHA256 85 && key.getParameters().getHashType() != HkdfPrfParameters.HashType.SHA512) { 86 throw new GeneralSecurityException("HkdfPrf hash type must be SHA256 or SHA512"); 87 } 88 return PrfImpl.wrap(HkdfStreamingPrf.create(key)); 89 } 90 createAesCmacPrf(AesCmacPrfKey key)91 private static Prf createAesCmacPrf(AesCmacPrfKey key) throws GeneralSecurityException { 92 if (key.getParameters().getKeySizeBytes() != 32) { 93 throw new GeneralSecurityException("AesCmacPrf key size must be 32 bytes"); 94 } 95 return PrfAesCmac.create(key); 96 } 97 } 98