summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKevin Jacobs <kjacobs@mozilla.com>2021-01-25 17:41:03 +0000
committerKevin Jacobs <kjacobs@mozilla.com>2021-01-25 17:41:03 +0000
commitddc9d5dd387672585d52dbf326b40c9ed00ed671 (patch)
tree67715709441f71b7fdcb23415523ac7562c9e7f6
parent34e04960e009510c84d419ec3edd6d31cfff1bea (diff)
downloadnss-hg-ddc9d5dd387672585d52dbf326b40c9ed00ed671.tar.gz
Bug 1678398 - Update HPKE to draft-07. r=mt
This patch updates HPKE to draft-07. A few other minor changes are included: - Refactor HPKE gtests for increased parameterized testing. - Replace memcpy calls with PORT_Memcpy - Serialization tweaks to make way for context Export/Import (D99277). This should not be landed without an ECH update, as fixed ECH test vectors will otherwise fail to decrypt. Differential Revision: https://phabricator.services.mozilla.com/D99276
-rw-r--r--gtests/common/testvectors/hpke-vectors.h250
-rw-r--r--gtests/pk11_gtest/pk11_hpke_unittest.cc491
-rw-r--r--lib/pk11wrap/pk11hpke.c182
-rw-r--r--lib/pk11wrap/pk11hpke.h6
-rw-r--r--lib/pk11wrap/pk11pub.h4
5 files changed, 487 insertions, 446 deletions
diff --git a/gtests/common/testvectors/hpke-vectors.h b/gtests/common/testvectors/hpke-vectors.h
index dd7b417b8..afed3fea8 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<HpkeKdfId>(1),
static_cast<HpkeAeadId>(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<HpkeKdfId>(1),
static_cast<HpkeAeadId>(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<HpkeModeId>(0),
static_cast<HpkeKemId>(32),
static_cast<HpkeKdfId>(1),
static_cast<HpkeAeadId>(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<HpkeModeId>(1),
static_cast<HpkeKemId>(32),
static_cast<HpkeKdfId>(1),
static_cast<HpkeAeadId>(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<HpkeModeId>(0),
+ static_cast<HpkeKemId>(32),
+ static_cast<HpkeKdfId>(3),
+ static_cast<HpkeAeadId>(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 c8220621e..26385f144 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<hpke_vector> {
+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<uint8_t> psk_bytes = hex_string_to_bytes(vec.psk);
- SECItem psk_item = {siBuffer, toUcharPtr(psk_bytes.data()),
- static_cast<unsigned int>(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<uint8_t> &expected, SECItem *actual) {
if (!actual) {
EXPECT_TRUE(expected.empty());
@@ -102,55 +74,159 @@ class Pkcs11HpkeTest : public ::testing::TestWithParam<hpke_vector> {
CheckEquality(expected_vec, actual);
}
- void SetupS(const ScopedHpkeContext &cx, const ScopedSECKEYPublicKey &pkE,
- const ScopedSECKEYPrivateKey &skE,
- const ScopedSECKEYPublicKey &pkR,
- const std::vector<uint8_t> &info) {
- SECItem info_item = {siBuffer, toUcharPtr(vec_info.data()),
- static_cast<unsigned int>(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<uint8_t> &enc,
- const std::vector<uint8_t> &info) {
- SECItem enc_item = {siBuffer, toUcharPtr(enc.data()),
- static_cast<unsigned int>(enc.size())};
- SECItem info_item = {siBuffer, toUcharPtr(vec_info.data()),
- static_cast<unsigned int>(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<uint8_t> &aad_vec,
- std::vector<uint8_t> &pt_vec, SECItem **out_ct) {
+ std::vector<uint8_t> &pt_vec, std::vector<uint8_t> &out_sealed) {
SECItem aad_item = {siBuffer, toUcharPtr(aad_vec.data()),
static_cast<unsigned int>(aad_vec.size())};
SECItem pt_item = {siBuffer, toUcharPtr(pt_vec.data()),
static_cast<unsigned int>(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<uint8_t> &aad_vec,
- std::vector<uint8_t> &ct_vec, SECItem **out_pt) {
+ std::vector<uint8_t> &ct_vec, std::vector<uint8_t> &out_opened) {
SECItem aad_item = {siBuffer, toUcharPtr(aad_vec.data()),
static_cast<unsigned int>(aad_vec.size())};
SECItem ct_item = {siBuffer, toUcharPtr(ct_vec.data()),
static_cast<unsigned int>(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<uint8_t> &msg,
+ std::vector<uint8_t> &aad, const std::vector<uint8_t> *expect) {
+ std::vector<uint8_t> sealed;
+ std::vector<uint8_t> 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<uint8_t> info = {'t', 'e', 's', 't', '-', 'i', 'n', 'f', 'o'};
+ SECItem info_item = {siBuffer, info.data(),
+ static_cast<unsigned int>(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<SECItem *>(enc), &info_item));
+ }
+};
+
+class TestVectors : public HpkeTest,
+ public ::testing::TestWithParam<hpke_vector> {
+ 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<uint8_t> psk_bytes = hex_string_to_bytes(vec.psk);
+ SECItem psk_item = {siBuffer, toUcharPtr(psk_bytes.data()),
+ static_cast<unsigned int>(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<uint8_t> context = hex_string_to_bytes(vec.ctxt);
std::vector<uint8_t> expected = hex_string_to_bytes(vec.exported);
@@ -158,12 +234,11 @@ class Pkcs11HpkeTest : public ::testing::TestWithParam<hpke_vector> {
static_cast<unsigned int>(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<hpke_vector> {
std::vector<uint8_t> msg = hex_string_to_bytes(enc_vec.pt);
std::vector<uint8_t> aad = hex_string_to_bytes(enc_vec.aad);
std::vector<uint8_t> 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<hpke_vector> {
SECItem pkcs8_e_item = {siBuffer, toUcharPtr(vec_pkcs8_e.data()),
static_cast<unsigned int>(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<hpke_vector> {
SECItem pkcs8_r_item = {siBuffer, toUcharPtr(vec_pkcs8_r.data()),
static_cast<unsigned int>(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<uint8_t> &info) {
+ SECItem info_item = {siBuffer, toUcharPtr(vec_info.data()),
+ static_cast<unsigned int>(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<uint8_t> &enc,
+ const std::vector<uint8_t> &info) {
+ SECItem enc_item = {siBuffer, toUcharPtr(enc.data()),
+ static_cast<unsigned int>(enc.size())};
+ SECItem info_item = {siBuffer, toUcharPtr(vec_info.data()),
+ static_cast<unsigned int>(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<uint8_t *>(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<hpke_vector> {
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<HpkeModeId, HpkeKemId, HpkeKdfId, HpkeAeadId>> {};
+
+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<SECItem *>(enc), &info_item);
- EXPECT_EQ(SECSuccess, rv);
+TEST_P(ModeParameterizedTest, EphemeralKeys) {
+ std::vector<uint8_t> msg = {'s', 'e', 'c', 'r', 'e', 't'};
+ std::vector<uint8_t> aad = {'a', 'a', 'd'};
+ SECItem msg_item = {siBuffer, msg.data(),
+ static_cast<unsigned int>(msg.size())};
+ SECItem aad_item = {siBuffer, aad.data(),
+ static_cast<unsigned int>(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<HpkeKemId>(1), HpkeKdfHkdfSha256,
+ PK11_HPKE_NewContext(static_cast<HpkeKemId>(0xff), HpkeKdfHkdfSha256,
HpkeAeadChaCha20Poly1305, nullptr, nullptr);
EXPECT_EQ(nullptr, cx);
EXPECT_EQ(SEC_ERROR_INVALID_ARGS, PORT_GetError());
- cx = PK11_HPKE_NewContext(HpkeDhKemX25519Sha256, static_cast<HpkeKdfId>(2),
+ cx = PK11_HPKE_NewContext(HpkeDhKemX25519Sha256, static_cast<HpkeKdfId>(0xff),
HpkeAeadChaCha20Poly1305, nullptr, nullptr);
EXPECT_EQ(nullptr, cx);
EXPECT_EQ(SEC_ERROR_INVALID_ARGS, PORT_GetError());
cx = PK11_HPKE_NewContext(HpkeDhKemX25519Sha256, HpkeKdfHkdfSha256,
- static_cast<HpkeAeadId>(4), nullptr, nullptr);
+ static_cast<HpkeAeadId>(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 7f8fe3b1b..02025cfcd 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 @@ CLEANUP:
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 @@ CLEANUP:
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 95a55fd33..e86d235b4 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 e6961e024..7ec6bb90b 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);