1 // Copyright 2021 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 package com.google.crypto.tink.config.internal; 17 18 import java.lang.reflect.Method; 19 import java.util.concurrent.atomic.AtomicBoolean; 20 import java.util.logging.Logger; 21 22 /** 23 * Static methods for checking if Tink was built in FIPS mode and to check for algorithm 24 * compatibility. 25 */ 26 public final class TinkFipsUtil { 27 private static final Logger logger = Logger.getLogger(TinkFipsUtil.class.getName()); 28 29 // Is true if the FIPS restrictions have been enabled at runtime. 30 private static final AtomicBoolean isRestrictedToFips = new AtomicBoolean(false); 31 32 /** The status of FIPS compatibility of an algorithm. */ 33 public enum AlgorithmFipsCompatibility { 34 /** The algorithm is not FIPS compatible */ 35 ALGORITHM_NOT_FIPS { 36 @Override isCompatible()37 public boolean isCompatible() { 38 // Non-FIPS algorithms are only allowed if Tink is not built in FIPS-only mode. 39 return !useOnlyFips(); 40 } 41 }, 42 /** The algorithm has a FIPS validated implementation if BoringCrypto is available. */ 43 ALGORITHM_REQUIRES_BORINGCRYPTO { 44 @Override isCompatible()45 public boolean isCompatible() { 46 // If Tink is not in FIPS-only mode, then no restrictions are necessary. In FIPS-only mode 47 // this returns True if BoringCrypto is available. 48 return !useOnlyFips() || fipsModuleAvailable(); 49 } 50 }; 51 isCompatible()52 public abstract boolean isCompatible(); 53 } 54 setFipsRestricted()55 public static void setFipsRestricted() { 56 isRestrictedToFips.set(true); 57 } 58 59 /** 60 * This method is only exposed for tests and should not be used to disable the FIPS restrictions. 61 */ unsetFipsRestricted()62 public static void unsetFipsRestricted() { 63 isRestrictedToFips.set(false); 64 } 65 useOnlyFips()66 public static boolean useOnlyFips() { 67 return TinkFipsStatus.useOnlyFips() || isRestrictedToFips.get(); 68 } 69 fipsModuleAvailable()70 public static boolean fipsModuleAvailable() { 71 return checkConscryptIsAvailableAndUsesFipsBoringSsl(); 72 } 73 checkConscryptIsAvailableAndUsesFipsBoringSsl()74 static Boolean checkConscryptIsAvailableAndUsesFipsBoringSsl() { 75 try { 76 Class<?> cls = Class.forName("org.conscrypt.Conscrypt"); 77 Method isBoringSslFIPSBuild = cls.getMethod("isBoringSslFIPSBuild"); 78 return (Boolean) isBoringSslFIPSBuild.invoke(null); 79 } catch (Exception e) { 80 // For older versions of Conscrypt we get a NoSuchMethodException. But no matter what goes 81 // wrong, we cannot guarantee that Conscrypt uses BoringCrypto, so we will return false. 82 logger.info("Conscrypt is not available or does not support checking for FIPS build."); 83 return false; 84 } 85 } 86 TinkFipsUtil()87 private TinkFipsUtil() {} 88 89 } 90