Subject: Re: [Perc] KMF/MDD interface: thoughts on a new approach

From: Adam Roach <[email-masked]>
Date: Mon, 1 Aug 2016 15:37:45 -0500

We had a discussion on this during the face-to-face in Berlin. The 
general conclusion from that discussion was to go in the general 
direction that Cullen outlines below: we create a single TLS/TCP 
connection from the KMF towards the MDD. Over that connection, we use a 
simple encapsulation protocol that allows us to exchange multiple flows 
of TLS traffic, along with some control messages (supported 
ciphersuites, HBH keys).

This leaves us to decide the syntax for this framing (I fear this is 
kind of bikesheddy, but we need to nail it down). So far I've heard 
three basic suggestions:

 1. Hand-roll our own protocol, similar to what is currently in the
    tunnel draft.
 2. Use JSON [RFC7159]
 3. Use CBOR [RFC7049]

Presumably, the JSON representation would look something like:

{
   "type": "tunnel",
   "channel": 4,
   "packet": 
"FgEAAAAAAAAAAAAAagEAAF4AAAAAAAAAXgEARI11KHx3QB6KyCKgoBj/kwjKrApkL8kiZ
LwIqBaJGT8AAAA2ADkAOAA1ABYAEwAKADMAMgAvAAcAZgAFAAQAYwBiAGEAFQASAAkAZQ
     BkAGAAFAARAAgABgADAQA="
}

{
   "type": "profiles",
   "supported": [7,8]
}

{
   "type": "keys",
   "channel": 4,
   "profile": 8,
   "mki": 17,
   "server_key": "...",
   "server_salt": "...",
   "client_key": "...",
   "server_salt": "..."
}

(The "..." above are base-64 encoded values)

And the CBOR representation would simply encode these structures in 
CBOR, using literal byte strings rather than base64 for the packets, 
keys, and salts, and integers to encode packet types.

I have a slight preference for CBOR (it's more general than a custom 
scheme, and more compact than JSON), but nothing extremely strong.

/a

On 7/18/16 07:02, Cullen Jennings wrote:
> So agree that snag kills the current plan.
>
> Running a webrtc data channel looks like the most hideously complicated thing we could do.  How about we just use a TLS connection made from the KMF to the MDD? I don’t think the head of line issue or the putting the MDD behind a NAT are practical enough use cases to justify the complexity.
>
>
>
>
>> On Jul 16, 2016, at 4:39 AM, Adam Roach <[email-masked]> wrote:
>>
>> Mozilla has started looking into implementation of a PERC KMF, and have run into a bit of a snag with the tunnel protocol. Right now, the current tunnel i-d plans on using the reliability of the underlying TLS handshake (client hello/server hello/finished/finished) to ensure that required information is exchanged between the KMF and the MDD.
>>
>> Unfortunately, this won't work. The *reason* it won't work is that TLS 1.3 (which we'll certainly want to support) performs a three-way handshake instead of a four-way handshake. So the message that we planned to use to send the HBH key from the KMF to the MDD simply doesn't exist.
>>
>> This means that we'll need some additional reliability mechanism.
>>
>> We can roll our own -- but (as SIP taught us) that's not an awesome thing to do -- or we can re-use something that already works. As we worked through how best to do this, something relatively simple presented itself. If we use a stack similar to what we're using for WebRTC (SCTP/DTLS/ICE/UDP), we can kill several birds with one stone:
>>
>> * ICE gives us the keepalives we need to maintain NAT and firewall
>>    pinholes
>> * ICE provides a means for finding which of UDP or TCP will work
>>    through the firewall
>> * SCTP provides reliability for exchanging messages pertaining to
>>    supported ciphersuites and hop-by-hop keys
>> * SCTP provides multiple channels that can be used to carry multiple
>>    DTLS associations
>>
>> Basically, this means we move away from a custom binary protocol for the tunnel and re-use existing designs. It's easier to specify, and (at least, for the architectures we've been considering) much easier to implement. It's worth noting that the MDD would only need to support ice-lite, assuming it's deployed on a publicly-routable address.
>>
>>
>> +------+------+------+------+
>> | Ctrl | DTLS | DTLS | DTLS |  <- DTLS for DTLS-SRTP terminates here
>> +------+------+------+------+
>> |           SCTP            |  <- Provides control channel reliability, channel IDs
>> +---------------------------+
>> |           DTLS            |  <- DTLS here is the KMF <-> MDD connection
>> +---------------------------+
>> |           ICE             |  <- Provides keepalives, firewall traversal
>> +---------------------------+
>> |        UDP or TCP         |
>> +---------------------------+
>>
>>
>> I know it's kind of a step back from the tunnel protocol we've been designing at so far, but it looks a lot cleaner, and allows for re-use of already debugged components that will largely exist in implementations (or that can be trivially sourced from commercially-friendly open source projects). Overall -- and in addition to the other advantages -- I think this will be easier to specify and easier to implement.
>>
>> /a
>>
>> _______________________________________________
>> Perc mailing list
>> [email-masked]
>> https://www.ietf.org/mailman/listinfo/perc
> _______________________________________________
> Perc mailing list
> [email-masked]
> https://www.ietf.org/mailman/listinfo/perc

