move cryptographicallySecure into Backend type

This is groundwork for external backends, but also makes sense to keep
this information with the rest of a Backend's implementation.

Also, removed isVerifiable. I noticed that the same information is
encoded by whether a Backend implements verifyKeyContent or not.
This commit is contained in:
Joey Hess 2020-07-20 12:08:37 -04:00
parent 4be5567372
commit 172743728e
No known key found for this signature in database
GPG key ID: DB12DB0FF05F8F38
10 changed files with 38 additions and 41 deletions

View file

@ -336,7 +336,7 @@ getViaTmpFromDisk rsp v key action = checkallowed $ do
checkallowed a = case rsp of checkallowed a = case rsp of
RetrievalAllKeysSecure -> a RetrievalAllKeysSecure -> a
RetrievalVerifiableKeysSecure RetrievalVerifiableKeysSecure
| isVerifiable (fromKey keyVariety key) -> a | Backend.isVerifiable key -> a
| otherwise -> ifM (annexAllowUnverifiedDownloads <$> Annex.getGitConfig) | otherwise -> ifM (annexAllowUnverifiedDownloads <$> Annex.getGitConfig)
( a ( a
, warnUnverifiableInsecure key >> return False , warnUnverifiableInsecure key >> return False
@ -360,7 +360,7 @@ verifyKeyContent :: RetrievalSecurityPolicy -> VerifyConfig -> Verification -> K
verifyKeyContent rsp v verification k f = case (rsp, verification) of verifyKeyContent rsp v verification k f = case (rsp, verification) of
(_, Verified) -> return True (_, Verified) -> return True
(RetrievalVerifiableKeysSecure, _) (RetrievalVerifiableKeysSecure, _)
| isVerifiable (fromKey keyVariety k) -> verify | Backend.isVerifiable k -> verify
| otherwise -> ifM (annexAllowUnverifiedDownloads <$> Annex.getGitConfig) | otherwise -> ifM (annexAllowUnverifiedDownloads <$> Annex.getGitConfig)
( verify ( verify
, warnUnverifiableInsecure k >> return False , warnUnverifiableInsecure k >> return False
@ -499,7 +499,7 @@ moveAnnex key src = ifM (checkSecureHashes' key)
checkSecureHashes :: Key -> Annex (Maybe String) checkSecureHashes :: Key -> Annex (Maybe String)
checkSecureHashes key checkSecureHashes key
| cryptographicallySecure (fromKey keyVariety key) = return Nothing | Backend.isCryptographicallySecure key = return Nothing
| otherwise = ifM (annexSecureHashesOnly <$> Annex.getGitConfig) | otherwise = ifM (annexSecureHashesOnly <$> Annex.getGitConfig)
( return $ Just $ "annex.securehashesonly blocked adding " ++ decodeBS (formatKeyVariety (fromKey keyVariety key)) ++ " key" ( return $ Just $ "annex.securehashesonly blocked adding " ++ decodeBS (formatKeyVariety (fromKey keyVariety key)) ++ " key"
, return Nothing , return Nothing

View file

@ -33,6 +33,7 @@ import qualified Types.Remote as Remote
import Types.Concurrency import Types.Concurrency
import Types.WorkerPool import Types.WorkerPool
import Annex.WorkerPool import Annex.WorkerPool
import Backend (isCryptographicallySecure)
import Control.Concurrent import Control.Concurrent
import qualified Data.Map.Strict as M import qualified Data.Map.Strict as M
@ -177,7 +178,7 @@ runTransfer' ignorelock t afile retrydecider transferaction = enteringStage Tran
-} -}
checkSecureHashes :: Observable v => Transfer -> Annex v -> Annex v checkSecureHashes :: Observable v => Transfer -> Annex v -> Annex v
checkSecureHashes t a checkSecureHashes t a
| cryptographicallySecure variety = a | isCryptographicallySecure (transferKey t) = a
| otherwise = ifM (annexSecureHashesOnly <$> Annex.getGitConfig) | otherwise = ifM (annexSecureHashesOnly <$> Annex.getGitConfig)
( do ( do
warning $ "annex.securehashesonly blocked transfer of " ++ decodeBS (formatKeyVariety variety) ++ " key" warning $ "annex.securehashesonly blocked transfer of " ++ decodeBS (formatKeyVariety variety) ++ " key"

View file

@ -1,6 +1,6 @@
{- git-annex key/value backends {- git-annex key/value backends
- -
- Copyright 2010-2017 Joey Hess <id@joeyh.name> - Copyright 2010-2020 Joey Hess <id@joeyh.name>
- -
- Licensed under the GNU AGPL version 3 or higher. - Licensed under the GNU AGPL version 3 or higher.
-} -}
@ -14,6 +14,8 @@ module Backend (
lookupBackendVariety, lookupBackendVariety,
maybeLookupBackendVariety, maybeLookupBackendVariety,
isStableKey, isStableKey,
isCryptographicallySecure,
isVerifiable,
) where ) where
import Annex.Common import Annex.Common
@ -101,3 +103,11 @@ varietyMap = M.fromList $ zip (map B.backendVariety list) list
isStableKey :: Key -> Bool isStableKey :: Key -> Bool
isStableKey k = maybe False (`B.isStableKey` k) isStableKey k = maybe False (`B.isStableKey` k)
(maybeLookupBackendVariety (fromKey keyVariety k)) (maybeLookupBackendVariety (fromKey keyVariety k))
isCryptographicallySecure :: Key -> Bool
isCryptographicallySecure k = maybe False (`B.isCryptographicallySecure` k)
(maybeLookupBackendVariety (fromKey keyVariety k))
isVerifiable :: Key -> Bool
isVerifiable k = maybe False (isJust . B.verifyKeyContent)
(maybeLookupBackendVariety (fromKey keyVariety k))

View file

@ -41,6 +41,17 @@ data Hash
| Blake2sHash HashSize | Blake2sHash HashSize
| Blake2spHash HashSize | Blake2spHash HashSize
cryptographicallySecure :: Hash -> Bool
cryptographicallySecure (SHA2Hash _) = True
cryptographicallySecure (SHA3Hash _) = True
cryptographicallySecure (SkeinHash _) = True
cryptographicallySecure (Blake2bHash _) = True
cryptographicallySecure (Blake2bpHash _) = True
cryptographicallySecure (Blake2sHash _) = True
cryptographicallySecure (Blake2spHash _) = True
cryptographicallySecure SHA1Hash = False
cryptographicallySecure MD5Hash = False
{- Order is slightly significant; want SHA256 first, and more general {- Order is slightly significant; want SHA256 first, and more general
- sizes earlier. -} - sizes earlier. -}
hashes :: [Hash] hashes :: [Hash]
@ -68,6 +79,7 @@ genBackend hash = Backend
, canUpgradeKey = Just needsUpgrade , canUpgradeKey = Just needsUpgrade
, fastMigrate = Just trivialMigrate , fastMigrate = Just trivialMigrate
, isStableKey = const True , isStableKey = const True
, isCryptographicallySecure = const (cryptographicallySecure hash)
} }
genBackendE :: Hash -> Backend genBackendE :: Hash -> Backend

View file

@ -28,6 +28,7 @@ backend = Backend
-- The content of an url can change at any time, so URL keys are -- The content of an url can change at any time, so URL keys are
-- not stable. -- not stable.
, isStableKey = const False , isStableKey = const False
, isCryptographicallySecure = const False
} }
{- Every unique url has a corresponding key. -} {- Every unique url has a corresponding key. -}

View file

@ -29,6 +29,7 @@ backend = Backend
, canUpgradeKey = Just needsUpgrade , canUpgradeKey = Just needsUpgrade
, fastMigrate = Just removeProblemChars , fastMigrate = Just removeProblemChars
, isStableKey = const True , isStableKey = const True
, isCryptographicallySecure = const False
} }
{- The key includes the file size, modification time, and the {- The key includes the file size, modification time, and the

View file

@ -261,7 +261,7 @@ verifyLocationLog key keystatus ai = do
- insecure hash is present. This should only be able to happen - insecure hash is present. This should only be able to happen
- if the repository already contained the content before the - if the repository already contained the content before the
- config was set. -} - config was set. -}
when (present && not (cryptographicallySecure (fromKey keyVariety key))) $ when (present && not (Backend.isCryptographicallySecure key)) $
whenM (annexSecureHashesOnly <$> Annex.getGitConfig) $ whenM (annexSecureHashesOnly <$> Annex.getGitConfig) $
warning $ "** Despite annex.securehashesonly being set, " ++ obj ++ " has content present in the annex using an insecure " ++ decodeBS (formatKeyVariety (fromKey keyVariety key)) ++ " key" warning $ "** Despite annex.securehashesonly being set, " ++ obj ++ " has content present in the annex using an insecure " ++ decodeBS (formatKeyVariety (fromKey keyVariety key)) ++ " key"

