[Last-Call] Re: Genart last call review of draft-ietf-ace-revoked-token-notification-06

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hello Dale,

Thanks a lot for your review! Please find in line below our detailed replies to your comments.

A Github PR where we have addressed your comments is available at [PR].

Unless any concern is raised, we plan to soon merge this PR (and the other ones related to other received reviews), and to submit the result as version -07 of the document.

Thanks,
/Marco

[PR] https://github.com/ace-wg/ace-revoked-token-notification/pull/8


On 2024-04-04 03:36, Dale Worley via Datatracker wrote:
Reviewer: Dale Worley
Review result: Ready with Issues

I am the assigned Gen-ART reviewer for this draft. The General Area
Review Team (Gen-ART) reviews all IETF documents being processed
by the IESG for the IETF Chair.  Please treat these comments just
like any other last call comments.

For more information, please see the FAQ at

<https://eur05.safelinks.protection.outlook.com/?url="">.

Document:  draft-ietf-ace-revoked-token-notification-06
Reviewer:  Dale R. Worley
Review Date:  2024-04-03
IETF LC End Date:  2024-04-05
IESG Telechat date:  not known

Summary:

    This draft is on the right track but has open issues, described in
    the review.

** Technical issues:

* Section 5.1 includes:

   For each requester, the AS maintains an update collection of maximum
   MAX_N series items, where MAX_N is a pre-defined, constant positive
   integer.  The AS MUST keep track of the MAX_N most recent updates to
   the subset of the TRL that pertains to each requester.

This suggests that that the AS needs to maintain either separate
collections for each requester or engage in some rather complicated
bookkeeping to tell when an item can be reaped (since sometimes the
oldest item cannot be reaped but some newer item can be).  Is this
what is intended?

==>MT

The AS indeed maintains one separate collection per requester.

This is what is intended, since different updates to the TRL yield a different history of updates for different registered devices. Having one update collection as intended prevents the AS from alternatively relying on a more complicated form of bookkeeping.

Related to this point, and also addressing a later editorial comment, we have added the following new sentence at the beginning of the quoted paragraph, to clarify that MAX_N is a single, constant value that the AS considers for all the update collections that it maintains.

NEW:
> The AS defines the single, constant positive integer MAX_N >= 1.

<==


* The Observe mechanism requires that the AS maintain per-observer
state for current subscriptions.  There are some complications:

- Is there a limitation to one subscription per registered client?

- The notifications sent for a subscription depend on the parameters
  of the GET which establishes the subscription.  Additionally, the
  URL to which notifications are to be sent must be recorded.

I suspect that these questions are answered (explicitly or implicitly)
by the specification of the CoAP Observe mechanism.  But I notice that
the data that the AS must store to support subscriptions is not stated
in Appendix B.

- More subtly, a subscription with Cursor implicitly saves the
"cursor" value sent with a notification to be used as the implicit
input "cursor" value used to construct the payload of the next
notification.  This processing is "obvious" but I didn't notice it
being specified anywhere.  And it likely isn't implicit in the general
CoAP Observe specification because it isn't data from the GET that is
stored to be used as input for generating each successive
notification.  So it seems that some additional specification is
needed.  Also, Appendix B doesn't specify this as part of the AS
state.

==>MT

(The following also relates to the editorial comment "In what way does the AS record the types of observation responses ..." about Section 10)

This document considers the use of Observe as-is, i.e., as defined in RFC 7641. That is, it is not adding or altering the behavior defined in RFC 7641, which is simply inherited.

By supporting resource observation for the TRL endpoint, the AS is simply following RFC 7641.

The following replies to the comment point-to-point.

**Point 1**

> - Is there a limitation to one subscription per registered client?

There is no fundamental limitation on the number of subscriptions that the same client has to the TRL resource at the AS.

Yet, just like any CoAP server providing an observable resource, the AS may certainly decide to ignore an Observe registration request, e.g., due to the excessive number of currently ongoing observations. Per Section 5.1 of RFC 7641:

> A server that is unable or unwilling to add a new entry to the list of observers of a resource MAY silently ignore the registration request and process the GET request as usual.

**Point 2**

> - The notifications sent for a subscription depend on the parameters
>   of the GET which establishes the subscription.  Additionally, the
>   URL to which notifications are to be sent must be recorded.
>
> I suspect that these questions are answered (explicitly or implicitly)
> by the specification of the CoAP Observe mechanism.  But I notice that
> the data that the AS must store to support subscriptions is not stated
> in Appendix B.

Fundamentally, these questions are answered in RFC 7641, and the AS behaves accordingly, just like any CoAP server providing observable resources.

On sending Observe notifications, Section 4.2 of RFC 7641 (referred to in Section 10 of the present document) says:

> A client is notified of changes to the resource state by additional responses sent by the server in reply to the GET request.

That is, upon changes to the TRL, the AS sends an Observe notification response to an observer client like if the AS had just received the stored GET Observation Request from that observer, i.e., consistent with the conveyed query parameters (if any).

On registering an Observation at the server, Section 4.1 of RFC 7641 says (note that "token" here refers to a CoAP message token, not to an ACE access token):

> The entry in the list of observers is keyed by the client endpoint and the token specified by the client in the request.

That was clearly specified to ensure that exactly that information was used as lookup key. Certainly, the CoAP server has to store information that practically allows it to produce Observe notifications consistent with the intended observation, i.e., as a description of the specific subscription to the observed resource.

Indeed, such a description has to include information on where notifications have to be sent for that observation (which is part of the "client endpoint" anyway), as well as information specific of the Observe Registration Request such as the URI of the resource that is object of observation and query parameters that were present in the request (if any).

The details about how to achieve that are implementation-specific, as long as the CoAP server is able to produce Observe notifications consistently with the semantics defined in RFC 7641.

In general, a CoAP server may have a resource observable. This does not mean and does not require that the specification of the semantics of a resource has also to specify what the server has to store as observation state in order to make Observe as such work for that resource.

As to the management of observations, the type of information and data structures that a CoAP server maintains as well as the particular way to maintain them abstract away from the specifically observed resources.

Consequently, as a CoAP server, the AS does not have to do anything special with respect to what is defined in RFC 7641, neither due to the fact that it is specifically an ACE Authorization Server, nor because the observable resource in question is specifically the TRL endpoint.

The rationale by which the AS stores information (including from the Observe Registration Request) to ensure a correct management of observations is intended for the observation management at large, and there is nothing new or special for the particular case of the TRL endpoint.

Therefore, such information related to enforcing Observe does not concern the maintenance of the **content** of the TRL endpoint, hence it is not intended to be included in Appendix B.

Implementation considerations/guidance for CoAP servers supporting Observe might have been useful, but we do not think that the present document is the right place where to have those.

**Point 3**

> - More subtly, a subscription with Cursor implicitly saves the
> "cursor" value sent with a notification to be used as the implicit
> input "cursor" value used to construct the payload of the next
> notification.  This processing is "obvious" but I didn't notice it
> being specified anywhere.  And it likely isn't implicit in the general
> CoAP Observe specification because it isn't data from the GET that is
> stored to be used as input for generating each successive
> notification.  So it seems that some additional specification is
> needed.  Also, Appendix B doesn't specify this as part of the AS
> state.

As per the answer to the previous point:

* This is indeed the intended behavior, which is specified in Section 4.2 of RFC 7641 (see above) and that the present document inherits as-is.

* The rationale by which the AS stores information (including from the Observe Registration Request) to ensure a correct observation of the TRL endpoint is not different than for any other observable resource that it hosts. In particular, **as to the establishment and maintenance of an Observation**, the "cursor" query parameter has nothing special compared to other query parameters.

* Information related to establishing and maintaining observations do not concern the maintenance of the **content** of the TRL endpoint, hence it is not intended to be included in Appendix B.

<==


