1{-# LANGUAGE OverloadedStrings #-}
2-- |
3-- Module      : Network.TLS.KeySchedule
4-- License     : BSD-style
5-- Maintainer  : Vincent Hanquez <vincent@snarc.org>
6-- Stability   : experimental
7-- Portability : unknown
8--
9module Network.TLS.KeySchedule
10    ( hkdfExtract
11    , hkdfExpandLabel
12    , deriveSecret
13    ) where
14
15import qualified Crypto.Hash as H
16import Crypto.KDF.HKDF
17import Data.ByteArray (convert)
18import qualified Data.ByteString as BS
19import Network.TLS.Crypto
20import Network.TLS.Wire
21import Network.TLS.Imports
22
23----------------------------------------------------------------
24
25hkdfExtract :: Hash -> ByteString -> ByteString -> ByteString
26hkdfExtract SHA1   salt ikm = convert (extract salt ikm :: PRK H.SHA1)
27hkdfExtract SHA256 salt ikm = convert (extract salt ikm :: PRK H.SHA256)
28hkdfExtract SHA384 salt ikm = convert (extract salt ikm :: PRK H.SHA384)
29hkdfExtract SHA512 salt ikm = convert (extract salt ikm :: PRK H.SHA512)
30hkdfExtract _ _ _           = error "hkdfExtract: unsupported hash"
31
32----------------------------------------------------------------
33
34deriveSecret :: Hash -> ByteString -> ByteString -> ByteString -> ByteString
35deriveSecret h secret label hashedMsgs =
36    hkdfExpandLabel h secret label hashedMsgs outlen
37  where
38    outlen = hashDigestSize h
39
40----------------------------------------------------------------
41
42hkdfExpandLabel :: Hash
43                -> ByteString
44                -> ByteString
45                -> ByteString
46                -> Int
47                -> ByteString
48hkdfExpandLabel h secret label ctx outlen = expand' h secret hkdfLabel outlen
49  where
50    hkdfLabel = runPut $ do
51        putWord16 $ fromIntegral outlen
52        putOpaque8 ("tls13 " `BS.append` label)
53        putOpaque8 ctx
54
55expand' :: Hash -> ByteString -> ByteString -> Int -> ByteString
56expand' SHA1   secret label len = expand (extractSkip secret :: PRK H.SHA1)   label len
57expand' SHA256 secret label len = expand (extractSkip secret :: PRK H.SHA256) label len
58expand' SHA384 secret label len = expand (extractSkip secret :: PRK H.SHA384) label len
59expand' SHA512 secret label len = expand (extractSkip secret :: PRK H.SHA512) label len
60expand' _ _ _ _ = error "expand'"
61
62----------------------------------------------------------------
63