RFC 8946

Personal Assertion Token (PASSporT) Extension for Diverted Calls

πŸ“… published February 2021, from ietf

RFC 8946: Personal Assertion Token (PASSporT) Extension for Diverted Calls πŸ“žπŸ’–

Title block tea β˜• This one is by J. Peterson from Neustar, dated February 2021, and it's on the Standards Track (so it's a real, official spec, not just an idea πŸ‘‘). It updates RFC 8224, which is written as Updates: 8224 in the header. The ISSN is 2070-1721. Okay, now let's get into it! ✨


Abstract 🌸

Okay so the Personal Assertion Token (PASSporT) is specified in RFC 8225 and it's how we send cryptographically signed info about the people in a personal call, like who's calling and who's getting it πŸ”. This doc adds a new thing to PASSporT: a way to say a call got diverted from where it was first going to a new place πŸ¦‹. This is huge for verification services handling call forwarding, because they can make way better calls about whether a call is legit πŸ’…. It also defines a way to nest one PASSporT inside another, which helps relying parties in some diversion situations 🧚.

This document updates RFC 8224.


Status of This Memo πŸ“‹

This is an Internet Standards Track document. Like, it's official 😭

This is a product of the Internet Engineering Task Force (IETF), so it represents what the IETF community agreed on 🫢. It got public review and was approved by the Internet Engineering Steering Group (IESG). If you want more about Internet Standards, check out Section 2 of RFC 7841 🌈.

For the latest status, errata, and how to send feedback, go to https://www.rfc-editor.org/info/rfc8946 πŸ”—.


Copyright (c) 2021 IETF Trust and the persons identified as the document authors. All rights reserved πŸ’œ.

This document is subject to BCP 78 and the IETF Trust's Legal Provisions Relating to IETF Documents (https://trustee.ietf.org/license-info) as they stood on the publication date. Read those carefully, bestie, because they explain your rights and restrictions for this document πŸ“œ. Code Components pulled out of this document must include Simplified BSD License text as described in Section 4.e of the Trust Legal Provisions, and they come without warranty, as the Simplified BSD License describes πŸ’€.


Table of Contents πŸ—ΊοΈ

   1.  Introduction
   2.  Terminology
   3.  The "div" PASSporT Type and Claim
   4.  Using "div" in SIP
     4.1.  Authentication Service Behavior
     4.2.  Verification Service Behavior
   5.  The "div-o" PASSporT Type
     5.1.  Processing "div-o" PASSporTs
   6.  Definition of "opt"
   7.  "div" and Redirection
   8.  Extending "div" to Work with Service Logic Tracking
   9.  IANA Considerations
     9.1.  JSON Web Token Claims Registrations
       9.1.1.  "div" registration
       9.1.2.  "opt" registration
     9.2.  PASSporT Type Registrations
   10. Privacy Considerations
   11. Security Considerations
   12. References
     12.1.  Normative References
     12.2.  Informative References
   Appendix A.  Keys for Examples
   Acknowledgments
   Author's Address

1. Introduction πŸ¦‹

Okay so a PASSporT [RFC8225] is a token format built on the JSON Web Token (JWT) [RFC7519]. Its whole job is conveying cryptographically signed info about the people involved in personal communications πŸ”. The Secure Telephone Identity Revisited (STIR) protocol [RFC8224] uses it to pass along a signed assertion of who the participants are in real-time communications set up through a protocol like SIP πŸ“ž. This spec extends PASSporT so it can show that a call was diverted from its original destination to a new one ✨.

Now, the STIR problem statement [RFC7340] is mainly about stopping caller impersonation, which is a big enabler for stuff like robocalling and voicemail hacking on the phone network today πŸ™…β€β™€οΈ. But it also signs the called number at the moment the authentication service sees it πŸ’…. As [RFC8224], Section 12.1 describes, that protection over the To header field contents is meant to stop a class of cut-and-paste attacks πŸ™ˆ. Say Alice calls Bob. Bob could cut and paste the Identity header field from Alice's INVITE into a new INVITE he sends to Carol, and suddenly Carol thinks the call came from Alice and not Bob 😭. But because the signature covers the To header field value, the INVITE Carol sees clearly was originally meant for Bob, so Carol can treat it as suspicious πŸ•΅οΈβ€β™€οΈ.

Here's the tea though. As [RFC8224], Section 12.1.1 points out, it's hard for Carol to confirm or reject those suspicions using only the info in the baseline PASSporT object πŸ₯². Call forwarding is the perfect example, since the original called number isn't always the number the call actually gets delivered to πŸ“². There are a few ways intermediaries can flag that forwarding happened 🧚. Baseline SIP behavior [RFC3261] says the To header field value in SIP requests isn't supposed to change, and it's the Request-URI that's supposed to get updated when a call is retargeted 🎯. In practice though, lots of operational environments do change the To header field anyway 😬. The History-Info header field [RFC7044] was made to store the Request-URIs that a call discards while it's in transit πŸ“š. The SIP Diversion header field [RFC5806] is historic, but some operators still use it for this purpose today πŸ¦•. Neither one gives any cryptographic assurance of secure redirection, and they both record entries for tiny syntactic changes in URIs that don't actually reflect a change to the call's real target πŸ™„.

