Andrea Cosentino created CAMEL-24445:
----------------------------------------
Summary: camel-pqc - producer shares one Signature instance across
concurrent exchanges without synchronization
Key: CAMEL-24445
URL: https://issues.apache.org/jira/browse/CAMEL-24445
Project: Camel
Issue Type: Bug
Components: camel-pqc
Reporter: Andrea Cosentino
Assignee: Andrea Cosentino
Fix For: 4.23.0
{{PQCProducer}} caches a single {{java.security.Signature}} in a field at
{{doStart()}}, and when no signer is configured it falls back to the shared
instances held by the {{PQCDefault*Material}} classes:
{code:java}
private Signature signer;
...
signer = getEndpoint().getConfiguration().getSigner();
if (ObjectHelper.isEmpty(signer)) {
signer = Signature.getInstance(sigAlg.getAlgorithm(),
sigAlg.getBcProvider());
}
{code}
Both {{signature()}} and {{verification()}} then run a full
{{initSign}}/{{initVerify}} -> {{update}} -> {{sign}}/{{verify}} sequence on
that object with no synchronization:
{code:java}
signer.initVerify(keyPair.getPublic());
updateSignatureFromBody(signer, exchange.getMessage());
if (signer.verify(exchange.getMessage().getHeader(PQCConstants.SIGNATURE,
byte[].class))) {
{code}
{{java.security.Signature}} is not thread-safe, and Camel producers are
singletons invoked concurrently. {{updateSignatureFromBody}} streams the body
in chunks, which widens the window: one thread's {{initVerify}} can reset the
object between another thread's {{update}} calls and its {{verify()}}, so a
verify can return a result that does not correspond to the message it was
called for.
Proposal: create the {{Signature}} per invocation, or hold it in a
{{ThreadLocal}}, or synchronize the whole init-update-finish sequence.
Per-invocation is the simplest and matches how the JDK expects the class to be
used; the configured-signer case needs the same treatment since a shared
configured instance has the same problem.
--
This message was sent by Atlassian Jira
(v8.20.10#820010)