* If I were writing this specification, I would replace MAX_INDEX with
"INDEX_LIMIT", defined as MAX_INDEX + 1.  That is, instead of the
constraint "index <= MAX_INDEX" would be "index < INDEX_LIMIT".  Then
the numerous places where "MAX_INDEX + 1" is used could be changed to
just "INDEX_LIMIT":

    The AS defines INDEX_LIMIT <= (2^64).

    If i_X is the value of 'index' associated with a series item X, then
    the following series item Y will take 'index' with value i_Y = (i_X +
    1) % INDEX_LIMIT.

    -  ( i_B = INDEX_LIMIT - 2, i_C = INDEX_LIMIT -1, i_D = 0 )

    a value (not less than)/(greater than or equal to) INDEX_LIMIT

Although then there are a number of places where "MAX_INDEX" is now
used that would have to be revised to "INDEX_LIMIT - 1".

==>MT

This seems indeed to be about subjective preferences.

Please consider that:

* The intent was to phrase the upper bound as inclusive, hence expressions like "index <= MAX_INDEX". That is, the maximum value is a legitimate value.

* To us, "INDEX_LIMIT" also suggests inclusiveness, i.e., the limit value is a legitimate value. Consistently, if choosing "INDEX_LIMIT", we would have said "index <= INDEX_LIMIT" anyway.

* The mindset built on the current "MAX_INDEX" has been considered in implementations.

Unless there are compelling complications or unclear/incorrect points that cannot be fixed in the present formulation, we would prefer to keep MAX_INDEX and its current use.

<==


* Section 3, "Token Hash" specifies two alternative ways of
constructing HASH_INPUT from an access token, depending on whether the
token value is a byte string or a text string.  If the token is a byte
string, HASH_INPUT is the CBOR serialization of the byte string, but
if the token is a (UTF-8) text string, HASH_INPUT is the text string
itself.

The document does not describe the motivation for this construction.
It cannot be to restrict the bytes in HASH_INPUT to a particular set,
because the CBOR serialization of a byte string can contain any byte
values.  I suspect that the motivation is to ensure that the hash of a
byte string is never the same as the hash of a character string.

However, this differentiation is not accomplished by the described
process.  For example, the byte sequence 0x41 0x41 is both the
character string "AA" as well as a CBOR serialization of the
single-byte string 0x41.  For that matter, the byte sequence 0x40 is
both the character string "@" as well as the most common CBOR
serialization of the null byte string.

In addition, for the overall processing to work, a receiver must be
able to recognize when a hash matches a token that it possesses.  But
the CBOR serialization of a byte string is not unique.  In the example
in section 3, the first byte of the encoding could be 58, 59, 5a, or
5b (corresponding to using a 1-, 2-, 4, or 8-byte extended count) or
5f (corresponding to using an indefinite length encoding).  Indeed,
since an indefinite-length byte string encoding may contain
zero-length chunks, there are an infinite number of valid CBOR
serializations of any byte string and the number of HASH_INPUT values
and derived hashes for any particular byte string token is infinite.
This makes it impossible to determine in general whether a particular
hash refers to a particular byte string token.

However, these problems can be eliminated (and the overall process
simplified) in this manner:  To distinguish byte strings from text
strings, set HASH_STRING to be the byte 0x80 prepended to the byte
string.  Since 0x80 can never be the initial byte of a UTF-8 text
string, this HASH_STRING value cannot be generated by any text string.

==>MT

Thanks for this comment!

Short answer: we have re-examined the building of HASH_INPUT and revised Section 3 as follows:

* We have motivated why the two different cases have to be considered. This was raised very early on the mailing list, see [MAIL1][MAIL2].

* We have revised the building of HASH_INPUT, in order to:

   - ensure that the RS can always compute the same token hash as C and the AS, considering the different transport profiles of ACE, the different formats of access tokens (i.e., CWTs and JWTs) and the possible different ways to transport them (i.e., in CBOR messages or in JSON messages);

   - neutralize a possible attack from a dishonest Client, which can otherwise induce the RS to build a wrong HASH_INPUT, hence to compute a wrong token hash than the one stored in the TRL at the AS.

* We have explicitly described the building of HASH_INPUT also from the point of view of the RS.

[MAIL1]
https://mailarchive.ietf.org/arch/msg/ace/VotSG9yx9aIzJcBkaAu2HsBr424/

[MAIL2] https://mailarchive.ietf.org/arch/msg/ace/3YYygq3tsQ3r6KllyH2sHp_h7w0/


The following provides a more comprehensive answer.


Used access tokens can have one among different formats, which are practically expected to be CWTs (RFC 8392) or JWTs (RFC 7519). Per Section 3 of RFC 9200, CWT is the default format to use in the ACE framework.

The RS knows whether access tokens that are issued for it to consume are either CWTs or JWTs, while the access tokens are opaque for the Client.

At the same time, there are two ways by which the AS can provide the Client with the access token in the AS-to-Client response (see Section 5.8.2 of RFC 9200). The RS is not necessarily aware of which of these ways the AS uses and with which Clients.

* One way relies on CBOR, which is required if CoAP is used, and is still recommended otherwise (see Section 5.0 of RFC 9200). That is, the AS-to-Client response has media-type "application/ace+cbor".

  This implies that, within the CBOR map specified as message payload, the parameter 'access_token' is a CBOR data item of **type** CBOR byte string and with **value** the binary representation BYTES of the access token. In particular:

  * If the access token is a CWT, then BYTES is the binary representation of the CWT (i.e., of the CBOR array that encodes the CWT).
  * If the access token is a JWT, then BYTES is the binary representation of the JWT (i.e., of the text string that encodes the JWT).

* A different way relies on JSON. That is, the AS-to-Client response has media-type "application/ace+json".

  This implies that, within the JSON object specified as message payload, the parameter 'access_token' has as value a text string TEXT encoding the access token. In particular:

  * If the access token is a JWT, then TEXT is the text string that encodes the JWT.
  * If the access token is a CWT (which is certainly a strange corner case), then TEXT is the base64url-encoded text string of the binary representation of the CWT (i.e., of the CBOR array that encodes the CWT).

With these variants in mind, the goal of this document is to ensure that the three parties AS, Client, and RS all agree on the same value HASH_INPUT, in order to compute the same token hash for a given access token.

As noted at a high-level in [MAIL2], the key is to ensure that HASH_INPUT is built based on the content of the 'access_token' parameter in the AS-to-Client response, since that content is what everyone (AS, Client, RS) sees.

Building on that, the revised Section 3 defines the following processing. Please note that:

* The binary representation of a text string is the corresponding UTF-8 encoding (RFC 3629).

* Per Section 8.1 of RFC 8259, UTF-8 is the implied charset used in JSON.

* The base64url encoding is specified in Section 5 of RFC 4648.


**Point-of-view of the AS and Client**

* Using CBOR (This has been a change in the draft) - If the AS-to-Client response is a CBOR message, then HASH_INPUT is built as follows.

   First, BYTES is defined as the value of the CBOR byte string conveyed by the parameter 'access_token'. With reference to Figure 2 in version -06 of the Internet Draft, BYTES is {0xd0 0x83 0x44 0xa1 ...}.

   Then, HASH_INPUT_TEXT is defined as the base64url-encoded text string that encodes BYTES. Finally, HASH_INPUT is the binary representation of HASH_INPUT_TEXT.

   Note that there are two possible cases to consider:

    * CBOR-CWT - If the access token is a CWT, then BYTES is the binary representation of the CWT (i.e., of the CBOR array that encodes the CWT).

    * CBOR-JWT - If the access token is a JWT, then BYTES is the binary representation of the JWT (i.e., of the text string that encodes the JWT).

* Using JSON (This has **not** been a change in the draft) - If the AS-to-Client response is a JSON message, then HASH_INPUT is the binary representation of the text string conveyed by the 'access_token' parameter.

    Note that there are two possible cases to consider:

    * JSON-JWT - If the access token is a JWT, then HASH_INPUT is the binary representation of the JWT (i.e., of the text string that encodes the JWT).

    * JSON-CWT - If the access token is a CWT, then HASH_INPUT is the binary representation of the base64url-encoded text string that encodes the binary representation of the CWT (i.e., of the CBOR array that encodes the CWT).


**Point-of-view of the RS**

In accordance with the used transport profile of ACE (e.g., RFC 9202, RFC 9203, RFC 9431), the RS receives a piece of token-related information that can generically be called TOKEN_INFO.

