/* * Class: sun_security_ec_ECKeyPairGenerator * Method: generateECKeyPair * Signature: (I[B[B)[[B */ JNIEXPORT jobjectArray JNICALL Java_sun_security_ec_ECKeyPairGenerator_generateECKeyPair (JNIEnv *env, jclass clazz, jint keySize, jbyteArray encodedParams, jbyteArray seed) { ECPrivateKey *privKey = NULL; // contains both public and private values ECParams *ecparams = NULL; SECKEYECParams params_item; jint jSeedLength; jbyte* pSeedBuffer = NULL; jobjectArray result = NULL; jclass baCls = NULL; jbyteArray jba; // Initialize the ECParams struct params_item.len = env->GetArrayLength(encodedParams); params_item.data = (unsigned char *) env->GetByteArrayElements(encodedParams, 0); if (params_item.data == NULL) { goto cleanup; } // Fill a new ECParams using the supplied OID if (EC_DecodeParams(¶ms_item, &ecparams, 0) != SECSuccess) { /* bad curve OID */ ThrowException(env, INVALID_ALGORITHM_PARAMETER_EXCEPTION); goto cleanup; } // Copy seed from Java to native buffer jSeedLength = env->GetArrayLength(seed); pSeedBuffer = new jbyte[jSeedLength]; env->GetByteArrayRegion(seed, 0, jSeedLength, pSeedBuffer); // Generate the new keypair (using the supplied seed) if (EC_NewKey(ecparams, &privKey, (unsigned char *) pSeedBuffer, jSeedLength, 0) != SECSuccess) { ThrowException(env, KEY_EXCEPTION); goto cleanup; } jboolean isCopy; baCls = env->FindClass("[B"); if (baCls == NULL) { goto cleanup; } result = env->NewObjectArray(2, baCls, NULL); if (result == NULL) { goto cleanup; } jba = getEncodedBytes(env, &(privKey->privateValue)); if (jba == NULL) { result = NULL; goto cleanup; } env->SetObjectArrayElement(result, 0, jba); // big integer if (env->ExceptionCheck()) { // should never happen result = NULL; goto cleanup; } jba = getEncodedBytes(env, &(privKey->publicValue)); if (jba == NULL) { result = NULL; goto cleanup; } env->SetObjectArrayElement(result, 1, jba); // encoded ec point if (env->ExceptionCheck()) { // should never happen result = NULL; goto cleanup; } cleanup: { if (params_item.data) { env->ReleaseByteArrayElements(encodedParams, (jbyte *) params_item.data, JNI_ABORT); } if (ecparams) { FreeECParams(ecparams, true); } if (privKey) { FreeECParams(&privKey->ecParams, false); SECITEM_FreeItem(&privKey->version, B_FALSE); SECITEM_FreeItem(&privKey->privateValue, B_FALSE); SECITEM_FreeItem(&privKey->publicValue, B_FALSE); free(privKey); } if (pSeedBuffer) { delete [] pSeedBuffer; } } return result; }
/* * Class: sun_security_ec_ECDHKeyAgreement * Method: deriveKey * Signature: ([B[B[B)[B */ JNIEXPORT jbyteArray JNICALL Java_sun_security_ec_ECDHKeyAgreement_deriveKey (JNIEnv *env, jclass clazz, jbyteArray privateKey, jbyteArray publicKey, jbyteArray encodedParams) { jbyteArray jSecret = NULL; ECParams *ecparams = NULL; SECItem privateValue_item; privateValue_item.data = NULL; SECItem publicValue_item; publicValue_item.data = NULL; SECKEYECParams params_item; params_item.data = NULL; // Extract private key value privateValue_item.len = env->GetArrayLength(privateKey); privateValue_item.data = (unsigned char *) env->GetByteArrayElements(privateKey, 0); if (privateValue_item.data == NULL) { goto cleanup; } // Extract public key value publicValue_item.len = env->GetArrayLength(publicKey); publicValue_item.data = (unsigned char *) env->GetByteArrayElements(publicKey, 0); if (publicValue_item.data == NULL) { goto cleanup; } // Initialize the ECParams struct params_item.len = env->GetArrayLength(encodedParams); params_item.data = (unsigned char *) env->GetByteArrayElements(encodedParams, 0); if (params_item.data == NULL) { goto cleanup; } // Fill a new ECParams using the supplied OID if (EC_DecodeParams(¶ms_item, &ecparams, 0) != SECSuccess) { /* bad curve OID */ ThrowException(env, INVALID_ALGORITHM_PARAMETER_EXCEPTION); goto cleanup; } // Prepare a buffer for the secret SECItem secret_item; secret_item.data = NULL; secret_item.len = ecparams->order.len * 2; if (ECDH_Derive(&publicValue_item, ecparams, &privateValue_item, B_FALSE, &secret_item, 0) != SECSuccess) { ThrowException(env, ILLEGAL_STATE_EXCEPTION); goto cleanup; } // Create new byte array jSecret = env->NewByteArray(secret_item.len); if (jSecret == NULL) { goto cleanup; } // Copy bytes from the SECItem buffer to a Java byte array env->SetByteArrayRegion(jSecret, 0, secret_item.len, (jbyte *)secret_item.data); // Free the SECItem data buffer SECITEM_FreeItem(&secret_item, B_FALSE); cleanup: { if (privateValue_item.data) env->ReleaseByteArrayElements(privateKey, (jbyte *) privateValue_item.data, JNI_ABORT); if (publicValue_item.data) env->ReleaseByteArrayElements(publicKey, (jbyte *) publicValue_item.data, JNI_ABORT); if (params_item.data) env->ReleaseByteArrayElements(encodedParams, (jbyte *) params_item.data, JNI_ABORT); if (ecparams) FreeECParams(ecparams, true); } return jSecret; }
/* * Class: sun_security_ec_ECDSASignature * Method: signDigest * Signature: ([B[B[B[B)[B */ JNIEXPORT jbyteArray JNICALL Java_sun_security_ec_ECDSASignature_signDigest (JNIEnv *env, jclass clazz, jbyteArray digest, jbyteArray privateKey, jbyteArray encodedParams, jbyteArray seed) { jbyte* pDigestBuffer = NULL; jint jDigestLength = env->GetArrayLength(digest); jbyteArray jSignedDigest = NULL; SECItem signature_item; jbyte* pSignedDigestBuffer = NULL; jbyteArray temp; jint jSeedLength = env->GetArrayLength(seed); jbyte* pSeedBuffer = NULL; // Copy digest from Java to native buffer pDigestBuffer = new jbyte[jDigestLength]; env->GetByteArrayRegion(digest, 0, jDigestLength, pDigestBuffer); SECItem digest_item; digest_item.data = (unsigned char *) pDigestBuffer; digest_item.len = jDigestLength; ECPrivateKey privKey; privKey.privateValue.data = NULL; // Initialize the ECParams struct ECParams *ecparams = NULL; SECKEYECParams params_item; params_item.len = env->GetArrayLength(encodedParams); params_item.data = (unsigned char *) env->GetByteArrayElements(encodedParams, 0); if (params_item.data == NULL) { goto cleanup; } // Fill a new ECParams using the supplied OID if (EC_DecodeParams(¶ms_item, &ecparams, 0) != SECSuccess) { /* bad curve OID */ ThrowException(env, INVALID_ALGORITHM_PARAMETER_EXCEPTION); goto cleanup; } // Extract private key data privKey.ecParams = *ecparams; // struct assignment privKey.privateValue.len = env->GetArrayLength(privateKey); privKey.privateValue.data = (unsigned char *) env->GetByteArrayElements(privateKey, 0); if (privKey.privateValue.data == NULL) { goto cleanup; } // Prepare a buffer for the signature (twice the key length) pSignedDigestBuffer = new jbyte[ecparams->order.len * 2]; signature_item.data = (unsigned char *) pSignedDigestBuffer; signature_item.len = ecparams->order.len * 2; // Copy seed from Java to native buffer pSeedBuffer = new jbyte[jSeedLength]; env->GetByteArrayRegion(seed, 0, jSeedLength, pSeedBuffer); // Sign the digest (using the supplied seed) if (ECDSA_SignDigest(&privKey, &signature_item, &digest_item, (unsigned char *) pSeedBuffer, jSeedLength, 0) != SECSuccess) { ThrowException(env, KEY_EXCEPTION); goto cleanup; } // Create new byte array temp = env->NewByteArray(signature_item.len); if (temp == NULL) { goto cleanup; } // Copy data from native buffer env->SetByteArrayRegion(temp, 0, signature_item.len, pSignedDigestBuffer); jSignedDigest = temp; cleanup: { if (params_item.data) { env->ReleaseByteArrayElements(encodedParams, (jbyte *) params_item.data, JNI_ABORT); } if (privKey.privateValue.data) { env->ReleaseByteArrayElements(privateKey, (jbyte *) privKey.privateValue.data, JNI_ABORT); } if (pDigestBuffer) { delete [] pDigestBuffer; } if (pSignedDigestBuffer) { delete [] pSignedDigestBuffer; } if (pSeedBuffer) { delete [] pSeedBuffer; } if (ecparams) { FreeECParams(ecparams, true); } } return jSignedDigest; }
/* * Class: sun_security_ec_ECDSASignature * Method: verifySignedDigest * Signature: ([B[B[B[B)Z */ JNIEXPORT jboolean JNICALL Java_sun_security_ec_ECDSASignature_verifySignedDigest (JNIEnv *env, jclass clazz, jbyteArray signedDigest, jbyteArray digest, jbyteArray publicKey, jbyteArray encodedParams) { jboolean isValid = false; // Copy signedDigest from Java to native buffer jbyte* pSignedDigestBuffer = NULL; jint jSignedDigestLength = env->GetArrayLength(signedDigest); pSignedDigestBuffer = new jbyte[jSignedDigestLength]; env->GetByteArrayRegion(signedDigest, 0, jSignedDigestLength, pSignedDigestBuffer); SECItem signature_item; signature_item.data = (unsigned char *) pSignedDigestBuffer; signature_item.len = jSignedDigestLength; // Copy digest from Java to native buffer jbyte* pDigestBuffer = NULL; jint jDigestLength = env->GetArrayLength(digest); pDigestBuffer = new jbyte[jDigestLength]; env->GetByteArrayRegion(digest, 0, jDigestLength, pDigestBuffer); SECItem digest_item; digest_item.data = (unsigned char *) pDigestBuffer; digest_item.len = jDigestLength; // Extract public key data ECPublicKey pubKey; pubKey.publicValue.data = NULL; ECParams *ecparams = NULL; SECKEYECParams params_item; // Initialize the ECParams struct params_item.len = env->GetArrayLength(encodedParams); params_item.data = (unsigned char *) env->GetByteArrayElements(encodedParams, 0); if (params_item.data == NULL) { goto cleanup; } // Fill a new ECParams using the supplied OID if (EC_DecodeParams(¶ms_item, &ecparams, 0) != SECSuccess) { /* bad curve OID */ ThrowException(env, INVALID_ALGORITHM_PARAMETER_EXCEPTION); goto cleanup; } pubKey.ecParams = *ecparams; // struct assignment pubKey.publicValue.len = env->GetArrayLength(publicKey); pubKey.publicValue.data = (unsigned char *) env->GetByteArrayElements(publicKey, 0); if (ECDSA_VerifyDigest(&pubKey, &signature_item, &digest_item, 0) != SECSuccess) { goto cleanup; } isValid = true; cleanup: { if (params_item.data) env->ReleaseByteArrayElements(encodedParams, (jbyte *) params_item.data, JNI_ABORT); if (pubKey.publicValue.data) env->ReleaseByteArrayElements(publicKey, (jbyte *) pubKey.publicValue.data, JNI_ABORT); if (ecparams) FreeECParams(ecparams, true); if (pSignedDigestBuffer) delete [] pSignedDigestBuffer; if (pDigestBuffer) delete [] pDigestBuffer; } return isValid; }
static int fips_ecdsa_sign_verify(uint8_t *encodedParams, unsigned int encodedParamsLen, uint8_t *knownSignature, unsigned int knownSignatureLen) { /* ECDSA Known Seed info for curves nistp256 */ static uint8_t ecdsa_Known_Seed[] = { 0x6a, 0x9b, 0xf6, 0xf7, 0xce, 0xed, 0x79, 0x11, 0xf0, 0xc7, 0xc8, 0x9a, 0xa5, 0xd1, 0x57, 0xb1, 0x7b, 0x5a, 0x3b, 0x76, 0x4e, 0x7b, 0x7c, 0xbc, 0xf2, 0x76, 0x1c, 0x1c, 0x7f, 0xc5, 0x53, 0x2f }; static uint8_t msg[] = { "Sun Microsystems Solaris is awesome!" }; unsigned char sha1[SHA1_DIGEST_SIZE]; /* SHA-1 hash (160 bits) */ unsigned char sig[2*MAX_ECKEY_LEN]; SECItem signature, digest; SECItem encodedparams; ECParams *ecparams = NULL; ECPrivateKey *ecdsa_private_key = NULL; ECPublicKey ecdsa_public_key; SECStatus ecdsaStatus = SECSuccess; SHA1_CTX *sha1_context = NULL; int rv = CKR_DEVICE_ERROR; (void) memset(&ecdsa_public_key, 0, sizeof (ECPublicKey)); /* construct the ECDSA private/public key pair */ encodedparams.type = siBuffer; encodedparams.data = (unsigned char *) encodedParams; encodedparams.len = encodedParamsLen; if (EC_DecodeParams(&encodedparams, &ecparams, 0) != SECSuccess) { return (CKR_ARGUMENTS_BAD); } /* * Generates a new EC key pair. The private key is a supplied * random value (in seed) and the public key is the result of * performing a scalar point multiplication of that value with * the curve's base point. */ ecdsaStatus = ec_NewKey(ecparams, &ecdsa_private_key, ecdsa_Known_Seed, sizeof (ecdsa_Known_Seed), 0); if (ecdsaStatus != SECSuccess) { goto loser; } /* construct public key from private key. */ ecdsaStatus = EC_CopyParams(ecdsa_private_key->ecParams.arena, &ecdsa_public_key.ecParams, &ecdsa_private_key->ecParams); if (ecdsaStatus != SECSuccess) { goto loser; } ecdsa_public_key.publicValue = ecdsa_private_key->publicValue; /* validate public key value */ ecdsaStatus = EC_ValidatePublicKey(&ecdsa_public_key.ecParams, &ecdsa_public_key.publicValue, 0); if (ecdsaStatus != SECSuccess) { goto loser; } /* validate public key value */ ecdsaStatus = EC_ValidatePublicKey(&ecdsa_private_key->ecParams, &ecdsa_private_key->publicValue, 0); if (ecdsaStatus != SECSuccess) { goto loser; } /* * ECDSA Known Answer Signature Test. */ #ifdef _KERNEL if ((sha1_context = kmem_zalloc(sizeof (SHA1_CTX), KM_SLEEP)) == NULL) { #else if ((sha1_context = malloc(sizeof (SHA1_CTX))) == NULL) { #endif ecdsaStatus = SECFailure; rv = CKR_HOST_MEMORY; goto loser; } SHA1Init(sha1_context); #ifdef __sparcv9 SHA1Update(sha1_context, msg, (uint_t)sizeof (msg)); #else /* !__sparcv9 */ SHA1Update(sha1_context, msg, sizeof (msg)); #endif /* __sparcv9 */ SHA1Final(sha1, sha1_context); digest.type = siBuffer; digest.data = sha1; digest.len = SHA1_DIGEST_SIZE; (void) memset(sig, 0, sizeof (sig)); signature.type = siBuffer; signature.data = sig; signature.len = sizeof (sig); ecdsaStatus = ECDSA_SignDigestWithSeed(ecdsa_private_key, &signature, &digest, ecdsa_Known_Seed, sizeof (ecdsa_Known_Seed), 0); if (ecdsaStatus != SECSuccess) { goto loser; } if ((signature.len != knownSignatureLen) || (memcmp(signature.data, knownSignature, knownSignatureLen) != 0)) { ecdsaStatus = SECFailure; goto loser; } /* * ECDSA Known Answer Verification Test. */ ecdsaStatus = ECDSA_VerifyDigest(&ecdsa_public_key, &signature, &digest, 0); loser: if (ecdsa_public_key.publicValue.data != NULL) free_ecpubkey(&ecdsa_public_key); if (ecdsa_private_key != NULL) free_ecprivkey(ecdsa_private_key); free_ecparams(ecparams, B_TRUE); if (sha1_context != NULL) #ifdef _KERNEL kmem_free(sha1_context, sizeof (SHA1_CTX)); #else free(sha1_context); #endif if (ecdsaStatus != SECSuccess) { return (rv); } return (CKR_OK); } int fips_ecdsa_post() { /* ECDSA Known curve nistp256 == SEC_OID_SECG_EC_SECP256R1 params */ static uint8_t ecdsa_known_P256_EncodedParams[] = { 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07 }; static uint8_t ecdsa_known_P256_signature[] = { 0x07, 0xb1, 0xcb, 0x57, 0x20, 0xa7, 0x10, 0xd6, 0x9d, 0x37, 0x4b, 0x1c, 0xdc, 0x35, 0x90, 0xff, 0x1a, 0x2d, 0x98, 0x95, 0x1b, 0x2f, 0xeb, 0x7f, 0xbb, 0x81, 0xca, 0xc0, 0x69, 0x75, 0xea, 0xc5, 0x2b, 0xdb, 0x86, 0x76, 0xe7, 0x32, 0xba, 0x13, 0x03, 0x7f, 0x7f, 0x92, 0x77, 0xd8, 0x35, 0xfe, 0x99, 0xb4, 0xb7, 0x85, 0x5a, 0xfb, 0xfb, 0xce, 0x5d, 0x0e, 0xbc, 0x01, 0xfa, 0x44, 0x97, 0x7e }; int rv; /* ECDSA GF(p) prime field curve test */ rv = fips_ecdsa_sign_verify(ecdsa_known_P256_EncodedParams, sizeof (ecdsa_known_P256_EncodedParams), ecdsa_known_P256_signature, sizeof (ecdsa_known_P256_signature)); if (rv != CKR_OK) { return (CKR_DEVICE_ERROR); } return (CKR_OK); } static void free_ecparams(ECParams *params, boolean_t freeit) { SECITEM_FreeItem(¶ms->fieldID.u.prime, B_FALSE); SECITEM_FreeItem(¶ms->curve.a, B_FALSE); SECITEM_FreeItem(¶ms->curve.b, B_FALSE); SECITEM_FreeItem(¶ms->curve.seed, B_FALSE); SECITEM_FreeItem(¶ms->base, B_FALSE); SECITEM_FreeItem(¶ms->order, B_FALSE); SECITEM_FreeItem(¶ms->DEREncoding, B_FALSE); SECITEM_FreeItem(¶ms->curveOID, B_FALSE); if (freeit) #ifdef _KERNEL kmem_free(params, sizeof (ECParams)); #else free(params); #endif }