---

From: Paul Kyzivat <[email-masked]>
Date: Mon, 1 Aug 2016 17:46:13 -0400

On 8/1/16 4:37 PM, Adam Roach wrote:
> connection from the KMF towards the MDD.

Hasn't there been discussion that one of the participants might be 
serving as KMF? And hasn't there been hope that webrtc clients might be 
able to be participants?

If so, IIUC webrtc clients typically can't set up a naked TLS 
connection. The best they can do is websockets.

	Thanks,
	Paul

---

From: Adam Roach <[email-masked]>
Date: Mon, 1 Aug 2016 18:02:24 -0500

The KMF in that case would be a function embedded in the web browser that the content can activate. The content itself can't serve as a KMF, because that would give it access to the keying material, which it could exfiltrate back to the service. 

/a

> On Aug 1, 2016, at 16:46, Paul Kyzivat <[email-masked]> wrote:
> 
> Hasn't there been discussion that one of the participants might be serving as KMF? And hasn't there been hope that webrtc clients might be able to be participants?
> 
> If so, IIUC webrtc clients typically can't set up a naked TLS connection. The best they can do is websockets.
> 
>    Thanks,
>    Paul
>

---

From: Cullen Jennings <[email-masked]>
Date: Tue, 2 Aug 2016 13:00:59 -0600

CBOR would be the worst of both worlds. Prefer the other approaches. 