In the cases CBOR-CWT, CBOR-JWT, and JSON-JWT, TOKEN_INFO is the binary representation of the access token. That is:

* In the cases CBOR-CWT and CBOR-JWT listed above, TOKEN_INFO is the value of the CBOR byte string conveyed by the 'access_token' parameter.

* In the case JSON-JWT, TOKEN_INFO is the binary representation of the text string conveyed by the 'access_token' parameter.

Instead, in the case JSON-CWT, TOKEN_INFO is the binary representation of the base64url-encoded text string that encodes the binary representation of the access token. That is, TOKEN_INFO is the binary representation of the base64url-encoded text string conveyed by the 'access_token' parameter.

The following list overviews how this specifically relates to the transport profiles of ACE.

* The access token can be uploaded to the RS by means of a POST request to the /authz-info endpoint (see Section 5.10.1 of RFC 9200), using a media-type different from "application/ace+cbor" (e.g., like in RFC 9202). In such a case, TOKEN_INFO is the request payload of the POST request.

* The access token can be uploaded to the RS by means of a POST request to the /authz-info enpoint, using the media-type "application/ace+cbor" (e.g., like in RFC 9203). In such a case, TOKEN_INFO is the value of the CBOR byte string conveyed by the 'access_token' parameter, within the CBOR map specified as payload of the POST request.

* The access token can be uploaded to the RS during a DTLS session establishment, e.g., like it is defined in Section 3.2.2 of RFC 9202. In such a case, TOKEN_INFO is the value of the 'psk_identity' field of the ClientKeyExchange message (when using DTLS 1.2), or of the 'identity' field of a PSKIdentity, within the PreSharedKeyExtension of a ClientHello message (when using DTLS 1.3).

* The access token can be uploaded to the RS within the MQTT CONNECT packet, e.g., like it is defined in Section 2.2.4.1 of RFC 9431. In such a case, TOKEN_INFO is specified within the 'Authentication Data' field of the MQTT CONNECT packet, following the property identifier 22 (0x16) and the token length.


If the RS expects access tokens to be **CWTs**, then the RS proceeds as follows.

1. The RS receives TOKEN_INFO, in accordance with what is specified by the used profile of ACE.

2. The RS assumes that the Client received the access token in an AS-to-Client response encoded in CBOR (see the case CBOR-CWT above). Hence, the RS assumes TOKEN_INFO to be the binary representation of the access token.

3. The RS processes the access token as a CWT and verifies it. If the verification fails, the RS moves to step 4. Otherwise, the RS stores the access token and computes the token hash associated with the access token.

   In particular, the RS considers HASH_INPUT_TEXT as the base64url-encoded text string that encodes TOKEN_INFO. Then, HASH_INPUT is the binary representation of HASH_INPUT_TEXT.

   After that, the RS stores the computed token hash as associated with the access token, and then terminates this algorithm.

4. The RS assumes that the Client received the access token in an AS-to-Client response encoded in JSON (see the case JSON-CWT above). Hence, the RS assumes TOKEN_INFO to be the binary representation of HASH_INPUT_TEXT, which is the base64url-encoded text string that encodes the binary representation of the access token.

5. The RS performs the base64url decoding of HASH_INPUT_TEXT, and considers the result as the binary representation of the access token.

6. The RS processes the access token as a CWT. If the verification fails, then the RS terminates this algorithm. Otherwise, the RS stores the access token and computes the token hash associated with the access token. In particular, HASH_INPUT is TOKEN_INFO.

   After that, the RS stores the computed token hash as associated with the access token, and then terminates this algorithm.


If the RS expects access tokens to be **JWTs**, then the RS proceeds as follows.

1. The RS receives TOKEN_INFO, in accordance with what is specified by the used profile of ACE.

2. The RS processes the access token as a JWT. If the verification fails, the RS terminates this algorithm. Otherwise, the RS stores the access token and moves to step 3.

3. The RS computes a first token hash associated with the access token. In particular, the RS assumes that the Client received the access token in an AS-to-Client response encoded in JSON (see the case JSON-JWT above). Hence, HASH_INPUT is TOKEN_INFO. After that, the RS stores the computed token hash as associated with the access token.

4. The RS computes a second token hash associated with the access token. To this end, the RS assumes that the Client received the access token in an AS-to-Client response encoded in CBOR (case CBOR-JWT above). Hence, HASH_INPUT is the binary representation of HASH_INPUT_TEXT, which in turn is the base64url-encoded text string that encodes TOKEN_INFO. After that, the RS stores the computed token hash as associated with the access token.

The RS skips step 3 only if it is certain that all its pertaining access tokens are provided to any Client by means of AS-to-Client responses encoded as CBOR messages. Otherwise, the RS MUST perform step 3.

The RS skips step 4 only if it is certain that all its pertaining access tokens are provided to any Client by means of AS-to-Client responses encoded as JSON messages. Otherwise, the RS MUST perform step 4.

If the RS performs both step 3 and step 4 above, then the RS MUST store, maintain, and rely on both token hashes as associated with the access token, consistent with what is specified in Section 10.1 of the Internet Draft.


Computing and storing both token hashes is necessary, because the RS does not know for sure if the AS provided the access token to the Client by means of an AS-to-Client response encoded in CBOR or in JSON.

Taking advantage of that, a dishonest Client can perform an attack against the RS. That is, the Client can first receive the JWT in an AS-to-Client response encoded in CBOR (JSON). Then, the Client can upload the JWT to the RS in a way that makes the RS believe that the Client instead received the JWT in an AS-to-Client response encoded in JSON (CBOR).

Consequently, the RS considers a different HASH_INPUT than the one considered by the AS and the Client. Hence, the RS computes a different token hash h' than the token hash h computed by the AS and the Client. It follows that, if the AS revokes the access token and advertises the right token hash h, then the RS will not learn about the access token revocation and thus will not delete the access token.

Fundamentally, this happens because the HASH_INPUT used for a JWT depends on whether the AS-to-Client response is encoded in CBOR or in JSON. This makes the RS vulnerable to the attack above, when JWTs are used as access tokens.

Instead, this is not a problem if the access token is a CWT, since the HASH_INPUT used for a CWT is the same, irrespective of whether the AS-to-Client response is encoded in CBOR or in JSON.

While this asymmetry cannot be avoided altogether, it has been deliberately chosen to penalize the case where the RS uses JWTs as access tokens. In such a case, the RS neutralizes the attack above by computing and storing two token hashes associated with the same access token.

As a result, this favors the case case where the RS uses CWTs as access tokens, which is the default case in the ACE framework (see Section 3 of RFC 9200) and a preferable option for resource-constrained RSs. That is, if a RS uses CWTs as access tokens, then the RS is not exposed to the attack above, and thus it computes and stores only one token hash per access token.

<==


* In regard to section 5.2, "Query Parameters":

   *  'cursor': if included, it indicates to perform a diff query of the
      TRL together with the "Cursor" extension, as defined in
      Section 8.2.  Its value MUST be either 0 or a positive integer.

The way the document is written suggests that "cursor" is an optional
extension of "diff", which is itself an optional feature.  Naively,
that suggests that a query with "cursor" must necessarily include
"diff".  But that is not stated in the document.

However, I'm having a hard time making out the design concept behind
the stated requirements.

This paragraph says that if the AS *does not* support Cursor, then it
MUST *process* GETs with 'cursor' and without 'diff', as a full query
(i.e., without reporting an error):

      If the AS does not support the "Cursor" extension, it ignores the
      'cursor' query parameter when present in the GET request.  In such
      a case, the AS proceeds: i) like when processing a diff query of
      the TRL (see Section 7), if it supports diff queries and the
      'diff' query parameter is present in the GET request; or ii) like
      when processing a full query of the TRL (see Section 6) otherwise.

These paragraphs say that if the AS *does* support Cursor, then if it
receives a GET with 'cursor' and without 'diff' it MUST *report a 4.00
error*:

      If the AS supports both diff queries and the "Cursor" extension,
      and the GET request specifies the 'cursor' query parameter, then
      the AS MUST return a 4.00 (Bad Request) response in case any of
      the conditions below holds.

      ...

      -  The GET request does not specify the 'diff' query parameter,
         irrespective of the value of the 'cursor' parameter.

