Skip to content

Commit

Permalink
Spec: Weaken null report requirement WRT max contributions
Browse files Browse the repository at this point in the history
It's not necessary to send a null report when the caller-provided "max
contributions" has no effect on the payload length.

This commit updates the algorithm "determine if a report should be
sent deterministically" to account for this edge case. Relatedly, it
also updates the prose description of payload-length side channel.
  • Loading branch information
dmcardle committed Jan 23, 2025
1 parent 1b961e3 commit 06e2b7d
Showing 1 changed file with 30 additions and 18 deletions.
48 changes: 30 additions & 18 deletions spec.bs
Original file line number Diff line number Diff line change
Expand Up @@ -572,14 +572,18 @@ scope=] |debugScope| and an optional [=debug details=] or null

<div algorithm>
To <dfn>determine if a report should be sent deterministically</dfn> given a
[=pre-specified report parameters=] |preSpecifiedParams|, perform the following
steps. They return a [=boolean=]:
[=pre-specified report parameters=] |preSpecifiedParams| and a [=context type=]
|api|, perform the following steps. They return a [=boolean=]:
1. If |preSpecifiedParams|' [=pre-specified report parameters/context ID=] is
not null, return true.
1. If |preSpecifiedParams|' [=pre-specified report parameters/filtering ID max
bytes=] is not the [=default filtering ID max bytes=], return true.
1. If |preSpecifiedParams|' [=pre-specified report parameters/max
contributions=] is not null, return true.
1. Let |effectiveMaxContributions| be the result of [=determining the max
contributions=] with |api| and |preSpecifiedParams|' [=pre-specified report
parameters/max contributions=].
1. Let |defaultMaxContributions| be the result of [=determining the max
contributions=] with |api| and null.
1. If |effectiveMaxContributions| is not |defaultMaxContributions|, return true.
1. Return false.

Note: It is sometimes necessary to send a 'null report' to conceal the fact that
Expand Down Expand Up @@ -738,7 +742,8 @@ null |timeout|:
1. If |hasProcessedContribution| is false, [=list/append=] |contribution| to
|mergedContributions|.
1. Let |effectiveMaxContributions| be the result of [=determining the max
contributions=] with |preSpecifiedParams| and |api|.
contributions=] with |api| and |preSpecifiedParams|' [=pre-specified report
parameters/max contributions=].
1. Let |truncatedContributions| be a new [=list=].
1. If |mergedContributions| has a [=list/size=] greater than
|effectiveMaxContributions|:
Expand Down Expand Up @@ -821,8 +826,9 @@ perform the following steps. They return an [=aggregatable report=].
:: |preSpecifiedParams|' [=pre-specified report parameters/filtering ID max
bytes=]
: [=aggregatable report/max contributions=]
:: The result of [=determining the max contributions=] with
|preSpecifiedParams| and |api|.
:: The result of [=determining the max contributions=] with |api| and
|preSpecifiedParams|' [=pre-specified report parameters/max
contributions=].
: [=aggregatable report/queued=]
:: false
1. Return |report|.
Expand All @@ -846,11 +852,9 @@ They return a [=moment=].
</div>

<div algorithm>
To <dfn>determine the max contributions</dfn> given a [=pre-specified report
parameters=] |preSpecifiedParams| and a [=context type=] |api|, perform the
following steps. They return a positive integer.
1. Let |maxContributions| be |preSpecifiedParams|' [=pre-specified report
parameters/max contributions=].
To <dfn>determine the max contributions</dfn> given a [=context type=] |api| and
a positive integer or null |maxContributions|, perform the following steps. They
return a positive integer.
1. If |maxContributions| is null, return [=default maxContributions by
API=][|api|].
1. If |maxContributions| is greater than [=maximum maxContributions=], return
Expand Down Expand Up @@ -1297,17 +1301,25 @@ by a randomized amount of time to make it difficult to determine whether a
report was sent or not from any particular event. In the case that a
[=pre-specified report parameters/context ID=] is supplied, a non-default
[=pre-specified report parameters/filtering ID max bytes=] is specified, or a
[=pre-specified report parameters/max contributions=] is specified, the API
makes the number of reports sent deterministic (sending 'null reports' if
necessary — each containing only a contribution with a value of 0 in the
non-default [=pre-specified report parameters/max contributions=] is specified,
the API makes the number of reports sent deterministic (sending 'null reports'
if necessary — each containing only a contribution with a value of 0 in the
payload). Additional mitigations may also be possible in the future, e.g. adding
noise to the report count.

### Protecting against leaks via payload size ### {#protecting-against-leaks-via-payload-size}

The length of the payload could additionally expose some cross-site information,
namely how many contributions are included. To protect against this, the payload
is padded to a fixed number of contributions.
The length of the encrypted payload could additionally expose some cross-site
information, namely the number of contributions present in the plaintext
payload. To eliminate this side channel, Private Aggregation ensures that
payloads contain a predetermined number of contributions prior to encryption,
potentially truncating or padding with null contributions to match the target.

The target number of contributions is based on [=pre-specified report
parameters/max contributions=] when it is non-null — it is the caller's
responsibility to ensure this value is uncorrelated with cross-site data.
Otherwise, the target is selected from [=default maxContributions by API=] based
on the caller's [=context type=].

### Temporary debugging mechanism ### {#temporary-debugging-mechanism}

Expand Down

0 comments on commit 06e2b7d

Please sign in to comment.