View file

@ -34,6 +34,7 @@ import Utility.Glob
import Utility.HumanTime import Utility.HumanTime
import Utility.DataUnits import Utility.DataUnits
import qualified Utility.RawFilePath as R import qualified Utility.RawFilePath as R
import Backend
import Data.Time.Clock.POSIX import Data.Time.Clock.POSIX
import qualified Data.Set as S import qualified Data.Set as S
@ -305,7 +306,7 @@ addSecureHash :: Annex ()
addSecureHash = addLimit $ Right limitSecureHash addSecureHash = addLimit $ Right limitSecureHash
limitSecureHash :: MatchFiles Annex limitSecureHash :: MatchFiles Annex
limitSecureHash _ = checkKey $ pure . cryptographicallySecure . fromKey keyVariety limitSecureHash _ = checkKey $ pure . isCryptographicallySecure
{- Adds a limit to skip files that are too large or too small -} {- Adds a limit to skip files that are too large or too small -}
addLargerThan :: String -> Annex () addLargerThan :: String -> Annex ()

View file

@ -2,7 +2,7 @@
- -
- Most things should not need this, using Types instead - Most things should not need this, using Types instead
- -
- Copyright 2010-2019 Joey Hess <id@joeyh.name> - Copyright 2010-2020 Joey Hess <id@joeyh.name>
- -
- Licensed under the GNU AGPL version 3 or higher. - Licensed under the GNU AGPL version 3 or higher.
-} -}
@ -18,7 +18,8 @@ import Utility.FileSystemEncoding
data BackendA a = Backend data BackendA a = Backend
{ backendVariety :: KeyVariety { backendVariety :: KeyVariety
, getKey :: Maybe (KeySource -> MeterUpdate -> a Key) , getKey :: Maybe (KeySource -> MeterUpdate -> a Key)
-- Verifies the content of a key. -- Verifies the content of a key using a hash. This does not need
-- to be cryptographically secure.
, verifyKeyContent :: Maybe (Key -> FilePath -> a Bool) , verifyKeyContent :: Maybe (Key -> FilePath -> a Bool)
-- Checks if a key can be upgraded to a better form. -- Checks if a key can be upgraded to a better form.
, canUpgradeKey :: Maybe (Key -> Bool) , canUpgradeKey :: Maybe (Key -> Bool)
@ -28,6 +29,8 @@ data BackendA a = Backend
-- Checks if a key is known (or assumed) to always refer to the -- Checks if a key is known (or assumed) to always refer to the
-- same data. -- same data.
, isStableKey :: Key -> Bool , isStableKey :: Key -> Bool
-- Checks if a key is verified using a cryptographically secure hash.
, isCryptographicallySecure :: Key -> Bool
} }
instance Show (BackendA a) where instance Show (BackendA a) where