It seems that whether such a query is valid depends on whether the AS
supports Cursor or not; certain ASs are required to treat such a query
as valid and other ASs are required to treat it as an error.

I suggest rectifying the ontology by saying

   *  'cursor': if included, it indicates to perform a diff query of the
      TRL together with the "Cursor" extension, as defined in
      Section 8.2.  Its value MUST be either 0 or a positive integer.
      If included, the 'diff' parameter MUST also be included.

and simplifying the above paragraph to:

      If the AS does not support the "Cursor" extension, it ignores the
      'cursor' query parameter when present in the GET request.  In such
      a case, the AS proceeds as specified elsewhere in this document.

That change doesn't change the inconsistent responses to "cursor
without diff", but it makes it clear that the requester is making an
error.

==>MT

As to the paragraph

> 'cursor': if included, it indicates ...

we have adopted the suggestion above and added the following sentence at its end:

> If the 'cursor' query parameter is included, then the 'diff' query parameter MUST also be included.

As to the paragraph:

> If the AS does not support the "Cursor" extension, it ignores ...

we think that it is still helpful to point to the exact sections of the document that specify the behavior to follow in the two different cases. Hence, we have taken a hybrid approach and rephrased the paragraph as follows:

NEW:
> If the AS does not support the "Cursor" extension, it ignores the 'cursor' query parameter when present in the GET request. In such a case, the AS proceeds as specified elsewhere in this document, i.e.: i) it performs a diff query of the TRL (see Section 7), if it supports diff queries and the 'diff' query parameter is present in the GET request; or ii) it performs a full query of the TRL (see Section 6) otherwise.

<==


* In regard to section 13.5, "Dishonest Clients":

I think that the substance of this section is critical, but the
discussion is unnecessarily restricted to situations where the client
has dishonest intent.  The problem to be addressed is broader, and is
essentially stated in the third paragraph:

   This makes the RS vulnerable during a time interval that starts
   when [the access token is revoked] ends when the RS expunges the
   access token, e.g., after having gained knowledge of its
   revocation.

And during that time interval, it is a security violation if a client
gains access to the resource, whether or not the client's intention is
dishonest or not.

I suggest a revision like

   If a Client attempts to access a protected resource after the
   access token is revoked but before the RS hosting the resource is
   aware of the revocation, it will be able to do so even though it
   should not.  Such an access is a security violation even if the
   Client is not attempting to be malicious.

   In order to minimize such risk, if an RS relies solely on polling
   through individual requests to the TRL endpoint to learn of revoked
   access tokens, the RS SHOULD implement an adequate trade-off
   between the polling frequency and the maximum length of the
   vulnerable time window.

==>MT

Thanks for the very good point and suggestion!

With minor rephrasing to the original proposal, we have revised Section 13.5 to include only include the following text.

> A Client may attempt to access a protected resource at an RS after the access token allowing such an access has been revoked, but before the RS is aware of the revocation.
>
> In such a case, if the RS is still storing the access token, the Client will be able to access the protected resource, even though it should not. Such an access is a security violation, even if the Client is not attempting to be malicious.
>
> In order to minimize such risk, if an RS relies solely on polling through individual requests to the TRL endpoint to learn of revoked access tokens, the RS SHOULD implement an adequate trade-off between the polling frequency and the maximum length of the vulnerable time window.

We have also changed the title of Section 13.5 as follows:

OLD:
> Dishonest Clients

NEW:
> Vulnerable Time Window at the RS

<==


** Editorial issues:

1.  Introduction

It might be worth noting that the process(es) by which a token is
declared revoked, and the method by which the AS is notified of that
(and consequently updates the TRL), is out of scope.  That fact is
implicit in this document, but stating it ensures someone doesn't hunt
through this document looking for a specification of the revocation
process.

==>MT

We have added the following text, as a new paragraph at the end of Section 1.0.

> The process by which access tokens are declared revoked is out of the scope of this document. It is also out of scope the method by which the AS determines or is notified of revoked access tokens, according to which the AS consequently updates the TRL as specified in this document.

<==


2.  Protocol Overview

      After the registration procedure is finished [...]  device can
      send an Observation Request to the TRL endpoint as [...]

      At any time, the registered device can send a GET request to the
      CTRL endpoint.  When doing so, it can request for: the current
      [...]

It seems that these two paragraphs are separate items and should be
marked with "*" like other items in the list.

==>MT

The two cited paragraphs are not intended to be as separate as distinct bullet points. They are both about the access of a registered device to the TRL endpoint, with the first paragraph covering the subscription case, and the second paragraph being more generic (irrespective of subscribing with Observe or not).

Based on this comment, we have revised the text as follows, while still keeping them under the same outer bullet point "When a device registers at the AS ...".

OLD
> When a device registers at the AS, it also receives the url-path to the TRL endpoint.
>
> After the registration procedure is finished, the registered device can send an Observation Request to the TRL endpoint as described in [RFC7641], i.e., a GET request including the CoAP Observe Option set to 0 (register). By doing so, the registered device effectively subscribes to the TRL, as interested to receive notifications about its update. Upon receiving the request, the AS adds the registered device to the list of observers of the TRL endpoint.
>
> At any time, the registered device can send a GET request to the TRL endpoint. When doing so, it can request for: the current list of pertaining revoked access tokens (see Section 6); or the most recent updates occurred over the list of pertaining revoked access tokens (see Section 7). In either case, the registered device may also rely on an Observation Request for subscribing to the TRL as discussed above.

NEW
> When a device registers at the AS, it also receives the url-path to the TRL endpoint.
>
> At any time after the registration procedure is finished, the registered device can send a GET request to the TRL endpoint at the AS. When doing so, it can request for: the current list of pertaining revoked access tokens (see Section 6); or the most recent updates occurred over the list of pertaining revoked access tokens (see Section 7).
>
> In particular, the registered device can rely on Observation for CoAP [RFC7641]. In such a case, the GET request sent to the TRL endpoint includes the CoAP Observe Option set to 0 (register), i.e., it is an Observation Request. By doing so, the registered device effectively subscribes to the TRL, as interested to receive notifications about its update. Upon receiving the Observation Request, the AS adds the registered device to the list of observers of the TRL endpoint.

Also, later in the same section, "observation request" has been changed to "Observation Request" for consistency.

<==


      Depending on the specific subscription established through the
      observation request, the notification provides the current updated
      list of revoked access tokens in the subset of the TRL pertaining
      to that device (see Section 6), or rather the most recent TRL
      updates occurred over that list of pertaining revoked access
      tokens (see Section 7).

Instead of "or rather", the wording probably should be "or
alternatively" or "or, if the 'diff' parameter is in effect,".

==>MT

The 'diff' parameter is inconvenient to use here, as it is introduced only much later in the document. We have made an even simpler phrasing, and just removed "rather". That is:

NEW:
> Depending on the specific subscription established through the Observation Request, the notification provides the current updated list of revoked access tokens in the subset of the TRL pertaining to that device (see Section 6), or the most recent TRL updates occurred over that list of pertaining revoked access tokens (see Section 7).

<==


   *  An administrator can access and subscribe to the TRL like a
      registered device, while getting the full updated content of the
      TRL.

Perhaps better phrased

   *  An administrator can access and subscribe to the TRL like a
      registered device, while getting updates of the full
      content of the TRL.

since there is no "un-updated content of the TRL".

==>MT

Taking the suggestion into account, we thought of further expanding the text, in order to avoid possible confusion between the full up-to-date TRL content obtained through a full query, and a list of most recent updates to the TRL obtained through a diff query.

As a result, we have rephrased as follows:

NEW:
> An administrator can access and subscribe to the TRL like a registered device, while getting the content of the whole TRL (see Section 6) or the most recent updates occurred to the whole TRL (see Section 7).

<==


   Consistently, the AS adds the three token hashes to the TRL at once,

