/* * 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; }
SECStatus ectest_ecdh_kat(ECDH_KAT *kat) { ECCurveName curve = kat->curve; ECParams ecParams = { 0 }; ECPrivateKey *ecPriv = NULL; SECItem theirKey = { siBuffer, NULL, 0 }; SECStatus rv = SECFailure; PLArenaPool *arena = NULL; SECItem seed = { siBuffer, NULL, 0 }; SECItem answer = { siBuffer, NULL, 0 }; SECItem answer2 = { siBuffer, NULL, 0 }; SECItem derived = { siBuffer, NULL, 0 }; SECItem ecEncodedParams = { siBuffer, NULL, 0 }; int i; arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); if (!arena) { return SECFailure; } rv = SECU_ecName2params(curve, &ecEncodedParams); if (rv != SECSuccess) { goto cleanup; } EC_FillParams(arena, &ecEncodedParams, &ecParams); if (kat->our_pubhex) { SECU_HexString2SECItem(arena, &answer, kat->our_pubhex); } SECU_HexString2SECItem(arena, &seed, kat->privhex); rv = EC_NewKeyFromSeed(&ecParams, &ecPriv, seed.data, seed.len); if (rv != SECSuccess) { rv = SECFailure; goto cleanup; } if (kat->our_pubhex) { if (SECITEM_CompareItem(&answer, &ecPriv->publicValue) != SECEqual) { rv = SECFailure; goto cleanup; } } SECU_HexString2SECItem(arena, &theirKey, kat->their_pubhex); SECU_HexString2SECItem(arena, &answer2, kat->common_key); rv = EC_ValidatePublicKey(&ecParams, &theirKey); if (rv != SECSuccess) { printf("EC_ValidatePublicKey failed\n"); goto cleanup; } for (i = 0; i < kat->iterations; ++i) { rv = ECDH_Derive(&theirKey, &ecParams, &ecPriv->privateValue, PR_TRUE, &derived); if (rv != SECSuccess) { rv = SECFailure; goto cleanup; } rv = SECITEM_CopyItem(ecParams.arena, &theirKey, &ecPriv->privateValue); if (rv != SECSuccess) { goto cleanup; } rv = SECITEM_CopyItem(ecParams.arena, &ecPriv->privateValue, &derived); if (rv != SECSuccess) { goto cleanup; } SECITEM_FreeItem(&derived, PR_FALSE); } if (SECITEM_CompareItem(&answer2, &ecPriv->privateValue) != SECEqual) { printf("expected: "); printBuf(&answer2); printf("derived: "); printBuf(&ecPriv->privateValue); rv = SECFailure; goto cleanup; } cleanup: SECITEM_FreeItem(&ecEncodedParams, PR_FALSE); PORT_FreeArena(arena, PR_FALSE); if (ecPriv) { PORT_FreeArena(ecPriv->ecParams.arena, PR_FALSE); } if (derived.data) { SECITEM_FreeItem(&derived, PR_FALSE); } return rv; }