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/native/sun/security/ec/ECC_JNI.cpp
38918 views
1
/*
2
* Copyright (c) 2009, 2017, 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
#include <jni.h>
27
#include "impl/ecc_impl.h"
28
29
#define ILLEGAL_STATE_EXCEPTION "java/lang/IllegalStateException"
30
#define INVALID_ALGORITHM_PARAMETER_EXCEPTION \
31
"java/security/InvalidAlgorithmParameterException"
32
#define INVALID_PARAMETER_EXCEPTION \
33
"java/security/InvalidParameterException"
34
#define KEY_EXCEPTION "java/security/KeyException"
35
36
extern "C" {
37
38
/*
39
* Throws an arbitrary Java exception.
40
*/
41
void ThrowException(JNIEnv *env, const char *exceptionName)
42
{
43
jclass exceptionClazz = env->FindClass(exceptionName);
44
if (exceptionClazz != NULL) {
45
env->ThrowNew(exceptionClazz, NULL);
46
}
47
}
48
49
/*
50
* Deep free of the ECParams struct
51
*/
52
void FreeECParams(ECParams *ecparams, jboolean freeStruct)
53
{
54
// Use B_FALSE to free the SECItem->data element, but not the SECItem itself
55
// Use B_TRUE to free both
56
57
SECITEM_FreeItem(&ecparams->fieldID.u.prime, B_FALSE);
58
SECITEM_FreeItem(&ecparams->curve.a, B_FALSE);
59
SECITEM_FreeItem(&ecparams->curve.b, B_FALSE);
60
SECITEM_FreeItem(&ecparams->curve.seed, B_FALSE);
61
SECITEM_FreeItem(&ecparams->base, B_FALSE);
62
SECITEM_FreeItem(&ecparams->order, B_FALSE);
63
SECITEM_FreeItem(&ecparams->DEREncoding, B_FALSE);
64
SECITEM_FreeItem(&ecparams->curveOID, B_FALSE);
65
if (freeStruct)
66
free(ecparams);
67
}
68
69
jbyteArray getEncodedBytes(JNIEnv *env, SECItem *hSECItem)
70
{
71
SECItem *s = (SECItem *)hSECItem;
72
73
jbyteArray jEncodedBytes = env->NewByteArray(s->len);
74
if (jEncodedBytes == NULL) {
75
return NULL;
76
}
77
// Copy bytes from a native SECItem buffer to Java byte array
78
env->SetByteArrayRegion(jEncodedBytes, 0, s->len, (jbyte *)s->data);
79
if (env->ExceptionCheck()) { // should never happen
80
return NULL;
81
}
82
return jEncodedBytes;
83
}
84
85
/*
86
* Class: sun_security_ec_ECKeyPairGenerator
87
* Method: isCurveSupported
88
* Signature: ([B)Z
89
*/
90
JNIEXPORT jboolean
91
JNICALL Java_sun_security_ec_ECKeyPairGenerator_isCurveSupported
92
(JNIEnv *env, jclass clazz, jbyteArray encodedParams)
93
{
94
SECKEYECParams params_item;
95
ECParams *ecparams = NULL;
96
jboolean result = JNI_FALSE;
97
98
// The curve is supported if we can get parameters for it
99
params_item.len = env->GetArrayLength(encodedParams);
100
params_item.data =
101
(unsigned char *) env->GetByteArrayElements(encodedParams, 0);
102
if (params_item.data == NULL) {
103
goto cleanup;
104
}
105
106
// Fill a new ECParams using the supplied OID
107
if (EC_DecodeParams(&params_item, &ecparams, 0) != SECSuccess) {
108
/* bad curve OID */
109
goto cleanup;
110
}
111
112
// If we make it to here, then the curve is supported
113
result = JNI_TRUE;
114
115
cleanup:
116
{
117
if (params_item.data) {
118
env->ReleaseByteArrayElements(encodedParams,
119
(jbyte *) params_item.data, JNI_ABORT);
120
}
121
if (ecparams) {
122
FreeECParams(ecparams, true);
123
}
124
}
125
126
return result;
127
}
128
129
/*
130
* Class: sun_security_ec_ECKeyPairGenerator
131
* Method: generateECKeyPair
132
* Signature: (I[B[B)[[B
133
*/
134
JNIEXPORT jobjectArray
135
JNICALL Java_sun_security_ec_ECKeyPairGenerator_generateECKeyPair
136
(JNIEnv *env, jclass clazz, jint keySize, jbyteArray encodedParams, jbyteArray seed)
137
{
138
ECPrivateKey *privKey = NULL; // contains both public and private values
139
ECParams *ecparams = NULL;
140
SECKEYECParams params_item;
141
jint jSeedLength;
142
jbyte* pSeedBuffer = NULL;
143
jobjectArray result = NULL;
144
jclass baCls = NULL;
145
jbyteArray jba;
146
147
// Initialize the ECParams struct
148
params_item.len = env->GetArrayLength(encodedParams);
149
params_item.data =
150
(unsigned char *) env->GetByteArrayElements(encodedParams, 0);
151
if (params_item.data == NULL) {
152
goto cleanup;
153
}
154
155
// Fill a new ECParams using the supplied OID
156
if (EC_DecodeParams(&params_item, &ecparams, 0) != SECSuccess) {
157
/* bad curve OID */
158
ThrowException(env, INVALID_ALGORITHM_PARAMETER_EXCEPTION);
159
goto cleanup;
160
}
161
162
// Copy seed from Java to native buffer
163
jSeedLength = env->GetArrayLength(seed);
164
pSeedBuffer = new jbyte[jSeedLength];
165
env->GetByteArrayRegion(seed, 0, jSeedLength, pSeedBuffer);
166
167
// Generate the new keypair (using the supplied seed)
168
if (EC_NewKey(ecparams, &privKey, (unsigned char *) pSeedBuffer,
169
jSeedLength, 0) != SECSuccess) {
170
ThrowException(env, KEY_EXCEPTION);
171
goto cleanup;
172
}
173
174
jboolean isCopy;
175
baCls = env->FindClass("[B");
176
if (baCls == NULL) {
177
goto cleanup;
178
}
179
result = env->NewObjectArray(2, baCls, NULL);
180
if (result == NULL) {
181
goto cleanup;
182
}
183
jba = getEncodedBytes(env, &(privKey->privateValue));
184
if (jba == NULL) {
185
result = NULL;
186
goto cleanup;
187
}
188
env->SetObjectArrayElement(result, 0, jba); // big integer
189
if (env->ExceptionCheck()) { // should never happen
190
result = NULL;
191
goto cleanup;
192
}
193
194
jba = getEncodedBytes(env, &(privKey->publicValue));
195
if (jba == NULL) {
196
result = NULL;
197
goto cleanup;
198
}
199
env->SetObjectArrayElement(result, 1, jba); // encoded ec point
200
if (env->ExceptionCheck()) { // should never happen
201
result = NULL;
202
goto cleanup;
203
}
204
205
cleanup:
206
{
207
if (params_item.data) {
208
env->ReleaseByteArrayElements(encodedParams,
209
(jbyte *) params_item.data, JNI_ABORT);
210
}
211
if (ecparams) {
212
FreeECParams(ecparams, true);
213
}
214
if (privKey) {
215
FreeECParams(&privKey->ecParams, false);
216
SECITEM_FreeItem(&privKey->version, B_FALSE);
217
SECITEM_FreeItem(&privKey->privateValue, B_FALSE);
218
SECITEM_FreeItem(&privKey->publicValue, B_FALSE);
219
free(privKey);
220
}
221
222
if (pSeedBuffer) {
223
delete [] pSeedBuffer;
224
}
225
}
226
227
return result;
228
}
229
230
/*
231
* Class: sun_security_ec_ECDSASignature
232
* Method: signDigest
233
* Signature: ([B[B[B[B)[B
234
*/
235
JNIEXPORT jbyteArray
236
JNICALL Java_sun_security_ec_ECDSASignature_signDigest
237
(JNIEnv *env, jclass clazz, jbyteArray digest, jbyteArray privateKey, jbyteArray encodedParams, jbyteArray seed, jint timing)
238
{
239
jbyte* pDigestBuffer = NULL;
240
jint jDigestLength = env->GetArrayLength(digest);
241
jbyteArray jSignedDigest = NULL;
242
243
SECItem signature_item;
244
jbyte* pSignedDigestBuffer = NULL;
245
jbyteArray temp;
246
247
jint jSeedLength = env->GetArrayLength(seed);
248
jbyte* pSeedBuffer = NULL;
249
250
// Copy digest from Java to native buffer
251
pDigestBuffer = new jbyte[jDigestLength];
252
env->GetByteArrayRegion(digest, 0, jDigestLength, pDigestBuffer);
253
SECItem digest_item;
254
digest_item.data = (unsigned char *) pDigestBuffer;
255
digest_item.len = jDigestLength;
256
257
ECPrivateKey privKey;
258
privKey.privateValue.data = NULL;
259
260
// Initialize the ECParams struct
261
ECParams *ecparams = NULL;
262
SECKEYECParams params_item;
263
params_item.len = env->GetArrayLength(encodedParams);
264
params_item.data =
265
(unsigned char *) env->GetByteArrayElements(encodedParams, 0);
266
if (params_item.data == NULL) {
267
goto cleanup;
268
}
269
270
// Fill a new ECParams using the supplied OID
271
if (EC_DecodeParams(&params_item, &ecparams, 0) != SECSuccess) {
272
/* bad curve OID */
273
ThrowException(env, INVALID_ALGORITHM_PARAMETER_EXCEPTION);
274
goto cleanup;
275
}
276
277
// Extract private key data
278
privKey.ecParams = *ecparams; // struct assignment
279
privKey.privateValue.len = env->GetArrayLength(privateKey);
280
privKey.privateValue.data =
281
(unsigned char *) env->GetByteArrayElements(privateKey, 0);
282
if (privKey.privateValue.data == NULL) {
283
goto cleanup;
284
}
285
286
// Prepare a buffer for the signature (twice the key length)
287
pSignedDigestBuffer = new jbyte[ecparams->order.len * 2];
288
signature_item.data = (unsigned char *) pSignedDigestBuffer;
289
signature_item.len = ecparams->order.len * 2;
290
291
// Copy seed from Java to native buffer
292
pSeedBuffer = new jbyte[jSeedLength];
293
env->GetByteArrayRegion(seed, 0, jSeedLength, pSeedBuffer);
294
295
// Sign the digest (using the supplied seed)
296
if (ECDSA_SignDigest(&privKey, &signature_item, &digest_item,
297
(unsigned char *) pSeedBuffer, jSeedLength, 0, timing) != SECSuccess) {
298
ThrowException(env, KEY_EXCEPTION);
299
goto cleanup;
300
}
301
302
// Create new byte array
303
temp = env->NewByteArray(signature_item.len);
304
if (temp == NULL) {
305
goto cleanup;
306
}
307
308
// Copy data from native buffer
309
env->SetByteArrayRegion(temp, 0, signature_item.len, pSignedDigestBuffer);
310
jSignedDigest = temp;
311
312
cleanup:
313
{
314
if (params_item.data) {
315
env->ReleaseByteArrayElements(encodedParams,
316
(jbyte *) params_item.data, JNI_ABORT);
317
}
318
if (privKey.privateValue.data) {
319
env->ReleaseByteArrayElements(privateKey,
320
(jbyte *) privKey.privateValue.data, JNI_ABORT);
321
}
322
if (pDigestBuffer) {
323
delete [] pDigestBuffer;
324
}
325
if (pSignedDigestBuffer) {
326
delete [] pSignedDigestBuffer;
327
}
328
if (pSeedBuffer) {
329
delete [] pSeedBuffer;
330
}
331
if (ecparams) {
332
FreeECParams(ecparams, true);
333
}
334
}
335
336
return jSignedDigest;
337
}
338
339
/*
340
* Class: sun_security_ec_ECDSASignature
341
* Method: verifySignedDigest
342
* Signature: ([B[B[B[B)Z
343
*/
344
JNIEXPORT jboolean
345
JNICALL Java_sun_security_ec_ECDSASignature_verifySignedDigest
346
(JNIEnv *env, jclass clazz, jbyteArray signedDigest, jbyteArray digest, jbyteArray publicKey, jbyteArray encodedParams)
347
{
348
jboolean isValid = false;
349
350
// Copy signedDigest from Java to native buffer
351
jbyte* pSignedDigestBuffer = NULL;
352
jint jSignedDigestLength = env->GetArrayLength(signedDigest);
353
pSignedDigestBuffer = new jbyte[jSignedDigestLength];
354
env->GetByteArrayRegion(signedDigest, 0, jSignedDigestLength,
355
pSignedDigestBuffer);
356
SECItem signature_item;
357
signature_item.data = (unsigned char *) pSignedDigestBuffer;
358
signature_item.len = jSignedDigestLength;
359
360
// Copy digest from Java to native buffer
361
jbyte* pDigestBuffer = NULL;
362
jint jDigestLength = env->GetArrayLength(digest);
363
pDigestBuffer = new jbyte[jDigestLength];
364
env->GetByteArrayRegion(digest, 0, jDigestLength, pDigestBuffer);
365
SECItem digest_item;
366
digest_item.data = (unsigned char *) pDigestBuffer;
367
digest_item.len = jDigestLength;
368
369
// Extract public key data
370
ECPublicKey pubKey;
371
pubKey.publicValue.data = NULL;
372
ECParams *ecparams = NULL;
373
SECKEYECParams params_item;
374
375
// Initialize the ECParams struct
376
params_item.len = env->GetArrayLength(encodedParams);
377
params_item.data =
378
(unsigned char *) env->GetByteArrayElements(encodedParams, 0);
379
if (params_item.data == NULL) {
380
goto cleanup;
381
}
382
383
// Fill a new ECParams using the supplied OID
384
if (EC_DecodeParams(&params_item, &ecparams, 0) != SECSuccess) {
385
/* bad curve OID */
386
ThrowException(env, INVALID_ALGORITHM_PARAMETER_EXCEPTION);
387
goto cleanup;
388
}
389
pubKey.ecParams = *ecparams; // struct assignment
390
pubKey.publicValue.len = env->GetArrayLength(publicKey);
391
pubKey.publicValue.data =
392
(unsigned char *) env->GetByteArrayElements(publicKey, 0);
393
394
if (ECDSA_VerifyDigest(&pubKey, &signature_item, &digest_item, 0)
395
!= SECSuccess) {
396
goto cleanup;
397
}
398
399
isValid = true;
400
401
cleanup:
402
{
403
if (params_item.data)
404
env->ReleaseByteArrayElements(encodedParams,
405
(jbyte *) params_item.data, JNI_ABORT);
406
407
if (pubKey.publicValue.data)
408
env->ReleaseByteArrayElements(publicKey,
409
(jbyte *) pubKey.publicValue.data, JNI_ABORT);
410
411
if (ecparams)
412
FreeECParams(ecparams, true);
413
414
if (pSignedDigestBuffer)
415
delete [] pSignedDigestBuffer;
416
417
if (pDigestBuffer)
418
delete [] pDigestBuffer;
419
}
420
421
return isValid;
422
}
423
424
/*
425
* Class: sun_security_ec_ECDHKeyAgreement
426
* Method: deriveKey
427
* Signature: ([B[B[B)[B
428
*/
429
JNIEXPORT jbyteArray
430
JNICALL Java_sun_security_ec_ECDHKeyAgreement_deriveKey
431
(JNIEnv *env, jclass clazz, jbyteArray privateKey, jbyteArray publicKey, jbyteArray encodedParams)
432
{
433
jbyteArray jSecret = NULL;
434
ECParams *ecparams = NULL;
435
SECItem privateValue_item;
436
privateValue_item.data = NULL;
437
SECItem publicValue_item;
438
publicValue_item.data = NULL;
439
SECKEYECParams params_item;
440
params_item.data = NULL;
441
442
// Extract private key value
443
privateValue_item.len = env->GetArrayLength(privateKey);
444
privateValue_item.data =
445
(unsigned char *) env->GetByteArrayElements(privateKey, 0);
446
if (privateValue_item.data == NULL) {
447
goto cleanup;
448
}
449
450
// Extract public key value
451
publicValue_item.len = env->GetArrayLength(publicKey);
452
publicValue_item.data =
453
(unsigned char *) env->GetByteArrayElements(publicKey, 0);
454
if (publicValue_item.data == NULL) {
455
goto cleanup;
456
}
457
458
// Initialize the ECParams struct
459
params_item.len = env->GetArrayLength(encodedParams);
460
params_item.data =
461
(unsigned char *) env->GetByteArrayElements(encodedParams, 0);
462
if (params_item.data == NULL) {
463
goto cleanup;
464
}
465
466
// Fill a new ECParams using the supplied OID
467
if (EC_DecodeParams(&params_item, &ecparams, 0) != SECSuccess) {
468
/* bad curve OID */
469
ThrowException(env, INVALID_ALGORITHM_PARAMETER_EXCEPTION);
470
goto cleanup;
471
}
472
473
// Prepare a buffer for the secret
474
SECItem secret_item;
475
secret_item.data = NULL;
476
secret_item.len = ecparams->order.len * 2;
477
478
if (ECDH_Derive(&publicValue_item, ecparams, &privateValue_item, B_FALSE,
479
&secret_item, 0) != SECSuccess) {
480
ThrowException(env, ILLEGAL_STATE_EXCEPTION);
481
goto cleanup;
482
}
483
484
// Create new byte array
485
jSecret = env->NewByteArray(secret_item.len);
486
if (jSecret == NULL) {
487
goto cleanup;
488
}
489
490
// Copy bytes from the SECItem buffer to a Java byte array
491
env->SetByteArrayRegion(jSecret, 0, secret_item.len,
492
(jbyte *)secret_item.data);
493
494
// Free the SECItem data buffer
495
SECITEM_FreeItem(&secret_item, B_FALSE);
496
497
cleanup:
498
{
499
if (privateValue_item.data)
500
env->ReleaseByteArrayElements(privateKey,
501
(jbyte *) privateValue_item.data, JNI_ABORT);
502
503
if (publicValue_item.data)
504
env->ReleaseByteArrayElements(publicKey,
505
(jbyte *) publicValue_item.data, JNI_ABORT);
506
507
if (params_item.data)
508
env->ReleaseByteArrayElements(encodedParams,
509
(jbyte *) params_item.data, JNI_ABORT);
510
511
if (ecparams)
512
FreeECParams(ecparams, true);
513
}
514
515
return jSecret;
516
}
517
518
} /* extern "C" */
519
520