Does "Consistently" carry any specific meaning here?  Actually, I
think you mean "Consequently", that is, in consequence of the
simultaneous revocation of three tokens.  And if so, combining this
paragraph with the preceding one would clarify that the actions in
this sentence were consequent to the actions in the preceding
sentence.

==>MT

We have rephrased as suggested. That is:

OLD
> ... respectively.
>
> Consistently, the AS adds ...

NEW
> ... respectively. Consequently, the AS adds ...

<==


3.  Token Hash

       *  If the content of the 'access_token' parameter from step 1 is
          a CBOR byte string, then HASH_INPUT takes the binary
          serialization of that CBOR byte string.  This is the case
          where CBOR was used to transport the Access Token (as a CWT or
          JWT).

          With reference to the example in Figure 2, and assuming the
          string's length in bytes to be 119 (i.e., 0x77 in
          hexadecimal), then HASH_INPUT takes the bytes {0x58 0x77 0xd0
          0x83 0x44 0xa1 ...}, i.e., the raw content of the
          'access_token' parameter.

I would change "HASH_INPUT takes" to "HASH_INPUT is".  And similarly
in the next item.

Probably better phrased "... HASH_INPUT is the CBOR encoding of the
byte string." and "... i.e., the CBOR-encoded content of the
'access_token' parameter."  (Unless the process is revised as
discussed in "Technical issues".)

==>MT

Within the bullet point 2, we have changed the three instances of "HASH_INPUT takes" to be "HASH_INPUT is", as suggested.

Also, we have replaced the three instances of "binary serialization" to be "binary representation".

As to the other suggested rephrasing, we have actually revised the text of Section 3 when addressing the related technical comment (see above).

<==


5.  The TRL Endpoint

   *  Diff query: [...]

      The entry associated with one of such updates contains a list of
      token hashes, such that: i) the corresponding revoked access
      tokens pertain to the requester; and ii) they were added to or
      removed from the TRL at that update.

This seems awkward to me.  Perhaps better:

      The entry associated with one of such updates contains the list
      of token hashes which were added to or removed from the TRL at
      that update and for which the corresponding revoked access
      tokens pertain to the requester.

==>MT

We have rephrased as below, after minor editing to the original suggestion.

NEW:
> The entry associated with one of such updates contains the list of token hashes that were added to or removed from the TRL at that update, and for which the corresponding revoked access tokens pertain to the requester.

<==


--

   First, the AS can avoid
   excessively big latencies when several diff entries have to be
   transferred, by delivering one adjacent subset at the time, in
   different diff query responses.

This seems awkward to me.  Perhaps better:

   First, the AS can avoid excessively long messages when several diff
   entries have to be transferred, by delivering several diff query
   responses, each containing one adjacent subset at a time.

==>MT

We have rephrased as suggested.

<==


5.1.  Supporting Diff Queries

   The AS MUST keep track of the MAX_N most recent updates to
   the subset of the TRL that pertains to each requester.

Clearer to say

   For each requester, the AS MUST keep track of the MAX_N most recent
   updates to the subset of the TRL that pertain to the requester.

==>MT

We have adopted the proposed rephrasing as-is, except for s/pertain/pertains.

(In the original formulation, "pertains" refer to "subset")

In the same third paragraph, we have also added a new first sentence and removed some following redundant text, thus highlighting upfront that MAX_N is a single-instance parameter.

Overall, the new text reads as follows:

OLD:
> For each requester, the AS maintains an update collection of maximum MAX_N series items, where MAX_N is a pre-defined, constant positive integer. The AS MUST keep track of the MAX_N most recent updates to the subset of the TRL that pertains to each requester. The AS SHOULD provide requesters with the value of MAX_N, upon their registration (see Section 9).

NEW:
> The AS defines the single, constant positive integer MAX_N >= 1. For each requester, the AS maintains an update collection of maximum MAX_N series items. For each requester, the AS MUST keep track of the MAX_N most recent updates to the subset of the TRL that pertains to the requester.

<==


--

   6.  The AS adds the series item to the update collection associated
       with the requester, as the most recent one.

Better

   6.  The AS adds the series item to the update collection associated
       with the requester, as the last (most recent) one.

==>MT

We have rephrased as suggested.

<==


5.1.1.  Supporting the "Cursor" Extension

   The AS defines the constant, unsigned integer MAX_INDEX <= ((2^64) -
   1), where "^" is the exponentiation operator.  In particular, the
   value of MAX_INDEX is REQUIRED to be at least (MAX_N - 1), and is
   RECOMMENDED to be at least ((2^32) - 1).

"In particular" isn't quite right when specifying a further
constraint.  Just start "The value of MAX_INDEX ..."

==>MT

We have removed "In particular". Also, we have added "single" in the previous sentence, thus highlighting upfront that MAX_INDEX is a single-instance parameter.

The result is as follows:

NEW:
> The AS defines the single, constant unsigned integer MAX_INDEX <= ((2^64) - 1), where "^" is the exponentiation operator. The value of MAX_INDEX is REQUIRED to be ...

<==


   Note that MAX_INDEX is practically expected to be order of
   magnitudes greater than MAX_N.

The phrase you want is either "an order of magnitude", meaning
MAX_INDEX >= 10 * MAX_N, or "orders of magnitude", meaning (more
intense but less precise) MAX_INDEX is expected to be >= 100 * MAX_N.
But you probably want to use "SHOULD", perhaps like this

   MAX_INDEX SHOULD be (at least an order of magnitude)/(orders of
   magnitude) greater than MAX_N.

==>MT

We have changed the text to be as follows.

NEW:
> ... to be at least ((2^32) - 1).
>
> MAX_INDEX SHOULD be orders of magnitude greater than MAX_N.

<==


Given the error processing in the last-but-one paragraph of 5.2, you
should add a warning:

   MAX_INDEX SHOULD be (at least an order of magnitude)/(orders of
   magnitude) greater than MAX_N.  Note that section 5.2 requires
   "Cursor" processing to return errors to a requester after index
   wrap-around has occurred for that requester, so a small value of
   MAX_INDEX will cause GETs to return errors when otherwise they
   would not.

==>MT

Please note that the raised issue does not apply.

Quoting the text from Section 5.2 mentioned in the comment:

> If the AS supports both diff queries and the "Cursor" extension, and the GET request specifies the 'cursor' query parameter, then the AS MUST return a 4.00 (Bad Request) response in case any of the conditions below holds.
> ...
> - All of the following hold: the update collection associated with the requester is not empty; no wrap-around of its 'index' value has occurred; and the 'cursor' query parameter has a value strictly greater than the current 'last_index' on the update collection (see Section 5.1.1).

Section 5.2 does **NOT** require "to return errors to a requester after index wrap-around has occurred for that requester".

The error here is triggered by the query parameter 'cursor' having a value X such that 'last_index' < X <= MAX_INDEX, **AND** a wrap-around of 'index' that has **NOT** happened yet. That is, the provided value of 'cursor' would be pointing to an item that has never existed, hence the error.

After a wrap-around of 'index' has occurred, there is no error condition as long as the value of the query parameter 'cursor' does not exceed MAX_INDEX. Irrespective of a wrap-around having occurred or not, that's a separate error condition, which is covered by the previous bullet point in the same list of error conditions in Section 5.2.

So there is no particular warning to give.

<==


--

   When maintaining the history of updates to the TRL, the following
   applies separately for each update collection.

Clearer to say

   When maintaining the history of updates to the TRL, the following
   applies separately for each requester's update collection.

==>MT

We have rephrased as suggested.

In a similar fashion, we have rephrased the first sentence of the last paragraph in Section 5.1.1 as follows.

OLD
> For each update collection, the AS also defines a constant, positive integer MAX_DIFF_BATCH <= MAX_N

NEW
> For each requester's update collection, the AS also defines a constant, positive integer MAX_DIFF_BATCH <= MAX_N

<==


--

      If the update collection is not empty, 'last_index' has the
      value of 'index' currently associated with the latest added
      series item in the update collection.

Note that "the latest added series item" is the same as "the last
series item".

==>MT

We have changed "the latest added series item" to be "the last series item".

