Skip to content

Commit

Permalink
Merge pull request #1751 from GaloisInc/issue_1740
Browse files Browse the repository at this point in the history
Remove bitvectors width from the value tag.
  • Loading branch information
yav authored Sep 17, 2024
2 parents 98c5cf6 + 496de4c commit b1bdfd0
Show file tree
Hide file tree
Showing 15 changed files with 116 additions and 91 deletions.
4 changes: 4 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@

## Bug fixes

* Fix #1740, removes duplicated width from word values.
Note that since this changes the types, it may require changes to
libraries depending on Cryptol.

## New features

# 3.2.0 -- 2024-08-20
Expand Down
4 changes: 2 additions & 2 deletions cryptol-remote-api/src/CryptolServer/Data/Expression.hs
Original file line number Diff line number Diff line change
Expand Up @@ -566,10 +566,10 @@ readBack ty val =
_ -> mismatchPanic
TVSeq len elemTy
| elemTy == TVBit
, VWord width wv <- val -> do
, VWord wv <- val -> do
Concrete.BV w v <- liftEval $ asWordVal Concrete.Concrete wv
let hexStr = T.pack $ showHex v ""
let paddedLen = fromIntegral ((width `quot` 4) + (if width `rem` 4 == 0 then 0 else 1))
let paddedLen = fromIntegral ((w `quot` 4) + (if w `rem` 4 == 0 then 0 else 1))
pure $ Just $ Num Hex (T.justifyRight paddedLen '0' hexStr) w
| VSeq _l (enumerateSeqMap len -> mVals) <- val -> do
vals <- liftEval $ sequence mVals
Expand Down
9 changes: 8 additions & 1 deletion src/Cryptol/Backend.hs
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
{-# Language FlexibleContexts #-}
{-# Language TypeFamilies #-}
{-# Language ScopedTypeVariables #-}
module Cryptol.Backend
( Backend(..)
, wordLen
, sDelay
, invalidIndex
, cryUserError
Expand Down Expand Up @@ -36,6 +38,7 @@ module Cryptol.Backend
import qualified Control.Exception as X
import Control.Monad.IO.Class
import Data.Kind (Type)
import Data.Proxy(Proxy(..))

import Cryptol.Backend.FloatHelpers (BF)
import Cryptol.Backend.Monad
Expand Down Expand Up @@ -295,7 +298,7 @@ class MonadIO (SEval sym) => Backend sym where
bitAsLit :: sym -> SBit sym -> Maybe Bool

-- | The number of bits in a word value.
wordLen :: sym -> SWord sym -> Integer
wordLen' :: proxy sym -> SWord sym -> Integer

-- | Determine if this symbolic word is a literal.
-- If so, return the bit width and value.
Expand Down Expand Up @@ -813,3 +816,7 @@ type FPArith2 sym =
SFloat sym ->
SFloat sym ->
SEval sym (SFloat sym)

wordLen :: forall sym. Backend sym => sym -> SWord sym -> Integer
wordLen _ x = wordLen' (Proxy :: Proxy sym) x
{-# INLINE wordLen #-}
4 changes: 3 additions & 1 deletion src/Cryptol/Backend/Concrete.hs
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,9 @@ instance Backend Concrete where
assertSideCondition _ True _ = return ()
assertSideCondition sym False err = raiseError sym err

wordLen _ (BV w _) = w
wordLen' _ (BV w _) = w
{-# INLINE wordLen' #-}

wordAsChar _ (BV _ x) = Just $! integerToChar x

wordBit _ (BV w x) idx = pure $! testBit x (fromInteger (w - 1 - idx))
Expand Down
3 changes: 2 additions & 1 deletion src/Cryptol/Backend/SBV.hs
Original file line number Diff line number Diff line change
Expand Up @@ -201,7 +201,8 @@ instance Backend SBV where
SBVResult pz z ->
pure $ SBVResult (svAnd (svIte c px py) pz) z

wordLen _ v = toInteger (intSizeOf v)
wordLen' _ v = toInteger (intSizeOf v)
{-# INLINE wordLen' #-}
wordAsChar _ v = integerToChar <$> svAsInteger v

iteBit _ b x y = pure $! svSymbolicMerge KBool True b x y
Expand Down
3 changes: 2 additions & 1 deletion src/Cryptol/Backend/What4.hs
Original file line number Diff line number Diff line change
Expand Up @@ -273,7 +273,8 @@ instance W4.IsSymExprBuilder sym => Backend (What4 sym) where
| SW.bvWidth bv == 8 = toEnum . fromInteger <$> SW.bvAsUnsignedInteger bv
| otherwise = Nothing

wordLen _ bv = SW.bvWidth bv
wordLen' _ bv = SW.bvWidth bv
{-# INLINE wordLen' #-}

bitLit sym b = W4.backendPred (w4 sym) b
bitAsLit _ v = W4.asConstantPred v
Expand Down
10 changes: 10 additions & 0 deletions src/Cryptol/Backend/WordValue.hs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ module Cryptol.Backend.WordValue
( -- * WordValue
WordValue
, wordVal
, wordValWidth
, bitmapWordVal
, asWordList
, asWordVal
Expand Down Expand Up @@ -59,6 +60,7 @@ module Cryptol.Backend.WordValue

import Control.Monad (unless)
import Data.Bits
import Data.Proxy(Proxy(..))
import GHC.Generics (Generic)

import Cryptol.Backend
Expand Down Expand Up @@ -97,6 +99,14 @@ data WordValue sym
!(SeqMap sym (SBit sym)) -- ^
deriving (Generic)

wordValWidth :: forall sym. Backend sym => WordValue sym -> Integer
wordValWidth val =
case val of
ThunkWordVal n _ -> n
WordVal sv -> wordLen' (Proxy :: Proxy sym) sv
BitmapVal n _ _ -> n
{-# INLINE wordValWidth #-}

wordVal :: SWord sym -> WordValue sym
wordVal = WordVal

Expand Down
10 changes: 5 additions & 5 deletions src/Cryptol/Eval.hs
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ evalExpr sym env expr = case expr of
-- NB, even if the list cannot be packed, we must use `VWord`
-- when the element type is `Bit`.
| isTBit tyv -> {-# SCC "evalExpr->Elist/bit" #-}
VWord len <$>
VWord <$>
(tryFromBits sym vs >>= \case
Just w -> pure (wordVal w)
Nothing -> do xs <- mapM (\x -> sDelay sym (fromVBit <$> x)) vs
Expand Down Expand Up @@ -594,7 +594,7 @@ evalSel sym val sel = case sel of
case v of
VSeq _ vs -> lookupSeqMap vs (toInteger n)
VStream vs -> lookupSeqMap vs (toInteger n)
VWord _ wv -> VBit <$> indexWordValue sym wv (toInteger n)
VWord wv -> VBit <$> indexWordValue sym wv (toInteger n)
_ -> do vdoc <- ppValue sym defaultPPOpts val
evalPanic "Cryptol.Eval.evalSel"
[ "Unexpected value in list selection"
Expand Down Expand Up @@ -643,7 +643,7 @@ evalSetSel sym _tyv e sel v =
case e of
VSeq i mp -> pure $ VSeq i $ updateSeqMap mp n v
VStream mp -> pure $ VStream $ updateSeqMap mp n v
VWord i m -> VWord i <$> updateWordValue sym m n asBit
VWord m -> VWord <$> updateWordValue sym m n asBit
_ -> bad "Sequence update on a non-sequence."

asBit = do res <- v
Expand Down Expand Up @@ -781,7 +781,7 @@ evalMatch sym (lsz, lenv) m = seq lsz $ case m of
let lenv' = lenv { leVars = fmap stutter (leVars lenv) }
let vs i = do let (q, r) = i `divMod` nLen
lookupSeqMap vss q >>= \case
VWord _ w -> VBit <$> indexWordValue sym w r
VWord w -> VBit <$> indexWordValue sym w r
VSeq _ xs' -> lookupSeqMap xs' r
VStream xs' -> lookupSeqMap xs' r
_ -> evalPanic "evalMatch" ["Not a list value"]
Expand All @@ -795,7 +795,7 @@ evalMatch sym (lsz, lenv) m = seq lsz $ case m of
let env = EvalEnv (leStatic lenv) (leTypes lenv)
xs <- evalExpr sym env expr
let vs i = case xs of
VWord _ w -> VBit <$> indexWordValue sym w i
VWord w -> VBit <$> indexWordValue sym w i
VSeq _ xs' -> lookupSeqMap xs' i
VStream xs' -> lookupSeqMap xs' i
_ -> evalPanic "evalMatch" ["Not a list value"]
Expand Down
28 changes: 14 additions & 14 deletions src/Cryptol/Eval/Concrete.hs
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ toExpr prims t0 v0 = findOne (go t0 v0)
(TVSeq _ b, VSeq n svs) ->
do ses <- traverse (go b) =<< lift (sequence (enumerateSeqMap n svs))
pure $ EList ses (tValTy b)
(TVSeq n TVBit, VWord _ wval) ->
(TVSeq n TVBit, VWord wval) ->
do BV _ v <- lift (asWordVal Concrete wval)
pure $ ETApp (ETApp (prim "number") (tNum v)) (tWord (tNum n))

Expand Down Expand Up @@ -206,7 +206,7 @@ primTable getEOpts = let sym = Concrete in
F2.pmult (fromInteger (u+1)) x y
else
F2.pmult (fromInteger (v+1)) y x
in return . VWord (1+u+v) . wordVal . mkBv (1+u+v) $! z)
in return . VWord . wordVal . mkBv (1+u+v) $! z)

, ("pmod",
PFinPoly \_u ->
Expand All @@ -215,7 +215,7 @@ primTable getEOpts = let sym = Concrete in
PWordFun \(BV _ m) ->
PPrim
do assertSideCondition sym (m /= 0) DivideByZero
return . VWord v . wordVal . mkBv v $! F2.pmod (fromInteger w) x m)
return . VWord . wordVal . mkBv v $! F2.pmod (fromInteger w) x m)

, ("pdiv",
PFinPoly \_u ->
Expand All @@ -224,7 +224,7 @@ primTable getEOpts = let sym = Concrete in
PWordFun \(BV _ m) ->
PPrim
do assertSideCondition sym (m /= 0) DivideByZero
return . VWord w . wordVal . mkBv w $! F2.pdiv (fromInteger w) x m)
return . VWord . wordVal . mkBv w $! F2.pdiv (fromInteger w) x m)
]


Expand Down Expand Up @@ -297,7 +297,7 @@ suiteBPrims = Map.fromList $ map (\(n, v) -> (suiteBPrim n, v))
foldM (\st blk -> seq st (SHA.processSHA256Block st <$> (toSHA256Block =<< blk)))
SHA.initialSHA224State blks
let f :: Word32 -> Eval Value
f = pure . VWord 32 . wordVal . BV 32 . toInteger
f = pure . VWord . wordVal . BV 32 . toInteger
zs = finiteSeqMap Concrete (map f [w0,w1,w2,w3,w4,w5,w6])
seq zs (pure (VSeq 7 zs)))

Expand All @@ -310,7 +310,7 @@ suiteBPrims = Map.fromList $ map (\(n, v) -> (suiteBPrim n, v))
foldM (\st blk -> seq st (SHA.processSHA256Block st <$> (toSHA256Block =<< blk)))
SHA.initialSHA256State blks
let f :: Word32 -> Eval Value
f = pure . VWord 32 . wordVal . BV 32 . toInteger
f = pure . VWord . wordVal . BV 32 . toInteger
zs = finiteSeqMap Concrete (map f [w0,w1,w2,w3,w4,w5,w6,w7])
seq zs (pure (VSeq 8 zs)))

Expand All @@ -323,7 +323,7 @@ suiteBPrims = Map.fromList $ map (\(n, v) -> (suiteBPrim n, v))
foldM (\st blk -> seq st (SHA.processSHA512Block st <$> (toSHA512Block =<< blk)))
SHA.initialSHA384State blks
let f :: Word64 -> Eval Value
f = pure . VWord 64 . wordVal . BV 64 . toInteger
f = pure . VWord . wordVal . BV 64 . toInteger
zs = finiteSeqMap Concrete (map f [w0,w1,w2,w3,w4,w5])
seq zs (pure (VSeq 6 zs)))

Expand All @@ -336,7 +336,7 @@ suiteBPrims = Map.fromList $ map (\(n, v) -> (suiteBPrim n, v))
foldM (\st blk -> seq st (SHA.processSHA512Block st <$> (toSHA512Block =<< blk)))
SHA.initialSHA512State blks
let f :: Word64 -> Eval Value
f = pure . VWord 64 . wordVal . BV 64 . toInteger
f = pure . VWord . wordVal . BV 64 . toInteger
zs = finiteSeqMap Concrete (map f [w0,w1,w2,w3,w4,w5,w6,w7])
seq zs (pure (VSeq 8 zs)))

Expand All @@ -348,7 +348,7 @@ suiteBPrims = Map.fromList $ map (\(n, v) -> (suiteBPrim n, v))
let toWord :: Integer -> Eval Word32
toWord i = fromInteger. bvVal <$> (fromVWord Concrete "AESInfKeyExpand" =<< lookupSeqMap ss i)
let fromWord :: Word32 -> Eval Value
fromWord = pure . VWord 32 . wordVal . BV 32 . toInteger
fromWord = pure . VWord . wordVal . BV 32 . toInteger
kws <- mapM toWord [0 .. k-1]
let ws = AES.keyExpansionWords k kws
let len = 4*(k+7)
Expand All @@ -361,7 +361,7 @@ suiteBPrims = Map.fromList $ map (\(n, v) -> (suiteBPrim n, v))
let toWord :: Integer -> Eval Word32
toWord i = fromInteger. bvVal <$> (fromVWord Concrete "AESInvMixColumns" =<< lookupSeqMap ss i)
let fromWord :: Word32 -> Eval Value
fromWord = pure . VWord 32 . wordVal . BV 32 . toInteger
fromWord = pure . VWord . wordVal . BV 32 . toInteger
ws <- mapM toWord [0,1,2,3]
let ws' = AES.invMixColumns ws
pure . VSeq 4 . finiteSeqMap Concrete . map fromWord $ ws')
Expand All @@ -373,7 +373,7 @@ suiteBPrims = Map.fromList $ map (\(n, v) -> (suiteBPrim n, v))
let toWord :: Integer -> Eval Word32
toWord i = fromInteger. bvVal <$> (fromVWord Concrete "AESEncRound" =<< lookupSeqMap ss i)
let fromWord :: Word32 -> Eval Value
fromWord = pure . VWord 32 . wordVal . BV 32 . toInteger
fromWord = pure . VWord . wordVal . BV 32 . toInteger
ws <- mapM toWord [0,1,2,3]
let ws' = AES.aesRound ws
pure . VSeq 4 . finiteSeqMap Concrete . map fromWord $ ws')
Expand All @@ -385,7 +385,7 @@ suiteBPrims = Map.fromList $ map (\(n, v) -> (suiteBPrim n, v))
let toWord :: Integer -> Eval Word32
toWord i = fromInteger. bvVal <$> (fromVWord Concrete "AESEncFinalRound" =<< lookupSeqMap ss i)
let fromWord :: Word32 -> Eval Value
fromWord = pure . VWord 32 . wordVal . BV 32 . toInteger
fromWord = pure . VWord . wordVal . BV 32 . toInteger
ws <- mapM toWord [0,1,2,3]
let ws' = AES.aesFinalRound ws
pure . VSeq 4 . finiteSeqMap Concrete . map fromWord $ ws')
Expand All @@ -397,7 +397,7 @@ suiteBPrims = Map.fromList $ map (\(n, v) -> (suiteBPrim n, v))
let toWord :: Integer -> Eval Word32
toWord i = fromInteger. bvVal <$> (fromVWord Concrete "AESDecRound" =<< lookupSeqMap ss i)
let fromWord :: Word32 -> Eval Value
fromWord = pure . VWord 32 . wordVal . BV 32 . toInteger
fromWord = pure . VWord . wordVal . BV 32 . toInteger
ws <- mapM toWord [0,1,2,3]
let ws' = AES.aesInvRound ws
pure . VSeq 4 . finiteSeqMap Concrete . map fromWord $ ws')
Expand All @@ -409,7 +409,7 @@ suiteBPrims = Map.fromList $ map (\(n, v) -> (suiteBPrim n, v))
let toWord :: Integer -> Eval Word32
toWord i = fromInteger. bvVal <$> (fromVWord Concrete "AESDecFinalRound" =<< lookupSeqMap ss i)
let fromWord :: Word32 -> Eval Value
fromWord = pure . VWord 32 . wordVal . BV 32 . toInteger
fromWord = pure . VWord . wordVal . BV 32 . toInteger
ws <- mapM toWord [0,1,2,3]
let ws' = AES.aesInvFinalRound ws
pure . VSeq 4 . finiteSeqMap Concrete . map fromWord $ ws')
Expand Down
Loading

0 comments on commit b1bdfd0

Please sign in to comment.