blob: 0f198127cd3c2ac6ce950d911fac9474a5ea088e [file] [log] [blame]
Alex Klyubin0ee93762015-04-10 10:20:48 -07001package android.security;
2
3import android.annotation.IntDef;
4
5import java.lang.annotation.Retention;
6import java.lang.annotation.RetentionPolicy;
7import java.security.spec.AlgorithmParameterSpec;
8
9import javax.crypto.Cipher;
10import javax.crypto.Mac;
11
12/**
13 * {@link AlgorithmParameterSpec} for ECIES (Integrated Encryption Scheme using Elliptic Curve
14 * cryptography) based on {@code ISO/IEC 18033-2}.
15 *
16 * <p>ECIES is a hybrid authenticated encryption scheme. Encryption is performed using an Elliptic
17 * Curve (EC) public key. The resulting ciphertext can be decrypted only using the corresponding EC
18 * private key. The scheme is called hybrid because the EC key is only used to securely encapsulate
19 * symmetric key material. Encryption of plaintext and authentication of the corresponding
20 * ciphertext is performed using symmetric cryptography.
21 *
22 * <p>Encryption using ECIES consists of two stages:
23 * <ol>
24 * <li>Key Encapsulation Mechanism (KEM) randomly generates symmetric key material and securely
25 * encapsulates it in the output so that it can be extracted by the KEM when decrypting.
26 * Encapsulated key material is represented in the output as an EC point.</li>
27 * <li>The above symmetric key material is used by Data Encapsulation Mechanism (DEM) to encrypt the
28 * provided plaintext and authenticate the ciphertext. The resulting authenticated ciphertext is
29 * then output. When decrypting, the DEM first authenticates the ciphertext and, only if it
30 * authenticates, decrypts the ciphertext and outputs the plaintext.</li>
31 * </ol>
32 *
33 * <p>Details of KEM:
34 * <ul>
35 * <li>Only curves with cofactor of {@code 1} are supported.</li>
36 * <li>{@code CheckMode}, {@code OldCofactorMode}, {@code CofactorMode}, and {@code SingleHashMode}
37 * are {@code 0}.
38 * <li>Point format is specified by {@link #getKemPointFormat()}.</li>
39 * <li>KDF algorithm is specified by {@link #getKemKdfAlgorithm()}.</li>
40 * </ul>
41 *
42 * <p>Details of DEM:
43 * <ul>
44 * <li>Only DEM1-like mechanism is supported, with its symmetric cipher (SC) specified by
45 * {@link #getDemCipherTransformation()} (e.g., {@code AES/CBC/NoPadding} for standard DEM1) and
46 * MAC algorithm specified by {@link #getDemMacAlgorithm()} (e.g., {@code HmacSHA1} for standard
47 * DEM1).</li>
48 * </ul>
49 *
50 * @hide
51 */
52public class EcIesParameterSpec implements AlgorithmParameterSpec {
53
54 @Retention(RetentionPolicy.SOURCE)
55 @IntDef(value = {PointFormat.UNCOMPRESSED, PointFormat.COMPRESSED})
56 public @interface PointFormatEnum {}
57
58 /**
59 * Wire format of the EC point.
60 */
61 public static abstract class PointFormat {
62
63 private PointFormat() {}
64
65 /** Unspecified point format. */
66 public static final int UNSPECIFIED = -1;
67
68 /**
69 * Uncompressed point format: both coordinates are stored separately.
70 *
71 * <p>The wire format is byte {@code 0x04} followed by binary representation of the
72 * {@code x} coordinate followed by binary representation of the {@code y} coordinate. See
73 * {@code ISO 18033-2} section {@code 5.4.3}.
74 */
75 public static final int UNCOMPRESSED = 0;
76
77 /**
78 * Compressed point format: only one coordinate is stored.
79 *
80 * <p>The wire format is byte {@code 0x02} or {@code 0x03} (depending on the value of the
81 * stored coordinate) followed by the binary representation of the {@code x} coordinate.
82 * See {@code ISO 18033-2} section {@code 5.4.3}.
83 */
84 public static final int COMPRESSED = 1;
85 }
86
87 /**
88 * Default parameter spec: NIST P-256 curve (aka secp256r1 aka prime256v1), compressed point
89 * format, {@code HKDFwithSHA256}, DEM uses 128-bit AES GCM.
90 */
91 public static final EcIesParameterSpec DEFAULT = new EcIesParameterSpec(
92 "P-256",
93 PointFormat.COMPRESSED,
94 "HKDFwithSHA256",
95 "AES/GCM/NoPadding",
96 128,
97 null,
98 0);
99
100 private final String mKemCurveName;
101 private final @PointFormatEnum int mKemPointFormat;
102 private final String mKemKdfAlgorithm;
103 private final String mDemCipherTransformation;
104 private final int mDemCipherKeySize;
105 private final String mDemMacAlgorithm;
106 private final int mDemMacKeySize;
107
108 private EcIesParameterSpec(
109 String kemCurveName,
110 @PointFormatEnum int kemPointFormat,
111 String kemKdfAlgorithm,
112 String demCipherTransformation,
113 int demCipherKeySize,
114 String demMacAlgorithm,
115 int demMacKeySize) {
116 mKemCurveName = kemCurveName;
117 mKemPointFormat = kemPointFormat;
118 mKemKdfAlgorithm = kemKdfAlgorithm;
119 mDemCipherTransformation = demCipherTransformation;
120 mDemCipherKeySize = demCipherKeySize;
121 mDemMacAlgorithm = demMacAlgorithm;
122 mDemMacKeySize = demMacKeySize;
123 }
124
125 /**
126 * Returns KEM EC curve name (e.g., {@code secp256r1}) or {@code null} if not specified.
127 */
128 public String getKemCurveName() {
129 return mKemCurveName;
130 }
131
132 /**
133 * Returns KEM EC point wire format or {@link PointFormat#UNSPECIFIED} if not specified.
134 */
135 public @PointFormatEnum int getKemPointFormat() {
136 return mKemPointFormat;
137 }
138
139 /**
140 * Returns KEM KDF algorithm (e.g., {@code HKDFwithSHA256} or {@code KDF1withSHA1}) or
141 * {@code null} if not specified.
142 */
143 public String getKemKdfAlgorithm() {
144 return mKemKdfAlgorithm;
145 }
146
147 /**
148 * Returns DEM {@link Cipher} transformation (e.g., {@code AES/GCM/NoPadding} or
149 * {@code AES/CBC/PKCS7Padding}) or {@code null} if not specified.
150 *
151 * @see Cipher#getInstance(String)
152 * @see #getDemCipherKeySize()
153 */
154 public String getDemCipherTransformation() {
155 return mDemCipherTransformation;
156 }
157
158 /**
159 * Returns DEM {@link Cipher} key size in bits.
160 *
161 * @see #getDemCipherTransformation()
162 */
163 public int getDemCipherKeySize() {
164 return mDemCipherKeySize;
165 }
166
167 /**
168 * Returns DEM {@link Mac} algorithm (e.g., {@code HmacSHA256} or {@code HmacSHA1}) or
169 * {@code null} if not specified.
170 *
171 * @see Mac#getInstance(String)
172 * @see #getDemMacKeySize()
173 */
174 public String getDemMacAlgorithm() {
175 return mDemMacAlgorithm;
176 }
177
178 /**
179 * Returns DEM {@link Mac} key size in bits.
180 *
181 * @see #getDemCipherTransformation()
182 */
183 public int getDemMacKeySize() {
184 return mDemMacKeySize;
185 }
186
187 /**
188 * Builder of {@link EcIesParameterSpec}.
189 */
190 public static class Builder {
191 private String mKemCurveName;
192 private @PointFormatEnum int mKemPointFormat = PointFormat.UNSPECIFIED;
193 private String mKemKdfAlgorithm;
194 private String mDemCipherTransformation;
195 private int mDemCipherKeySize = 128;
196 private String mDemMacAlgorithm;
197 private int mDemMacKeySize = -1;
198
199 /**
200 * Sets KEM EC curve name. For example, {@code P-256} or {@code secp256r1}.
201 *
202 * <p>NOTE: Only curves with cofactor of {@code 1} are supported.
203 */
204 public Builder setKemCurveName(String name) {
205 mKemCurveName = name;
206 return this;
207 }
208
209 /**
210 * Sets KEM EC point wire format.
211 */
212 public Builder setKemPointFormat(@PointFormatEnum int pointFormat) {
213 mKemPointFormat = pointFormat;
214 return this;
215 }
216
217 /**
218 * Sets KEM KDF algorithm. For example, {@code HKDFwithSHA256}, {@code KDF2withSHA256}, or
219 * {@code KDF1withSHA1}.
220 */
221 public Builder setKemKdfAlgorithm(String algorithm) {
222 mKemKdfAlgorithm = algorithm;
223 return this;
224 }
225
226 /**
227 * Sets DEM {@link Cipher} transformation. For example, {@code AES/GCM/NoPadding},
228 * {@code AES/CBC/PKCS7Padding} or {@code AES/CTR/NoPadding}.
229 *
230 * @see Cipher#getInstance(String)
231 */
232 public Builder setDemCipherTransformation(String transformation) {
233 mDemCipherTransformation = transformation;
234 return this;
235 }
236
237 /**
238 * Returns DEM {@link Cipher} key size in bits.
239 *
240 * <p>The default value is {@code 128} bits.
241 *
242 * @see #setDemCipherTransformation(String)
243 */
244 public Builder setDemCipherKeySize(int sizeBits) {
245 mDemCipherKeySize = sizeBits;
246 return this;
247 }
248
249 /**
250 * Sets DEM {@link Mac} algorithm. For example, {@code HmacSHA256} or {@code HmacSHA1}.
251 *
252 * @see Mac#getInstance(String)
253 */
254 public Builder setDemMacAlgorithm(String algorithm) {
255 mDemMacAlgorithm = algorithm;
256 return this;
257 }
258
259 /**
260 * Sets DEM {@link Mac} key size in bits.
261 *
262 * <p>By default, {@code Mac} key size is the same as the {@code Cipher} key size.
263 *
264 * @see #setDemCipherKeySize(int)
265 */
266 public Builder setDemMacKeySize(int sizeBits) {
267 mDemMacKeySize = sizeBits;
268 return this;
269 }
270
271 /**
272 * Returns a new {@link EcIesParameterSpec} based on the current state of this builder.
273 */
274 public EcIesParameterSpec build() {
275 int demMacKeySize = (mDemMacKeySize != -1) ? mDemMacKeySize : mDemCipherKeySize;
276 return new EcIesParameterSpec(
277 mKemCurveName,
278 mKemPointFormat,
279 mKemKdfAlgorithm,
280 mDemCipherTransformation,
281 mDemCipherKeySize,
282 mDemMacAlgorithm,
283 demMacKeySize
284 );
285 }
286 }
287}