diff --git a/Benchmarks/Benchmarks.hs b/Benchmarks/Benchmarks.hs
deleted file mode 100644
--- a/Benchmarks/Benchmarks.hs
+++ /dev/null
@@ -1,187 +0,0 @@
-{-# LANGUAGE BangPatterns #-}
-
-module Main where
-
-import Certificate
-import Control.Concurrent.Chan
-import Data.Default (def)
-import Data.IORef
-import Data.X509
-import Data.X509.Validation
-import Test.Tasty.Bench
-import Network.TLS
-import Network.TLS.Extra.Cipher
-import Session
-import Run
-import PubKey
-
-import qualified Data.ByteString as B
-import qualified Data.ByteString.Lazy as L
-
-blockCipher :: Cipher
-blockCipher =
-    Cipher
-        { cipherID = 0xff12
-        , cipherName = "rsa-id-const"
-        , cipherBulk =
-            Bulk
-                { bulkName = "id"
-                , bulkKeySize = 16
-                , bulkIVSize = 16
-                , bulkExplicitIV = 0
-                , bulkAuthTagLen = 0
-                , bulkBlockSize = 16
-                , bulkF = BulkBlockF $ \_ _ _ m -> (m, B.empty)
-                }
-        , cipherHash = MD5
-        , cipherPRFHash = Nothing
-        , cipherKeyExchange = CipherKeyExchange_RSA
-        , cipherMinVer = Nothing
-        }
-
-getParams :: Version -> Cipher -> (ClientParams, ServerParams)
-getParams connectVer cipher = (cParams, sParams)
-  where
-    sParams =
-        def
-            { serverSupported = supported
-            , serverShared =
-                def
-                    { sharedCredentials =
-                        Credentials
-                            [(CertificateChain [simpleX509 $ PubKeyRSA pubKey], PrivKeyRSA privKey)]
-                    }
-            }
-    cParams =
-        (defaultParamsClient "" B.empty)
-            { clientSupported = supported
-            , clientShared =
-                def
-                    { sharedValidationCache =
-                        ValidationCache
-                            { cacheAdd = \_ _ _ -> return ()
-                            , cacheQuery = \_ _ _ -> return ValidationCachePass
-                            }
-                    }
-            }
-    supported =
-        def
-            { supportedCiphers = [cipher]
-            , supportedVersions = [connectVer]
-            , supportedGroups = [X25519, FFDHE2048]
-            }
-    (pubKey, privKey) = getGlobalRSAPair
-
-runTLSPipe
-    :: (ClientParams, ServerParams)
-    -> (Context -> Chan b -> IO ())
-    -> (Chan a -> Context -> IO ())
-    -> a
-    -> IO b
-runTLSPipe params tlsServer tlsClient d = do
-    withDataPipe params tlsServer tlsClient $ \(writeStart, readResult) -> do
-        writeStart d
-        readResult
-
-runTLSPipeSimple
-    :: (ClientParams, ServerParams) -> B.ByteString -> IO B.ByteString
-runTLSPipeSimple params = runTLSPipe params tlsServer tlsClient
-  where
-    tlsServer ctx queue = do
-        handshake ctx
-        d <- recvData ctx
-        writeChan queue d
-        bye ctx
-    tlsClient queue ctx = do
-        handshake ctx
-        d <- readChan queue
-        sendData ctx (L.fromChunks [d])
-        byeBye ctx
-
-benchConnection
-    :: (ClientParams, ServerParams) -> B.ByteString -> String -> Benchmark
-benchConnection params !d name = bench name . nfIO $ runTLSPipeSimple params d
-
-benchResumption
-    :: (ClientParams, ServerParams) -> B.ByteString -> String -> Benchmark
-benchResumption params !d name = env initializeSession runResumption
-  where
-    initializeSession = do
-        sessionRefs <- twoSessionRefs
-        let sessionManagers = twoSessionManagers sessionRefs
-            params1 = setPairParamsSessionManagers sessionManagers params
-        _ <- runTLSPipeSimple params1 d
-
-        Just sessionParams <- readClientSessionRef sessionRefs
-        let params2 = setPairParamsSessionResuming sessionParams params1
-        newIORef params2
-
-    runResumption paramsRef = bench name . nfIO $ do
-        params2 <- readIORef paramsRef
-        runTLSPipeSimple params2 d
-
-benchResumption13
-    :: (ClientParams, ServerParams) -> B.ByteString -> String -> Benchmark
-benchResumption13 params !d name = env initializeSession runResumption
-  where
-    initializeSession = do
-        sessionRefs <- twoSessionRefs
-        let sessionManagers = twoSessionManagers sessionRefs
-            params1 = setPairParamsSessionManagers sessionManagers params
-        _ <- runTLSPipeSimple params1 d
-        newIORef (params1, sessionRefs)
-
-    -- with TLS13 the sessionId is constantly changing so we must update
-    -- our parameters at each iteration unfortunately
-    runResumption paramsRef = bench name . nfIO $ do
-        (params1, sessionRefs) <- readIORef paramsRef
-        Just sessionParams <- readClientSessionRef sessionRefs
-        let params2 = setPairParamsSessionResuming sessionParams params1
-        runTLSPipeSimple params2 d
-
-benchCiphers :: String -> Version -> B.ByteString -> [Cipher] -> Benchmark
-benchCiphers name connectVer d = bgroup name . map doBench
-  where
-    doBench cipher =
-        benchResumption13 (getParams connectVer cipher) d (cipherName cipher)
-
-main :: IO ()
-main =
-    defaultMain
-        [ bgroup
-            "connection"
-            -- not sure the number actually make sense for anything. improve ..
-            [ benchConnection (getParams TLS12 blockCipher) small "TLS12-256 bytes"
-            ]
-        , bgroup
-            "resumption"
-            [ benchResumption (getParams TLS12 blockCipher) small "TLS12-256 bytes"
-            ]
-        , -- Here we try to measure TLS12 and TLS13 performance with AEAD ciphers.
-          -- Resumption and a larger message can be a demonstration of the symmetric
-          -- crypto but for TLS13 this does not work so well because of dhe_psk.
-          benchCiphers
-            "TLS12"
-            TLS12
-            large
-            [ cipher_DHE_RSA_WITH_AES_128_GCM_SHA256
-            , cipher_DHE_RSA_WITH_AES_256_GCM_SHA384
-            , cipher_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256
-            , cipher_ECDHE_RSA_WITH_AES_128_GCM_SHA256
-            , cipher_ECDHE_RSA_WITH_AES_256_GCM_SHA384
-            , cipher_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256
-            ]
-        , benchCiphers
-            "TLS13"
-            TLS13
-            large
-            [ cipher13_AES_128_GCM_SHA256
-            , cipher13_AES_256_GCM_SHA384
-            , cipher13_CHACHA20_POLY1305_SHA256
-            , cipher13_AES_128_CCM_SHA256
-            , cipher13_AES_128_CCM_8_SHA256
-            ]
-        ]
-  where
-    small = B.replicate 256 0
-    large = B.replicate 102400 0
diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,16 @@
 # Change log for "tls"
 
+## Version 2.4.11
+
+* Keep preferring AES-GCM on AArch64 with crypton 2.2, which names the
+  ARMv8 instructions rather than x86's.
+  [#584](https://github.com/haskell-tls/hs-tls/pull/584)
+* Sign and verify RSA PKCS#1 v1.5 through crypton's digest-taking
+  operations, which deprecate the ones used before.  crypton >= 2.1.9 is
+  now required.
+  [#585](https://github.com/haskell-tls/hs-tls/pull/585)
+* Remove the `tls-bench` benchmark.
+
 ## Version 2.4.10
 
 * Support ML-DSA certificates and CertificateVerify, TLS 1.3 only
diff --git a/Network/TLS/Crypto.hs b/Network/TLS/Crypto.hs
--- a/Network/TLS/Crypto.hs
+++ b/Network/TLS/Crypto.hs
@@ -431,13 +431,17 @@
     -> RSA.PrivateKey
     -> ByteString
     -> m (Either RSA.Error ByteString)
-rsaSignHash SHA1_MD5 pk msg = RSA.signSafer noHash pk msg
-rsaSignHash MD5 pk msg = RSA.signSafer (Just H.MD5) pk msg
-rsaSignHash SHA1 pk msg = RSA.signSafer (Just H.SHA1) pk msg
-rsaSignHash SHA224 pk msg = RSA.signSafer (Just H.SHA224) pk msg
-rsaSignHash SHA256 pk msg = RSA.signSafer (Just H.SHA256) pk msg
-rsaSignHash SHA384 pk msg = RSA.signSafer (Just H.SHA384) pk msg
-rsaSignHash SHA512 pk msg = RSA.signSafer (Just H.SHA512) pk msg
+-- SHA1_MD5 arrives already digested -- see buildVerifyData -- and what it
+-- carries is MD5 ++ SHA1 with no ASN.1 around it, which is what TLS before
+-- 1.2 signs.  That is the DigestInfo case: nothing here hashes or encodes.
+-- The rest are handed the message and hash it on the way, as signSafer did.
+rsaSignHash SHA1_MD5 pk msg = RSA.signSaferDigestInfo pk msg
+rsaSignHash MD5 pk msg = RSA.signSaferDigest pk (H.hashWith H.MD5 msg)
+rsaSignHash SHA1 pk msg = RSA.signSaferDigest pk (H.hashWith H.SHA1 msg)
+rsaSignHash SHA224 pk msg = RSA.signSaferDigest pk (H.hashWith H.SHA224 msg)
+rsaSignHash SHA256 pk msg = RSA.signSaferDigest pk (H.hashWith H.SHA256 msg)
+rsaSignHash SHA384 pk msg = RSA.signSaferDigest pk (H.hashWith H.SHA384 msg)
+rsaSignHash SHA512 pk msg = RSA.signSaferDigest pk (H.hashWith H.SHA512 msg)
 
 rsapssSignHash
     :: MonadRandom m
@@ -451,22 +455,19 @@
 rsapssSignHash _ _ _ = error "rsapssSignHash: unsupported hash"
 
 rsaVerifyHash :: Hash -> RSA.PublicKey -> ByteString -> ByteString -> Bool
-rsaVerifyHash SHA1_MD5 = RSA.verify noHash
-rsaVerifyHash MD5 = RSA.verify (Just H.MD5)
-rsaVerifyHash SHA1 = RSA.verify (Just H.SHA1)
-rsaVerifyHash SHA224 = RSA.verify (Just H.SHA224)
-rsaVerifyHash SHA256 = RSA.verify (Just H.SHA256)
-rsaVerifyHash SHA384 = RSA.verify (Just H.SHA384)
-rsaVerifyHash SHA512 = RSA.verify (Just H.SHA512)
+rsaVerifyHash SHA1_MD5 pk msg = RSA.verifyDigestInfo pk msg
+rsaVerifyHash MD5 pk msg = RSA.verifyDigest pk (H.hashWith H.MD5 msg)
+rsaVerifyHash SHA1 pk msg = RSA.verifyDigest pk (H.hashWith H.SHA1 msg)
+rsaVerifyHash SHA224 pk msg = RSA.verifyDigest pk (H.hashWith H.SHA224 msg)
+rsaVerifyHash SHA256 pk msg = RSA.verifyDigest pk (H.hashWith H.SHA256 msg)
+rsaVerifyHash SHA384 pk msg = RSA.verifyDigest pk (H.hashWith H.SHA384 msg)
+rsaVerifyHash SHA512 pk msg = RSA.verifyDigest pk (H.hashWith H.SHA512 msg)
 
 rsapssVerifyHash :: Hash -> RSA.PublicKey -> ByteString -> ByteString -> Bool
 rsapssVerifyHash SHA256 = PSS.verify (PSS.defaultPSSParams H.SHA256)
 rsapssVerifyHash SHA384 = PSS.verify (PSS.defaultPSSParams H.SHA384)
 rsapssVerifyHash SHA512 = PSS.verify (PSS.defaultPSSParams H.SHA512)
 rsapssVerifyHash _ = error "rsapssVerifyHash: unsupported hash"
-
-noHash :: Maybe H.MD5
-noHash = Nothing
 
 ecdsaSignHash
     :: (MonadRandom m, ECDSA.EllipticCurveECDSA curve)
diff --git a/Network/TLS/Extra/Cipher.hs b/Network/TLS/Extra/Cipher.hs
--- a/Network/TLS/Extra/Cipher.hs
+++ b/Network/TLS/Extra/Cipher.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE CPP #-}
 module Network.TLS.Extra.Cipher (
     -- * Cipher suite
     ciphersuite_default,
@@ -573,9 +574,22 @@
 sortOptimized :: [CipherSet] -> [Cipher]
 sortOptimized = concatMap f
   where
+    -- crypton 2.2 gives the AArch64 instructions their own names.  Before
+    -- it, the ARMv8 path set the slots Haskell read as AESNI and PCLMUL, so
+    -- asking for those names answered "is AES fast here" on both
+    -- architectures; from 2.2 they are x86's names, which an AArch64 machine
+    -- does not have.  hasAESAcceleration and hasGHASHAcceleration ask the
+    -- question without naming an instruction set.  Either spelling compiles
+    -- against either version -- the names are pattern synonyms now -- so
+    -- nothing but this guard says which one is right for which.
     f (SetAead gcm chacha ccm)
+#if MIN_VERSION_crypton(2,2,0)
+        | not hasAESAcceleration = chacha ++ gcm ++ ccm
+        | not hasGHASHAcceleration = ccm ++ chacha ++ gcm
+#else
         | AESNI `notElem` processorOptions = chacha ++ gcm ++ ccm
         | PCLMUL `notElem` processorOptions = ccm ++ chacha ++ gcm
+#endif
         | otherwise = gcm ++ ccm ++ chacha
     f (SetOther ciphers) = ciphers
 
diff --git a/tls.cabal b/tls.cabal
--- a/tls.cabal
+++ b/tls.cabal
@@ -1,6 +1,6 @@
 cabal-version:      2.0
 name:               tls
-version:            2.4.10
+version:            2.4.11
 license:            BSD3
 license-file:       LICENSE
 copyright:          Vincent Hanquez <vincent@snarc.org>
@@ -15,6 +15,8 @@
 build-type:         Simple
 extra-source-files:
     test/*.hs
+
+extra-doc-files:
     CHANGELOG.md
 
 source-repository head
@@ -122,7 +124,7 @@
         base16-bytestring,
         bytestring >=0.10 && <0.13,
         cereal >=0.5.3 && <0.6,
-        crypton >=2.1.8 && <2.3,
+        crypton >=2.1.9 && <2.3,
         crypton-asn1-encoding >= 0.10.0 && < 0.11,
         crypton-asn1-types >= 0.4.1 && < 0.5,
         crypton-x509 >=1.10 && <1.11,
@@ -237,46 +239,3 @@
         time-hourglass,
         tls,
         zlib
-
-benchmark tls-bench
-    type:             exitcode-stdio-1.0
-    main-is:          Benchmarks.hs
-    hs-source-dirs:   Benchmarks test
-    other-modules:
-        API
-        Arbitrary
-        Certificate
-        CiphersSpec
-        ECHSpec
-        EncodeSpec
-        HandshakeSpec
-        PipeChan
-        PubKey
-        Run
-        Session
-        ThreadSpec
-
-    default-language: Haskell2010
-    ghc-options:      -Wall
-    build-depends:
-        base >=4.9 && <5,
-        QuickCheck,
-        async,
-        base64-bytestring,
-        bytestring,
-        containers,
-        crypton,
-        crypton-asn1-types,
-        crypton-x509,
-        crypton-x509-store,
-        crypton-x509-validation,
-        data-default,
-        ech-config,
-        hspec,
-        network,
-        network-run,
-        ram,
-        serialise,
-        tasty-bench,
-        time-hourglass,
-        tls
