1 // Copyright 2023 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.keyderivation; 18 19 import com.google.crypto.tink.AccessesPartialKey; 20 import com.google.crypto.tink.Key; 21 import com.google.crypto.tink.prf.PrfKey; 22 import com.google.errorprone.annotations.RestrictedApi; 23 import java.security.GeneralSecurityException; 24 import java.util.Objects; 25 import javax.annotation.Nullable; 26 27 /** 28 * Represents a Derivation key which is based on a PRF. 29 * 30 * <p>An object of this class represents the map which 1) uses the given PRF (as specified by {@link 31 * #getPrfKey}) to get sufficient key material from the salt, then 2) creates a key for the 32 * parameters as specified in {@code getParameters().getDerivedKeyParameters()}. 33 */ 34 public final class PrfBasedKeyDerivationKey extends KeyDerivationKey { 35 @RestrictedApi( 36 explanation = "Accessing parts of keys can produce unexpected incompatibilities, annotate the function with @AccessesPartialKey", 37 link = "https://developers.google.com/tink/design/access_control#accessing_partial_keys", 38 allowedOnPath = ".*Test\\.java", 39 allowlistAnnotations = {AccessesPartialKey.class}) create( PrfBasedKeyDerivationParameters parameters, PrfKey prfKey, @Nullable Integer idRequirement)40 public static PrfBasedKeyDerivationKey create( 41 PrfBasedKeyDerivationParameters parameters, PrfKey prfKey, @Nullable Integer idRequirement) 42 throws GeneralSecurityException { 43 if (!parameters.getPrfParameters().equals(prfKey.getParameters())) { 44 throw new GeneralSecurityException( 45 "PrfParameters of passed in PrfBasedKeyDerivationParameters and passed in prfKey" 46 + " parameters object must match. DerivationParameters gave: " 47 + parameters.getPrfParameters() 48 + ", key gives: " 49 + prfKey.getParameters()); 50 } 51 if (parameters.getDerivedKeyParameters().hasIdRequirement()) { 52 if (idRequirement == null) { 53 throw new GeneralSecurityException( 54 "Derived key has an ID requirement, but no idRequirement was passed in on creation of" 55 + " this key"); 56 } 57 } 58 if (!parameters.getDerivedKeyParameters().hasIdRequirement()) { 59 if (idRequirement != null) { 60 throw new GeneralSecurityException( 61 "Derived key has no ID requirement, but idRequirement was passed in on creation of" 62 + " this key"); 63 } 64 } 65 return new PrfBasedKeyDerivationKey(parameters, prfKey, idRequirement); 66 } 67 68 private final PrfBasedKeyDerivationParameters parameters; 69 private final PrfKey prfKey; 70 private final Integer idRequirementOrNull; 71 PrfBasedKeyDerivationKey( PrfBasedKeyDerivationParameters parameters, PrfKey prfKey, @Nullable Integer idRequirement)72 private PrfBasedKeyDerivationKey( 73 PrfBasedKeyDerivationParameters parameters, PrfKey prfKey, @Nullable Integer idRequirement) { 74 this.parameters = parameters; 75 this.prfKey = prfKey; 76 this.idRequirementOrNull = idRequirement; 77 } 78 79 @RestrictedApi( 80 explanation = "Accessing parts of keys can produce unexpected incompatibilities, annotate the function with @AccessesPartialKey", 81 link = "https://developers.google.com/tink/design/access_control#accessing_partial_keys", 82 allowedOnPath = ".*Test\\.java", 83 allowlistAnnotations = {AccessesPartialKey.class}) getPrfKey()84 public PrfKey getPrfKey() { 85 return prfKey; 86 } 87 88 @Override getParameters()89 public PrfBasedKeyDerivationParameters getParameters() { 90 return parameters; 91 } 92 93 @Override 94 @Nullable getIdRequirementOrNull()95 public Integer getIdRequirementOrNull() { 96 return idRequirementOrNull; 97 } 98 99 @Override equalsKey(Key other)100 public boolean equalsKey(Key other) { 101 if (!(other instanceof PrfBasedKeyDerivationKey)) { 102 return false; 103 } 104 105 PrfBasedKeyDerivationKey otherKey = (PrfBasedKeyDerivationKey) other; 106 return otherKey.getParameters().equals(getParameters()) 107 && otherKey.prfKey.equalsKey(prfKey) 108 && Objects.equals(otherKey.idRequirementOrNull, idRequirementOrNull); 109 } 110 } 111