<==


      As long as a wrap-around of the 'index' value has not occurred,
      the value of 'last_index' is the absolute counter of series items
      added to that update collection until and including V, minus 1.

I think "until and including V" should be removed, as "V" isn't the
name of any thing, and the sentence has the right meaning without
those words.  That is,

      As long as a wrap-around of the 'index' value has not occurred,
      the value of 'last_index' is the absolute counter of series items
      added to that update collection, minus 1.

==>MT

We have rephrased as suggested.

<==


--

   The specific value depends on the specific registered
   device or administrator associated with the update collection in
   question.

Strictly, you want to add "MAY", because some implementations may use
the same value for all devices/administrators:

   The specific value MAY depend on the specific registered
   device or administrator associated with the update collection in
   question.

==>MT

We have rephrased as suggested.

<==


6.  Full Query of the TRL

       *  The 'full_set' parameter MUST be included and specifies a CBOR
          array 'full_set_value'.

There are quotes around 'full_set_value' as if the value is a
parameter name, but "full_set_value" is only used in this document to
describe how the response is assembled (similarly to "HASHES",
"HASH_INPUT", etc.) and there's no need to quote its name.

Similarly for 'diff_entry', 'diff_set_value' and some other variables
in various places.

==>MT

We prefer to keep the current notation.

Those identifiers are often used to denote and refer to CBOR data items, or elements used for composing those.

The used notation is also convenient where used with single-word identifiers, to avoid sentences that might otherwise be harder to parse (think, e.g., of 'removed' and 'added').

<==


7.  Diff Query of the TRL

       *  The 'diff_set' parameter MUST be present and specifies a CBOR
          array 'diff_set_value' of U elements.  Each element of
          'diff_set_value' specifies one of the CBOR arrays 'diff_entry'
          prepared above as diff entry.

s/as diff entry/as a diff entry/

==>MT

We have fixed it as suggested, also in Sections 8.2.2 and 8.2.3.

<==


          Their values are specified according to what is defined in
          Section 8.2, [...]

Can be simplified to "Their values are specified in Section 8.2, [...]".

==>MT

Well, Section 8.2 does not specify the values, but how to determine/compute those.

Still, we have simplified the text as follows.

NEW:
> Their values are set as specified in Section 8.2, ...

We have made a similar rephrasing also earlier in Section 6, i.e.:

OLD:
> Its value is specified according to what is defined in Section 8.1,

NEW:
> Its value is set as specified in Section 8.1, ...

<==


   Figure 7 shows an example of response from the AS, [...]

Can be simplified to "[...] shows an example response [...]".

==>MT

We have rephrased as suggested.

We have also made a similar rephrasing earlier in Section 6, i.e.:

OLD:
> Figure 5 shows an example of response from the AS, ...

NEW:
> Figure 5 shows an example response from the AS, ...

<==


8.  Response Messages when Using the "Cursor" Extension

   If it supports both diff queries and the "Cursor" extension, the AS
   composes a response [...]

Clearer to say

   If the AS supports both diff queries and the "Cursor" extension, it
   composes a response [...]

==>MT

We have rephrased as suggested.

<==


8.2.2.  Cursor Not Specified in the Diff Query Request

   [...] the AS performs the same actions defined in Section 7,
   with the following differences.

Can be simplified as

   [...] the AS performs the actions defined in Section 7,
   with the following differences.

==>MT

We have rephrased as suggested.

We have also made a similar rephrasing later in Section 8.2.3, i.e.:

OLD:
> In this case, the AS performs the same actions defined in Section 7, with the following differences.

NEW:
> In this case, the AS performs the actions defined in Section 7, with the following differences.

<==


--

         If the 'more' parameter has value "true", the requester can
         send [...]

This paragraph should be at the normal left margin (which is outdented
from its current position).

==>MT

We have brought the quoted paragraph to the normal left margin as suggested.

To ensure that proper context is given, we have rephrased its first sentence as follows.

OLD:
> If the 'more' parameter has value "true", the requester can ...

NEW:
> If the 'more' parameter in the payload of the received 2.05 (Content) response has value "true", the requester can ...

We have also made a similar repositioning and rephrasing later in Section 8.2.3. That is, its last paragraph has been given the same indentation as the paragraph "In this case, the AS performs ...", and has been rephrased as followed.

OLD:
> If 'more' has value "true", the requester can ...

NEW:
> If the 'more' parameter in the payload of the received 2.05 (Content) response has value "true", the requester can ...

<==


9.  Registration at the Authorization Server

   *  The hash function used to compute token hashes.  This is specified
      as an integer or a text string, taking value from the "ID" or
      "Hash Name String" column of the "Named Information Hash
      Algorithm" Registry [Named.Information.Hash.Algorithm],
      respectively.

Actually, given that the registration process is seemingly not
specified anywhere, the only thing that can be specified in this
document is the overall semantic effect, which is that some entry in
the registry is specified by some method:

   *  The hash function used to compute token hashes.  This is specified
      by identifying an entry in the "Named Information Hash
      Algorithm" Registry [Named.Information.Hash.Algorithm].  The
      specific means for this is outside the scope of this document.

==>MT

We have rephrased as suggested.

<==


10.  Notification of Revoked Access Tokens

In what way does the AS record the types of observation responses that
the client is capable of understanding?  There seem to be three
varieties, full, diff, and diff-with-cursor.  I would guess that the
absence of diff in the GET-with-Observe indicates that full
observation responses must be sent, the presence of diff without
cursor indicates that diff responses (using the saved value of the
'diff' parameter) must be sent, and the presence of diff and cursor
indicates that cursor responses must be sent (with the AS caching the
cursor value from one response to generate the next response).  But
all of this seems to be only implicit in this document and needs to be
specified.

==>MT

Irrespective of using Observe or not, the client sends a GET request consistent with what it understands and supports. As summarized in the comment, a request from the client asks the AS to reply according to:

* The full query mode, if the 'diff' query parameter is not present in the GET request.
* The diff query mode, if the 'diff' query parameter is present in the GET request.
* The diff query mode with the "Cursor" extension, if both the 'diff' and 'cursor' query parameters are present in the GET request.

This is consistent with what is defined in Section 5.2, which applies for GET requests in general and for GET Observe Requests in particular.

(The following also relates to the second technical comment "The Observe mechanism requires that the AS ...")

When the client uses Observe, the AS records the type of observation responses to return simply based on the GET Observation Request that started the observation and that the AS stores for the duration of the observation. That is, as stated in Section 10 of the present document:

> Observe notifications are sent as per Section 4.2 of [RFC7641].

Where Section 4.2 of [RFC7641] says:

> A client is notified of changes to the resource state by additional responses sent by the server in reply to the GET request.

That is, upon changes to the TRL, the AS sends an Observe notification response to an observer client like if the AS had just received the stored GET Observation Request from that observer, i.e., consistent with the conveyed query parameters (if any). This document is not adding or altering the behavior defined in RFC 7641, which is simply inherited.

Consequently, the AS sends Observe notification responses as summarized in the comment, with one difference: if the GET Observe Request includes both the 'diff' and the 'cursor' query parameters, then the Observe notification responses will not be based on "the AS caching the cursor value from one response to generate the next response". Instead, the AS will consistently consider the value of the 'cursor' parameter specified in the 'cursor' query parameter of the GET Observation Request.

<==


   Once completed the registration procedure at the AS, [...]

Maybe better "After completing the registration procedure at the AS,
[...]".

==>MT

Building on the simpler formulation in the first paragraph of Section 1, we have rephrased as follows.

OLD
> Once completed the registration procedure at the AS, the administrator or registered device can send a GET request to the TRL endpoint at the AS.

NEW
> Once registered at the AS, the administrator or registered device can send a GET request to the TRL endpoint at the AS.

<==


   When doing so, the requester towards the TRL endpoint can perform a
   full query (see Section 6) or a diff query (see Section 7) of the
   TRL.

Or for that matter, a diff-with-cursor query (see Section 8).

==>MT

We have rephrased as follows.

OLD
> When doing so, the requester towards the TRL endpoint can perform a full query (see Section 6) or a diff query (see Section 7) of the TRL.

