Subject: DIGEST-MD5 SASL mechanism?

From: Lawrence Greenfield <[email-masked]>
Date: 4 Jul 1999 22:00:04 -0400

Hi,

I'm attempting to clean up our implementation of DIGEST-MD5, and have
some questions that I'm unable to answer from
draft-leach-digest-sasl-03.txt.  I was wondering if anyone else has
attempted to implement this or has thought about it.

Specifically, I'm wondering about how to correctly implementing
privacy protection with block ciphers such as DES or 3DES and other
issues related to privacy and integrity protection.

The text I'm having trouble with is quoted below.

There appear to be several ambiguities in this:

- a "2-byte message type number" conflicts with "0x00000001"

- the MAC is defined including the "variable length padding prefix",
  but the padding is treated as part of the message.

- the padding  appears to be ambigious.  it is impossible to
  determine upon receipt of the message whether padding was or was not
  inserted versus a message that happened to end with something that
  looked like padding.

- it is unclear whether the encipherment of the {msg,pad} should be
  done before or after the encipherment of the HMAC.

Thanks,
Larry

----
[from section 2.4]

   The MAC is a variable length padding prefix followed by 16 bytes
   formatted as follows: a 2-byte message type number in network byte order
   with value 1, the first 10 bytes of the HMAC-MD5 [RFC 2104] of the
   message and the 4-byte sequence number in network byte order. If the
   blocksize of the chosen cipher is not 1 byte, the padding prefix is one
   or more octets each containing the number of padding bytes such that
   length of the message plus the length of the padding prefix is a
   multiple of the blocksize.

   SEAL(Ki, Kc, SeqNum, msg) = CIPHER(Kc, { msg, pad}), CMAC(Ki, Kc,
         SeqNum, msg)
   CMAC(Ki, Kc, SeqNum, msg) =
       { 0x00000001, CIPHER(Kc, HMAC(Ki, (SeqNum, msg))[0..7]), SeqNum }

---

From: Paul Leach <[email-masked]>
Date: Tue, 6 Jul 1999 10:06:08 -0700

> -----Original Message-----
> From: Lawrence Greenfield [mailto:[email-masked]]
> Sent: Sunday, July 04, 1999 7:00 PM
> To: [email-masked]
> Subject: DIGEST-MD5 SASL mechanism?
> 
> 
> Hi,
> 

Sorry -- didn't update the example when changing the spec. Should be
"0x0001"

>   but the padding is treated as part of the message.

No, it is just encrypted with the message, it isn't part of the message. The
MAC for encrypted messages is the padding concatenated with the MAC for
unencrypted messages.

>   inserted versus a message that happened to end with something that

There is always at least 1 pad byte: "the padding prefix is one or more
octets each containing the number of padding bytes". I tried to not have any
extra padding if the message happened to be a multiple of the cipher
blocksize, but couldn't figure out a way.
 
>   done before or after the encipherment of the HMAC.

Before.  The definition in section 2.4 is
    SEAL(Ki, Kc, SeqNum, msg) = CIPHER(Kc, { msg, pad}), CMAC(Ki, Kc,
SeqNum, msg)

So, the CIPHER happens before the CMAC.

---

From: Paul Leach <[email-masked]>
Date: Wed, 7 Jul 1999 15:48:55 -0700

> Sent: Wednesday, July 07, 1999 1:20 PM
> To: Paul Leach
> Cc: [email-masked]'
> Subject: Re: DIGEST-MD5 SASL mechanism?
> 
> 
> [...]
>    > 
> This really doesn't make sense.  A "MAC" is a message authentication
> code; padding is not part of the message authentication.

If I wanted to be technical: sure it is, in the sense that if the pad bytes
contain the incorrect value, the MAC won't check. However, it indeed isn't a
traditional MAC such as HMAC or keyed MD5.

However, I take your point. I'll admit I was loose with the terminology --
it would have been more accurate to be something like the "MAC trailer"
which is the pad, version, MAC, and sequence number.

> 
> Further, you don't cover what happens if the HMAC length is not a
> multiple of the cipher blocksize.

Duh. Oops. Drat. Good catch.

> 
> draft 03 specifies the encryption as follows:
> 
> From your message, I've corrected this to:
> 
>     { 0x0001, CIPHER(Kc, HMAC(Ki, (SeqNum, msg))[0..9]), SeqNum }
> 
> Of course, the 10 byte HMAC prefix is not a multiple of the 8 byte DES
> block.

Someone made me change it; it used to be 8 bytes. That's when the version
number was 4 bytes. And everything worked -- but there was an objection that
the MAC wasn't long enough.
(Of course, it's still true that we'd be screwed with any cipher with a
block size longer than 8 bytes.)

> 
> I would propose encoding instead as follows:
> 
> SEAL(Ki, Kc, SeqNum, msg) = 
>    CIPHER(Kc, { msg, pad, CMAC(Ki, SeqNum, msg) } )
> 
> CMAC(Ki, SeqNum, msg) =
>    { 0x0001, HMAC(Ki, (SeqNum, msg))[0..9], SeqNum }
> 
> where pad is 1 or more bytes containing the amount of padding needed
> to make msg + CMAC be a multiple of the block size.

The simplest change is just to make the size of the pad big enough to (msg +
10) (10 being the size of HMAC output) be a multiple of the block size.

The reason for preferring the simplest change is that the DIGEST-SASL
mechanism is holding up the LDAP RFCs.

> 
> Is there a reason that the sequence number and version field were left
> unencrypted?  In order to minimize the amount of easy cribs?

Although not decribed, the same basic algorithm works for packet flows which
can be recieved out of order (because they are sent over UDP or because of
multiplexing a single TCP connection, as the HTTP/NG folks have talked about
doing. Stream ciphers are problematic in this case. To accomodate them, when
handling out-of-order delivery, each packet, instead of using Ke for the
encryption key, uses HMAC(Ke, SeqNum). This requires the SeqNum to be in the
clear.

The version number beng in the clear is a holdover from an existing protocol
with which I have experience which I thought would be useful to leave in the
clear. The idea it could affect the decryption somehow in future versions,
or indicate different MAC, or that rekeying was needed after a certain
amount of traffic. However, I agree that it's not so important.

Paul