1 // Copyright 2018 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.signature; 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.InsecureSecretKeyAccess; 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.PrivateKeyManager; 27 import com.google.crypto.tink.PublicKeySign; 28 import com.google.crypto.tink.PublicKeyVerify; 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.MutableParametersRegistry; 34 import com.google.crypto.tink.internal.MutablePrimitiveRegistry; 35 import com.google.crypto.tink.internal.PrimitiveConstructor; 36 import com.google.crypto.tink.proto.KeyData.KeyMaterialType; 37 import com.google.crypto.tink.signature.internal.RsaSsaPssProtoSerialization; 38 import com.google.crypto.tink.subtle.EngineFactory; 39 import com.google.crypto.tink.subtle.RsaSsaPssSignJce; 40 import com.google.crypto.tink.subtle.RsaSsaPssVerifyJce; 41 import com.google.crypto.tink.util.SecretBigInteger; 42 import java.math.BigInteger; 43 import java.security.GeneralSecurityException; 44 import java.security.KeyPair; 45 import java.security.KeyPairGenerator; 46 import java.security.interfaces.RSAPrivateCrtKey; 47 import java.security.interfaces.RSAPublicKey; 48 import java.security.spec.RSAKeyGenParameterSpec; 49 import java.util.Collections; 50 import java.util.HashMap; 51 import java.util.Map; 52 import javax.annotation.Nullable; 53 54 /** 55 * This key manager generates new {@code RsaSsaPssPrivateKey} keys and produces new instances of 56 * {@code RsaSsaPssSignJce}. 57 */ 58 public final class RsaSsaPssSignKeyManager { 59 private static final PrimitiveConstructor<RsaSsaPssPrivateKey, PublicKeySign> 60 PUBLIC_KEY_SIGN_PRIMITIVE_CONSTRUCTOR = 61 PrimitiveConstructor.create( 62 RsaSsaPssSignJce::create, RsaSsaPssPrivateKey.class, PublicKeySign.class); 63 64 private static final PrimitiveConstructor<RsaSsaPssPublicKey, PublicKeyVerify> 65 PUBLIC_KEY_VERIFY_PRIMITIVE_CONSTRUCTOR = 66 PrimitiveConstructor.create( 67 RsaSsaPssVerifyJce::create, RsaSsaPssPublicKey.class, PublicKeyVerify.class); 68 69 private static final PrivateKeyManager<PublicKeySign> legacyPrivateKeyManager = 70 LegacyKeyManagerImpl.createPrivateKeyManager( 71 getKeyType(), 72 PublicKeySign.class, 73 com.google.crypto.tink.proto.RsaSsaPssPrivateKey.parser()); 74 75 private static final KeyManager<PublicKeyVerify> legacyPublicKeyManager = 76 LegacyKeyManagerImpl.create( 77 RsaSsaPssVerifyKeyManager.getKeyType(), 78 PublicKeyVerify.class, 79 KeyMaterialType.ASYMMETRIC_PUBLIC, 80 com.google.crypto.tink.proto.RsaSsaPssPublicKey.parser()); 81 getKeyType()82 static String getKeyType() { 83 return "type.googleapis.com/google.crypto.tink.RsaSsaPssPrivateKey"; 84 } 85 86 @AccessesPartialKey createKey( RsaSsaPssParameters parameters, @Nullable Integer idRequirement)87 private static RsaSsaPssPrivateKey createKey( 88 RsaSsaPssParameters parameters, @Nullable Integer idRequirement) 89 throws GeneralSecurityException { 90 KeyPairGenerator keyGen = EngineFactory.KEY_PAIR_GENERATOR.getInstance("RSA"); 91 RSAKeyGenParameterSpec spec = 92 new RSAKeyGenParameterSpec( 93 parameters.getModulusSizeBits(), 94 new BigInteger(1, parameters.getPublicExponent().toByteArray())); 95 keyGen.initialize(spec); 96 KeyPair keyPair = keyGen.generateKeyPair(); 97 RSAPublicKey pubKey = (RSAPublicKey) keyPair.getPublic(); 98 RSAPrivateCrtKey privKey = (RSAPrivateCrtKey) keyPair.getPrivate(); 99 100 // Creates RsaSsaPssPublicKey. 101 RsaSsaPssPublicKey rsaSsaPssPublicKey = 102 RsaSsaPssPublicKey.builder() 103 .setParameters(parameters) 104 .setModulus(pubKey.getModulus()) 105 .setIdRequirement(idRequirement) 106 .build(); 107 108 // Creates RsaSsaPssPrivateKey. 109 return RsaSsaPssPrivateKey.builder() 110 .setPublicKey(rsaSsaPssPublicKey) 111 .setPrimes( 112 SecretBigInteger.fromBigInteger(privKey.getPrimeP(), InsecureSecretKeyAccess.get()), 113 SecretBigInteger.fromBigInteger(privKey.getPrimeQ(), InsecureSecretKeyAccess.get())) 114 .setPrivateExponent( 115 SecretBigInteger.fromBigInteger( 116 privKey.getPrivateExponent(), InsecureSecretKeyAccess.get())) 117 .setPrimeExponents( 118 SecretBigInteger.fromBigInteger( 119 privKey.getPrimeExponentP(), InsecureSecretKeyAccess.get()), 120 SecretBigInteger.fromBigInteger( 121 privKey.getPrimeExponentQ(), InsecureSecretKeyAccess.get())) 122 .setCrtCoefficient( 123 SecretBigInteger.fromBigInteger( 124 privKey.getCrtCoefficient(), InsecureSecretKeyAccess.get())) 125 .build(); 126 } 127 128 @SuppressWarnings("InlineLambdaConstant") // We need a correct Object#equals in registration. 129 private static final MutableKeyCreationRegistry.KeyCreator<RsaSsaPssParameters> KEY_CREATOR = 130 RsaSsaPssSignKeyManager::createKey; 131 namedParameters()132 private static Map<String, Parameters> namedParameters() throws GeneralSecurityException { 133 Map<String, Parameters> result = new HashMap<>(); 134 result.put( 135 "RSA_SSA_PSS_3072_SHA256_F4", 136 RsaSsaPssParameters.builder() 137 .setSigHashType(RsaSsaPssParameters.HashType.SHA256) 138 .setMgf1HashType(RsaSsaPssParameters.HashType.SHA256) 139 .setSaltLengthBytes(32) 140 .setModulusSizeBits(3072) 141 .setPublicExponent(RsaSsaPssParameters.F4) 142 .setVariant(RsaSsaPssParameters.Variant.TINK) 143 .build()); 144 result.put( 145 "RSA_SSA_PSS_3072_SHA256_F4_RAW", 146 RsaSsaPssParameters.builder() 147 .setSigHashType(RsaSsaPssParameters.HashType.SHA256) 148 .setMgf1HashType(RsaSsaPssParameters.HashType.SHA256) 149 .setSaltLengthBytes(32) 150 .setModulusSizeBits(3072) 151 .setPublicExponent(RsaSsaPssParameters.F4) 152 .setVariant(RsaSsaPssParameters.Variant.NO_PREFIX) 153 .build()); 154 // This is identical to RSA_SSA_PSS_3072_SHA256_F4. It is needed to maintain backward 155 // compatibility with SignatureKeyTemplates. 156 result.put( 157 "RSA_SSA_PSS_3072_SHA256_SHA256_32_F4", 158 PredefinedSignatureParameters.RSA_SSA_PSS_3072_SHA256_SHA256_32_F4); 159 result.put( 160 "RSA_SSA_PSS_4096_SHA512_F4", 161 RsaSsaPssParameters.builder() 162 .setSigHashType(RsaSsaPssParameters.HashType.SHA512) 163 .setMgf1HashType(RsaSsaPssParameters.HashType.SHA512) 164 .setSaltLengthBytes(64) 165 .setModulusSizeBits(4096) 166 .setPublicExponent(RsaSsaPssParameters.F4) 167 .setVariant(RsaSsaPssParameters.Variant.TINK) 168 .build()); 169 result.put( 170 "RSA_SSA_PSS_4096_SHA512_F4_RAW", 171 RsaSsaPssParameters.builder() 172 .setSigHashType(RsaSsaPssParameters.HashType.SHA512) 173 .setMgf1HashType(RsaSsaPssParameters.HashType.SHA512) 174 .setSaltLengthBytes(64) 175 .setModulusSizeBits(4096) 176 .setPublicExponent(RsaSsaPssParameters.F4) 177 .setVariant(RsaSsaPssParameters.Variant.NO_PREFIX) 178 .build()); 179 // This is identical to RSA_SSA_PSS_4096_SHA512_F4. It is needed to maintain backward 180 // compatibility with SignatureKeyTemplates. 181 result.put( 182 "RSA_SSA_PSS_4096_SHA512_SHA512_64_F4", 183 PredefinedSignatureParameters.RSA_SSA_PSS_4096_SHA512_SHA512_64_F4); 184 return Collections.unmodifiableMap(result); 185 } 186 187 private static final TinkFipsUtil.AlgorithmFipsCompatibility FIPS = 188 TinkFipsUtil.AlgorithmFipsCompatibility.ALGORITHM_REQUIRES_BORINGCRYPTO; 189 190 /** 191 * Registers the {@link RsaSsaPssSignKeyManager} and the {@link RsaSsaPssVerifyKeyManager} with 192 * the registry, so that the the RsaSsaPss-Keys can be used with Tink. 193 */ registerPair(boolean newKeyAllowed)194 public static void registerPair(boolean newKeyAllowed) throws GeneralSecurityException { 195 if (!FIPS.isCompatible()) { 196 throw new GeneralSecurityException( 197 "Can not use RSA SSA PSS in FIPS-mode, as BoringCrypto module is not available."); 198 } 199 RsaSsaPssProtoSerialization.register(); 200 MutableParametersRegistry.globalInstance().putAll(namedParameters()); 201 MutablePrimitiveRegistry.globalInstance() 202 .registerPrimitiveConstructor(PUBLIC_KEY_SIGN_PRIMITIVE_CONSTRUCTOR); 203 MutablePrimitiveRegistry.globalInstance() 204 .registerPrimitiveConstructor(PUBLIC_KEY_VERIFY_PRIMITIVE_CONSTRUCTOR); 205 MutableKeyCreationRegistry.globalInstance().add(KEY_CREATOR, RsaSsaPssParameters.class); 206 KeyManagerRegistry.globalInstance() 207 .registerKeyManagerWithFipsCompatibility(legacyPrivateKeyManager, FIPS, newKeyAllowed); 208 KeyManagerRegistry.globalInstance() 209 .registerKeyManagerWithFipsCompatibility(legacyPublicKeyManager, FIPS, false); 210 } 211 212 /** 213 * @return A {@link KeyTemplate} that generates new instances of RSA-SSA-PSS key pairs with the 214 * following parameters: 215 * <ul> 216 * <li>Signature hash: SHA256. 217 * <li>MGF1 hash: SHA256. 218 * <li>Salt length: 32 (i.e., SHA256's output length). 219 * <li>Modulus size: 3072 bit. 220 * <li>Public exponent: 65537 (aka F4). 221 * <li>Prefix type: {@link KeyTemplate.OutputPrefixType#TINK}. 222 * </ul> 223 */ rsa3072PssSha256F4Template()224 public static final KeyTemplate rsa3072PssSha256F4Template() { 225 return exceptionIsBug( 226 () -> 227 KeyTemplate.createFrom( 228 RsaSsaPssParameters.builder() 229 .setSigHashType(RsaSsaPssParameters.HashType.SHA256) 230 .setMgf1HashType(RsaSsaPssParameters.HashType.SHA256) 231 .setSaltLengthBytes(32) 232 .setModulusSizeBits(3072) 233 .setPublicExponent(RsaSsaPssParameters.F4) 234 .setVariant(RsaSsaPssParameters.Variant.TINK) 235 .build())); 236 } 237 /** 238 * @return A {@link KeyTemplate} that generates new instances of RSA-SSA-PSS key pairs with the 239 * following parameters: 240 * <ul> 241 * <li>Signature hash: SHA256. 242 * <li>MGF1 hash: SHA256. 243 * <li>Salt length: 32 (i.e., SHA256's output length). 244 * <li>Modulus size: 3072 bit. 245 * <li>Public exponent: 65537 (aka F4). 246 * <li>Prefix type: {@link KeyTemplate.OutputPrefixType#RAW} (no prefix). 247 * </ul> 248 * <p>Keys generated from this template create signatures compatible with OpenSSL and other 249 * libraries. 250 */ rawRsa3072PssSha256F4Template()251 public static final KeyTemplate rawRsa3072PssSha256F4Template() { 252 return exceptionIsBug( 253 () -> 254 KeyTemplate.createFrom( 255 RsaSsaPssParameters.builder() 256 .setSigHashType(RsaSsaPssParameters.HashType.SHA256) 257 .setMgf1HashType(RsaSsaPssParameters.HashType.SHA256) 258 .setSaltLengthBytes(32) 259 .setModulusSizeBits(3072) 260 .setPublicExponent(RsaSsaPssParameters.F4) 261 .setVariant(RsaSsaPssParameters.Variant.NO_PREFIX) 262 .build())); 263 } 264 265 /** 266 * @return A {@link KeyTemplate} that generates new instances of RSA-SSA-PSS key pairs with the 267 * following parameters: 268 * <ul> 269 * <li>Signature hash: SHA512. 270 * <li>MGF1 hash: SHA512. 271 * <li>Salt length: 64 (i.e., SHA512's output length). 272 * <li>Modulus size: 4096 bit. 273 * <li>Public exponent: 65537 (aka F4). 274 * <li>Prefix type: {@link KeyTemplate.OutputPrefixType#TINK}. 275 * </ul> 276 */ rsa4096PssSha512F4Template()277 public static final KeyTemplate rsa4096PssSha512F4Template() { 278 return exceptionIsBug( 279 () -> 280 KeyTemplate.createFrom( 281 RsaSsaPssParameters.builder() 282 .setSigHashType(RsaSsaPssParameters.HashType.SHA512) 283 .setMgf1HashType(RsaSsaPssParameters.HashType.SHA512) 284 .setSaltLengthBytes(64) 285 .setModulusSizeBits(4096) 286 .setPublicExponent(RsaSsaPssParameters.F4) 287 .setVariant(RsaSsaPssParameters.Variant.TINK) 288 .build())); 289 } 290 291 /** 292 * @return A {@link KeyTemplate} that generates new instances of RSA-SSA-PSS key pairs with the 293 * following parameters: 294 * <ul> 295 * <li>Signature hash: SHA512. 296 * <li>MGF1 hash: SHA512. 297 * <li>Salt length: 64 (i.e., SHA512's output length). 298 * <li>Modulus size: 4096 bit. 299 * <li>Public exponent: 65537 (aka F4). 300 * <li>Prefix type: {@link KeyTemplate.OutputPrefixType#RAW} (no prefix). 301 * </ul> 302 * <p>Keys generated from this template create signatures compatible with OpenSSL and other 303 * libraries. 304 */ rawRsa4096PssSha512F4Template()305 public static final KeyTemplate rawRsa4096PssSha512F4Template() { 306 return exceptionIsBug( 307 () -> 308 KeyTemplate.createFrom( 309 RsaSsaPssParameters.builder() 310 .setSigHashType(RsaSsaPssParameters.HashType.SHA512) 311 .setMgf1HashType(RsaSsaPssParameters.HashType.SHA512) 312 .setSaltLengthBytes(64) 313 .setModulusSizeBits(4096) 314 .setPublicExponent(RsaSsaPssParameters.F4) 315 .setVariant(RsaSsaPssParameters.Variant.NO_PREFIX) 316 .build())); 317 } 318 RsaSsaPssSignKeyManager()319 private RsaSsaPssSignKeyManager() {} 320 } 321