Skip to content
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

Adding states and parameters for TLS 1.3 #280

Closed
wants to merge 16 commits into from

Conversation

kazu-yamamoto
Copy link
Collaborator

This PR adds some states, parameters, APIs for TLS 1.3.
This does not break the current testing.

Copy link
Contributor

@ocheron ocheron left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Globally ok, but I start to have some questions.

@@ -30,7 +30,7 @@ import System.IO.Error (mkIOError, eofErrorType)
checkValid :: Context -> IO ()
checkValid ctx = do
established <- ctxEstablished ctx
unless established $ throwIO ConnectionNotEstablished
when (established == NotEstablished) $ throwIO ConnectionNotEstablished
eofed <- ctxEOF ctx
when eofed $ throwIO $ mkIOError eofErrorType "data" Nothing Nothing
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does that mean sendData and recvData are possible in all 3 other states?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For TLS 1.2 or earlier and clients of TLS 1.3, only Established and NotEstablished are used.

For servers of TLS 1.3, sendData can be used only on Established.
recvData can be used on either Established or EarlyDataAllowed.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you are concerned about this, let's come back to this issue after the entire merge process is finished.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can see the coming patches on https://github.com/kazu-yamamoto/hs-tls/tree/work13

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK we can see checkValid later.

| AcceptEarlyData Word32
| SendEarlyData ByteString
deriving (Eq, Show)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be documented. I'm not sure to understand what the Word32 is for. If it's a length, then Int would be easier to use on external APIs. Also then I don't see difference between NoEarlyData and AcceptEarlyData 0.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • NoEarlyData is deleted. AcceptEarlyData 0 is used instead.
  • AcceptEarlyData Word32 is changed to AcceptEarlyData Int
  • Document is written.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK but if type is different for client and server, maybe this should be moved out of Supported to ClientParams / ServerParams directly.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AcceptEarlyData is used in recvData which takes only Context.
So, if we take your approach, we need to add a new field to Context and copy the value from ServerParams to Context.

It it worth doing?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes that looks useful. Because it would allow to track how much 0RTT data has been received and how much left is allowed. Maybe inside the EarlyDataAllowed constructor.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using EarlyDataAllowed is a really nice idea!
The patch to implement this idea is pushed.

++ ", ageAdd = " ++ show (ageAdd s)
++ ", txrxTime = " ++ show (txrxTime s)
++ " }"

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This could implement showsPrec instead. Not long ago I was looking for an example and did one here: https://github.com/ocheron/cryptostore/blob/d6212dca8135c07b7dfa4f51b1c269d9a8bc5cb7/src/Crypto/Store/CMS/Info.hs#L194

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice idea!
Done.

, sessionGroup :: Maybe Group
, sessionTicketInfo :: Maybe TLS13TicketInfo
, sessionALPN :: Maybe ByteString
, sessionMaxEarlyDataSize :: Word32
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here, I'm not sure Word32 is the best type on external API.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now Int is used.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If Int is 32 bits, how should we treat valid values of 2^31 or larger?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this validation code acceptable?

-- Word32 is used in TLS 1.3 protocol.
-- Int is used for API for Haskell TLS because it is natural.
-- If Int is 64 bits, users can specify bigger number than Word32.
-- If Int is 32 bits, 2^31 or larger may be converted into minus numbers.
safeNonNegative32 :: (Num a, Ord a) => a -> a
safeNonNegative32 x
  | x <= 0    = 0
  | otherwise = x
          `min` fromIntegral (maxBound :: Int)    -- Int is 32 bits
          `min` fromIntegral (maxBound :: Word32) -- Int is 64 bits

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think fromIntegral (maxBound :: Word32) will be -1 with a 32-bit Int.
What about this instead:

safeNonNegative32 :: Int -> Word32
safeNonNegative32 x
    | x <= 0                = 0
    | finiteBitSize x <= 32 = fromIntegral x
    | otherwise             =
        fromIntegral (x `min` fromIntegral (maxBound :: Word32))

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice!

, ageAdd :: Second -- NewSessionTicket.ticket_age_add
, txrxTime :: Millisecond -- serverSendTime or clientReceiveTime
, estimatedRTT :: IORef (Maybe Millisecond)
} deriving (Eq)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Isn't it an issue to expose this IORef? This will allow to change the value.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

RTT has not been estimated when TLS13TicketInfo is created.
So, we need to set it when RTT is estimated.

TLS13TicketInfo is an abstract data type. Its internal is not exported.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK but SessionData used to be fully serializable, i.e. the content could be written to a file. What are the recommendations to do this now? Can the IORef be simply skipped and reconstructed empty?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • When writing, the IORef should be read and the value should be stored.
  • When reading, the value should be obtained and a new IORef should be created with the value.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tried to consider the possibility to remove estimatedRTT from SessionData.
But it results in introducing a new state manager, sigh.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Issue is not only with estimatedRTT. If TLS13TicketInfo is opaque then it's not possible to serialize, unless dedicated primitives are provided.

sessionResume :: SessionID -> IO (Maybe SessionData)
sessionResume :: SessionID -> IO (Maybe SessionData)
-- | used on server side to decide whether to resume a client session for TLS 1.3 0RTT
, sessionResumeOnlyOnce :: SessionID -> IO (Maybe SessionData)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The documentation should explain expectation about the implementation. i.e. not returning the SessionData again after this call.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for your suggestion.
Done.

@kazu-yamamoto
Copy link
Collaborator Author

I think that I answered all questions.

@kazu-yamamoto
Copy link
Collaborator Author

@ocheron What's necessary to approve this PR?

Copy link
Contributor

@ocheron ocheron left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK with this, I edited slightly the checklist in #282.

kazu-yamamoto added a commit to kazu-yamamoto/hs-tls that referenced this pull request Aug 20, 2018
@kazu-yamamoto
Copy link
Collaborator Author

Merged. Thank you for your review.

@kazu-yamamoto kazu-yamamoto deleted the adding13 branch August 20, 2018 22:37
@kazu-yamamoto kazu-yamamoto mentioned this pull request Sep 13, 2018
7 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants