Permalink
Browse files

Move to a C implementation for constant time comparisons.

  • Loading branch information...
1 parent b0041ac commit 2a1dd8e6978c2b49587aa62ea9445bfed7204f02 @TomMD committed Dec 1, 2011
Showing with 45 additions and 7 deletions.
  1. +7 −0 CHANGELOG
  2. +16 −4 Crypto/Classes.hs
  3. +7 −0 cbits/misc.c
  4. +4 −0 cbits/misc.h
  5. +11 −3 crypto-api.cabal
View
@@ -1,3 +1,10 @@
+0.8.1
+* Moved to a C implementation for constant time equality.
+
+0.8
+* Altered the HMAC Key type to carry phantom types
+* Added a constant time equality checker
+
0.5.3
* Add reasonably performing cnt' mode of operation (good for BlockCipher based RNGs)
View
@@ -13,7 +13,7 @@ as changing a type signature.
-}
module Crypto.Classes
- (
+ (
-- * Hash class and helper functions
Hash(..)
, hash
@@ -40,12 +40,16 @@ import Data.Serialize
import qualified Data.ByteString.Lazy as L
import qualified Data.ByteString as B
import qualified Data.ByteString.Internal as I
+import Data.ByteString.Unsafe (unsafeUseAsCStringLen)
import Data.Bits ((.|.), xor)
import Data.List (foldl')
import Data.Word (Word64)
import Data.Tagged
import Crypto.Types
import Crypto.Random
+import System.IO.Unsafe (unsafePerformIO)
+import Foreign (Ptr)
+import Foreign.C (CChar, CInt)
import System.Entropy
-- |The Hash class is intended as the generic interface
@@ -221,12 +225,20 @@ for t _ = unTagged t
-- time when the first byte is different than when the first byte
-- is equal. This side channel allows an attacker to mount a
-- timing attack. On the other hand, @constTimeEq@ always takes the
--- same time regardless of the bytestrings' contents.
+-- same time regardless of the bytestrings' contents, unless they are
+-- of difference size.
--
-- You should always use @constTimeEq@ when comparing hashes,
-- otherwise you may leave a significant security hole
-- (cf. <http://codahale.com/a-lesson-in-timing-attacks/>).
constTimeEq :: B.ByteString -> B.ByteString -> Bool
constTimeEq s1 s2 =
- B.length s1 == B.length s2 &&
- foldl' (.|.) 0 (B.zipWith xor s1 s2) == 0
+ unsafePerformIO $
@singpolyma
singpolyma Jan 1, 2013 Contributor

Why not just specify in the FFI import that the C function is pure? It doesn't use any IO-needing operations, even internally.

+ unsafeUseAsCStringLen s1 $ \(s1_ptr, s1_len) ->
+ unsafeUseAsCStringLen s2 $ \(s2_ptr, s2_len) ->
+ if s1_len /= s2_len
+ then return False
+ else (== 0) `fmap` c_constTimeEq s1_ptr s2_ptr (fromIntegral s1_len)
+
+foreign import ccall unsafe
+ c_constTimeEq :: Ptr CChar -> Ptr CChar -> CInt -> IO CInt
View
@@ -0,0 +1,7 @@
+/* Fast C implementation of a safe string equality test. */
+int c_safeEq(char *x, char *y, int length) {
+ int ret = 0, i;
+ for (i = 0; i < length; i++)
+ ret = ret | x[i] ^ y[i];
+ return ret;
+}
View
@@ -0,0 +1,4 @@
+#ifndef CRYPTO_API_MISC_H
+#define CRYPTO_API_MISC_H
+int c_safeEq(char *x, char *y, int length);
+#endif
View
@@ -1,5 +1,5 @@
name: crypto-api
-version: 0.8
+version: 0.8.1
license: BSD3
license-file: LICENSE
copyright: Thomas DuBuisson <thomas.dubuisson@gmail.com>, Francisco Blas Izquierdo Riera (klondike) (see AUTHORS)
@@ -23,7 +23,10 @@ bug-reports: http://trac.haskell.org/crypto-api/report/1
stability: stable
build-type: Simple
cabal-version: >= 1.6
-tested-with: GHC == 7.0.3
+tested-with: GHC == 7.2.2
+extra-source-files:
+ cbits/misc.c
+ cbits/misc.h
Library
@@ -34,8 +37,13 @@ Library
largeword >= 1.0.0, array, entropy
ghc-options:
hs-source-dirs:
- exposed-modules: Crypto.Classes, Crypto.Types, Crypto.HMAC, Crypto.Modes, Crypto.Random, Crypto.Padding
+ exposed-modules: Crypto.Classes, Crypto.Types, Crypto.HMAC,
+ Crypto.Modes, Crypto.Random, Crypto.Padding
other-modules: Crypto.Util, Crypto.CPoly
+ extensions: ForeignFunctionInterface, MultiParamTypeClasses,
+ BangPatterns, FunctionalDependencies, FlexibleInstances,
+ TypeSynonymInstances
+ c-sources: cbits/misc.c
source-repository head
type: git

0 comments on commit 2a1dd8e

Please sign in to comment.