Skip to content
This repository has been archived by the owner on Apr 17, 2024. It is now read-only.

Commit

Permalink
Add InsecureNonceChaCha20Poly1305Jce to aead/internal.
Browse files Browse the repository at this point in the history
This is an implementation of InsecureNonceChaCha20Poly1305 using the ChaCha20Poly1305 provided by the JCE. It doesn't implement the encrypt/decrypt function using ByteBuffer, because it is only intened to be used by HPKE, which doesn't require those functions.

PiperOrigin-RevId: 601462223
  • Loading branch information
juergw authored and copybara-github committed Jan 25, 2024
1 parent f13be53 commit 0fea4d3
Show file tree
Hide file tree
Showing 6 changed files with 525 additions and 0 deletions.
2 changes: 2 additions & 0 deletions java_src/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@ gen_maven_jar_rules(
"//src/main/java/com/google/crypto/tink/aead/internal:insecure_nonce_cha_cha20_base",
"//src/main/java/com/google/crypto/tink/aead/internal:insecure_nonce_cha_cha20_poly1305",
"//src/main/java/com/google/crypto/tink/aead/internal:insecure_nonce_cha_cha20_poly1305_base",
"//src/main/java/com/google/crypto/tink/aead/internal:insecure_nonce_cha_cha20_poly1305_jce",
"//src/main/java/com/google/crypto/tink/aead/internal:insecure_nonce_x_cha_cha20",
"//src/main/java/com/google/crypto/tink/aead/internal:insecure_nonce_x_cha_cha20_poly1305",
"//src/main/java/com/google/crypto/tink/aead/internal:legacy_full_aead",
Expand Down Expand Up @@ -565,6 +566,7 @@ gen_maven_jar_rules(
"//src/main/java/com/google/crypto/tink/aead/internal:insecure_nonce_cha_cha20_base-android",
"//src/main/java/com/google/crypto/tink/aead/internal:insecure_nonce_cha_cha20_poly1305-android",
"//src/main/java/com/google/crypto/tink/aead/internal:insecure_nonce_cha_cha20_poly1305_base-android",
"//src/main/java/com/google/crypto/tink/aead/internal:insecure_nonce_cha_cha20_poly1305_jce-android",
"//src/main/java/com/google/crypto/tink/aead/internal:insecure_nonce_x_cha_cha20-android",
"//src/main/java/com/google/crypto/tink/aead/internal:insecure_nonce_x_cha_cha20_poly1305-android",
"//src/main/java/com/google/crypto/tink/aead/internal:legacy_full_aead-android",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -383,3 +383,25 @@ android_library(
"@maven//:com_google_errorprone_error_prone_annotations",
],
)

java_library(
name = "insecure_nonce_cha_cha20_poly1305_jce",
srcs = ["InsecureNonceChaCha20Poly1305Jce.java"],
deps = [
":cha_cha20_poly1305_jce",
"//src/main/java/com/google/crypto/tink:accesses_partial_key",
"//src/main/java/com/google/crypto/tink/config/internal:tink_fips_util",
"@maven//:com_google_errorprone_error_prone_annotations",
],
)

android_library(
name = "insecure_nonce_cha_cha20_poly1305_jce-android",
srcs = ["InsecureNonceChaCha20Poly1305Jce.java"],
deps = [
":cha_cha20_poly1305_jce-android",
"//src/main/java/com/google/crypto/tink:accesses_partial_key-android",
"//src/main/java/com/google/crypto/tink/config/internal:tink_fips_util-android",
"@maven//:com_google_errorprone_error_prone_annotations",
],
)
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,15 @@ public static Aead create(ChaCha20Poly1305Key key) throws GeneralSecurityExcepti
key.getOutputPrefix().toByteArray());
}

/**
* Returns a thread-local instance of the ChaCha20Poly1305, or null if ChaCha20Poly1305 is
* not supported.
*/
@Nullable
static Cipher getThreadLocalCipherOrNull() {
return localCipher.get();
}

