Hi, this is a long message...
I've looked through the -01 version of the QSKE draft. The draft has been
expanded
and now it covers such aspects as QSKE negotiation, fragmentation and
transferring
of payloads larger than 64K. I didn't review the draft in details, however
after reading
I have concerns over the technical solutions the draft proposes. In particular,
I think that
the problems of negotiation, fragmentation and representation of large payloads
could be solved better.
1. Negotiation.
The draft introduces a new negotiation mechanism to be used explicitly with
multiple QS key exchanges. While the proposed mechanism looks like an ingenious
way to deal with legacy implementations and as a powerful tool to negotiate
complex policies, I don't think it is ever needed, since all this can be done
using existing mechanism. How it can be achieved:
Let's define a bunch of new Transform Types each defining some kind of QSKE:
Transform Type 6 - Lattice QSKE
Transform Type 7 - Code-based QSKE
Transform Type 8 - Isogeny-based QSKE
Transform Type 9 - Symmetric QSKE
...
Each of these Transform Types must then be populated with Transform IDs
for QSKE of corresponding type. It is also important to add NONE into each of
these
types. The Initiator willing to combine QSKEs of specific types would include
corresponding Transform Types populated with the Transform IDs the initiator
deems acceptable. If NONE for some Transform Type is included, it means
that this Transform Type is optional. IKEv2 requires the responder to select
a combination of transforms such that a single Transform ID of each Transform
Type
is present. It means that the current SA payload syntax is able to represent
the policies
that the new negotiation mechanism in the draft is designed for. For example:
SA:
Proposal1:
TransformType1: ENCR_AES_CBC
TransformType2: PRF_HMAC_SHA2_256
TransformType3: AUTH_HMAC_SHA2_256_128
TransformType4: 2048-bit MODP Group
Proposal2:
TransformType1: ENCR_AES_CBC
TransformType2: PRF_HMAC_SHA2_256
TransformType3: AUTH_HMAC_SHA2_256_128
TransformType4: 2048-bit MODP Group
TransformType6: LatticeQSKE_2
TransformType6: CodebasedQSKE_1, CodebasedQSKE_2
Proposal3:
TransformType1: ENCR_AES_CBC
TransformType2: PRF_HMAC_SHA2_256
TransformType3: AUTH_HMAC_SHA2_256_128
TransformType4: 2048-bit MODP Group
TransformType6: LatticeQSKE_1
TransformType6: LatticeQSKE_2, NONE
TransformType6: IsogenybasedQSKE_1, IsogenybasedQSKE_2
In this example the Proposal1 is aimed for the legacy responders.
Proposals means that the classic MODP_2048 group
must be combined with LatticeQSKE_2 and either CodebasedQSKE_1 or
CodebasedQSKE_2. Proposal3 means that the classic MODP_2048 group must be
combined with either IsogenybasedQSKE_1 or IsogenybasedQSKE_2 and may
optionally
be combined with LatticeQSKE_2.
Legacy responders would ignore Proposals 2 and 3 since they contain
unknown Transform Type. However they would pick Proposal1.
QSKE-enabled responders would select either Proposal 2 or 3 depending
on their policy.
Re-using existing mechanism is much easier to implement since the parsing
code is already there, as well as the interface with the local policy.
This mechanism is flexible enough to express the policies from the draft.
It doesn't have a round trip penalty when communicating with legacy
responder. It assumes that classic KE is always present, however I can
see it as a feature, not as a disadvantage (see the next topic in the message).
And in the future it will be possible to add QSKE mechanisms into Transform
Type 4,
provided their public key are small enough (and their security is proved, of
course).
In this case no classic KE is more needed.
One disadvantage of using SA payload comparing with the new mechanism from
the draft is that it is less compact and complex policies can lead to the
situation
when SA payload size will become too large. However, there is a draft
describing compact
representation of IKE payloads that allows to significantly decrease SA payload
size
(https://datatracker.ietf.org/doc/draft-smyslov-ipsecme-ikev2-compact/)
One more consideration. I assume that existing implementations are conformant
with
RFC 7296, which states (Section 3.3.6):
If the responder receives a proposal that contains a Transform Type
it does not understand, or a proposal that is missing a mandatory
Transform Type, it MUST consider this proposal unacceptable; however,
other proposals in the same SA payload are processed as usual.
There were a concerns that some implementations could incorrectly
reject the whole SA payload if they encountered an unknown Transform Type.
To deal with such (crippled) implementations one more round trip and an
additional logic would be needed (if we decide to deal with them ever),
but I think that it'll be no more complex than the negotiation mechanism from
the draft.
Am I missing something here?
2. Fragmentation
I think that defining a new fragmentation mechanism for IKE_SA_INIT is bad
choice.
We already have IKE fragmentation and it is more appropriate to re-use
existing mechanism. It is possible to do it in a way suggested by Tero:
https://www.ietf.org/mail-archive/web/ipsec/current/msg11563.html
I've published a draft defining auxiliary exchange for this purpose:
https://datatracker.ietf.org/doc/draft-smyslov-ipsecme-ikev2-aux/
Comparing with a new fragmentation mechanism for IKE_SA_INIT defined in the
draft,
re-using the existing IKE fragmentation via an auxiliary exchange has the
following advantages.
- It is easier to implement. The IKE fragmentation is already supported by many
vendors
and it is easier to add a new simple exchange than to complicate
IKE_SA_INIT, that is already
quite complex. Note, that with the draft's proposal IKE_SESSION_RESUME
exchange would
need to be modified as well. With auxiliary exchanges resumption will be
supported for free.
- It is substantially more secure. The way the draft deals with fragmentation
is susceptible to DoS
attacks when an attacker injects bogus fragments poisoning reassembly
buffer. Adding
cookie to the fragments. as the draft suggests to prevent this attack,
doesn't help at all:
to inject bogus fragments an attacker need to know IKE SPIs, so he/she must
be able
to view messages from the peers, and if he/she is able to do it, then he/she
will also
know the cookie. So, the proposed defense never works. This attack is
impossible
with the standard IKE fragmentation unless an attacker is able to break key
exchange
in the IKE_SA_INIT in real time. I presume he/she would need QC for that and
I hope
by the time it is possible we'll already have some QC-proof key exchange
with small
public keys, so that it can be used in the IKE_SA_INIT and thwart the attack.
- It is more robust. The problem with the approach suggested in the draft is
that it
works very poorly in case of packet loss, because all the fragments are sent
simultaneously.
If the number of fragments is small enough, then it doesn't cause major
problems.
However, as the number of fragment grows, single packet loss results in
resending
the whole bunch of fragments. If the packet loss is caused by congestion,
then
momentary resending all the fragments would result in more congestion, that
would only make things worse. Standard IKE fragmentation is also susceptible
to this problem, since it wasn't designed to deal with more than a handful
fragments.
This is no more true with QC-safe huge public keys. Ideally, each fragment
should be acknowledged individually, however in is generally impossible with
IKE
request-reply paradigm (since reply fragments must also be acknowledged).
Fortunately, using several auxiliary exchanges for transferring QC-safe
public keys
make it possible to at least make this problem less significant. The idea is
to perform several QC-safe key exchanges utilizing large public keys one by
one:
HDR (IKE_SA_INIT, MID=0), SAi1, KEi, Ni,
[N(AUX_EXCHANGE_SUPPORTED)] -->
<-- HDR (IKE_SA_INIT, MID=0), SAr1, KEr,
Nr,
[N(AUX_EXCHANGE_SUPPORTED)]
HDR (IKE_AUX, MID = 1), SK {QSKE1i} -->
<-- HDR (IKE_AUX, MID = 1), SK { QSKE1ir}
HDR (IKE_AUX, MID = 2), SK {QSKE2i} -->
<-- HDR (IKE_AUX, MID = 2), SK { QSKE2ir}
HDR (IKE_AUTH, MID = 3), SK {SA, TSi, TSr} -->
<-- HDR (IKE_AUTH, MID = 3), SK { SA,
TSi, TSr}
So each of negotiated QSKEs is performed in a separate exchange,
thus reducing the number of fragments in case it is fragmented.
It is even possible to split any single QS key exchange in a several
IKE_AUX exchanges if the exchange is DH-like, i.e. if public keys are
of the same size and are generated independently.
[Actually the same problem with reliable transferring of large number
of fragments in case of QSKE will also arise in case of re-keying...
There are several possible solutions, but I think they can be discussed
separately.]
So, I see no advantages of the new IKE_SA_INIT fragmentation mechanism
over the re-using of existing one. Again, am I missing something here?
3. Large KE payloads
The draft makes it possible to deal with public keys greater than 64K
by means of a complex pointer-like system (integrated with proposed
fragmentation mechanism). I think that it is too complex. I'd rather
use simple approach, that is aligned with the re-using of standard
IKE fragmentation described above.
I propose that in case the public key is greater than 64K, it is
split into several consecutive KE payloads in a single message.
If several long public keys are present in the message, then
all the payloads each key is split into must be grouped together.
An example:
HDR (IKE_AUX, MID = 1), SK {QSKE1i, QSKE1i, QSKE1i, QSKE2i, QSKE2i } -->
<-- HDR (IKE_AUX, MID = 1), SK { QSKE1ir, QSKE1ir, QSKE1ir, QSKE2ir,
QSKE2ir }
Here we have 2 large public key in a single message, QSKEi1 is split
into 3 payloads and QSKEi2 is split into 2 payloads. Actually, I don't think
it is a good idea to send several large public keys in a single message given
the problems outlined above, but it is a possible construction.
A better way would be:
HDR (IKE_AUX, MID = 1), SK {QSKE1i, QSKE1i, QSKE1i} -->
<-- HDR (IKE_AUX, MID = 1), SK { QSKE1ir, QSKE1ir,
QSKE1ir}
HDR (IKE_AUX, MID = 2), SK {QSKE2i, QSKE2i} -->
<-- HDR (IKE_AUX, MID = 2), SK { QSKE2ir, QSKE2ir}
And even better way would be (provided the QSKEs are DH-like):
HDR (IKE_AUX, MID = 1), SK {QSKE1i} -->
<-- HDR (IKE_AUX, MID = 1), SK { QSKE1ir}
HDR (IKE_AUX, MID = 2), SK {QSKE1i} -->
<-- HDR (IKE_AUX, MID = 2), SK { QSKE1ir}
HDR (IKE_AUX, MID = 3), SK {QSKE1i} -->
<-- HDR (IKE_AUX, MID = 3), SK { QSKE1ir}
HDR (IKE_AUX, MID = 4), SK {QSKE2i} -->
<-- HDR (IKE_AUX, MID = 4), SK { QSKE2ir}
HDR (IKE_AUX, MID = 5), SK {QSKE2i} -->
<-- HDR (IKE_AUX, MID = 5), SK { QSKE2ir}
[And I still hope that cryptographers won't leave us with only
those QC safe key exchange methods that use huge public keys.
I really don't want to transfer megabytes of keys just to create an SA
to read my one hundred bytes long e-mail...]
So, the bottom line. I think that the QSKE draft goes into wrong
direction, suggesting over-complicated and insecure solutions
and ignoring existing mechanisms that can be used instead.
I hope the authors will re-consider this.
Regards,
Valery.
_______________________________________________
IPsec mailing list
[email protected]
https://www.ietf.org/mailman/listinfo/ipsec