From 3055a69e8e49f553a3bc00e3394550a1587948e3 Mon Sep 17 00:00:00 2001 From: Tony Arcieri Date: Thu, 9 Nov 2023 18:05:29 -0600 Subject: [PATCH] p521: add Wycheproof test vectors (#957) Generated using the `wycheproof2blb` utility: $ cargo run ~/src/wycheproof secp521r1 521 wycheproof.blb desc.txt This required a small change to `wycheproof2blb`: https://github.com/RustCrypto/utils/pull/980 Includes the following test vectors: ECDSA case 1 [valid] signature malleability ECDSA case 2 [valid] valid ECDSA case 3 [invalid] length of sequence contains leading 0 ECDSA case 4 [invalid] wrong length of sequence ECDSA case 5 [invalid] wrong length of sequence ECDSA case 6 [invalid] uint32 overflow in length of sequence ECDSA case 7 [invalid] uint64 overflow in length of sequence ECDSA case 8 [invalid] length of sequence = 2**31 - 1 ECDSA case 9 [invalid] length of sequence = 2**32 - 1 ECDSA case 10 [invalid] length of sequence = 2**40 - 1 ECDSA case 11 [invalid] length of sequence = 2**64 - 1 ECDSA case 12 [invalid] incorrect length of sequence ECDSA case 13 [invalid] indefinite length without termination ECDSA case 14 [invalid] indefinite length without termination ECDSA case 15 [invalid] indefinite length without termination ECDSA case 16 [invalid] removing sequence ECDSA case 17 [invalid] lonely sequence tag ECDSA case 18 [invalid] appending 0's to sequence ECDSA case 19 [invalid] prepending 0's to sequence ECDSA case 20 [invalid] appending unused 0's to sequence ECDSA case 21 [invalid] appending null value to sequence ECDSA case 22 [invalid] including garbage ECDSA case 23 [invalid] including garbage ECDSA case 24 [invalid] including garbage ECDSA case 25 [invalid] including garbage ECDSA case 26 [invalid] including garbage ECDSA case 27 [invalid] including garbage ECDSA case 28 [invalid] including garbage ECDSA case 29 [invalid] including garbage ECDSA case 30 [invalid] including garbage ECDSA case 31 [invalid] including undefined tags ECDSA case 32 [invalid] including undefined tags ECDSA case 33 [invalid] including undefined tags ECDSA case 34 [invalid] including undefined tags ECDSA case 35 [invalid] including undefined tags ECDSA case 36 [invalid] including undefined tags ECDSA case 37 [invalid] truncated length of sequence ECDSA case 38 [invalid] using composition with indefinite length ECDSA case 39 [invalid] using composition with indefinite length ECDSA case 40 [invalid] using composition with indefinite length ECDSA case 41 [invalid] using composition with wrong tag ECDSA case 42 [invalid] using composition with wrong tag ECDSA case 43 [invalid] using composition with wrong tag ECDSA case 44 [invalid] Replacing sequence with NULL ECDSA case 45 [invalid] changing tag value of sequence ECDSA case 46 [invalid] changing tag value of sequence ECDSA case 47 [invalid] changing tag value of sequence ECDSA case 48 [invalid] changing tag value of sequence ECDSA case 49 [invalid] changing tag value of sequence ECDSA case 50 [invalid] dropping value of sequence ECDSA case 51 [invalid] using composition for sequence ECDSA case 52 [invalid] truncated sequence ECDSA case 53 [invalid] truncated sequence ECDSA case 54 [invalid] indefinite length ECDSA case 55 [invalid] indefinite length with truncated delimiter ECDSA case 56 [invalid] indefinite length with additional element ECDSA case 57 [invalid] indefinite length with truncated element ECDSA case 58 [invalid] indefinite length with garbage ECDSA case 59 [invalid] indefinite length with nonempty EOC ECDSA case 60 [invalid] prepend empty sequence ECDSA case 61 [invalid] append empty sequence ECDSA case 62 [invalid] append garbage with high tag number ECDSA case 63 [invalid] sequence of sequence ECDSA case 64 [invalid] truncated sequence: removed last 1 elements ECDSA case 65 [invalid] repeating element in sequence ECDSA case 66 [invalid] long form encoding of length of integer ECDSA case 67 [invalid] long form encoding of length of integer ECDSA case 68 [invalid] length of integer contains leading 0 ECDSA case 69 [invalid] length of integer contains leading 0 ECDSA case 70 [invalid] wrong length of integer ECDSA case 71 [invalid] wrong length of integer ECDSA case 72 [invalid] wrong length of integer ECDSA case 73 [invalid] wrong length of integer ECDSA case 74 [invalid] uint32 overflow in length of integer ECDSA case 75 [invalid] uint32 overflow in length of integer ECDSA case 76 [invalid] uint64 overflow in length of integer ECDSA case 77 [invalid] uint64 overflow in length of integer ECDSA case 78 [invalid] length of integer = 2**31 - 1 ECDSA case 79 [invalid] length of integer = 2**31 - 1 ECDSA case 80 [invalid] length of integer = 2**32 - 1 ECDSA case 81 [invalid] length of integer = 2**32 - 1 ECDSA case 82 [invalid] length of integer = 2**40 - 1 ECDSA case 83 [invalid] length of integer = 2**40 - 1 ECDSA case 84 [invalid] length of integer = 2**64 - 1 ECDSA case 85 [invalid] length of integer = 2**64 - 1 ECDSA case 86 [invalid] incorrect length of integer ECDSA case 87 [invalid] incorrect length of integer ECDSA case 88 [invalid] removing integer ECDSA case 89 [invalid] lonely integer tag ECDSA case 90 [invalid] lonely integer tag ECDSA case 91 [invalid] appending 0's to integer ECDSA case 92 [invalid] appending 0's to integer ECDSA case 93 [invalid] prepending 0's to integer ECDSA case 94 [invalid] prepending 0's to integer ECDSA case 95 [invalid] appending unused 0's to integer ECDSA case 96 [invalid] appending null value to integer ECDSA case 97 [invalid] appending null value to integer ECDSA case 98 [invalid] truncated length of integer ECDSA case 99 [invalid] truncated length of integer ECDSA case 100 [invalid] Replacing integer with NULL ECDSA case 101 [invalid] Replacing integer with NULL ECDSA case 102 [invalid] changing tag value of integer ECDSA case 103 [invalid] changing tag value of integer ECDSA case 104 [invalid] changing tag value of integer ECDSA case 105 [invalid] changing tag value of integer ECDSA case 106 [invalid] changing tag value of integer ECDSA case 107 [invalid] changing tag value of integer ECDSA case 108 [invalid] changing tag value of integer ECDSA case 109 [invalid] changing tag value of integer ECDSA case 110 [invalid] changing tag value of integer ECDSA case 111 [invalid] changing tag value of integer ECDSA case 112 [invalid] dropping value of integer ECDSA case 113 [invalid] dropping value of integer ECDSA case 114 [invalid] using composition for integer ECDSA case 115 [invalid] using composition for integer ECDSA case 116 [invalid] modify first byte of integer ECDSA case 117 [invalid] modify first byte of integer ECDSA case 118 [invalid] modify last byte of integer ECDSA case 119 [invalid] modify last byte of integer ECDSA case 120 [invalid] truncated integer ECDSA case 121 [invalid] truncated integer ECDSA case 122 [invalid] truncated integer ECDSA case 123 [invalid] truncated integer ECDSA case 124 [invalid] leading ff in integer ECDSA case 125 [invalid] leading ff in integer ECDSA case 126 [invalid] replaced integer by infinity ECDSA case 127 [invalid] replaced integer by infinity ECDSA case 128 [invalid] replacing integer with zero ECDSA case 129 [invalid] replacing integer with zero ECDSA case 130 [invalid] Modified r or s, e.g. by adding or subtracting the order of the group ECDSA case 131 [invalid] Modified r or s, e.g. by adding or subtracting the order of the group ECDSA case 132 [invalid] Modified r or s, e.g. by adding or subtracting the order of the group ECDSA case 133 [invalid] Modified r or s, e.g. by adding or subtracting the order of the group ECDSA case 134 [invalid] Modified r or s, e.g. by adding or subtracting the order of the group ECDSA case 135 [invalid] Modified r or s, e.g. by adding or subtracting the order of the group ECDSA case 136 [invalid] Modified r or s, e.g. by adding or subtracting the order of the group ECDSA case 137 [invalid] Modified r or s, e.g. by adding or subtracting the order of the group ECDSA case 138 [invalid] Modified r or s, e.g. by adding or subtracting the order of the group ECDSA case 139 [invalid] Modified r or s, e.g. by adding or subtracting the order of the group ECDSA case 140 [invalid] Modified r or s, e.g. by adding or subtracting the order of the group ECDSA case 141 [invalid] Modified r or s, e.g. by adding or subtracting the order of the group ECDSA case 142 [invalid] Modified r or s, e.g. by adding or subtracting the order of the group ECDSA case 143 [invalid] Modified r or s, e.g. by adding or subtracting the order of the group ECDSA case 144 [invalid] Modified r or s, e.g. by adding or subtracting the order of the group ECDSA case 145 [invalid] Signature with special case values for r and s ECDSA case 146 [invalid] Signature with special case values for r and s ECDSA case 147 [invalid] Signature with special case values for r and s ECDSA case 148 [invalid] Signature with special case values for r and s ECDSA case 149 [invalid] Signature with special case values for r and s ECDSA case 150 [invalid] Signature with special case values for r and s ECDSA case 151 [invalid] Signature with special case values for r and s ECDSA case 152 [invalid] Signature with special case values for r and s ECDSA case 153 [invalid] Signature with special case values for r and s ECDSA case 154 [invalid] Signature with special case values for r and s ECDSA case 155 [invalid] Signature with special case values for r and s ECDSA case 156 [invalid] Signature with special case values for r and s ECDSA case 157 [invalid] Signature with special case values for r and s ECDSA case 158 [invalid] Signature with special case values for r and s ECDSA case 159 [invalid] Signature with special case values for r and s ECDSA case 160 [invalid] Signature with special case values for r and s ECDSA case 161 [invalid] Signature with special case values for r and s ECDSA case 162 [invalid] Signature with special case values for r and s ECDSA case 163 [invalid] Signature with special case values for r and s ECDSA case 164 [invalid] Signature with special case values for r and s ECDSA case 165 [invalid] Signature with special case values for r and s ECDSA case 166 [invalid] Signature with special case values for r and s ECDSA case 167 [invalid] Signature with special case values for r and s ECDSA case 168 [invalid] Signature with special case values for r and s ECDSA case 169 [invalid] Signature with special case values for r and s ECDSA case 170 [invalid] Signature with special case values for r and s ECDSA case 171 [invalid] Signature with special case values for r and s ECDSA case 172 [invalid] Signature with special case values for r and s ECDSA case 173 [invalid] Signature with special case values for r and s ECDSA case 174 [invalid] Signature with special case values for r and s ECDSA case 175 [invalid] Signature with special case values for r and s ECDSA case 176 [invalid] Signature with special case values for r and s ECDSA case 177 [invalid] Signature with special case values for r and s ECDSA case 178 [invalid] Signature with special case values for r and s ECDSA case 179 [invalid] Signature with special case values for r and s ECDSA case 180 [invalid] Signature with special case values for r and s ECDSA case 181 [invalid] Signature with special case values for r and s ECDSA case 182 [invalid] Signature with special case values for r and s ECDSA case 183 [invalid] Signature with special case values for r and s ECDSA case 184 [invalid] Signature with special case values for r and s ECDSA case 185 [invalid] Signature with special case values for r and s ECDSA case 186 [invalid] Signature with special case values for r and s ECDSA case 187 [invalid] Signature with special case values for r and s ECDSA case 188 [invalid] Signature with special case values for r and s ECDSA case 189 [invalid] Signature with special case values for r and s ECDSA case 190 [invalid] Signature with special case values for r and s ECDSA case 191 [invalid] Signature with special case values for r and s ECDSA case 192 [invalid] Signature with special case values for r and s ECDSA case 193 [invalid] Signature with special case values for r and s ECDSA case 194 [invalid] Signature with special case values for r and s ECDSA case 195 [invalid] Signature with special case values for r and s ECDSA case 196 [invalid] Signature with special case values for r and s ECDSA case 197 [invalid] Signature with special case values for r and s ECDSA case 198 [invalid] Signature with special case values for r and s ECDSA case 199 [invalid] Signature with special case values for r and s ECDSA case 200 [invalid] Signature with special case values for r and s ECDSA case 201 [invalid] Signature with special case values for r and s ECDSA case 202 [invalid] Signature with special case values for r and s ECDSA case 203 [invalid] Signature with special case values for r and s ECDSA case 204 [invalid] Signature with special case values for r and s ECDSA case 205 [invalid] Signature with special case values for r and s ECDSA case 206 [invalid] Signature with special case values for r and s ECDSA case 207 [invalid] Signature with special case values for r and s ECDSA case 208 [invalid] Signature with special case values for r and s ECDSA case 209 [invalid] Signature with special case values for r and s ECDSA case 210 [invalid] Signature with special case values for r and s ECDSA case 211 [invalid] Signature with special case values for r and s ECDSA case 212 [invalid] Signature with special case values for r and s ECDSA case 213 [invalid] Signature with special case values for r and s ECDSA case 214 [invalid] Signature with special case values for r and s ECDSA case 215 [invalid] Signature with special case values for r and s ECDSA case 216 [invalid] Signature with special case values for r and s ECDSA case 217 [invalid] Signature with special case values for r and s ECDSA case 218 [invalid] Signature with special case values for r and s ECDSA case 219 [invalid] Signature with special case values for r and s ECDSA case 220 [invalid] Signature with special case values for r and s ECDSA case 221 [invalid] Signature with special case values for r and s ECDSA case 222 [invalid] Signature with special case values for r and s ECDSA case 223 [invalid] Signature with special case values for r and s ECDSA case 224 [invalid] Signature with special case values for r and s ECDSA case 225 [invalid] Signature encoding contains wrong types. ECDSA case 226 [invalid] Signature encoding contains wrong types. ECDSA case 227 [invalid] Signature encoding contains wrong types. ECDSA case 228 [invalid] Signature encoding contains wrong types. ECDSA case 229 [invalid] Signature encoding contains wrong types. ECDSA case 230 [invalid] Signature encoding contains wrong types. ECDSA case 231 [valid] Edge case for Shamir multiplication ECDSA case 232 [valid] special case hash ECDSA case 233 [valid] special case hash ECDSA case 234 [valid] special case hash ECDSA case 235 [valid] special case hash ECDSA case 236 [valid] special case hash ECDSA case 237 [valid] special case hash ECDSA case 238 [valid] special case hash ECDSA case 239 [valid] special case hash ECDSA case 240 [valid] special case hash ECDSA case 241 [valid] special case hash ECDSA case 242 [valid] special case hash ECDSA case 243 [valid] special case hash ECDSA case 244 [valid] special case hash ECDSA case 245 [valid] special case hash ECDSA case 246 [valid] special case hash ECDSA case 247 [valid] special case hash ECDSA case 248 [valid] special case hash ECDSA case 249 [valid] special case hash ECDSA case 250 [valid] special case hash ECDSA case 251 [valid] special case hash ECDSA case 252 [valid] special case hash ECDSA case 253 [valid] special case hash ECDSA case 254 [valid] special case hash ECDSA case 255 [valid] special case hash ECDSA case 256 [valid] special case hash ECDSA case 257 [valid] special case hash ECDSA case 258 [valid] special case hash ECDSA case 259 [valid] special case hash ECDSA case 260 [valid] special case hash ECDSA case 261 [valid] special case hash ECDSA case 262 [valid] special case hash ECDSA case 263 [valid] special case hash ECDSA case 264 [valid] special case hash ECDSA case 265 [valid] special case hash ECDSA case 266 [valid] special case hash ECDSA case 267 [valid] special case hash ECDSA case 268 [valid] special case hash ECDSA case 269 [valid] special case hash ECDSA case 270 [valid] special case hash ECDSA case 271 [valid] special case hash ECDSA case 272 [valid] special case hash ECDSA case 273 [valid] special case hash ECDSA case 274 [valid] special case hash ECDSA case 275 [valid] special case hash ECDSA case 276 [valid] special case hash ECDSA case 277 [valid] special case hash ECDSA case 278 [valid] special case hash ECDSA case 279 [valid] special case hash ECDSA case 280 [valid] special case hash ECDSA case 281 [valid] special case hash ECDSA case 282 [valid] special case hash ECDSA case 283 [valid] special case hash ECDSA case 284 [valid] special case hash ECDSA case 285 [valid] special case hash ECDSA case 286 [valid] special case hash ECDSA case 287 [valid] special case hash ECDSA case 288 [valid] special case hash ECDSA case 289 [valid] special case hash ECDSA case 290 [valid] special case hash ECDSA case 291 [valid] special case hash ECDSA case 292 [valid] special case hash ECDSA case 293 [valid] special case hash ECDSA case 294 [valid] special case hash ECDSA case 295 [valid] special case hash ECDSA case 296 [valid] special case hash ECDSA case 297 [valid] special case hash ECDSA case 298 [valid] special case hash ECDSA case 299 [valid] special case hash ECDSA case 300 [valid] special case hash ECDSA case 301 [valid] special case hash ECDSA case 302 [valid] special case hash ECDSA case 303 [valid] special case hash ECDSA case 304 [valid] special case hash ECDSA case 305 [valid] special case hash ECDSA case 306 [valid] special case hash ECDSA case 307 [valid] special case hash ECDSA case 308 [valid] special case hash ECDSA case 309 [valid] special case hash ECDSA case 310 [valid] special case hash ECDSA case 311 [valid] special case hash ECDSA case 312 [valid] special case hash ECDSA case 313 [valid] special case hash ECDSA case 314 [valid] special case hash ECDSA case 315 [valid] special case hash ECDSA case 316 [valid] special case hash ECDSA case 317 [valid] special case hash ECDSA case 318 [valid] special case hash ECDSA case 319 [valid] special case hash ECDSA case 320 [valid] special case hash ECDSA case 321 [valid] special case hash ECDSA case 322 [valid] special case hash ECDSA case 323 [valid] special case hash ECDSA case 324 [valid] special case hash ECDSA case 325 [valid] special case hash ECDSA case 326 [valid] special case hash ECDSA case 327 [valid] special case hash ECDSA case 328 [valid] special case hash ECDSA case 329 [valid] special case hash ECDSA case 330 [valid] special case hash ECDSA case 331 [valid] special case hash ECDSA case 332 [valid] special case hash ECDSA case 333 [valid] special case hash ECDSA case 334 [valid] special case hash ECDSA case 335 [valid] special case hash ECDSA case 336 [valid] special case hash ECDSA case 337 [valid] special case hash ECDSA case 338 [valid] special case hash ECDSA case 339 [valid] special case hash ECDSA case 340 [valid] special case hash ECDSA case 341 [valid] special case hash ECDSA case 342 [valid] special case hash ECDSA case 343 [valid] special case hash ECDSA case 344 [valid] special case hash ECDSA case 345 [valid] special case hash ECDSA case 346 [valid] special case hash ECDSA case 347 [valid] special case hash ECDSA case 348 [valid] special case hash ECDSA case 349 [valid] special case hash ECDSA case 350 [valid] special case hash ECDSA case 351 [valid] special case hash ECDSA case 352 [valid] special case hash ECDSA case 353 [valid] special case hash ECDSA case 354 [valid] special case hash ECDSA case 355 [valid] k*G has a large x-coordinate ECDSA case 356 [invalid] r too large ECDSA case 357 [valid] r,s are large ECDSA case 358 [valid] r and s^-1 have a large Hamming weight ECDSA case 359 [valid] r and s^-1 have a large Hamming weight ECDSA case 360 [valid] small r and s ECDSA case 361 [valid] small r and s ECDSA case 362 [valid] small r and s ECDSA case 363 [invalid] r is larger than n ECDSA case 364 [invalid] s is larger than n ECDSA case 365 [valid] small r and s^-1 ECDSA case 366 [valid] smallish r and s^-1 ECDSA case 367 [valid] 100-bit r and small s^-1 ECDSA case 368 [valid] small r and 100 bit s^-1 ECDSA case 369 [valid] 100-bit r and s^-1 ECDSA case 370 [valid] r and s^-1 are close to n ECDSA case 371 [valid] s == 1 ECDSA case 372 [invalid] s == 0 ECDSA case 373 [invalid] point at infinity during verify ECDSA case 374 [valid] edge case for signature malleability ECDSA case 375 [valid] edge case for signature malleability ECDSA case 376 [valid] u1 == 1 ECDSA case 377 [valid] u1 == n - 1 ECDSA case 378 [valid] u2 == 1 ECDSA case 379 [valid] u2 == n - 1 ECDSA case 380 [valid] edge case for u1 ECDSA case 381 [valid] edge case for u1 ECDSA case 382 [valid] edge case for u1 ECDSA case 383 [valid] edge case for u1 ECDSA case 384 [valid] edge case for u1 ECDSA case 385 [valid] edge case for u1 ECDSA case 386 [valid] edge case for u1 ECDSA case 387 [valid] edge case for u1 ECDSA case 388 [valid] edge case for u1 ECDSA case 389 [valid] edge case for u1 ECDSA case 390 [valid] edge case for u1 ECDSA case 391 [valid] edge case for u1 ECDSA case 392 [valid] edge case for u1 ECDSA case 393 [valid] edge case for u1 ECDSA case 394 [valid] edge case for u2 ECDSA case 395 [valid] edge case for u2 ECDSA case 396 [valid] edge case for u2 ECDSA case 397 [valid] edge case for u2 ECDSA case 398 [valid] edge case for u2 ECDSA case 399 [valid] edge case for u2 ECDSA case 400 [valid] edge case for u2 ECDSA case 401 [valid] edge case for u2 ECDSA case 402 [valid] edge case for u2 ECDSA case 403 [valid] edge case for u2 ECDSA case 404 [valid] edge case for u2 ECDSA case 405 [valid] edge case for u2 ECDSA case 406 [valid] edge case for u2 ECDSA case 407 [valid] edge case for u2 ECDSA case 408 [valid] point duplication during verification ECDSA case 409 [invalid] duplication bug ECDSA case 410 [invalid] point with x-coordinate 0 ECDSA case 411 [invalid] point with x-coordinate 0 ECDSA case 412 [invalid] comparison with point at infinity ECDSA case 413 [valid] extreme value for k and edgecase s ECDSA case 414 [valid] extreme value for k and s^-1 ECDSA case 415 [valid] extreme value for k and s^-1 ECDSA case 416 [valid] extreme value for k and s^-1 ECDSA case 417 [valid] extreme value for k and s^-1 ECDSA case 418 [valid] extreme value for k ECDSA case 419 [valid] extreme value for k and edgecase s ECDSA case 420 [valid] extreme value for k and s^-1 ECDSA case 421 [valid] extreme value for k and s^-1 ECDSA case 422 [valid] extreme value for k and s^-1 ECDSA case 423 [valid] extreme value for k and s^-1 ECDSA case 424 [valid] extreme value for k ECDSA case 425 [invalid] testing point duplication ECDSA case 426 [invalid] testing point duplication ECDSA case 427 [invalid] testing point duplication ECDSA case 428 [invalid] testing point duplication ECDSA case 429 [valid] pseudorandom signature ECDSA case 430 [valid] pseudorandom signature ECDSA case 431 [valid] pseudorandom signature ECDSA case 432 [valid] pseudorandom signature ECDSA case 433 [valid] y-coordinate of the public key is small ECDSA case 434 [valid] y-coordinate of the public key is small ECDSA case 435 [valid] y-coordinate of the public key is small ECDSA case 436 [valid] y-coordinate of the public key is large ECDSA case 437 [valid] y-coordinate of the public key is large ECDSA case 438 [valid] y-coordinate of the public key is large ECDSA case 439 [valid] x-coordinate of the public key is small ECDSA case 440 [valid] x-coordinate of the public key is small ECDSA case 441 [valid] x-coordinate of the public key is small ECDSA case 442 [valid] x-coordinate of the public key is large ECDSA case 443 [valid] x-coordinate of the public key is large ECDSA case 444 [valid] x-coordinate of the public key is large ECDSA case 445 [valid] y-coordinate of the public key has many trailing 1's ECDSA case 446 [valid] y-coordinate of the public key has many trailing 1's ECDSA case 447 [valid] y-coordinate of the public key has many trailing 1's --- Cargo.lock | 1 + p521/Cargo.toml | 1 + p521/src/ecdsa.rs | 90 ++++++++++++++++++++-- p521/src/test_vectors/data/wycheproof.blb | Bin 0 -> 67526 bytes 4 files changed, 87 insertions(+), 5 deletions(-) create mode 100644 p521/src/test_vectors/data/wycheproof.blb diff --git a/Cargo.lock b/Cargo.lock index b70f2b25..17ed3526 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -779,6 +779,7 @@ name = "p521" version = "0.13.0" dependencies = [ "base16ct", + "blobby", "ecdsa", "elliptic-curve", "hex-literal", diff --git a/p521/Cargo.toml b/p521/Cargo.toml index bd3b9a68..513421dc 100644 --- a/p521/Cargo.toml +++ b/p521/Cargo.toml @@ -27,6 +27,7 @@ rand_core = { version = "0.6", optional = true, default-features = false } sha2 = { version = "0.10", optional = true, default-features = false } [dev-dependencies] +blobby = "0.3" ecdsa-core = { version = "0.16", package = "ecdsa", default-features = false, features = ["dev"] } hex-literal = "0.4" primeorder = { version = "0.13.3", features = ["dev"], path = "../primeorder" } diff --git a/p521/src/ecdsa.rs b/p521/src/ecdsa.rs index aafa4695..659aeed1 100644 --- a/p521/src/ecdsa.rs +++ b/p521/src/ecdsa.rs @@ -241,9 +241,89 @@ mod tests { ecdsa_core::new_verification_test!(NistP521, ECDSA_TEST_VECTORS); } - // TODO(tarcieri): wycheproof test vectors - // mod wycheproof { - // use crate::NistP521; - // ecdsa_core::new_wycheproof_test!(wycheproof, "wycheproof", NistP521); - // } + mod wycheproof { + use crate::{ + ecdsa::{Signature, Verifier, VerifyingKey}, + EncodedPoint, NistP521, + }; + + // TODO: use ecdsa_core::new_wycheproof_test!(wycheproof, "wycheproof", NistP521); + #[test] + fn wycheproof() { + use blobby::Blob5Iterator; + use elliptic_curve::generic_array::typenum::Unsigned; + + // Build a field element but allow for too-short input (left pad with zeros) + // or too-long input (check excess leftmost bytes are zeros). + fn element_from_padded_slice( + data: &[u8], + ) -> elliptic_curve::FieldBytes { + let point_len = C::FieldBytesSize::USIZE; + if data.len() >= point_len { + let offset = data.len() - point_len; + for v in data.iter().take(offset) { + assert_eq!(*v, 0, "EcdsaVerifier: point too large"); + } + elliptic_curve::FieldBytes::::clone_from_slice(&data[offset..]) + } else { + // Provided slice is too short and needs to be padded with zeros + // on the left. Build a combined exact iterator to do this. + let iter = core::iter::repeat(0) + .take(point_len - data.len()) + .chain(data.iter().cloned()); + elliptic_curve::FieldBytes::::from_exact_iter(iter).unwrap() + } + } + + fn run_test( + wx: &[u8], + wy: &[u8], + msg: &[u8], + sig: &[u8], + pass: bool, + ) -> Option<&'static str> { + let x = element_from_padded_slice::(wx); + let y = element_from_padded_slice::(wy); + let q_encoded = + EncodedPoint::from_affine_coordinates(&x, &y, /* compress= */ false); + let verifying_key = VerifyingKey::from_encoded_point(&q_encoded).unwrap(); + + let sig = match Signature::from_der(sig) { + Ok(s) => s, + Err(_) if !pass => return None, + Err(_) => return Some("failed to parse signature ASN.1"), + }; + + match verifying_key.verify(msg, &sig) { + Ok(_) if pass => None, + Ok(_) => Some("signature verify unexpectedly succeeded"), + Err(_) if !pass => None, + Err(_) => Some("signature verify failed"), + } + } + + let data = include_bytes!(concat!("test_vectors/data/wycheproof.blb")); + + for (i, row) in Blob5Iterator::new(data).unwrap().enumerate() { + let [wx, wy, msg, sig, status] = row.unwrap(); + let pass = match status[0] { + 0 => false, + 1 => true, + _ => panic!("invalid value for pass flag"), + }; + if let Some(desc) = run_test(wx, wy, msg, sig, pass) { + panic!( + "\n\ + Failed test №{}: {}\n\ + wx:\t{:?}\n\ + wy:\t{:?}\n\ + msg:\t{:?}\n\ + sig:\t{:?}\n\ + pass:\t{}\n", + i, desc, wx, wy, msg, sig, pass, + ); + } + } + } + } } diff --git a/p521/src/test_vectors/data/wycheproof.blb b/p521/src/test_vectors/data/wycheproof.blb new file mode 100644 index 0000000000000000000000000000000000000000..2ab50eab1b3c7ad72e3b8ecec3bd1a75119608e7 GIT binary patch literal 67526 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