So this spec adds an explicit indication to PASSporT that the original called number no longer reflects where the call is supposed to be delivered πŸ’–. For that, it defines a Divert PASSporT type ("div") for common SIP retargeting cases πŸŽ€. In this case, SIP INVITE requests are expected to carry multiple Identity header fields, each with its own PASSporT 🫢. Throughout this document, PASSporTs that contain a "div" element are called "div" PASSporTs 🌈. Verification services and the relying parties making authorization decisions about communications can use this diversion indication to confirm that a legit retargeting happened, instead of a cut-and-paste attack πŸ‘‘. For out-of-band use cases [RFC8816] and other non-SIP uses of PASSporT, there's also a separate "div-o" PASSporT type πŸ“. It defines an "opt" PASSporT element for carrying nested PASSporTs inside a PASSporT 🧩. In this document, these shall in turn be referred to as "div-o" PASSporTs πŸ’œ.


2. Terminology πŸ’…

Okay, the key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be read as described in BCP 14 [RFC2119] [RFC8174]. But they only count when they show up in all capitals, exactly like this, so lowercase versions are just regular words πŸ€“βœ¨.

3. The "div" PASSporT Type and Claim πŸŽ€

okay so this section is where the "div" PASSporT type gets introduced, and it is such a main character moment πŸ’…. This spec defines a PASSporT [RFC8225] type called "div", and it's meant for authentication services sitting at retargeting entities. Every "div" PASSporT MUST contain a brand new JSON Web Token "div" claim (also defined right here) that tells you the previous destination for a call during its routing process πŸ¦‹. When a retargeting entity gets a call signed with a PASSporT, it MAY act as an authentication service and create a new PASSporT with the "div" claim to attach to the call ✨.

ngl the big thing to remember is that a new PASSporT is only needed when the canonical form of the "dest" identifier (per the canonicalization procedures in [RFC8224], Section 8.3) actually changes because of the retargeting πŸ™ˆ. If the canonical form of "dest" stays the same during retargeting, then a new PASSporT with a "div" claim MUST NOT be produced πŸ’€.

The headers of the new PASSporTs made by retargeting entities MUST include the "div" PASSporT type, plus an "x5u" field pointing to a credential that the retargeting entity controls 🫢. "div" PASSporTs MUST use full form instead of compact form πŸ“. Here's what the new PASSporT header looks like:

{ "typ":"passport",
  "ppt":"div",
  "alg":"ES256",
  "x5u":"https://www.example.com/cert.cer" }

A "div" PASSporT claims set gets filled with elements pulled from the PASSporT(s) the retargeting entity received for a call 🌸. At a high level, the original identifier for the called party in the "dest" object becomes the "div" claim in the new PASSporT ✨. If the original "dest" object has multiple identifiers (because it has one or more name/value pairs whose value is an array), the retargeting entity MUST select only one identifier from those values to occupy the "div" field in the new PASSporT πŸ‘‘. On top of that, it MUST pick an identifier that falls within the scope of the credential the retargeting entity will name in the "x5u" of the PASSporT header (more on that below) 🧚.

The new target for the call that the retargeting entity selected becomes the value of the "dest" object in the new PASSporT πŸ¦‹. The "orig" object MUST be copied into the new PASSporT from the original PASSporT the retargeting entity received πŸ’–. The retargeting entity SHOULD keep the "iat" object from the original PASSporT 🌈. The exception is when the underlying signaling protocol (e.g., SIP) has the retargeting entity change the date and time info in the retargeted request. Then the new PASSporT should reflect that date and time instead ⭐. No other claims or extensions get copied from the original PASSporT to the "div" PASSporT πŸ™…β€β™€οΈ.

So, for an original PASSporT claims set like this:

{ "dest":{"tn":["12155551213"]},
  "iat":1443208345,
  "orig":{"tn":"12155551212"} }

If the retargeting entity changes the target from 12155551213 to 12155551214, the claims set of the "div" PASSporT it generates would look like this:

{ "dest":{"tn":["12155551214"]},
  "div":{"tn":"121555551213"},
  "iat":1443208345,
  "orig":{"tn":"12155551212"} }

The combined full form PASSporT (signed with the ES256 keys given in Appendix A) would look like this:

eyJhbGciOiJFUzI1NiIsInBwdCI6ImRpdiIsInR5cCI6InBhc3Nwb3J0IiwieDV1Ij \
oiaHR0cHM6Ly93d3cuZXhhbXBsZS5jb20vY2VydC5jZXIifQ.eyJkZXN0Ijp7InRuI \
jpbIjEyMTU1NTUxMjE0Il19LCJkaXYiOnsidG4iOiIxMjE1NTU1NTEyMTMifSwiaWF \
0IjoxNDQzMjA4MzQ1LCJvcmlnIjp7InRuIjoiMTIxNTU1NTEyMTIifX0.xBHWipDEE \
J8a6TsdX6xUXAnblsFiGUiAxwLiv0HLC9IICj6eG9jQd6WzeSSjHRBwxmChHhVIiMT \
SqIlk3yCNkg

