1 // Copyright 2024 Google 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.subtle; 18 19 import static com.google.common.truth.Truth.assertThat; 20 import static org.junit.Assert.assertThrows; 21 22 import com.google.crypto.tink.config.TinkFips; 23 import com.google.crypto.tink.config.internal.TinkFipsUtil; 24 import com.google.crypto.tink.signature.RsaSsaPssParameters; 25 import com.google.crypto.tink.signature.RsaSsaPssPublicKey; 26 import com.google.crypto.tink.signature.internal.RsaSsaPssProtoSerialization; 27 import com.google.crypto.tink.subtle.Enums.HashType; 28 import java.math.BigInteger; 29 import java.security.GeneralSecurityException; 30 import java.security.KeyFactory; 31 import java.security.Security; 32 import java.security.interfaces.RSAPublicKey; 33 import java.security.spec.RSAPublicKeySpec; 34 import org.conscrypt.Conscrypt; 35 import org.junit.Assume; 36 import org.junit.Before; 37 import org.junit.Test; 38 import org.junit.runner.RunWith; 39 import org.junit.runners.JUnit4; 40 41 @RunWith(JUnit4.class) 42 public final class RsaSsaPssVerifyJceFipsTest { 43 44 @Before useConscrypt()45 public void useConscrypt() throws Exception { 46 Assume.assumeTrue(TinkFips.useOnlyFips()); 47 Conscrypt.checkAvailability(); 48 Security.addProvider(Conscrypt.newProvider()); 49 } 50 51 private static final BigInteger EXPONENT = new BigInteger("010001", 16); 52 53 // Test vector from Wycheproof's testvectors rsa_pss_2048_sha256_mgf1_32_test.json 54 static final BigInteger MODULUS_2048 = 55 new BigInteger( 56 "00a2b451a07d0aa5f96e455671513550514a8a5b462ebef717094fa1fee82224e637f9746d3f7cafd31878d80325b6ef5a1700f65903b469429e89d6eac8845097b5ab393189db92512ed8a7711a1253facd20f79c15e8247f3d3e42e46e48c98e254a2fe9765313a03eff8f17e1a029397a1fa26a8dce26f490ed81299615d9814c22da610428e09c7d9658594266f5c021d0fceca08d945a12be82de4d1ece6b4c03145b5d3495d4ed5411eb878daf05fd7afc3e09ada0f1126422f590975a1969816f48698bcbba1b4d9cae79d460d8f9f85e7975005d9bc22c4e5ac0f7c1a45d12569a62807d3b9a02e5a530e773066f453d1f5b4c2e9cf7820283f742b9d5", 57 16); 58 59 // Test vector from Wycheproof's testvectors rsa_pss_3072_sha256_mgf1_32_test.json 60 static final BigInteger MODULUS_3072 = 61 new BigInteger( 62 "00c6fe23792566023c265287c5ac6f71541c0994d11d059ee6403986efa21c24b51bd91d8862f9df79a4e328e3e27c83df260b25a9b43420affc44b51e8d7525b6f29c372a405104732007527a62ed82fac73f4892a80e09682a41a58cd347017f3be7d801334f92d9321aafd53b51bffabfc752cfccae0b1ee03bdaff9e428cc1c117f1ac96b4fe23f8c23e6381186a66fd59289339ae55c4bcdadbff84abdaa532240d4e1d28b2d0481dadd3b246557ca8fe18092817730b39e6ee378ffcc85b19ffdc916a9b991a6b66d4a9c7bab5f5e7a3722101142e7a4108c15d573b15289e07e46eaea07b42c2abcba330e99554b4656165bb4c0db2b6393a07eca575c51a93c4e15bdb0f747909447e3efe34c67ca8954b530e56a20a1b6d84d45ed1bcd3aa58ec06f184ee5857aaa819e1cca9a26f4e28d6b977d33916db9896d252d1afa762e287cb0d384cc75bfe53f4e922d02dd0a481c042e2d306b4b3c189371e575b25e0005a164cf69dd0976e4d5be476806ea6be6084e71ab4f5ac5c1b1203", 63 16); 64 65 // Test vector from Wycheproof's testvectors rsa_pss_4096_sha256_mgf1_32_test.json 66 static final BigInteger MODULUS_4096 = 67 new BigInteger( 68 "00956353ecb7561945dc5544e4602466078c93f28507701ffd39e2a9813c8ac8740e6ad61c955d484e513b3dcea527e001a018ee2c207c1806a96763280236cd3c820dff79837c9b709cb4b522d3ddbc9192242259c43be75ea244d37ccfa8a4c75024a2cf7cc76e842ea69cc7ca1227405b070047387a5068e4976e4b8ed5f9aadd7b4db024fbb8d7bd8a040d8f6610c1c6eb1d4b606dfd182235d0360880304d5a750603af0c424b8c8e6dbc12c3697d2d609c97547e774e2e362ea96d1690dc9432112c535258b3db2c4c32ad510d6c07ad0788357883869efb8b629298724847925cf42b34386be700f02903db5852276bee2370941f397bdc3905e30964a0b5e73602703340960c3ed6078263b611f197955fecce4b9a32e43cd1d2e5e87c4ceb65edc8853a7ee31d28e16e5adffb8ac7b760fbfc63d5f174f4d0936461dbb12c964a6b6d6cee752e5fca1ab4a9fd238dd3e8860a1d763d2019f9e7b99ed7666d4e038710f90e0093bc566987d6c0092f571376e705b342d066c54e6e2578927b92c1f0928de44e9a6e1f49b907c6aa4f605ec9c398d55df81c67373b03cc8110162fb417f96fd321048647dfcbb392455115cd912ea83351853e6a185284648842adcbd25e67174a3b93b8a64ce2ce9de0e8577b8b662ce32e2565782665dd38e5bb5fcc4fe12e4320dab7773b545a09c6d39d9dbad459f21f3e624ee6ed", 69 16); 70 71 @Test create_accepts2048ModulusIfFipsModuleIsAvailable()72 public void create_accepts2048ModulusIfFipsModuleIsAvailable() throws Exception { 73 RsaSsaPssProtoSerialization.register(); 74 RsaSsaPssParameters parameters = 75 RsaSsaPssParameters.builder() 76 .setModulusSizeBits(2048) 77 .setPublicExponent(EXPONENT) 78 .setSigHashType(RsaSsaPssParameters.HashType.SHA256) 79 .setMgf1HashType(RsaSsaPssParameters.HashType.SHA256) 80 .setVariant(RsaSsaPssParameters.Variant.NO_PREFIX) 81 .setSaltLengthBytes(64) 82 .build(); 83 RsaSsaPssPublicKey publicKey = 84 RsaSsaPssPublicKey.builder().setParameters(parameters).setModulus(MODULUS_2048).build(); 85 86 if (TinkFipsUtil.fipsModuleAvailable()) { 87 assertThat(RsaSsaPssVerifyJce.create(publicKey)).isNotNull(); 88 } else { 89 assertThrows(GeneralSecurityException.class, () -> RsaSsaPssVerifyJce.create(publicKey)); 90 } 91 } 92 93 @Test constructor_accepts2048ModulusIfFipsModuleIsAvailable()94 public void constructor_accepts2048ModulusIfFipsModuleIsAvailable() throws Exception { 95 KeyFactory keyFactory = EngineFactory.KEY_FACTORY.getInstance("RSA"); 96 RSAPublicKey publicKey = 97 (RSAPublicKey) keyFactory.generatePublic(new RSAPublicKeySpec(MODULUS_2048, EXPONENT)); 98 99 if (TinkFipsUtil.fipsModuleAvailable()) { 100 assertThat(new RsaSsaPssVerifyJce(publicKey, HashType.SHA256, HashType.SHA256, 64)) 101 .isNotNull(); 102 } else { 103 assertThrows( 104 GeneralSecurityException.class, 105 () -> new RsaSsaPssVerifyJce(publicKey, HashType.SHA256, HashType.SHA256, 64)); 106 } 107 } 108 109 @Test create_accepts3072ModulusIfFipsModuleIsAvailable()110 public void create_accepts3072ModulusIfFipsModuleIsAvailable() throws Exception { 111 RsaSsaPssProtoSerialization.register(); 112 RsaSsaPssParameters parameters = 113 RsaSsaPssParameters.builder() 114 .setModulusSizeBits(3072) 115 .setPublicExponent(EXPONENT) 116 .setSigHashType(RsaSsaPssParameters.HashType.SHA256) 117 .setMgf1HashType(RsaSsaPssParameters.HashType.SHA256) 118 .setVariant(RsaSsaPssParameters.Variant.NO_PREFIX) 119 .setSaltLengthBytes(64) 120 .build(); 121 RsaSsaPssPublicKey publicKey = 122 RsaSsaPssPublicKey.builder().setParameters(parameters).setModulus(MODULUS_3072).build(); 123 124 if (TinkFipsUtil.fipsModuleAvailable()) { 125 assertThat(RsaSsaPssVerifyJce.create(publicKey)).isNotNull(); 126 } else { 127 assertThrows(GeneralSecurityException.class, () -> RsaSsaPssVerifyJce.create(publicKey)); 128 } 129 } 130 131 @Test constructor_accepts3072ModulusIfFipsModuleIsAvailable()132 public void constructor_accepts3072ModulusIfFipsModuleIsAvailable() throws Exception { 133 KeyFactory keyFactory = EngineFactory.KEY_FACTORY.getInstance("RSA"); 134 RSAPublicKey publicKey = 135 (RSAPublicKey) keyFactory.generatePublic(new RSAPublicKeySpec(MODULUS_3072, EXPONENT)); 136 137 if (TinkFipsUtil.fipsModuleAvailable()) { 138 assertThat(new RsaSsaPssVerifyJce(publicKey, HashType.SHA256, HashType.SHA256, 64)) 139 .isNotNull(); 140 } else { 141 assertThrows( 142 GeneralSecurityException.class, 143 () -> new RsaSsaPssVerifyJce(publicKey, HashType.SHA256, HashType.SHA256, 64)); 144 } 145 } 146 147 @Test create_refuses4096Modulus()148 public void create_refuses4096Modulus() throws Exception { 149 RsaSsaPssProtoSerialization.register(); 150 RsaSsaPssParameters parameters = 151 RsaSsaPssParameters.builder() 152 .setModulusSizeBits(4096) 153 .setPublicExponent(EXPONENT) 154 .setSigHashType(RsaSsaPssParameters.HashType.SHA256) 155 .setMgf1HashType(RsaSsaPssParameters.HashType.SHA256) 156 .setVariant(RsaSsaPssParameters.Variant.NO_PREFIX) 157 .setSaltLengthBytes(64) 158 .build(); 159 RsaSsaPssPublicKey publicKey = 160 RsaSsaPssPublicKey.builder().setParameters(parameters).setModulus(MODULUS_4096).build(); 161 162 assertThrows(GeneralSecurityException.class, () -> RsaSsaPssVerifyJce.create(publicKey)); 163 } 164 165 @Test constructor_refuses4096Modulus()166 public void constructor_refuses4096Modulus() throws Exception { 167 KeyFactory keyFactory = EngineFactory.KEY_FACTORY.getInstance("RSA"); 168 RSAPublicKey publicKey = 169 (RSAPublicKey) keyFactory.generatePublic(new RSAPublicKeySpec(MODULUS_4096, EXPONENT)); 170 171 assertThrows( 172 GeneralSecurityException.class, 173 () -> new RsaSsaPssVerifyJce(publicKey, HashType.SHA256, HashType.SHA256, 64)); 174 } 175 } 176