@@ -50,7 +50,6 @@ public:
50
50
// Add salt to digest context in order to generate or verify salted signature.
51
51
// Currently only used for RSA-PSS sign and verify operations.
52
52
53
-
54
53
// ---------------------------------------------------------------------------
55
54
// Implementation of CryptoKey
56
55
@@ -1175,7 +1174,7 @@ public:
1175
1174
1176
1175
auto outputBitLength = resultBitLength.orDefault (sharedSecret.size () * 8 );
1177
1176
JSG_REQUIRE (outputBitLength <= sharedSecret.size () * 8 , DOMOperationError,
1178
- " Derived key length (" , outputBitLength, " bits) is too long (should be less than " ,
1177
+ " Derived key length (" , outputBitLength, " bits) is too long (should be at most " ,
1179
1178
sharedSecret.size () * 8 , " bits)." );
1180
1179
1181
1180
// Round up since outputBitLength may not be a perfect multiple of 8.
@@ -1479,6 +1478,15 @@ kj::Own<EVP_PKEY> ellipticJwkReader(int curveId, SubtleCrypto::JsonWebKey keyDat
1479
1478
" Missing field \" crv\" for " , curveName, " key." );
1480
1479
JSG_REQUIRE (crv == curveName, DOMNotSupportedError,
1481
1480
" Only " , curveName, " is supported but \" " , crv, " \" was requested." );
1481
+ KJ_IF_MAYBE (alg, keyDataJwk.alg ) {
1482
+ // If this JWK specifies an algorithm, make sure it jives with the hash we were passed via
1483
+ // importKey().
1484
+ if (curveId == NID_ED25519) {
1485
+ JSG_REQUIRE (*alg == " EdDSA" , DOMDataError,
1486
+ " JSON Web Key Algorithm parameter \" alg\" (\" " , *alg, " \" ) does not match requested "
1487
+ " Ed25519 curve." );
1488
+ }
1489
+ }
1482
1490
1483
1491
auto x = UNWRAP_JWK_BIGNUM (kj::mv (keyDataJwk.x ), DOMDataError,
1484
1492
" Invalid " , crv, " key in JSON WebKey; missing or invalid public key component (\" x\" )." );
@@ -1526,7 +1534,7 @@ kj::Own<EVP_PKEY> ellipticJwkReader(int curveId, SubtleCrypto::JsonWebKey keyDat
1526
1534
" \" listed in JSON Web Key Algorithm parameter." );
1527
1535
1528
1536
JSG_REQUIRE (iter->second == curveId, DOMDataError,
1529
- " JSON Web Key Algorithm parameter \" alg\" \" " , *alg, " \" does not match requested EC curve." );
1537
+ " JSON Web Key Algorithm parameter \" alg\" ( \" " , *alg, " \" ) does not match requested curve." );
1530
1538
}
1531
1539
1532
1540
auto ecKey = OSSLCALL_OWN (EC_KEY, EC_KEY_new_by_curve_name (curveId), DOMOperationError,
@@ -1728,7 +1736,6 @@ kj::Own<CryptoKey::Impl> CryptoKey::Impl::importEcdh(
1728
1736
// =====================================================================================
1729
1737
// EDDSA & EDDH
1730
1738
1731
-
1732
1739
namespace {
1733
1740
1734
1741
// Abstract base class for EDDSA and EDDH. Unfortunately, the legacy NODE-ED25519 identifier has a
@@ -1837,6 +1844,11 @@ public:
1837
1844
" Private key for derivation is using \" " , getAlgorithmName (),
1838
1845
" \" while public key is using \" " , publicKey->getAlgorithmName (), " \" ." );
1839
1846
1847
+ auto outputBitLength = resultBitLength.orDefault (X25519_SHARED_KEY_LEN * 8 );
1848
+ JSG_REQUIRE (outputBitLength <= X25519_SHARED_KEY_LEN * 8 , DOMOperationError,
1849
+ " Derived key length (" , outputBitLength, " bits) is too long (should be at most " ,
1850
+ X25519_SHARED_KEY_LEN * 8 , " bits)." );
1851
+
1840
1852
// The check above for the algorithm `which` equality ensures that the impl can be downcast to
1841
1853
// EdDsaKey (assuming we don't accidentally create a class that doesn't inherit this one that
1842
1854
// for some reason returns an EdDsaKey).
@@ -1849,13 +1861,12 @@ public:
1849
1861
JSG_REQUIRE (1 == EVP_PKEY_derive_set_peer (ctx, publicKeyImpl.getEvpPkey ()),
1850
1862
InternalDOMOperationError, " Failed to set EDDH peer" , internalDescribeOpensslErrors ());
1851
1863
1852
- kj::Vector<kj::byte> sharedSecret (X25519_SHARED_KEY_LEN);
1853
- size_t skeylen = 0 ;
1854
- JSG_REQUIRE (1 == EVP_PKEY_derive (ctx, NULL , &skeylen), DOMOperationError,
1855
- " Failed to derive EDDH key" , internalDescribeOpensslErrors ());
1856
- KJ_ASSERT (skeylen == X25519_SHARED_KEY_LEN);
1864
+ kj::Vector<kj::byte> sharedSecret;
1865
+ sharedSecret.resize (X25519_SHARED_KEY_LEN);
1866
+ size_t skeylen = X25519_SHARED_KEY_LEN;
1857
1867
JSG_REQUIRE (1 == EVP_PKEY_derive (ctx, sharedSecret.begin (), &skeylen), DOMOperationError,
1858
1868
" Failed to derive EDDH key" , internalDescribeOpensslErrors ());
1869
+ KJ_ASSERT (skeylen == X25519_SHARED_KEY_LEN);
1859
1870
1860
1871
// Check for all-zero value as mandated by spec
1861
1872
kj::byte isNonZeroSecret = 0 ;
@@ -1864,6 +1875,14 @@ public:
1864
1875
}
1865
1876
JSG_REQUIRE (isNonZeroSecret, DOMOperationError,
1866
1877
" Detected small order secure curve points, aborting EDDH derivation" );
1878
+
1879
+ // mask off bits like in ECDH's deriveBits()
1880
+ auto resultByteLength = integerCeilDivision (outputBitLength, 8u );
1881
+ sharedSecret.truncate (resultByteLength);
1882
+ auto numBitsToMaskOff = resultByteLength * 8 - outputBitLength;
1883
+ KJ_DASSERT (numBitsToMaskOff < 8 , numBitsToMaskOff);
1884
+ uint8_t mask = ~((1 << numBitsToMaskOff) - 1 );
1885
+ sharedSecret.back () &= mask;
1867
1886
return sharedSecret.releaseAsArray ();
1868
1887
}
1869
1888
@@ -1884,6 +1903,9 @@ private:
1884
1903
jwk.kty = kj::str (" OKP" );
1885
1904
jwk.crv = kj::str (getAlgorithmName () == " X25519" _kj ? " X25519" _kj : " Ed25519" _kj);
1886
1905
jwk.x = kj::encodeBase64Url (kj::arrayPtr (rawPublicKey, publicKeyLen));
1906
+ if (getAlgorithmName () == " Ed25519" _kj) {
1907
+ jwk.alg = kj::str (" EdDSA" );
1908
+ }
1887
1909
1888
1910
if (getType () == " private" _kj) {
1889
1911
// Deliberately use ED25519_PUBLIC_KEY_LEN here.
@@ -1972,6 +1994,7 @@ kj::OneOf<jsg::Ref<CryptoKey>, CryptoKeyPair> EdDsaKeyBase::generateKey(
1972
1994
uint8_t rawPublicKey[keylen];
1973
1995
uint8_t rawPrivateKey[keylen * 2 ];
1974
1996
keypair (rawPublicKey, rawPrivateKey);
1997
+
1975
1998
// The private key technically also contains the public key. Why does the keypair function bother
1976
1999
// writing out the public key to a separate buffer?
1977
2000
0 commit comments