Subject: RE: DIGEST-MD5 SASL mechanism?

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

> -----Original Message-----
> From: Lawrence Greenfield [mailto:[email-masked]]
> Sent: Wednesday, July 07, 1999 1:20 PM
> To: Paul Leach
> Cc: [email-masked]'
> Subject: Re: DIGEST-MD5 SASL mechanism?
> 
> 
> [...]
>    > 
>    > - the MAC is defined including the "variable length 
> padding prefix",
>    >   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.
> 
> 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:
> 
> 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 your message, I've corrected this to:
> 
> SEAL(Ki, Kc, SeqNum, msg) = CIPHER(Kc, { msg, pad}), CMAC(Ki, Kc,
>       SeqNum, msg)
> CMAC(Ki, Kc, SeqNum, msg) =
>     { 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

---

From: Lawrence Greenfield <[email-masked]>
Date: 7 Jul 1999 22:07:21 -0400

[...]

I guess I sometimes have enough problems understanding these
specifications without the little confusions.

   > Of course, the 10 byte HMAC prefix is not a multiple of the 8 byte DES

   [... my suggestion deleted ....]
   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.

While this could work with silly enough coding, I don't think that
this is really what we want.  Let's see what would come over the wire:

ciphertext 0x0001 ciphertext SeqNum
{msg,pad}         {pad,HMAC}

This means, in order to decrypt using a block cipher, I'll have to
extract the ciphertext corresponding to {msg,pad}, extract the
ciphertext corresponding to {pad,HMAC}, concatenate the two, perform
the decryption, take the last 10 bytes for the HMAC, and the remaining
non-pad bytes corresponding to the msg.  This seems overly complex.

If we could go:
{ msg, HMAC, pad, version, SeqNum }
  ----encrypt----
   
that would work.  Then it's also clear that I don't use the padding to
generate the checksum.

Another possible solution makes me ask this ignorant
question---perhaps it is obvious: why is the HMAC encrypted?

Larry

---

From: Lawrence Greenfield <[email-masked]>
Date: 7 Jul 1999 22:07:21 -0400

[...]

If we could go:
  ----encrypt----

Larry