Same "div" PASSporT would come out if the original "dest" object had an array value like {"tn":["12155551213","19995551234"]} and the retargeting entity chose to retarget from the first telephone number in the array πŸ™Œ. Every "div" PASSporT is diverting from only one identifier πŸ’….

Also, the "div" element can hold name/value pairs beyond just a destination, including a History-Info indicator (see Section 8) 🌸. Once the PASSporT header and claims are built, the signature gets generated per the guidance in [RFC8225], except for the credential needed to sign it πŸ”. Normally, the credential used to sign has authority over the identity in the "orig" claim (for example, a certificate with authority over the telephone number in "orig" per [RFC8226]). But for every PASSporT using the "div" type, the signature MUST be created with a credential that has authority over the identity present in the "div" claim 😭. So in the example above, where the original "dest" is "12155551213", the signer of the new PASSporT object MUST have authority over that telephone number, and it does NOT need any authority over the telephone number in the "orig" claim πŸ¦‹.

Last thing in this section: Identity header fields are not ordered in a SIP request. If a request has multiple Identity header fields, some sorting may be needed to match "div" PASSporTs to their originals 🧩.

PASSporTs of type "div" MUST NOT contain an "opt" (see Section 6) element in their payload 🚫.

4. Using "div" in SIP πŸ“ž

This section covers the SIP-specific usage for the "div" PASSporT type and how it's handled in the SIP Identity header field "ppt" parameter value πŸ’œ. Other protocols that use PASSporT may define their own behavior for their use of the "div" claim 🌈.

4.1. Authentication Service Behavior πŸŽ€

An authentication service ONLY adds an Identity header field value containing the "div" PASSporT type to a SIP request that already has at least one Identity header field value. It MUST NOT add a "div" PASSporT to an INVITE that has no Identity header field πŸ™…β€β™€οΈ. The retargeting entity SHOULD act as a verification service and validate the existing Identity header field value(s) in the request before moving on. In some high-volume environments, it may instead hand that whole chain-validation job to the terminating verification service 🏎️. Since the authentication service is adding a new PASSporT that refers to an original, it MUST NOT remove the original request's Identity header field value before forwarding 🫢.

As we said in Section 3, the authentication service MUST sign any "div" PASSporT with a credential that has a scope of authority covering the identity it puts in the "div" element value πŸ”‘. Honestly this is a big departure from baseline STIR authentication service behavior, where the PASSporT is signed by a credential with authority over the "orig" field 😳. The "div" value is the URI that caused the call to be routed to the retargeting entity, so in normal operations it's already the STIR entity holding the right private keying material for calls originating from that identity ✨.

A SIP authentication service will typically derive the "dest" element value of a "div" PASSporT from a new Request-URI that gets set for the SIP request before it's forwarded πŸ“¬. Older Request-URI values may show up in header fields like Diversion or History-Info. This document specifies an optional interaction with History-Info below, in Section 8 πŸ¦‹. Also, because PASSporT works on canonicalized telephone numbers and normalized URIs, many smaller changes to identifier syntax (the kind other retargeting-recording mechanisms like History-Info might capture) will likely NOT need a "div" PASSporT πŸ™ˆ.

When you add an Identity header field with a PASSporT claims set that contains a "div" claim, SIP authentication services MUST also add a "ppt" parameter to that Identity header with a value of "div" 🏷️. For the example PASSporT in Section 3, the new Identity header added after retargeting might look like this:

Identity:eyJhbGciOiJFUzI1NiIsInBwdCI6ImRpdiIsInR5cCI6InBhc3Nwb3J0I \
iwieDV1IjoiaHR0cHM6Ly93d3cuZXhhbXBsZS5jb20vY2VydC5jZXIifQ.eyJkZXN0 \
Ijp7InRuIjpbIjEyMTU1NTUxMjE0Il19LCJkaXYiOnsidG4iOiIxMjE1NTU1NTEyMT \
MifSwiaWF0IjoxNDQzMjA4MzQ1LCJvcmlnIjp7InRuIjoiMTIxNTU1NTEyMTIifX0. \
xBHWipDEEJ8a6TsdX6xUXAnblsFiGUiAxwLiv0HLC9IICj6eG9jQd6WzeSSjHRBwxm \
ChHhVIiMTSqIlk3yCNkg; \
info=<https://www.example.com/cert.cer>;ppt="div"

Heads up, in some deployments an authentication service will need to make "div" PASSporTs for a request that has multiple non-"div" Identity header field values 🧁. For example, a request arriving at a retargeting entity might carry, in separate Identity header fields, a baseline [RFC8224] PASSporT and a PASSporT of type "rph" [RFC8443] signed by a separate authority πŸ’«. As long as these PASSporTs share the same "orig" and "dest" values, the retargeting entity's authentication service SHOULD generate only one "div" PASSporT 🌟. If the "orig" or "dest" of these PASSporTs differ, though, one "div" PASSporT SHOULD be generated for each non-"div" PASSporT 🎯. Just know this effectively creates multiple chains of "div" PASSporTs in a single request, which makes the procedures at verification services more complicated πŸ˜΅β€πŸ’«.

