1
1
/*
2
- * Copyright (c) 2009, 2020 , Oracle and/or its affiliates. All rights reserved.
2
+ * Copyright (c) 2009, 2021 , Oracle and/or its affiliates. All rights reserved.
3
3
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4
4
*
5
5
* This code is free software; you can redistribute it and/or modify it
25
25
26
26
package sun .security .ec ;
27
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
-
28
+ import sun .security .ec .point .AffinePoint ;
29
+ import sun .security .ec .point .Point ;
37
30
import sun .security .util .ArrayUtil ;
38
31
import sun .security .util .CurveDB ;
39
- import sun .security .util .ECUtil ;
40
32
import sun .security .util .NamedCurve ;
41
- import sun .security .util .math .*;
42
- import sun .security .ec .point .*;
33
+ import sun .security .util .math .ImmutableIntegerModuloP ;
34
+ import sun .security .util .math .IntegerFieldModuloP ;
35
+ import sun .security .util .math .MutableIntegerModuloP ;
36
+ import sun .security .util .math .SmallValue ;
37
+
38
+ import javax .crypto .KeyAgreementSpi ;
39
+ import javax .crypto .SecretKey ;
40
+ import javax .crypto .ShortBufferException ;
41
+ import javax .crypto .spec .SecretKeySpec ;
42
+ import java .math .BigInteger ;
43
+ import java .security .InvalidAlgorithmParameterException ;
44
+ import java .security .InvalidKeyException ;
45
+ import java .security .Key ;
46
+ import java .security .NoSuchAlgorithmException ;
47
+ import java .security .PrivateKey ;
48
+ import java .security .SecureRandom ;
49
+ import java .security .interfaces .ECPrivateKey ;
50
+ import java .security .interfaces .ECPublicKey ;
51
+ import java .security .spec .AlgorithmParameterSpec ;
52
+ import java .security .spec .ECParameterSpec ;
53
+ import java .security .spec .EllipticCurve ;
54
+ import java .util .Optional ;
43
55
44
56
/**
45
57
* KeyAgreement implementation for ECDH.
@@ -50,6 +62,7 @@ public final class ECDHKeyAgreement extends KeyAgreementSpi {
50
62
51
63
// private key, if initialized
52
64
private ECPrivateKey privateKey ;
65
+ ECOperations privateKeyOps ;
53
66
54
67
// public key, non-null between doPhase() & generateSecret() only
55
68
private ECPublicKey publicKey ;
@@ -63,16 +76,34 @@ public final class ECDHKeyAgreement extends KeyAgreementSpi {
63
76
public ECDHKeyAgreement () {
64
77
}
65
78
79
+ // Generic init
80
+ private void init (Key key ) throws
81
+ InvalidKeyException , InvalidAlgorithmParameterException {
82
+ if (!(key instanceof PrivateKey )) {
83
+ throw new InvalidKeyException ("Key must be instance of PrivateKey" );
84
+ }
85
+ privateKey = (ECPrivateKey )ECKeyFactory .toECKey (key );
86
+ publicKey = null ;
87
+ Optional <ECOperations > opsOpt =
88
+ ECOperations .forParameters (privateKey .getParams ());
89
+ if (opsOpt .isEmpty ()) {
90
+ NamedCurve nc = CurveDB .lookup (privateKey .getParams ());
91
+ throw new InvalidAlgorithmParameterException (
92
+ "Curve not supported: " + (nc != null ? nc .toString () :
93
+ "unknown" ));
94
+ }
95
+ privateKeyOps = opsOpt .get ();
96
+ }
97
+
66
98
// see JCE spec
67
99
@ Override
68
100
protected void engineInit (Key key , SecureRandom random )
69
101
throws InvalidKeyException {
70
- if (!(key instanceof PrivateKey )) {
71
- throw new InvalidKeyException
72
- ("Key must be instance of PrivateKey" );
102
+ try {
103
+ init (key );
104
+ } catch (InvalidAlgorithmParameterException e ) {
105
+ throw new InvalidKeyException (e );
73
106
}
74
- privateKey = (ECPrivateKey ) ECKeyFactory .toECKey (key );
75
- publicKey = null ;
76
107
}
77
108
78
109
// see JCE spec
@@ -84,7 +115,7 @@ protected void engineInit(Key key, AlgorithmParameterSpec params,
84
115
throw new InvalidAlgorithmParameterException
85
116
("Parameters not supported" );
86
117
}
87
- engineInit (key , random );
118
+ init (key );
88
119
}
89
120
90
121
// see JCE spec
@@ -108,28 +139,34 @@ protected Key engineDoPhase(Key key, boolean lastPhase)
108
139
109
140
this .publicKey = (ECPublicKey ) key ;
110
141
111
- ECParameterSpec params = publicKey . getParams ();
112
- int keyLenBits = params .getCurve ().getField ().getFieldSize ();
142
+ int keyLenBits =
143
+ publicKey . getParams () .getCurve ().getField ().getFieldSize ();
113
144
secretLen = (keyLenBits + 7 ) >> 3 ;
114
145
146
+ // Validate public key
147
+ validate (privateKeyOps , publicKey );
148
+
115
149
return null ;
116
150
}
117
151
118
- private static void validateCoordinate (BigInteger c , BigInteger mod ) {
152
+ private static void validateCoordinate (BigInteger c , BigInteger mod )
153
+ throws InvalidKeyException {
119
154
if (c .compareTo (BigInteger .ZERO ) < 0 ) {
120
- throw new ProviderException ( "invalid coordinate" );
155
+ throw new InvalidKeyException ( "Invalid coordinate" );
121
156
}
122
157
123
158
if (c .compareTo (mod ) >= 0 ) {
124
- throw new ProviderException ( "invalid coordinate" );
159
+ throw new InvalidKeyException ( "Invalid coordinate" );
125
160
}
126
161
}
127
162
128
163
/*
129
- * Check whether a public key is valid. Throw ProviderException
130
- * if it is not valid or could not be validated.
164
+ * Check whether a public key is valid.
131
165
*/
132
- private static void validate (ECOperations ops , ECPublicKey key ) {
166
+ private static void validate (ECOperations ops , ECPublicKey key )
167
+ throws InvalidKeyException {
168
+
169
+ ECParameterSpec spec = key .getParams ();
133
170
134
171
// ensure that integers are in proper range
135
172
BigInteger x = key .getW ().getAffineX ();
@@ -140,23 +177,23 @@ private static void validate(ECOperations ops, ECPublicKey key) {
140
177
validateCoordinate (y , p );
141
178
142
179
// ensure the point is on the curve
143
- EllipticCurve curve = key . getParams () .getCurve ();
180
+ EllipticCurve curve = spec .getCurve ();
144
181
BigInteger rhs = x .modPow (BigInteger .valueOf (3 ), p ).add (curve .getA ()
145
182
.multiply (x )).add (curve .getB ()).mod (p );
146
183
BigInteger lhs = y .modPow (BigInteger .valueOf (2 ), p ).mod (p );
147
184
if (!rhs .equals (lhs )) {
148
- throw new ProviderException ( "point is not on curve" );
185
+ throw new InvalidKeyException ( "Point is not on curve" );
149
186
}
150
187
151
188
// check the order of the point
152
189
ImmutableIntegerModuloP xElem = ops .getField ().getElement (x );
153
190
ImmutableIntegerModuloP yElem = ops .getField ().getElement (y );
154
191
AffinePoint affP = new AffinePoint (xElem , yElem );
155
- byte [] order = key . getParams () .getOrder ().toByteArray ();
192
+ byte [] order = spec .getOrder ().toByteArray ();
156
193
ArrayUtil .reverse (order );
157
194
Point product = ops .multiply (affP , order );
158
195
if (!ops .isNeutral (product )) {
159
- throw new ProviderException ( "point has incorrect order" );
196
+ throw new InvalidKeyException ( "Point has incorrect order" );
160
197
}
161
198
162
199
}
@@ -167,15 +204,13 @@ protected byte[] engineGenerateSecret() throws IllegalStateException {
167
204
if ((privateKey == null ) || (publicKey == null )) {
168
205
throw new IllegalStateException ("Not initialized correctly" );
169
206
}
207
+
170
208
byte [] result ;
171
- Optional <byte []> resultOpt = deriveKeyImpl (privateKey , publicKey );
172
- if (resultOpt .isEmpty ()) {
173
- NamedCurve nc = CurveDB .lookup (publicKey .getParams ());
174
- throw new IllegalStateException (
175
- new InvalidAlgorithmParameterException ("Curve not supported: " +
176
- (nc != null ? nc .toString () : "unknown" )));
209
+ try {
210
+ result = deriveKeyImpl (privateKey , privateKeyOps , publicKey );
211
+ } catch (Exception e ) {
212
+ throw new IllegalStateException (e );
177
213
}
178
- result = resultOpt .get ();
179
214
publicKey = null ;
180
215
return result ;
181
216
}
@@ -210,48 +245,30 @@ protected SecretKey engineGenerateSecret(String algorithm)
210
245
}
211
246
212
247
private static
213
- Optional <byte []> deriveKeyImpl (ECPrivateKey priv , ECPublicKey pubKey ) {
214
-
215
- ECParameterSpec ecSpec = priv .getParams ();
216
- EllipticCurve curve = ecSpec .getCurve ();
217
- Optional <ECOperations > opsOpt = ECOperations .forParameters (ecSpec );
218
- if (opsOpt .isEmpty ()) {
219
- return Optional .empty ();
220
- }
221
- ECOperations ops = opsOpt .get ();
222
- if (! (priv instanceof ECPrivateKeyImpl )) {
223
- return Optional .empty ();
224
- }
225
- ECPrivateKeyImpl privImpl = (ECPrivateKeyImpl ) priv ;
226
- byte [] sArr = privImpl .getArrayS ();
227
-
228
- // to match the native implementation, validate the public key here
229
- // and throw ProviderException if it is invalid
230
- validate (ops , pubKey );
248
+ byte [] deriveKeyImpl (ECPrivateKey priv , ECOperations ops ,
249
+ ECPublicKey pubKey ) throws InvalidKeyException {
231
250
232
251
IntegerFieldModuloP field = ops .getField ();
233
252
// convert s array into field element and multiply by the cofactor
234
- MutableIntegerModuloP scalar = field .getElement (sArr ).mutable ();
253
+ MutableIntegerModuloP scalar = field .getElement (priv . getS () ).mutable ();
235
254
SmallValue cofactor =
236
255
field .getSmallValue (priv .getParams ().getCofactor ());
237
256
scalar .setProduct (cofactor );
238
- int keySize = (curve .getField ().getFieldSize () + 7 ) / 8 ;
239
- byte [] privArr = scalar .asByteArray (keySize );
240
-
257
+ int keySize =
258
+ (priv .getParams ().getCurve ().getField ().getFieldSize () + 7 ) / 8 ;
241
259
ImmutableIntegerModuloP x =
242
260
field .getElement (pubKey .getW ().getAffineX ());
243
261
ImmutableIntegerModuloP y =
244
262
field .getElement (pubKey .getW ().getAffineY ());
245
- AffinePoint affPub = new AffinePoint (x , y );
246
- Point product = ops . multiply ( affPub , privArr );
263
+ Point product = ops . multiply ( new AffinePoint (x , y ),
264
+ scalar . asByteArray ( keySize ) );
247
265
if (ops .isNeutral (product )) {
248
- throw new ProviderException ("Product is zero" );
266
+ throw new InvalidKeyException ("Product is zero" );
249
267
}
250
- AffinePoint affProduct = product .asAffine ();
251
268
252
- byte [] result = affProduct .getX ().asByteArray (keySize );
269
+ byte [] result = product . asAffine () .getX ().asByteArray (keySize );
253
270
ArrayUtil .reverse (result );
254
271
255
- return Optional . of ( result ) ;
272
+ return result ;
256
273
}
257
274
}
0 commit comments