blob: a3e5aec7bb8666fd57b3be2af91d08da9b77b98a [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>
Alex Klyubin0ee93762015-04-10 10:20:48 -070049 */
50public class EcIesParameterSpec implements AlgorithmParameterSpec {
51
52 @Retention(RetentionPolicy.SOURCE)
53 @IntDef(value = {PointFormat.UNCOMPRESSED, PointFormat.COMPRESSED})
54 public @interface PointFormatEnum {}
55
56 /**
57 * Wire format of the EC point.
58 */
59 public static abstract class PointFormat {
60
61 private PointFormat() {}
62
63 /** Unspecified point format. */
64 public static final int UNSPECIFIED = -1;
65
66 /**
67 * Uncompressed point format: both coordinates are stored separately.
68 *
69 * <p>The wire format is byte {@code 0x04} followed by binary representation of the
70 * {@code x} coordinate followed by binary representation of the {@code y} coordinate. See
71 * {@code ISO 18033-2} section {@code 5.4.3}.
72 */
73 public static final int UNCOMPRESSED = 0;
74
75 /**
76 * Compressed point format: only one coordinate is stored.
77 *
78 * <p>The wire format is byte {@code 0x02} or {@code 0x03} (depending on the value of the
79 * stored coordinate) followed by the binary representation of the {@code x} coordinate.
80 * See {@code ISO 18033-2} section {@code 5.4.3}.
81 */
82 public static final int COMPRESSED = 1;
83 }
84
85 /**
Alex Klyubin33454dd2015-04-13 10:20:24 -070086 * Default parameter spec: compressed point format, {@code HKDFwithSHA256}, DEM uses 128-bit AES
87 * GCM.
Alex Klyubin0ee93762015-04-10 10:20:48 -070088 */
89 public static final EcIesParameterSpec DEFAULT = new EcIesParameterSpec(
Alex Klyubin0ee93762015-04-10 10:20:48 -070090 PointFormat.COMPRESSED,
91 "HKDFwithSHA256",
92 "AES/GCM/NoPadding",
93 128,
94 null,
95 0);
96
Alex Klyubin0ee93762015-04-10 10:20:48 -070097 private final @PointFormatEnum int mKemPointFormat;
98 private final String mKemKdfAlgorithm;
99 private final String mDemCipherTransformation;
100 private final int mDemCipherKeySize;
101 private final String mDemMacAlgorithm;
102 private final int mDemMacKeySize;
103
104 private EcIesParameterSpec(
Alex Klyubin0ee93762015-04-10 10:20:48 -0700105 @PointFormatEnum int kemPointFormat,
106 String kemKdfAlgorithm,
107 String demCipherTransformation,
108 int demCipherKeySize,
109 String demMacAlgorithm,
110 int demMacKeySize) {
Alex Klyubin0ee93762015-04-10 10:20:48 -0700111 mKemPointFormat = kemPointFormat;
112 mKemKdfAlgorithm = kemKdfAlgorithm;
113 mDemCipherTransformation = demCipherTransformation;
114 mDemCipherKeySize = demCipherKeySize;
115 mDemMacAlgorithm = demMacAlgorithm;
116 mDemMacKeySize = demMacKeySize;
117 }
118
119 /**
Alex Klyubin0ee93762015-04-10 10:20:48 -0700120 * Returns KEM EC point wire format or {@link PointFormat#UNSPECIFIED} if not specified.
121 */
122 public @PointFormatEnum int getKemPointFormat() {
123 return mKemPointFormat;
124 }
125
126 /**
127 * Returns KEM KDF algorithm (e.g., {@code HKDFwithSHA256} or {@code KDF1withSHA1}) or
128 * {@code null} if not specified.
129 */
130 public String getKemKdfAlgorithm() {
131 return mKemKdfAlgorithm;
132 }
133
134 /**
135 * Returns DEM {@link Cipher} transformation (e.g., {@code AES/GCM/NoPadding} or
136 * {@code AES/CBC/PKCS7Padding}) or {@code null} if not specified.
137 *
138 * @see Cipher#getInstance(String)
139 * @see #getDemCipherKeySize()
140 */
141 public String getDemCipherTransformation() {
142 return mDemCipherTransformation;
143 }
144
145 /**
146 * Returns DEM {@link Cipher} key size in bits.
147 *
148 * @see #getDemCipherTransformation()
149 */
150 public int getDemCipherKeySize() {
151 return mDemCipherKeySize;
152 }
153
154 /**
155 * Returns DEM {@link Mac} algorithm (e.g., {@code HmacSHA256} or {@code HmacSHA1}) or
156 * {@code null} if not specified.
157 *
158 * @see Mac#getInstance(String)
159 * @see #getDemMacKeySize()
160 */
161 public String getDemMacAlgorithm() {
162 return mDemMacAlgorithm;
163 }
164
165 /**
166 * Returns DEM {@link Mac} key size in bits.
167 *
168 * @see #getDemCipherTransformation()
169 */
170 public int getDemMacKeySize() {
171 return mDemMacKeySize;
172 }
173
174 /**
175 * Builder of {@link EcIesParameterSpec}.
176 */
177 public static class Builder {
Alex Klyubin0ee93762015-04-10 10:20:48 -0700178 private @PointFormatEnum int mKemPointFormat = PointFormat.UNSPECIFIED;
179 private String mKemKdfAlgorithm;
180 private String mDemCipherTransformation;
181 private int mDemCipherKeySize = 128;
182 private String mDemMacAlgorithm;
183 private int mDemMacKeySize = -1;
184
185 /**
Alex Klyubin0ee93762015-04-10 10:20:48 -0700186 * Sets KEM EC point wire format.
187 */
188 public Builder setKemPointFormat(@PointFormatEnum int pointFormat) {
189 mKemPointFormat = pointFormat;
190 return this;
191 }
192
193 /**
194 * Sets KEM KDF algorithm. For example, {@code HKDFwithSHA256}, {@code KDF2withSHA256}, or
195 * {@code KDF1withSHA1}.
196 */
197 public Builder setKemKdfAlgorithm(String algorithm) {
198 mKemKdfAlgorithm = algorithm;
199 return this;
200 }
201
202 /**
203 * Sets DEM {@link Cipher} transformation. For example, {@code AES/GCM/NoPadding},
204 * {@code AES/CBC/PKCS7Padding} or {@code AES/CTR/NoPadding}.
205 *
206 * @see Cipher#getInstance(String)
207 */
208 public Builder setDemCipherTransformation(String transformation) {
209 mDemCipherTransformation = transformation;
210 return this;
211 }
212
213 /**
214 * Returns DEM {@link Cipher} key size in bits.
215 *
216 * <p>The default value is {@code 128} bits.
217 *
218 * @see #setDemCipherTransformation(String)
219 */
220 public Builder setDemCipherKeySize(int sizeBits) {
221 mDemCipherKeySize = sizeBits;
222 return this;
223 }
224
225 /**
226 * Sets DEM {@link Mac} algorithm. For example, {@code HmacSHA256} or {@code HmacSHA1}.
227 *
228 * @see Mac#getInstance(String)
229 */
230 public Builder setDemMacAlgorithm(String algorithm) {
231 mDemMacAlgorithm = algorithm;
232 return this;
233 }
234
235 /**
236 * Sets DEM {@link Mac} key size in bits.
237 *
238 * <p>By default, {@code Mac} key size is the same as the {@code Cipher} key size.
239 *
240 * @see #setDemCipherKeySize(int)
241 */
242 public Builder setDemMacKeySize(int sizeBits) {
243 mDemMacKeySize = sizeBits;
244 return this;
245 }
246
247 /**
248 * Returns a new {@link EcIesParameterSpec} based on the current state of this builder.
249 */
250 public EcIesParameterSpec build() {
251 int demMacKeySize = (mDemMacKeySize != -1) ? mDemMacKeySize : mDemCipherKeySize;
252 return new EcIesParameterSpec(
Alex Klyubin0ee93762015-04-10 10:20:48 -0700253 mKemPointFormat,
254 mKemKdfAlgorithm,
255 mDemCipherTransformation,
256 mDemCipherKeySize,
257 mDemMacAlgorithm,
258 demMacKeySize
259 );
260 }
261 }
262}