NEW
> When doing so, the requester towards the TRL endpoint can perform a full query (see Section 6) or a diff query (see Section 7) of the TRL. In the latter case, the requester can additionally rely on the "Cursor" extension (see Sections 5.2 and 8.2).

This formulation is also consistent with what was eventually agreed as to the presentation of this protocol: it has two modes of operation, one of which with the optional "Cursor" extension.

<==


10.1.  Handling of Access Tokens and Token Hashes

   An RS stores a token hash th1 corresponding to an access token t1
   until both the following conditions hold.

It seems like this should be "MUST store".

==>MT

We have rephrased as follows.

OLD:
> An RS stores a token hash th1 ...

NEW:
> An RS MUST store the token hash th1 ...

<==


11.  ACE Token Revocation List Parameters

   The table below summarizes them, and specifies the CBOR value to use
   as abbreviation instead of the full descriptive name.

This sort of thing is probably conventional in CBOR, but to the naive
reader a more explicit explanation is useful.  Perhaps

   The table below summarizes the parameters, and specifies the CBOR
   value to use as the key in the map pair for the parameter instead
   of the string that is used as the parameter's name in this document.

==>MT

Based on this comment and the later comment about Section 14.3 together with its resolution, we have rephrased as follows:

OLD:
> The table below summarizes them, and specifies the CBOR value to use as abbreviation instead of the full descriptive name.

NEW:
> The table below summarizes the parameters. For each of them, it specifies the value to use as CBOR key, i.e., as abbreviation in the key of the map pair for the parameter, instead of the parameter's name as a text string.

Also, the table headers "CBOR Value" and "CBOR Type" have been changed to "CBOR Key" and "Value Type", respectively.

Please note that a parameter's name is not simply "used in this document"; it is also registered in the newly defined "ACE Token Revocation List Parameters" Registry (see Section 14.3), together with the corresponding CBOR key used as abbreviation.

<==


13.  Security Considerations

   Security considerations are inherited from the ACE framework for
   Authentication and Authorization [RFC9200], [...]

It would be clearer to state

   ACE token revocation notification inherits the security
   considerations from the ACE framework for Authentication and
   Authorization [RFC9200], [...]

==>MT

After slightly editing the original suggestion, we have rephrased as follows.

NEW:
> The protocol defined in this document inherits the security considerations from the ACE framework for Authentication and Authorization [RFC9200], ...

<==


13.1.  Content Retrieval from the TRL

   To this end, the AS can perform the required filtering [...]

Probably better to be normative:

   To this end, the AS MAY perform the required filtering [...]

unless the intention is to assert that an AS can always use this
method to perform the required filtering, in which case "can" should
be "can always".

==>MT

The latter interpretation is the correct one, consistent with Section 5 of RFC 9200, which says:

> For the AS to be able to issue a token, the client MUST be authenticated and present a valid grant for the scopes requested. Profiles of this framework MUST specify how the AS authenticates the client and how the communication between the client and AS is protected, ...

So, we have rephrased as follows:

NEW:
> To this end, the AS can always perform the required filtering ...

<==


   Disclosing any information about revoked access tokens to entities
   other than the intended registered devices [...]

"intended" is not well defined here.  "pertain" should be used
instead.  I think you want to say

   Disclosing any information about revoked access tokens to entities
   to which they do not pertain [...]

==>MT

We have rephrased as suggested.

<==


13.2.  Size of the TRL

   Issuing access tokens with not too long expiration time could help
   reduce [...]

Less awkward to say

   Issuing access tokens with limited expiration time could help
   reduce [...]

==>MT

By combining another comment received on this sentence and the suggestion above, we have rephrased as follows.

OLD:
> Issuing access tokens with not too long expiration time could help reduce the size of the TRL, but an AS SHOULD take measures to limit this size.

NEW:
> Therefore, in order to help reduce the size of the TRL, the AS SHOULD refrain from issuing access tokens with an excessively long expiration time.

<==


13.4.  Request of New Access Tokens

   [...] the Client might anyway receive an unprotected 4.01
   (Unauthorized) response from the RS.

Probably better to say

   [...] the Client may receive an unprotected 4.01 (Unauthorized)
   response from the RS.

since the next paragraph explains why it might receive such a
response.

==>MT

We have rephrased as suggested.

<==


--

   This can be due to different reasons.  For example, the access token
   has actually been revoked and the Client is not aware about that yet,
   while the RS has gained knowledge about that and has expunged the
   access token.

Probably better to say

   This can be due to a number of causes.  For example, the access
   token has been revoked, the RS is aware of it and expunged the
   token, but the Client is not aware of it (yet).

==>MT

Building on the suggestion, we have rephrased as follows.

NEW:
> This can be due to a number of causes. For example, the access token has been revoked, and the RS has become aware of it and has expunged the access token, but the Client is not aware of it (yet).

<==


14.3.  ACE Token Revocation List Parameters Registry

   *  CBOR Value: This field contains the value used as CBOR
      abbreviation of the item.

Parallel to the comment on section 11, 

   *  CBOR Value: This field contains the value used as CBOR
      abbreviation of the item, specifically as the key in CBOR maps
      that are values of media type application/ace-trl+cbor.

--

==>MT

Based on this comment, on a previous comment about Section 11, and on what is done in other documents including RFC 9200, we have made the following changes:

OLD:
> CBOR Value: This field contains the value used as CBOR abbreviation of the item.

NEW:
> CBOR Key: This field contains the value used as CBOR map key of the item.

OLD:
> CBOR Type: This field contains the CBOR type of the item, or ...

NEW:
> Value Type: This field contains the allowable CBOR data types for values of this item, or ...

Please note that detailed information such as media types of messages conveying these parameters does not usually appear in the definition of the fields of an IANA registry. This is consistent with what we have, e.g., for IANA registries defined in RFC 9200: see "CBOR Key" in its Sections 8.1 and 8.10.

Indeed, this document uses these abbreviations in payloads of media type "application/ace-trl+cbor", which is why there is a separate Section 11 specifying that and pointing to the IANA registry where to pick values from.

<==


      The value can be an unsigned integer or a negative integer.

I assume the intention is

      The value MUST be an unsigned integer or a negative integer.

rather than MAY.  Similarly for "Value" in the registry of section 14.4.

==>MT

For that particular piece of information, other RFCs do not use normative language. See, e.g., Section 9.4 of RFC 9203, which says:

> The label can be a positive integer, a negative integer, or a string.

We have made the following change:

OLD:
> The value can be an unsigned integer or a negative integer.

NEW:
> The value is an unsigned integer or a negative integer.

We have also made the same change in the later Section 14.4.

<==


Appendix B.  Parameters of the TRL Endpoint

"parameters" isn't quite the right word here.  Compare with the use of
"parameters" in section 5.2.

==>MT

We believe that these are indeed parameters of the TRL endpoint used by the AS.

While keeping the word "parameters", we have made the following changes. These highlight how the parameters in question are local to the AS and supportive of the internal operations on the TRL.

OLD (Appendix B):
> Appendix B. Parameters of the TRL Endpoint

NEW (Appendix B):
> Appendix B. Local Supportive Parameters of the TRL Endpoint

OLD (Appendix B):
> Figure 10 provides an aggregated overview of the parameters used by the TRL endpoint, when the AS supports ...

NEW (Appendix B):
> Figure 10 provides an aggregated overview of the local supportive parameters that the AS internally uses at its TRL endpoint, when supporting ...

OLD (Section 5.0):
> Appendix B provides an aggregated overview of the parameters used by the TRL endpoint, when the AS supports ...

NEW (Section 5.0):
> Appendix B provides an aggregated overview of the local supportive parameters that the AS internally uses at its TRL endpoint, when supporting ...


Please note that Section 5.2 unambiguously refers to three different kinds of parameters:

* Mainly "query parameters" (as the main object of that section, per its title), i.e., the parameters that are possible to specify through the Uri-Query CoAP Option of a GET request to the TRL endpoint (e.g., 'diff').

* Parameters that the AS can include in a response from the TRL endpoint, as entries of the CBOR map encoding the message payload (e.g., 'cursor').

