diff --git a/Cargo.lock b/Cargo.lock index ffbc845..30022ab 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4,22 +4,23 @@ version = 4 [[package]] name = "aes" -version = "0.8.4" +version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b169f7a6d4742236a0a00c541b845991d0ac43e546831af1249753ab4c3aa3a0" +checksum = "f1fc76eaeac4c9164506c466d4ffdd8ec9d0c5bf57ee97177c4d8eceb3a0e138" dependencies = [ - "cfg-if", "cipher", + "cpubits", "cpufeatures", ] [[package]] name = "aes-kw" -version = "0.2.1" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69fa2b352dcefb5f7f3a5fb840e02665d311d878955380515e4fd50095dd3d8c" +checksum = "41ac571010bd60765c56085a4f1d412012a9be2663b1a2f2b19b49318653fd0d" dependencies = [ "aes", + "const-oid", ] [[package]] @@ -28,56 +29,50 @@ version = "0.22.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" -[[package]] -name = "base64ct" -version = "1.8.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2af50177e190e07a26ab74f8b1efbfe2ef87da2116221318cb1c2e82baf7de06" - [[package]] name = "bitflags" -version = "2.11.0" +version = "2.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "843867be96c8daad0d758b57df9392b6d8d271134fce549de6ce169ff98a92af" +checksum = "c4512299f36f043ab09a583e57bceb5a5aab7a73db1805848e8fef3c9e8c78b3" [[package]] name = "block-buffer" -version = "0.10.4" +version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" +checksum = "cdd35008169921d80bc60d3d0ab416eecb028c4cd653352907921d95084790be" dependencies = [ - "generic-array", + "hybrid-array", ] [[package]] name = "block-padding" -version = "0.3.3" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8894febbff9f758034a5b8e12d87918f56dfc64a8e1fe757d65e29041538d93" +checksum = "710f1dd022ef4e93f8a438b4ba958de7f64308434fa6a87104481645cc30068b" dependencies = [ - "generic-array", + "hybrid-array", ] [[package]] name = "bumpalo" -version = "3.20.2" +version = "3.20.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d20789868f4b01b2f2caec9f5c4e0213b41e3e5702a50157d699ae31ced2fcb" +checksum = "72f5acc6cb2ba439de613abc23857ec3d78374d8ed5ac84e9d11336e87da8649" [[package]] name = "cbc" -version = "0.1.2" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26b52a9543ae338f279b96b0b9fed9c8093744685043739079ce85cd58f289a6" +checksum = "ce2dc9ee5f88d11e0beb842c88b33c8a5cf0d1329c4b19494af42b07dbfe8896" dependencies = [ "cipher", ] [[package]] name = "cc" -version = "1.2.57" +version = "1.2.62" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a0dd1ca384932ff3641c8718a02769f1698e7563dc6974ffd03346116310423" +checksum = "a1dce859f0832a7d088c4f1119888ab94ef4b5d6795d1ce05afb7fe159d79f98" dependencies = [ "find-msvc-tools", "shlex", @@ -91,19 +86,37 @@ checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" [[package]] name = "cipher" -version = "0.4.4" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad" +checksum = "e8cf2a2c93cd704877c0858356ed03480ff301ee950b43f1cbe4573b088bfa6c" dependencies = [ "crypto-common", "inout", ] +[[package]] +name = "cmov" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f88a43d011fc4a6876cb7344703e297c71dda42494fee094d5f7c76bf13f746" + +[[package]] +name = "const-oid" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6ef517f0926dd24a1582492c791b6a4818a4d94e789a334894aa15b0d12f55c" + +[[package]] +name = "cpubits" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "15b85f9c39137c3a891689859392b1bd49812121d0d61c9caf00d46ed5ce06ae" + [[package]] name = "cpufeatures" -version = "0.2.17" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280" +checksum = "8b2a41393f66f16b0823bb79094d54ac5fbd34ab292ddafb9a0456ac9f87d201" dependencies = [ "libc", ] @@ -124,12 +137,20 @@ dependencies = [ [[package]] name = "crypto-common" -version = "0.1.7" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78c8292055d1c1df0cce5d180393dc8cce0abec0a7102adb6c7b1eef6016d60a" +checksum = "ce6e4c961d6cd6c9a86db418387425e8bdeaf05b3c8bc1411e6dca4c252f1453" dependencies = [ - "generic-array", - "typenum", + "hybrid-array", +] + +[[package]] +name = "ctutils" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d5515a3834141de9eafb9717ad39eea8247b5674e6066c404e8c4b365d2a29e" +dependencies = [ + "cmov", ] [[package]] @@ -143,13 +164,14 @@ dependencies = [ [[package]] name = "digest" -version = "0.10.7" +version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +checksum = "f1dd6dbb5841937940781866fa1281a1ff7bd3bf827091440879f9994983d5c2" dependencies = [ "block-buffer", + "const-oid", "crypto-common", - "subtle", + "ctutils", ] [[package]] @@ -182,16 +204,6 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "77ce24cb58228fbb8aa041425bb1050850ac19177686ea6e0f41a70416f56fdb" -[[package]] -name = "generic-array" -version = "0.14.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" -dependencies = [ - "typenum", - "version_check", -] - [[package]] name = "hashbrown" version = "0.16.1" @@ -201,71 +213,87 @@ dependencies = [ "foldhash", ] +[[package]] +name = "hashbrown" +version = "0.17.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed5909b6e89a2db4456e54cd5f673791d7eca6732202bbf2a9cc504fe2f9b84a" + [[package]] name = "hashlink" version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ea0b22561a9c04a7cb1a302c013e0259cd3b4bb619f145b32f72b8b4bcbed230" dependencies = [ - "hashbrown", + "hashbrown 0.16.1", ] [[package]] name = "hmac" -version = "0.12.1" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" +checksum = "6303bc9732ae41b04cb554b844a762b4115a61bfaa81e3e83050991eeb56863f" dependencies = [ "digest", ] +[[package]] +name = "hybrid-array" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9155a582abd142abc056962c29e3ce5ff2ad5469f4246b537ed42c5deba857da" +dependencies = [ + "typenum", +] + [[package]] name = "indexmap" -version = "2.13.0" +version = "2.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7714e70437a7dc3ac8eb7e6f8df75fd8eb422675fc7678aff7364301092b1017" +checksum = "d466e9454f08e4a911e14806c24e16fba1b4c121d1ea474396f396069cf949d9" dependencies = [ "equivalent", - "hashbrown", + "hashbrown 0.17.1", ] [[package]] name = "inout" -version = "0.1.4" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "879f10e63c20629ecabbb64a8010319738c66a5cd0c29b02d63d272b03751d01" +checksum = "4250ce6452e92010fdf7268ccc5d14faa80bb12fc741938534c58f16804e03c7" dependencies = [ "block-padding", - "generic-array", + "hybrid-array", ] [[package]] name = "itoa" -version = "1.0.17" +version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92ecc6618181def0457392ccd0ee51198e065e016d1d527a7ac1b6dc7c1f09d2" +checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682" [[package]] name = "js-sys" -version = "0.3.91" +version = "0.3.99" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b49715b7073f385ba4bc528e5747d02e66cb39c6146efb66b781f131f0fb399c" +checksum = "142bc4740e452c1e57ade0cbc129f139c9093e354346f0872ef985f4f5cf5f11" dependencies = [ + "cfg-if", "once_cell", "wasm-bindgen", ] [[package]] name = "libc" -version = "0.2.183" +version = "0.2.186" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5b646652bf6661599e1da8901b3b9522896f01e736bad5f723fe7a3a27f899d" +checksum = "68ab91017fe16c622486840e4c83c9a37afeff978bd239b5293d61ece587de66" [[package]] name = "libsqlite3-sys" -version = "0.37.0" +version = "0.38.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1f111c8c41e7c61a49cd34e44c7619462967221a6443b0ec299e0ac30cfb9b1" +checksum = "a76001fb4daed01e5f2b518aac0b4dc592e7c734da63dbffcf0c64fa612a8d0c" dependencies = [ "cc", "pkg-config", @@ -274,15 +302,15 @@ dependencies = [ [[package]] name = "memchr" -version = "2.8.0" +version = "2.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8ca58f447f06ed17d5fc4043ce1b10dd205e060fb3ce5b979b8ed8e59ff3f79" +checksum = "6b947ae49db0d222b1dbc6b113ce7248a3fc3a6ca21b696717bfc000ba4484d8" [[package]] name = "num-conv" -version = "0.2.0" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf97ec579c3c42f953ef76dbf8d55ac91fb219dde70e49aa4a6b7d74e9919050" +checksum = "521739c6d2bac4aa25192232afe6841231376b2b26d4d9fae5ecf8ca5772e441" [[package]] name = "once_cell" @@ -290,40 +318,27 @@ version = "1.21.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" -[[package]] -name = "password-hash" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "346f04948ba92c43e8469c1ee6736c7563d71012b17d40745260fe106aac2166" -dependencies = [ - "base64ct", - "rand_core", - "subtle", -] - [[package]] name = "pbkdf2" -version = "0.12.2" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8ed6a7761f76e3b9f92dfb0a60a6a6477c61024b775147ff0973a02653abaf2" +checksum = "112d82ceb8c5bf524d9af484d4e4970c9fd5a0cc15ba14ad93dccd28873b0629" dependencies = [ "digest", "hmac", - "password-hash", - "sha2", ] [[package]] name = "pkg-config" -version = "0.3.32" +version = "0.3.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c" +checksum = "19f132c84eca552bf34cab8ec81f1c1dcc229b811638f9d283dceabe58c5569e" [[package]] name = "plist" -version = "1.8.0" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "740ebea15c5d1428f910cd1a5f52cebf8d25006245ed8ade92702f4943d91e07" +checksum = "092791278e026273c1b65bbdcfbba3a300f2994c896bd01ab01da613c29c46f1" dependencies = [ "base64", "indexmap", @@ -349,9 +364,9 @@ dependencies = [ [[package]] name = "quick-xml" -version = "0.38.4" +version = "0.39.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b66c2058c55a409d601666cffe35f04333cf1013010882cec174a7467cd4e21c" +checksum = "cdcc8dd4e2f670d309a5f0e83fe36dfdc05af317008fea29144da1a2ac858e5e" dependencies = [ "memchr", ] @@ -365,27 +380,21 @@ dependencies = [ "proc-macro2", ] -[[package]] -name = "rand_core" -version = "0.6.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" - [[package]] name = "rsqlite-vfs" -version = "0.1.0" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8a1f2315036ef6b1fbacd1972e8ee7688030b0a2121edfc2a6550febd41574d" +checksum = "c51c9ae4df8a7fba42103df5c621fa3c37eccf3a3c650879e90fc48b11cc192c" dependencies = [ - "hashbrown", + "hashbrown 0.16.1", "thiserror", ] [[package]] name = "rusqlite" -version = "0.39.0" +version = "0.40.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a0d2b0146dd9661bf67bb107c0bb2a55064d556eeb3fc314151b957f313bcd4e" +checksum = "1b3492ea85308705c3a5cc24fb9b9cf77273d30590349070db42991202b214c4" dependencies = [ "bitflags", "fallible-iterator", @@ -433,9 +442,9 @@ dependencies = [ [[package]] name = "sha1" -version = "0.10.6" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba" +checksum = "aacc4cc499359472b4abe1bf11d0b12e688af9a805fa5e3016f9a386dc2d0214" dependencies = [ "cfg-if", "cpufeatures", @@ -444,9 +453,9 @@ dependencies = [ [[package]] name = "sha2" -version = "0.10.9" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283" +checksum = "446ba717509524cb3f22f17ecc096f10f4822d76ab5c0b9822c5f9c284e825f4" dependencies = [ "cfg-if", "cpufeatures", @@ -467,9 +476,9 @@ checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" [[package]] name = "sqlite-wasm-rs" -version = "0.5.2" +version = "0.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f4206ed3a67690b9c29b77d728f6acc3ce78f16bf846d83c94f76400320181b" +checksum = "dc3efc0da82635d7e1ced0053bbbfa8c7ab9645d0bf36ceb4f7127bb85315d75" dependencies = [ "cc", "js-sys", @@ -477,12 +486,6 @@ dependencies = [ "wasm-bindgen", ] -[[package]] -name = "subtle" -version = "2.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" - [[package]] name = "syn" version = "2.0.117" @@ -547,9 +550,9 @@ dependencies = [ [[package]] name = "typenum" -version = "1.19.0" +version = "1.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "562d481066bde0658276a35467c4af00bdc6ee726305698a55b86e61d7ad82bb" +checksum = "40ce102ab67701b8526c123c1bab5cbe42d7040ccfd0f64af1a385808d2f43de" [[package]] name = "unicode-ident" @@ -563,17 +566,11 @@ version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" -[[package]] -name = "version_check" -version = "0.9.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" - [[package]] name = "wasm-bindgen" -version = "0.2.114" +version = "0.2.122" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6532f9a5c1ece3798cb1c2cfdba640b9b3ba884f5db45973a6f442510a87d38e" +checksum = "3ed04576f974d2b2fba0f38c51dbc5518011e38c36bf1143164be765528fd409" dependencies = [ "cfg-if", "once_cell", @@ -584,9 +581,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.114" +version = "0.2.122" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18a2d50fcf105fb33bb15f00e7a77b772945a2ee45dcf454961fd843e74c18e6" +checksum = "916151b09da36bd82f6615cbf3a419e2f0ba23a03c6160e8e92eb6bd4aa1dec6" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -594,9 +591,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.114" +version = "0.2.122" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03ce4caeaac547cdf713d280eda22a730824dd11e6b8c3ca9e42247b25c631e3" +checksum = "299047362ccbfce148b67ab7e73349f77748e00c8296f9542adfad2ad82c5c5e" dependencies = [ "bumpalo", "proc-macro2", @@ -607,9 +604,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.114" +version = "0.2.122" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75a326b8c223ee17883a4251907455a2431acc2791c98c26279376490c378c16" +checksum = "9a929b2c61f11ba3e9bc35b50c1f25cb38e0e892c0c231ae2b8cf78d5dad4437" dependencies = [ "unicode-ident", ] diff --git a/Cargo.toml b/Cargo.toml index eb20d06..864f218 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,11 +12,11 @@ keywords = ["ios", "cryptography", "backup"] categories = ["cryptography", "security", "database"] [dependencies] -aes = "0.8.4" -plist = "1.8.0" -aes-kw = "0.2.1" -pbkdf2 = { version = "0.12.2", features = ["simple", "hmac"] } -rusqlite = { version = "0.39.0", features = ["bundled", "blob"] } -cbc = "0.1.2" -sha1 = "0.10.6" -sha2 = "0.10.9" +aes = "0.9.1" +plist = "1.9.0" +aes-kw = "0.3.1" +pbkdf2 = { version = "0.13.0", features = ["hmac"] } +rusqlite = { version = "0.40.0", features = ["bundled", "blob"] } +cbc = "0.2.1" +sha1 = "0.11.0" +sha2 = "0.11.0" diff --git a/src/backup/crypto.rs b/src/backup/crypto.rs index 2419075..74197dc 100644 --- a/src/backup/crypto.rs +++ b/src/backup/crypto.rs @@ -6,13 +6,14 @@ use std::{ }; use aes::{ - Aes128, Aes192, Aes256, + Aes256, cipher::{ - BlockDecryptMut, BlockEncryptMut, KeyIvInit, block_padding::Pkcs7, - generic_array::GenericArray, + Array, BlockModeDecrypt, BlockModeEncrypt, KeyIvInit, + block_padding::{Padding, Pkcs7}, + consts::{U16, U24, U32}, }, }; -use aes_kw::Kek; +use aes_kw::{KeyInit, KwAes128, KwAes192, KwAes256}; use pbkdf2::pbkdf2_hmac; use sha1::Sha1; use sha2::Sha256; @@ -174,13 +175,12 @@ pub(crate) fn unlock_keys_from_manifest( /// assert_eq!(plaintext, data); /// ``` pub fn aes_decrypt_cbc_with_padding(data: &[u8], key: &EncryptionKey) -> Result> { - if key.len() != 32 { - // Assuming AES-256 for this function - return Err(BackupError::InvalidCryptoDataLength { + let key_array = <&Array>::try_from(key.as_slice()).map_err(|_| { + BackupError::InvalidCryptoDataLength { expected: 32, actual: key.len(), - }); - } + } + })?; // Ensure data length is a multiple of 16 bytes (AES block size) let data_len = if data.len().is_multiple_of(16) { @@ -189,8 +189,7 @@ pub fn aes_decrypt_cbc_with_padding(data: &[u8], key: &EncryptionKey) -> Result< data.len() - (data.len() % 16) }; - let iv_bytes = [0u8; 16]; - let iv = GenericArray::from_slice(&iv_bytes); + let iv: [u8; 16] = [0u8; 16]; // Create buffer with truncated data if necessary let mut buf = if data.len() == data_len { @@ -199,11 +198,10 @@ pub fn aes_decrypt_cbc_with_padding(data: &[u8], key: &EncryptionKey) -> Result< data[..data_len].to_vec() }; - let key_ga = GenericArray::from_slice(key); - let cipher = Aes256CbcDec::new(key_ga, iv); + let cipher = Aes256CbcDec::new(key_array, &iv.into()); let pt_len = cipher - .decrypt_padded_mut::(&mut buf) + .decrypt_padded::(&mut buf) .map_err(|e| BackupError::Crypto(format!("AES CBC decryption error (padding): {e:?}")))? .len(); @@ -236,24 +234,21 @@ pub fn aes_decrypt_cbc_with_padding(data: &[u8], key: &EncryptionKey) -> Result< /// assert_eq!(pt, data); /// ``` pub fn aes_encrypt_cbc_with_padding(data: &[u8], key: &EncryptionKey) -> Result> { - if key.len() != 32 { - // Assuming AES-256 for this function - return Err(BackupError::InvalidCryptoDataLength { + let key_array = <&Array>::try_from(key.as_slice()).map_err(|_| { + BackupError::InvalidCryptoDataLength { expected: 32, actual: key.len(), - }); - } - let iv_bytes = [0u8; 16]; - let iv = GenericArray::from_slice(&iv_bytes); + } + })?; + let iv: [u8; 16] = [0u8; 16]; let mut buffer = vec![0u8; data.len() + 16]; // Max possible size for ciphertext with padding buffer[..data.len()].copy_from_slice(data); - let key_ga = GenericArray::from_slice(key); - let cipher = Aes256CbcEnc::new(key_ga, iv); + let cipher = Aes256CbcEnc::new(key_array, &iv.into()); let ct_len = cipher - .encrypt_padded_mut::(&mut buffer, data.len()) + .encrypt_padded::(&mut buffer, data.len()) .map_err(|e| BackupError::Crypto(format!("AES CBC encryption error (padding): {e:?}")))? .len(); @@ -287,20 +282,26 @@ pub(crate) fn aes_kw_unwrap( match kek_bytes.len() { 16 => { // AES-128 key unwrap - let kek = Kek::::new(GenericArray::from_slice(kek_bytes)); - kek.unwrap(wrapped_data, &mut unwrapped) + let key = <&Array>::try_from(kek_bytes.as_slice()) + .map_err(BackupError::ConversionFailed)?; + let kek = KwAes128::new(key); + kek.unwrap_key(wrapped_data, &mut unwrapped) .map_err(|_| BackupError::Crypto("AES 128 Key Unwrap failed".to_string()))?; } 24 => { // AES-192 key unwrap - let kek = Kek::::new(GenericArray::from_slice(kek_bytes)); - kek.unwrap(wrapped_data, &mut unwrapped) + let key = <&Array>::try_from(kek_bytes.as_slice()) + .map_err(BackupError::ConversionFailed)?; + let kek = KwAes192::new(key); + kek.unwrap_key(wrapped_data, &mut unwrapped) .map_err(|_| BackupError::Crypto("AES 192 Key Unwrap failed".to_string()))?; } 32 => { // AES-256 key unwrap - let kek = Kek::::new(GenericArray::from_slice(kek_bytes)); - kek.unwrap(wrapped_data, &mut unwrapped) + let key = <&Array>::try_from(kek_bytes.as_slice()) + .map_err(BackupError::ConversionFailed)?; + let kek = KwAes256::new(key); + kek.unwrap_key(wrapped_data, &mut unwrapped) .map_err(|_| BackupError::Crypto("AES 256 Key Unwrap failed".to_string()))?; } _ => { @@ -364,12 +365,12 @@ impl AesCbcDecryptReader { /// copy(&mut reader, &mut plaintext).unwrap(); /// ``` pub fn from(reader: R, key: &EncryptionKey) -> Result>> { - if key.len() != 32 { - return Err(BackupError::InvalidCryptoDataLength { + let key_array = <&Array>::try_from(key.as_slice()).map_err(|_| { + BackupError::InvalidCryptoDataLength { expected: 32, actual: key.len(), - }); - } + } + })?; // Wrap source in buffered reader to reduce syscalls let mut buf_reader = BufReader::with_capacity(STREAM_BUFFER_SIZE, reader); // Read first cipher block into lookahead buffer @@ -385,9 +386,8 @@ impl AesCbcDecryptReader { "Unexpected ciphertext length: {n}" ))); } - let iv = GenericArray::from_slice(&[0u8; 16]); - let key_ga = GenericArray::from_slice(key); - let cipher = Aes256CbcDec::new(key_ga, iv); + let iv: [u8; 16] = [0u8; 16]; + let cipher = Aes256CbcDec::new(key_array, &iv.into()); Ok(AesCbcDecryptReader { inner: buf_reader, cipher, @@ -422,14 +422,11 @@ impl Read for AesCbcDecryptReader { let n = self.inner.read(&mut chunk)?; if n == 0 { // Final block: decrypt & unpad last lookahead block - let mut tail = self.lookahead.to_vec(); - let pt = self - .cipher - .clone() - .decrypt_padded_mut::(&mut tail) - .map_err(|e| { - io::Error::new(io::ErrorKind::InvalidData, format!("Padding error: {e:?}")) - })?; + let mut block: Array = self.lookahead.into(); + self.cipher.decrypt_block(&mut block); + let pt = Pkcs7::unpad(&block).map_err(|e| { + io::Error::new(io::ErrorKind::InvalidData, format!("Padding error: {e:?}")) + })?; self.buf.clear(); self.buf.extend_from_slice(pt); self.buf_pos = 0; @@ -447,11 +444,16 @@ impl Read for AesCbcDecryptReader { } else { // Decrypt all except the last block for chaining/padding self.buf.clear(); - for i in 0..(num_blocks - 1) { - let start = i * 16; - let mut arr = GenericArray::clone_from_slice(&data[start..start + 16]); - self.cipher.decrypt_block_mut(&mut arr); - self.buf.extend_from_slice(&arr); + for chunk in data[..(num_blocks - 1) * 16].chunks_exact(16) { + let block = <&Array>::try_from(chunk).map_err(|e| { + io::Error::new( + io::ErrorKind::InvalidData, + format!("block conversion: {e}"), + ) + })?; + let mut block = *block; + self.cipher.decrypt_block(&mut block); + self.buf.extend_from_slice(&block); } // Update lookahead to last full block let last_start = (num_blocks - 1) * 16; @@ -469,9 +471,7 @@ impl Read for AesCbcDecryptReader { #[cfg(test)] mod tests { use super::*; - use aes::cipher::generic_array::GenericArray; - use aes::{Aes128, Aes192, Aes256}; - use aes_kw::Kek; + use aes_kw::{KwAes128, KwAes192, KwAes256}; #[test] fn test_derive_key_consistency() { @@ -496,16 +496,19 @@ mod tests { let mut wrapped = vec![0u8; plain.len() + 8]; match kek_bytes.len() { 16 => { - let kek = Kek::::new(GenericArray::from_slice(kek_bytes)); - kek.wrap(plain, &mut wrapped).unwrap(); + let key: [u8; 16] = kek_bytes.as_slice().try_into().unwrap(); + let kek = KwAes128::new(&key.into()); + kek.wrap_key(plain, &mut wrapped).unwrap(); } 24 => { - let kek = Kek::::new(GenericArray::from_slice(kek_bytes)); - kek.wrap(plain, &mut wrapped).unwrap(); + let key: [u8; 24] = kek_bytes.as_slice().try_into().unwrap(); + let kek = KwAes192::new(&key.into()); + kek.wrap_key(plain, &mut wrapped).unwrap(); } 32 => { - let kek = Kek::::new(GenericArray::from_slice(kek_bytes)); - kek.wrap(plain, &mut wrapped).unwrap(); + let key: [u8; 32] = kek_bytes.as_slice().try_into().unwrap(); + let kek = KwAes256::new(&key.into()); + kek.wrap_key(plain, &mut wrapped).unwrap(); } _ => panic!("Invalid KEK length"), }