From ad5b48dc4bcdf0b08e05abe4de5644ff80249093 Mon Sep 17 00:00:00 2001 From: David Drysdale Date: Sun, 18 Jul 2021 16:15:24 +0100 Subject: [PATCH] k256: add Wycheproof test vectors Generated with the tool from https://github.com/RustCrypto/utils/pull/280 using: cargo run ~/src/tink-rust/wycheproof/ secp256k1 0 secp256k1.blb secp256k1.txt This uses a manual expansion of the new_wycheproof_test! macro because an extra call to normalize_s() is needed. Contents of secp256k1.txt: ECDSA case 1 [valid] signature malleability ECDSA case 3 [valid] valid ECDSA case 4 [invalid] long form encoding of length of sequence ECDSA case 5 [invalid] length of sequence contains leading 0 ECDSA case 6 [invalid] wrong length of sequence ECDSA case 7 [invalid] wrong length of sequence ECDSA case 8 [invalid] uint32 overflow in length of sequence ECDSA case 9 [invalid] uint64 overflow in length of sequence ECDSA case 10 [invalid] length of sequence = 2**31 - 1 ECDSA case 11 [invalid] length of sequence = 2**32 - 1 ECDSA case 12 [invalid] length of sequence = 2**40 - 1 ECDSA case 13 [invalid] length of sequence = 2**64 - 1 ECDSA case 14 [invalid] incorrect length of sequence ECDSA case 15 [invalid] indefinite length without termination ECDSA case 16 [invalid] indefinite length without termination ECDSA case 17 [invalid] indefinite length without termination ECDSA case 18 [invalid] removing sequence ECDSA case 19 [invalid] lonely sequence tag ECDSA case 20 [invalid] appending 0's to sequence ECDSA case 21 [invalid] prepending 0's to sequence ECDSA case 22 [invalid] appending unused 0's to sequence ECDSA case 23 [invalid] appending null value to sequence 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 garbage ECDSA case 32 [invalid] including garbage 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] including undefined tags ECDSA case 38 [invalid] including undefined tags ECDSA case 39 [invalid] truncated length of sequence ECDSA case 40 [invalid] using composition with indefinite length ECDSA case 41 [invalid] using composition with indefinite length ECDSA case 42 [invalid] using composition with indefinite length ECDSA case 43 [invalid] using composition with wrong tag ECDSA case 44 [invalid] using composition with wrong tag ECDSA case 45 [invalid] using composition with wrong tag ECDSA case 46 [invalid] Replacing sequence with NULL 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] changing tag value of sequence ECDSA case 51 [invalid] changing tag value of sequence ECDSA case 52 [invalid] dropping value of sequence ECDSA case 53 [invalid] using composition for sequence ECDSA case 54 [invalid] truncated sequence ECDSA case 55 [invalid] truncated sequence ECDSA case 56 [invalid] indefinite length ECDSA case 57 [invalid] indefinite length with truncated delimiter ECDSA case 58 [invalid] indefinite length with additional element ECDSA case 59 [invalid] indefinite length with truncated element ECDSA case 60 [invalid] indefinite length with garbage ECDSA case 61 [invalid] indefinite length with nonempty EOC ECDSA case 62 [invalid] prepend empty sequence ECDSA case 63 [invalid] append empty sequence ECDSA case 64 [invalid] append garbage with high tag number ECDSA case 65 [invalid] sequence of sequence ECDSA case 66 [invalid] truncated sequence: removed last 1 elements ECDSA case 67 [invalid] repeating element in sequence ECDSA case 68 [invalid] long form encoding of length of integer ECDSA case 69 [invalid] long form encoding of length of integer ECDSA case 70 [invalid] length of integer contains leading 0 ECDSA case 71 [invalid] length of integer contains leading 0 ECDSA case 72 [invalid] wrong length of integer ECDSA case 73 [invalid] wrong length of integer ECDSA case 74 [invalid] wrong length of integer ECDSA case 75 [invalid] wrong length of integer ECDSA case 76 [invalid] uint32 overflow in length of integer ECDSA case 77 [invalid] uint32 overflow in length of integer ECDSA case 78 [invalid] uint64 overflow in length of integer ECDSA case 79 [invalid] uint64 overflow in length of integer ECDSA case 80 [invalid] length of integer = 2**31 - 1 ECDSA case 81 [invalid] length of integer = 2**31 - 1 ECDSA case 82 [invalid] length of integer = 2**32 - 1 ECDSA case 83 [invalid] length of integer = 2**32 - 1 ECDSA case 84 [invalid] length of integer = 2**40 - 1 ECDSA case 85 [invalid] length of integer = 2**40 - 1 ECDSA case 86 [invalid] length of integer = 2**64 - 1 ECDSA case 87 [invalid] length of integer = 2**64 - 1 ECDSA case 88 [invalid] incorrect length of integer ECDSA case 89 [invalid] incorrect length of integer ECDSA case 90 [invalid] removing integer ECDSA case 91 [invalid] lonely integer tag ECDSA case 92 [invalid] lonely integer tag ECDSA case 93 [invalid] appending 0's to integer ECDSA case 94 [invalid] appending 0's to integer ECDSA case 95 [invalid] prepending 0's to integer ECDSA case 96 [invalid] prepending 0's to integer ECDSA case 97 [invalid] appending unused 0's to integer ECDSA case 98 [invalid] appending null value to integer ECDSA case 99 [invalid] appending null value to integer ECDSA case 100 [invalid] truncated length of integer ECDSA case 101 [invalid] truncated length of integer ECDSA case 102 [invalid] Replacing integer with NULL ECDSA case 103 [invalid] Replacing integer with NULL 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] changing tag value of integer ECDSA case 113 [invalid] changing tag value of integer ECDSA case 114 [invalid] dropping value of integer ECDSA case 115 [invalid] dropping value of integer ECDSA case 116 [invalid] using composition for integer ECDSA case 117 [invalid] using composition for integer ECDSA case 118 [invalid] modify first byte of integer ECDSA case 119 [invalid] modify first byte of integer ECDSA case 120 [invalid] modify last byte of integer ECDSA case 121 [invalid] modify last byte of integer ECDSA case 122 [invalid] truncated integer ECDSA case 123 [invalid] truncated integer ECDSA case 124 [invalid] truncated integer ECDSA case 125 [invalid] leading ff in integer ECDSA case 126 [invalid] leading ff in integer ECDSA case 127 [invalid] replaced integer by infinity ECDSA case 128 [invalid] replaced integer by infinity ECDSA case 129 [invalid] replacing integer with zero ECDSA case 130 [invalid] replacing integer with zero 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] Signature with special case values for r and s 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 encoding contains wrong types. 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 [valid] Edge case for Shamir multiplication ECDSA case 231 [valid] special case hash 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] k*G has a large x-coordinate ECDSA case 286 [invalid] r too large ECDSA case 287 [valid] r,s are large ECDSA case 288 [valid] r and s^-1 have a large Hamming weight ECDSA case 289 [valid] r and s^-1 have a large Hamming weight ECDSA case 290 [valid] small r and s ECDSA case 291 [valid] small r and s ECDSA case 292 [valid] small r and s ECDSA case 293 [invalid] r is larger than n ECDSA case 294 [invalid] s is larger than n ECDSA case 295 [valid] small r and s^-1 ECDSA case 296 [valid] smallish r and s^-1 ECDSA case 297 [valid] 100-bit r and small s^-1 ECDSA case 298 [valid] small r and 100 bit s^-1 ECDSA case 299 [valid] 100-bit r and s^-1 ECDSA case 300 [valid] r and s^-1 are close to n ECDSA case 301 [valid] s == 1 ECDSA case 302 [invalid] s == 0 ECDSA case 303 [invalid] point at infinity during verify ECDSA case 304 [valid] edge case for signature malleability ECDSA case 305 [valid] edge case for signature malleability ECDSA case 306 [valid] u1 == 1 ECDSA case 307 [valid] u1 == n - 1 ECDSA case 308 [valid] u2 == 1 ECDSA case 309 [valid] u2 == n - 1 ECDSA case 310 [valid] edge case for u1 ECDSA case 311 [valid] edge case for u1 ECDSA case 312 [valid] edge case for u1 ECDSA case 313 [valid] edge case for u1 ECDSA case 314 [valid] edge case for u1 ECDSA case 315 [valid] edge case for u1 ECDSA case 316 [valid] edge case for u1 ECDSA case 317 [valid] edge case for u1 ECDSA case 318 [valid] edge case for u1 ECDSA case 319 [valid] edge case for u1 ECDSA case 320 [valid] edge case for u1 ECDSA case 321 [valid] edge case for u1 ECDSA case 322 [valid] edge case for u1 ECDSA case 323 [valid] edge case for u1 ECDSA case 324 [valid] edge case for u1 ECDSA case 325 [valid] edge case for u2 ECDSA case 326 [valid] edge case for u2 ECDSA case 327 [valid] edge case for u2 ECDSA case 328 [valid] edge case for u2 ECDSA case 329 [valid] edge case for u2 ECDSA case 330 [valid] edge case for u2 ECDSA case 331 [valid] edge case for u2 ECDSA case 332 [valid] edge case for u2 ECDSA case 333 [valid] edge case for u2 ECDSA case 334 [valid] edge case for u2 ECDSA case 335 [valid] edge case for u2 ECDSA case 336 [valid] edge case for u2 ECDSA case 337 [valid] edge case for u2 ECDSA case 338 [valid] edge case for u2 ECDSA case 339 [valid] edge case for u2 ECDSA case 340 [valid] point duplication during verification ECDSA case 341 [invalid] duplication bug ECDSA case 342 [invalid] comparison with point at infinity ECDSA case 343 [valid] extreme value for k and edgecase s ECDSA case 344 [valid] extreme value for k and s^-1 ECDSA case 345 [valid] extreme value for k and s^-1 ECDSA case 346 [valid] extreme value for k and s^-1 ECDSA case 347 [valid] extreme value for k and s^-1 ECDSA case 348 [valid] extreme value for k ECDSA case 349 [valid] extreme value for k and edgecase s ECDSA case 350 [valid] extreme value for k and s^-1 ECDSA case 351 [valid] extreme value for k and s^-1 ECDSA case 352 [valid] extreme value for k and s^-1 ECDSA case 353 [valid] extreme value for k and s^-1 ECDSA case 354 [valid] extreme value for k ECDSA case 355 [invalid] testing point duplication ECDSA case 356 [invalid] testing point duplication ECDSA case 357 [invalid] testing point duplication ECDSA case 358 [invalid] testing point duplication ECDSA case 359 [valid] pseudorandom signature ECDSA case 360 [valid] pseudorandom signature ECDSA case 361 [valid] pseudorandom signature ECDSA case 362 [valid] pseudorandom signature ECDSA case 363 [valid] y-coordinate of the public key is small ECDSA case 364 [valid] y-coordinate of the public key is small ECDSA case 365 [valid] y-coordinate of the public key is small ECDSA case 366 [valid] y-coordinate of the public key is large ECDSA case 367 [valid] y-coordinate of the public key is large ECDSA case 368 [valid] y-coordinate of the public key is large ECDSA case 369 [valid] x-coordinate of the public key is small ECDSA case 370 [valid] x-coordinate of the public key is small ECDSA case 371 [valid] x-coordinate of the public key is small ECDSA case 372 [valid] x-coordinate of the public key has many trailing 1's ECDSA case 373 [valid] x-coordinate of the public key has many trailing 1's ECDSA case 374 [valid] x-coordinate of the public key has many trailing 1's ECDSA case 375 [valid] y-coordinate of the public key has many trailing 1's ECDSA case 376 [valid] y-coordinate of the public key has many trailing 1's ECDSA case 377 [valid] y-coordinate of the public key has many trailing 1's ECDSA case 378 [valid] x-coordinate of the public key has many trailing 0's ECDSA case 379 [valid] x-coordinate of the public key has many trailing 0's ECDSA case 380 [valid] x-coordinate of the public key has many trailing 0's --- Cargo.lock | 1 + k256/Cargo.toml | 1 + k256/src/ecdsa.rs | 87 ++++++++++++++++++++++ k256/src/test_vectors/data/wycheproof.blb | Bin 0 -> 30900 bytes 4 files changed, 89 insertions(+) create mode 100644 k256/src/test_vectors/data/wycheproof.blb diff --git a/Cargo.lock b/Cargo.lock index 72862f3b..129706f9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -466,6 +466,7 @@ dependencies = [ name = "k256" version = "0.9.5" dependencies = [ + "blobby", "cfg-if", "criterion", "ecdsa", diff --git a/k256/Cargo.toml b/k256/Cargo.toml index c6fa395e..6625dff6 100644 --- a/k256/Cargo.toml +++ b/k256/Cargo.toml @@ -33,6 +33,7 @@ default-features = false features = ["der"] [dev-dependencies] +blobby = "0.3" criterion = "0.3" ecdsa-core = { version = "0.12.1", package = "ecdsa", default-features = false, features = ["dev"] } hex-literal = "0.3" diff --git a/k256/src/ecdsa.rs b/k256/src/ecdsa.rs index a6b243bc..8d9c0524 100644 --- a/k256/src/ecdsa.rs +++ b/k256/src/ecdsa.rs @@ -113,3 +113,90 @@ fn check_scalars(signature: &Signature) -> Result<(), Error> { Err(Error::new()) } } + +#[cfg(all(test, feature = "ecdsa", feature = "arithmetic"))] +mod tests { + mod wycheproof { + use crate::Secp256k1; + use ecdsa_core::{elliptic_curve::sec1::EncodedPoint, signature::Verifier, Signature}; + + #[test] + fn wycheproof() { + use blobby::Blob5Iterator; + use elliptic_curve::bigint::Encoding as _; + + // 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::UInt::BYTE_SIZE; + 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 { + 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 = + EncodedPoint::from_affine_coordinates(&x, &y, /* compress= */ false); + let verifying_key = + ecdsa_core::VerifyingKey::from_encoded_point(&q_encoded).unwrap(); + + let mut sig = match Signature::::from_der(sig) { + Ok(s) => s, + Err(_) if !pass => return None, + Err(_) => return Some("failed to parse signature ASN.1"), + }; + + sig.normalize_s().unwrap(); + + 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/k256/src/test_vectors/data/wycheproof.blb b/k256/src/test_vectors/data/wycheproof.blb new file mode 100644 index 0000000000000000000000000000000000000000..e36ba525975f716aa4f43dd024a4581909ed36a5 GIT binary patch literal 30900 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 b`fW1qq5inl*cY-eCo0<3+7R8d?vVcnBDz1u literal 0 HcmV?d00001