Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 7 additions & 7 deletions src/main/java/com/ibm/crypto/plus/provider/XDHKeyAgreement.java
Original file line number Diff line number Diff line change
Expand Up @@ -103,13 +103,13 @@ protected Key engineDoPhase(Key key, boolean lastPhase)

try {
int secrectBufferSize = 0;
String curveName = ((NamedParameterSpec) xdhPublicKeyImpl.getParams()).getName();
if (NamedParameterSpec.X25519.getName().equalsIgnoreCase(curveName)) {
secrectBufferSize = SECRET_BUFFER_SIZE_X25519; // X25519 secret buffer size
} else if (NamedParameterSpec.X448.getName().equalsIgnoreCase(curveName)) {
secrectBufferSize = SECRET_BUFFER_SIZE_X448; // X448 secret buffer size
} else {
secrectBufferSize = 0; // Let OCK decide the size
if (System.getProperty("os.name").equals("z/OS")) {
String curveName = ((NamedParameterSpec) xdhPublicKeyImpl.getParams()).getName();
if (NamedParameterSpec.X25519.getName().equalsIgnoreCase(curveName)) {
secrectBufferSize = SECRET_BUFFER_SIZE_X25519; // X25519 secret buffer size
} else if (NamedParameterSpec.X448.getName().equalsIgnoreCase(curveName)) {
secrectBufferSize = SECRET_BUFFER_SIZE_X448; // X448 secret buffer size
}
}
this.secret = XECKey.computeECDHSecret(genCtx,
ockXecKeyPub.getPKeyId(), ockXecKeyPriv.getPKeyId(), secrectBufferSize, provider);
Expand Down
114 changes: 78 additions & 36 deletions src/main/native/ock/ECKey.c
Original file line number Diff line number Diff line change
Expand Up @@ -2233,6 +2233,7 @@ Java_com_ibm_crypto_plus_provider_ock_NativeOCKImplementation_XECKEY_1computeECD
jbyteArray secretBytes = NULL;
unsigned char *secretBytesNative = NULL;
jboolean isCopy = 0;
size_t required_len = 0;
size_t secret_key_len = 0;
int rc = 0;

Expand All @@ -2244,56 +2245,97 @@ Java_com_ibm_crypto_plus_provider_ock_NativeOCKImplementation_XECKEY_1computeECD
NULL); /* Set private key */
if (NULL == gen_ctx) {
throwOCKException(env, 0, "NULL from ICC_EVP_PKEY_CTX_new");
goto cleanup;
}

rc = ICC_EVP_PKEY_derive_init(ockCtx, gen_ctx);
if (ICC_OSSL_SUCCESS != rc) {
throwOCKException(env, 0, "ICC_EVP_PKEY_derive_init failed");
goto cleanup;
}

rc = ICC_EVP_PKEY_derive_set_peer(ockCtx, gen_ctx, ockPubXecKey); /* Set public key */
if (ICC_OSSL_SUCCESS != rc) {
throwOCKException(env, 0, "ICC_EVP_PKEY_derive_set_peer failed");
goto cleanup;
}

if (secretBufferSize > 0) {
/*
* On z/OS, querying the required secret size may not work properly.
* In that case, use the caller-provided secretBufferSize as the
* expected derived secret size.
*/
required_len = (size_t) secretBufferSize;
} else {
ICC_EVP_PKEY_derive_init(ockCtx, gen_ctx);
ICC_EVP_PKEY_derive_set_peer(ockCtx, gen_ctx,
ockPubXecKey); /* Set public key */
if (secretBufferSize > 0) {
secret_key_len = secretBufferSize;
} else {
ICC_EVP_PKEY_derive(ockCtx, gen_ctx, NULL,
&secret_key_len); /* Get secret key size */
/*
* Query the required secret size before deriving the secret.
* This avoids deriving into a buffer with an incorrect size.
*/
rc = ICC_EVP_PKEY_derive(ockCtx, gen_ctx, NULL, &required_len); /* Get secret key size */
if (ICC_OSSL_SUCCESS != rc) {
throwOCKException(env, 0,
"ICC_EVP_PKEY_derive failed to get secret size");
goto cleanup;
}
secretBytes = (*env)->NewByteArray(
env, secret_key_len); /* Create Java secret bytes array with size */
if (NULL == secretBytes) {
throwOCKException(env, 0, "NewByteArray failed");
} else {
secretBytesNative =
(unsigned char *)((*env)->GetPrimitiveArrayCritical(
env, secretBytes, &isCopy));
if (NULL == secretBytesNative) {
throwOCKException(env, 0,
"NULL from GetPrimitiveArrayCritical");
} else {
rc = ICC_EVP_PKEY_derive(ockCtx, gen_ctx, secretBytesNative,
&secret_key_len);
if (ICC_OSSL_SUCCESS != rc) {
throwOCKException(
env, 0, "ICC_EVP_PKEY_derive failed to derive a key");
}
ICC_EVP_PKEY_CTX_free(ockCtx, gen_ctx);
(*env)->ReleasePrimitiveArrayCritical(env, secretBytes,
secretBytesNative, 0);
if (debug) {
gslogFunctionExit(functionName);
}
return secretBytes;
}
if (required_len == 0) {
throwOCKException(env, 0, "Derived secret size is zero");
goto cleanup;
}
}
secret_key_len = required_len;

secretBytes = (*env)->NewByteArray(env, secret_key_len); /* Create Java secret bytes array */
if (NULL == secretBytes) {
throwOCKException(env, 0, "NewByteArray failed");
goto cleanup;
}

secretBytesNative = (unsigned char *)(*env)->GetPrimitiveArrayCritical(
env, secretBytes, &isCopy);
if (NULL == secretBytesNative) {
throwOCKException(env, 0, "NULL from GetPrimitiveArrayCritical");
goto cleanup;
}

rc = ICC_EVP_PKEY_derive(ockCtx, gen_ctx, secretBytesNative, &secret_key_len);
if (ICC_OSSL_SUCCESS != rc) {
throwOCKException(env, 0, "ICC_EVP_PKEY_derive failed to derive a key");
goto cleanup;
}

if (secret_key_len != required_len) {
throwOCKException(env, 0,
"Derived secret size does not match required size");
goto cleanup;
}

ICC_EVP_PKEY_CTX_free(ockCtx, gen_ctx);
gen_ctx = NULL;

(*env)->ReleasePrimitiveArrayCritical(env, secretBytes, secretBytesNative, 0);
secretBytesNative = NULL;

if (debug) {
gslogFunctionExit(functionName);
}

return secretBytes;

cleanup:
if (NULL != gen_ctx) {
ICC_EVP_PKEY_CTX_free(ockCtx, gen_ctx);
gen_ctx = NULL;
}

if (NULL != secretBytesNative) {
(*env)->ReleasePrimitiveArrayCritical(env, secretBytes,
secretBytesNative, 0);
(*env)->ReleasePrimitiveArrayCritical(env, secretBytes, secretBytesNative, 0);
secretBytesNative = NULL;
}

if (NULL != secretBytes) {
(*env)->DeleteLocalRef(env, secretBytes);
secretBytes = NULL;
}

if (debug) {
Expand Down
Loading