|
21 | 21 |
|
22 | 22 | #include <tests/unit.h> |
23 | 23 |
|
| 24 | +#include <tests/api/api.h> |
24 | 25 | #include <tests/api/test_asn.h> |
25 | 26 |
|
26 | 27 | #include <wolfssl/wolfcrypt/asn.h> |
| 28 | +#include <wolfssl/wolfcrypt/asn_public.h> |
| 29 | +#include <wolfssl/wolfcrypt/random.h> |
27 | 30 | #include <wolfssl/wolfcrypt/rsa.h> |
| 31 | +#ifdef HAVE_ED25519 |
| 32 | + #include <wolfssl/wolfcrypt/ed25519.h> |
| 33 | +#endif |
28 | 34 |
|
29 | 35 | #if defined(WC_ENABLE_ASYM_KEY_EXPORT) && defined(HAVE_ED25519) |
30 | 36 | static int test_SetAsymKeyDer_once(byte* privKey, word32 privKeySz, byte* pubKey, |
@@ -55,6 +61,9 @@ int test_SetAsymKeyDer(void) |
55 | 61 | #if defined(WC_ENABLE_ASYM_KEY_EXPORT) && defined(HAVE_ED25519) |
56 | 62 | /* We can't access the keyEd25519Oid variable, so declare it instead */ |
57 | 63 | byte algId[] = {43, 101, 112}; |
| 64 | + /* RFC 5958: version is v1 (0) for private only, v2 (1) when public key |
| 65 | + * bundled. Conditions 1-5 are private only, 6-8 include pub key and |
| 66 | + * mutate version[0] = 0x1 before building trueDer. */ |
58 | 67 | byte version[] = {0x0}; |
59 | 68 | byte keyPat = 0xcc; |
60 | 69 |
|
@@ -286,6 +295,7 @@ int test_SetAsymKeyDer(void) |
286 | 295 | privKeySz = 32; |
287 | 296 | pubKeySz = 32; |
288 | 297 | trueDerSz = 82; |
| 298 | + version[0] = 0x1; /* publicKey present (v2) */ |
289 | 299 |
|
290 | 300 | /* SEQ */ |
291 | 301 | trueDer[0] = ASN_SEQUENCE | ASN_CONSTRUCTED; |
@@ -328,6 +338,7 @@ int test_SetAsymKeyDer(void) |
328 | 338 | privKeySz = 32; |
329 | 339 | pubKeySz = 128; |
330 | 340 | trueDerSz = 180; |
| 341 | + version[0] = 0x1; /* publicKey present (v2) */ |
331 | 342 |
|
332 | 343 | /* SEQ */ |
333 | 344 | trueDer[0] = ASN_SEQUENCE | ASN_CONSTRUCTED; |
@@ -372,6 +383,7 @@ int test_SetAsymKeyDer(void) |
372 | 383 | privKeySz = 32; |
373 | 384 | pubKeySz = 256; |
374 | 385 | trueDerSz = 310; |
| 386 | + version[0] = 0x1; /* publicKey present (v2) */ |
375 | 387 |
|
376 | 388 | /* SEQ */ |
377 | 389 | trueDer[0] = ASN_SEQUENCE | ASN_CONSTRUCTED; |
@@ -413,6 +425,155 @@ int test_SetAsymKeyDer(void) |
413 | 425 |
|
414 | 426 | } |
415 | 427 |
|
| 428 | +/* RFC 5958 leniency: parser must accept all four variants: |
| 429 | + * {v=0,v=1} x {publicKey absent, present}. */ |
| 430 | +int test_DecodeAsymKey_lenient_versions(void) |
| 431 | +{ |
| 432 | + EXPECT_DECLS; |
| 433 | +#if defined(HAVE_ED25519) && defined(HAVE_ED25519_KEY_EXPORT) && \ |
| 434 | + defined(HAVE_ED25519_KEY_IMPORT) && defined(WOLFSSL_KEY_GEN) |
| 435 | + ed25519_key key; |
| 436 | + ed25519_key parsed; |
| 437 | + WC_RNG rng; |
| 438 | + byte bundled[256]; /* v=1 + publicKey */ |
| 439 | + byte privOnly[256]; /* v=0, no publicKey */ |
| 440 | + byte tmp[256]; |
| 441 | + int bundledSz = 0; |
| 442 | + int privOnlySz = 0; |
| 443 | + word32 idx; |
| 444 | + |
| 445 | + XMEMSET(&key, 0, sizeof(key)); |
| 446 | + XMEMSET(&parsed, 0, sizeof(parsed)); |
| 447 | + XMEMSET(&rng, 0, sizeof(rng)); |
| 448 | + |
| 449 | + ExpectIntEQ(wc_InitRng(&rng), 0); |
| 450 | + ExpectIntEQ(wc_ed25519_init(&key), 0); |
| 451 | + ExpectIntEQ(wc_ed25519_make_key(&rng, ED25519_KEY_SIZE, &key), 0); |
| 452 | + |
| 453 | + ExpectIntGT(bundledSz = wc_Ed25519KeyToDer(&key, bundled, |
| 454 | + (word32)sizeof(bundled)), 0); |
| 455 | + ExpectIntGT(privOnlySz = wc_Ed25519PrivateKeyToDer(&key, privOnly, |
| 456 | + (word32)sizeof(privOnly)), 0); |
| 457 | + |
| 458 | + if (EXPECT_SUCCESS() && |
| 459 | + ((bundledSz > 0) && ((size_t)bundledSz <= sizeof(bundled)) && |
| 460 | + (privOnlySz > 0) && ((size_t)privOnlySz <= sizeof(privOnly)))) { |
| 461 | + |
| 462 | + /* v=1 + publicKey */ |
| 463 | + XMEMCPY(tmp, bundled, (size_t)bundledSz); |
| 464 | + XMEMSET(&parsed, 0, sizeof(parsed)); |
| 465 | + ExpectIntEQ(wc_ed25519_init(&parsed), 0); |
| 466 | + idx = 0; |
| 467 | + ExpectIntEQ(wc_Ed25519PrivateKeyDecode(tmp, &idx, &parsed, |
| 468 | + (word32)bundledSz), 0); |
| 469 | + wc_ed25519_free(&parsed); |
| 470 | + |
| 471 | + /* v=0 + publicKey: patch version byte, [1] publicKey field present. */ |
| 472 | + XMEMCPY(tmp, bundled, (size_t)bundledSz); |
| 473 | + ExpectIntGT(test_pkcs8_patch_version_byte(tmp, (word32)bundledSz, 0), |
| 474 | + 0); |
| 475 | + XMEMSET(&parsed, 0, sizeof(parsed)); |
| 476 | + ExpectIntEQ(wc_ed25519_init(&parsed), 0); |
| 477 | + idx = 0; |
| 478 | + ExpectIntEQ(wc_Ed25519PrivateKeyDecode(tmp, &idx, &parsed, |
| 479 | + (word32)bundledSz), 0); |
| 480 | + wc_ed25519_free(&parsed); |
| 481 | + |
| 482 | + /* v=0, no publicKey */ |
| 483 | + XMEMCPY(tmp, privOnly, (size_t)privOnlySz); |
| 484 | + XMEMSET(&parsed, 0, sizeof(parsed)); |
| 485 | + ExpectIntEQ(wc_ed25519_init(&parsed), 0); |
| 486 | + idx = 0; |
| 487 | + ExpectIntEQ(wc_Ed25519PrivateKeyDecode(tmp, &idx, &parsed, |
| 488 | + (word32)privOnlySz), 0); |
| 489 | + wc_ed25519_free(&parsed); |
| 490 | + |
| 491 | + /* v=1, no publicKey */ |
| 492 | + XMEMCPY(tmp, privOnly, (size_t)privOnlySz); |
| 493 | + ExpectIntGT(test_pkcs8_patch_version_byte(tmp, (word32)privOnlySz, 1), |
| 494 | + 0); |
| 495 | + XMEMSET(&parsed, 0, sizeof(parsed)); |
| 496 | + ExpectIntEQ(wc_ed25519_init(&parsed), 0); |
| 497 | + idx = 0; |
| 498 | + ExpectIntEQ(wc_Ed25519PrivateKeyDecode(tmp, &idx, &parsed, |
| 499 | + (word32)privOnlySz), 0); |
| 500 | + wc_ed25519_free(&parsed); |
| 501 | + } |
| 502 | + |
| 503 | + wc_ed25519_free(&key); |
| 504 | + wc_FreeRng(&rng); |
| 505 | +#endif |
| 506 | + return EXPECT_RESULT(); |
| 507 | +} |
| 508 | + |
| 509 | +int test_DecodeAsymKey_negative(void) |
| 510 | +{ |
| 511 | + EXPECT_DECLS; |
| 512 | +#if defined(HAVE_ED25519) && defined(HAVE_ED25519_KEY_EXPORT) && \ |
| 513 | + defined(HAVE_ED25519_KEY_IMPORT) && defined(WOLFSSL_KEY_GEN) |
| 514 | + ed25519_key key; |
| 515 | + ed25519_key parsed; |
| 516 | + WC_RNG rng; |
| 517 | + byte good[256]; |
| 518 | + byte tmp[256]; |
| 519 | + int goodSz = 0; |
| 520 | + word32 idx; |
| 521 | + |
| 522 | + XMEMSET(&key, 0, sizeof(key)); |
| 523 | + XMEMSET(&parsed, 0, sizeof(parsed)); |
| 524 | + XMEMSET(&rng, 0, sizeof(rng)); |
| 525 | + |
| 526 | + ExpectIntEQ(wc_InitRng(&rng), 0); |
| 527 | + ExpectIntEQ(wc_ed25519_init(&key), 0); |
| 528 | + ExpectIntEQ(wc_ed25519_make_key(&rng, ED25519_KEY_SIZE, &key), 0); |
| 529 | + ExpectIntGT(goodSz = wc_Ed25519KeyToDer(&key, good, |
| 530 | + (word32)sizeof(good)), 0); |
| 531 | + |
| 532 | + if (EXPECT_SUCCESS() && |
| 533 | + (goodSz > 0 && (size_t)goodSz <= sizeof(good))) { |
| 534 | + |
| 535 | + /* Truncated buffer */ |
| 536 | + XMEMCPY(tmp, good, (size_t)goodSz); |
| 537 | + ExpectIntEQ(wc_ed25519_init(&parsed), 0); |
| 538 | + idx = 0; |
| 539 | + ExpectIntLT(wc_Ed25519PrivateKeyDecode(tmp, &idx, &parsed, |
| 540 | + (word32)(goodSz - 1)), 0); |
| 541 | + wc_ed25519_free(&parsed); |
| 542 | + |
| 543 | + /* Outer length too big. Patch low-order length byte (long form: bump |
| 544 | + * the last byte of the multi-byte length encoding). */ |
| 545 | + XMEMCPY(tmp, good, (size_t)goodSz); |
| 546 | + if ((good[1] & 0x80) == 0) { |
| 547 | + tmp[1] = (byte)(good[1] + 1); |
| 548 | + } |
| 549 | + else { |
| 550 | + word32 nBytes = (word32)(good[1] & 0x7F); |
| 551 | + tmp[1 + nBytes] = (byte)(good[1 + nBytes] + 1); |
| 552 | + } |
| 553 | + XMEMSET(&parsed, 0, sizeof(parsed)); |
| 554 | + ExpectIntEQ(wc_ed25519_init(&parsed), 0); |
| 555 | + idx = 0; |
| 556 | + ExpectIntLT(wc_Ed25519PrivateKeyDecode(tmp, &idx, &parsed, |
| 557 | + (word32)goodSz), 0); |
| 558 | + wc_ed25519_free(&parsed); |
| 559 | + |
| 560 | + /* Outer tag not SEQUENCE */ |
| 561 | + XMEMCPY(tmp, good, (size_t)goodSz); |
| 562 | + tmp[0] = 0x02; |
| 563 | + XMEMSET(&parsed, 0, sizeof(parsed)); |
| 564 | + ExpectIntEQ(wc_ed25519_init(&parsed), 0); |
| 565 | + idx = 0; |
| 566 | + ExpectIntLT(wc_Ed25519PrivateKeyDecode(tmp, &idx, &parsed, |
| 567 | + (word32)goodSz), 0); |
| 568 | + wc_ed25519_free(&parsed); |
| 569 | + } |
| 570 | + |
| 571 | + wc_ed25519_free(&key); |
| 572 | + wc_FreeRng(&rng); |
| 573 | +#endif |
| 574 | + return EXPECT_RESULT(); |
| 575 | +} |
| 576 | + |
416 | 577 | #ifndef NO_ASN |
417 | 578 | static int test_GetSetShortInt_once(word32 val, byte* valDer, word32 valDerSz) |
418 | 579 | { |
|
0 commit comments