> On Aug 1, 2016, at 2:37 PM, Adam Roach <[email-masked]> wrote:
> 
> We had a discussion on this during the face-to-face in Berlin. The general conclusion from that discussion was to go in the general direction that Cullen outlines below: we create a single TLS/TCP connection from the KMF towards the MDD. Over that connection, we use a simple encapsulation protocol that allows us to exchange multiple flows of TLS traffic, along with some control messages (supported ciphersuites, HBH keys).
> 
> This leaves us to decide the syntax for this framing (I fear this is kind of bikesheddy, but we need to nail it down). So far I've heard three basic suggestions:
> 	• Hand-roll our own protocol, similar to what is currently in the tunnel draft.
> 	• Use JSON [RFC7159]
> 	• Use CBOR [RFC7049]
>   "packet": "FgEAAAAAAAAAAAAAagEAAF4AAAAAAAAAXgEARI11KHx3QB6KyCKgoBj/kwjKrApkL8kiZ
> And the CBOR representation would simply encode these structures in CBOR, using literal byte strings rather than base64 for the packets, keys, and salts, and integers to encode packet types.
> 
> I have a slight preference for CBOR (it's more general than a custom scheme, and more compact than JSON), but nothing extremely strong.
> 
> /a
>

---

From: Adam Roach <[email-masked]>
Date: Tue, 2 Aug 2016 14:02:44 -0500

Like I said, I don't feel strongly about it. JSON would be my second 
choice. It's verbose, but this is going to be a low-traffic interface, 
so it doesn't bother me too much.

/a

---

From: Richard Barnes <[email-masked]>
Date: Tue, 2 Aug 2016 15:15:24 -0400

This may have been raised and rebutted already, but have we considered
WebSockets?  Yes, the handshake and framing is a little clumsy, but it
seems to meet the basic requirements here:

1. Reliable, secure transport
2. Message framing
3. Direct representation of both binary and text data
4. Ability for either side to send messages at any time

With that, you could just say:

a. Any binary frame is a 4-byte connection ID followed by a DTLS message
b. Any text frame MDD -> KMF is a JSON message with capabilities
c. Any text frame KMF -> MDD is a JSON message with keys

It seems like that would maximize the "just glue some libraries together
and don't do any custom parsing" factor here.  Your KMF-side tunnel
implementation just glues a WebSocket libary to a JSON parser and a DTLS
stack, and the likewise on the MDD side.

On Tue, Aug 2, 2016 at 3:02 PM, Adam Roach <[email-masked]> wrote:

> choice. It's verbose, but this is going to be a low-traffic interface, so
> it doesn't bother me too much.
>
> /a
>
>
>>> general conclusion from that discussion was to go in the general direction
>>> that Cullen outlines below: we create a single TLS/TCP connection from the
>>> KMF towards the MDD. Over that connection, we use a simple encapsulation
>>> protocol that allows us to exchange multiple flows of TLS traffic, along
>>> with some control messages (supported ciphersuites, HBH keys).
>>>
>>> kind of bikesheddy, but we need to nail it down). So far I've heard three
>>> basic suggestions:
>>> CBOR, using literal byte strings rather than base64 for the packets, keys,
>>> and salts, and integers to encode packet types.
>>>
>>>> Running a webrtc data channel looks like the most hideously complicated
>>>> thing we could do.  How about we just use a TLS connection made from the
>>>> KMF to the MDD? I don’t think the head of line issue or the putting the MDD
>>>> behind a NAT are practical enough use cases to justify the complexity.
>>>>
>>>>
>>>>
>>>>
>>>>
>>>>> Mozilla has started looking into implementation of a PERC KMF, and
>>>>> have run into a bit of a snag with the tunnel protocol. Right now, the
>>>>> current tunnel i-d plans on using the reliability of the underlying TLS
>>>>> handshake (client hello/server hello/finished/finished) to ensure that
>>>>> required information is exchanged between the KMF and the MDD.
>>>>>
>>>>> Unfortunately, this won't work. The *reason* it won't work is that TLS
>>>>> 1.3 (which we'll certainly want to support) performs a three-way handshake
>>>>> instead of a four-way handshake. So the message that we planned to use to
>>>>> send the HBH key from the KMF to the MDD simply doesn't exist.
>>>>>
>>>>> We can roll our own -- but (as SIP taught us) that's not an awesome
>>>>> thing to do -- or we can re-use something that already works. As we worked
>>>>> through how best to do this, something relatively simple presented itself.
>>>>> If we use a stack similar to what we're using for WebRTC
>>>>> (SCTP/DTLS/ICE/UDP), we can kill several birds with one stone:
>>>>>
>>>>> Basically, this means we move away from a custom binary protocol for
>>>>> the tunnel and re-use existing designs. It's easier to specify, and (at
>>>>> least, for the architectures we've been considering) much easier to
>>>>> implement. It's worth noting that the MDD would only need to support
>>>>> ice-lite, assuming it's deployed on a publicly-routable address.
>>>>>
>>>>>
>>>>> I know it's kind of a step back from the tunnel protocol we've been
>>>>> designing at so far, but it looks a lot cleaner, and allows for re-use of
>>>>> already debugged components that will largely exist in implementations (or
>>>>> that can be trivially sourced from commercially-friendly open source
>>>>> projects). Overall -- and in addition to the other advantages -- I think
>>>>> this will be easier to specify and easier to implement.
>>>>>
>>>>> /a
>>>>>

---

From: Adam Roach <[email-masked]>
Date: Tue, 2 Aug 2016 14:18:19 -0500

> c. Any text frame KMF -> MDD is a JSON message with keys

I think we want to be more extensible than this. While we currently only 
envision the need for one control message type in each direction, I 
don't want to have to tear the design up and start over if we discover more.

/a

---

From: Richard Barnes <[email-masked]>
Date: Tue, 2 Aug 2016 15:19:34 -0400

Sure. { "type": "keys" } and so on.  But it at least gives you a clear
separation between the control channel and the DTLS, effectively for free.

On Tue, Aug 2, 2016 at 3:18 PM, Adam Roach <[email-masked]> wrote:

> envision the need for one control message type in each direction, I don't
> want to have to tear the design up and start over if we discover more.
>
>
> /a
>
>

---

From: Adam Roach <[email-masked]>
Date: Tue, 2 Aug 2016 17:56:44 -0500

Okay, a few of us managed to get together on an ad hoc call today, and 
hashed out something that is much simpler than any of the proposals so 
far. It sheds the verbosity of JSON and Base64 encoding DTLS packets, 
avoids the need to add a CBOR parser to the system, and allows us to 
focus on the contents of our messages rather than hand-rolling a binary 
protocol.

What we'd like to do is use the TLS presentation language 
<https://tools.ietf.org/html/rfc5246#section-4> to define binary 
structures that are then carried across the TLS connection between the 
KMF and MDD. Note that these are NOT new TLS messages; they're 
application data sent over TLS.

The definition for what we have right now in the tunnel document would 
look something like:

enum {
invalid(0),
supported_profiles(1),
media_keys(2),
tunneled_dtls(3),
(255)
} MsgType;

struct {
MsgType msg_type;
select (MsgType) {
case supported_profiles: SupportedProfiles;
case media_keys:         MediaKeys;
case tunneled_dtls:      TunneledDtls;
   } body;
} TunnelMessage;

// uint8 SRTPProtectionProfile[2]; // from RFC5764

struct {
SRTPProtectionProfile suites<0..2^16-1>;
} SupportedProfiles;

struct {
uint32 associationID;
SRTPProtectionProfile profile;
opaque mki<0..255>;
opaque clientWriteKey<0..255>;
opaque serverWriteKey<0..255>;
opaque clientWriteSalt<0..255>;
opaque serverWriteSalt<0..255>;
} MediaKeys;

struct {
uint32 associationID;
opaque dtlsMessage<0..2^16-1>;
} TunneledDtls;

[thanks to Richard and Cullen for working out the syntax here]

If there are no objections, I believe one of our implementors will 
submit a PR in a short while to update the tunnel draft accordingly.

/a

---

From: "Paul E. Jones" <[email-masked]>
Date: Wed, 03 Aug 2016 02:38:58 +0000

Adam,

Coming full circle...
https://tools.ietf.org/html/draft-jones-perc-dtls-tunnel-00#section-6

Obviously, I like this form of syntax.  And, we can insert comments to 
add clarity ;-)

