Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openjdk-multiarch-jdk8u
Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/share/classes/sun/security/ec/ECDHKeyAgreement.java
38830 views
1
/*
2
* Copyright (c) 2009, 2018, Oracle and/or its affiliates. All rights reserved.
3
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4
*
5
* This code is free software; you can redistribute it and/or modify it
6
* under the terms of the GNU General Public License version 2 only, as
7
* published by the Free Software Foundation. Oracle designates this
8
* particular file as subject to the "Classpath" exception as provided
9
* by Oracle in the LICENSE file that accompanied this code.
10
*
11
* This code is distributed in the hope that it will be useful, but WITHOUT
12
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14
* version 2 for more details (a copy is included in the LICENSE file that
15
* accompanied this code).
16
*
17
* You should have received a copy of the GNU General Public License version
18
* 2 along with this work; if not, write to the Free Software Foundation,
19
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20
*
21
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22
* or visit www.oracle.com if you need additional information or have any
23
* questions.
24
*/
25
26
package sun.security.ec;
27
28
import java.math.*;
29
import java.security.*;
30
import java.security.interfaces.*;
31
import java.security.spec.*;
32
import java.util.Optional;
33
34
import javax.crypto.*;
35
import javax.crypto.spec.*;
36
37
import sun.security.util.ArrayUtil;
38
import sun.security.util.ECUtil;
39
import sun.security.util.math.*;
40
import sun.security.ec.point.*;
41
42
/**
43
* KeyAgreement implementation for ECDH.
44
*
45
* @since 1.7
46
*/
47
public final class ECDHKeyAgreement extends KeyAgreementSpi {
48
49
// private key, if initialized
50
private ECPrivateKey privateKey;
51
52
// public key, non-null between doPhase() & generateSecret() only
53
private ECPublicKey publicKey;
54
55
// length of the secret to be derived
56
private int secretLen;
57
58
/**
59
* Constructs a new ECDHKeyAgreement.
60
*/
61
public ECDHKeyAgreement() {
62
}
63
64
// see JCE spec
65
@Override
66
protected void engineInit(Key key, SecureRandom random)
67
throws InvalidKeyException {
68
if (!(key instanceof PrivateKey)) {
69
throw new InvalidKeyException
70
("Key must be instance of PrivateKey");
71
}
72
privateKey = (ECPrivateKey) ECKeyFactory.toECKey(key);
73
publicKey = null;
74
}
75
76
// see JCE spec
77
@Override
78
protected void engineInit(Key key, AlgorithmParameterSpec params,
79
SecureRandom random) throws InvalidKeyException,
80
InvalidAlgorithmParameterException {
81
if (params != null) {
82
throw new InvalidAlgorithmParameterException
83
("Parameters not supported");
84
}
85
engineInit(key, random);
86
}
87
88
// see JCE spec
89
@Override
90
protected Key engineDoPhase(Key key, boolean lastPhase)
91
throws InvalidKeyException, IllegalStateException {
92
if (privateKey == null) {
93
throw new IllegalStateException("Not initialized");
94
}
95
if (publicKey != null) {
96
throw new IllegalStateException("Phase already executed");
97
}
98
if (!lastPhase) {
99
throw new IllegalStateException
100
("Only two party agreement supported, lastPhase must be true");
101
}
102
if (!(key instanceof ECPublicKey)) {
103
throw new InvalidKeyException
104
("Key must be a PublicKey with algorithm EC");
105
}
106
107
this.publicKey = (ECPublicKey) key;
108
109
ECParameterSpec params = publicKey.getParams();
110
int keyLenBits = params.getCurve().getField().getFieldSize();
111
secretLen = (keyLenBits + 7) >> 3;
112
113
return null;
114
}
115
116
private static void validateCoordinate(BigInteger c, BigInteger mod) {
117
if (c.compareTo(BigInteger.ZERO) < 0) {
118
throw new ProviderException("invalid coordinate");
119
}
120
121
if (c.compareTo(mod) >= 0) {
122
throw new ProviderException("invalid coordinate");
123
}
124
}
125
126
/*
127
* Check whether a public key is valid. Throw ProviderException
128
* if it is not valid or could not be validated.
129
*/
130
private static void validate(ECOperations ops, ECPublicKey key) {
131
132
// ensure that integers are in proper range
133
BigInteger x = key.getW().getAffineX();
134
BigInteger y = key.getW().getAffineY();
135
136
BigInteger p = ops.getField().getSize();
137
validateCoordinate(x, p);
138
validateCoordinate(y, p);
139
140
// ensure the point is on the curve
141
EllipticCurve curve = key.getParams().getCurve();
142
BigInteger rhs = x.modPow(BigInteger.valueOf(3), p).add(curve.getA()
143
.multiply(x)).add(curve.getB()).mod(p);
144
BigInteger lhs = y.modPow(BigInteger.valueOf(2), p).mod(p);
145
if (!rhs.equals(lhs)) {
146
throw new ProviderException("point is not on curve");
147
}
148
149
// check the order of the point
150
ImmutableIntegerModuloP xElem = ops.getField().getElement(x);
151
ImmutableIntegerModuloP yElem = ops.getField().getElement(y);
152
AffinePoint affP = new AffinePoint(xElem, yElem);
153
byte[] order = key.getParams().getOrder().toByteArray();
154
ArrayUtil.reverse(order);
155
Point product = ops.multiply(affP, order);
156
if (!ops.isNeutral(product)) {
157
throw new ProviderException("point has incorrect order");
158
}
159
160
}
161
162
// see JCE spec
163
@Override
164
protected byte[] engineGenerateSecret() throws IllegalStateException {
165
if ((privateKey == null) || (publicKey == null)) {
166
throw new IllegalStateException("Not initialized correctly");
167
}
168
169
Optional<byte[]> resultOpt = deriveKeyImpl(privateKey, publicKey);
170
return resultOpt.orElseGet(
171
() -> deriveKeyNative(privateKey, publicKey)
172
);
173
}
174
175
// see JCE spec
176
@Override
177
protected int engineGenerateSecret(byte[] sharedSecret, int
178
offset) throws IllegalStateException, ShortBufferException {
179
if (offset + secretLen > sharedSecret.length) {
180
throw new ShortBufferException("Need " + secretLen
181
+ " bytes, only " + (sharedSecret.length - offset)
182
+ " available");
183
}
184
byte[] secret = engineGenerateSecret();
185
System.arraycopy(secret, 0, sharedSecret, offset, secret.length);
186
return secret.length;
187
}
188
189
// see JCE spec
190
@Override
191
protected SecretKey engineGenerateSecret(String algorithm)
192
throws IllegalStateException, NoSuchAlgorithmException,
193
InvalidKeyException {
194
if (algorithm == null) {
195
throw new NoSuchAlgorithmException("Algorithm must not be null");
196
}
197
if (!(algorithm.equals("TlsPremasterSecret"))) {
198
throw new NoSuchAlgorithmException
199
("Only supported for algorithm TlsPremasterSecret");
200
}
201
return new SecretKeySpec(engineGenerateSecret(), "TlsPremasterSecret");
202
}
203
204
private static
205
Optional<byte[]> deriveKeyImpl(ECPrivateKey priv, ECPublicKey pubKey) {
206
207
ECParameterSpec ecSpec = priv.getParams();
208
EllipticCurve curve = ecSpec.getCurve();
209
Optional<ECOperations> opsOpt = ECOperations.forParameters(ecSpec);
210
if (!opsOpt.isPresent()) {
211
return Optional.empty();
212
}
213
ECOperations ops = opsOpt.get();
214
if (! (priv instanceof ECPrivateKeyImpl)) {
215
return Optional.empty();
216
}
217
ECPrivateKeyImpl privImpl = (ECPrivateKeyImpl) priv;
218
byte[] sArr = privImpl.getArrayS();
219
220
// to match the native implementation, validate the public key here
221
// and throw ProviderException if it is invalid
222
validate(ops, pubKey);
223
224
IntegerFieldModuloP field = ops.getField();
225
// convert s array into field element and multiply by the cofactor
226
MutableIntegerModuloP scalar = field.getElement(sArr).mutable();
227
SmallValue cofactor =
228
field.getSmallValue(priv.getParams().getCofactor());
229
scalar.setProduct(cofactor);
230
int keySize = (curve.getField().getFieldSize() + 7) / 8;
231
byte[] privArr = scalar.asByteArray(keySize);
232
233
ImmutableIntegerModuloP x =
234
field.getElement(pubKey.getW().getAffineX());
235
ImmutableIntegerModuloP y =
236
field.getElement(pubKey.getW().getAffineY());
237
AffinePoint affPub = new AffinePoint(x, y);
238
Point product = ops.multiply(affPub, privArr);
239
if (ops.isNeutral(product)) {
240
throw new ProviderException("Product is zero");
241
}
242
AffinePoint affProduct = product.asAffine();
243
244
byte[] result = affProduct.getX().asByteArray(keySize);
245
ArrayUtil.reverse(result);
246
247
return Optional.of(result);
248
}
249
250
private static
251
byte[] deriveKeyNative(ECPrivateKey privateKey, ECPublicKey publicKey) {
252
253
ECParameterSpec params = privateKey.getParams();
254
byte[] s = privateKey.getS().toByteArray();
255
byte[] encodedParams = // DER OID
256
ECUtil.encodeECParameterSpec(null, params);
257
258
byte[] publicValue;
259
if (publicKey instanceof ECPublicKeyImpl) {
260
ECPublicKeyImpl ecPub = (ECPublicKeyImpl) publicKey;
261
publicValue = ecPub.getEncodedPublicValue();
262
} else { // instanceof ECPublicKey
263
publicValue =
264
ECUtil.encodePoint(publicKey.getW(), params.getCurve());
265
}
266
267
try {
268
return deriveKey(s, publicValue, encodedParams);
269
270
} catch (GeneralSecurityException e) {
271
throw new ProviderException("Could not derive key", e);
272
}
273
}
274
275
276
/**
277
* Generates a secret key using the public and private keys.
278
*
279
* @param s the private key's S value.
280
* @param w the public key's W point (in uncompressed form).
281
* @param encodedParams the curve's DER encoded object identifier.
282
*
283
* @return byte[] the secret key.
284
*/
285
private static native byte[] deriveKey(byte[] s, byte[] w,
286
byte[] encodedParams) throws GeneralSecurityException;
287
}
288
289