diff options
author | Stephen Paul Weber <singpolyma@singpolyma.net> | 2013-01-03 13:53:55 -0500 |
---|---|---|
committer | Stephen Paul Weber <singpolyma@singpolyma.net> | 2013-01-03 13:53:55 -0500 |
commit | fc9dd0707c349e8e8e822d8e5a624dd46ac961f2 (patch) | |
tree | 413be0ad73ef8e1d033a6f32a8eb4afe48a8faed | |
parent | 77ee44a5ba50aacc8520b24614bbc044b6cf48f7 (diff) |
Properly verify secret key checksums
-rw-r--r-- | Data/OpenPGP.hs | 25 |
1 files changed, 13 insertions, 12 deletions
diff --git a/Data/OpenPGP.hs b/Data/OpenPGP.hs index 61d6dfd..209d876 100644 --- a/Data/OpenPGP.hs +++ b/Data/OpenPGP.hs | |||
@@ -170,6 +170,10 @@ pad l s = replicate (l - length s) '0' ++ s | |||
170 | padBS :: Int -> B.ByteString -> B.ByteString | 170 | padBS :: Int -> B.ByteString -> B.ByteString |
171 | padBS l s = B.replicate (fromIntegral l - B.length s) 0 `B.append` s | 171 | padBS l s = B.replicate (fromIntegral l - B.length s) 0 `B.append` s |
172 | 172 | ||
173 | checksum :: B.ByteString -> Word16 | ||
174 | checksum = fromIntegral . | ||
175 | B.foldl (\c i -> (c + fromIntegral i) `mod` 65536) (0::Integer) | ||
176 | |||
173 | data Packet = | 177 | data Packet = |
174 | AsymmetricSessionKeyPacket { | 178 | AsymmetricSessionKeyPacket { |
175 | version::Word8, | 179 | version::Word8, |
@@ -454,15 +458,11 @@ put_packet (SecretKeyPacket { version = version, timestamp = timestamp, | |||
454 | [encode symmetric_algorithm] | 458 | [encode symmetric_algorithm] |
455 | ) ++ | 459 | ) ++ |
456 | (if symmetric_algorithm /= Unencrypted then | 460 | (if symmetric_algorithm /= Unencrypted then |
461 | -- For V3 keys, the "encrypted data" has an unencrypted checksum | ||
462 | -- of the unencrypted MPIs on the end | ||
457 | [encrypted_data] | 463 | [encrypted_data] |
458 | else s ++ | 464 | else s ++ |
459 | -- TODO: Checksum is part of encrypted_data for V4 ONLY | 465 | [encode $ checksum $ B.concat s]), |
460 | if s2k_useage == 254 then | ||
461 | [B.replicate 20 0] -- TODO SHA1 Checksum | ||
462 | else | ||
463 | [encode (fromIntegral $ | ||
464 | B.foldl (\c i -> (c + fromIntegral i) `mod` 65536) | ||
465 | (0::Integer) (B.concat s) :: Word16)]), | ||
466 | if is_subkey then 7 else 5) | 466 | if is_subkey then 7 else 5) |
467 | where | 467 | where |
468 | p = fst (put_packet $ | 468 | p = fst (put_packet $ |
@@ -610,12 +610,13 @@ parse_packet 5 = do | |||
610 | encrypted <- getRemainingByteString; | 610 | encrypted <- getRemainingByteString; |
611 | return (k s2k symmetric_algorithm encrypted False) | 611 | return (k s2k symmetric_algorithm encrypted False) |
612 | } else do | 612 | } else do |
613 | key <- foldM (\m f -> do | 613 | skey <- foldM (\m f -> do |
614 | mpi <- get :: Get MPI | 614 | mpi <- get :: Get MPI |
615 | return $ (f,mpi):m) key (secret_key_fields algorithm) | 615 | return $ (f,mpi):m) [] (secret_key_fields algorithm) |
616 | checksum <- getRemainingByteString | 616 | chk <- get |
617 | -- TODO: verify checksum | 617 | when (checksum (B.concat $ map (encode . snd) skey) /= chk) $ |
618 | return ((k s2k symmetric_algorithm B.empty False) {key = key}) | 618 | fail "Checksum verification failed for unencrypted secret key" |
619 | return ((k s2k symmetric_algorithm B.empty False) {key = key ++ skey}) | ||
619 | -- PublicKeyPacket, http://tools.ietf.org/html/rfc4880#section-5.5.2 | 620 | -- PublicKeyPacket, http://tools.ietf.org/html/rfc4880#section-5.5.2 |
620 | parse_packet 6 = do | 621 | parse_packet 6 = do |
621 | version <- get :: Get Word8 | 622 | version <- get :: Get Word8 |