blob: 3372da92140d75ee37dd4280ace45a95153eae3d [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 /**
Alex Klyubin33454dd2015-04-13 10:20:24 -070088 * Default parameter spec: compressed point format, {@code HKDFwithSHA256}, DEM uses 128-bit AES
89 * GCM.
Alex Klyubin0ee93762015-04-10 10:20:48 -070090 */
91 public static final EcIesParameterSpec DEFAULT = new EcIesParameterSpec(
Alex Klyubin0ee93762015-04-10 10:20:48 -070092 PointFormat.COMPRESSED,
93 "HKDFwithSHA256",
94 "AES/GCM/NoPadding",
95 128,
96 null,
97 0);
98
Alex Klyubin0ee93762015-04-10 10:20:48 -070099 private final @PointFormatEnum int mKemPointFormat;
100 private final String mKemKdfAlgorithm;
101 private final String mDemCipherTransformation;
102 private final int mDemCipherKeySize;
103 private final String mDemMacAlgorithm;
104 private final int mDemMacKeySize;
105
106 private EcIesParameterSpec(
Alex Klyubin0ee93762015-04-10 10:20:48 -0700107 @PointFormatEnum int kemPointFormat,
108 String kemKdfAlgorithm,
109 String demCipherTransformation,
110 int demCipherKeySize,
111 String demMacAlgorithm,
112 int demMacKeySize) {
Alex Klyubin0ee93762015-04-10 10:20:48 -0700113 mKemPointFormat = kemPointFormat;
114 mKemKdfAlgorithm = kemKdfAlgorithm;
115 mDemCipherTransformation = demCipherTransformation;
116 mDemCipherKeySize = demCipherKeySize;
117 mDemMacAlgorithm = demMacAlgorithm;
118 mDemMacKeySize = demMacKeySize;
119 }
120
121 /**
Alex Klyubin0ee93762015-04-10 10:20:48 -0700122 * Returns KEM EC point wire format or {@link PointFormat#UNSPECIFIED} if not specified.
123 */
124 public @PointFormatEnum int getKemPointFormat() {
125 return mKemPointFormat;
126 }
127
128 /**
129 * Returns KEM KDF algorithm (e.g., {@code HKDFwithSHA256} or {@code KDF1withSHA1}) or
130 * {@code null} if not specified.
131 */
132 public String getKemKdfAlgorithm() {
133 return mKemKdfAlgorithm;
134 }
135
136 /**
137 * Returns DEM {@link Cipher} transformation (e.g., {@code AES/GCM/NoPadding} or
138 * {@code AES/CBC/PKCS7Padding}) or {@code null} if not specified.
139 *
140 * @see Cipher#getInstance(String)
141 * @see #getDemCipherKeySize()
142 */
143 public String getDemCipherTransformation() {
144 return mDemCipherTransformation;
145 }
146
147 /**
148 * Returns DEM {@link Cipher} key size in bits.
149 *
150 * @see #getDemCipherTransformation()
151 */
152 public int getDemCipherKeySize() {
153 return mDemCipherKeySize;
154 }
155
156 /**
157 * Returns DEM {@link Mac} algorithm (e.g., {@code HmacSHA256} or {@code HmacSHA1}) or
158 * {@code null} if not specified.
159 *
160 * @see Mac#getInstance(String)
161 * @see #getDemMacKeySize()
162 */
163 public String getDemMacAlgorithm() {
164 return mDemMacAlgorithm;
165 }
166
167 /**
168 * Returns DEM {@link Mac} key size in bits.
169 *
170 * @see #getDemCipherTransformation()
171 */
172 public int getDemMacKeySize() {
173 return mDemMacKeySize;
174 }
175
176 /**
177 * Builder of {@link EcIesParameterSpec}.
178 */
179 public static class Builder {
Alex Klyubin0ee93762015-04-10 10:20:48 -0700180 private @PointFormatEnum int mKemPointFormat = PointFormat.UNSPECIFIED;
181 private String mKemKdfAlgorithm;
182 private String mDemCipherTransformation;
183 private int mDemCipherKeySize = 128;
184 private String mDemMacAlgorithm;
185 private int mDemMacKeySize = -1;
186
187 /**
Alex Klyubin0ee93762015-04-10 10:20:48 -0700188 * Sets KEM EC point wire format.
189 */
190 public Builder setKemPointFormat(@PointFormatEnum int pointFormat) {
191 mKemPointFormat = pointFormat;
192 return this;
193 }
194
195 /**
196 * Sets KEM KDF algorithm. For example, {@code HKDFwithSHA256}, {@code KDF2withSHA256}, or
197 * {@code KDF1withSHA1}.
198 */
199 public Builder setKemKdfAlgorithm(String algorithm) {
200 mKemKdfAlgorithm = algorithm;
201 return this;
202 }
203
204 /**
205 * Sets DEM {@link Cipher} transformation. For example, {@code AES/GCM/NoPadding},
206 * {@code AES/CBC/PKCS7Padding} or {@code AES/CTR/NoPadding}.
207 *
208 * @see Cipher#getInstance(String)
209 */
210 public Builder setDemCipherTransformation(String transformation) {
211 mDemCipherTransformation = transformation;
212 return this;
213 }
214
215 /**
216 * Returns DEM {@link Cipher} key size in bits.
217 *
218 * <p>The default value is {@code 128} bits.
219 *
220 * @see #setDemCipherTransformation(String)
221 */
222 public Builder setDemCipherKeySize(int sizeBits) {
223 mDemCipherKeySize = sizeBits;
224 return this;
225 }
226
227 /**
228 * Sets DEM {@link Mac} algorithm. For example, {@code HmacSHA256} or {@code HmacSHA1}.
229 *
230 * @see Mac#getInstance(String)
231 */
232 public Builder setDemMacAlgorithm(String algorithm) {
233 mDemMacAlgorithm = algorithm;
234 return this;
235 }
236
237 /**
238 * Sets DEM {@link Mac} key size in bits.
239 *
240 * <p>By default, {@code Mac} key size is the same as the {@code Cipher} key size.
241 *
242 * @see #setDemCipherKeySize(int)
243 */
244 public Builder setDemMacKeySize(int sizeBits) {
245 mDemMacKeySize = sizeBits;
246 return this;
247 }
248
249 /**
250 * Returns a new {@link EcIesParameterSpec} based on the current state of this builder.
251 */
252 public EcIesParameterSpec build() {
253 int demMacKeySize = (mDemMacKeySize != -1) ? mDemMacKeySize : mDemCipherKeySize;
254 return new EcIesParameterSpec(
Alex Klyubin0ee93762015-04-10 10:20:48 -0700255 mKemPointFormat,
256 mKemKdfAlgorithm,
257 mDemCipherTransformation,
258 mDemCipherKeySize,
259 mDemMacAlgorithm,
260 demMacKeySize
261 );
262 }
263 }
264}