1// Copyright 2020 Google LLC 2// 3// Licensed under the Apache License, Version 2.0 (the "License"); 4// you may not use this file except in compliance with the License. 5// You may obtain a copy of the License at 6// 7// http://www.apache.org/licenses/LICENSE-2.0 8// 9// Unless required by applicable law or agreed to in writing, software 10// distributed under the License is distributed on an "AS IS" BASIS, 11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12// See the License for the specific language governing permissions and 13// limitations under the License. 14// 15//////////////////////////////////////////////////////////////////////////////// 16 17package subtle_test 18 19import ( 20 "bytes" 21 "crypto/ecdsa" 22 "crypto/elliptic" 23 "crypto/x509" 24 "encoding/hex" 25 "errors" 26 "fmt" 27 "math/big" 28 "strings" 29 "testing" 30 31 "github.com/google/tink/go/hybrid/subtle" 32 "github.com/google/tink/go/testutil" 33) 34 35// The tests are from 36// http://google.github.io/end-to-end/api/source/src/javascript/crypto/e2e/ecc/ecdh_testdata.js.src.html. 37type testEC1 struct { 38 elliptic.Curve 39 pubX, pubY string 40} 41 42type testEC2 struct { 43 elliptic.Curve 44 pointFormat string 45 encoded string 46 X, Y string 47} 48 49var ( 50 tEC1 = []testEC1{ 51 { 52 elliptic.P256(), 53 "700c48f77f56584c5cc632ca65640db91b6bacce3a4df6b42ce7cc838833d287", 54 "db71e509e3fd9b060ddb20ba5c51dcc5948d46fbf640dfe0441782cab85fa4ac", 55 }, 56 { 57 elliptic.P256(), 58 "809f04289c64348c01515eb03d5ce7ac1a8cb9498f5caa50197e58d43a86a7ae", 59 "b29d84e811197f25eba8f5194092cb6ff440e26d4421011372461f579271cda3", 60 }, 61 { 62 elliptic.P256(), 63 "df3989b9fa55495719b3cf46dccd28b5153f7808191dd518eff0c3cff2b705ed", 64 "422294ff46003429d739a33206c8752552c8ba54a270defc06e221e0feaf6ac4", 65 }, 66 { 67 elliptic.P256(), 68 "356c5a444c049a52fee0adeb7e5d82ae5aa83030bfff31bbf8ce2096cf161c4b", 69 "57d128de8b2a57a094d1a001e572173f96e8866ae352bf29cddaf92fc85b2f92", 70 }, 71 { 72 elliptic.P384(), 73 "a7c76b970c3b5fe8b05d2838ae04ab47697b9eaf52e764592efda27fe7513272" + 74 "734466b400091adbf2d68c58e0c50066", 75 "ac68f19f2e1cb879aed43a9969b91a0839c4c38a49749b661efedf243451915e" + 76 "d0905a32b060992b468c64766fc8437a", 77 }, 78 { 79 elliptic.P384(), 80 "30f43fcf2b6b00de53f624f1543090681839717d53c7c955d1d69efaf0349b736" + 81 "3acb447240101cbb3af6641ce4b88e0", 82 "25e46c0c54f0162a77efcc27b6ea792002ae2ba82714299c860857a68153ab62e" + 83 "525ec0530d81b5aa15897981e858757", 84 }, 85 { 86 elliptic.P521(), 87 "000000685a48e86c79f0f0875f7bc18d25eb5fc8c0b07e5da4f4370f3a9490340" + 88 "854334b1e1b87fa395464c60626124a4e70d0f785601d37c09870ebf176666877a2" + 89 "046d", 90 "000001ba52c56fc8776d9e8f5db4f0cc27636d0b741bbe05400697942e80b7398" + 91 "84a83bde99e0f6716939e632bc8986fa18dccd443a348b6c3e522497955a4f3c302" + 92 "f676", 93 }, 94 { 95 elliptic.P521(), 96 "000001df277c152108349bc34d539ee0cf06b24f5d3500677b4445453ccc21409" + 97 "453aafb8a72a0be9ebe54d12270aa51b3ab7f316aa5e74a951c5e53f74cd95fc29a" + 98 "ee7a", 99 "0000013d52f33a9f3c14384d1587fa8abe7aed74bc33749ad9c570b471776422c" + 100 "7d4505d9b0a96b3bfac041e4c6a6990ae7f700e5b4a6640229112deafa0cd8bb0d0" + 101 "89b0", 102 }, 103 { 104 elliptic.P521(), 105 "00000092db3142564d27a5f0006f819908fba1b85038a5bc2509906a497daac67" + 106 "fd7aee0fc2daba4e4334eeaef0e0019204b471cd88024f82115d8149cc0cf4f7ce1" + 107 "a4d5", 108 "0000016bad0623f517b158d9881841d2571efbad63f85cbe2e581960c5d670601" + 109 "a6760272675a548996217e4ab2b8ebce31d71fca63fcc3c08e91c1d8edd91cf6fe8" + 110 "45f8", 111 }, 112 { 113 elliptic.P521(), 114 "0000004f38816681771289ce0cb83a5e29a1ab06fc91f786994b23708ff08a08a" + 115 "0f675b809ae99e9f9967eb1a49f196057d69e50d6dedb4dd2d9a81c02bdcc8f7f51" + 116 "8460", 117 "0000009efb244c8b91087de1eed766500f0e81530752d469256ef79f6b965d8a2" + 118 "232a0c2dbc4e8e1d09214bab38485be6e357c4200d073b52f04e4a16fc6f5247187" + 119 "aecb", 120 }, 121 { 122 elliptic.P521(), 123 "000001a32099b02c0bd85371f60b0dd20890e6c7af048c8179890fda308b359db" + 124 "bc2b7a832bb8c6526c4af99a7ea3f0b3cb96ae1eb7684132795c478ad6f962e4a6f" + 125 "446d", 126 "0000017627357b39e9d7632a1370b3e93c1afb5c851b910eb4ead0c9d387df67c" + 127 "de85003e0e427552f1cd09059aad0262e235cce5fba8cedc4fdc1463da76dcd4b6d" + 128 "1a46", 129 }, 130 } 131 tEC2 = []testEC2{ 132 // NIST_P256 133 { 134 elliptic.P256(), 135 "UNCOMPRESSED", 136 "04" + 137 "b0cfc7bc02fc980d858077552947ffb449b10df8949dee4e56fe21e016dcb25a" + 138 "1886ccdca5487a6772f9401888203f90587cc00a730e2b83d5c6f89b3b568df7", 139 "79974177209371530366349631093481213364328002500948308276357601809416549347930", 140 "11093679777528052772423074391650378811758820120351664471899251711300542565879", 141 }, 142 { 143 elliptic.P256(), 144 "DO_NOT_USE_CRUNCHY_UNCOMPRESSED", 145 "b0cfc7bc02fc980d858077552947ffb449b10df8949dee4e56fe21e016dcb25a" + 146 "1886ccdca5487a6772f9401888203f90587cc00a730e2b83d5c6f89b3b568df7", 147 "79974177209371530366349631093481213364328002500948308276357601809416549347930", 148 "11093679777528052772423074391650378811758820120351664471899251711300542565879", 149 }, 150 { 151 elliptic.P256(), 152 "COMPRESSED", 153 "03b0cfc7bc02fc980d858077552947ffb449b10df8949dee4e56fe21e016dcb25a", 154 "79974177209371530366349631093481213364328002500948308276357601809416549347930", 155 "11093679777528052772423074391650378811758820120351664471899251711300542565879", 156 }, 157 // Exceptional point: x==0 158 { 159 elliptic.P256(), 160 "UNCOMPRESSED", 161 "04" + 162 "0000000000000000000000000000000000000000000000000000000000000000" + 163 "66485c780e2f83d72433bd5d84a06bb6541c2af31dae871728bf856a174f93f4", 164 "0", 165 "46263761741508638697010950048709651021688891777877937875096931459006746039284", 166 }, 167 { 168 elliptic.P256(), 169 "DO_NOT_USE_CRUNCHY_UNCOMPRESSED", 170 "0000000000000000000000000000000000000000000000000000000000000000" + 171 "66485c780e2f83d72433bd5d84a06bb6541c2af31dae871728bf856a174f93f4", 172 "0", 173 "46263761741508638697010950048709651021688891777877937875096931459006746039284", 174 }, 175 { 176 elliptic.P256(), 177 "COMPRESSED", 178 "020000000000000000000000000000000000000000000000000000000000000000", 179 "0", 180 "46263761741508638697010950048709651021688891777877937875096931459006746039284", 181 }, 182 // Exceptional point: x==-3 183 { 184 elliptic.P256(), 185 "UNCOMPRESSED", 186 "04" + 187 "ffffffff00000001000000000000000000000000fffffffffffffffffffffffc" + 188 "19719bebf6aea13f25c96dfd7c71f5225d4c8fc09eb5a0ab9f39e9178e55c121", 189 "115792089210356248762697446949407573530086143415290314195533631308867097853948", 190 "11508551065151498768481026661199445482476508121209842448718573150489103679777", 191 }, 192 { 193 elliptic.P256(), 194 "DO_NOT_USE_CRUNCHY_UNCOMPRESSED", 195 "ffffffff00000001000000000000000000000000fffffffffffffffffffffffc" + 196 "19719bebf6aea13f25c96dfd7c71f5225d4c8fc09eb5a0ab9f39e9178e55c121", 197 "115792089210356248762697446949407573530086143415290314195533631308867097853948", 198 "11508551065151498768481026661199445482476508121209842448718573150489103679777", 199 }, 200 { 201 elliptic.P256(), 202 "COMPRESSED", 203 "03ffffffff00000001000000000000000000000000fffffffffffffffffffffffc", 204 "115792089210356248762697446949407573530086143415290314195533631308867097853948", 205 "11508551065151498768481026661199445482476508121209842448718573150489103679777", 206 }, 207 // NIST_P384 208 { 209 elliptic.P384(), 210 "UNCOMPRESSED", 211 "04aa87ca22be8b05378eb1c71ef320ad746e1d3b628ba79b9859f741e082542a" + 212 "385502f25dbf55296c3a545e3872760ab73617de4a96262c6f5d9e98bf9292dc" + 213 "29f8f41dbd289a147ce9da3113b5f0b8c00a60b1ce1d7e819d7a431d7c90ea0e" + 214 "5f", 215 "2624703509579968926862315674456698189185292349110921338781561590" + 216 "0925518854738050089022388053975719786650872476732087", 217 "8325710961489029985546751289520108179287853048861315594709205902" + 218 "480503199884419224438643760392947333078086511627871", 219 }, 220 { 221 elliptic.P384(), 222 "COMPRESSED", 223 "03aa87ca22be8b05378eb1c71ef320ad746e1d3b628ba79b9859f741e082542a" + 224 "385502f25dbf55296c3a545e3872760ab7", 225 "2624703509579968926862315674456698189185292349110921338781561590" + 226 "0925518854738050089022388053975719786650872476732087", 227 "8325710961489029985546751289520108179287853048861315594709205902" + 228 "480503199884419224438643760392947333078086511627871", 229 }, 230 // x = 0 231 { 232 elliptic.P384(), 233 "UNCOMPRESSED", 234 "0400000000000000000000000000000000000000000000000000000000000000" + 235 "00000000000000000000000000000000003cf99ef04f51a5ea630ba3f9f960dd" + 236 "593a14c9be39fd2bd215d3b4b08aaaf86bbf927f2c46e52ab06fb742b8850e52" + 237 "1e", 238 "0", 239 "9384923975005507693384933751151973636103286582194273515051780595" + 240 "652610803541482195894618304099771370981414591681054", 241 }, 242 { 243 elliptic.P384(), 244 "COMPRESSED", 245 "0200000000000000000000000000000000000000000000000000000000000000" + 246 "0000000000000000000000000000000000", 247 "0", 248 "9384923975005507693384933751151973636103286582194273515051780595" + 249 "652610803541482195894618304099771370981414591681054", 250 }, 251 // x = 2 252 { 253 elliptic.P384(), 254 "UNCOMPRESSED", 255 "0400000000000000000000000000000000000000000000000000000000000000" + 256 "0000000000000000000000000000000002732152442fb6ee5c3e6ce1d920c059" + 257 "bc623563814d79042b903ce60f1d4487fccd450a86da03f3e6ed525d02017bfd" + 258 "b3", 259 "2", 260 "1772015366480916228638409476801818679957736647795608728422858375" + 261 "4887974043472116432532980617621641492831213601947059", 262 }, 263 { 264 elliptic.P384(), 265 "COMPRESSED", 266 "0300000000000000000000000000000000000000000000000000000000000000" + 267 "0000000000000000000000000000000002", 268 "2", 269 "1772015366480916228638409476801818679957736647795608728422858375" + 270 "4887974043472116432532980617621641492831213601947059", 271 }, 272 // x = -3 273 { 274 elliptic.P384(), 275 "UNCOMPRESSED", 276 "04ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" + 277 "feffffffff0000000000000000fffffffc2de9de09a95b74e6b2c430363e1afb" + 278 "8dff7164987a8cfe0a0d5139250ac02f797f81092a9bdc0e09b574a8f43bf80c" + 279 "17", 280 "3940200619639447921227904010014361380507973927046544666794829340" + 281 "4245721771496870329047266088258938001861606973112316", 282 "7066741234775658874139271223692271325950306561732202191471600407" + 283 "582071247913794644254895122656050391930754095909911", 284 }, 285 { 286 elliptic.P384(), 287 "COMPRESSED", 288 "03ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" + 289 "feffffffff0000000000000000fffffffc", 290 "3940200619639447921227904010014361380507973927046544666794829340" + 291 "4245721771496870329047266088258938001861606973112316", 292 "7066741234775658874139271223692271325950306561732202191471600407" + 293 "582071247913794644254895122656050391930754095909911", 294 }, 295 // NIST_P521 296 { 297 elliptic.P521(), 298 "UNCOMPRESSED", 299 "0400c6858e06b70404e9cd9e3ecb662395b4429c648139053fb521f828af606b" + 300 "4d3dbaa14b5e77efe75928fe1dc127a2ffa8de3348b3c1856a429bf97e7e31c2" + 301 "e5bd66011839296a789a3bc0045c8a5fb42c7d1bd998f54449579b446817afbd" + 302 "17273e662c97ee72995ef42640c550b9013fad0761353c7086a272c24088be94" + 303 "769fd16650", 304 "2661740802050217063228768716723360960729859168756973147706671368" + 305 "4188029449964278084915450806277719023520942412250655586621571135" + 306 "45570916814161637315895999846", 307 "3757180025770020463545507224491183603594455134769762486694567779" + 308 "6155444774405563166912344050129455395621444445372894285225856667" + 309 "29196580810124344277578376784", 310 }, 311 { 312 elliptic.P521(), 313 "COMPRESSED", 314 "0200c6858e06b70404e9cd9e3ecb662395b4429c648139053fb521f828af606b" + 315 "4d3dbaa14b5e77efe75928fe1dc127a2ffa8de3348b3c1856a429bf97e7e31c2" + 316 "e5bd66", 317 "2661740802050217063228768716723360960729859168756973147706671368" + 318 "4188029449964278084915450806277719023520942412250655586621571135" + 319 "45570916814161637315895999846", 320 "3757180025770020463545507224491183603594455134769762486694567779" + 321 "6155444774405563166912344050129455395621444445372894285225856667" + 322 "29196580810124344277578376784", 323 }, 324 // x = 0 325 { 326 elliptic.P521(), 327 "UNCOMPRESSED", 328 "0400000000000000000000000000000000000000000000000000000000000000" + 329 "0000000000000000000000000000000000000000000000000000000000000000" + 330 "00000000d20ec9fea6b577c10d26ca1bb446f40b299e648b1ad508aad068896f" + 331 "ee3f8e614bc63054d5772bf01a65d412e0bcaa8e965d2f5d332d7f39f846d440" + 332 "ae001f4f87", 333 "0", 334 "2816414230262626695230339754503506208598534788872316917808418392" + 335 "0894686826982898181454171638541149642517061885689521392260532032" + 336 "30035588176689756661142736775", 337 }, 338 { 339 elliptic.P521(), 340 "COMPRESSED", 341 "0300000000000000000000000000000000000000000000000000000000000000" + 342 "0000000000000000000000000000000000000000000000000000000000000000" + 343 "000000", 344 "0", 345 "2816414230262626695230339754503506208598534788872316917808418392" + 346 "0894686826982898181454171638541149642517061885689521392260532032" + 347 "30035588176689756661142736775", 348 }, 349 // x = 1 350 { 351 elliptic.P521(), 352 "UNCOMPRESSED", 353 "0400000000000000000000000000000000000000000000000000000000000000" + 354 "0000000000000000000000000000000000000000000000000000000000000000" + 355 "0000010010e59be93c4f269c0269c79e2afd65d6aeaa9b701eacc194fb3ee03d" + 356 "f47849bf550ec636ebee0ddd4a16f1cd9406605af38f584567770e3f272d688c" + 357 "832e843564", 358 "1", 359 "2265505274322546447629271557184988697103589068170534253193208655" + 360 "0778100463909972583865730916407864371153050622267306901033104806" + 361 "9570407113457901669103973732", 362 }, 363 { 364 elliptic.P521(), 365 "COMPRESSED", 366 "0200000000000000000000000000000000000000000000000000000000000000" + 367 "0000000000000000000000000000000000000000000000000000000000000000" + 368 "000001", 369 "1", 370 "2265505274322546447629271557184988697103589068170534253193208655" + 371 "0778100463909972583865730916407864371153050622267306901033104806" + 372 "9570407113457901669103973732", 373 }, 374 // x = 2 375 { 376 elliptic.P521(), 377 "UNCOMPRESSED", 378 "0400000000000000000000000000000000000000000000000000000000000000" + 379 "0000000000000000000000000000000000000000000000000000000000000000" + 380 "00000200d9254fdf800496acb33790b103c5ee9fac12832fe546c632225b0f7f" + 381 "ce3da4574b1a879b623d722fa8fc34d5fc2a8731aad691a9a8bb8b554c95a051" + 382 "d6aa505acf", 383 "2", 384 "2911448509017565583245824537994174021964465504209366849707937264" + 385 "0417919148200722009442607963590225526059407040161685364728526719" + 386 "10134103604091376779754756815", 387 }, 388 { 389 elliptic.P521(), 390 "COMPRESSED", 391 "0300000000000000000000000000000000000000000000000000000000000000" + 392 "0000000000000000000000000000000000000000000000000000000000000000" + 393 "000002", 394 "2", 395 "2911448509017565583245824537994174021964465504209366849707937264" + 396 "0417919148200722009442607963590225526059407040161685364728526719" + 397 "10134103604091376779754756815", 398 }, 399 // x = -2 400 { 401 elliptic.P521(), 402 "UNCOMPRESSED", 403 "0401ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" + 404 "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" + 405 "fffffd0010e59be93c4f269c0269c79e2afd65d6aeaa9b701eacc194fb3ee03d" + 406 "f47849bf550ec636ebee0ddd4a16f1cd9406605af38f584567770e3f272d688c" + 407 "832e843564", 408 "6864797660130609714981900799081393217269435300143305409394463459" + 409 "1855431833976560521225596406614545549772963113914808580371219879" + 410 "99716643812574028291115057149", 411 "2265505274322546447629271557184988697103589068170534253193208655" + 412 "0778100463909972583865730916407864371153050622267306901033104806" + 413 "9570407113457901669103973732", 414 }, 415 { 416 elliptic.P521(), 417 "COMPRESSED", 418 "0201ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" + 419 "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" + 420 "fffffd", 421 "6864797660130609714981900799081393217269435300143305409394463459" + 422 "1855431833976560521225596406614545549772963113914808580371219879" + 423 "99716643812574028291115057149", 424 "2265505274322546447629271557184988697103589068170534253193208655" + 425 "0778100463909972583865730916407864371153050622267306901033104806" + 426 "9570407113457901669103973732", 427 }, 428 } 429) 430 431func TestPointOnCurve(t *testing.T) { 432 for i := 0; i < len(tEC1); i++ { 433 x, y, ye := new(big.Int), new(big.Int), new(big.Int) 434 x.SetString(tEC1[i].pubX, 16) 435 y.SetString(tEC1[i].pubY, 16) 436 ye.Sub(y, big.NewInt(1)) 437 if !tEC1[i].Curve.IsOnCurve(x, y) { 438 t.Fatalf("valid points not on curve for test case :%d", i) 439 } 440 if tEC1[i].Curve.IsOnCurve(x, ye) { 441 t.Fatalf("invalid points is on curve for test case :%d", i) 442 } 443 } 444 445} 446 447func TestPointEncode(t *testing.T) { 448 for i := 0; i < len(tEC2); i++ { 449 x, y := new(big.Int), new(big.Int) 450 x.SetString(tEC2[i].X, 10) 451 y.SetString(tEC2[i].Y, 10) 452 p := subtle.ECPoint{ 453 X: x, 454 Y: y, 455 } 456 encodedpoint, err := subtle.PointEncode(tEC2[i].Curve, tEC2[i].pointFormat, p) 457 if err != nil { 458 t.Errorf("error in point encoding in test case %d : %v", i, err) 459 } 460 want, err := hex.DecodeString(tEC2[i].encoded) 461 if err != nil { 462 t.Errorf("error reading encoded point in test case %d", i) 463 } 464 if !bytes.Equal(encodedpoint, want) { 465 t.Errorf("mismatch point encoding in test case %d", i) 466 } 467 } 468} 469 470func TestPointDecode(t *testing.T) { 471 for i := 0; i < len(tEC2); i++ { 472 x, y := new(big.Int), new(big.Int) 473 x.SetString(tEC2[i].X, 10) 474 y.SetString(tEC2[i].Y, 10) 475 e, err := hex.DecodeString(tEC2[i].encoded) 476 if err != nil { 477 t.Errorf("error reading encoded point in test case %d", i) 478 } 479 pt, err := subtle.PointDecode(tEC2[i].Curve, tEC2[i].pointFormat, e) 480 if err != nil { 481 t.Errorf("error in point decoding in test case %d: %v", i, err) 482 } 483 spt := subtle.ECPoint{ 484 X: x, 485 Y: y, 486 } 487 488 if pt.X.Cmp(spt.X) != 0 || pt.Y.Cmp(spt.Y) != 0 { 489 t.Errorf("mismatch point decoding in test case %d", i) 490 } 491 } 492} 493 494func checkFlag(t *testing.T, flags []string, check []string) bool { 495 t.Helper() 496 for _, f := range flags { 497 for _, c := range check { 498 if strings.Compare(f, c) == 0 { 499 return true 500 } 501 } 502 } 503 return false 504} 505 506// convertX509PublicKey converts an encoded public key to an ECPublicKey. 507func convertX509PublicKey(t *testing.T, b []byte) (*subtle.ECPublicKey, error) { 508 t.Helper() 509 pkey, err := x509.ParsePKIXPublicKey(b) 510 if err != nil { 511 return nil, err 512 } 513 ecdsaP, ok := pkey.(*ecdsa.PublicKey) 514 if !ok { 515 return nil, errors.New("invalid elliptic curve key") 516 } 517 return &subtle.ECPublicKey{ 518 Curve: ecdsaP.Curve, 519 Point: subtle.ECPoint{ 520 X: ecdsaP.X, 521 Y: ecdsaP.Y, 522 }, 523 }, nil 524} 525 526// convertPointPublicKey converts an EC point public key to an ECPublicKey. 527func convertPointPublicKey(t *testing.T, pk []byte, curve elliptic.Curve, flags []string) (*subtle.ECPublicKey, error) { 528 ptFormat := "UNCOMPRESSED" 529 if checkFlag(t, flags, []string{"CompressedPoint"}) { 530 ptFormat = "COMPRESSED" 531 } 532 pt, err := subtle.PointDecode(curve, ptFormat, pk) 533 if err != nil { 534 return nil, err 535 } 536 return &subtle.ECPublicKey{ 537 Curve: curve, 538 Point: *pt, 539 }, nil 540} 541 542func TestECWycheproofCases(t *testing.T) { 543 testutil.SkipTestIfTestSrcDirIsNotSet(t) 544 545 vectors := []string{ 546 "ecdh_test.json", 547 "ecdh_secp224r1_ecpoint_test.json", 548 "ecdh_secp256r1_ecpoint_test.json", 549 "ecdh_secp384r1_ecpoint_test.json", 550 "ecdh_secp521r1_ecpoint_test.json", 551 } 552 for _, v := range vectors { 553 suite := new(ecdhSuite) 554 if err := testutil.PopulateSuite(suite, v); err != nil { 555 t.Fatalf("failed populating suite: %s", err) 556 } 557 for _, group := range suite.TestGroups { 558 curve, err := subtle.GetCurve(group.Curve) 559 if err != nil { 560 t.Logf("unsupported curve: %s", group.Curve) 561 continue 562 } 563 for _, test := range group.Tests { 564 caseName := fmt.Sprintf("%s-%s:Case-%d", suite.Algorithm, group.Type, test.CaseID) 565 t.Run(caseName, func(t *testing.T) { 566 pvtKey := subtle.GetECPrivateKey(curve, test.Private) 567 568 var pubKey *subtle.ECPublicKey 569 var errPub error 570 switch suite.Schema { 571 case "ecdh_test_schema.json": 572 pubKey, errPub = convertX509PublicKey(t, test.Public) 573 case "ecdh_ecpoint_test_schema.json": 574 pubKey, errPub = convertPointPublicKey(t, test.Public, curve, test.Flags) 575 default: 576 t.Logf("Unsupported schema: %q", suite.Schema) 577 return 578 } 579 580 switch test.Result { 581 case "valid": 582 if errPub != nil { 583 t.Fatalf("failed decoding public key: %s", errPub) 584 } 585 586 shared, err := subtle.ComputeSharedSecret(&pubKey.Point, pvtKey) 587 if err != nil { 588 t.Errorf("subtle.ComputeSharedSecret() failed: %s", err) 589 } 590 if !bytes.Equal(shared, test.Shared) { 591 t.Error("valid test case, incorrect shared secret") 592 } 593 594 case "invalid": 595 if errPub != nil { 596 // Public key not decoded. OK for invalid test case. 597 return 598 } 599 600 shared, err := subtle.ComputeSharedSecret(&pubKey.Point, pvtKey) 601 if err != nil { 602 // Shared secret was not computed. OK for invalid test case. 603 return 604 } 605 validReason := checkFlag(t, test.Flags, []string{"WrongOrder", "WeakPublicKey", "UnnamedCurve"}) 606 if validReason && bytes.Equal(shared, test.Shared) { 607 t.Log("accepted invalid parameters but shared secret is correct") 608 return 609 } 610 t.Error("accepted invalid parameters") 611 612 case "acceptable": 613 if errPub != nil { 614 // Public key not decoded. OK for acceptable test case. 615 return 616 } 617 618 shared, err := subtle.ComputeSharedSecret(&pubKey.Point, pvtKey) 619 if err != nil { 620 // Shared secret was not computed. OK for acceptable test case. 621 return 622 } 623 if !bytes.Equal(shared, test.Shared) { 624 t.Error("acceptable test case, incorrect shared secret") 625 } 626 627 default: 628 t.Errorf("unsupported test result: %q", test.Result) 629 } 630 }) 631 } 632 } 633 } 634} 635