* Parameters that are local to the TRL endpoint at the AS and related to the diff query and its possible "Cursor" extension (e.g., "MAX_INDEX", or the 'last_index' associated with the update collection of a requester).

<==


This list seems to combine two things:

"configuration parameters", values which have a single instance and
are constant over long periods of time for a single AS.  For example,
MAX_N, MAX_DIFF_BATCH, and MAX_INDEX.  It is this uniqueness and
constancy that allows the values to be communicated to the client only
"upon registration", an event which seems to be intended to happen
infrequently.

"state variables", values which the AS stores and updates as it
performs its various operations.  I notice that in this situation, a
parameter is a state variable if and only if it has multiple
(per-client) instances, but the fundamental difference is whether the
parameter changes during normal operation, and that difference isn't
clearly noted in this section.

There seem to be a lot of state variables which are not listed here.
The leading example is the TRL itself, but there is also a lot of
information about the observation subscriptions that needs to be
maintained.

==>MT

Please find below our reply, separately to the different parts of this comment.

**General**

At a high level, thinking of "configuration parameters" and "state variables" also makes sense. However, "state variables" are first of all "state parameters", with their values being mutable, hence variable.

Other RFCs use "parameters" to denote "information elements" possibly within a well defined data structure, some of which may be constant/immutable and some other variable.

An example is RFC 8613, where its Section 3.2 "Establishment of Security Context Parameters" defines a Security Context, where only two of its parameters are mutable in value, hence variable, as mentioned already in the earlier section 3.1:

> All parameters except Sender Sequence Number and Replay Window are immutable once the security context is established.

Also, please note that this appendix does not introduce new information, and it is only intended to recap at a glance the different supportive parameters introduced throughout the document, which the AS locally uses at its TRL endpoint to operate the TRL data structure.


**On the "configuration parameters" part**

* The three mentioned parameters MAX_N, MAX_DIFF_BATCH, and MAX_INDEX are indeed immutable once initialized, as denoted by their names in capital letters. However, MAX_DIFF_BATCH has not a single instance, as there is one instance per client (see its value "N" in the column "Single instance").

* Indeed, the constancy of these parameters enables the AS to reliably communicate their values to devices upon their registration. However, the AS is expected to provide devices with the value of MAX_N and the corresponding value of MAX_DIFF_BATCH (see the third paragraph of Section 5.1, the last paragraph of Section 5.1.1, and the recap on Section 9), but it is not expected to provide the value of MAX_INDEX, which is intended for internal use at the AS.


**On the "state variables" part**

* Both 'index' and 'last_index' have a per-client instance and mutable. However, as discussed above, MAX_DIFF_BATCH has a per-client instance, but each of such instances is immutable.

* This section does notice whether a parameter is mutable in value or not. The bullet list above the table says:

  > * Name: parameter name. A name with letters in uppercase denotes a parameter whose value does not change after its initialization.

  Consistent with that convention, MAX_N, MAX_DIFF_BATCH, and MAX_INDEX are immutable, while 'index' and 'last_index' are mutable.


**On missing state variables (final part)**

* The TRL is a data structure encoded as a CBOR array, with its semantics and update operation defined in Section 4. We think that it would be confusing to present the TRL as a "state variable" or a "parameter".

  When addressing the previous comment also about Appendix B, we have introduced the _expression_ "local supportive parameters", which hopefully clarifies this separation.

* Regarding the maintenance of information about the observation subscription, that relies on how Observe is defined in RFC 7641 as-is, which we are not altering or extending in this document. Please see also our reply to a previous, related comment about Section 10.

<==


Appendix C.  Interaction Examples

   The details of the registration process are omitted, but it is
   assumed that the RS sends an unspecified payload to the AS, which
   replies with a 2.01 (Created) response.

   The payload of the registration response is a CBOR map, which
   includes the following entries:

Given that the registration process is (seems to be) entirely
unspecified, the wording should be a little broader:

   Registration is assumed to be done by the RS sending a POST request
   with an unspecified payload to the AS, which replies with a 2.01
   (Created) response.  The payload of the registration response is
   assumed to be a CBOR map which includes the following entries:

Note the absence of a comma in the last sentence, because we also
assume that the response includes the specified entries.  If a comma
was present, we would be asserting that we are *assuming* that the
response is a map, but that assumption *implies* that the map contains
the specified entries.

==>MT

We have rephrased as below, by expanding the last sentence of the new text to explicitly state that two assumptions are made.  I for one have missed the hint from the absent comma :-)

NEW
> Registration is assumed to be done by the RS sending a POST request with an unspecified payload to the AS, which replies with a 2.01 (Created) response. The payload of the registration response is assumed to be a CBOR map, which in turn is assumed to include the following entries:

<==


   *  a 'trl_hash' parameter, specifying the hash function used to
      compute token hashes as defined in Section 3;

might as well flesh out to:

   *  a 'trl_hash' parameter, specifying the "Hash Name String" of the
      hash function used to compute token hashes as defined in
      Section 3;

==>MT

We have rephrased as suggested.

<==


C.1.  Full Query with Observe

          |<---------------------------------------------------+
          |      2.05 CONTENT Observe: 42                      |
          |        Content-Format: "application/ace-trl+cbor"  |
          |        Payload: {                                  |
          |          "full_set" : []                           |
          |        }                                           |
          |                         .                          |
          |                         .                          |
          |                         .                          |
          |                                                    |
          |          (Access tokens t1 and t2 issued           |
          |          and successfully submitted to RS)         |
          |                         .                          |
          |                         .                          |
          |                         .                          |
          |                                                    |
          |                                                    |
          |             (Access token t1 is revoked)           |

This might made easier to draw by (1) making sure that every response
body is followed by an empty line (I initially mistook that the
"Payload" above was followed by more data in the response than is
shown.), and (2) replacing the vertical "..." with a horizontal "..."
(to save space):

          |<---------------------------------------------------+
          |      2.05 CONTENT Observe: 42                      |
          |        Content-Format: "application/ace-trl+cbor"  |
          |        Payload: {                                  |
          |          "full_set" : []                           |
          |        }                                           |
          |                                                    |
          |                        ...                         |
          |          (Access tokens t1 and t2 issued           |
          |          and successfully submitted to RS)         |
          |                        ...                         |
          |             (Access token t1 is revoked)           |

==>MT

In all the five examples shown in Appendix C, we have made the suggested changes, while adding an empty line also between "..." and the preceding/following inline comment.

<==


C.3.  Full Query with Observe plus Diff Query

   The example also considers one of the notifications from the AS to
   get lost in transmission, and thus not reaching the RS.
   [...]
          |  X<------------------------------------------------+
          |      2.05 CONTENT Observe: 86                      |
          |        Content-Format: "application/ace-trl+cbor"  |

You might want to make the message loss more obvious.  (I overlooked
it the first time I read this section.)  Perhaps

          |   Lost <-------------------------------------------+
          |      2.05 CONTENT Observe: 86                      |
          |        Content-Format: "application/ace-trl+cbor"  |

Similarly in section C.5.

==>MT

Both in Appendix C.3 and Appendix C.5, we have made the following change, combining the current notation with the suggested one.

OLD:
> |  X<------------------------------------------------+

NEW:
> |  Lost X <------------------------------------------+

<==


[END]




-- 
Marco Tiloca
Ph.D., Senior Researcher

Phone: +46 (0)70 60 46 501

RISE Research Institutes of Sweden AB
Box 1263
164 29 Kista (Sweden)

Division: Digital Systems
Department: Computer Science
Unit: Cybersecurity

https://www.ri.se

Attachment: OpenPGP_0xEE2664B40E58DA43.asc
Description: OpenPGP public key

Attachment: OpenPGP_signature.asc
Description: OpenPGP digital signature

-- 
last-call mailing list -- last-call@xxxxxxxx
To unsubscribe send an email to last-call-leave@xxxxxxxx

[Index of Archives]     [IETF Annoucements]     [IETF]     [IP Storage]     [Yosemite News]     [Linux SCTP]     [Linux Newbies]     [Mhonarc]     [Fedora Users]

  Powered by Linux