summaryrefslogtreecommitdiff
path: root/KeyRing.hs
diff options
context:
space:
mode:
authorjoe <joe@jerkface.net>2014-05-02 14:31:17 -0400
committerjoe <joe@jerkface.net>2014-05-02 14:31:17 -0400
commit970665ceb98b969b040e9f5400705846d54f77ad (patch)
tree354c328a26448f8ebcfa29298a295bdcdc26be31 /KeyRing.hs
parenta1e0ac16e1ab889fd4a015a0c6914f331f034799 (diff)
Implemented kTransforms
Diffstat (limited to 'KeyRing.hs')
-rw-r--r--KeyRing.hs153
1 files changed, 146 insertions, 7 deletions
diff --git a/KeyRing.hs b/KeyRing.hs
index 2bde001..b1e23b4 100644
--- a/KeyRing.hs
+++ b/KeyRing.hs
@@ -55,6 +55,9 @@ module KeyRing
55 , usageString 55 , usageString
56 , walletImportFormat 56 , walletImportFormat
57 , writePEM 57 , writePEM
58 , getBindings
59 , accBindings
60 , isSubkeySignature
58 ) where 61 ) where
59 62
60import System.Environment 63import System.Environment
@@ -83,16 +86,18 @@ import Data.ASN1.BitArray ( BitArray(..), toBitArray )
83import Data.ASN1.Encoding ( encodeASN1, encodeASN1', decodeASN1, decodeASN1' ) 86import Data.ASN1.Encoding ( encodeASN1, encodeASN1', decodeASN1, decodeASN1' )
84import Data.ASN1.BinaryEncoding ( DER(..) ) 87import Data.ASN1.BinaryEncoding ( DER(..) )
85import Data.Time.Clock.POSIX ( getPOSIXTime, POSIXTime ) 88import Data.Time.Clock.POSIX ( getPOSIXTime, POSIXTime )
89import Data.Bits ( Bits )
90import Data.Text.Encoding ( encodeUtf8 )
86import qualified Data.Map as Map 91import qualified Data.Map as Map
87import qualified Data.ByteString.Lazy as L ( unpack, pack, null, readFile, writeFile 92import qualified Data.ByteString.Lazy as L ( unpack, pack, null, readFile, writeFile
88 , ByteString, toChunks, hGetContents, hPut, concat ) 93 , ByteString, toChunks, hGetContents, hPut, concat, fromChunks )
89import qualified Data.ByteString as S ( ByteString, unpack, splitAt, concat, cons, spanEnd, hGetContents, readFile) 94import qualified Data.ByteString as S ( ByteString, unpack, splitAt, concat, cons, spanEnd, hGetContents, readFile)
90import qualified Crypto.Types.PubKey.ECC as ECC 95import qualified Crypto.Types.PubKey.ECC as ECC
91import qualified Codec.Binary.Base32 as Base32 96import qualified Codec.Binary.Base32 as Base32
92import qualified Codec.Binary.Base64 as Base64 97import qualified Codec.Binary.Base64 as Base64
93import qualified Crypto.Hash.SHA1 as SHA1 98import qualified Crypto.Hash.SHA1 as SHA1
94import qualified Data.Text as T ( Text, unpack, pack, 99import qualified Data.Text as T ( Text, unpack, pack,
95 strip, reverse, drop, break, dropAround ) 100 strip, reverse, drop, break, dropAround, length )
96import qualified System.Posix.Types as Posix 101import qualified System.Posix.Types as Posix
97import System.Posix.Files ( modificationTime, getFileStatus, getFdStatus 102import System.Posix.Files ( modificationTime, getFileStatus, getFdStatus
98 , setFileCreationMask, setFileTimes ) 103 , setFileCreationMask, setFileTimes )
@@ -199,7 +204,7 @@ data StreamInfo = StreamInfo
199 , typ :: FileType 204 , typ :: FileType
200 , fill :: KeyFilter 205 , fill :: KeyFilter
201 , spill :: KeyFilter -- ^ Currently respected for PEMFile and KeyRingFile. 206 , spill :: KeyFilter -- ^ Currently respected for PEMFile and KeyRingFile.
202 -- TODO: WalletFile and Hosts 207 -- (TODO: WalletFile and Hosts)
203 -- Note that this is currently treated as a boolean 208 -- Note that this is currently treated as a boolean
204 -- flag. KF_None means the file is not spillable 209 -- flag. KF_None means the file is not spillable
205 -- and anything else means that it is. 210 -- and anything else means that it is.
@@ -262,14 +267,14 @@ data PassphraseSpec = PassphraseSpec
262 } 267 }
263 268
264data Transform = Autosign 269data Transform = Autosign
270 deriving (Eq,Ord)
265 271
266data KeyRingOperation = KeyRingOperation 272data KeyRingOperation = KeyRingOperation
267 { kFiles :: Map.Map InputFile StreamInfo 273 { kFiles :: Map.Map InputFile StreamInfo
268 , kPassphrases :: [PassphraseSpec] 274 , kPassphrases :: [PassphraseSpec]
269 , kTransform :: [Transform] 275 , kTransform :: [Transform]
270 -- ^ TODO: this is currently ignored
271 , kManip :: KeyRingRuntime -> KeyData -> [PacketUpdate]--[KeyRingAddress PacketUpdate] 276 , kManip :: KeyRingRuntime -> KeyData -> [PacketUpdate]--[KeyRingAddress PacketUpdate]
272 -- ^ TODO: this should be obsoleted by kTransform 277 -- ^ TODO: this is deprecated in favor of kTransform (remove it)
273 , homeSpec :: Maybe String 278 , homeSpec :: Maybe String
274 } 279 }
275 280
@@ -1725,10 +1730,11 @@ performManipulations ::
1725 -> KeyRingOperation 1730 -> KeyRingOperation
1726 -> KeyRingRuntime 1731 -> KeyRingRuntime
1727 -> Maybe MappedPacket 1732 -> Maybe MappedPacket
1733 -> (KeyRingRuntime -> KeyData -> [PacketUpdate])
1728 -> IO (KikiCondition (KeyRingRuntime,[(FilePath,KikiReportAction)])) 1734 -> IO (KikiCondition (KeyRingRuntime,[(FilePath,KikiReportAction)]))
1729performManipulations doDecrypt operation rt wk = do 1735performManipulations doDecrypt operation rt wk manip = do
1730 let db = rtKeyDB rt 1736 let db = rtKeyDB rt
1731 performAll kd = foldM perform (KikiSuccess kd) $ kManip operation rt kd 1737 performAll kd = foldM perform (KikiSuccess kd) $ manip rt kd
1732 r <- Traversable.mapM performAll db 1738 r <- Traversable.mapM performAll db
1733 try (sequenceA r) $ \db -> do 1739 try (sequenceA r) $ \db -> do
1734 return $ KikiSuccess (rt { rtKeyDB = db },[]) 1740 return $ KikiSuccess (rt { rtKeyDB = db },[])
@@ -1849,6 +1855,138 @@ interpretManip kd (KeyRingAddress kk sk (InducerSignature ps)) = error "todo"
1849interpretManip kd manip = return kd 1855interpretManip kd manip = return kd
1850-} 1856-}
1851 1857
1858combineTransforms :: KeyRingOperation -> KeyRingRuntime -> KeyData -> [PacketUpdate]
1859combineTransforms operation rt kd = updates
1860 where
1861 updates = kManip operation rt kd
1862 ++ concatMap (\t -> resolveTransform t rt kd) sanitized
1863 sanitized = group (sort (kTransform operation)) >>= take 1
1864
1865isSubkeySignature (SubkeySignature {}) = True
1866isSubkeySignature _ = False
1867
1868-- Returned data is simmilar to getBindings but the Word8 codes
1869-- are ORed together.
1870accBindings ::
1871 Bits t =>
1872 [(t, (Packet, Packet), [a], [a1], [a2])]
1873 -> [(t, (Packet, Packet), [a], [a1], [a2])]
1874accBindings bs = as
1875 where
1876 gs = groupBy samePair . sortBy (comparing bindingPair) $ bs
1877 as = map (foldl1 combine) gs
1878 bindingPair (_,p,_,_,_) = pub2 p
1879 where
1880 pub2 (a,b) = (pub a, pub b)
1881 pub a = fingerprint_material a
1882 samePair a b = bindingPair a == bindingPair b
1883 combine (ac,p,akind,ahashed,aclaimaints)
1884 (bc,_,bkind,bhashed,bclaimaints)
1885 = (ac .|. bc,p,akind++bkind,ahashed++bhashed,aclaimaints++bclaimaints)
1886
1887
1888
1889verifyBindings keys nonkeys = (top ++ filter isSubkeySignature embedded,othersigs)
1890 where
1891 verified = do
1892 sig <- signatures (Message nonkeys)
1893 let v = verify (Message keys) sig
1894 guard (not . null $ signatures_over v)
1895 return v
1896 (top,othersigs) = partition isSubkeySignature verified
1897 embedded = do
1898 sub <- top
1899 let sigover = signatures_over sub
1900 unhashed = sigover >>= unhashed_subpackets
1901 subsigs = mapMaybe backsig unhashed
1902 -- This should consist only of 0x19 values
1903 -- subtypes = map signature_type subsigs
1904 -- trace ("subtypes = "++show subtypes) (return ())
1905 -- trace ("issuers: "++show (map signature_issuer subsigs)) (return ())
1906 sig <- signatures (Message ([topkey sub,subkey sub]++subsigs))
1907 let v = verify (Message [subkey sub]) sig
1908 guard (not . null $ signatures_over v)
1909 return v
1910
1911smallpr k = drop 24 $ fingerprint k
1912
1913disjoint_fp ks = {- concatMap group2 $ -} transpose grouped
1914 where
1915 grouped = groupBy samepr . sortBy (comparing smallpr) $ ks
1916 samepr a b = smallpr a == smallpr b
1917
1918 {-
1919 -- useful for testing
1920 group2 :: [a] -> [[a]]
1921 group2 (x:y:ys) = [x,y]:group2 ys
1922 group2 [x] = [[x]]
1923 group2 [] = []
1924 -}
1925
1926
1927getBindings ::
1928 [Packet]
1929 ->
1930 ( [([Packet],[SignatureOver])] -- ^ other signatures with key sets
1931 -- that were used for the verifications
1932 , [(Word8,
1933 (Packet, Packet), -- (topkey,subkey)
1934 [String], -- usage flags
1935 [SignatureSubpacket], -- hashed data
1936 [Packet])] -- ^ binding signatures
1937 )
1938getBindings pkts = (sigs,bindings)
1939 where
1940 (sigs,concat->bindings) = unzip $ do
1941 let (keys,_) = partition isKey pkts
1942 keys <- disjoint_fp keys
1943 let (bs,sigs) = verifyBindings keys pkts
1944 return . ((keys,sigs),) $ do
1945 b <- bs -- trace ("sigs = "++show (map (map signature_issuer . signatures_over) sigs)) bs
1946 i <- map signature_issuer (signatures_over b)
1947 i <- maybeToList i
1948 who <- maybeToList $ find_key fingerprint (Message keys) i
1949 let (code,claimants) =
1950 case () of
1951 _ | who == topkey b -> (1,[])
1952 _ | who == subkey b -> (2,[])
1953 _ -> (0,[who])
1954 let hashed = signatures_over b >>= hashed_subpackets
1955 kind = guard (code==1) >> hashed >>= maybeToList . usage
1956 return (code,(topkey b,subkey b), kind, hashed,claimants)
1957
1958resolveTransform Autosign rt kd@(KeyData k ksigs umap submap) = ops
1959 where
1960 ops = map (\u -> InducerSignature u []) us
1961 us = filter torStyle $ Map.keys umap
1962 torStyle str = and [ uid_topdomain parsed == "onion"
1963 , uid_realname parsed `elem` ["","Anonymous"]
1964 , uid_user parsed == "root"
1965 , fmap (match . fst) (lookup (packet k) torbindings)
1966 == Just True ]
1967 where parsed = parseUID str
1968 match = (==subdom) . take (fromIntegral len)
1969 subdom0 = L.fromChunks [encodeUtf8 (uid_subdomain parsed)]
1970 subdom = Char8.unpack subdom0
1971 len = T.length (uid_subdomain parsed)
1972 torbindings = getTorKeys (map packet $ flattenTop "" True kd)
1973 getTorKeys pub = do
1974 xs <- groupBindings pub
1975 (_,(top,sub),us,_,_) <- xs
1976 guard ("tor" `elem` us)
1977 let torhash = fromMaybe "" $ derToBase32 <$> derRSA sub
1978 return (top,(torhash,sub))
1979
1980 groupBindings pub = gs
1981 where (_,bindings) = getBindings pub
1982 bindings' = accBindings bindings
1983 code (c,(m,s),_,_,_) = (fingerprint_material m,-c)
1984 ownerkey (_,(a,_),_,_,_) = a
1985 sameMaster (ownerkey->a) (ownerkey->b)
1986 = fingerprint_material a==fingerprint_material b
1987 gs = groupBy sameMaster (sortBy (comparing code) bindings')
1988
1989
1852runKeyRing :: KeyRingOperation -> IO (KikiResult KeyRingRuntime) 1990runKeyRing :: KeyRingOperation -> IO (KikiResult KeyRingRuntime)
1853runKeyRing operation = do 1991runKeyRing operation = do
1854 homedir <- getHomeDir (homeSpec operation) 1992 homedir <- getHomeDir (homeSpec operation)
@@ -1902,6 +2040,7 @@ runKeyRing operation = do
1902 operation 2040 operation
1903 rt 2041 rt
1904 wk 2042 wk
2043 (combineTransforms operation)
1905 try' r $ \(rt,report_manips) -> do 2044 try' r $ \(rt,report_manips) -> do
1906 2045
1907 r <- writeWalletKeys operation (rtKeyDB rt) (fmap packet wk) 2046 r <- writeWalletKeys operation (rtKeyDB rt) (fmap packet wk)