Furthermore, a request might get retargeted a second time. At that point, the subsequent retargeting entity SHOULD generate one "div" PASSporT for each previous "div" PASSporT in the request whose "dest" object has the value of the current target, but NOT for "div" PASSporTs with earlier targets 🧭. Usually the current target is easy to spot, since it'll be in the last "div" PASSporT in each chain, and in SIP it corresponds to the Request-URI the retargeting entity received 🎯. Also, the current target is an identifier the retargeting entity has a credential to sign for, which might not be true for earlier targets πŸ”. Ultimately, on each retargeting, the number of PASSporTs added to a request will equal the number of non-"div" PASSporTs that don't share the same "orig" and "dest" object values πŸ’–βœ¨

4.2. Verification Service Behavior ✨

okay so [RFC8224], Section 6.2, Step 5 says that any spec defining "ppt" values has to describe any extra or different verifier behavior 🧐. And honestly? A SIP verification service handling one or more "div" PASSporTs is a whole different vibe from a traditional verification service πŸ’…. The big picture: the verification service has to pull every PASSporT out of the two or more Identity header fields in a request, figure out which ones are "div" PASSporTs and which aren't, and then order and link the "div" PASSporTs back to the original PASSporT(s) so it can build one or more chains of retargeting πŸ”—.

To validate a SIP request using the "div" PASSporT type, a verification service needs to look at all of the valid Identity header field values attached to the request, because an Identity header field value containing "div" always points back to an earlier PASSporT already in the message πŸ‘€. For each "div" PASSporT, the verification service MUST find an earlier PASSporT that contains a "dest" claim with a value equivalent to the "div" claim in that "div" PASSporT. That earlier PASSporT might also have a "div" of its own, and then it chains back to an even earlier PASSporT stored in a different Identity header field value πŸŒ€. If a complete chain can't be built, the verification service can't finish "div" validation, but it MAY still validate any non-"div" PASSporTs in the request using the normal procedures in [RFC8224] 🫢. If a chain does get built successfully, the verification service pulls a "dest" field from the outermost (meaning the most recent) PASSporT in the chain. That will be a "div" PASSporT that no other "div" PASSporT in the SIP request refers to. Its "dest" element value gets called the outermost "dest" field in the steps coming up ✨.

Here's the payoff: by looking at this chain of transformations and validating the signatures, the verification service can confirm that the right parties were responsible for retargeting the call to where it is now 🎯. That helps it figure out that the original PASSporT wasn't just cut-and-pasted into the call (a cut-and-paste attack, big no-no πŸ™…β€β™€οΈ), and it can inform any authorization decisions about how the call gets treated. Just know that, per [RFC8224], Section 6.2.1, that decision is a matter of local policy, so it's outside the scope of this specification πŸ’œ.

