• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2022 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.aead;
18 
19 import com.google.errorprone.annotations.CanIgnoreReturnValue;
20 import com.google.errorprone.annotations.Immutable;
21 import java.security.GeneralSecurityException;
22 import java.security.InvalidAlgorithmParameterException;
23 import java.util.Objects;
24 import javax.annotation.Nullable;
25 
26 /** Describes the parameters of an {@link AesEaxKey}. */
27 public final class AesEaxParameters extends AeadParameters {
28   /**
29    * Describes how the prefix is computed. For AEAD there are three main possibilities: NO_PREFIX
30    * (empty prefix), TINK (prefix the ciphertext with 0x01 followed by a 4-byte key id in big endian
31    * format) or CRUNCHY (prefix the ciphertext with 0x00 followed by a 4-byte key id in big endian
32    * format)
33    */
34   @Immutable
35   public static final class Variant {
36     public static final Variant TINK = new Variant("TINK");
37     public static final Variant CRUNCHY = new Variant("CRUNCHY");
38     public static final Variant NO_PREFIX = new Variant("NO_PREFIX");
39 
40     private final String name;
41 
Variant(String name)42     private Variant(String name) {
43       this.name = name;
44     }
45 
46     @Override
toString()47     public String toString() {
48       return name;
49     }
50   }
51 
52   /** Builds a new AesEaxParameters instance. */
53   public static final class Builder {
54     @Nullable private Integer keySizeBytes = null;
55     @Nullable private Integer ivSizeBytes = null;
56     @Nullable private Integer tagSizeBytes = null;
57     private Variant variant = Variant.NO_PREFIX;
58 
Builder()59     private Builder() {}
60 
61     /**
62      * Accepts key sizes of 16, 24 or 32 bytes. However, some implementation may not support the
63      * full set of parameters at the moment and may restrict the key size to 16 or 32-byte values.
64      */
65     @CanIgnoreReturnValue
setKeySizeBytes(int keySizeBytes)66     public Builder setKeySizeBytes(int keySizeBytes) throws GeneralSecurityException {
67       if (keySizeBytes != 16 && keySizeBytes != 24 && keySizeBytes != 32) {
68         throw new InvalidAlgorithmParameterException(
69             String.format(
70                 "Invalid key size %d; only 16-byte, 24-byte and 32-byte AES keys are supported",
71                 keySizeBytes));
72       }
73       this.keySizeBytes = keySizeBytes;
74       return this;
75     }
76     /** IV size must be 12 or 16 bytes. */
77     @CanIgnoreReturnValue
setIvSizeBytes(int ivSizeBytes)78     public Builder setIvSizeBytes(int ivSizeBytes) throws GeneralSecurityException {
79       if (ivSizeBytes != 12 && ivSizeBytes != 16) {
80         throw new GeneralSecurityException(
81             String.format(
82                 "Invalid IV size in bytes %d; acceptable values have 12 or 16 bytes", ivSizeBytes));
83       }
84       this.ivSizeBytes = ivSizeBytes;
85       return this;
86     }
87     /**
88      * The tag size accepts values between 0 and 16 bytes. However, some implementation may not
89      * support the full set of parameters at the moment and may restrict the tag size to a fixed
90      * value (i.e. 16 bytes).
91      */
92     @CanIgnoreReturnValue
setTagSizeBytes(int tagSizeBytes)93     public Builder setTagSizeBytes(int tagSizeBytes) throws GeneralSecurityException {
94       if (tagSizeBytes < 0 || tagSizeBytes > 16) {
95         throw new GeneralSecurityException(
96             String.format(
97                 "Invalid tag size in bytes %d; value must be at most 16 bytes", tagSizeBytes));
98       }
99       this.tagSizeBytes = tagSizeBytes;
100       return this;
101     }
102 
103     @CanIgnoreReturnValue
setVariant(Variant variant)104     public Builder setVariant(Variant variant) {
105       this.variant = variant;
106       return this;
107     }
108 
build()109     public AesEaxParameters build() throws GeneralSecurityException {
110       if (keySizeBytes == null) {
111         throw new GeneralSecurityException("Key size is not set");
112       }
113       if (ivSizeBytes == null) {
114         throw new GeneralSecurityException("IV size is not set");
115       }
116       if (variant == null) {
117         throw new GeneralSecurityException("Variant is not set");
118       }
119 
120       if (tagSizeBytes == null) {
121         throw new GeneralSecurityException("Tag size is not set");
122       }
123 
124       return new AesEaxParameters(keySizeBytes, ivSizeBytes, tagSizeBytes, variant);
125     }
126   }
127 
128   private final int keySizeBytes;
129   private final int ivSizeBytes;
130   private final int tagSizeBytes;
131   private final Variant variant;
132 
AesEaxParameters(int keySizeBytes, int ivSizeBytes, int tagSizeBytes, Variant variant)133   private AesEaxParameters(int keySizeBytes, int ivSizeBytes, int tagSizeBytes, Variant variant) {
134     this.keySizeBytes = keySizeBytes;
135     this.ivSizeBytes = ivSizeBytes;
136     this.tagSizeBytes = tagSizeBytes;
137     this.variant = variant;
138   }
139 
builder()140   public static Builder builder() {
141     return new Builder();
142   }
143 
getKeySizeBytes()144   public int getKeySizeBytes() {
145     return keySizeBytes;
146   }
147 
getIvSizeBytes()148   public int getIvSizeBytes() {
149     return ivSizeBytes;
150   }
151 
getTagSizeBytes()152   public int getTagSizeBytes() {
153     return tagSizeBytes;
154   }
155 
156   /** Returns a variant object. */
getVariant()157   public Variant getVariant() {
158     return variant;
159   }
160 
161   @Override
equals(Object o)162   public boolean equals(Object o) {
163     if (!(o instanceof AesEaxParameters)) {
164       return false;
165     }
166     AesEaxParameters that = (AesEaxParameters) o;
167     return that.getKeySizeBytes() == getKeySizeBytes()
168         && that.getIvSizeBytes() == getIvSizeBytes()
169         && that.getTagSizeBytes() == getTagSizeBytes()
170         && that.getVariant() == getVariant();
171   }
172 
173   @Override
hashCode()174   public int hashCode() {
175     return Objects.hash(AesEaxParameters.class, keySizeBytes, ivSizeBytes, tagSizeBytes, variant);
176   }
177 
178   @Override
hasIdRequirement()179   public boolean hasIdRequirement() {
180     return variant != Variant.NO_PREFIX;
181   }
182 
183   @Override
toString()184   public String toString() {
185     return "AesEax Parameters (variant: "
186         + variant
187         + ", "
188         + ivSizeBytes
189         + "-byte IV, "
190         + tagSizeBytes
191         + "-byte tag, and "
192         + keySizeBytes
193         + "-byte key)";
194   }
195 }
196