summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Arbitrary.patch8
-rw-r--r--Data/OpenPGP.hs86
-rw-r--r--Makefile2
-rw-r--r--tests/suite.hs5
4 files changed, 57 insertions, 44 deletions
diff --git a/Arbitrary.patch b/Arbitrary.patch
index 641609f..2d14399 100644
--- a/Arbitrary.patch
+++ b/Arbitrary.patch
@@ -24,6 +24,14 @@
24 2 -> do x1 <- arbitrary 24 2 -> do x1 <- arbitrary
25 x2 <- arbitrary 25 x2 <- arbitrary
26 x3 <- arbitrary 26 x3 <- arbitrary
27@@ -88,5 +93,5 @@
28 x2 <- arbitrary
29- x3 <- arbitrary
30+ x3 <- fmap decode_s2k_count arbitrary
31 return (IteratedSaltedS2K x1 x2 x3)
32- 3 -> do x1 <- arbitrary
33+ 3 -> do x1 <- suchThat arbitrary (`notElem` [0,1,3])
34 x2 <- arbitrary
27@@ -73,7 +72,7 @@ 35@@ -73,7 +72,7 @@
28 4 -> return SHA384 36 4 -> return SHA384
29 5 -> return SHA512 37 5 -> return SHA512
diff --git a/Data/OpenPGP.hs b/Data/OpenPGP.hs
index 4dad404..5e62d1a 100644
--- a/Data/OpenPGP.hs
+++ b/Data/OpenPGP.hs
@@ -34,14 +34,11 @@ module Data.OpenPGP (
34 message, 34 message,
35 nested, 35 nested,
36 private_hash, 36 private_hash,
37 s2k_count,
38 s2k_hash_algorithm,
39 s2k_salt,
40 s2k_type,
41 s2k_useage, 37 s2k_useage,
38 s2k,
42 signature, 39 signature,
43 signature_type, 40 signature_type,
44 symmetric_type, 41 symmetric_algorithm,
45 timestamp, 42 timestamp,
46 trailer, 43 trailer,
47 unhashed_subpackets, 44 unhashed_subpackets,
@@ -51,6 +48,7 @@ module Data.OpenPGP (
51 signaturePacket, 48 signaturePacket,
52 Message(..), 49 Message(..),
53 SignatureSubpacket(..), 50 SignatureSubpacket(..),
51 S2K(..),
54 HashAlgorithm(..), 52 HashAlgorithm(..),
55 KeyAlgorithm(..), 53 KeyAlgorithm(..),
56 SymmetricAlgorithm(..), 54 SymmetricAlgorithm(..),
@@ -211,12 +209,9 @@ data Packet =
211 timestamp::Word32, 209 timestamp::Word32,
212 key_algorithm::KeyAlgorithm, 210 key_algorithm::KeyAlgorithm,
213 key::[(Char,MPI)], 211 key::[(Char,MPI)],
214 s2k_useage::Word8, -- ^ determines if the 'Maybe's are 'Just' or 'Nothing' 212 s2k_useage::Word8,
215 symmetric_type::Maybe Word8, 213 s2k::Maybe S2K,
216 s2k_type::Maybe Word8, 214 symmetric_algorithm::SymmetricAlgorithm,
217 s2k_hash_algorithm::Maybe HashAlgorithm,
218 s2k_salt::Maybe Word64,
219 s2k_count::Maybe Word32,
220 encrypted_data::B.ByteString, 215 encrypted_data::B.ByteString,
221 private_hash::Maybe B.ByteString, -- ^ the hash may be in the encrypted data 216 private_hash::Maybe B.ByteString, -- ^ the hash may be in the encrypted data
222 is_subkey::Bool 217 is_subkey::Bool
@@ -436,23 +431,16 @@ put_packet (OnePassSignaturePacket { version = version,
436 ], 4) 431 ], 4)
437put_packet (SecretKeyPacket { version = version, timestamp = timestamp, 432put_packet (SecretKeyPacket { version = version, timestamp = timestamp,
438 key_algorithm = algorithm, key = key, 433 key_algorithm = algorithm, key = key,
439 s2k_useage = s2k_useage, 434 s2k_useage = s2k_useage, s2k = s2k,
440 symmetric_type = symmetric_type, 435 symmetric_algorithm = symmetric_algorithm,
441 s2k_type = s2k_type,
442 s2k_hash_algorithm = s2k_hash_algo,
443 s2k_salt = s2k_salt,
444 s2k_count = s2k_count,
445 encrypted_data = encrypted_data, 436 encrypted_data = encrypted_data,
446 is_subkey = is_subkey }) = 437 is_subkey = is_subkey }) =
447 (B.concat $ [p, encode s2k_useage] ++ 438 (B.concat $ p :
448 (if s2k_useage `elem` [255, 254] then 439 (case s2k of
449 [encode $ fromJust symmetric_type, encode s2k_t, 440 Just s2k -> [encode s2k_useage, encode symmetric_algorithm, encode s2k]
450 encode $ fromJust s2k_hash_algo] ++ 441 Nothing -> [encode symmetric_algorithm]
451 (if s2k_t `elem` [1,3] then [encode $ fromJust s2k_salt] else []) ++ 442 ) ++
452 if s2k_t == 3 then 443 (if symmetric_algorithm /= Unencrypted then
453 [encode $ encode_s2k_count $ fromJust s2k_count] else []
454 else []) ++
455 (if s2k_useage > 0 then
456 [encrypted_data] 444 [encrypted_data]
457 else s ++ 445 else s ++
458 -- XXX: Checksum is part of encrypted_data for V4 ONLY 446 -- XXX: Checksum is part of encrypted_data for V4 ONLY
@@ -464,7 +452,6 @@ put_packet (SecretKeyPacket { version = version, timestamp = timestamp,
464 (0::Integer) (B.concat s) :: Word16)]), 452 (0::Integer) (B.concat s) :: Word16)]),
465 if is_subkey then 7 else 5) 453 if is_subkey then 7 else 5)
466 where 454 where
467 (Just s2k_t) = s2k_type
468 p = fst (put_packet $ 455 p = fst (put_packet $
469 PublicKeyPacket version timestamp algorithm key False Nothing) 456 PublicKeyPacket version timestamp algorithm key False Nothing)
470 s = map (encode . (key !)) (secret_key_fields algorithm) 457 s = map (encode . (key !)) (secret_key_fields algorithm)
@@ -592,31 +579,22 @@ parse_packet 5 = do
592 }) <- parse_packet 6 579 }) <- parse_packet 6
593 s2k_useage <- get :: Get Word8 580 s2k_useage <- get :: Get Word8
594 let k = SecretKeyPacket version timestamp algorithm key s2k_useage 581 let k = SecretKeyPacket version timestamp algorithm key s2k_useage
595 k' <- case s2k_useage of 582 (symmetric_algorithm, s2k) <- case () of
596 _ | s2k_useage `elem` [255, 254] -> do 583 _ | s2k_useage `elem` [255, 254] -> (,) <$> get <*> fmap Just get
597 symmetric_type <- get
598 s2k_type <- get
599 s2k_hash_algorithm <- get
600 s2k_salt <- if s2k_type `elem` [1, 3] then get
601 else return undefined
602 s2k_count <- if s2k_type == 3 then fmap decode_s2k_count get else
603 return undefined
604 return (k (Just symmetric_type) (Just s2k_type)
605 (Just s2k_hash_algorithm) (Just s2k_salt) (Just s2k_count))
606 _ | s2k_useage > 0 -> 584 _ | s2k_useage > 0 ->
607 -- s2k_useage is symmetric_type in this case 585 -- s2k_useage is symmetric_type in this case
608 return (k (Just s2k_useage) Nothing Nothing Nothing Nothing) 586 return (decode $ encode s2k_useage, Just $ SimpleS2K MD5)
609 _ -> 587 _ ->
610 return (k Nothing Nothing Nothing Nothing Nothing) 588 return (Unencrypted, Nothing)
611 if s2k_useage > 0 then do { 589 if symmetric_algorithm /= Unencrypted then do {
612 encrypted <- getRemainingByteString; 590 encrypted <- getRemainingByteString;
613 return (k' encrypted Nothing False) 591 return (k s2k symmetric_algorithm encrypted Nothing False)
614 } else do 592 } else do
615 key <- foldM (\m f -> do 593 key <- foldM (\m f -> do
616 mpi <- get :: Get MPI 594 mpi <- get :: Get MPI
617 return $ (f,mpi):m) key (secret_key_fields algorithm) 595 return $ (f,mpi):m) key (secret_key_fields algorithm)
618 private_hash <- getRemainingByteString 596 private_hash <- getRemainingByteString
619 return ((k' B.empty (Just private_hash) False) {key = key}) 597 return ((k s2k symmetric_algorithm B.empty (Just private_hash) False) {key = key})
620-- PublicKeyPacket, http://tools.ietf.org/html/rfc4880#section-5.5.2 598-- PublicKeyPacket, http://tools.ietf.org/html/rfc4880#section-5.5.2
621parse_packet 6 = do 599parse_packet 6 = do
622 version <- get :: Get Word8 600 version <- get :: Get Word8
@@ -718,6 +696,28 @@ enum_to_word8 = fromIntegral . fromEnum
718enum_from_word8 :: (Enum a) => Word8 -> a 696enum_from_word8 :: (Enum a) => Word8 -> a
719enum_from_word8 = toEnum . fromIntegral 697enum_from_word8 = toEnum . fromIntegral
720 698
699data S2K =
700 SimpleS2K HashAlgorithm |
701 SaltedS2K HashAlgorithm Word64 |
702 IteratedSaltedS2K HashAlgorithm Word64 Word32 |
703 S2K Word8 B.ByteString
704 deriving (Show, Read, Eq)
705
706instance BINARY_CLASS S2K where
707 put (SimpleS2K halgo) = put (0::Word8) >> put halgo
708 put (SaltedS2K halgo salt) = put (1::Word8) >> put halgo >> put salt
709 put (IteratedSaltedS2K halgo salt count) = put (3::Word8) >> put halgo
710 >> put salt >> put (encode_s2k_count count)
711 put (S2K t body) = put t >> putSomeByteString body
712
713 get = do
714 t <- get :: Get Word8
715 case t of
716 0 -> SimpleS2K <$> get
717 1 -> SaltedS2K <$> get <*> get
718 3 -> IteratedSaltedS2K <$> get <*> get <*> (decode_s2k_count <$> get)
719 _ -> S2K t <$> getRemainingByteString
720
721data HashAlgorithm = MD5 | SHA1 | RIPEMD160 | SHA256 | SHA384 | SHA512 | SHA224 | HashAlgorithm Word8 721data HashAlgorithm = MD5 | SHA1 | RIPEMD160 | SHA256 | SHA384 | SHA512 | SHA224 | HashAlgorithm Word8
722 deriving (Show, Read, Eq) 722 deriving (Show, Read, Eq)
723 723
diff --git a/Makefile b/Makefile
index 35b6523..4f03424 100644
--- a/Makefile
+++ b/Makefile
@@ -23,7 +23,7 @@ tests/suite: tests/suite.hs Data/OpenPGP.hs Data/OpenPGP/Internal.hs Data/OpenPG
23 ghc --make $(GHCFLAGS) -o $@ $^ 23 ghc --make $(GHCFLAGS) -o $@ $^
24 24
25Data/OpenPGP/Arbitrary.hs: Data/OpenPGP.hs Arbitrary.patch 25Data/OpenPGP/Arbitrary.hs: Data/OpenPGP.hs Arbitrary.patch
26 derive -d Arbitrary -m Data.OpenPGP.Arbitrary -iData.OpenPGP -iTest.QuickCheck -iTest.QuickCheck.Instances -iNumeric -iData.Char -iData.Word -o $@ Data/OpenPGP.hs 26 derive -d Arbitrary -m Data.OpenPGP.Arbitrary -iData.OpenPGP -iData.OpenPGP.Internal -iTest.QuickCheck -iTest.QuickCheck.Instances -iNumeric -iData.Char -iData.Word -o $@ Data/OpenPGP.hs
27 patch $@ Arbitrary.patch 27 patch $@ Arbitrary.patch
28 28
29report.html: tests/suite.hs Data/OpenPGP.hs Data/OpenPGP/Internal.hs 29report.html: tests/suite.hs Data/OpenPGP.hs Data/OpenPGP/Internal.hs
diff --git a/tests/suite.hs b/tests/suite.hs
index 3094214..feb5fe6 100644
--- a/tests/suite.hs
+++ b/tests/suite.hs
@@ -44,6 +44,10 @@ prop_MPI_serialization_loop :: OpenPGP.MPI -> Bool
44prop_MPI_serialization_loop mpi = 44prop_MPI_serialization_loop mpi =
45 mpi == decode' (encode mpi) 45 mpi == decode' (encode mpi)
46 46
47prop_S2K_serialization_loop :: OpenPGP.S2K -> Bool
48prop_S2K_serialization_loop s2k =
49 s2k == decode' (encode s2k)
50
47prop_SignatureSubpacket_serialization_loop :: OpenPGP.SignatureSubpacket -> Bool 51prop_SignatureSubpacket_serialization_loop :: OpenPGP.SignatureSubpacket -> Bool
48prop_SignatureSubpacket_serialization_loop packet = 52prop_SignatureSubpacket_serialization_loop packet =
49 packet == decode' (encode packet) 53 packet == decode' (encode packet)
@@ -141,6 +145,7 @@ tests =
141 testCase "uncompressed-ops-dsa-sha384.txt.gpg" (testSerialization "uncompressed-ops-dsa-sha384.txt.gpg"), 145 testCase "uncompressed-ops-dsa-sha384.txt.gpg" (testSerialization "uncompressed-ops-dsa-sha384.txt.gpg"),
142 testCase "uncompressed-ops-rsa.gpg" (testSerialization "uncompressed-ops-rsa.gpg"), 146 testCase "uncompressed-ops-rsa.gpg" (testSerialization "uncompressed-ops-rsa.gpg"),
143 testProperty "MPI encode/decode" prop_MPI_serialization_loop, 147 testProperty "MPI encode/decode" prop_MPI_serialization_loop,
148 testProperty "S2K encode/decode" prop_S2K_serialization_loop,
144 testProperty "SignatureSubpacket encode/decode" prop_SignatureSubpacket_serialization_loop 149 testProperty "SignatureSubpacket encode/decode" prop_SignatureSubpacket_serialization_loop
145 ], 150 ],
146 testGroup "S2K count" [ 151 testGroup "S2K count" [