File: GF.hs

package info (click to toggle)
haskell-crypto-cipher-types 0.0.9-13
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 116 kB
  • sloc: haskell: 464; makefile: 2
file content (49 lines) | stat: -rw-r--r-- 1,672 bytes parent folder | download | duplicates (6)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
-- |
-- Module      : Crypto.Cipher.Types.GF
-- License     : BSD-style
-- Maintainer  : Vincent Hanquez <vincent@snarc.org>
-- Stability   : Stable
-- Portability : Excellent
--
-- Slow Galois Field arithmetic for generic XTS and GCM implementation
--
module Crypto.Cipher.Types.GF
    (
    -- * XTS support
      xtsGFMul
    ) where

import Control.Applicative
import Data.ByteString (ByteString)
import qualified Data.ByteString as B
import qualified Data.ByteString.Internal as B
import Data.Byteable
import Foreign.Storable
import Foreign.Ptr
import Data.Word
import Data.Bits

-- block size need to be 128 bits.
--
-- FIXME: add support for big endian.
xtsGFMul :: ByteString -> ByteString
xtsGFMul b
    | B.length b == 16 = B.unsafeCreate (B.length b) $ \dst ->
                         withBytePtr b $ \src -> do
                         (hi,lo) <- gf <$> peek (castPtr src) <*> peek (castPtr src `plusPtr` 8)
                         poke (castPtr dst) lo
                         poke (castPtr dst `plusPtr` 8) hi
    | otherwise        = error "unsupported block size in GF"
  where gf :: Word64 -> Word64 -> (Word64, Word64)
        gf srcLo srcHi =
            ((if carryLo then (.|. 1) else id) (srcHi `shiftL` 1)
            ,(if carryHi then xor 0x87 else id) $ (srcLo `shiftL` 1)
            )
          where carryHi = srcHi `testBit` 63 
                carryLo = srcLo `testBit` 63
{-
	const uint64_t gf_mask = cpu_to_le64(0x8000000000000000ULL);
	uint64_t r = ((a->q[1] & gf_mask) ? cpu_to_le64(0x87) : 0);
	a->q[1] = cpu_to_le64((le64_to_cpu(a->q[1]) << 1) | (a->q[0] & gf_mask ? 1 : 0));
	a->q[0] = cpu_to_le64(le64_to_cpu(a->q[0]) << 1) ^ r;
-}