In the original version, I had a "version" field.  Do we want 
versioning?

I also placed the association ID before the select().  The association 
ID has no meaning for supported profiles, but the value could be made 
optional, e.g.:

uint32 association_id<0..4> /* Optional Association Identifier */

Or, just have it as "uint32 association_id" and reserve the value 0 to 
indicate absence.

The reason for this is only to avoid duplicating that field in every 
message type.

I note that the keys and protection profiles are allowed to be absent 
("<0.." syntax).  Is that really desired?

Paul

---

From: Cullen Jennings <[email-masked]>
Date: Wed, 3 Aug 2016 15:52:36 -0600

> On Aug 2, 2016, at 8:38 PM, Paul E. Jones <[email-masked]> wrote:
> 
> 
> In the original version, I had a "version" field.  Do we want versioning?
> 
> 

At some level, we get versioning by being able to add new messages to the MsgType enum. We could also add an explicit version field. I'm fine either way.

---

From: "Paul E. Jones" <[email-masked]>
Date: Wed, 03 Aug 2016 22:16:42 +0000

If we want to add new data elements to existing messages, we'd need to 
version the protocol since a receiver would otherwise barf on the 
received message.

We could easily get by with a single version octet (versus the two 
octets I had in the -00 draft).  I would prefer we introduce a single 
"uint8 protocol_version" element to ensure we have a means of gracefully 
handling version misalignment.

Paul

------ Original Message ------
From: "Cullen Jennings" <[email-masked]>
To: "Paul Jones" <[email-masked]>
Cc: "Adam Roach" <[email-masked]>; "Richard Barnes" <[email-masked]>; 
"[email-masked]" <[email-masked]>
Sent: 8/3/2016 5:52:36 PM
Subject: Re: [Perc] KMF/MDD interface: thoughts on a new approach

>At some level, we get versioning by being able to add new messages to 
>the MsgType enum. We could also add an explicit version field. I'm fine 
>either way.
>
>
>

---

From: Cullen Jennings <[email-masked]>
Date: Wed, 3 Aug 2016 18:20:41 -0600

> On Aug 3, 2016, at 4:16 PM, Paul E. Jones <[email-masked]> wrote:
> 
> We could easily get by with a single version octet (versus the two octets I had in the -00 draft).  I would prefer we introduce a single "uint8 protocol_version" element to ensure we have a means of gracefully handling version misalignment.

sounds good to me