| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
1 parent b505cd5 commit 7907134
3 files changed
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -78,6 +78,147 @@ bool ApplyRSAOptions(const EVPKeyPointer& pkey, | |||
| 78 | 78 | return true; | |
| 79 | 79 | } | |
| 80 | 80 | ||
| 81 | + constexpr size_t kEd25519PointSize = 32; | ||
| 82 | + constexpr size_t kEd448PointSize = 57; | ||
| 83 | + | ||
| 84 | + // Ed25519 has cofactor 8, so the first eight entries are the full | ||
| 85 | + // canonical small-order subgroup: identity, one point of order 2, | ||
| 86 | + // two points of order 4, and four points of order 8. | ||
| 87 | + constexpr unsigned char kEd25519SmallOrderPoints[][kEd25519PointSize] = { | ||
| 88 | + // Identity. | ||
| 89 | + {0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
| 90 | + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
| 91 | + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, | ||
| 92 | + // Order 2. | ||
| 93 | + {0xec, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | ||
| 94 | + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | ||
| 95 | + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f}, | ||
| 96 | + // Order 4. | ||
| 97 | + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
| 98 | + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
| 99 | + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80}, | ||
| 100 | + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
| 101 | + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
| 102 | + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, | ||
| 103 | + // Order 8. | ||
| 104 | + {0xc7, 0x17, 0x6a, 0x70, 0x3d, 0x4d, 0xd8, 0x4f, 0xba, 0x3c, 0x0b, | ||
| 105 | + 0x76, 0x0d, 0x10, 0x67, 0x0f, 0x2a, 0x20, 0x53, 0xfa, 0x2c, 0x39, | ||
| 106 | + 0xcc, 0xc6, 0x4e, 0xc7, 0xfd, 0x77, 0x92, 0xac, 0x03, 0x7a}, | ||
| 107 | + {0xc7, 0x17, 0x6a, 0x70, 0x3d, 0x4d, 0xd8, 0x4f, 0xba, 0x3c, 0x0b, | ||
| 108 | + 0x76, 0x0d, 0x10, 0x67, 0x0f, 0x2a, 0x20, 0x53, 0xfa, 0x2c, 0x39, | ||
| 109 | + 0xcc, 0xc6, 0x4e, 0xc7, 0xfd, 0x77, 0x92, 0xac, 0x03, 0xfa}, | ||
| 110 | + {0x26, 0xe8, 0x95, 0x8f, 0xc2, 0xb2, 0x27, 0xb0, 0x45, 0xc3, 0xf4, | ||
| 111 | + 0x89, 0xf2, 0xef, 0x98, 0xf0, 0xd5, 0xdf, 0xac, 0x05, 0xd3, 0xc6, | ||
| 112 | + 0x33, 0x39, 0xb1, 0x38, 0x02, 0x88, 0x6d, 0x53, 0xfc, 0x05}, | ||
| 113 | + {0x26, 0xe8, 0x95, 0x8f, 0xc2, 0xb2, 0x27, 0xb0, 0x45, 0xc3, 0xf4, | ||
| 114 | + 0x89, 0xf2, 0xef, 0x98, 0xf0, 0xd5, 0xdf, 0xac, 0x05, 0xd3, 0xc6, | ||
| 115 | + 0x33, 0x39, 0xb1, 0x38, 0x02, 0x88, 0x6d, 0x53, 0xfc, 0x85}, | ||
| 116 | + // Non-canonical encodings of the same small-order points. | ||
| 117 | + {0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
| 118 | + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
| 119 | + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80}, | ||
| 120 | + {0xec, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | ||
| 121 | + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | ||
| 122 | + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, | ||
| 123 | + {0xee, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | ||
| 124 | + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | ||
| 125 | + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f}, | ||
| 126 | + {0xee, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | ||
| 127 | + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | ||
| 128 | + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, | ||
| 129 | + {0xed, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | ||
| 130 | + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | ||
| 131 | + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}, | ||
| 132 | + {0xed, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | ||
| 133 | + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | ||
| 134 | + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f}, | ||
| 135 | + }; | ||
| 136 | + | ||
| 137 | + // Ed448 has cofactor 4, so these four entries are the full canonical | ||
| 138 | + // small-order subgroup: identity, one point of order 2, and two points | ||
| 139 | + // of order 4. | ||
| 140 | + constexpr unsigned char kEd448SmallOrderPoints[][kEd448PointSize] = { | ||
| 141 | + // Identity. | ||
| 142 | + {0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
| 143 | + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
| 144 | + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
| 145 | + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
| 146 | + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, | ||
| 147 | + // Order 2. | ||
| 148 | + {0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | ||
| 149 | + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | ||
| 150 | + 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | ||
| 151 | + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | ||
| 152 | + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00}, | ||
| 153 | + // Order 4. | ||
| 154 | + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
| 155 | + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
| 156 | + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
| 157 | + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
| 158 | + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, | ||
| 159 | + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
| 160 | + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
| 161 | + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
| 162 | + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
| 163 | + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80}, | ||
| 164 | + }; | ||
| 165 | + | ||
| 166 | + template <size_t PointSize, size_t Count> | ||
| 167 | + bool ContainsPoint(const unsigned char* candidate, | ||
| 168 | + const unsigned char (&points)[Count][PointSize]) { | ||
| 169 | + for (const auto& point : points) { | ||
| 170 | + if (memcmp(candidate, point, PointSize) == 0) return true; | ||
| 171 | + } | ||
| 172 | + return false; | ||
| 173 | + } | ||
| 174 | + | ||
| 175 | + bool IsSmallOrderEdDsaPoint(int id, | ||
| 176 | + const unsigned char* candidate, | ||
| 177 | + size_t size) { | ||
| 178 | + switch (id) { | ||
| 179 | + case EVP_PKEY_ED25519: | ||
| 180 | + return size == kEd25519PointSize && | ||
| 181 | + ContainsPoint(candidate, kEd25519SmallOrderPoints); | ||
| 182 | + case EVP_PKEY_ED448: | ||
| 183 | + return size == kEd448PointSize && | ||
| 184 | + ContainsPoint(candidate, kEd448SmallOrderPoints); | ||
| 185 | + default: | ||
| 186 | + return false; | ||
| 187 | + } | ||
| 188 | + } | ||
| 189 | + | ||
| 190 | + bool HasSmallOrderEdDsaPoint(const EVPKeyPointer& key, | ||
| 191 | + const ByteSource& signature) { | ||
| 192 | + const int id = key.id(); | ||
| 193 | + size_t point_size; | ||
| 194 | + | ||
| 195 | + switch (id) { | ||
| 196 | + case EVP_PKEY_ED25519: | ||
| 197 | + point_size = kEd25519PointSize; | ||
| 198 | + break; | ||
| 199 | + case EVP_PKEY_ED448: | ||
| 200 | + point_size = kEd448PointSize; | ||
| 201 | + break; | ||
| 202 | + default: | ||
| 203 | + return false; | ||
| 204 | + } | ||
| 205 | + | ||
| 206 | + if (signature.size() != point_size * 2) return false; | ||
| 207 | + | ||
| 208 | + if (IsSmallOrderEdDsaPoint(id, signature.data<unsigned char>(), point_size)) { | ||
| 209 | + return true; | ||
| 210 | + } | ||
| 211 | + | ||
| 212 | + unsigned char raw_public_key[kEd448PointSize]; | ||
| 213 | + size_t raw_public_key_size = point_size; | ||
| 214 | + if (EVP_PKEY_get_raw_public_key( | ||
| 215 | + key.get(), raw_public_key, &raw_public_key_size) != 1) { | ||
| 216 | + return false; | ||
| 217 | + } | ||
| 218 | + | ||
| 219 | + return IsSmallOrderEdDsaPoint(id, raw_public_key, raw_public_key_size); | ||
| 220 | + } | ||
| 221 | + | ||
| 81 | 222 | std::unique_ptr<BackingStore> Node_SignFinal(Environment* env, | |
| 82 | 223 | EVPMDCtxPointer&& mdctx, | |
| 83 | 224 | const EVPKeyPointer& pkey, | |
@@ -757,7 +898,8 @@ bool SignTraits::DeriveBits(Environment* env, | |||
| 757 | 898 | case SignConfiguration::Mode::Verify: { | |
| 758 | 899 | auto buf = DataPointer::Alloc(1); | |
| 759 | 900 | static_cast<char*>(buf.get())[0] = 0; | |
| 760 | - if (context.verify(params.data, params.signature)) { | ||
| 901 | + if (context.verify(params.data, params.signature) && | ||
| 902 | + !HasSmallOrderEdDsaPoint(key, params.signature)) { | ||
| 761 | 903 | static_cast<char*>(buf.get())[0] = 1; | |
| 762 | 904 | } | |
| 763 | 905 | *out = ByteSource::Allocated(buf.release()); | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -15,6 +15,44 @@ const vectors = require('../fixtures/crypto/eddsa')(); | |||
| 15 | 15 | ||
| 16 | 16 | const supportsContext = hasOpenSSL(3, 2); | |
| 17 | 17 | ||
| 18 | + const smallOrderVerifyVectors = [ | ||
| 19 | + { | ||
| 20 | + name: 'Ed25519', | ||
| 21 | + publicKey: Buffer.from( | ||
| 22 | + 'c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac03fa', | ||
| 23 | + 'hex'), | ||
| 24 | + signature: Buffer.from( | ||
| 25 | + 'c7176a703d4dd84fba3c0b760d10670f2a2053fa2c39ccc64ec7fd7792ac037a' + | ||
| 26 | + '0000000000000000000000000000000000000000000000000000000000000000', | ||
| 27 | + 'hex'), | ||
| 28 | + data: Buffer.from( | ||
| 29 | + '8c93255d71dcab10e8f379c26200f3c7bd5f09d9bc3068d3ef4edeb4853022b6', | ||
| 30 | + 'hex'), | ||
| 31 | + }, | ||
| 32 | + ]; | ||
| 33 | + | ||
| 34 | + if (!process.features.openssl_is_boringssl) { | ||
| 35 | + smallOrderVerifyVectors.push({ | ||
| 36 | + name: 'Ed448', | ||
| 37 | + publicKey: Buffer.concat([Buffer.from([1]), Buffer.alloc(56)]), | ||
| 38 | + signature: Buffer.concat([Buffer.from([1]), Buffer.alloc(113)]), | ||
| 39 | + data: Buffer.from([1, 2, 3]), | ||
| 40 | + }); | ||
| 41 | + } | ||
| 42 | + | ||
| 43 | + async function testSmallOrderVerify({ name, publicKey, signature, data }) { | ||
| 44 | + const key = await subtle.importKey( | ||
| 45 | + 'raw', | ||
| 46 | + publicKey, | ||
| 47 | + { name }, | ||
| 48 | + false, | ||
| 49 | + ['verify']); | ||
| 50 | + | ||
| 51 | + assert.strictEqual( | ||
| 52 | + await subtle.verify({ name }, key, signature, data), | ||
| 53 | + false); | ||
| 54 | + } | ||
| 55 | + | ||
| 18 | 56 | async function testVerify({ name, | |
| 19 | 57 | context, | |
| 20 | 58 | publicKeyBuffer, | |
@@ -260,6 +298,9 @@ async function testSign({ name, | |||
| 260 | 298 | variations.push(testVerify(vector)); | |
| 261 | 299 | variations.push(testSign(vector)); | |
| 262 | 300 | }); | |
| 301 | + smallOrderVerifyVectors.forEach((vector) => { | ||
| 302 | + variations.push(testSmallOrderVerify(vector)); | ||
| 303 | + }); | ||
| 263 | 304 | ||
| 264 | 305 | await Promise.all(variations); | |
| 265 | 306 | })().then(common.mustCall()); | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -1,11 +1,7 @@ | |||
| 1 | 1 | 'use strict'; | |
| 2 | 2 | ||
| 3 | - const os = require('node:os'); | ||
| 4 | - | ||
| 5 | 3 | const { hasOpenSSL } = require('../../common/crypto.js'); | |
| 6 | 4 | ||
| 7 | - const s390x = os.arch() === 's390x'; | ||
| 8 | - | ||
| 9 | 5 | const conditionalFileSkips = {}; | |
| 10 | 6 | const conditionalSubtestSkips = {}; | |
| 11 | 7 | ||
@@ -115,21 +111,6 @@ module.exports = { | |||
| 115 | 111 | 'historical.any.js': { | |
| 116 | 112 | 'skip': 'Not relevant in Node.js context', | |
| 117 | 113 | }, | |
| 118 | - 'sign_verify/eddsa_small_order_points.https.any.js': { | ||
| 119 | - 'fail': { | ||
| 120 | - 'note': 'see https://github.com/nodejs/node/issues/54572', | ||
| 121 | - 'expected': [ | ||
| 122 | - 'Ed25519 Verification checks with small-order key of order - Test 1', | ||
| 123 | - 'Ed25519 Verification checks with small-order key of order - Test 2', | ||
| 124 | - 'Ed25519 Verification checks with small-order key of order - Test 12', | ||
| 125 | - 'Ed25519 Verification checks with small-order key of order - Test 13', | ||
| 126 | - ...(s390x ? [] : [ | ||
| 127 | - 'Ed25519 Verification checks with small-order key of order - Test 0', | ||
| 128 | - 'Ed25519 Verification checks with small-order key of order - Test 11', | ||
| 129 | - ]), | ||
| 130 | - ], | ||
| 131 | - }, | ||
| 132 | - }, | ||
| 133 | 114 | 'getRandomValues.any.js': { | |
| 134 | 115 | 'fail': { | |
| 135 | 116 | 'note': 'https://github.com/nodejs/node/issues/58987', | |
| Back | FazBrowse Home | New Git URL |
0 commit comments