• 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.aead;
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.Aead;
23 import com.google.crypto.tink.KeyManager;
24 import com.google.crypto.tink.KeyTemplate;
25 import com.google.crypto.tink.Parameters;
26 import com.google.crypto.tink.SecretKeyAccess;
27 import com.google.crypto.tink.aead.internal.XChaCha20Poly1305Jce;
28 import com.google.crypto.tink.aead.internal.XChaCha20Poly1305ProtoSerialization;
29 import com.google.crypto.tink.config.internal.TinkFipsUtil;
30 import com.google.crypto.tink.internal.KeyManagerRegistry;
31 import com.google.crypto.tink.internal.LegacyKeyManagerImpl;
32 import com.google.crypto.tink.internal.MutableKeyCreationRegistry;
33 import com.google.crypto.tink.internal.MutableKeyDerivationRegistry;
34 import com.google.crypto.tink.internal.MutableParametersRegistry;
35 import com.google.crypto.tink.internal.MutablePrimitiveRegistry;
36 import com.google.crypto.tink.internal.PrimitiveConstructor;
37 import com.google.crypto.tink.internal.Util;
38 import com.google.crypto.tink.proto.KeyData.KeyMaterialType;
39 import com.google.crypto.tink.subtle.XChaCha20Poly1305;
40 import com.google.crypto.tink.util.SecretBytes;
41 import java.io.InputStream;
42 import java.security.GeneralSecurityException;
43 import java.util.Collections;
44 import java.util.HashMap;
45 import java.util.Map;
46 import javax.annotation.Nullable;
47 
48 /**
49  * This instance of {@code KeyManager} generates new {@code XChaCha20Poly1305} keys and produces new
50  * instances of {@code XChaCha20Poly1305}.
51  */
52 public final class XChaCha20Poly1305KeyManager {
53 
createAead(XChaCha20Poly1305Key key)54   private static Aead createAead(XChaCha20Poly1305Key key) throws GeneralSecurityException {
55     if (XChaCha20Poly1305Jce.isSupported()) {
56       return XChaCha20Poly1305Jce.create(key);
57     }
58     return XChaCha20Poly1305.create(key);
59   }
60 
61   private static final PrimitiveConstructor<XChaCha20Poly1305Key, Aead>
62       X_CHA_CHA_20_POLY_1305_PRIMITIVE_CONSTRUCTOR =
63           PrimitiveConstructor.create(
64               XChaCha20Poly1305KeyManager::createAead, XChaCha20Poly1305Key.class, Aead.class);
65 
66   private static final int KEY_SIZE_IN_BYTES = 32;
67 
getKeyType()68   static String getKeyType() {
69     return "type.googleapis.com/google.crypto.tink.XChaCha20Poly1305Key";
70   }
71 
72   private static final KeyManager<Aead> legacyKeyManager =
73       LegacyKeyManagerImpl.create(
74           getKeyType(),
75           Aead.class,
76           KeyMaterialType.SYMMETRIC,
77           com.google.crypto.tink.proto.XChaCha20Poly1305Key.parser());
78 
79   @SuppressWarnings("InlineLambdaConstant") // We need a correct Object#equals in registration.
80   private static final MutableKeyDerivationRegistry.InsecureKeyCreator<XChaCha20Poly1305Parameters>
81       KEY_DERIVER = XChaCha20Poly1305KeyManager::createXChaChaKeyFromRandomness;
82 
83   @AccessesPartialKey
createXChaChaKeyFromRandomness( XChaCha20Poly1305Parameters parameters, InputStream stream, @Nullable Integer idRequirement, SecretKeyAccess access)84   static com.google.crypto.tink.aead.XChaCha20Poly1305Key createXChaChaKeyFromRandomness(
85       XChaCha20Poly1305Parameters parameters,
86       InputStream stream,
87       @Nullable Integer idRequirement,
88       SecretKeyAccess access)
89       throws GeneralSecurityException {
90     return com.google.crypto.tink.aead.XChaCha20Poly1305Key.create(
91         parameters.getVariant(),
92         Util.readIntoSecretBytes(stream, KEY_SIZE_IN_BYTES, access),
93         idRequirement);
94   }
95 
96   @SuppressWarnings("InlineLambdaConstant") // We need a correct Object#equals in registration.
97   private static final MutableKeyCreationRegistry.KeyCreator<XChaCha20Poly1305Parameters>
98       KEY_CREATOR = XChaCha20Poly1305KeyManager::createXChaChaKey;
99 
100   @AccessesPartialKey
createXChaChaKey( XChaCha20Poly1305Parameters parameters, @Nullable Integer idRequirement)101   static com.google.crypto.tink.aead.XChaCha20Poly1305Key createXChaChaKey(
102       XChaCha20Poly1305Parameters parameters, @Nullable Integer idRequirement)
103       throws GeneralSecurityException {
104     return com.google.crypto.tink.aead.XChaCha20Poly1305Key.create(
105         parameters.getVariant(), SecretBytes.randomBytes(KEY_SIZE_IN_BYTES), idRequirement);
106   }
107 
namedParameters()108   private static Map<String, Parameters> namedParameters() throws GeneralSecurityException {
109     Map<String, Parameters> result = new HashMap<>();
110         result.put(
111             "XCHACHA20_POLY1305",
112             XChaCha20Poly1305Parameters.create(XChaCha20Poly1305Parameters.Variant.TINK));
113     result.put(
114         "XCHACHA20_POLY1305_RAW",
115         XChaCha20Poly1305Parameters.create(XChaCha20Poly1305Parameters.Variant.NO_PREFIX));
116         return Collections.unmodifiableMap(result);
117   }
118 
register(boolean newKeyAllowed)119   public static void register(boolean newKeyAllowed) throws GeneralSecurityException {
120     if (!TinkFipsUtil.AlgorithmFipsCompatibility.ALGORITHM_NOT_FIPS.isCompatible()) {
121       throw new GeneralSecurityException(
122           "Registering XChaCha20Poly1305 is not supported in FIPS mode");
123     }
124     XChaCha20Poly1305ProtoSerialization.register();
125     MutablePrimitiveRegistry.globalInstance()
126         .registerPrimitiveConstructor(X_CHA_CHA_20_POLY_1305_PRIMITIVE_CONSTRUCTOR);
127     MutableParametersRegistry.globalInstance().putAll(namedParameters());
128     MutableKeyCreationRegistry.globalInstance().add(KEY_CREATOR, XChaCha20Poly1305Parameters.class);
129     MutableKeyDerivationRegistry.globalInstance()
130         .add(KEY_DERIVER, XChaCha20Poly1305Parameters.class);
131     KeyManagerRegistry.globalInstance().registerKeyManager(legacyKeyManager, newKeyAllowed);
132   }
133 
134   /**
135    * @return a {@link KeyTemplate} that generates new instances of XChaCha20Poly1305 keys.
136    */
xChaCha20Poly1305Template()137   public static final KeyTemplate xChaCha20Poly1305Template() {
138     return exceptionIsBug(
139         () ->
140             KeyTemplate.createFrom(
141                 XChaCha20Poly1305Parameters.create(XChaCha20Poly1305Parameters.Variant.TINK)));
142   }
143 
144   /**
145    * @return a {@link KeyTemplate} that generates new instances of XChaCha20Poly1305 keys. Keys
146    *     generated from this template create ciphertexts compatible with libsodium and other
147    *     libraries.
148    */
rawXChaCha20Poly1305Template()149   public static final KeyTemplate rawXChaCha20Poly1305Template() {
150     return exceptionIsBug(
151         () ->
152             KeyTemplate.createFrom(
153                 XChaCha20Poly1305Parameters.create(XChaCha20Poly1305Parameters.Variant.NO_PREFIX)));
154   }
155 
XChaCha20Poly1305KeyManager()156   private XChaCha20Poly1305KeyManager() {}
157 }
158