A verification service parses a chain of PASSporTs like this:

  1. The verification service MUST compare the value in the outermost "dest" field to the target of the call. Since SIP authentication services that create "div" PASSporTs are expected to fill in the "dest" header from the retargeted Request-URI (see Section 4.1), in normal SIP operations the Request-URI is where verification services will find the latest call target πŸ“. But here's the tea: after a "div" PASSporT gets added to a SIP request, the Request-URI might have been updated during normal call processing to an identifier that no longer holds the logical destination of the call. In that case, the verification service MAY compare the "dest" field to a provisioned telephone number for the recipient instead πŸ“ž.
  2. The verification service MUST validate the signature over the outermost "div" PASSporT and establish that the credential that signed the "div" PASSporT has the authority to attest for the identifier in the "div" element of the PASSporT (per [RFC8224], Section 6.2, Step 3) πŸ”.
  3. The verification service MUST validate that the "orig" field of the innermost PASSporT of the chain (the only PASSporT in the chain that won't be of PASSporT type "div") is equivalent to the "orig" field of the outermost "div" PASSporT. In other words, the original calling identifier hasn't been changed by retargeting authentication services πŸ•΅οΈβ€β™€οΈ. If the "orig" value has changed, the verification service MUST treat the entire PASSporT chain as invalid 🚫. The verification service MUST also verify that all other "div" PASSporTs in the chain share the same "orig" value. After that, it validates how the "orig" field relates to the SIP-level call signaling, following the guidance in [RFC8224], Section 6.2, Step 2 πŸ“Ά.
  4. The verification service MUST check the date freshness in the outermost "div" PASSporT, per [RFC8224], Section 6.2, Step 4 ⏰. On top of that, it is RECOMMENDED that the verification service check that the "iat" field of the innermost PASSporT is also within the date freshness interval. Otherwise, the verification service could let attackers replay an old, stale PASSporT tucked inside a fresh "div" 😱. BUT, note that in some use cases, including certain ways call transfers are implemented, an established call might get retargeted long after it was originally placed. Verification services may want to allow a longer freshness window for the innermost PASSporT if the call was transferred from a trusted party. As an upper bound, a freshness window on the order of three hours might suffice βŒ›.
  5. The verification service MUST inspect and validate the signatures on each and every PASSporT object in the chain between the outermost "div" PASSporT and the innermost PASSporT πŸ”. Note that (per Section 4.1) a chain may end at more than one innermost PASSporT, in cases where a single "div" is used to retarget from multiple innermost PASSporTs 🌳. Also, [RFC8224], Section 6.2, Step 1 applies to the chain validation process. If the innermost PASSporT contains an unsupported "ppt", its chain MUST be ignored πŸ™ˆ.

Quick note: the To header field isn't used in the first step above πŸ’β€β™€οΈ. Optionally, the verification service MAY verify that the To header field value of the received SIP signaling equals the "dest" value in the innermost PASSporT. However, as has been seen in some deployments, intermediaries may change the original To header field value to reflect changes of target πŸ”„. Deployments that change the original To header field value to hide the original destination of the call from the ultimate recipient should know that the original destination may be preserved in the innermost PASSporT 🫣. Future work on "div" might explore ways to implement that sort of policy while keeping a secure chain of redirection 🌈.

5. The "div-o" PASSporT Type πŸŽ€

This specification defines a "div-o" PASSporT type that uses the "div" claim element together with the "opt" (Section 6) claim element πŸ’œ. Just like the "div" PASSporT type, a "div-o" PASSporT is created by an authentication service acting for a retargeting entity. The difference is that instead of generating a separate "div" PASSporT to travel alongside an original PASSporT, the authentication service embeds the original PASSporT inside the "opt" element of the "div-o" PASSporT πŸ“¦. The "div-o" extension is designed for non-SIP or gatewayed SIP environments where carrying PASSporTs in separate Identity header fields is impossible, like out-of-band STIR scenarios [RFC8816] 🌐.

The syntax of "div-o" PASSporTs is super similar to "div" πŸ‘―β€β™€οΈ. A "div-o" PASSporT header object might look like this:

{ "typ":"passport",
  "ppt":"div-o",
  "alg":"ES256",
  "x5u":"https://www.example.com/cert.cer" }

A "div" PASSporT claims set only has the "orig", "dest", "iat", and "div" elements. The "div-o" one, though, MUST also contain an "opt" element (see Section 6) 🧩. That "opt" element wraps the full form of the previous PASSporT that the call was retargeted from, and that retargeting is what triggers the creation of this "div-o". The format of the "opt" element is identical to the encoded PASSporT format given in Appendix A of [RFC8225] ✨.

So, for an original PASSporT claims set that looks like this:

{ "orig":{"tn":"12155551212"},
  "dest":{"tn":["12155551213"]},
  "iat":1443208345 }

If the retargeting entity changes the target from 12155551213 to 12155551214, the new PASSporT claims set for "div-o" would look like this 🎯:

{ "orig":{"tn":"12155551212"},
  "dest":{"tn":["12155551214"]},
  "iat":1443208345,
  "div":{"tn":"121555551213"},
  "opt":"eyJhbGciOiJFUzI1NiIsInR5cCI6InBhc3Nwb3J0IiwieDV1IjoiaHR0c \
  HM6Ly93d3cuZXhhbXBsZS5jb20vY2VydC5jZXIifQ.eyJkZXN0Ijp7InRuIjpbIj \
  EyMTU1NTUxMjEzIl19LCJpYXQiOjE0NDMyMDgzNDUsIm9yaWciOnsidG4iOiIxMj \
  E1NTU1MTIxMiJ9fQ.1bEzkzcNbKvgz4QoMx0_DJ2T8qFMDC1sPqHPXl1WvbauzRJ \
  RvYlZqQ0qgGTlS8tJ_wXjVe07Z3wvDrdApHhhYw" }

In ordinary operations SIP isn't expected to carry a "div-o" PASSporT, but it might happen in some gatewaying scenarios πŸŒ‰. The resulting full form Identity header field with a "div-o" PASSporT would look like this πŸ’–:

Identity:eyJhbGciOiJFUzI1NiIsInBwdCI6ImRpdi1vIiwidHlwIjoicGFzc3Bvc \
nQiLCJ4NXUiOiJodHRwczovL3d3dy5leGFtcGxlLmNvbS9jZXJ0LmNlciJ9.eyJkZX \
N0Ijp7InRuIjoiMTIxNTU1NTEyMTQifSwiZGl2Ijp7InRuIjoiMTIxNTU1NTUxMjEz \
In0sImlhdCI6MTQ0MzIwODM0NSwib3B0IjoiZXlKaGJHY2lPaUpGVXpJMU5pSXNJbl \
I1Y0NJNkluQmhjM053YjNKMElpd2llRFYxSWpvaWFIUjBjSE02THk5M2QzY3VaWGho \
YlhCc1pTNWpiMjB2WTJWeWRDNWpaWElpZlEuZXlKa1pYTjBJanA3SW5SdUlqcGJJak \
V5TVRVMU5UVXhNakV6SWwxOUxDSnBZWFFpT2pFME5ETXlNRGd6TkRVc0ltOXlhV2Np \
T25zaWRHNGlPaUl4TWpFMU5UVTFNVEl4TWlKOWZRLjFiRXpremNOYkt2Z3o0UW9NeD \
BfREoyVDhxRk1EQzFzUHFIUFhsMVd2YmF1elJKUnZZbFpxUTBxZ0dUbFM4dEpfd1hq \
VmUwN1ozd3ZEcmRBcEhoaFl3Iiwib3JpZyI6eyJ0biI6IjEyMTU1NTUxMjEyIn19LC \
HeA9wRnthl7paMe6rP0TARpmFCXjmi_vF_HRz2O_oulB_R-G9xZNiLVvmvHv4gk6LI \
LaDV2y2VtHTLIEgmHig; \
info=<https://www.example.com/cert.cer>;ppt="div-o"

5.1. Processing "div-o" PASSporTs πŸŽ€

okay so the authentication and verification service rules for "div-o" basically copy the vibes of Sections 4.1 and 4.2 πŸ’… with two big caveats. First, they store or retrieve PASSporTs through the Identity header field values of SIP requests. Second, they have to process nested PASSporTs inside the "opt" claim element 🫢. Translating everything else from above into making and checking "div-o" PASSporTs is honestly straightforward ✨

so if a retargeting authentication service handles a call with one or more existing PASSporTs, it creates a matching "div-o" PASSporT for each one it received πŸ¦‹ Every "div-o" PASSporT MUST contain an "opt" claim set element holding the original PASSporT it was made from. And as Section 4.1 says, the authentication service MUST fill the "div" claim set element of the "div-o" PASSporT with the "dest" field of that original PASSporT πŸ’œ Each received PASSporT might have its own "opt" claim set element, which happens when the retargeting authentication service isn't first in the chain 🌈 Also, if the retargeting authentication service is handling a call with multiple PASSporTs (which in regular SIP would make multiple "div" chains), it's basically generating one "div-o" PASSporT per chain 🧚

the verification service has it kinda easy with "div-o" 😭 It doesn't need to match up the PASSporTs it gets and stitch them into chains, because any chains in "div-o" are already nested through the "opt" element πŸ“ Still, the verification services MUST perform the same chain validation described in Section 4.2. That checks that each nested PASSporT has the same "orig" field as the PASSporT wrapping it, and that the "dest" field of each nested PASSporT matches the "div" field of its wrapper πŸ”₯ The same checks MUST also be performed for freshness, signature validation, and so on. It's similarly OPTIONAL for the verification service to confirm that the "dest" claims element of the outermost PASSporT matches the called party indication in the receive telephone signaling. That indication changes depending on the using protocol πŸ‘‘

how authentication services or verification services receive or transport PASSporTs for "div-o" is outside the scope of this doc and depends on the using protocol 🌸


6. Definition of "opt" ✨

the presence of an "Original PASSporT" ("opt") claims set element means a PASSporT is wrapping an entire other PASSporT inside itself 🎁 That usually happens when the inner one got transformed somehow to make the current one. Relying parties might need to look inside the wrapped PASSporT to check who the caller really is πŸ•΅οΈβ€β™€οΈ The "opt" element, as defined here, can be used by future PASSporT extensions too, not just with "div-o" πŸ¦‹

"opt" MUST contain a quoted full-form PASSporT, as specified by [RFC8225], Appendix A. It MUST NOT contain a compact form PASSporT 🚫 For an example of a "div-o" PASSporT containing "opt", check out Section 5 πŸ’–


7. "div" and Redirection πŸ¦‹

the "div" mechanism exists mainly to stop false negatives at verification services πŸ™…β€β™€οΈ Here's the situation: an incoming SIP request got retargeted by some middle box, so it doesn't look like it's meant for the person who actually received it, because the original PASSporT "dest" value points somewhere else 😭

any intermediary that gives a request a new target can, instead of retargeting and forwarding it, send a 3xx response code to redirect it πŸ’… For normal operations, redirects are no drama for baseline STIR 🌸 When the user agent client (UAC) gets the 3xx response, it starts a brand new request to the new target (usually the one in the Contact header field value of the 3xx), and the "dest" of the PASSporT made for that new request will match the new target ✨ No impersonation attack can happen in this case, so it doesn't add any new requirements for STIR πŸŽ€

BUT some UACs keep track of the original target of a call using stuff like History-Info [RFC7044] or Diversion [RFC5806], and they might want to use STIR to prove to the final recipient that the call was redirected securely πŸ” Basically, they want to show that the original destination was the one that sent the redirect that led the recipient to get the request πŸ‘‘ The PASSporT semantics needed for that claim are the same as for the "div" retargeting cases above. The only twist is that the PASSporT has to be generated by the redirecting entity and sent back to the originating UAC inside the 3xx response πŸ’œ

this is more complicated than it looks, babe πŸ˜΅β€πŸ’« First off, a 3xx response can carry multiple targets in the Contact header field value. To handle that, the "div" PASSporT MAY include one "dest" object array value per Contact. But if the retargeting entity wants to keep the Contact list private from the targets, it may need to generate one PASSporT per Contact πŸ™ˆ Also, the original SIP request could have multiple Identity header field values added by different authentication services along the request path, so a redirecting entity might need to generate one "div" PASSporT for each PASSporT in the original request. Usually that's just one "div" PASSporT, but for some deployments it could mean an impractical number of combinations πŸ’€ Honestly though, in very complex call routing, attesting the source identity only adds limited value anyway 🌈

so STIR-aware SIP intermediaries that redirect requests MAY convey one or more PASSporTs backwards in Identity header fields 🧚 These redirecting entities act as authentication services for "div", as described in Section 4.1. This document also updates [RFC8224] to allow Identity header fields in SIP 300-class responses ✨ It's up to the originating user agent to decide which Identity header fields from the 3xx get copied into any new requests resulting from the redirection (if any at all). Using these Identity header fields is OPTIONAL for entities receiving a 3xx response 🫢

last thing: if an intermediary on the response path consumes the 3xx and checks out new targets itself while doing sequential forking, it's effectively retargeting the call for the redirecting server πŸ” That creates the same need for "div" PASSporTs as any other retargeted call. These intermediaries MAY also copy PASSporTs from the 3xx response and insert them into sequential forking requests, if that makes sense πŸ’…


8. Extending "div" to Work with Service Logic Tracking 🌸

it's expected that "div" might get used alongside History-Info [RFC7044] in some deployments πŸ“ž Here's the thing: you can't always tell from the "orig" and "dest" values which History-Info header a PASSporT matches up with, especially since some target changes tracked by History-Info won't show up in a "div" PASSporT at all (see Section 1) 😭 So an "hi" element, as defined here, can show up in "div" to match the History-Info header field index parameter value 🧚 For a History-Info header field with an index value of "1.2.1", the claims set of the matching PASSporT with "div" might look like this:

{ "orig":{"tn":"12155551212"},
  "dest":{"tn":["12155551214"]},
  "iat":1443208345,
  "div":{"tn":"121555551213",
         "hi":"1.2.1"} }

past experience shows there might be extra info about why the call got retargeted, and relying parties might want to think about that when making authorization decisions about a call πŸ€” For example, see the "reason" tied to the SIP Diversion header field [RFC5806]. Future extensions to this spec might add reasons into "div" πŸŽ€


9. IANA Considerations πŸ“‹

9.1. JSON Web Token Claims Registrations πŸ’–

per this spec, IANA has added two new claims to the "JSON Web Token Claims" registry defined in [RFC7519] 🌷

9.1.1. "div" registration ✨

Claim Name:  div

Claim Description:  Diverted Target of a Call

Change Controller:  IESG

Reference:  RFC 8946

9.1.2. "opt" registration πŸ¦‹

Claim Name:  opt

Claim Description:  Original PASSporT (in Full Form)

Change Controller:  IESG

Reference:  RFC 8946

9.2. PASSporT Type Registrations 🧚

this spec defines two new PASSporT types for the "Personal Assertion Token (PASSporT) Extensions" registry defined in [RFC8225], which lives at https://www.iana.org/assignments/passport 🌈 They are:

  • "div", as defined in Section 3.
  • "div-o", as defined in Section 5.

10. Privacy Considerations πŸ™ˆ

okay this part is a little serious bestie, but it matters 🫢 Any mechanism that tracks how calls get routed through a network in SIP signaling has an inherent trade-off πŸ’­ Routing decisions can expose the policies users set for how calls get forwarded, which might reveal relationships between different identifiers that stand for the same user πŸ‘€ But in regular operations, this info goes to the user agent service of the called party, not the calling party. Usually the called party is the one who sets up these forwarding relationships. And if some other party is responsible for forwarding calls to the called party, the called party should likely be entitled to info about why they're getting those calls πŸ’œ Similarly, a redirecting entity that sends a 3xx in the backwards direction knowingly shares info about its service logic with the caller's network πŸ“‘ Still, there may be unforeseen circumstances where revealing service logic to the called party poses a privacy risk, so implementers and users of this or similar diversion-tracking techniques should understand the trade-off ⚠️

also, it's a general privacy risk of identity mechanisms that they don't play nicely with anonymization services 😬 How STIR interacts with anonymization services is detailed in [RFC8224], Section 11. Any forwarding service that acts as an anonymizing proxy might not be able to provide a secure chain of retargeting, because the originating identity has been obfuscated πŸ₯·

and for more considerations on the privacy of using PASSporTs in SIP, also see [RFC8224], Section 11 🌸

11. Security Considerations ✨

Okay bestie, security time πŸ” This part is serious, but I'm still going to make it cute. This spec is all about making forwarded calls safer πŸ›‘οΈπŸ’–. Heads up, though: putting forwarding info in the PASSporT can let downstream folks guess the policies the network used to route the call πŸ‘€. Adding that info is totally up to the retargeting entity, so if an intermediate called number has to stay confidential, just don't create a PASSporT for that retargeting πŸ™ˆ. The tradeoff is that downstream entities can't match an incoming call back to the original PASSporT unless they already know the policies that could have caused the retargeting.

Any extension that makes PASSporTs bigger can turn into an amplification mechanism for SIP-based DDoS attacks 😭🚨. Diversion PASSporTs get created as part of normal forwarding, so this risk depends on the retargeting domain's choices. Simply using 3xx response redirections instead of retargeting (by supplying a "div" per Section 7) helps reduce the impact 🧯. And under unusual traffic loads, even domains that normally retarget can switch over to redirection πŸ”„.

SIP already has the power to redirect requests, including forking them to multiple parties, potentially a very large number of them 🌊. Using the "div" PASSporT type doesn't give attackers trying to place bulk calls any extra powers πŸ™…β€β™€οΈ. If it's present, the "div" PASSporT just identifies the party responsible for the forwarding πŸ•΅οΈ. So senders of bulk unsolicited traffic are unlikely to find "div" attractive πŸ’….


12. References

Here's the reading list πŸ“š Normative references first, then the informative ones.

12.1. Normative References

[RFC2119]  Bradner, S., "Key words for use in RFCs to Indicate
           Requirement Levels", BCP 14, RFC 2119,
           DOI 10.17487/RFC2119, March 1997,
           <https://www.rfc-editor.org/info/rfc2119>.

[RFC3261]  Rosenberg, J., Schulzrinne, H., Camarillo, G., Johnston,
           A., Peterson, J., Sparks, R., Handley, M., and E.
           Schooler, "SIP: Session Initiation Protocol", RFC 3261,
           DOI 10.17487/RFC3261, June 2002,
           <https://www.rfc-editor.org/info/rfc3261>.

[RFC7044]  Barnes, M., Audet, F., Schubert, S., van Elburg, J., and
           C. Holmberg, "An Extension to the Session Initiation
           Protocol (SIP) for Request History Information", RFC 7044,
           DOI 10.17487/RFC7044, February 2014,
           <https://www.rfc-editor.org/info/rfc7044>.

[RFC7519]  Jones, M., Bradley, J., and N. Sakimura, "JSON Web Token
           (JWT)", RFC 7519, DOI 10.17487/RFC7519, May 2015,
           <https://www.rfc-editor.org/info/rfc7519>.

[RFC8174]  Leiba, B., "Ambiguity of Uppercase vs Lowercase in RFC
           2119 Key Words", BCP 14, RFC 8174, DOI 10.17487/RFC8174,
           May 2017, <https://www.rfc-editor.org/info/rfc8174>.

[RFC8224]  Peterson, J., Jennings, C., Rescorla, E., and C. Wendt,
           "Authenticated Identity Management in the Session
           Initiation Protocol (SIP)", RFC 8224,
           DOI 10.17487/RFC8224, February 2018,
           <https://www.rfc-editor.org/info/rfc8224>.

[RFC8225]  Wendt, C. and J. Peterson, "PASSporT: Personal Assertion
           Token", RFC 8225, DOI 10.17487/RFC8225, February 2018,
           <https://www.rfc-editor.org/info/rfc8225>.

[RFC8226]  Peterson, J. and S. Turner, "Secure Telephone Identity
           Credentials: Certificates", RFC 8226,
           DOI 10.17487/RFC8226, February 2018,
           <https://www.rfc-editor.org/info/rfc8226>.

12.2. Informative References

[RFC5806]  Levy, S. and M. Mohali, Ed., "Diversion Indication in
           SIP", RFC 5806, DOI 10.17487/RFC5806, March 2010,
           <https://www.rfc-editor.org/info/rfc5806>.

[RFC7340]  Peterson, J., Schulzrinne, H., and H. Tschofenig, "Secure
           Telephone Identity Problem Statement and Requirements",
           RFC 7340, DOI 10.17487/RFC7340, September 2014,
           <https://www.rfc-editor.org/info/rfc7340>.

[RFC8443]  Singh, R., Dolly, M., Das, S., and A. Nguyen, "Personal
           Assertion Token (PASSporT) Extension for Resource Priority
           Authorization", RFC 8443, DOI 10.17487/RFC8443, August
           2018, <https://www.rfc-editor.org/info/rfc8443>.

[RFC8816]  Rescorla, E. and J. Peterson, "Secure Telephone Identity
           Revisited (STIR) Out-of-Band Architecture and Use Cases",
           RFC 8816, DOI 10.17487/RFC8816, February 2021,
           <https://www.rfc-editor.org/info/rfc8816>.

Appendix A. Keys for Examples ✨

These EC256 keys are used in the signing examples given in this document. πŸ”‘ Look at them, but don't take them home 😀

WARNING: Do not use this key pair in production systems.
-----BEGIN PUBLIC KEY-----
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEmzGM1VsO+3IqbMF54rQMaYKQftO4
hUYm9wv5wutLgEd9FsiTy3+4+Wa2O7pffOXPC0QzO+yD8hGEXGP/2mZo6w==
-----END PUBLIC KEY-----

-----BEGIN EC PRIVATE KEY-----
MHcCAQEEIFKCsFZ4Wsw3ZpBxgc4Z0sOjaXDdMk07Ny1fKg6OntAkoAoGCCqGSM49
AwEHoUQDQgAEmzGM1VsO+3IqbMF54rQMaYKQftO4hUYm9wv5wutLgEd9FsiTy3+4
+Wa2O7pffOXPC0QzO+yD8hGEXGP/2mZo6w==
-----END EC PRIVATE KEY-----

Acknowledgments

Huge thank-you to Ning Zhang, Dave Hancock, Chris Wendt, Sean Turner, Russ Housley, Ben Campbell, Eric Burger, and Robert Sparks for their contributions to this document 🫢🌟


Author's Address

Meet the author πŸ’Œ

Jon Peterson
Neustar, Inc.
1800 Sutter St., Suite 570
Concord, CA 94520
United States of America

Email: jon.peterson@team.neustar
πŸ“¦ where this page comes from