From a48e9580293785d8f35d85743268d7abff653c64 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Olivier=20Ch=C3=A9ron?= Date: Sun, 2 Jun 2024 17:32:39 +0200 Subject: [PATCH] SHA-3 support in CMS --- src/Crypto/Store/CMS/Algorithms.hs | 64 ++++++++++++++++++++++++++---- tests/CMS/Instances.hs | 15 +++++-- tests/CMS/Tests.hs | 16 +++++--- tests/PKCS12/Instances.hs | 13 ++++++ tests/files/cms-digested-data.pem | 19 +++++++++ tests/files/generate.sh | 2 +- 6 files changed, 110 insertions(+), 19 deletions(-) diff --git a/src/Crypto/Store/CMS/Algorithms.hs b/src/Crypto/Store/CMS/Algorithms.hs index c099d89..f7b89e3 100644 --- a/src/Crypto/Store/CMS/Algorithms.hs +++ b/src/Crypto/Store/CMS/Algorithms.hs @@ -167,6 +167,14 @@ data DigestProxy hashAlg where SHA384 :: DigestProxy Hash.SHA384 -- | SHA-512 SHA512 :: DigestProxy Hash.SHA512 + -- | SHA3-224 + SHA3_224 :: DigestProxy Hash.SHA3_224 + -- | SHA3-256 + SHA3_256 :: DigestProxy Hash.SHA3_256 + -- | SHA3-384 + SHA3_384 :: DigestProxy Hash.SHA3_384 + -- | SHA3-512 + SHA3_512 :: DigestProxy Hash.SHA3_512 -- | SHAKE128 (256 bits) SHAKE128_256 :: DigestProxy (Hash.SHAKE128 256) -- | SHAKE256 (512 bits) @@ -186,6 +194,10 @@ instance Show (DigestProxy hashAlg) where showsPrec _ SHA256 = showString "SHA256" showsPrec _ SHA384 = showString "SHA384" showsPrec _ SHA512 = showString "SHA512" + showsPrec _ SHA3_224 = showString "SHA3_224" + showsPrec _ SHA3_256 = showString "SHA3_256" + showsPrec _ SHA3_384 = showString "SHA3_384" + showsPrec _ SHA3_512 = showString "SHA3_512" showsPrec _ SHAKE128_256 = showString "SHAKE128_256" showsPrec _ SHAKE256_512 = showString "SHAKE256_512" showsPrec d (SHAKE128 p) = @@ -208,6 +220,10 @@ instance HasStrength (DigestProxy hashAlg) where getSecurityBits SHA256 = 128 getSecurityBits SHA384 = 192 getSecurityBits SHA512 = 256 + getSecurityBits SHA3_224 = 112 + getSecurityBits SHA3_256 = 128 + getSecurityBits SHA3_384 = 192 + getSecurityBits SHA3_512 = 256 getSecurityBits SHAKE128_256 = 128 getSecurityBits SHAKE256_512 = 256 getSecurityBits (SHAKE128 a) = shakeSecurityBits 128 a @@ -233,6 +249,10 @@ instance Eq DigestAlgorithm where DigestAlgorithm SHA256 == DigestAlgorithm SHA256 = True DigestAlgorithm SHA384 == DigestAlgorithm SHA384 = True DigestAlgorithm SHA512 == DigestAlgorithm SHA512 = True + DigestAlgorithm SHA3_224 == DigestAlgorithm SHA3_224 = True + DigestAlgorithm SHA3_256 == DigestAlgorithm SHA3_256 = True + DigestAlgorithm SHA3_384 == DigestAlgorithm SHA3_384 = True + DigestAlgorithm SHA3_512 == DigestAlgorithm SHA3_512 = True DigestAlgorithm SHAKE128_256 == DigestAlgorithm SHAKE128_256 = True DigestAlgorithm SHAKE256_512 == DigestAlgorithm SHAKE256_512 = True DigestAlgorithm (SHAKE128 a) == DigestAlgorithm (SHAKE128 b) = natVal a == natVal b @@ -251,6 +271,10 @@ data DigestType | Type_SHA256 | Type_SHA384 | Type_SHA512 + | Type_SHA3_224 + | Type_SHA3_256 + | Type_SHA3_384 + | Type_SHA3_512 | Type_SHAKE128_256 | Type_SHAKE256_512 | Type_SHAKE128_Len @@ -265,6 +289,10 @@ instance Enumerable DigestType where , Type_SHA256 , Type_SHA384 , Type_SHA512 + , Type_SHA3_224 + , Type_SHA3_256 + , Type_SHA3_384 + , Type_SHA3_512 , Type_SHAKE128_256 , Type_SHAKE256_512 , Type_SHAKE128_Len @@ -280,6 +308,10 @@ instance OIDable DigestType where getObjectID Type_SHA256 = [2,16,840,1,101,3,4,2,1] getObjectID Type_SHA384 = [2,16,840,1,101,3,4,2,2] getObjectID Type_SHA512 = [2,16,840,1,101,3,4,2,3] + getObjectID Type_SHA3_224 = [2,16,840,1,101,3,4,2,7] + getObjectID Type_SHA3_256 = [2,16,840,1,101,3,4,2,8] + getObjectID Type_SHA3_384 = [2,16,840,1,101,3,4,2,9] + getObjectID Type_SHA3_512 = [2,16,840,1,101,3,4,2,10] getObjectID Type_SHAKE128_256 = [2,16,840,1,101,3,4,2,11] getObjectID Type_SHAKE256_512 = [2,16,840,1,101,3,4,2,12] getObjectID Type_SHAKE128_Len = [2,16,840,1,101,3,4,2,17] @@ -300,6 +332,10 @@ instance AlgorithmId DigestAlgorithm where algorithmType (DigestAlgorithm SHA256) = Type_SHA256 algorithmType (DigestAlgorithm SHA384) = Type_SHA384 algorithmType (DigestAlgorithm SHA512) = Type_SHA512 + algorithmType (DigestAlgorithm SHA3_224) = Type_SHA3_224 + algorithmType (DigestAlgorithm SHA3_256) = Type_SHA3_256 + algorithmType (DigestAlgorithm SHA3_384) = Type_SHA3_384 + algorithmType (DigestAlgorithm SHA3_512) = Type_SHA3_512 algorithmType (DigestAlgorithm SHAKE128_256) = Type_SHAKE128_256 algorithmType (DigestAlgorithm SHAKE256_512) = Type_SHAKE256_512 algorithmType (DigestAlgorithm (SHAKE128 _)) = Type_SHAKE128_Len @@ -320,6 +356,10 @@ instance AlgorithmId DigestAlgorithm where parseParameter Type_SHA256 = parseDigestParam (DigestAlgorithm SHA256) parseParameter Type_SHA384 = parseDigestParam (DigestAlgorithm SHA384) parseParameter Type_SHA512 = parseDigestParam (DigestAlgorithm SHA512) + parseParameter Type_SHA3_224 = parseDigestParam (DigestAlgorithm SHA3_224) + parseParameter Type_SHA3_256 = parseDigestParam (DigestAlgorithm SHA3_256) + parseParameter Type_SHA3_384 = parseDigestParam (DigestAlgorithm SHA3_384) + parseParameter Type_SHA3_512 = parseDigestParam (DigestAlgorithm SHA3_512) parseParameter Type_SHAKE128_256 = parseDigestParam (DigestAlgorithm SHAKE128_256) parseParameter Type_SHAKE256_512 = parseDigestParam (DigestAlgorithm SHAKE256_512) parseParameter Type_SHAKE128_Len = parseBitLen $ @@ -456,19 +496,27 @@ instance Enumerable MACType where , TypeHMAC SHA256 , TypeHMAC SHA384 , TypeHMAC SHA512 + , TypeHMAC SHA3_224 + , TypeHMAC SHA3_256 + , TypeHMAC SHA3_384 + , TypeHMAC SHA3_512 , TypeKMAC_SHAKE128 , TypeKMAC_SHAKE256 ] instance OIDable MACType where - getObjectID (TypeHMAC MD5) = [1,3,6,1,5,5,8,1,1] - getObjectID (TypeHMAC SHA1) = [1,3,6,1,5,5,8,1,2] - getObjectID (TypeHMAC SHA224) = [1,2,840,113549,2,8] - getObjectID (TypeHMAC SHA256) = [1,2,840,113549,2,9] - getObjectID (TypeHMAC SHA384) = [1,2,840,113549,2,10] - getObjectID (TypeHMAC SHA512) = [1,2,840,113549,2,11] - getObjectID TypeKMAC_SHAKE128 = [2,16,840,1,101,3,4,2,19] - getObjectID TypeKMAC_SHAKE256 = [2,16,840,1,101,3,4,2,20] + getObjectID (TypeHMAC MD5) = [1,3,6,1,5,5,8,1,1] + getObjectID (TypeHMAC SHA1) = [1,3,6,1,5,5,8,1,2] + getObjectID (TypeHMAC SHA224) = [1,2,840,113549,2,8] + getObjectID (TypeHMAC SHA256) = [1,2,840,113549,2,9] + getObjectID (TypeHMAC SHA384) = [1,2,840,113549,2,10] + getObjectID (TypeHMAC SHA512) = [1,2,840,113549,2,11] + getObjectID (TypeHMAC SHA3_224) = [2,16,840,1,101,3,4,2,13] + getObjectID (TypeHMAC SHA3_256) = [2,16,840,1,101,3,4,2,14] + getObjectID (TypeHMAC SHA3_384) = [2,16,840,1,101,3,4,2,15] + getObjectID (TypeHMAC SHA3_512) = [2,16,840,1,101,3,4,2,16] + getObjectID TypeKMAC_SHAKE128 = [2,16,840,1,101,3,4,2,19] + getObjectID TypeKMAC_SHAKE256 = [2,16,840,1,101,3,4,2,20] getObjectID ty = error ("Unsupported MACAlgorithm: " ++ show ty) diff --git a/tests/CMS/Instances.hs b/tests/CMS/Instances.hs index e8a15a2..0074647 100644 --- a/tests/CMS/Instances.hs +++ b/tests/CMS/Instances.hs @@ -4,7 +4,6 @@ module CMS.Instances ( arbitraryPassword , arbitraryAttributes - , arbitraryIntegrityDigest , arbitrarySigVer , arbitraryEnvDev ) where @@ -138,25 +137,33 @@ instance Arbitrary DigestAlgorithm where , pure $ DigestAlgorithm SHA256 , pure $ DigestAlgorithm SHA384 , pure $ DigestAlgorithm SHA512 + , pure $ DigestAlgorithm SHA3_224 + , pure $ DigestAlgorithm SHA3_256 + , pure $ DigestAlgorithm SHA3_384 + , pure $ DigestAlgorithm SHA3_512 , pure $ DigestAlgorithm SHAKE128_256 , pure $ DigestAlgorithm SHAKE256_512 , (\(SomeNat p) -> DigestAlgorithm (SHAKE128 p)) <$> arbitraryNat , (\(SomeNat p) -> DigestAlgorithm (SHAKE256 p)) <$> arbitraryNat ] -arbitraryIntegrityDigest :: Gen DigestAlgorithm -arbitraryIntegrityDigest = elements +arbitraryDigest :: Gen DigestAlgorithm +arbitraryDigest = elements [ DigestAlgorithm MD5 , DigestAlgorithm SHA1 , DigestAlgorithm SHA224 , DigestAlgorithm SHA256 , DigestAlgorithm SHA384 , DigestAlgorithm SHA512 + , DigestAlgorithm SHA3_224 + , DigestAlgorithm SHA3_256 + , DigestAlgorithm SHA3_384 + , DigestAlgorithm SHA3_512 ] instance Arbitrary MACAlgorithm where arbitrary = oneof - [ (\(DigestAlgorithm alg) -> HMAC alg) <$> arbitraryIntegrityDigest + [ (\(DigestAlgorithm alg) -> HMAC alg) <$> arbitraryDigest , (\(SomeNat p) -> KMAC_SHAKE128 p) <$> arbitraryNat <*> arbitraryCtx , (\(SomeNat p) -> KMAC_SHAKE256 p) <$> arbitraryNat <*> arbitraryCtx ] diff --git a/tests/CMS/Tests.hs b/tests/CMS/Tests.hs index 95a7147..12518dd 100644 --- a/tests/CMS/Tests.hs +++ b/tests/CMS/Tests.hs @@ -180,12 +180,16 @@ digestedDataTests = ci' = toAttachedCI dd' ci @?= ci' where path = testFile "cms-digested-data.pem" - algs = [ ("MD5", DigestAlgorithm MD5) - , ("SHA1", DigestAlgorithm SHA1) - , ("SHA224", DigestAlgorithm SHA224) - , ("SHA256", DigestAlgorithm SHA256) - , ("SHA384", DigestAlgorithm SHA384) - , ("SHA512", DigestAlgorithm SHA512) + algs = [ ("MD5", DigestAlgorithm MD5) + , ("SHA1", DigestAlgorithm SHA1) + , ("SHA224", DigestAlgorithm SHA224) + , ("SHA256", DigestAlgorithm SHA256) + , ("SHA384", DigestAlgorithm SHA384) + , ("SHA512", DigestAlgorithm SHA512) + , ("SHA3_224", DigestAlgorithm SHA3_224) + , ("SHA3_256", DigestAlgorithm SHA3_256) + , ("SHA3_384", DigestAlgorithm SHA3_384) + , ("SHA3_512", DigestAlgorithm SHA3_512) ] encryptedDataTests :: TestTree diff --git a/tests/PKCS12/Instances.hs b/tests/PKCS12/Instances.hs index 9239ca5..70010bc 100644 --- a/tests/PKCS12/Instances.hs +++ b/tests/PKCS12/Instances.hs @@ -13,6 +13,7 @@ import Data.Semigroup import Test.Tasty.QuickCheck +import Crypto.Store.CMS import Crypto.Store.PKCS12 import Crypto.Store.PKCS5 @@ -26,6 +27,18 @@ arbitraryAlias :: Gen String arbitraryAlias = resize 16 asciiChar where asciiChar = listOf $ choose ('\x20','\x7f') +arbitraryIntegrityDigest :: Gen DigestAlgorithm +arbitraryIntegrityDigest = elements + [ DigestAlgorithm MD2 + , DigestAlgorithm MD4 + , DigestAlgorithm MD5 + , DigestAlgorithm SHA1 + , DigestAlgorithm SHA224 + , DigestAlgorithm SHA256 + , DigestAlgorithm SHA384 + , DigestAlgorithm SHA512 + ] + arbitraryIntegrityParams :: Gen IntegrityParams arbitraryIntegrityParams = (,) <$> arbitraryIntegrityDigest <*> arbitrary diff --git a/tests/files/cms-digested-data.pem b/tests/files/cms-digested-data.pem index 4fe3f2b..c6c3e40 100644 --- a/tests/files/cms-digested-data.pem +++ b/tests/files/cms-digested-data.pem @@ -25,3 +25,22 @@ MIGABgkqhkiG9w0BBwWgczBxAgEAMAsGCWCGSAFlAwQCAzAdBgkqhkiG9w0BBwGg EAQOaGVsbG8sIHdvcmxkDQoEQNmRYGENk6X3fR9Sk9k++QSKUPYBvF+nGKHL4FXN QVoNz4kKv9BI4MPnsV77ikuw7kWGR3OFLWO8waCyFK+EEu0= -----END CMS----- +-----BEGIN CMS----- +MFwGCSqGSIb3DQEHBaBPME0CAQAwCwYJYIZIAWUDBAIHMB0GCSqGSIb3DQEHAaAQ +BA5oZWxsbywgd29ybGQNCgQcrHRNG/sKxDCiVbjFsYvAvrXdZNaPFFkUnKb7eg== +-----END CMS----- +-----BEGIN CMS----- +MGAGCSqGSIb3DQEHBaBTMFECAQAwCwYJYIZIAWUDBAIIMB0GCSqGSIb3DQEHAaAQ +BA5oZWxsbywgd29ybGQNCgQgead3JnYtNJOYL50QfPgWkqUtpmuiU9T7itIfOmfa +3l4= +-----END CMS----- +-----BEGIN CMS----- +MHAGCSqGSIb3DQEHBaBjMGECAQAwCwYJYIZIAWUDBAIJMB0GCSqGSIb3DQEHAaAQ +BA5oZWxsbywgd29ybGQNCgQwPvv+XafJtPR2UXRqu2t6l3BuJeoOghvrAfPbbRQ2 +cr5IHYmzioNIZ1HlrP6RG0R3 +-----END CMS----- +-----BEGIN CMS----- +MIGABgkqhkiG9w0BBwWgczBxAgEAMAsGCWCGSAFlAwQCCjAdBgkqhkiG9w0BBwGg +EAQOaGVsbG8sIHdvcmxkDQoEQHjsLFT6QOVe+FI6fBZhWEIHpXzDX9L4/ARGWEXp +rKVTw6DfjRFICt66Mxxqn4WbRCa/FJXAnVY1PduwTN1Fiqw= +-----END CMS----- diff --git a/tests/files/generate.sh b/tests/files/generate.sh index 407bb2e..2c734d2 100755 --- a/tests/files/generate.sh +++ b/tests/files/generate.sh @@ -384,7 +384,7 @@ echo "$MESSAGE" | "$OPENSSL" cms -data_create \ # CMS digested data ( - for digest in MD5 SHA1 SHA224 SHA256 SHA384 SHA512; do + for digest in MD5 SHA1 SHA224 SHA256 SHA384 SHA512 SHA3-224 SHA3-256 SHA3-384 SHA3-512; do echo "$MESSAGE" | "$OPENSSL" cms -digest_create -md $digest \ -outform PEM done