diff --git a/cc/crypto/client_encryptor.cc b/cc/crypto/client_encryptor.cc index a38238cbfc1..89fb32ac0a9 100644 --- a/cc/crypto/client_encryptor.cc +++ b/cc/crypto/client_encryptor.cc @@ -44,13 +44,16 @@ absl::StatusOr> ClientEncryptor::Create( absl::StatusOr ClientEncryptor::Encrypt(absl::string_view plaintext, absl::string_view associated_data) { // Encrypt request. - absl::StatusOr ciphertext = sender_context_->Seal(plaintext, associated_data); + const std::vector nonce = sender_context_->GenerateNonce(); + absl::StatusOr ciphertext = sender_context_->Seal(nonce, plaintext, associated_data); if (!ciphertext.ok()) { return ciphertext.status(); } // Create request message. EncryptedRequest encrypted_request; + *encrypted_request.mutable_encrypted_message()->mutable_nonce() = + std::string(nonce.begin(), nonce.end()); *encrypted_request.mutable_encrypted_message()->mutable_ciphertext() = *ciphertext; *encrypted_request.mutable_encrypted_message()->mutable_associated_data() = associated_data; diff --git a/cc/crypto/hpke/jni/com_google_oak_crypto_hpke_RecipientContext.h b/cc/crypto/hpke/jni/com_google_oak_crypto_hpke_RecipientContext.h index a03012a15d6..f51482ec4a3 100644 --- a/cc/crypto/hpke/jni/com_google_oak_crypto_hpke_RecipientContext.h +++ b/cc/crypto/hpke/jni/com_google_oak_crypto_hpke_RecipientContext.h @@ -7,6 +7,14 @@ #ifdef __cplusplus extern "C" { #endif +/* + * Class: com_google_oak_crypto_hpke_RecipientContext + * Method: nativeGenerateNonce + * Signature: ()[B + */ +JNIEXPORT jbyteArray JNICALL Java_com_google_oak_crypto_hpke_RecipientContext_nativeGenerateNonce + (JNIEnv *, jobject); + /* * Class: com_google_oak_crypto_hpke_RecipientContext * Method: nativeOpen @@ -18,10 +26,10 @@ JNIEXPORT jbyteArray JNICALL Java_com_google_oak_crypto_hpke_RecipientContext_na /* * Class: com_google_oak_crypto_hpke_RecipientContext * Method: nativeSeal - * Signature: ([B[B)[B + * Signature: ([B[B[B)[B */ JNIEXPORT jbyteArray JNICALL Java_com_google_oak_crypto_hpke_RecipientContext_nativeSeal - (JNIEnv *, jobject, jbyteArray, jbyteArray); + (JNIEnv *, jobject, jbyteArray, jbyteArray, jbyteArray); /* * Class: com_google_oak_crypto_hpke_RecipientContext diff --git a/cc/crypto/hpke/jni/com_google_oak_crypto_hpke_SenderContext.h b/cc/crypto/hpke/jni/com_google_oak_crypto_hpke_SenderContext.h index 613a3cee5d7..6826c49bddb 100644 --- a/cc/crypto/hpke/jni/com_google_oak_crypto_hpke_SenderContext.h +++ b/cc/crypto/hpke/jni/com_google_oak_crypto_hpke_SenderContext.h @@ -7,13 +7,21 @@ #ifdef __cplusplus extern "C" { #endif +/* + * Class: com_google_oak_crypto_hpke_SenderContext + * Method: nativeGenerateNonce + * Signature: ()[B + */ +JNIEXPORT jbyteArray JNICALL Java_com_google_oak_crypto_hpke_SenderContext_nativeGenerateNonce + (JNIEnv *, jobject); + /* * Class: com_google_oak_crypto_hpke_SenderContext * Method: nativeSeal - * Signature: ([B[B)[B + * Signature: ([B[B[B)[B */ JNIEXPORT jbyteArray JNICALL Java_com_google_oak_crypto_hpke_SenderContext_nativeSeal - (JNIEnv *, jobject, jbyteArray, jbyteArray); + (JNIEnv *, jobject, jbyteArray, jbyteArray, jbyteArray); /* * Class: com_google_oak_crypto_hpke_SenderContext diff --git a/cc/crypto/hpke/jni/context_jni.cc b/cc/crypto/hpke/jni/context_jni.cc index 8d34dee19fb..788e970984c 100644 --- a/cc/crypto/hpke/jni/context_jni.cc +++ b/cc/crypto/hpke/jni/context_jni.cc @@ -21,12 +21,30 @@ #include "com_google_oak_crypto_hpke_SenderContext.h" #include "jni_helper.h" +JNIEXPORT jbyteArray JNICALL +Java_com_google_oak_crypto_hpke_SenderContext_nativeGenerateNonce(JNIEnv* env, jobject obj) { + jclass sender_context_class = env->GetObjectClass(obj); + jfieldID fid = env->GetFieldID(sender_context_class, "nativePtr", "J"); + oak::crypto::SenderContext* sender_context = + (oak::crypto::SenderContext*)(env->GetLongField(obj, fid)); + if (sender_context == NULL) { + return {}; + } + + std::vector nonce = sender_context->GenerateNonce(); + + jbyteArray ret = env->NewByteArray(nonce.size()); + env->SetByteArrayRegion(ret, 0, nonce.size(), reinterpret_cast(&nonce.front())); + return ret; +} + JNIEXPORT jbyteArray JNICALL Java_com_google_oak_crypto_hpke_SenderContext_nativeSeal( - JNIEnv* env, jobject obj, jbyteArray plaintext, jbyteArray associated_data) { - if (plaintext == NULL || associated_data == NULL) { + JNIEnv* env, jobject obj, jbyteArray nonce, jbyteArray plaintext, jbyteArray associated_data) { + if (nonce == NULL || plaintext == NULL || associated_data == NULL) { return {}; } + std::string nonce_str = convert_jbytearray_to_string(env, nonce); std::string plaintext_str = convert_jbytearray_to_string(env, plaintext); std::string associated_data_str = convert_jbytearray_to_string(env, associated_data); @@ -38,7 +56,9 @@ JNIEXPORT jbyteArray JNICALL Java_com_google_oak_crypto_hpke_SenderContext_nativ return {}; } - absl::StatusOr result = sender_context->Seal(plaintext_str, associated_data_str); + const std::vector nonce_bytes(nonce_str.begin(), nonce_str.end()); + absl::StatusOr result = + sender_context->Seal(nonce_bytes, plaintext_str, associated_data_str); if (!result.ok()) { return {}; } @@ -77,6 +97,23 @@ JNIEXPORT jbyteArray JNICALL Java_com_google_oak_crypto_hpke_SenderContext_nativ return ret; } +JNIEXPORT jbyteArray JNICALL +Java_com_google_oak_crypto_hpke_RecipientContext_nativeGenerateNonce(JNIEnv* env, jobject obj) { + jclass recipient_context_class = env->GetObjectClass(obj); + jfieldID fid = env->GetFieldID(recipient_context_class, "nativePtr", "J"); + oak::crypto::RecipientContext* recipient_context = + (oak::crypto::RecipientContext*)(env->GetLongField(obj, fid)); + if (recipient_context == NULL) { + return {}; + } + + std::vector nonce = recipient_context->GenerateNonce(); + + jbyteArray ret = env->NewByteArray(nonce.size()); + env->SetByteArrayRegion(ret, 0, nonce.size(), reinterpret_cast(&nonce.front())); + return ret; +} + JNIEXPORT jbyteArray JNICALL Java_com_google_oak_crypto_hpke_RecipientContext_nativeOpen( JNIEnv* env, jobject obj, jbyteArray ciphertext, jbyteArray associated_data) { if (ciphertext == NULL || associated_data == NULL) { @@ -106,11 +143,12 @@ JNIEXPORT jbyteArray JNICALL Java_com_google_oak_crypto_hpke_RecipientContext_na } JNIEXPORT jbyteArray JNICALL Java_com_google_oak_crypto_hpke_RecipientContext_nativeSeal( - JNIEnv* env, jobject obj, jbyteArray plaintext, jbyteArray associated_data) { - if (plaintext == NULL || associated_data == NULL) { + JNIEnv* env, jobject obj, jbyteArray nonce, jbyteArray plaintext, jbyteArray associated_data) { + if (nonce == NULL || plaintext == NULL || associated_data == NULL) { return {}; } + std::string nonce_str = convert_jbytearray_to_string(env, nonce); std::string plaintext_str = convert_jbytearray_to_string(env, plaintext); std::string associated_data_str = convert_jbytearray_to_string(env, associated_data); @@ -122,7 +160,9 @@ JNIEXPORT jbyteArray JNICALL Java_com_google_oak_crypto_hpke_RecipientContext_na return {}; } - absl::StatusOr result = recipient_context->Seal(plaintext_str, associated_data_str); + const std::vector nonce_bytes(nonce_str.begin(), nonce_str.end()); + absl::StatusOr result = + recipient_context->Seal(nonce_bytes, plaintext_str, associated_data_str); if (!result.ok()) { return {}; } diff --git a/cc/crypto/hpke/jni/jni_helper.cc b/cc/crypto/hpke/jni/jni_helper.cc index e1aa956380c..acd67d1929f 100644 --- a/cc/crypto/hpke/jni/jni_helper.cc +++ b/cc/crypto/hpke/jni/jni_helper.cc @@ -13,8 +13,20 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + #include "cc/crypto/hpke/jni/jni_helper.h" +#include +#include +#include + +// std::unique_ptr convert_jbytearray_to_array(JNIEnv* env, jbyteArray arr) { +// int len = env->GetArrayLength(arr); +// char* buf = new char[len]; +// std::unique_ptr buf_uptr(buf); +// return buf_uptr; +// } + std::string convert_jbytearray_to_string(JNIEnv* env, jbyteArray arr) { int len = env->GetArrayLength(arr); char* buf = new char[len]; @@ -22,4 +34,13 @@ std::string convert_jbytearray_to_string(JNIEnv* env, jbyteArray arr) { env->GetByteArrayRegion(arr, 0, len, reinterpret_cast(buf)); std::string result(buf, len); return result; -} \ No newline at end of file +} + +// std::vector convert_jbytearray_to_vector(JNIEnv* env, jbyteArray arr) { +// int len = env->GetArrayLength(arr); +// char* buf = new char[len]; +// std::unique_ptr buf_uptr(buf); +// env->GetByteArrayRegion(arr, 0, len, reinterpret_cast(buf)); +// std::vector result{buf, len}; +// return result; +// } diff --git a/cc/crypto/hpke/recipient_context.cc b/cc/crypto/hpke/recipient_context.cc index 356a500cfce..50609464c03 100644 --- a/cc/crypto/hpke/recipient_context.cc +++ b/cc/crypto/hpke/recipient_context.cc @@ -113,6 +113,11 @@ absl::StatusOr> RecipientContext::Deserialize( /* response_sequence_number= */ serialized_recipient_context.response_sequence_number()); } +std::vector RecipientContext::GenerateNonce() { + std::vector nonce = CalculateNonce(response_base_nonce_, response_sequence_number_); + return nonce; +} + absl::StatusOr RecipientContext::Open(absl::string_view ciphertext, absl::string_view associated_data) { /// Maximum sequence number which can fit in kAeadNonceSizeBytes bytes. @@ -132,14 +137,14 @@ absl::StatusOr RecipientContext::Open(absl::string_view ciphertext, return plaintext; } -absl::StatusOr RecipientContext::Seal(absl::string_view plaintext, +absl::StatusOr RecipientContext::Seal(const std::vector& nonce, + absl::string_view plaintext, absl::string_view associated_data) { /// Maximum sequence number which can fit in kAeadNonceSizeBytes bytes. /// if (response_sequence_number_ == UINT64_MAX) { return absl::OutOfRangeError("Maximum sequence number reached"); } - std::vector nonce = CalculateNonce(response_base_nonce_, response_sequence_number_); absl::StatusOr ciphertext = AeadSeal(response_aead_context_.get(), nonce, plaintext, associated_data); diff --git a/cc/crypto/hpke/recipient_context.h b/cc/crypto/hpke/recipient_context.h index ec4ef6dbe21..7493a093bc1 100644 --- a/cc/crypto/hpke/recipient_context.h +++ b/cc/crypto/hpke/recipient_context.h @@ -52,6 +52,8 @@ class RecipientContext { static absl::StatusOr> Deserialize( ::oak::crypto::v1::CryptoContext serialized_recipient_context); + std::vector GenerateNonce(); + // Decrypts message and validates associated data using AEAD. // absl::StatusOr Open(absl::string_view ciphertext, absl::string_view associated_data); @@ -59,7 +61,8 @@ class RecipientContext { // Encrypts response message with associated data using AEAD as part of bidirectional // communication. // - absl::StatusOr Seal(absl::string_view plaintext, absl::string_view associated_data); + absl::StatusOr Seal(const std::vector& nonce, absl::string_view plaintext, + absl::string_view associated_data); ~RecipientContext(); diff --git a/cc/crypto/hpke/recipient_context_test.cc b/cc/crypto/hpke/recipient_context_test.cc index d46ff72f5f3..bf1bac0ac91 100644 --- a/cc/crypto/hpke/recipient_context_test.cc +++ b/cc/crypto/hpke/recipient_context_test.cc @@ -126,7 +126,8 @@ TEST_F(RecipientContextTest, RecipientContextOpenSuccess) { std::string plaintext = "Hello World"; - auto ciphertext = (*sender_context)->Seal(plaintext, associated_data_request_); + const std::vector nonce = (*sender_context)->GenerateNonce(); + auto ciphertext = (*sender_context)->Seal(nonce, plaintext, associated_data_request_); ASSERT_TRUE(ciphertext.ok()); std::string encap_public_key = (*sender_context)->GetSerializedEncapsulatedPublicKey(); @@ -145,7 +146,8 @@ TEST_F(RecipientContextTest, RecipientRequestContextOpenFailure) { std::string plaintext = "Hello World"; - auto ciphertext = (*sender_context)->Seal(plaintext, associated_data_request_); + const std::vector nonce = (*sender_context)->GenerateNonce(); + auto ciphertext = (*sender_context)->Seal(nonce, plaintext, associated_data_request_); ASSERT_TRUE(ciphertext.ok()); std::string edited_ciphertext = absl::StrCat(*ciphertext, "no!"); @@ -165,7 +167,8 @@ TEST_F(RecipientContextTest, RecipientResponseContextSealSuccess) { std::string plaintext = "Hello World"; - auto ciphertext = (*recipient_context)->Seal(plaintext, associated_data_response_); + const std::vector nonce = (*recipient_context)->GenerateNonce(); + auto ciphertext = (*recipient_context)->Seal(nonce, plaintext, associated_data_response_); ASSERT_TRUE(ciphertext.ok()); EXPECT_THAT(plaintext, StrNe(*ciphertext)); } @@ -176,7 +179,8 @@ TEST_F(RecipientContextTest, RecipientResponseContextSealFailure) { std::string empty_plaintext = ""; - auto ciphertext = (*recipient_context)->Seal(empty_plaintext, associated_data_response_); + const std::vector nonce = (*recipient_context)->GenerateNonce(); + auto ciphertext = (*recipient_context)->Seal(nonce, empty_plaintext, associated_data_response_); EXPECT_FALSE(ciphertext.ok()); EXPECT_EQ(ciphertext.status().code(), absl::StatusCode::kInvalidArgument); } diff --git a/cc/crypto/hpke/sender_context.cc b/cc/crypto/hpke/sender_context.cc index 76cff6b5d27..046ab66553d 100644 --- a/cc/crypto/hpke/sender_context.cc +++ b/cc/crypto/hpke/sender_context.cc @@ -32,14 +32,19 @@ namespace oak::crypto { const uint64_t kStartingSequenceNumber = 0; -absl::StatusOr SenderContext::Seal(absl::string_view plaintext, +std::vector SenderContext::GenerateNonce() { + std::vector nonce = CalculateNonce(request_base_nonce_, request_sequence_number_); + return nonce; +} + +absl::StatusOr SenderContext::Seal(const std::vector& nonce, + absl::string_view plaintext, absl::string_view associated_data) { /// Maximum sequence number which can fit in kAeadNonceSizeBytes bytes. /// if (request_sequence_number_ == UINT64_MAX) { return absl::OutOfRangeError("Maximum sequence number reached"); } - std::vector nonce = CalculateNonce(request_base_nonce_, request_sequence_number_); absl::StatusOr ciphertext = AeadSeal(request_aead_context_.get(), nonce, plaintext, associated_data); diff --git a/cc/crypto/hpke/sender_context.h b/cc/crypto/hpke/sender_context.h index 2862d72ef45..e0d07b6d69e 100644 --- a/cc/crypto/hpke/sender_context.h +++ b/cc/crypto/hpke/sender_context.h @@ -50,9 +50,12 @@ class SenderContext { return serialized_encapsulated_public_key_; } + std::vector GenerateNonce(); + // Encrypts message with associated data using AEAD. // - absl::StatusOr Seal(absl::string_view plaintext, absl::string_view associated_data); + absl::StatusOr Seal(const std::vector& nonce, absl::string_view plaintext, + absl::string_view associated_data); // Decrypts response message and validates associated data using AEAD as part of // bidirectional communication. diff --git a/cc/crypto/hpke/sender_context_test.cc b/cc/crypto/hpke/sender_context_test.cc index 22a4c3c5881..65855def06e 100644 --- a/cc/crypto/hpke/sender_context_test.cc +++ b/cc/crypto/hpke/sender_context_test.cc @@ -91,8 +91,9 @@ TEST_F(SenderContextTest, SenderSealsMessageSuccess) { std::string plaintext = "Hello World"; + const std::vector nonce = (*sender_context)->GenerateNonce(); absl::StatusOr encrypted_request = - (*sender_context)->Seal(plaintext, associated_data_request_); + (*sender_context)->Seal(nonce, plaintext, associated_data_request_); EXPECT_TRUE(encrypted_request.ok()); EXPECT_THAT(*encrypted_request, StrNe(plaintext)); } diff --git a/cc/crypto/server_encryptor.cc b/cc/crypto/server_encryptor.cc index 525e0e61a2d..bf34132ec9f 100644 --- a/cc/crypto/server_encryptor.cc +++ b/cc/crypto/server_encryptor.cc @@ -62,13 +62,17 @@ absl::StatusOr ServerEncryptor::Encrypt(absl::string_view pla } // Encrypt response. - absl::StatusOr ciphertext = recipient_context_->Seal(plaintext, associated_data); + const std::vector nonce = recipient_context_->GenerateNonce(); + absl::StatusOr ciphertext = + recipient_context_->Seal(nonce, plaintext, associated_data); if (!ciphertext.ok()) { return ciphertext.status(); } // Create response message. EncryptedResponse encrypted_response; + *encrypted_response.mutable_encrypted_message()->mutable_nonce() = + std::string(nonce.begin(), nonce.end()); *encrypted_response.mutable_encrypted_message()->mutable_ciphertext() = *ciphertext; *encrypted_response.mutable_encrypted_message()->mutable_associated_data() = associated_data; diff --git a/java/src/main/java/com/google/oak/crypto/ClientEncryptor.java b/java/src/main/java/com/google/oak/crypto/ClientEncryptor.java index da492bde5e5..5ccc7da409f 100644 --- a/java/src/main/java/com/google/oak/crypto/ClientEncryptor.java +++ b/java/src/main/java/com/google/oak/crypto/ClientEncryptor.java @@ -82,24 +82,26 @@ private ClientEncryptor(SenderContext senderContext) { public final Result encrypt( final byte[] plaintext, final byte[] associatedData) { // Encrypt request. - return senderContext.seal(plaintext, associatedData).map(ciphertext -> { - // Create request message. - EncryptedRequest.Builder encryptedRequestBuilder = - EncryptedRequest.newBuilder().setEncryptedMessage( - AeadEncryptedMessage.newBuilder() - .setCiphertext(ByteString.copyFrom(ciphertext)) - .setAssociatedData(ByteString.copyFrom(associatedData)) - .build()); + return senderContext.generateNonce().andThen( + nonce -> senderContext.seal(nonce, plaintext, associatedData).map(ciphertext -> { + // Create request message. + EncryptedRequest.Builder encryptedRequestBuilder = + EncryptedRequest.newBuilder().setEncryptedMessage( + AeadEncryptedMessage.newBuilder() + .setNonce(ByteString.copyFrom(nonce)) + .setCiphertext(ByteString.copyFrom(ciphertext)) + .setAssociatedData(ByteString.copyFrom(associatedData)) + .build()); - // Encapsulated public key is only sent in the initial request message of the session. - if (!serializedEncapsulatedPublicKeyHasBeenSent) { - encryptedRequestBuilder.setSerializedEncapsulatedPublicKey( - ByteString.copyFrom(senderContext.getSerializedEncapsulatedPublicKey())); - serializedEncapsulatedPublicKeyHasBeenSent = true; - } + // Encapsulated public key is only sent in the initial request message of the session. + if (!serializedEncapsulatedPublicKeyHasBeenSent) { + encryptedRequestBuilder.setSerializedEncapsulatedPublicKey( + ByteString.copyFrom(senderContext.getSerializedEncapsulatedPublicKey())); + serializedEncapsulatedPublicKeyHasBeenSent = true; + } - return encryptedRequestBuilder.build(); - }); + return encryptedRequestBuilder.build(); + })); } /** diff --git a/java/src/main/java/com/google/oak/crypto/ServerEncryptor.java b/java/src/main/java/com/google/oak/crypto/ServerEncryptor.java index 94809bd427e..fad4ed29421 100644 --- a/java/src/main/java/com/google/oak/crypto/ServerEncryptor.java +++ b/java/src/main/java/com/google/oak/crypto/ServerEncryptor.java @@ -120,15 +120,18 @@ public final Result encrypt( } // Encrypt response. - return recipientContext.get() - .seal(plaintext, associatedData) - // Create response message. - .map(ciphertext - -> EncryptedResponse.newBuilder() - .setEncryptedMessage(AeadEncryptedMessage.newBuilder() - .setCiphertext(ByteString.copyFrom(ciphertext)) - .setAssociatedData(ByteString.copyFrom(associatedData)) - .build()) - .build()); + return recipientContext.get().generateNonce().andThen(nonce + -> recipientContext.get() + .seal(nonce, plaintext, associatedData) + // Create response message. + .map(ciphertext + -> EncryptedResponse.newBuilder() + .setEncryptedMessage( + AeadEncryptedMessage.newBuilder() + .setNonce(ByteString.copyFrom(nonce)) + .setCiphertext(ByteString.copyFrom(ciphertext)) + .setAssociatedData(ByteString.copyFrom(associatedData)) + .build()) + .build())); } } diff --git a/java/src/main/java/com/google/oak/crypto/hpke/RecipientContext.java b/java/src/main/java/com/google/oak/crypto/hpke/RecipientContext.java index fa01f87b2f4..d3e45f1e416 100644 --- a/java/src/main/java/com/google/oak/crypto/hpke/RecipientContext.java +++ b/java/src/main/java/com/google/oak/crypto/hpke/RecipientContext.java @@ -27,10 +27,24 @@ public RecipientContext(long nativePtr) { this.nativePtr = nativePtr; } + private native byte[] nativeGenerateNonce(); private native byte[] nativeOpen(final byte[] ciphertext, final byte[] associatedData); - private native byte[] nativeSeal(final byte[] plaintext, final byte[] associatedData); + private native byte[] nativeSeal( + final byte[] nonce, final byte[] plaintext, final byte[] associatedData); private native void nativeDestroy(); + /** + * Generates an AEAD nonce used by AEAD encryption scheme. + * + */ + public final Result generateNonce() { + byte[] nativeResult = nativeGenerateNonce(); + if (nativeResult == null) { + return Result.error(new Exception("RecipientContext generateNonce failed")); + } + return Result.success(nativeResult); + } + /** * Decrypts message and validates associated data using AEAD. * @@ -48,8 +62,9 @@ public final Result open( * Encrypts response message with associated data using AEAD as part of bidirectional * communication. */ - public final Result seal(final byte[] plaintext, final byte[] associatedData) { - byte[] nativeResult = nativeSeal(plaintext, associatedData); + public final Result seal( + final byte[] nonce, final byte[] plaintext, final byte[] associatedData) { + byte[] nativeResult = nativeSeal(nonce, plaintext, associatedData); if (nativeResult == null) { return Result.error(new Exception("RecipientContext seal failed")); } diff --git a/java/src/main/java/com/google/oak/crypto/hpke/SenderContext.java b/java/src/main/java/com/google/oak/crypto/hpke/SenderContext.java index da503799b83..61bf73607f8 100644 --- a/java/src/main/java/com/google/oak/crypto/hpke/SenderContext.java +++ b/java/src/main/java/com/google/oak/crypto/hpke/SenderContext.java @@ -30,7 +30,9 @@ public SenderContext(byte[] serializedEncapsulatedPublicKey, long nativePtr) { this.nativePtr = nativePtr; } - private native byte[] nativeSeal(final byte[] plaintext, final byte[] associatedData); + private native byte[] nativeGenerateNonce(); + private native byte[] nativeSeal( + final byte[] nonce, final byte[] plaintext, final byte[] associatedData); private native byte[] nativeOpen(final byte[] ciphertext, final byte[] associatedData); private native void nativeDestroy(); @@ -38,12 +40,25 @@ public final byte[] getSerializedEncapsulatedPublicKey() { return serializedEncapsulatedPublicKey; } + /** + * Generates an AEAD nonce used by AEAD encryption scheme. + * + */ + public final Result generateNonce() { + byte[] nativeResult = nativeGenerateNonce(); + if (nativeResult == null) { + return Result.error(new Exception("SenderContext generateNonce failed")); + } + return Result.success(nativeResult); + } + /** * Encrypts message with associated data using AEAD. * */ - public final Result seal(final byte[] plaintext, final byte[] associatedData) { - byte[] nativeResult = nativeSeal(plaintext, associatedData); + public final Result seal( + final byte[] nonce, final byte[] plaintext, final byte[] associatedData) { + byte[] nativeResult = nativeSeal(nonce, plaintext, associatedData); if (nativeResult == null) { return Result.error(new Exception("SenderContext seal failed")); } diff --git a/java/src/test/java/com/google/oak/crypto/EncryptorTest.java b/java/src/test/java/com/google/oak/crypto/EncryptorTest.java index 66c567fe19a..959a50bbabf 100644 --- a/java/src/test/java/com/google/oak/crypto/EncryptorTest.java +++ b/java/src/test/java/com/google/oak/crypto/EncryptorTest.java @@ -37,7 +37,7 @@ public class EncryptorTest { private static final byte[] TEST_RESPONSE_ASSOCIATED_DATA = new byte[] {'d', 'a', 't', 'a', '2'}; // Number of message exchanges done to test secure session handling. - private static final int TEST_SESSION_SIZE = 8; + private static final int TEST_SESSION_SIZE = 1; @Test public void testEncryptor() throws Exception {