• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2017 Google Inc.
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 static com.google.crypto.tink.internal.TinkBugException.exceptionIsBug;
20 
21 import com.google.crypto.tink.AccessesPartialKey;
22 import com.google.crypto.tink.KeyManager;
23 import com.google.crypto.tink.KeyTemplate;
24 import com.google.crypto.tink.Parameters;
25 import com.google.crypto.tink.SecretKeyAccess;
26 import com.google.crypto.tink.config.internal.TinkFipsUtil;
27 import com.google.crypto.tink.internal.KeyManagerRegistry;
28 import com.google.crypto.tink.internal.LegacyKeyManagerImpl;
29 import com.google.crypto.tink.internal.MutableKeyCreationRegistry;
30 import com.google.crypto.tink.internal.MutableKeyDerivationRegistry;
31 import com.google.crypto.tink.internal.MutableParametersRegistry;
32 import com.google.crypto.tink.internal.MutablePrimitiveRegistry;
33 import com.google.crypto.tink.internal.PrimitiveConstructor;
34 import com.google.crypto.tink.internal.Util;
35 import com.google.crypto.tink.prf.internal.HmacPrfProtoSerialization;
36 import com.google.crypto.tink.proto.KeyData.KeyMaterialType;
37 import com.google.crypto.tink.subtle.PrfHmacJce;
38 import com.google.crypto.tink.util.SecretBytes;
39 import java.io.InputStream;
40 import java.security.GeneralSecurityException;
41 import java.util.Collections;
42 import java.util.HashMap;
43 import java.util.Map;
44 import javax.annotation.Nullable;
45 
46 /**
47  * This key manager generates new {@code HmacPrfKey} keys and produces new instances of {@code
48  * PrfHmacJce}.
49  */
50 public final class HmacPrfKeyManager {
51 
52   private static final PrimitiveConstructor<com.google.crypto.tink.prf.HmacPrfKey, Prf>
53       PRF_PRIMITIVE_CONSTRUCTOR =
54           PrimitiveConstructor.create(
55               PrfHmacJce::create, com.google.crypto.tink.prf.HmacPrfKey.class, Prf.class);
56 
57   private static final KeyManager<Prf> legacyKeyManager =
58       LegacyKeyManagerImpl.create(
59           getKeyType(),
60           Prf.class,
61           KeyMaterialType.SYMMETRIC,
62           com.google.crypto.tink.proto.HmacPrfKey.parser());
63 
64   @AccessesPartialKey
newKey(HmacPrfParameters parameters, @Nullable Integer idRequirement)65   private static HmacPrfKey newKey(HmacPrfParameters parameters, @Nullable Integer idRequirement)
66       throws GeneralSecurityException {
67     if (idRequirement != null) {
68       throw new GeneralSecurityException("Id Requirement is not supported for HMAC PRF keys");
69     }
70     return HmacPrfKey.builder()
71         .setParameters(parameters)
72         .setKeyBytes(SecretBytes.randomBytes(parameters.getKeySizeBytes()))
73         .build();
74   }
75 
76   @SuppressWarnings("InlineLambdaConstant") // We need a correct Object#equals in registration.
77   private static final MutableKeyCreationRegistry.KeyCreator<HmacPrfParameters> KEY_CREATOR =
78       HmacPrfKeyManager::newKey;
79 
getKeyType()80   static String getKeyType() {
81     return "type.googleapis.com/google.crypto.tink.HmacPrfKey";
82   }
83 
84   @SuppressWarnings("InlineLambdaConstant") // We need a correct Object#equals in registration.
85   private static final MutableKeyDerivationRegistry.InsecureKeyCreator<HmacPrfParameters>
86       KEY_DERIVER = HmacPrfKeyManager::createHmacKeyFromRandomness;
87 
88   @AccessesPartialKey
createHmacKeyFromRandomness( HmacPrfParameters parameters, InputStream stream, @Nullable Integer idRequirement, SecretKeyAccess access)89   static com.google.crypto.tink.prf.HmacPrfKey createHmacKeyFromRandomness(
90       HmacPrfParameters parameters,
91       InputStream stream,
92       @Nullable Integer idRequirement,
93       SecretKeyAccess access)
94       throws GeneralSecurityException {
95     return com.google.crypto.tink.prf.HmacPrfKey.builder()
96         .setParameters(parameters)
97         .setKeyBytes(Util.readIntoSecretBytes(stream, parameters.getKeySizeBytes(), access))
98         .build();
99   }
100 
namedParameters()101   private static Map<String, Parameters> namedParameters() throws GeneralSecurityException {
102         Map<String, Parameters> result = new HashMap<>();
103         result.put("HMAC_SHA256_PRF", PredefinedPrfParameters.HMAC_SHA256_PRF);
104         result.put("HMAC_SHA512_PRF", PredefinedPrfParameters.HMAC_SHA512_PRF);
105     return Collections.unmodifiableMap(result);
106   }
107 
108   private static final TinkFipsUtil.AlgorithmFipsCompatibility FIPS =
109       TinkFipsUtil.AlgorithmFipsCompatibility.ALGORITHM_REQUIRES_BORINGCRYPTO;
110 
register(boolean newKeyAllowed)111   public static void register(boolean newKeyAllowed) throws GeneralSecurityException {
112     if (!FIPS.isCompatible()) {
113       throw new GeneralSecurityException(
114           "Can not use HMAC in FIPS-mode, as BoringCrypto module is not available.");
115     }
116     HmacPrfProtoSerialization.register();
117     MutablePrimitiveRegistry.globalInstance()
118         .registerPrimitiveConstructor(PRF_PRIMITIVE_CONSTRUCTOR);
119     MutableParametersRegistry.globalInstance().putAll(namedParameters());
120     MutableKeyCreationRegistry.globalInstance().add(KEY_CREATOR, HmacPrfParameters.class);
121     MutableKeyDerivationRegistry.globalInstance().add(KEY_DERIVER, HmacPrfParameters.class);
122     KeyManagerRegistry.globalInstance()
123         .registerKeyManagerWithFipsCompatibility(legacyKeyManager, FIPS, newKeyAllowed);
124   }
125 
126   /**
127    * Returns a {@link KeyTemplate} that generates new instances of HMAC keys with the following
128    * parameters:
129    *
130    * <ul>
131    *   <li>Key size: 32 bytes
132    *   <li>Hash function: SHA256
133    *   <li>Prefix type: {@link KeyTemplate.OutputPrefixType#RAW}
134    * </ul>
135    */
hmacSha256Template()136   public static final KeyTemplate hmacSha256Template() {
137     return exceptionIsBug(
138         () ->
139             KeyTemplate.createFrom(
140                 HmacPrfParameters.builder()
141                     .setKeySizeBytes(32)
142                     .setHashType(HmacPrfParameters.HashType.SHA256)
143                     .build()));
144   }
145 
146   /**
147    * Returns a {@link KeyTemplate} that generates new instances of HMAC keys with the following
148    * parameters:
149    *
150    * <ul>
151    *   <li>Key size: 64 bytes
152    *   <li>Hash function: SHA512
153    *   <li>Prefix type: {@link KeyTemplate.OutputPrefixType#RAW}
154    * </ul>
155    */
hmacSha512Template()156   public static final KeyTemplate hmacSha512Template() {
157     return exceptionIsBug(
158         () ->
159             KeyTemplate.createFrom(
160                 HmacPrfParameters.builder()
161                     .setKeySizeBytes(64)
162                     .setHashType(HmacPrfParameters.HashType.SHA512)
163                     .build()));
164   }
165 
HmacPrfKeyManager()166   private HmacPrfKeyManager() {}
167 }
168