-
Notifications
You must be signed in to change notification settings - Fork 369
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Introduce dtls connection id. #857
Conversation
8a25154
to
88d7496
Compare
I moved some lines into much smaller PR and marked them with "merged soon". |
f026b4e
to
0baafdf
Compare
Should I review this one ? or should we plan more split ? |
At least I rebase and retest it ... split may be ... so review not today :-) |
14e2243
to
c715147
Compare
c715147
to
fb5af41
Compare
fb5af41
to
1dfd856
Compare
If possible PR #868 this week, and this PR next week :-). |
a008bd6
to
5256485
Compare
It would great, if this PR could be merged this week. |
cb3b001
to
704985d
Compare
if (cidLength != null && cidLength > 0 && cidLength != connectionStore.getConnectionIdLength()) { | ||
throw new IllegalArgumentException("Connection store must use the same cid length! " + cidLength | ||
+ " != " + connectionStore.getConnectionIdLength()); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If I well understand, to set ConnectionIdLength
, I need to set it in DtlsConnectorConfig
? but also in connectionStore
(in case of custom store) ?
Should we avoid to set this information twice ?
I see cidlenght is only needed to newConnectionId
which is only called by put
which is only called by DTLSconnector
?
Maybe we can change the API with something like : boolean put(Connection connection, integer cidlenght);
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
but also in
connectionStore
(in case of custom store) ?
I assume, there will be only rare cases, when a custom store is used. But if, the same cid length must be used as for the Record.fromByteArray
. I would prefer to keep the configuration values in the DtlsConnectorConfig
(at least as leading definition ).
So together:
- configuration value in
DtlsConnectorConfig
- rarely use custom store
I think, add it to the javadoc of the DTLSConnector constructor will do it best.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just in case there is misunderstanding, I would keep it DtlsconnectorConfig
but remove it from connectionStore
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remove what? The method getConnectionIdLength
? Or the field cidLength
?
My assumption was, that a custom connection store is rarely used, so I don't think, that spending time into that will payout.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
like express above :
I see cidlenght is only needed to newConnectionId which is only called by put which is only called by DTLSconnector ?
Maybe we can change the API with something like : boolean put(Connection connection, integer cidlenght);
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The constructor also calls newConnectionId, if a ClientSessionCache is restored.
If you really feel, it's worth, then introduce the DtlsConnectorConfig into the parameters of the constructor and replace the others. But please, shift that into an other PR :-).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I missed it was used in the constructor too.
So not so easy to change it.
@@ -869,6 +932,12 @@ private void processRecord(Record record, Connection connection) { | |||
LOGGER.info("Unexpected error occurred while processing record from peer [{}]", | |||
record.getPeerAddress(), e); | |||
terminateConnection(connection, e, AlertLevel.FATAL, AlertDescription.INTERNAL_ERROR); | |||
} catch (GeneralSecurityException e) { | |||
LOGGER.info("error occurred while processing record from peer [{}]", | |||
record.getPeerAddress(), e); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't really know when those 2 exceptions are raised but is it normal we don't terminate the connection ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's the receiving part, so I would not terminate the connection, because this may by used as attack vector. That's somehow the opposite of the catch RuntimeException in receiveNextDatagramFromNetwork. But this PR is more about introducing the cid, than the cleanup of exception handling. I tried to keep it as I found it, may be it gets cleaned up later in an other PR, if we find that it must be improved.
@@ -73,6 +73,8 @@ | |||
public static final int SEQUENCE_NUMBER_BITS = 48; | |||
|
|||
public static final int LENGTH_BITS = 16; | |||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't see it in github but in eclipse I see unwanted whitespaces ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK
this.sequenceNumber = sequenceNumber; | ||
if (session != null && session.getWriteState() != null && epoch > 0) { | ||
fragmentBytes = encryptFragment(fragment.toByteArray()); | ||
if (this.sequenceNumber != sequenceNumber) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You faced situation where this.sequenceNumber == sequenceNumber
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, I haven't seen it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok so you add this test just in case ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, in the case, that some calls it without changing it. FMPOV, protecting such a method, which may require more resources, is not a bad practice.
byte[] byteArray = fragment.toByteArray(); | ||
byteArray = applyInnerTypeAndPadding(byteArray); | ||
fragmentLength = byteArray.length; | ||
fragmentBytes = encryptFragment(byteArray); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it seems pretty much the same idea that setFragment
.
I don't know if this is worthy to factorize this code ?
(I don't like so much those setters which are doing more than it looks like :))
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
FMPOV, I don't like a setter, which then have something "always call additionally" in the javadoc.
Before the change, encryptFragment was called, now with the new record type, the inner type and padding must also be applied. The grants before this change was, that the new sequence number also triggers a new encryption, because the explicit nonce is changed. Now the same grants as before are kept.
So should we go for rename the setter to update
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
FMPOV, I don't like a setter, which then have something "always call additionally" in the javadoc.
It's not better I agree.
So you're right it's just a naming issue, update
sounds good.
But you didn't answer to the first question : it seems pretty much the same idea that setFragment.
I don't know if this is worthy to factorize this code ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
worthy to factorize this code
If I would guess, what you have in mind ...
Do you want the two 4-lines snippet to be merged into a single function?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
byte[] byteArray = fragment.toByteArray();
// the current length of the unprotected message
// this value is needed to generate the additional data when using AEAD
fragmentLength = byteArray.length;
Verifying the comment, I found that it's not (longer?) valid. I would prefer to clean it up with the commit of the wip adding more cipher suites.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See e4df69e
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see, this would be changed in next PR
return; | ||
} else { | ||
record.setSession(session); | ||
record.getFragment(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A bit disturbed about a "getter call" to execute some inner calculation.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This PR doesn't change that.
The new record_type with the "encrypted inner type" just requires, that it is called before that real type is used to determine the record type for processing.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This PR doesn't change that.
I agree. Here this is just more visible as we just call a getter without really use the result.
The new record_type with the "encrypted inner type" just requires, that it is called before that real type is used to determine the record type for processing.
If we don't want do change the idea (I mean a getter which do some processing), maybe this would be more consistent to just "extract the fragment" on getType() ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If you check, where "getType()" is called, you will see the answer.
The inner/outer is a little shitty, but for now, "it works".
I added to comment to give a hint about the intention.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ok
int length = id.length(); | ||
writer.write(1 + length, LENGTH_BITS); | ||
writer.write(length, CID_FIELD_LENGTH_BITS); | ||
writer.writeBytes(id.getBytes()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is an arbitrary way to encode CID ?
I mean there is nothing which say that first byte is the length and next byte are CID ?
We could have used fixed size CID right ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I mean there is nothing which say that first byte is the length and next byte are CID ?
The draft encodes the cid different in the hello extension and the new record type.
In the extension with leading uint8 length, and opaque bytes, in the new record type only the opaque bytes. That's specified by the draft.
Anyway the draft allows you to be more flexible as my current implementation. The draft specifies the cid similar to the coap-token. If one peer send the cid in the hello extension, then the other, if agreed, sent that cid in the records of the next epoch. If a peer uses different sized cids, it must do it in a proper way, so that the peer will be able to read them back.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok I missed the meaning of https://tools.ietf.org/html/rfc5246#section-4.3 notation
"Connection id length too large! 255 max, but has " + (extensionData.length - 1), | ||
new AlertMessage(AlertLevel.FATAL, AlertDescription.ILLEGAL_PARAMETER, peerAddress)); | ||
} | ||
int len = extensionData[0]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is the extension length not the CID length ? right ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's the cid length.
The extension length is encoded as uint16 and is decoded in
HelloExtensions.fromByteArray
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I get it now.
3b2b612
to
685b55e
Compare
Let me propose to shift the renames (set => update) to a later PR, which only contains that renames. |
Improve dtls communication for environments with unaware address changes (e.g. NATs). Signed-off-by: Achim Kraus <[email protected]>
Signed-off-by: Achim Kraus <[email protected]>
👍 |
685b55e
to
aa34d08
Compare
Some cosmetic. |
Add also Bytes for byte array based ids. Redesign connection store. Use
connection id as identifier to support address changes.
Signed-off-by: Achim Kraus [email protected]