• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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