View file

@ -23,8 +23,6 @@ module Types.Key (
HashSize(..), HashSize(..),
hasExt, hasExt,
sameExceptExt, sameExceptExt,
cryptographicallySecure,
isVerifiable,
formatKeyVariety, formatKeyVariety,
parseKeyVariety, parseKeyVariety,
) where ) where
@ -262,36 +260,6 @@ sameExceptExt (SHA1Key _) (SHA1Key _) = True
sameExceptExt (MD5Key _) (MD5Key _) = True sameExceptExt (MD5Key _) (MD5Key _) = True
sameExceptExt _ _ = False sameExceptExt _ _ = False
{- Is the Key variety cryptographically secure, such that no two differing
- file contents can be mapped to the same Key? -}
cryptographicallySecure :: KeyVariety -> Bool
cryptographicallySecure (SHA2Key _ _) = True
cryptographicallySecure (SHA3Key _ _) = True
cryptographicallySecure (SKEINKey _ _) = True
cryptographicallySecure (Blake2bKey _ _) = True
cryptographicallySecure (Blake2bpKey _ _) = True
cryptographicallySecure (Blake2sKey _ _) = True
cryptographicallySecure (Blake2spKey _ _) = True
cryptographicallySecure _ = False
{- Is the Key variety backed by a hash, which allows verifying content?
- It does not have to be cryptographically secure against eg birthday
- attacks.
-}
isVerifiable :: KeyVariety -> Bool
isVerifiable (SHA2Key _ _) = True
isVerifiable (SHA3Key _ _) = True
isVerifiable (SKEINKey _ _) = True
isVerifiable (Blake2bKey _ _) = True
isVerifiable (Blake2bpKey _ _) = True
isVerifiable (Blake2sKey _ _) = True
isVerifiable (Blake2spKey _ _) = True
isVerifiable (SHA1Key _) = True
isVerifiable (MD5Key _) = True
isVerifiable WORMKey = False
isVerifiable URLKey = False
isVerifiable (OtherKey _) = False
formatKeyVariety :: KeyVariety -> S.ByteString formatKeyVariety :: KeyVariety -> S.ByteString
formatKeyVariety v = case v of formatKeyVariety v = case v of
SHA2Key sz e -> adde e (addsz sz "SHA") SHA2Key sz e -> adde e (addsz sz "SHA")