Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/share/native/sun/security/ec/ECC_JNI.cpp
38918 views
/*1* Copyright (c) 2009, 2017, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425#include <jni.h>26#include "impl/ecc_impl.h"2728#define ILLEGAL_STATE_EXCEPTION "java/lang/IllegalStateException"29#define INVALID_ALGORITHM_PARAMETER_EXCEPTION \30"java/security/InvalidAlgorithmParameterException"31#define INVALID_PARAMETER_EXCEPTION \32"java/security/InvalidParameterException"33#define KEY_EXCEPTION "java/security/KeyException"3435extern "C" {3637/*38* Throws an arbitrary Java exception.39*/40void ThrowException(JNIEnv *env, const char *exceptionName)41{42jclass exceptionClazz = env->FindClass(exceptionName);43if (exceptionClazz != NULL) {44env->ThrowNew(exceptionClazz, NULL);45}46}4748/*49* Deep free of the ECParams struct50*/51void FreeECParams(ECParams *ecparams, jboolean freeStruct)52{53// Use B_FALSE to free the SECItem->data element, but not the SECItem itself54// Use B_TRUE to free both5556SECITEM_FreeItem(&ecparams->fieldID.u.prime, B_FALSE);57SECITEM_FreeItem(&ecparams->curve.a, B_FALSE);58SECITEM_FreeItem(&ecparams->curve.b, B_FALSE);59SECITEM_FreeItem(&ecparams->curve.seed, B_FALSE);60SECITEM_FreeItem(&ecparams->base, B_FALSE);61SECITEM_FreeItem(&ecparams->order, B_FALSE);62SECITEM_FreeItem(&ecparams->DEREncoding, B_FALSE);63SECITEM_FreeItem(&ecparams->curveOID, B_FALSE);64if (freeStruct)65free(ecparams);66}6768jbyteArray getEncodedBytes(JNIEnv *env, SECItem *hSECItem)69{70SECItem *s = (SECItem *)hSECItem;7172jbyteArray jEncodedBytes = env->NewByteArray(s->len);73if (jEncodedBytes == NULL) {74return NULL;75}76// Copy bytes from a native SECItem buffer to Java byte array77env->SetByteArrayRegion(jEncodedBytes, 0, s->len, (jbyte *)s->data);78if (env->ExceptionCheck()) { // should never happen79return NULL;80}81return jEncodedBytes;82}8384/*85* Class: sun_security_ec_ECKeyPairGenerator86* Method: isCurveSupported87* Signature: ([B)Z88*/89JNIEXPORT jboolean90JNICALL Java_sun_security_ec_ECKeyPairGenerator_isCurveSupported91(JNIEnv *env, jclass clazz, jbyteArray encodedParams)92{93SECKEYECParams params_item;94ECParams *ecparams = NULL;95jboolean result = JNI_FALSE;9697// The curve is supported if we can get parameters for it98params_item.len = env->GetArrayLength(encodedParams);99params_item.data =100(unsigned char *) env->GetByteArrayElements(encodedParams, 0);101if (params_item.data == NULL) {102goto cleanup;103}104105// Fill a new ECParams using the supplied OID106if (EC_DecodeParams(¶ms_item, &ecparams, 0) != SECSuccess) {107/* bad curve OID */108goto cleanup;109}110111// If we make it to here, then the curve is supported112result = JNI_TRUE;113114cleanup:115{116if (params_item.data) {117env->ReleaseByteArrayElements(encodedParams,118(jbyte *) params_item.data, JNI_ABORT);119}120if (ecparams) {121FreeECParams(ecparams, true);122}123}124125return result;126}127128/*129* Class: sun_security_ec_ECKeyPairGenerator130* Method: generateECKeyPair131* Signature: (I[B[B)[[B132*/133JNIEXPORT jobjectArray134JNICALL Java_sun_security_ec_ECKeyPairGenerator_generateECKeyPair135(JNIEnv *env, jclass clazz, jint keySize, jbyteArray encodedParams, jbyteArray seed)136{137ECPrivateKey *privKey = NULL; // contains both public and private values138ECParams *ecparams = NULL;139SECKEYECParams params_item;140jint jSeedLength;141jbyte* pSeedBuffer = NULL;142jobjectArray result = NULL;143jclass baCls = NULL;144jbyteArray jba;145146// Initialize the ECParams struct147params_item.len = env->GetArrayLength(encodedParams);148params_item.data =149(unsigned char *) env->GetByteArrayElements(encodedParams, 0);150if (params_item.data == NULL) {151goto cleanup;152}153154// Fill a new ECParams using the supplied OID155if (EC_DecodeParams(¶ms_item, &ecparams, 0) != SECSuccess) {156/* bad curve OID */157ThrowException(env, INVALID_ALGORITHM_PARAMETER_EXCEPTION);158goto cleanup;159}160161// Copy seed from Java to native buffer162jSeedLength = env->GetArrayLength(seed);163pSeedBuffer = new jbyte[jSeedLength];164env->GetByteArrayRegion(seed, 0, jSeedLength, pSeedBuffer);165166// Generate the new keypair (using the supplied seed)167if (EC_NewKey(ecparams, &privKey, (unsigned char *) pSeedBuffer,168jSeedLength, 0) != SECSuccess) {169ThrowException(env, KEY_EXCEPTION);170goto cleanup;171}172173jboolean isCopy;174baCls = env->FindClass("[B");175if (baCls == NULL) {176goto cleanup;177}178result = env->NewObjectArray(2, baCls, NULL);179if (result == NULL) {180goto cleanup;181}182jba = getEncodedBytes(env, &(privKey->privateValue));183if (jba == NULL) {184result = NULL;185goto cleanup;186}187env->SetObjectArrayElement(result, 0, jba); // big integer188if (env->ExceptionCheck()) { // should never happen189result = NULL;190goto cleanup;191}192193jba = getEncodedBytes(env, &(privKey->publicValue));194if (jba == NULL) {195result = NULL;196goto cleanup;197}198env->SetObjectArrayElement(result, 1, jba); // encoded ec point199if (env->ExceptionCheck()) { // should never happen200result = NULL;201goto cleanup;202}203204cleanup:205{206if (params_item.data) {207env->ReleaseByteArrayElements(encodedParams,208(jbyte *) params_item.data, JNI_ABORT);209}210if (ecparams) {211FreeECParams(ecparams, true);212}213if (privKey) {214FreeECParams(&privKey->ecParams, false);215SECITEM_FreeItem(&privKey->version, B_FALSE);216SECITEM_FreeItem(&privKey->privateValue, B_FALSE);217SECITEM_FreeItem(&privKey->publicValue, B_FALSE);218free(privKey);219}220221if (pSeedBuffer) {222delete [] pSeedBuffer;223}224}225226return result;227}228229/*230* Class: sun_security_ec_ECDSASignature231* Method: signDigest232* Signature: ([B[B[B[B)[B233*/234JNIEXPORT jbyteArray235JNICALL Java_sun_security_ec_ECDSASignature_signDigest236(JNIEnv *env, jclass clazz, jbyteArray digest, jbyteArray privateKey, jbyteArray encodedParams, jbyteArray seed, jint timing)237{238jbyte* pDigestBuffer = NULL;239jint jDigestLength = env->GetArrayLength(digest);240jbyteArray jSignedDigest = NULL;241242SECItem signature_item;243jbyte* pSignedDigestBuffer = NULL;244jbyteArray temp;245246jint jSeedLength = env->GetArrayLength(seed);247jbyte* pSeedBuffer = NULL;248249// Copy digest from Java to native buffer250pDigestBuffer = new jbyte[jDigestLength];251env->GetByteArrayRegion(digest, 0, jDigestLength, pDigestBuffer);252SECItem digest_item;253digest_item.data = (unsigned char *) pDigestBuffer;254digest_item.len = jDigestLength;255256ECPrivateKey privKey;257privKey.privateValue.data = NULL;258259// Initialize the ECParams struct260ECParams *ecparams = NULL;261SECKEYECParams params_item;262params_item.len = env->GetArrayLength(encodedParams);263params_item.data =264(unsigned char *) env->GetByteArrayElements(encodedParams, 0);265if (params_item.data == NULL) {266goto cleanup;267}268269// Fill a new ECParams using the supplied OID270if (EC_DecodeParams(¶ms_item, &ecparams, 0) != SECSuccess) {271/* bad curve OID */272ThrowException(env, INVALID_ALGORITHM_PARAMETER_EXCEPTION);273goto cleanup;274}275276// Extract private key data277privKey.ecParams = *ecparams; // struct assignment278privKey.privateValue.len = env->GetArrayLength(privateKey);279privKey.privateValue.data =280(unsigned char *) env->GetByteArrayElements(privateKey, 0);281if (privKey.privateValue.data == NULL) {282goto cleanup;283}284285// Prepare a buffer for the signature (twice the key length)286pSignedDigestBuffer = new jbyte[ecparams->order.len * 2];287signature_item.data = (unsigned char *) pSignedDigestBuffer;288signature_item.len = ecparams->order.len * 2;289290// Copy seed from Java to native buffer291pSeedBuffer = new jbyte[jSeedLength];292env->GetByteArrayRegion(seed, 0, jSeedLength, pSeedBuffer);293294// Sign the digest (using the supplied seed)295if (ECDSA_SignDigest(&privKey, &signature_item, &digest_item,296(unsigned char *) pSeedBuffer, jSeedLength, 0, timing) != SECSuccess) {297ThrowException(env, KEY_EXCEPTION);298goto cleanup;299}300301// Create new byte array302temp = env->NewByteArray(signature_item.len);303if (temp == NULL) {304goto cleanup;305}306307// Copy data from native buffer308env->SetByteArrayRegion(temp, 0, signature_item.len, pSignedDigestBuffer);309jSignedDigest = temp;310311cleanup:312{313if (params_item.data) {314env->ReleaseByteArrayElements(encodedParams,315(jbyte *) params_item.data, JNI_ABORT);316}317if (privKey.privateValue.data) {318env->ReleaseByteArrayElements(privateKey,319(jbyte *) privKey.privateValue.data, JNI_ABORT);320}321if (pDigestBuffer) {322delete [] pDigestBuffer;323}324if (pSignedDigestBuffer) {325delete [] pSignedDigestBuffer;326}327if (pSeedBuffer) {328delete [] pSeedBuffer;329}330if (ecparams) {331FreeECParams(ecparams, true);332}333}334335return jSignedDigest;336}337338/*339* Class: sun_security_ec_ECDSASignature340* Method: verifySignedDigest341* Signature: ([B[B[B[B)Z342*/343JNIEXPORT jboolean344JNICALL Java_sun_security_ec_ECDSASignature_verifySignedDigest345(JNIEnv *env, jclass clazz, jbyteArray signedDigest, jbyteArray digest, jbyteArray publicKey, jbyteArray encodedParams)346{347jboolean isValid = false;348349// Copy signedDigest from Java to native buffer350jbyte* pSignedDigestBuffer = NULL;351jint jSignedDigestLength = env->GetArrayLength(signedDigest);352pSignedDigestBuffer = new jbyte[jSignedDigestLength];353env->GetByteArrayRegion(signedDigest, 0, jSignedDigestLength,354pSignedDigestBuffer);355SECItem signature_item;356signature_item.data = (unsigned char *) pSignedDigestBuffer;357signature_item.len = jSignedDigestLength;358359// Copy digest from Java to native buffer360jbyte* pDigestBuffer = NULL;361jint jDigestLength = env->GetArrayLength(digest);362pDigestBuffer = new jbyte[jDigestLength];363env->GetByteArrayRegion(digest, 0, jDigestLength, pDigestBuffer);364SECItem digest_item;365digest_item.data = (unsigned char *) pDigestBuffer;366digest_item.len = jDigestLength;367368// Extract public key data369ECPublicKey pubKey;370pubKey.publicValue.data = NULL;371ECParams *ecparams = NULL;372SECKEYECParams params_item;373374// Initialize the ECParams struct375params_item.len = env->GetArrayLength(encodedParams);376params_item.data =377(unsigned char *) env->GetByteArrayElements(encodedParams, 0);378if (params_item.data == NULL) {379goto cleanup;380}381382// Fill a new ECParams using the supplied OID383if (EC_DecodeParams(¶ms_item, &ecparams, 0) != SECSuccess) {384/* bad curve OID */385ThrowException(env, INVALID_ALGORITHM_PARAMETER_EXCEPTION);386goto cleanup;387}388pubKey.ecParams = *ecparams; // struct assignment389pubKey.publicValue.len = env->GetArrayLength(publicKey);390pubKey.publicValue.data =391(unsigned char *) env->GetByteArrayElements(publicKey, 0);392393if (ECDSA_VerifyDigest(&pubKey, &signature_item, &digest_item, 0)394!= SECSuccess) {395goto cleanup;396}397398isValid = true;399400cleanup:401{402if (params_item.data)403env->ReleaseByteArrayElements(encodedParams,404(jbyte *) params_item.data, JNI_ABORT);405406if (pubKey.publicValue.data)407env->ReleaseByteArrayElements(publicKey,408(jbyte *) pubKey.publicValue.data, JNI_ABORT);409410if (ecparams)411FreeECParams(ecparams, true);412413if (pSignedDigestBuffer)414delete [] pSignedDigestBuffer;415416if (pDigestBuffer)417delete [] pDigestBuffer;418}419420return isValid;421}422423/*424* Class: sun_security_ec_ECDHKeyAgreement425* Method: deriveKey426* Signature: ([B[B[B)[B427*/428JNIEXPORT jbyteArray429JNICALL Java_sun_security_ec_ECDHKeyAgreement_deriveKey430(JNIEnv *env, jclass clazz, jbyteArray privateKey, jbyteArray publicKey, jbyteArray encodedParams)431{432jbyteArray jSecret = NULL;433ECParams *ecparams = NULL;434SECItem privateValue_item;435privateValue_item.data = NULL;436SECItem publicValue_item;437publicValue_item.data = NULL;438SECKEYECParams params_item;439params_item.data = NULL;440441// Extract private key value442privateValue_item.len = env->GetArrayLength(privateKey);443privateValue_item.data =444(unsigned char *) env->GetByteArrayElements(privateKey, 0);445if (privateValue_item.data == NULL) {446goto cleanup;447}448449// Extract public key value450publicValue_item.len = env->GetArrayLength(publicKey);451publicValue_item.data =452(unsigned char *) env->GetByteArrayElements(publicKey, 0);453if (publicValue_item.data == NULL) {454goto cleanup;455}456457// Initialize the ECParams struct458params_item.len = env->GetArrayLength(encodedParams);459params_item.data =460(unsigned char *) env->GetByteArrayElements(encodedParams, 0);461if (params_item.data == NULL) {462goto cleanup;463}464465// Fill a new ECParams using the supplied OID466if (EC_DecodeParams(¶ms_item, &ecparams, 0) != SECSuccess) {467/* bad curve OID */468ThrowException(env, INVALID_ALGORITHM_PARAMETER_EXCEPTION);469goto cleanup;470}471472// Prepare a buffer for the secret473SECItem secret_item;474secret_item.data = NULL;475secret_item.len = ecparams->order.len * 2;476477if (ECDH_Derive(&publicValue_item, ecparams, &privateValue_item, B_FALSE,478&secret_item, 0) != SECSuccess) {479ThrowException(env, ILLEGAL_STATE_EXCEPTION);480goto cleanup;481}482483// Create new byte array484jSecret = env->NewByteArray(secret_item.len);485if (jSecret == NULL) {486goto cleanup;487}488489// Copy bytes from the SECItem buffer to a Java byte array490env->SetByteArrayRegion(jSecret, 0, secret_item.len,491(jbyte *)secret_item.data);492493// Free the SECItem data buffer494SECITEM_FreeItem(&secret_item, B_FALSE);495496cleanup:497{498if (privateValue_item.data)499env->ReleaseByteArrayElements(privateKey,500(jbyte *) privateValue_item.data, JNI_ABORT);501502if (publicValue_item.data)503env->ReleaseByteArrayElements(publicKey,504(jbyte *) publicValue_item.data, JNI_ABORT);505506if (params_item.data)507env->ReleaseByteArrayElements(encodedParams,508(jbyte *) params_item.data, JNI_ABORT);509510if (ecparams)511FreeECParams(ecparams, true);512}513514return jSecret;515}516517} /* extern "C" */518519520