diff --git a/gtests/common/testvectors/hpke-vectors.h b/gtests/common/testvectors/hpke-vectors.h index dd7b417b8a..afed3fea8c 100644 --- a/gtests/common/testvectors/hpke-vectors.h +++ b/gtests/common/testvectors/hpke-vectors.h @@ -52,48 +52,37 @@ const hpke_vector kHpkeTestVectors[] = { static_cast(1), static_cast(1), "4f6465206f6e2061204772656369616e2055726e", - "3067020100301406072a8648ce3d020106092b06010401da470f01044c304a" - "02010104208c490e5b0c7dbe0c6d2192484d2b7a0423b3b4544f2481095a9" - "9dbf238fb350fa1230321008a07563949fac6232936ed6f36c4fa735930ecd" - "eaef6734e314aeac35a56fd0a", - "3067020100301406072a8648ce3d020106092b06010401da470f01044c304a" - "02010104205a8aa0d2476b28521588e0c704b14db82cdd4970d340d293a957" - "6deaee9ec1c7a1230321008756e2580c07c1d2ffcb662f5fadc6d6ff13da85" - "abd7adfecf984aaa102c1269", + "3067020100301406072a8648ce3d020106092b06010401da470f01044c304a02010104206" + "cee2e2755790708a2a1be22667883a5e3f9ec52810404a0d889a0ed3e28de00a123032100" + "950897e0d37a8bdb0f2153edf5fa580a64b399c39fbb3d014f80983352a63617", + "3067020100301406072a8648ce3d020106092b06010401da470f01044c304a0201010420e" + "caf25b8485bcf40b9f013dbb96a6230f25733b8435bba0997a1dedbc7f78806a123032100" + "a5912b20892e36905bac635267e2353d58f8cc7525271a2bf57b9c48d2ec2c07", "", "", - "8a07563949fac6232936ed6f36c4fa735930ecdeaef6734e314aeac35a56fd0a", - "550ee0b7ec1ea2532f2e2bac87040a4c", - "2b855847756795a57229559a", + "950897e0d37a8bdb0f2153edf5fa580a64b399c39fbb3d014f80983352a63617", + "e20cee1bf5392ad2d3a442e231f187ae", + "5d99b2f03c452f7a9441933a", {// Encryptions {"4265617574792069732074727574682c20747275746820626561757479", "436f756e742d30", - "971ba65db526758ea30ae748cd769bc8d90579b62a037816057f24ce4274" - "16bd47c05ed1c2446ac8e19ec9ae79"}, + "9418f1ae06eddc43aa911032aed4a951754ee2286a786733761857f8d96a7ec8d852da9" + "3bc5eeab49623344aba"}, {"4265617574792069732074727574682c20747275746820626561757479", "436f756e742d31", - "f18f1ec397667ca069b9a6ee0bebf0890cd5caa34bb9875b3600ca0142cb" - "a774dd35f2aafd79a02a08ca5f2806"}, + "74d69c61899b9158bb50e95d92fbad106f612ea67c61b3c4bef65c8bf3dc18e17bf41ec" + "4c408688aae58358d0e"}, {"4265617574792069732074727574682c20747275746820626561757479", "436f756e742d32", - "51a8dea350fe6e753f743ec17c956de4cbdfa35f3018fc6a12752c51d137" - "2c5093959f18c7253da9c953c6cfbe"}}, + "e6602db9be05d81c4ab8fa621bc35993a7b759851075a34b3bffd257340011c70c9fa1f" + "5c11868a076fc3adb3b"}}, {// Exports - {"436f6e746578742d30", 32, - "0df04ac640d34a56561419bab20a68e6b7331070208004f89c7b973f4c47" - "2e92"}, - {"436f6e746578742d31", 32, - "723c2c8f80e6b827e72bd8e80973a801a05514afe3d4bc46e82e505dceb9" - "53aa"}, - {"436f6e746578742d32", 32, - "38010c7d5d81093a11b55e2403a258e9a195bcf066817b332dd996b0a9bc" - "bc9a"}, - {"436f6e746578742d33", 32, - "ebf6ab4c3186131de9b2c3c0bc3e2ad21dfcbc4efaf050cd0473f5b1535a" - "8b6d"}, - {"436f6e746578742d34", 32, - "c4823eeb3efd2d5216b2d3b16e542bf57470dc9b9ea9af6bce85b151a358" - "9d90"}}}, + {"", 32, + "be82c06bd83fd6edd74385de5a70859b9e03def4c7bb224a10cfae86087f8a25"}, + {"00", 32, + "82cbfd3c2b2db75e2311d457e569cf12b6387eb4309bca8e77adb2f2b599fc85"}, + {"54657374436f6e74657874", 32, + "c8387c1e6ec4f026c7f3577e3f29df51f46161295eec84c4f64a9174f7b64e4f"}}}, // A.1. DHKEM(X25519, HKDF-SHA256), HKDF-SHA256, AES-128-GCM, PSK mode {1, @@ -102,132 +91,153 @@ const hpke_vector kHpkeTestVectors[] = { static_cast(1), static_cast(1), "4f6465206f6e2061204772656369616e2055726e", - "3067020100301406072a8648ce3d020106092b06010401da470f01044c304a020" - "1010420e7d2b539792a48a24451303ccd0cfe77176b6cb06823c439edfd217458" - "a1398aa12303210008d39d3e7f9b586341b6004dafba9679d2bd9340066edb247" - "e3e919013efcd0f", - "3067020100301406072a8648ce3d020106092b06010401da470f01044c304a020" - "10104204b41ef269169090551fcea177ecdf622bca86d82298e21cd93119b804c" - "cc5eaba123032100a5c85773bed3a831e7096f7df4ff5d1d8bac48fc97bfac366" - "141efab91892a3a", - "5db3b80a81cb63ca59470c83414ef70a", + "3067020100301406072a8648ce3d020106092b06010401da470f01044c304a02010104204" + "c1feed23e15ec6a55b8457e0c0f42a3a1ab3ccc309b7cbb7ac6165fc657bd3ba123032100" + "f16fa9440b2cb36c855b4b82fb87e1c02ce656dd132f7a7aec739294b6912768", + "3067020100301406072a8648ce3d020106092b06010401da470f01044c304a02010104208" + "e5430f0d821407670e5e3f6eecc9f52b2cad27b15a5fad1f3d05359ae30d81ca123032100" + "13c789187a2dda71889e4b98dc5443624ae68f309cea91865561cfa207586e3a", + "0247fd33b913760fa1fa51e1892d9f307fbe65eb171e8132c2af18555a738b82", "456e6e796e20447572696e206172616e204d6f726961", - "08d39d3e7f9b586341b6004dafba9679d2bd9340066edb247e3e919013efcd0f", - "811e9b2d7a10f4f9d58786bf8a534ca6", - "b79b0c5a8c3808e238b10411", + "f16fa9440b2cb36c855b4b82fb87e1c02ce656dd132f7a7aec739294b6912768", + "70030b55bfb737d4f4355cf62302d281", + "746d5e6255902701c3e0b99f", {// Encryptions {"4265617574792069732074727574682c20747275746820626561757479", "436f756e742d30", - "fb68f911b4e4033d1547f646ea30c9cee987fb4b4a8c30918e5de6e96de32fc" - "63466f2fc05e09aeff552489741"}, + "63f7ed3d99e625d4a7373982b5f04daf0c3dfff39cac4b38eeb9d5c225cc3183bdbc91a" + "053db9b195319cc8c45"}, {"4265617574792069732074727574682c20747275746820626561757479", "436f756e742d31", - "85e7472fbb7e2341af35fb2a0795df9a85caa99a8f584056b11d452bc160470" - "672e297f9892ce2c5020e794ae1"}, + "65e7160f80fdf47893a5abe1edcff46c85899f04acb97882e194ce6d4fceec2dc4cb2d3" + "abe5d969880722859b2"}, {"4265617574792069732074727574682c20747275746820626561757479", "436f756e742d32", - "74229b7491102bcf94cf7633888bc48baa4e5a73cc544bfad4ff61585506fac" - "b44b359ade03c0b2b35c6430e4c"}}, + "915e08e6e340fca64982e90ad93490826bfb74af8f48062212c87105dad2b7569c83688" + "e564ed5862592b77cdc"}}, {// Exports - {"436f6e746578742d30", 32, - "bd292b132fae00243851451c3f3a87e9e11c3293c14d61b114b7e12e07245ffd"}, - {"436f6e746578742d31", 32, - "695de26bc9336caee01cb04826f6e224f4d2108066ab17fc18f0c993dce05f24"}, - {"436f6e746578742d32", 32, - "c53f26ef1bf4f5fd5469d807c418a0e103d035c76ccdbc6afb5bc42b24968f6c"}, - {"436f6e746578742d33", 32, - "8cea4a595dfe3de84644ca8ea7ea9401a345f0db29bb4beebc2c471afc602ec4"}, - {"436f6e746578742d34", 32, - "e6313f12f6c2054c69018f273211c54fcf2439d90173392eaa34b4caac929068"}}}, - - // A.2. DHKEM(X25519, HKDF-SHA256), HKDF-SHA256, ChaCha20Poly1305, Base mode + {"", 32, + "7c40ceb745e14d19fceeac6e4756c796957fe5ff28709198c3f8cbdb5d368fe1"}, + {"00", 32, + "1ef0fd07bd40326f1b88f3545c92969cff202ca7186b9fd1315241f93fcc2edf"}, + {"54657374436f6e74657874", 32, + "997368419db9490aa96c977cdd90bda8fd6234054d4add3d2f31aaaa2f8c1172"}}}, + // A.2. DHKEM(X25519, HKDF-SHA256), HKDF-SHA256, ChaCha20Poly1305, Base + // mode {2, static_cast(0), static_cast(32), static_cast(1), static_cast(3), "4f6465206f6e2061204772656369616e2055726e", - "3067020100301406072a8648ce3d020106092b06010401da470f01044c304a020" - "10104205006a9a0f0138b9b5d577ed4a67c4f795aee8fc146ac63d7a4167765be" - "3ad7dca123032100716281787b035b2fee90455d951fa70b3db6cc92f13bedfd7" - "58c3487994b7020", - "3067020100301406072a8648ce3d020106092b06010401da470f01044c304a020" - "101042062139576dcbf9878ccd56262d1b28dbea897821c03370d81971513cc74" - "aea3ffa1230321001ae26f65041b36ad69eb392c198bfd33df1c6ff17a910cb3e" - "49db7506b6a4e7f", + "3067020100301406072a8648ce3d020106092b06010401da470f01044c304a0201010420e" + "fda8f0538ce6ab9f165aae26e02ad96dcb1775b248267174aeb3d140e002ee3a123032100" + "1440805f4e60cbd34835baf0813c3071d17def1dbd8c04e75889bb2271d7823a", + "3067020100301406072a8648ce3d020106092b06010401da470f01044c304a02010104201" + "4365bb26500e7cf263720c4ab04bd45b8e146b4f724facd1fa01d58b63975e4a123032100" + "26147d5c2978bccc3cc03a4f9ac607560b5d83f852be4e9024f2cb7207d4c30e", "", "", - "716281787b035b2fee90455d951fa70b3db6cc92f13bedfd758c3487994b7020", - "1d5e71e2885ddadbcc479798cc65ea74d308f2a9e99c0cc7fe480adce66b5722", - "8354a7fcfef97d4bbef6d24e", + "1440805f4e60cbd34835baf0813c3071d17def1dbd8c04e75889bb2271d7823a", + "a17448a542d0d6d75e3b21be0a1f68607904b4802c6b19a7e7e90976aa00a5c8", + "6f6b832dba944a91e5684514", {// Encryptions {"4265617574792069732074727574682c20747275746820626561757479", "436f756e742d30", - "fa4632a400962c98143e58450e75d879365359afca81a5f5b5997c6555647ec" - "302045a80c57d3e2c2abe7e1ced"}, + "1b9ce69bd0e6b4242ac2dd841ef093fc9dfa9e684f81c2d1778fd3268ca5aa7d612cd87" + "f72acd2aeaee084dee2"}, {"4265617574792069732074727574682c20747275746820626561757479", "436f756e742d31", - "8313fcbf760714f5a93b6864820e48dcec3ddd476ad4408ff1c1a1f7bfb8cb8" - "699fada4a9e59bf8086eb1c0635"}, + "f041fb8de275b5319587269cb39190029906b9267eb5619b7bec8a5e0b3b3a0bead1696" + "17f2c4d45d028b1b654"}, {"4265617574792069732074727574682c20747275746820626561757479", "436f756e742d32", - "020f2856d95b85e1def9549bf327c484d327616f1e213045f117be4c287571a" - "b983958f74766cbc6f8197c8d8d"}}, + "0042c74002608a20e432ee9628e84cba76482aca29359e93d60067371be547355acca2c" + "271a2072b85a77a6237"}}, {// Exports - {"436f6e746578742d30", 32, - "22bbe971392c685b55e13544cdaf976f36b89dc1dbe1296c2884971a5aa9e331"}, - {"436f6e746578742d31", 32, - "5c0fa72053a2622d8999b726446db9ef743e725e2cb040afac2d83eae0d41981"}, - {"436f6e746578742d32", 32, - "72b0f9999fd37ac2b948a07dadd01132587501a5a9460d596c1f7383299a2442"}, - {"436f6e746578742d33", 32, - "73d2308ed5bdd63aacd236effa0db2d3a30742b6293a924d95a372e76d90486b"}, - {"436f6e746578742d34", 32, - "d4f8878dbc471935e86cdee08746e53837bbb4b6013003bebb0bc1cc3e074085"}}}, - - // A.2. DHKEM(X25519, HKDF-SHA256), HKDF-SHA256, ChaCha20Poly1305, PSK mode + {"", 32, + "996dc6fda1dc47e687613e0e221d64a3598e1ead9585177d22f230716569c04d"}, + {"00", 32, + "6d07b4e3e06ace3dc3f1b2a0826a0f896aa828769ff993c2e3829ae40325c27d"}, + {"54657374436f6e74657874", 32, + "bb69068c4f7767331512d375e4ab0ca0c6c51446040096ea0ae1cc3f9a3f54bd"}}}, + // A.2. DHKEM(X25519, HKDF-SHA256), HKDF-SHA256, ChaCha20Poly1305, PSK + // mode {3, static_cast(1), static_cast(32), static_cast(1), static_cast(3), "4f6465206f6e2061204772656369616e2055726e", - "3067020100301406072a8648ce3d020106092b06010401da470f01044c304a020" - "10104204bfdb62b95ae2a1f29f20ea49e24aa2673e0d240c6e967f668f55ed5de" - "e996dca123032100f4639297e3305b03d34dd5d86522ddc6ba11a608a0003670a" - "30734823cdd3763", - "3067020100301406072a8648ce3d020106092b06010401da470f01044c304a020" - "1010420a6ab4e1bb782d580d837843089d65ebe271a0ee9b5a951777cecf1293c" - "58c150a123032100c49b46ed73ecb7d3a6a3e44f54b8f00f9ab872b57dd79ded6" - "6d7231a14c64144", - "5db3b80a81cb63ca59470c83414ef70a", + "3067020100301406072a8648ce3d020106092b06010401da470f01044c304a0201010420d" + "b1c9dfba77e1e3b8687ea18af207cffca803bdd983f955376b8271ef9c78a46a123032100" + "8e4b29035c22b67b3a7a0f5a52f12b3ab17a9ae1f0c63b029137ba09f420224a", + "3067020100301406072a8648ce3d020106092b06010401da470f01044c304a02010104204" + "e335da3ec60e68c156586b8217de6801cb83b5a4de413645fcb112c00b2228ba123032100" + "94ea1227a357dfd3548aadb9ef19d9974add594871498e123390a8bcb4db5d51", + "0247fd33b913760fa1fa51e1892d9f307fbe65eb171e8132c2af18555a738b82", "456e6e796e20447572696e206172616e204d6f726961", - "f4639297e3305b03d34dd5d86522ddc6ba11a608a0003670a30734823cdd3763", - "396c06a52b39d0930594aa2c6944561cc1741f638557a12bef1c1cad349157c9", - "baa4ecf96b5d6d536d0d7210", + "8e4b29035c22b67b3a7a0f5a52f12b3ab17a9ae1f0c63b029137ba09f420224a", + "a603fe0f9897dc6ce042a467d6bd430a01cd679e930f1b5706ad425e4153496d", + "318e48afae42913a928146e6", {// Encryptions {"4265617574792069732074727574682c20747275746820626561757479", "436f756e742d30", - "f97ca72675b8199e8ffec65b4c200d901110b177b246f241b6f9716fb60b35b" - "32a6d452675534b591e8141468a"}, + "c87f8158a501c7a2f31708bbdba10f9c5ad035624c3153eeb028e65b82f41f38cbe1cd9" + "aafb10e502d328b83c1"}, {"4265617574792069732074727574682c20747275746820626561757479", "436f756e742d31", - "57796e2b9dd0ddf807f1a7cb5884dfc50e61468c4fd69fa03963731e51674ca" - "88fee94eeac3290734e1627ded6"}, + "aef7a0b0e3a58b177dac9628439b44d1e706724e265ab3b46d791612b51637342479ad9" + "45607b8b54112bd8c86"}, {"4265617574792069732074727574682c20747275746820626561757479", "436f756e742d32", - "b514150af1057151687d0036a9b4a3ad50fb186253f839d8433622baa85719e" - "d5d2532017a0ce7b9ca0007f276"}}, + "c00884a5c658213bd4381d65b54d93682692fef9408a6e437a97a904267727269b242d3" + "d81725ad8f0c764e082"}}, {// Exports - {"436f6e746578742d30", 32, - "735400cd9b9193daffe840f412074728ade6b1978e9ae27957aacd588dbd7c9e"}, - {"436f6e746578742d31", 32, - "cf4e351e1943d171ff2d88726f18160086ecbec52a8151dba8cf5ba0737a6097"}, - {"436f6e746578742d32", 32, - "8e23b44d4f23dd906d1c100580a670d171132c9786212c4ca2876a1541a84fae"}, - {"436f6e746578742d33", 32, - "56252a940ece53d4013eb619b444ee1d019a08eec427ded2b6dbf24be624a4a0"}, - {"436f6e746578742d34", 32, - "fc6cdca9ce8ab062401478ffd16ee1c07e2b15d7c781d4227f07c6043d937fad"}}}}; - + {"", 32, + "23c31ee2757bbecf105f74c90bf1e640b6ddc545dc8d80b1abbf2aa9dd1786ce"}, + {"00", 32, + "05af7597519945fe8443f7cb84cdb651a8dd18cd7bbbd65d31095d3c69c1257e"}, + {"54657374436f6e74657874", 32, + "5814619f842c7c328c9657854154e51b581c7bbd3b646bd773be67f93900a109"}}}, + // DHKEM(X25519, HKDF-SHA256), HKDF-SHA512, ChaCha20Poly1305, Base mode + // Tests KEM.hash != KDF.hash. + {4, + static_cast(0), + static_cast(32), + static_cast(3), + static_cast(3), + "4f6465206f6e2061204772656369616e2055726e", + "3067020100301406072a8648ce3d020106092b06010401da470f01044c304a02010104200" + "6e74abcc8b65671d1ef4a6cb273662c6a3b3ff6590852bfebc7bc94887f5c4ea123032100" + "de2746f66f3e14a3389f570e8f8cc1de4e39a89d1cbb445fad711d7acf407e15", + "3067020100301406072a8648ce3d020106092b06010401da470f01044c304a02010104202" + "dc14b2f31b233963f0a2d9a836072f29666fdea84a5893d30254deb9183e0a9a123032100" + "318f92c9e96142c4ce9a06ea04f7099698ee4160044f2db585d9e2b02abd6041", + "", + "", + "de2746f66f3e14a3389f570e8f8cc1de4e39a89d1cbb445fad711d7acf407e15", + "4a54adb318d8a420506b0473815a32c2b1923a936fa7c735c8a038a38fcc80d2", + "9c6d83a59628e7327d19a3d8", + {// Encryptions + {"4265617574792069732074727574682c20747275746820626561757479", + "436f756e742d30", + "59cbc98df2d7640598377e3184e07c008dea1c264c72a8414028715960ab6d6909a3110" + "e633a23baf8b9b5e2f1"}, + {"4265617574792069732074727574682c20747275746820626561757479", + "436f756e742d31", + "c9a4b68ea349eea9fdf499f7577c9325e9b76f24308a81ac5dfbbee3489dd41c85d7fb3" + "5e585859ea5c790f155"}, + {"4265617574792069732074727574682c20747275746820626561757479", + "436f756e742d32", + "5d9f717b192b43bea1f6bd25ee63d7b88b06019132c31a4e262a4c1d4f01c7bd70d00df" + "0e2f858cf654ae86447"}}, + {// Exports + {"", 32, + "97b0ac016b9dedb5f115cf6fd24b927f8e75b48a2ab6069efe7fec6a18ff4272"}, + {"00", 32, + "c994b47854104e476d9e47bb15f9fb66f4879f68bc89a4cfccc259e80a30c913"}, + {"54657374436f6e74657874", 32, + "9199e5beeda45397b1bbee3dd13ad1afbd2963f83d9e5ebdf1e23b6c7e012317"}}}, +}; #endif // hpke_vectors_h__ diff --git a/gtests/pk11_gtest/pk11_hpke_unittest.cc b/gtests/pk11_gtest/pk11_hpke_unittest.cc index c8220621e2..26385f144d 100644 --- a/gtests/pk11_gtest/pk11_hpke_unittest.cc +++ b/gtests/pk11_gtest/pk11_hpke_unittest.cc @@ -22,36 +22,8 @@ namespace nss_test { #ifdef NSS_ENABLE_DRAFT_HPKE #include "cpputil.h" -class Pkcs11HpkeTest : public ::testing::TestWithParam { +class HpkeTest { protected: - void ReadVector(const hpke_vector &vec) { - ScopedPK11SymKey vec_psk; - if (!vec.psk.empty()) { - ASSERT_FALSE(vec.psk_id.empty()); - vec_psk_id = hex_string_to_bytes(vec.psk_id); - - std::vector psk_bytes = hex_string_to_bytes(vec.psk); - SECItem psk_item = {siBuffer, toUcharPtr(psk_bytes.data()), - static_cast(psk_bytes.size())}; - ScopedPK11SlotInfo slot(PK11_GetInternalSlot()); - ASSERT_TRUE(slot); - PK11SymKey *psk_key = - PK11_ImportSymKey(slot.get(), CKM_HKDF_KEY_GEN, PK11_OriginUnwrap, - CKA_WRAP, &psk_item, nullptr); - ASSERT_NE(nullptr, psk_key); - vec_psk_key.reset(psk_key); - } - - vec_pkcs8_r = hex_string_to_bytes(vec.pkcs8_r); - vec_pkcs8_e = hex_string_to_bytes(vec.pkcs8_e); - vec_key = hex_string_to_bytes(vec.key); - vec_nonce = hex_string_to_bytes(vec.nonce); - vec_enc = hex_string_to_bytes(vec.enc); - vec_info = hex_string_to_bytes(vec.info); - vec_encryptions = vec.encrypt_vecs; - vec_exports = vec.export_vecs; - } - void CheckEquality(const std::vector &expected, SECItem *actual) { if (!actual) { EXPECT_TRUE(expected.empty()); @@ -102,55 +74,159 @@ class Pkcs11HpkeTest : public ::testing::TestWithParam { CheckEquality(expected_vec, actual); } - void SetupS(const ScopedHpkeContext &cx, const ScopedSECKEYPublicKey &pkE, - const ScopedSECKEYPrivateKey &skE, - const ScopedSECKEYPublicKey &pkR, - const std::vector &info) { - SECItem info_item = {siBuffer, toUcharPtr(vec_info.data()), - static_cast(vec_info.size())}; - SECStatus rv = - PK11_HPKE_SetupS(cx.get(), pkE.get(), skE.get(), pkR.get(), &info_item); - EXPECT_EQ(SECSuccess, rv); - } - - void SetupR(const ScopedHpkeContext &cx, const ScopedSECKEYPublicKey &pkR, - const ScopedSECKEYPrivateKey &skR, - const std::vector &enc, - const std::vector &info) { - SECItem enc_item = {siBuffer, toUcharPtr(enc.data()), - static_cast(enc.size())}; - SECItem info_item = {siBuffer, toUcharPtr(vec_info.data()), - static_cast(vec_info.size())}; - SECStatus rv = - PK11_HPKE_SetupR(cx.get(), pkR.get(), skR.get(), &enc_item, &info_item); - EXPECT_EQ(SECSuccess, rv); - } - void Seal(const ScopedHpkeContext &cx, std::vector &aad_vec, - std::vector &pt_vec, SECItem **out_ct) { + std::vector &pt_vec, std::vector &out_sealed) { SECItem aad_item = {siBuffer, toUcharPtr(aad_vec.data()), static_cast(aad_vec.size())}; SECItem pt_item = {siBuffer, toUcharPtr(pt_vec.data()), static_cast(pt_vec.size())}; - SECStatus rv = PK11_HPKE_Seal(cx.get(), &aad_item, &pt_item, out_ct); - EXPECT_EQ(SECSuccess, rv); + SECItem *sealed_item = nullptr; + EXPECT_EQ(SECSuccess, + PK11_HPKE_Seal(cx.get(), &aad_item, &pt_item, &sealed_item)); + ASSERT_NE(nullptr, sealed_item); + ScopedSECItem sealed(sealed_item); + out_sealed.assign(sealed->data, sealed->data + sealed->len); } void Open(const ScopedHpkeContext &cx, std::vector &aad_vec, - std::vector &ct_vec, SECItem **out_pt) { + std::vector &ct_vec, std::vector &out_opened) { SECItem aad_item = {siBuffer, toUcharPtr(aad_vec.data()), static_cast(aad_vec.size())}; SECItem ct_item = {siBuffer, toUcharPtr(ct_vec.data()), static_cast(ct_vec.size())}; - SECStatus rv = PK11_HPKE_Open(cx.get(), &aad_item, &ct_item, out_pt); - EXPECT_EQ(SECSuccess, rv); + SECItem *opened_item = nullptr; + EXPECT_EQ(SECSuccess, + PK11_HPKE_Open(cx.get(), &aad_item, &ct_item, &opened_item)); + ASSERT_NE(nullptr, opened_item); + ScopedSECItem opened(opened_item); + out_opened.assign(opened->data, opened->data + opened->len); + } + + void SealOpen(const ScopedHpkeContext &sender, + const ScopedHpkeContext &receiver, std::vector &msg, + std::vector &aad, const std::vector *expect) { + std::vector sealed; + std::vector opened; + Seal(sender, aad, msg, sealed); + if (expect) { + EXPECT_EQ(*expect, sealed); + } + Open(receiver, aad, sealed, opened); + EXPECT_EQ(msg, opened); + } + + bool GenerateKeyPair(ScopedSECKEYPublicKey &pub_key, + ScopedSECKEYPrivateKey &priv_key) { + ScopedPK11SlotInfo slot(PK11_GetInternalSlot()); + if (!slot) { + ADD_FAILURE() << "Couldn't get slot"; + return false; + } + + unsigned char param_buf[65]; + SECItem ecdsa_params = {siBuffer, param_buf, sizeof(param_buf)}; + SECOidData *oid_data = SECOID_FindOIDByTag(SEC_OID_CURVE25519); + if (!oid_data) { + ADD_FAILURE() << "Couldn't get oid_data"; + return false; + } + ecdsa_params.data[0] = SEC_ASN1_OBJECT_ID; + ecdsa_params.data[1] = oid_data->oid.len; + memcpy(ecdsa_params.data + 2, oid_data->oid.data, oid_data->oid.len); + ecdsa_params.len = oid_data->oid.len + 2; + + SECKEYPublicKey *pub_tmp; + SECKEYPrivateKey *priv_tmp; + priv_tmp = + PK11_GenerateKeyPair(slot.get(), CKM_EC_KEY_PAIR_GEN, &ecdsa_params, + &pub_tmp, PR_FALSE, PR_TRUE, nullptr); + if (!pub_tmp || !priv_tmp) { + ADD_FAILURE() << "PK11_GenerateKeyPair failed"; + return false; + } + + pub_key.reset(pub_tmp); + priv_key.reset(priv_tmp); + return true; + } + + void SetUpEphemeralContexts(ScopedHpkeContext &sender, + ScopedHpkeContext &receiver, + HpkeModeId mode = HpkeModeBase, + HpkeKemId kem = HpkeDhKemX25519Sha256, + HpkeKdfId kdf = HpkeKdfHkdfSha256, + HpkeAeadId aead = HpkeAeadAes128Gcm) { + // Generate a PSK, if the mode calls for it. + PRUint8 psk_id_buf[] = {'p', 's', 'k', '-', 'i', 'd'}; + SECItem psk_id = {siBuffer, psk_id_buf, sizeof(psk_id_buf)}; + SECItem *psk_id_item = (mode == HpkeModePsk) ? &psk_id : nullptr; + ScopedPK11SymKey psk; + if (mode == HpkeModePsk) { + ScopedPK11SlotInfo slot(PK11_GetInternalSlot()); + ASSERT_TRUE(slot); + PK11SymKey *tmp_psk = + PK11_KeyGen(slot.get(), CKM_HKDF_DERIVE, nullptr, 16, nullptr); + ASSERT_NE(nullptr, tmp_psk); + psk.reset(tmp_psk); + } + + std::vector info = {'t', 'e', 's', 't', '-', 'i', 'n', 'f', 'o'}; + SECItem info_item = {siBuffer, info.data(), + static_cast(info.size())}; + sender.reset(PK11_HPKE_NewContext(kem, kdf, aead, psk.get(), psk_id_item)); + receiver.reset( + PK11_HPKE_NewContext(kem, kdf, aead, psk.get(), psk_id_item)); + ASSERT_TRUE(sender); + ASSERT_TRUE(receiver); + + ScopedSECKEYPublicKey pub_key_r; + ScopedSECKEYPrivateKey priv_key_r; + ASSERT_TRUE(GenerateKeyPair(pub_key_r, priv_key_r)); + EXPECT_EQ(SECSuccess, PK11_HPKE_SetupS(sender.get(), nullptr, nullptr, + pub_key_r.get(), &info_item)); + + const SECItem *enc = PK11_HPKE_GetEncapPubKey(sender.get()); + EXPECT_NE(nullptr, enc); + EXPECT_EQ(SECSuccess, PK11_HPKE_SetupR( + receiver.get(), pub_key_r.get(), priv_key_r.get(), + const_cast(enc), &info_item)); + } +}; + +class TestVectors : public HpkeTest, + public ::testing::TestWithParam { + protected: + void ReadVector(const hpke_vector &vec) { + ScopedPK11SymKey vec_psk; + if (!vec.psk.empty()) { + ASSERT_FALSE(vec.psk_id.empty()); + vec_psk_id = hex_string_to_bytes(vec.psk_id); + + std::vector psk_bytes = hex_string_to_bytes(vec.psk); + SECItem psk_item = {siBuffer, toUcharPtr(psk_bytes.data()), + static_cast(psk_bytes.size())}; + ScopedPK11SlotInfo slot(PK11_GetInternalSlot()); + ASSERT_TRUE(slot); + PK11SymKey *psk_key = + PK11_ImportSymKey(slot.get(), CKM_HKDF_KEY_GEN, PK11_OriginUnwrap, + CKA_WRAP, &psk_item, nullptr); + ASSERT_NE(nullptr, psk_key); + vec_psk_key.reset(psk_key); + } + + vec_pkcs8_r = hex_string_to_bytes(vec.pkcs8_r); + vec_pkcs8_e = hex_string_to_bytes(vec.pkcs8_e); + vec_key = hex_string_to_bytes(vec.key); + vec_nonce = hex_string_to_bytes(vec.nonce); + vec_enc = hex_string_to_bytes(vec.enc); + vec_info = hex_string_to_bytes(vec.info); + vec_encryptions = vec.encrypt_vecs; + vec_exports = vec.export_vecs; } void TestExports(const ScopedHpkeContext &sender, const ScopedHpkeContext &receiver) { - SECStatus rv; - for (auto &vec : vec_exports) { std::vector context = hex_string_to_bytes(vec.ctxt); std::vector expected = hex_string_to_bytes(vec.exported); @@ -158,12 +234,11 @@ class Pkcs11HpkeTest : public ::testing::TestWithParam { static_cast(context.size())}; PK11SymKey *actual_r = nullptr; PK11SymKey *actual_s = nullptr; - rv = PK11_HPKE_ExportSecret(sender.get(), &context_item, vec.len, - &actual_s); - ASSERT_EQ(SECSuccess, rv); - rv = PK11_HPKE_ExportSecret(receiver.get(), &context_item, vec.len, - &actual_r); - ASSERT_EQ(SECSuccess, rv); + ASSERT_EQ(SECSuccess, PK11_HPKE_ExportSecret(sender.get(), &context_item, + vec.len, &actual_s)); + ASSERT_EQ(SECSuccess, + PK11_HPKE_ExportSecret(receiver.get(), &context_item, vec.len, + &actual_r)); ScopedPK11SymKey scoped_act_s(actual_s); ScopedPK11SymKey scoped_act_r(actual_r); CheckEquality(expected, scoped_act_s.get()); @@ -177,15 +252,7 @@ class Pkcs11HpkeTest : public ::testing::TestWithParam { std::vector msg = hex_string_to_bytes(enc_vec.pt); std::vector aad = hex_string_to_bytes(enc_vec.aad); std::vector expect_ct = hex_string_to_bytes(enc_vec.ct); - SECItem *act_ct = nullptr; - Seal(sender, aad, msg, &act_ct); - CheckEquality(expect_ct, act_ct); - ScopedSECItem scoped_ct(act_ct); - - SECItem *act_pt = nullptr; - Open(receiver, aad, expect_ct, &act_pt); - CheckEquality(msg, act_pt); - ScopedSECItem scoped_pt(act_pt); + SealOpen(sender, receiver, msg, aad, &expect_ct); } } @@ -200,10 +267,9 @@ class Pkcs11HpkeTest : public ::testing::TestWithParam { SECItem pkcs8_e_item = {siBuffer, toUcharPtr(vec_pkcs8_e.data()), static_cast(vec_pkcs8_e.size())}; SECKEYPrivateKey *sk_e = nullptr; - SECStatus rv = PK11_ImportDERPrivateKeyInfoAndReturnKey( - slot.get(), &pkcs8_e_item, nullptr, nullptr, false, false, KU_ALL, - &sk_e, nullptr); - EXPECT_EQ(SECSuccess, rv); + EXPECT_EQ(SECSuccess, PK11_ImportDERPrivateKeyInfoAndReturnKey( + slot.get(), &pkcs8_e_item, nullptr, nullptr, + false, false, KU_ALL, &sk_e, nullptr)); skE_derived.reset(sk_e); SECKEYPublicKey *pk_e = SECKEY_ConvertToPublicKey(skE_derived.get()); ASSERT_NE(nullptr, pk_e); @@ -212,64 +278,49 @@ class Pkcs11HpkeTest : public ::testing::TestWithParam { SECItem pkcs8_r_item = {siBuffer, toUcharPtr(vec_pkcs8_r.data()), static_cast(vec_pkcs8_r.size())}; SECKEYPrivateKey *sk_r = nullptr; - rv = PK11_ImportDERPrivateKeyInfoAndReturnKey( - slot.get(), &pkcs8_r_item, nullptr, nullptr, false, false, KU_ALL, - &sk_r, nullptr); - EXPECT_EQ(SECSuccess, rv); + EXPECT_EQ(SECSuccess, PK11_ImportDERPrivateKeyInfoAndReturnKey( + slot.get(), &pkcs8_r_item, nullptr, nullptr, + false, false, KU_ALL, &sk_r, nullptr)); skR_derived.reset(sk_r); SECKEYPublicKey *pk_r = SECKEY_ConvertToPublicKey(skR_derived.get()); ASSERT_NE(nullptr, pk_r); pkR_derived.reset(pk_r); } + void SetupS(const ScopedHpkeContext &cx, const ScopedSECKEYPublicKey &pkE, + const ScopedSECKEYPrivateKey &skE, + const ScopedSECKEYPublicKey &pkR, + const std::vector &info) { + SECItem info_item = {siBuffer, toUcharPtr(vec_info.data()), + static_cast(vec_info.size())}; + EXPECT_EQ(SECSuccess, PK11_HPKE_SetupS(cx.get(), pkE.get(), skE.get(), + pkR.get(), &info_item)); + } + + void SetupR(const ScopedHpkeContext &cx, const ScopedSECKEYPublicKey &pkR, + const ScopedSECKEYPrivateKey &skR, + const std::vector &enc, + const std::vector &info) { + SECItem enc_item = {siBuffer, toUcharPtr(enc.data()), + static_cast(enc.size())}; + SECItem info_item = {siBuffer, toUcharPtr(vec_info.data()), + static_cast(vec_info.size())}; + EXPECT_EQ(SECSuccess, PK11_HPKE_SetupR(cx.get(), pkR.get(), skR.get(), + &enc_item, &info_item)); + } + void SetupSenderReceiver(const ScopedHpkeContext &sender, const ScopedHpkeContext &receiver) { SetupS(sender, pkE_derived, skE_derived, pkR_derived, vec_info); uint8_t buf[32]; // Curve25519 only, fixed size. SECItem encap_item = {siBuffer, const_cast(buf), sizeof(buf)}; - SECStatus rv = PK11_HPKE_Serialize(pkE_derived.get(), encap_item.data, - &encap_item.len, encap_item.len); - ASSERT_EQ(SECSuccess, rv); + ASSERT_EQ(SECSuccess, + PK11_HPKE_Serialize(pkE_derived.get(), encap_item.data, + &encap_item.len, encap_item.len)); CheckEquality(vec_enc, &encap_item); SetupR(receiver, pkR_derived, skR_derived, vec_enc, vec_info); } - bool GenerateKeyPair(ScopedSECKEYPublicKey &pub_key, - ScopedSECKEYPrivateKey &priv_key) { - unsigned char param_buf[65]; - - ScopedPK11SlotInfo slot(PK11_GetInternalSlot()); - if (!slot) { - ADD_FAILURE() << "Couldn't get slot"; - return false; - } - - SECItem ecdsa_params = {siBuffer, param_buf, sizeof(param_buf)}; - SECOidData *oid_data = SECOID_FindOIDByTag(SEC_OID_CURVE25519); - if (!oid_data) { - ADD_FAILURE() << "Couldn't get oid_data"; - return false; - } - - ecdsa_params.data[0] = SEC_ASN1_OBJECT_ID; - ecdsa_params.data[1] = oid_data->oid.len; - memcpy(ecdsa_params.data + 2, oid_data->oid.data, oid_data->oid.len); - ecdsa_params.len = oid_data->oid.len + 2; - SECKEYPublicKey *pub_tmp; - SECKEYPrivateKey *priv_tmp; - priv_tmp = - PK11_GenerateKeyPair(slot.get(), CKM_EC_KEY_PAIR_GEN, &ecdsa_params, - &pub_tmp, PR_FALSE, PR_TRUE, nullptr); - if (!pub_tmp || !priv_tmp) { - ADD_FAILURE() << "PK11_GenerateKeyPair failed"; - return false; - } - - pub_key.reset(pub_tmp); - priv_key.reset(priv_tmp); - return true; - } - void RunTestVector(const hpke_vector &vec) { ReadVector(vec); SECItem psk_id_item = {siBuffer, toUcharPtr(vec_psk_id.data()), @@ -307,12 +358,31 @@ class Pkcs11HpkeTest : public ::testing::TestWithParam { ScopedSECKEYPrivateKey skR_derived; }; -TEST_P(Pkcs11HpkeTest, TestVectors) { RunTestVector(GetParam()); } +TEST_P(TestVectors, TestVectors) { RunTestVector(GetParam()); } -INSTANTIATE_TEST_SUITE_P(Pkcs11HpkeTests, Pkcs11HpkeTest, +INSTANTIATE_TEST_SUITE_P(Pk11Hpke, TestVectors, ::testing::ValuesIn(kHpkeTestVectors)); -TEST_F(Pkcs11HpkeTest, BadEncapsulatedPubKey) { +class ModeParameterizedTest + : public HpkeTest, + public ::testing::TestWithParam< + std::tuple> {}; + +static const HpkeModeId kHpkeModesAll[] = {HpkeModeBase, HpkeModePsk}; +static const HpkeKemId kHpkeKemIdsAll[] = {HpkeDhKemX25519Sha256}; +static const HpkeKdfId kHpkeKdfIdsAll[] = {HpkeKdfHkdfSha256, HpkeKdfHkdfSha384, + HpkeKdfHkdfSha512}; +static const HpkeAeadId kHpkeAeadIdsAll[] = {HpkeAeadAes128Gcm, + HpkeAeadChaCha20Poly1305}; + +INSTANTIATE_TEST_SUITE_P( + Pk11Hpke, ModeParameterizedTest, + ::testing::Combine(::testing::ValuesIn(kHpkeModesAll), + ::testing::ValuesIn(kHpkeKemIdsAll), + ::testing::ValuesIn(kHpkeKdfIdsAll), + ::testing::ValuesIn(kHpkeAeadIdsAll))); + +TEST_F(ModeParameterizedTest, BadEncapsulatedPubKey) { ScopedHpkeContext sender( PK11_HPKE_NewContext(HpkeDhKemX25519Sha256, HpkeKdfHkdfSha256, HpkeAeadAes128Gcm, nullptr, nullptr)); @@ -331,157 +401,112 @@ TEST_F(Pkcs11HpkeTest, BadEncapsulatedPubKey) { ASSERT_TRUE(GenerateKeyPair(pub_key, priv_key)); // Decapsulating an empty buffer should fail. - SECStatus rv = - PK11_HPKE_Deserialize(sender.get(), empty.data, empty.len, &tmp_pub_key); - EXPECT_EQ(SECFailure, rv); + EXPECT_EQ(SECFailure, PK11_HPKE_Deserialize(sender.get(), empty.data, + empty.len, &tmp_pub_key)); EXPECT_EQ(SEC_ERROR_INVALID_ARGS, PORT_GetError()); - // Decapsulating anything else will succeed, but the setup will fail. - rv = PK11_HPKE_Deserialize(sender.get(), short_encap.data, short_encap.len, - &tmp_pub_key); + // Decapsulating anything short will succeed, but the setup will fail. + EXPECT_EQ(SECSuccess, PK11_HPKE_Deserialize(sender.get(), short_encap.data, + short_encap.len, &tmp_pub_key)); ScopedSECKEYPublicKey bad_pub_key(tmp_pub_key); - EXPECT_EQ(SECSuccess, rv); - rv = PK11_HPKE_SetupS(receiver.get(), pub_key.get(), priv_key.get(), - bad_pub_key.get(), &empty); - EXPECT_EQ(SECFailure, rv); + EXPECT_EQ(SECFailure, + PK11_HPKE_SetupS(receiver.get(), pub_key.get(), priv_key.get(), + bad_pub_key.get(), &empty)); EXPECT_EQ(SEC_ERROR_INVALID_KEY, PORT_GetError()); // Test the same for a receiver. - rv = PK11_HPKE_SetupR(sender.get(), pub_key.get(), priv_key.get(), &empty, - &empty); - EXPECT_EQ(SECFailure, rv); + EXPECT_EQ(SECFailure, PK11_HPKE_SetupR(sender.get(), pub_key.get(), + priv_key.get(), &empty, &empty)); EXPECT_EQ(SEC_ERROR_INVALID_ARGS, PORT_GetError()); - - rv = PK11_HPKE_SetupR(sender.get(), pub_key.get(), priv_key.get(), - &short_encap, &empty); - EXPECT_EQ(SECFailure, rv); + EXPECT_EQ(SECFailure, PK11_HPKE_SetupR(sender.get(), pub_key.get(), + priv_key.get(), &short_encap, &empty)); EXPECT_EQ(SEC_ERROR_INVALID_KEY, PORT_GetError()); // Encapsulated key too long - rv = PK11_HPKE_Deserialize(sender.get(), long_encap.data, long_encap.len, - &tmp_pub_key); + EXPECT_EQ(SECSuccess, PK11_HPKE_Deserialize(sender.get(), long_encap.data, + long_encap.len, &tmp_pub_key)); bad_pub_key.reset(tmp_pub_key); - EXPECT_EQ(SECSuccess, rv); - - rv = PK11_HPKE_SetupS(receiver.get(), pub_key.get(), priv_key.get(), - bad_pub_key.get(), &empty); - EXPECT_EQ(SECFailure, rv); + EXPECT_EQ(SECFailure, + PK11_HPKE_SetupS(receiver.get(), pub_key.get(), priv_key.get(), + bad_pub_key.get(), &empty)); EXPECT_EQ(SEC_ERROR_INVALID_ARGS, PORT_GetError()); - rv = PK11_HPKE_SetupR(sender.get(), pub_key.get(), priv_key.get(), - &long_encap, &empty); - EXPECT_EQ(SECFailure, rv); + EXPECT_EQ(SECFailure, PK11_HPKE_SetupR(sender.get(), pub_key.get(), + priv_key.get(), &long_encap, &empty)); EXPECT_EQ(SEC_ERROR_INVALID_ARGS, PORT_GetError()); } -// Vectors used fixed keypairs on each end. Make sure the -// ephemeral (particularly sender) path works. -TEST_F(Pkcs11HpkeTest, EphemeralKeys) { - unsigned char info[] = {"info"}; - unsigned char msg[] = {"secret"}; - unsigned char aad[] = {"aad"}; - SECItem info_item = {siBuffer, info, sizeof(info)}; - SECItem msg_item = {siBuffer, msg, sizeof(msg)}; - SECItem aad_item = {siBuffer, aad, sizeof(aad)}; - - ScopedHpkeContext sender( - PK11_HPKE_NewContext(HpkeDhKemX25519Sha256, HpkeKdfHkdfSha256, - HpkeAeadAes128Gcm, nullptr, nullptr)); - ScopedHpkeContext receiver( - PK11_HPKE_NewContext(HpkeDhKemX25519Sha256, HpkeKdfHkdfSha256, - HpkeAeadAes128Gcm, nullptr, nullptr)); - ASSERT_TRUE(sender); - ASSERT_TRUE(receiver); - - ScopedSECKEYPublicKey pub_key_r; - ScopedSECKEYPrivateKey priv_key_r; - ASSERT_TRUE(GenerateKeyPair(pub_key_r, priv_key_r)); - - SECStatus rv = PK11_HPKE_SetupS(sender.get(), nullptr, nullptr, - pub_key_r.get(), &info_item); - EXPECT_EQ(SECSuccess, rv); - - const SECItem *enc = PK11_HPKE_GetEncapPubKey(sender.get()); - EXPECT_NE(nullptr, enc); - rv = PK11_HPKE_SetupR(receiver.get(), pub_key_r.get(), priv_key_r.get(), - const_cast(enc), &info_item); - EXPECT_EQ(SECSuccess, rv); +TEST_P(ModeParameterizedTest, EphemeralKeys) { + std::vector msg = {'s', 'e', 'c', 'r', 'e', 't'}; + std::vector aad = {'a', 'a', 'd'}; + SECItem msg_item = {siBuffer, msg.data(), + static_cast(msg.size())}; + SECItem aad_item = {siBuffer, aad.data(), + static_cast(aad.size())}; + ScopedHpkeContext sender; + ScopedHpkeContext receiver; + SetUpEphemeralContexts(sender, receiver, std::get<0>(GetParam()), + std::get<1>(GetParam()), std::get<2>(GetParam()), + std::get<3>(GetParam())); + + SealOpen(sender, receiver, msg, aad, nullptr); + // Seal for negative tests SECItem *tmp_sealed = nullptr; - rv = PK11_HPKE_Seal(sender.get(), &aad_item, &msg_item, &tmp_sealed); - EXPECT_EQ(SECSuccess, rv); - ScopedSECItem sealed(tmp_sealed); - SECItem *tmp_unsealed = nullptr; - rv = PK11_HPKE_Open(receiver.get(), &aad_item, sealed.get(), &tmp_unsealed); - EXPECT_EQ(SECSuccess, rv); - CheckEquality(&msg_item, tmp_unsealed); - ScopedSECItem unsealed(tmp_unsealed); - - // Once more - tmp_sealed = nullptr; - rv = PK11_HPKE_Seal(sender.get(), &aad_item, &msg_item, &tmp_sealed); - EXPECT_EQ(SECSuccess, rv); - ASSERT_NE(nullptr, sealed); - sealed.reset(tmp_sealed); - tmp_unsealed = nullptr; - rv = PK11_HPKE_Open(receiver.get(), &aad_item, sealed.get(), &tmp_unsealed); - EXPECT_EQ(SECSuccess, rv); - CheckEquality(&msg_item, tmp_unsealed); - unsealed.reset(tmp_unsealed); - - // Seal for negative tests - tmp_sealed = nullptr; - tmp_unsealed = nullptr; - rv = PK11_HPKE_Seal(sender.get(), &aad_item, &msg_item, &tmp_sealed); - EXPECT_EQ(SECSuccess, rv); - ASSERT_NE(nullptr, sealed); - sealed.reset(tmp_sealed); + EXPECT_EQ(SECSuccess, + PK11_HPKE_Seal(sender.get(), &aad_item, &msg_item, &tmp_sealed)); + ASSERT_NE(nullptr, tmp_sealed); + ScopedSECItem sealed(tmp_sealed); // Drop AAD - rv = PK11_HPKE_Open(receiver.get(), nullptr, sealed.get(), &tmp_unsealed); - EXPECT_EQ(SECFailure, rv); + EXPECT_EQ(SECFailure, PK11_HPKE_Open(receiver.get(), nullptr, sealed.get(), + &tmp_unsealed)); + EXPECT_EQ(SEC_ERROR_BAD_DATA, PORT_GetError()); EXPECT_EQ(nullptr, tmp_unsealed); // Modify AAD aad_item.data[0] ^= 0xff; - rv = PK11_HPKE_Open(receiver.get(), &aad_item, sealed.get(), &tmp_unsealed); - EXPECT_EQ(SECFailure, rv); + EXPECT_EQ(SECFailure, PK11_HPKE_Open(receiver.get(), &aad_item, sealed.get(), + &tmp_unsealed)); + EXPECT_EQ(SEC_ERROR_BAD_DATA, PORT_GetError()); EXPECT_EQ(nullptr, tmp_unsealed); aad_item.data[0] ^= 0xff; // Modify ciphertext sealed->data[0] ^= 0xff; - rv = PK11_HPKE_Open(receiver.get(), &aad_item, sealed.get(), &tmp_unsealed); - EXPECT_EQ(SECFailure, rv); + EXPECT_EQ(SECFailure, PK11_HPKE_Open(receiver.get(), &aad_item, sealed.get(), + &tmp_unsealed)); + EXPECT_EQ(SEC_ERROR_BAD_DATA, PORT_GetError()); EXPECT_EQ(nullptr, tmp_unsealed); sealed->data[0] ^= 0xff; - rv = PK11_HPKE_Open(receiver.get(), &aad_item, sealed.get(), &tmp_unsealed); - EXPECT_EQ(SECSuccess, rv); + EXPECT_EQ(SECSuccess, PK11_HPKE_Open(receiver.get(), &aad_item, sealed.get(), + &tmp_unsealed)); EXPECT_NE(nullptr, tmp_unsealed); - unsealed.reset(tmp_unsealed); + ScopedSECItem unsealed(tmp_unsealed); + CheckEquality(&msg_item, unsealed.get()); } -TEST_F(Pkcs11HpkeTest, InvalidContextParams) { +TEST_F(ModeParameterizedTest, InvalidContextParams) { HpkeContext *cx = - PK11_HPKE_NewContext(static_cast(1), HpkeKdfHkdfSha256, + PK11_HPKE_NewContext(static_cast(0xff), HpkeKdfHkdfSha256, HpkeAeadChaCha20Poly1305, nullptr, nullptr); EXPECT_EQ(nullptr, cx); EXPECT_EQ(SEC_ERROR_INVALID_ARGS, PORT_GetError()); - cx = PK11_HPKE_NewContext(HpkeDhKemX25519Sha256, static_cast(2), + cx = PK11_HPKE_NewContext(HpkeDhKemX25519Sha256, static_cast(0xff), HpkeAeadChaCha20Poly1305, nullptr, nullptr); EXPECT_EQ(nullptr, cx); EXPECT_EQ(SEC_ERROR_INVALID_ARGS, PORT_GetError()); cx = PK11_HPKE_NewContext(HpkeDhKemX25519Sha256, HpkeKdfHkdfSha256, - static_cast(4), nullptr, nullptr); + static_cast(0xff), nullptr, nullptr); EXPECT_EQ(nullptr, cx); EXPECT_EQ(SEC_ERROR_INVALID_ARGS, PORT_GetError()); } -TEST_F(Pkcs11HpkeTest, InvalidReceiverKeyType) { +TEST_F(ModeParameterizedTest, InvalidReceiverKeyType) { ScopedHpkeContext sender( PK11_HPKE_NewContext(HpkeDhKemX25519Sha256, HpkeKdfHkdfSha256, HpkeAeadChaCha20Poly1305, nullptr, nullptr)); @@ -507,9 +532,8 @@ TEST_F(Pkcs11HpkeTest, InvalidReceiverKeyType) { pub_key.reset(pub_tmp); SECItem info_item = {siBuffer, nullptr, 0}; - SECStatus rv = PK11_HPKE_SetupS(sender.get(), nullptr, nullptr, pub_key.get(), - &info_item); - EXPECT_EQ(SECFailure, rv); + EXPECT_EQ(SECFailure, PK11_HPKE_SetupS(sender.get(), nullptr, nullptr, + pub_key.get(), &info_item)); EXPECT_EQ(SEC_ERROR_BAD_KEY, PORT_GetError()); // Try with an unexpected curve @@ -529,13 +553,12 @@ TEST_F(Pkcs11HpkeTest, InvalidReceiverKeyType) { ASSERT_NE(nullptr, priv_key); ASSERT_NE(nullptr, pub_tmp); pub_key.reset(pub_tmp); - rv = PK11_HPKE_SetupS(sender.get(), nullptr, nullptr, pub_key.get(), - &info_item); - EXPECT_EQ(SECFailure, rv); + EXPECT_EQ(SECFailure, PK11_HPKE_SetupS(sender.get(), nullptr, nullptr, + pub_key.get(), &info_item)); EXPECT_EQ(SEC_ERROR_BAD_KEY, PORT_GetError()); } #else -TEST(Pkcs11HpkeTest, EnsureNotImplemented) { +TEST(HpkeTest, EnsureNotImplemented) { ScopedHpkeContext cx( PK11_HPKE_NewContext(HpkeDhKemX25519Sha256, HpkeKdfHkdfSha256, HpkeAeadChaCha20Poly1305, nullptr, nullptr)); diff --git a/lib/pk11wrap/pk11hpke.c b/lib/pk11wrap/pk11hpke.c index 7f8fe3b1b0..02025cfcd0 100644 --- a/lib/pk11wrap/pk11hpke.c +++ b/lib/pk11wrap/pk11hpke.c @@ -1,5 +1,5 @@ /* - * draft-irtf-cfrg-hpke-05 + * draft-irtf-cfrg-hpke-07 * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this @@ -94,15 +94,15 @@ PK11_HPKE_SetupR(HpkeContext *cx, const SECKEYPublicKey *pkR, SECKEYPrivateKey * } #else -static const char *DRAFT_LABEL = "HPKE-05 "; + +static const char *DRAFT_LABEL = "HPKE-07"; static const char *EXP_LABEL = "exp"; static const char *HPKE_LABEL = "HPKE"; static const char *INFO_LABEL = "info_hash"; static const char *KEM_LABEL = "KEM"; static const char *KEY_LABEL = "key"; -static const char *NONCE_LABEL = "nonce"; +static const char *NONCE_LABEL = "base_nonce"; static const char *PSK_ID_LABEL = "psk_id_hash"; -static const char *PSK_LABEL = "psk_hash"; static const char *SECRET_LABEL = "secret"; static const char *SEC_LABEL = "sec"; static const char *EAE_PRK_LABEL = "eae_prk"; @@ -114,7 +114,7 @@ struct HpkeContextStr { const hpkeAeadParams *aeadParams; PRUint8 mode; /* Base and PSK modes supported. */ SECItem *encapPubKey; /* Marshalled public key, sent to receiver. */ - SECItem *nonce; /* Deterministic nonce for AEAD. */ + SECItem *baseNonce; /* Deterministic nonce for AEAD. */ SECItem *pskId; /* PSK identifier (non-secret). */ PK11Context *aeadContext; /* AEAD context used by Seal/Open. */ PRUint64 sequenceNumber; /* seqNo for decrypt IV construction. */ @@ -132,6 +132,8 @@ static const hpkeKemParams kemParams[] = { static const hpkeKdfParams kdfParams[] = { /* KDF, Nh, mechanism */ { HpkeKdfHkdfSha256, SHA256_LENGTH, CKM_SHA256 }, + { HpkeKdfHkdfSha384, SHA384_LENGTH, CKM_SHA384 }, + { HpkeKdfHkdfSha512, SHA512_LENGTH, CKM_SHA512 }, }; static const hpkeAeadParams aeadParams[] = { /* AEAD, Nk, Nn, tagLen, mechanism */ @@ -156,6 +158,10 @@ kdfId2Params(HpkeKdfId kdfId) switch (kdfId) { case HpkeKdfHkdfSha256: return &kdfParams[0]; + case HpkeKdfHkdfSha384: + return &kdfParams[1]; + case HpkeKdfHkdfSha512: + return &kdfParams[2]; default: return NULL; } @@ -174,16 +180,16 @@ aeadId2Params(HpkeAeadId aeadId) } } -static SECStatus -encodeShort(PRUint32 val, PRUint8 *b) +static PRUint8 * +encodeNumber(PRUint64 value, PRUint8 *b, size_t count) { - if (val > 0xFFFF || !b) { - PORT_SetError(SEC_ERROR_INVALID_ARGS); - return SECFailure; - } - b[0] = (val >> 8) & 0xff; - b[1] = val & 0xff; - return SECSuccess; + PRUint64 encoded; + PORT_Assert(b && count > 0 && count <= sizeof(encoded)); + + encoded = PR_htonll(value); + PORT_Memcpy(b, ((unsigned char *)(&encoded)) + (sizeof(encoded) - count), + count); + return b + count; } SECStatus @@ -268,14 +274,14 @@ PK11_HPKE_DestroyContext(HpkeContext *cx, PRBool freeit) PK11_FreeSymKey(cx->key); PK11_FreeSymKey(cx->psk); SECITEM_FreeItem(cx->pskId, PR_TRUE); - SECITEM_FreeItem(cx->nonce, PR_TRUE); + SECITEM_FreeItem(cx->baseNonce, PR_TRUE); SECITEM_FreeItem(cx->encapPubKey, PR_TRUE); cx->exporterSecret = NULL; cx->sharedSecret = NULL; cx->key = NULL; cx->psk = NULL; cx->pskId = NULL; - cx->nonce = NULL; + cx->baseNonce = NULL; cx->encapPubKey = NULL; if (freeit) { PORT_ZFree(cx, sizeof(HpkeContext)); @@ -347,7 +353,7 @@ PK11_HPKE_Deserialize(const HpkeContext *cx, const PRUint8 *enc, // Set parameters. pubKey->u.ec.DEREncodedParams.data[0] = SEC_ASN1_OBJECT_ID; pubKey->u.ec.DEREncodedParams.data[1] = oidData->oid.len; - memcpy(pubKey->u.ec.DEREncodedParams.data + 2, oidData->oid.data, oidData->oid.len); + PORT_Memcpy(pubKey->u.ec.DEREncodedParams.data + 2, oidData->oid.data, oidData->oid.len); *outPubKey = pubKey; CLEANUP: @@ -403,7 +409,7 @@ pk11_hpke_GenerateKeyPair(const HpkeContext *cx, SECKEYPublicKey **pkE, ecp.type = siDEROID; ecp.data[0] = SEC_ASN1_OBJECT_ID; ecp.data[1] = oidData->oid.len; - memcpy(&ecp.data[2], oidData->oid.data, oidData->oid.len); + PORT_Memcpy(&ecp.data[2], oidData->oid.data, oidData->oid.len); slot = PK11_GetBestSlot(CKM_EC_KEY_PAIR_GEN, NULL); CHECK_FAIL(!slot); @@ -433,21 +439,21 @@ pk11_hpke_MakeExtractLabel(const char *prefix, unsigned int prefixLen, const SECItem *suiteId, const SECItem *ikm) { SECItem *out = NULL; - size_t off = 0; + PRUint8 *walker; out = SECITEM_AllocItem(NULL, NULL, prefixLen + labelLen + suiteId->len + (ikm ? ikm->len : 0)); if (!out) { return NULL; } - memcpy(&out->data[off], prefix, prefixLen); - off += prefixLen; - memcpy(&out->data[off], suiteId->data, suiteId->len); - off += suiteId->len; - memcpy(&out->data[off], label, labelLen); - off += labelLen; + walker = out->data; + PORT_Memcpy(walker, prefix, prefixLen); + walker += prefixLen; + PORT_Memcpy(walker, suiteId->data, suiteId->len); + walker += suiteId->len; + PORT_Memcpy(walker, label, labelLen); + walker += labelLen; if (ikm && ikm->data) { - memcpy(&out->data[off], ikm->data, ikm->len); - off += ikm->len; + PORT_Memcpy(walker, ikm->data, ikm->len); } return out; @@ -474,7 +480,7 @@ pk11_hpke_LabeledExtractData(const HpkeContext *cx, SECItem *salt, CHECK_FAIL(!labeledIkm); params.bExtract = CK_TRUE; params.bExpand = CK_FALSE; - params.prfHashMechanism = cx->kemParams->hashMech; + params.prfHashMechanism = cx->kdfParams->mech; params.ulSaltType = salt ? CKF_HKDF_SALT_DATA : CKF_HKDF_SALT_NULL; params.pSalt = salt ? (CK_BYTE_PTR)salt->data : NULL; params.ulSaltLen = salt ? salt->len : 0; @@ -511,7 +517,7 @@ pk11_hpke_LabeledExtractData(const HpkeContext *cx, SECItem *salt, static SECStatus pk11_hpke_LabeledExtract(const HpkeContext *cx, PK11SymKey *salt, - const SECItem *suiteId, const char *label, + const SECItem *suiteId, const char *label, CK_MECHANISM_TYPE hashMech, unsigned int labelLen, PK11SymKey *ikm, PK11SymKey **out) { SECStatus rv = SECSuccess; @@ -537,7 +543,7 @@ pk11_hpke_LabeledExtract(const HpkeContext *cx, PK11SymKey *salt, params.bExtract = CK_TRUE; params.bExpand = CK_FALSE; - params.prfHashMechanism = cx->kemParams->hashMech; + params.prfHashMechanism = hashMech; params.ulSaltType = salt ? CKF_HKDF_SALT_KEY : CKF_HKDF_SALT_NULL; params.hSaltKey = salt ? PK11_GetSymKeyHandle(salt) : CK_INVALID_HANDLE; @@ -555,9 +561,10 @@ pk11_hpke_LabeledExtract(const HpkeContext *cx, PK11SymKey *salt, static SECStatus pk11_hpke_LabeledExpand(const HpkeContext *cx, PK11SymKey *prk, const SECItem *suiteId, const char *label, unsigned int labelLen, const SECItem *info, - unsigned int L, PK11SymKey **outKey, SECItem **outItem) + unsigned int L, CK_MECHANISM_TYPE hashMech, PK11SymKey **outKey, + SECItem **outItem) { - SECStatus rv; + SECStatus rv = SECSuccess; CK_MECHANISM_TYPE keyMech; CK_MECHANISM_TYPE deriveMech; CK_HKDF_PARAMS params = { 0 }; @@ -567,34 +574,32 @@ pk11_hpke_LabeledExpand(const HpkeContext *cx, PK11SymKey *prk, const SECItem *s sizeof(params) }; SECItem *derivedKeyData; PRUint8 encodedL[2]; - size_t off = 0; + PRUint8 *walker = encodedL; size_t len; PORT_Assert(cx && prk && label && (!!outKey != !!outItem)); - rv = encodeShort(L, encodedL); - CHECK_RV(rv); - + walker = encodeNumber(L, walker, 2); len = info ? info->len : 0; len += sizeof(encodedL) + strlen(DRAFT_LABEL) + suiteId->len + labelLen; labeledInfoItem = SECITEM_AllocItem(NULL, NULL, len); CHECK_FAIL(!labeledInfoItem); - memcpy(&labeledInfoItem->data[off], encodedL, sizeof(encodedL)); - off += sizeof(encodedL); - memcpy(&labeledInfoItem->data[off], DRAFT_LABEL, strlen(DRAFT_LABEL)); - off += strlen(DRAFT_LABEL); - memcpy(&labeledInfoItem->data[off], suiteId->data, suiteId->len); - off += suiteId->len; - memcpy(&labeledInfoItem->data[off], label, labelLen); - off += labelLen; + walker = labeledInfoItem->data; + PORT_Memcpy(walker, encodedL, sizeof(encodedL)); + walker += sizeof(encodedL); + PORT_Memcpy(walker, DRAFT_LABEL, strlen(DRAFT_LABEL)); + walker += strlen(DRAFT_LABEL); + PORT_Memcpy(walker, suiteId->data, suiteId->len); + walker += suiteId->len; + PORT_Memcpy(walker, label, labelLen); + walker += labelLen; if (info) { - memcpy(&labeledInfoItem->data[off], info->data, info->len); - off += info->len; + PORT_Memcpy(walker, info->data, info->len); } params.bExtract = CK_FALSE; params.bExpand = CK_TRUE; - params.prfHashMechanism = cx->kemParams->hashMech; + params.prfHashMechanism = hashMech; params.ulSaltType = CKF_HKDF_SALT_NULL; params.pInfo = labeledInfoItem->data; params.ulInfoLen = labeledInfoItem->len; @@ -635,19 +640,22 @@ pk11_hpke_ExtractAndExpand(const HpkeContext *cx, PK11SymKey *ikm, PK11SymKey *eaePrk = NULL; PK11SymKey *sharedSecret = NULL; PRUint8 suiteIdBuf[5]; + PRUint8 *walker; PORT_Memcpy(suiteIdBuf, KEM_LABEL, strlen(KEM_LABEL)); SECItem suiteIdItem = { siBuffer, suiteIdBuf, sizeof(suiteIdBuf) }; PORT_Assert(cx && ikm && kemContext && out); - rv = encodeShort(cx->kemParams->id, &suiteIdBuf[3]); - CHECK_RV(rv); + walker = &suiteIdBuf[3]; + walker = encodeNumber(cx->kemParams->id, walker, 2); rv = pk11_hpke_LabeledExtract(cx, NULL, &suiteIdItem, EAE_PRK_LABEL, - strlen(EAE_PRK_LABEL), ikm, &eaePrk); + cx->kemParams->hashMech, strlen(EAE_PRK_LABEL), + ikm, &eaePrk); CHECK_RV(rv); rv = pk11_hpke_LabeledExpand(cx, eaePrk, &suiteIdItem, SH_SEC_LABEL, strlen(SH_SEC_LABEL), - kemContext, cx->kemParams->Nsecret, &sharedSecret, NULL); + kemContext, cx->kemParams->Nsecret, cx->kemParams->hashMech, + &sharedSecret, NULL); CHECK_RV(rv); *out = sharedSecret; @@ -698,7 +706,7 @@ pk11_hpke_Encap(HpkeContext *cx, const SECKEYPublicKey *pkE, SECKEYPrivateKey *s kemContext = SECITEM_AllocItem(NULL, NULL, cx->encapPubKey->len + tmpLen); CHECK_FAIL(!kemContext); - memcpy(kemContext->data, cx->encapPubKey->data, cx->encapPubKey->len); + PORT_Memcpy(kemContext->data, cx->encapPubKey->data, cx->encapPubKey->len); rv = PK11_HPKE_Serialize(pkR, &kemContext->data[cx->encapPubKey->len], &tmpLen, tmpLen); CHECK_RV(rv); @@ -723,6 +731,7 @@ PK11_HPKE_ExportSecret(const HpkeContext *cx, const SECItem *info, unsigned int SECStatus rv; PK11SymKey *exported; PRUint8 suiteIdBuf[10]; + PRUint8 *walker; PORT_Memcpy(suiteIdBuf, HPKE_LABEL, strlen(HPKE_LABEL)); SECItem suiteIdItem = { siBuffer, suiteIdBuf, sizeof(suiteIdBuf) }; @@ -733,15 +742,14 @@ PK11_HPKE_ExportSecret(const HpkeContext *cx, const SECItem *info, unsigned int return SECFailure; } - rv = encodeShort(cx->kemParams->id, &suiteIdBuf[4]); - CHECK_RV(rv); - rv = encodeShort(cx->kdfParams->id, &suiteIdBuf[6]); - CHECK_RV(rv); - rv = encodeShort(cx->aeadParams->id, &suiteIdBuf[8]); - CHECK_RV(rv); + walker = &suiteIdBuf[4]; + walker = encodeNumber(cx->kemParams->id, walker, 2); + walker = encodeNumber(cx->kdfParams->id, walker, 2); + walker = encodeNumber(cx->aeadParams->id, walker, 2); rv = pk11_hpke_LabeledExpand(cx, cx->exporterSecret, &suiteIdItem, SEC_LABEL, - strlen(SEC_LABEL), info, L, &exported, NULL); + strlen(SEC_LABEL), info, L, cx->kdfParams->mech, + &exported, NULL); CHECK_RV(rv); *out = exported; @@ -785,7 +793,7 @@ pk11_hpke_Decap(HpkeContext *cx, const SECKEYPublicKey *pkR, SECKEYPrivateKey *s kemContext = SECITEM_AllocItem(NULL, NULL, encS->len + tmpLen); CHECK_FAIL(!kemContext); - memcpy(kemContext->data, encS->data, encS->len); + PORT_Memcpy(kemContext->data, encS->data, encS->len); rv = PK11_HPKE_Serialize(pkR, &kemContext->data[encS->len], &tmpLen, kemContext->len - encS->len); CHECK_RV(rv); @@ -820,21 +828,19 @@ pk11_hpke_KeySchedule(HpkeContext *cx, const SECItem *info) SECItem contextItem = { siBuffer, NULL, 0 }; unsigned int len; unsigned int off; - PK11SymKey *pskHash = NULL; PK11SymKey *secret = NULL; SECItem *pskIdHash = NULL; SECItem *infoHash = NULL; PRUint8 suiteIdBuf[10]; + PRUint8 *walker; PORT_Memcpy(suiteIdBuf, HPKE_LABEL, strlen(HPKE_LABEL)); SECItem suiteIdItem = { siBuffer, suiteIdBuf, sizeof(suiteIdBuf) }; PORT_Assert(cx && info && cx->psk && cx->pskId); - rv = encodeShort(cx->kemParams->id, &suiteIdBuf[4]); - CHECK_RV(rv); - rv = encodeShort(cx->kdfParams->id, &suiteIdBuf[6]); - CHECK_RV(rv); - rv = encodeShort(cx->aeadParams->id, &suiteIdBuf[8]); - CHECK_RV(rv); + walker = &suiteIdBuf[4]; + walker = encodeNumber(cx->kemParams->id, walker, 2); + walker = encodeNumber(cx->kdfParams->id, walker, 2); + walker = encodeNumber(cx->aeadParams->id, walker, 2); rv = pk11_hpke_LabeledExtractData(cx, NULL, &suiteIdItem, PSK_ID_LABEL, strlen(PSK_ID_LABEL), cx->pskId, &pskIdHash); @@ -847,33 +853,33 @@ pk11_hpke_KeySchedule(HpkeContext *cx, const SECItem *info) len = sizeof(cx->mode) + pskIdHash->len + infoHash->len; CHECK_FAIL(!SECITEM_AllocItem(NULL, &contextItem, len)); off = 0; - memcpy(&contextItem.data[off], &cx->mode, sizeof(cx->mode)); + PORT_Memcpy(&contextItem.data[off], &cx->mode, sizeof(cx->mode)); off += sizeof(cx->mode); - memcpy(&contextItem.data[off], pskIdHash->data, pskIdHash->len); + PORT_Memcpy(&contextItem.data[off], pskIdHash->data, pskIdHash->len); off += pskIdHash->len; - memcpy(&contextItem.data[off], infoHash->data, infoHash->len); + PORT_Memcpy(&contextItem.data[off], infoHash->data, infoHash->len); off += infoHash->len; // Compute the keys - rv = pk11_hpke_LabeledExtract(cx, NULL, &suiteIdItem, PSK_LABEL, - strlen(PSK_LABEL), cx->psk, &pskHash); - CHECK_RV(rv); - rv = pk11_hpke_LabeledExtract(cx, pskHash, &suiteIdItem, SECRET_LABEL, - strlen(SECRET_LABEL), cx->sharedSecret, &secret); + rv = pk11_hpke_LabeledExtract(cx, cx->sharedSecret, &suiteIdItem, SECRET_LABEL, + cx->kdfParams->mech, strlen(SECRET_LABEL), + cx->psk, &secret); CHECK_RV(rv); rv = pk11_hpke_LabeledExpand(cx, secret, &suiteIdItem, KEY_LABEL, strlen(KEY_LABEL), - &contextItem, cx->aeadParams->Nk, &cx->key, NULL); + &contextItem, cx->aeadParams->Nk, cx->kdfParams->mech, + &cx->key, NULL); CHECK_RV(rv); rv = pk11_hpke_LabeledExpand(cx, secret, &suiteIdItem, NONCE_LABEL, strlen(NONCE_LABEL), - &contextItem, cx->aeadParams->Nn, NULL, &cx->nonce); + &contextItem, cx->aeadParams->Nn, cx->kdfParams->mech, + NULL, &cx->baseNonce); CHECK_RV(rv); rv = pk11_hpke_LabeledExpand(cx, secret, &suiteIdItem, EXP_LABEL, strlen(EXP_LABEL), - &contextItem, cx->kdfParams->Nh, &cx->exporterSecret, NULL); + &contextItem, cx->kdfParams->Nh, cx->kdfParams->mech, + &cx->exporterSecret, NULL); CHECK_RV(rv); CLEANUP: /* If !SECSuccess, callers will tear down the context. */ - PK11_FreeSymKey(pskHash); PK11_FreeSymKey(secret); SECITEM_FreeItem(&contextItem, PR_FALSE); SECITEM_FreeItem(infoHash, PR_TRUE); @@ -886,7 +892,7 @@ PK11_HPKE_SetupR(HpkeContext *cx, const SECKEYPublicKey *pkR, SECKEYPrivateKey * const SECItem *enc, const SECItem *info) { SECStatus rv; - SECItem nullParams = { siBuffer, NULL, 0 }; + SECItem empty = { siBuffer, NULL, 0 }; CHECK_FAIL_ERR((!cx || !skR || !info || !enc || !enc->data || !enc->len), SEC_ERROR_INVALID_ARGS); @@ -903,7 +909,7 @@ PK11_HPKE_SetupR(HpkeContext *cx, const SECKEYPublicKey *pkR, SECKEYPrivateKey * PORT_Assert(cx->key); cx->aeadContext = PK11_CreateContextBySymKey(cx->aeadParams->mech, CKA_NSS_MESSAGE | CKA_DECRYPT, - cx->key, &nullParams); + cx->key, &empty); CHECK_FAIL_ERR((!cx->aeadContext), SEC_ERROR_LIBRARY_FAILURE); CLEANUP: @@ -973,8 +979,8 @@ PK11_HPKE_Seal(HpkeContext *cx, const SECItem *aad, const SECItem *pt, unsigned char tagBuf[HASH_LENGTH_MAX]; size_t tagLen; unsigned int fixedBits; - PORT_Assert(cx->nonce->len == sizeof(ivOut)); - memcpy(ivOut, cx->nonce->data, cx->nonce->len); + PORT_Assert(cx->baseNonce->len == sizeof(ivOut)); + PORT_Memcpy(ivOut, cx->baseNonce->data, cx->baseNonce->len); /* aad may be NULL, PT may be zero-length but not NULL. */ if (!cx || !cx->aeadContext || @@ -987,7 +993,7 @@ PK11_HPKE_Seal(HpkeContext *cx, const SECItem *aad, const SECItem *pt, tagLen = cx->aeadParams->tagLen; maxOut = pt->len + tagLen; - fixedBits = (cx->nonce->len - 8) * 8; + fixedBits = (cx->baseNonce->len - 8) * 8; ct = SECITEM_AllocItem(NULL, NULL, maxOut); CHECK_FAIL(!ct); @@ -1003,7 +1009,7 @@ PK11_HPKE_Seal(HpkeContext *cx, const SECItem *aad, const SECItem *pt, CHECK_FAIL_ERR((ct->len > maxOut - tagLen), SEC_ERROR_LIBRARY_FAILURE); /* Append the tag to the ciphertext. */ - memcpy(&ct->data[ct->len], tagBuf, tagLen); + PORT_Memcpy(&ct->data[ct->len], tagBuf, tagLen); ct->len += tagLen; *out = ct; @@ -1023,7 +1029,7 @@ static SECStatus pk11_hpke_makeIv(HpkeContext *cx, PRUint8 *iv, size_t ivLen) { unsigned int counterLen = sizeof(cx->sequenceNumber); - PORT_Assert(cx->nonce->len == ivLen); + PORT_Assert(cx->baseNonce->len == ivLen); PORT_Assert(counterLen == 8); if (cx->sequenceNumber == PR_UINT64(0xffffffffffffffff)) { /* Overflow */ @@ -1031,9 +1037,9 @@ pk11_hpke_makeIv(HpkeContext *cx, PRUint8 *iv, size_t ivLen) return SECFailure; } - memcpy(iv, cx->nonce->data, cx->nonce->len); + PORT_Memcpy(iv, cx->baseNonce->data, cx->baseNonce->len); for (size_t i = 0; i < counterLen; i++) { - iv[cx->nonce->len - 1 - i] ^= + iv[cx->baseNonce->len - 1 - i] ^= PORT_GET_BYTE_BE(cx->sequenceNumber, counterLen - 1 - i, counterLen); } diff --git a/lib/pk11wrap/pk11hpke.h b/lib/pk11wrap/pk11hpke.h index 95a55fd336..e86d235b43 100644 --- a/lib/pk11wrap/pk11hpke.h +++ b/lib/pk11wrap/pk11hpke.h @@ -9,7 +9,7 @@ #include "seccomon.h" #ifdef NSS_ENABLE_DRAFT_HPKE -#define HPKE_DRAFT_VERSION 5 +#define HPKE_DRAFT_VERSION 7 #define CLEANUP \ PORT_Assert(rv == SECSuccess); \ @@ -42,13 +42,15 @@ typedef enum { HpkeModePsk = 1, } HpkeModeId; -/* https://tools.ietf.org/html/draft-irtf-cfrg-hpke-05#section-7.1 */ +/* https://tools.ietf.org/html/draft-irtf-cfrg-hpke-07#section-7.1 */ typedef enum { HpkeDhKemX25519Sha256 = 0x20, } HpkeKemId; typedef enum { HpkeKdfHkdfSha256 = 1, + HpkeKdfHkdfSha384 = 2, + HpkeKdfHkdfSha512 = 3, } HpkeKdfId; typedef enum { diff --git a/lib/pk11wrap/pk11pub.h b/lib/pk11wrap/pk11pub.h index e6961e0244..7ec6bb90b7 100644 --- a/lib/pk11wrap/pk11pub.h +++ b/lib/pk11wrap/pk11pub.h @@ -728,7 +728,7 @@ CK_BBOOL PK11_HasAttributeSet(PK11SlotInfo *slot, PRBool haslock /* must be set to PR_FALSE */); /********************************************************************** - * Hybrid Public Key Encryption (draft-05) + * Hybrid Public Key Encryption (draft-07) **********************************************************************/ /* * NOTE: All HPKE functions will fail with SEC_ERROR_INVALID_ALGORITHM @@ -746,9 +746,9 @@ HpkeContext *PK11_HPKE_NewContext(HpkeKemId kemId, HpkeKdfId kdfId, HpkeAeadId a SECStatus PK11_HPKE_Deserialize(const HpkeContext *cx, const PRUint8 *enc, unsigned int encLen, SECKEYPublicKey **outPubKey); void PK11_HPKE_DestroyContext(HpkeContext *cx, PRBool freeit); -const SECItem *PK11_HPKE_GetEncapPubKey(const HpkeContext *cx); SECStatus PK11_HPKE_ExportSecret(const HpkeContext *cx, const SECItem *info, unsigned int L, PK11SymKey **outKey); +const SECItem *PK11_HPKE_GetEncapPubKey(const HpkeContext *cx); SECStatus PK11_HPKE_Open(HpkeContext *cx, const SECItem *aad, const SECItem *ct, SECItem **outPt); SECStatus PK11_HPKE_Seal(HpkeContext *cx, const SECItem *aad, const SECItem *pt, SECItem **outCt); SECStatus PK11_HPKE_Serialize(const SECKEYPublicKey *pk, PRUint8 *buf, unsigned int *len, unsigned int maxLen);