| ... | ... | @@ -470,10 +470,9 @@ pub fn chacha20poly1305Seal(dst: []u8, plaintext: []const u8, data: []const u8, |
| 470 | 470 | } |
| 471 | 471 | |
| 472 | 472 | /// Verifies and decrypts an authenticated message produced by chacha20poly1305Open. |
| 473 | | /// Returns false if message was invalid or authentication failed. |
| 474 | | pub fn chacha20poly1305Open(dst: []u8, ciphertext: []const u8, data: []const u8, key: [32]u8, nonce: [12]u8) bool { |
| 473 | pub fn chacha20poly1305Open(dst: []u8, ciphertext: []const u8, data: []const u8, key: [32]u8, nonce: [12]u8) !void { |
| 475 | 474 | if (ciphertext.len < chacha20poly1305_tag_size) { |
| 476 | | return false; |
| 475 | return error.InvalidMessage; |
| 477 | 476 | } |
| 478 | 477 | |
| 479 | 478 | // split ciphertext and tag |
| ... | ... | @@ -515,12 +514,11 @@ pub fn chacha20poly1305Open(dst: []u8, ciphertext: []const u8, data: []const u8, |
| 515 | 514 | acc |= (computedTag[i] ^ polyTag[i]); |
| 516 | 515 | } |
| 517 | 516 | if (acc != 0) { |
| 518 | | return false; |
| 517 | return error.AuthenticationFailed; |
| 519 | 518 | } |
| 520 | 519 | |
| 521 | 520 | // decrypt ciphertext |
| 522 | 521 | chaCha20IETF(dst[0..ciphertext.len], ciphertext, 1, key, nonce); |
| 523 | | return true; |
| 524 | 522 | } |
| 525 | 523 | |
| 526 | 524 | test "seal" { |
| ... | ... | @@ -585,8 +583,7 @@ test "open" { |
| 585 | 583 | const exp_out = ""; |
| 586 | 584 | |
| 587 | 585 | var out: [exp_out.len]u8 = undefined; |
| 588 | | var valid: bool = chacha20poly1305Open(out[0..], ciphertext[0..], data, key, nonce); |
| 589 | | testing.expect(valid); |
| 586 | try chacha20poly1305Open(out[0..], ciphertext[0..], data, key, nonce); |
| 590 | 587 | testing.expectEqualSlices(u8, exp_out, out); |
| 591 | 588 | } |
| 592 | 589 | { |
| ... | ... | @@ -619,22 +616,24 @@ test "open" { |
| 619 | 616 | }; |
| 620 | 617 | |
| 621 | 618 | var out: [exp_out.len]u8 = undefined; |
| 622 | | var valid: bool = chacha20poly1305Open(out[0..], ciphertext[0..], data[0..], key, nonce); |
| 623 | | testing.expect(valid); |
| 619 | try chacha20poly1305Open(out[0..], ciphertext[0..], data[0..], key, nonce); |
| 624 | 620 | testing.expectEqualSlices(u8, exp_out, out); |
| 625 | 621 | |
| 626 | 622 | // corrupting the ciphertext, data, key, or nonce should cause a failure |
| 627 | 623 | var bad_ciphertext = ciphertext; |
| 628 | 624 | bad_ciphertext[0] ^= 1; |
| 629 | | testing.expect(!chacha20poly1305Open(out[0..], bad_ciphertext[0..], data, key, nonce)); |
| 625 | testing.expectError(error.AuthenticationFailed, chacha20poly1305Open(out[0..], bad_ciphertext[0..], data, key, nonce)); |
| 630 | 626 | var bad_data = data; |
| 631 | 627 | bad_data[0] ^= 1; |
| 632 | | testing.expect(!chacha20poly1305Open(out[0..], ciphertext[0..], bad_data, key, nonce)); |
| 628 | testing.expectError(error.AuthenticationFailed, chacha20poly1305Open(out[0..], ciphertext[0..], bad_data, key, nonce)); |
| 633 | 629 | var bad_key = key; |
| 634 | 630 | bad_key[0] ^= 1; |
| 635 | | testing.expect(!chacha20poly1305Open(out[0..], ciphertext[0..], data, bad_key, nonce)); |
| 631 | testing.expectError(error.AuthenticationFailed, chacha20poly1305Open(out[0..], ciphertext[0..], data, bad_key, nonce)); |
| 636 | 632 | var bad_nonce = nonce; |
| 637 | 633 | bad_nonce[0] ^= 1; |
| 638 | | testing.expect(!chacha20poly1305Open(out[0..], ciphertext[0..], data, key, bad_nonce)); |
| 634 | testing.expectError(error.AuthenticationFailed, chacha20poly1305Open(out[0..], ciphertext[0..], data, key, bad_nonce)); |
| 635 | |
| 636 | // a short ciphertext should result in a different error |
| 637 | testing.expectError(error.InvalidMessage, chacha20poly1305Open(out[0..], "", data, key, bad_nonce)); |
| 639 | 638 | } |
| 640 | 639 | } |