public static boolean isSupported() {
return localCipher.get() != null;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
// Copyright 2021 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
////////////////////////////////////////////////////////////////////////////////

package com.google.crypto.tink.aead.internal;

import com.google.crypto.tink.AccessesPartialKey;
import com.google.crypto.tink.config.internal.TinkFipsUtil;
import com.google.errorprone.annotations.Immutable;
import java.security.GeneralSecurityException;
import java.security.InvalidKeyException;
import java.security.spec.AlgorithmParameterSpec;
import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;

/**
* Implements ChaCha20Poly1305, as described in <a
* href="https://tools.ietf.org/html/rfc8439#section-2.8">RFC 8439, section 2.8</a>.
*
* <p>It is similar to {@link ChaCha20Poly1305Jce}, but it offers an interface for the user to
* choose the nonce, which is needed in HPKE.
*
* <p>It uses the JCE, and requires that algorithm "ChaCha20-Poly1305" is present.
*/
@Immutable
public final class InsecureNonceChaCha20Poly1305Jce {

private static final TinkFipsUtil.AlgorithmFipsCompatibility FIPS =
TinkFipsUtil.AlgorithmFipsCompatibility.ALGORITHM_NOT_FIPS;

private static final int NONCE_SIZE_IN_BYTES = 12;
private static final int TAG_SIZE_IN_BYTES = 16;
private static final int KEY_SIZE_IN_BYTES = 32;

private static final String CIPHER_NAME = "ChaCha20-Poly1305";
private static final String KEY_NAME = "ChaCha20";

@SuppressWarnings("Immutable")
private final SecretKey keySpec;

private InsecureNonceChaCha20Poly1305Jce(final byte[] key) throws GeneralSecurityException {
if (!FIPS.isCompatible()) {
throw new GeneralSecurityException("Can not use ChaCha20Poly1305 in FIPS-mode.");
}
if (!isSupported()) {
throw new GeneralSecurityException("JCE does not support algorithm: " + CIPHER_NAME);
}
if (key.length != KEY_SIZE_IN_BYTES) {
throw new InvalidKeyException("The key length in bytes must be 32.");
}
this.keySpec = new SecretKeySpec(key, KEY_NAME);
}

@AccessesPartialKey
public static InsecureNonceChaCha20Poly1305Jce create(final byte[] key)
throws GeneralSecurityException {
return new InsecureNonceChaCha20Poly1305Jce(key);
}

public static boolean isSupported() {
return ChaCha20Poly1305Jce.getThreadLocalCipherOrNull() != null;
}

public byte[] encrypt(final byte[] nonce, final byte[] plaintext, final byte[] associatedData)
throws GeneralSecurityException {
if (plaintext == null) {
throw new NullPointerException("plaintext is null");
}
if (nonce.length != NONCE_SIZE_IN_BYTES) {
throw new GeneralSecurityException("nonce length must be " + NONCE_SIZE_IN_BYTES + " bytes.");
}
AlgorithmParameterSpec params = new IvParameterSpec(nonce);
Cipher cipher = ChaCha20Poly1305Jce.getThreadLocalCipherOrNull();
cipher.init(Cipher.ENCRYPT_MODE, keySpec, params);
if (associatedData != null && associatedData.length != 0) {
cipher.updateAAD(associatedData);
}
return cipher.doFinal(plaintext);
}

public byte[] decrypt(final byte[] nonce, final byte[] ciphertext, final byte[] associatedData)
throws GeneralSecurityException {
if (ciphertext == null) {
throw new NullPointerException("ciphertext is null");
}
if (nonce.length != NONCE_SIZE_IN_BYTES) {
throw new GeneralSecurityException("nonce length must be " + NONCE_SIZE_IN_BYTES + " bytes.");
}
if (ciphertext.length < TAG_SIZE_IN_BYTES) {
throw new GeneralSecurityException("ciphertext too short");
}
AlgorithmParameterSpec params = new IvParameterSpec(nonce);

Cipher cipher = ChaCha20Poly1305Jce.getThreadLocalCipherOrNull();
cipher.init(Cipher.DECRYPT_MODE, keySpec, params);
if (associatedData != null && associatedData.length != 0) {
cipher.updateAAD(associatedData);
}
return cipher.doFinal(ciphertext);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -237,3 +237,23 @@ java_test(
"@maven//:junit_junit",
],
)

java_test(
name = "InsecureNonceChaCha20Poly1305JceTest",
size = "small",
srcs = ["InsecureNonceChaCha20Poly1305JceTest.java"],
data = ["@wycheproof//testvectors:all"],
deps = [
"//src/main/java/com/google/crypto/tink/aead/internal:insecure_nonce_cha_cha20_poly1305_jce",
"//src/main/java/com/google/crypto/tink/config:tink_fips",
"//src/main/java/com/google/crypto/tink/internal:util",
"//src/main/java/com/google/crypto/tink/subtle:bytes",
"//src/main/java/com/google/crypto/tink/subtle:hex",
"//src/main/java/com/google/crypto/tink/subtle:random",
"//src/main/java/com/google/crypto/tink/testing:test_util",
"//src/main/java/com/google/crypto/tink/testing:wycheproof_test_util",
"@maven//:com_google_code_gson_gson",
"@maven//:com_google_truth_truth",
"@maven//:junit_junit",
],
)
Loading

0 comments on commit 0fea4d3

Please sign in to comment.