[Swan] Can you elaborate on this ?

Paul Wouters pwouters at redhat.com
Tue Jan 22 18:47:23 EET 2013


On Tue, 22 Jan 2013, Philippe Vouters wrote:

> Part or all of Elison's problems is caused by this in 
> ./programs/pluto/ikev1.c:
>     {
>        /* packet was not encryped -- should it have been? */
>
>        if (smc->flags & SMF_INPUT_ENCRYPTED)
>        {
>            loglog(RC_LOG_SERIOUS, "packet rejected: should have been 
> encrypted");
>            SEND_NOTIFICATION(INVALID_FLAGS);
>            return;
>        }
> It gets conditionally executed when if (md->hdr.isa_flags & 
> ISAKMP_FLAG_ENCRYPTION) reveals false.
> SMF_INPUT_ENCRYPTED is a macro inside the same source file which is set to:
> #define SMF_INPUT_ENCRYPTED     LELEM(OAKLEY_AUTH_ROOF + 2)
>
> OAKLEY_AUTH_ROOF is defined as:
> #define OAKLEY_AUTH_ROOF           8  /*roof on auth values THAT WE SUPPORT 
> */
> ./include/ietf_constants.h
>
> Can you justify a bit more on the pertinence or not of the above 
> loglog(RC_LOG_SERIOUS,...) that Elison faces ????

SMF stands for State Machine Flags. Those are predicates that must be
met to be a valid packet for a certain state in the state machine.

When we initiate or respond to a connection, an "instance" is created
for that connection with a state object (see struct state). The state
machines defines the valid states. For each state, following the RFCs,
certain conditions must be met. These are encoded with the SMF_* flags.
When processing an incoming packet, a state change transition may
happen. These are encoded in the STF_XXXX messages, such as:

STF_OK: state changed successfully
STF_FAIL: state change not successful. Usually this triggers sending a
packet with an error condition, such as NO_PROPOSAL_CHOSEN.
STF_INLINE: an internal state change (not based on RFC). Usually refers
to helper processes that we wait on.
STF_FATAL: we should never have reached this point. There is an error in
our code - launch assertion failure, dump core, and restart daemon.
STF_IGNORE: we are remaining in the same state, awaiting a new event.

pluto is event based. State changes happen as a result of an event. This
could be receiving a packet, a timer based event, or our select() call
receiving an event (eg crypto helper ready, whack command on socket)

The terms I and R in MAIN_I1 or AGGR_R2 stands for the mode (main mode,
aggressive mode, quick mode, etc) followed by the I for initiator states
and R for responder states, followed by the packet number. Functions
related to the state have names that signify what comes in, and what
goes out, so aggr_inI2_outR2() is called only when the state is in
Aggressive mode R1, and we are waiting to receive the second packet from
the initiator, upon which we will send out the second packet as
responder and move into the Aggr R2 state (which if you would look at
the state table, would be expecting a Quick Mode I1 packet)

md is the message digest, the stream of bytes from the incoming packet.
It contains the IKE (ISAKMP) header of the incoming packet. The IKE header
of the incoming packet contains a flag stating whether or not the packet
is encrypted. So for each state in the state machine, we compare the
received "encryption flag" (md->hdr.isa_flags & ISAKMP_FLAG_ENCRYPTION)
with the expected state machine "encryption flag" (SMF_INPUT_ENCRYPTED)

The ROOF and LELEM are constructs designed by Hugh Redelmeier to ease
the checking of certain flags and switch cases. You normally iterate
until you hit the ROOF. If you hit the ROOF, it means what that what
you were looking for was not found. ROOF is like "maximum". I find the
construct of LELEM complicated, it is deeply depending on MACRO's. I
should have an explanation by Hugh somewhere in old email that I can try
to find for you at a later date. So I cannot tell you right now how the
construct of LELEM works with a ROOF + value, but I am fairly confident
that the code is correct. Perhaps Hugh can elaborate further.

As stated in my answers on the list, I am pretty sure the "encrypted"
versus "unencrypted" messages are due because of a disagreement between
the parameters of the connection. Because this is Aggressive Mode, and
exchanging parameters and Diffie-Hellman happen concurrently (unlike in
Main Mode where DH is completed before parameters are exchanged, but it
takes double the number of packets exchanged, so has double the
latency in establishing the connection)

One could argue a new state in the state machine could be made where we
can go and receive an unencrypted message, and parse the notification
payload. This state would not allow to move into Aggr R2.

But we are remaining in the same state because we could still receive a
properly encrypted message. An unencrypted message could be send by an
attacker to mislead us, so we cannot make any state machine changes based
on such an unsecured packet that could have been spoofed. So we log it,
and remain waiting for a proper packet that complies with the RFCs as
implemented in our state machine. This is likely signaled by the
function returning STF_IGNORE (I did not look it up)

Paul


More information about the Swan mailing list