From 36bb87f4de38834a9a6ebfc7a434684d04408b56 Mon Sep 17 00:00:00 2001 From: Juerg Wullschleger Date: Mon, 1 Jul 2024 08:45:14 -0700 Subject: [PATCH] Remove unnecessary copy of data for LEGACY RSA PKCS1 and PSS signature verifying. PiperOrigin-RevId: 648381734 Change-Id: Ib29fc1bda75ff92846770e5a53b3bf708920f558 --- .../tink/subtle/RsaSsaPkcs1VerifyJce.java | 20 ++++++++++--------- .../tink/subtle/RsaSsaPssVerifyJce.java | 18 +++++++++-------- 2 files changed, 21 insertions(+), 17 deletions(-) diff --git a/src/main/java/com/google/crypto/tink/subtle/RsaSsaPkcs1VerifyJce.java b/src/main/java/com/google/crypto/tink/subtle/RsaSsaPkcs1VerifyJce.java index 074fb94d0..5b268b9be 100644 --- a/src/main/java/com/google/crypto/tink/subtle/RsaSsaPkcs1VerifyJce.java +++ b/src/main/java/com/google/crypto/tink/subtle/RsaSsaPkcs1VerifyJce.java @@ -43,6 +43,9 @@ public final class RsaSsaPkcs1VerifyJce implements PublicKeyVerify { public static final TinkFipsUtil.AlgorithmFipsCompatibility FIPS = TinkFipsUtil.AlgorithmFipsCompatibility.ALGORITHM_REQUIRES_BORINGCRYPTO; + private static final byte[] EMPTY = new byte[0]; + private static final byte[] LEGACY_MESSAGE_SUFFIX = new byte[] {0}; + // See definitions in https://tools.ietf.org/html/rfc3447#page-43 private static final String ASN_PREFIX_SHA256 = "3031300d060960864801650304020105000420"; private static final String ASN_PREFIX_SHA384 = "3041300d060960864801650304020205000430"; @@ -81,8 +84,8 @@ public static PublicKeyVerify create(RsaSsaPkcs1PublicKey key) throws GeneralSec HASH_TYPE_CONVERTER.toProtoEnum(key.getParameters().getHashType()), key.getOutputPrefix().toByteArray(), key.getParameters().getVariant().equals(RsaSsaPkcs1Parameters.Variant.LEGACY) - ? new byte[] {0} - : new byte[0]); + ? LEGACY_MESSAGE_SUFFIX + : EMPTY); } private RsaSsaPkcs1VerifyJce( @@ -104,7 +107,7 @@ private RsaSsaPkcs1VerifyJce( public RsaSsaPkcs1VerifyJce(final RSAPublicKey pubKey, HashType hash) throws GeneralSecurityException { - this(pubKey, hash, new byte[0], new byte[0]); + this(pubKey, hash, EMPTY, EMPTY); } private void noPrefixVerify(final byte[] signature, final byte[] data) @@ -144,6 +147,9 @@ private byte[] emsaPkcs1(byte[] m, int emLen, HashType hash) throws GeneralSecur MessageDigest digest = EngineFactory.MESSAGE_DIGEST.getInstance(SubtleUtil.toDigestAlgo(this.hash)); digest.update(m); + if (messageSuffix.length != 0) { + digest.update(messageSuffix); + } byte[] h = digest.digest(); byte[] asnPrefix = toAsnPrefix(hash); int tLen = asnPrefix.length + h.length; @@ -179,18 +185,14 @@ private byte[] toAsnPrefix(HashType hash) throws GeneralSecurityException { @Override public void verify(final byte[] signature, final byte[] data) throws GeneralSecurityException { - if (outputPrefix.length == 0 && messageSuffix.length == 0) { + if (outputPrefix.length == 0) { noPrefixVerify(signature, data); return; } if (!isPrefix(outputPrefix, signature)) { throw new GeneralSecurityException("Invalid signature (output prefix mismatch)"); } - byte[] dataCopy = data; - if (messageSuffix.length != 0) { - dataCopy = Bytes.concat(data, messageSuffix); - } byte[] signatureNoPrefix = Arrays.copyOfRange(signature, outputPrefix.length, signature.length); - noPrefixVerify(signatureNoPrefix, dataCopy); + noPrefixVerify(signatureNoPrefix, data); } } diff --git a/src/main/java/com/google/crypto/tink/subtle/RsaSsaPssVerifyJce.java b/src/main/java/com/google/crypto/tink/subtle/RsaSsaPssVerifyJce.java index a97097bc2..9f63d9c92 100644 --- a/src/main/java/com/google/crypto/tink/subtle/RsaSsaPssVerifyJce.java +++ b/src/main/java/com/google/crypto/tink/subtle/RsaSsaPssVerifyJce.java @@ -141,7 +141,8 @@ private void noPrefixVerify(final byte[] signature, final byte[] data) } // https://tools.ietf.org/html/rfc8017#section-9.1.2. - private void emsaPssVerify(byte[] m, byte[] em, int emBits) throws GeneralSecurityException { + private void emsaPssVerify(byte[] message, byte[] em, int emBits) + throws GeneralSecurityException { // Step 1. Length checking. // This step is unnecessary because Java's byte[] only supports up to 2^31 -1 bytes while the // input limitation for the hash function is far larger (2^61 - 1 for SHA-1). @@ -150,7 +151,12 @@ private void emsaPssVerify(byte[] m, byte[] em, int emBits) throws GeneralSecuri Validators.validateSignatureHash(sigHash); MessageDigest digest = EngineFactory.MESSAGE_DIGEST.getInstance(SubtleUtil.toDigestAlgo(this.sigHash)); - byte[] mHash = digest.digest(m); + // M = concat(message, messageSuffix) + digest.update(message); + if (messageSuffix.length != 0) { + digest.update(messageSuffix); + } + byte[] mHash = digest.digest(); int hLen = digest.getDigestLength(); int emLen = em.length; @@ -222,18 +228,14 @@ private void emsaPssVerify(byte[] m, byte[] em, int emBits) throws GeneralSecuri @Override public void verify(final byte[] signature, final byte[] data) throws GeneralSecurityException { - if (outputPrefix.length == 0 && messageSuffix.length == 0) { + if (outputPrefix.length == 0) { noPrefixVerify(signature, data); return; } if (!isPrefix(outputPrefix, signature)) { throw new GeneralSecurityException("Invalid signature (output prefix mismatch)"); } - byte[] dataCopy = data; - if (messageSuffix.length != 0) { - dataCopy = Bytes.concat(data, messageSuffix); - } byte[] signatureNoPrefix = Arrays.copyOfRange(signature, outputPrefix.length, signature.length); - noPrefixVerify(signatureNoPrefix, dataCopy); + noPrefixVerify(signatureNoPrefix, data); } }