| author | |
| committer | |
| log | fd0dd6c2a8f98fdb8413f04f90cebe704f429f49 |
| tree | 0e5114396550b9f5e0d77bf9e564080c3ae525a3 |
| parent | 705a6b4efb7b19feb7d2ee86f2ac6e56653cb923 |
| parent | 9552ca4c2e9a478fa9187b1eaf64d82c7c2d2b84 |
Reviewed-on: https://codeberg.org/ziglang/zig/pulls/37264
Reviewed-by: Andrew Kelley <andrew@ziglang.org>11 files changed, 8 insertions(+), 30 deletions(-)
lib/std/crypto.zig+2| ... | ... | @@ -417,6 +417,8 @@ test "issue #4532: no index out of bounds" { |
| 417 | 417 | |
| 418 | 418 | /// Sets a slice to zeroes. |
| 419 | 419 | /// Prevents the store from being optimized out. |
| 420 | /// Does not clear copies in registers or elsewhere in memory. | |
| 421 | /// Wiping a value held in registers can force an extra copy into memory. | |
| 420 | 422 | pub fn secureZero(comptime T: type, s: []volatile T) void { |
| 421 | 423 | @memset(s, std.mem.zeroes(T)); |
| 422 | 424 | } |
lib/std/crypto/aegis.zig+2-4| ... | ... | @@ -351,10 +351,9 @@ fn Aegis128XGeneric(comptime degree: u7, comptime tag_bits: u9) type { |
| 351 | 351 | if (m.len % block_length != 0) { |
| 352 | 352 | state.decLast(m[i..], c[i..]); |
| 353 | 353 | } |
| 354 | var computed_tag = state.finalize(tag_bits, ad.len, m.len); | |
| 354 | const computed_tag = state.finalize(tag_bits, ad.len, m.len); | |
| 355 | 355 | const verify = crypto.timing_safe.eql([tag_length]u8, computed_tag, tag); |
| 356 | 356 | if (!verify) { |
| 357 | crypto.secureZero(u8, &computed_tag); | |
| 358 | 357 | @memset(m, undefined); |
| 359 | 358 | return error.AuthenticationFailed; |
| 360 | 359 | } |
| ... | ... | @@ -646,10 +645,9 @@ fn Aegis256XGeneric(comptime degree: u7, comptime tag_bits: u9) type { |
| 646 | 645 | if (m.len % block_length != 0) { |
| 647 | 646 | state.decLast(m[i..], c[i..]); |
| 648 | 647 | } |
| 649 | var computed_tag = state.finalize(tag_bits, ad.len, m.len); | |
| 648 | const computed_tag = state.finalize(tag_bits, ad.len, m.len); | |
| 650 | 649 | const verify = crypto.timing_safe.eql([tag_length]u8, computed_tag, tag); |
| 651 | 650 | if (!verify) { |
| 652 | crypto.secureZero(u8, &computed_tag); | |
| 653 | 651 | @memset(m, undefined); |
| 654 | 652 | return error.AuthenticationFailed; |
| 655 | 653 | } |
lib/std/crypto/aes_ccm.zig-10| ... | ... | @@ -91,9 +91,6 @@ fn AesCcm(comptime BlockCipher: type, comptime tag_len: usize, comptime nonce_le |
| 91 | 91 | for (tag, mac_result[0..tag_length], s0[0..tag_length]) |*t, mac_byte, s_byte| { |
| 92 | 92 | t.* = mac_byte ^ s_byte; |
| 93 | 93 | } |
| 94 | ||
| 95 | crypto.secureZero(u8, &mac_result); | |
| 96 | crypto.secureZero(u8, &s0); | |
| 97 | 94 | } |
| 98 | 95 | |
| 99 | 96 | // Encrypt the plaintext using CTR mode (starting from counter = 1) |
| ... | ... | @@ -153,16 +150,9 @@ fn AesCcm(comptime BlockCipher: type, comptime tag_len: usize, comptime nonce_le |
| 153 | 150 | // Constant-time tag comparison |
| 154 | 151 | const valid = crypto.timing_safe.eql([tag_length]u8, expected_mac, tag); |
| 155 | 152 | if (!valid) { |
| 156 | crypto.secureZero(u8, &expected_mac); | |
| 157 | crypto.secureZero(u8, &mac_result); | |
| 158 | crypto.secureZero(u8, &s0); | |
| 159 | 153 | crypto.secureZero(u8, m); |
| 160 | 154 | return error.AuthenticationFailed; |
| 161 | 155 | } |
| 162 | ||
| 163 | crypto.secureZero(u8, &expected_mac); | |
| 164 | crypto.secureZero(u8, &mac_result); | |
| 165 | crypto.secureZero(u8, &s0); | |
| 166 | 156 | } |
| 167 | 157 | } |
| 168 | 158 |
lib/std/crypto/aes_gcm.zig-1| ... | ... | @@ -101,7 +101,6 @@ fn AesGcm(comptime Aes: anytype) type { |
| 101 | 101 | |
| 102 | 102 | const verify = crypto.timing_safe.eql([tag_length]u8, computed_tag, tag); |
| 103 | 103 | if (!verify) { |
| 104 | crypto.secureZero(u8, &computed_tag); | |
| 105 | 104 | @memset(m, undefined); |
| 106 | 105 | return error.AuthenticationFailed; |
| 107 | 106 | } |
lib/std/crypto/aes_gcm_siv.zig-1| ... | ... | @@ -218,7 +218,6 @@ fn AesGcmSiv(comptime Aes: anytype) type { |
| 218 | 218 | // Verify tag |
| 219 | 219 | const verify = crypto.timing_safe.eql([tag_length]u8, computed_tag, tag); |
| 220 | 220 | if (!verify) { |
| 221 | crypto.secureZero(u8, &computed_tag); | |
| 222 | 221 | @memset(m, undefined); |
| 223 | 222 | return error.AuthenticationFailed; |
| 224 | 223 | } |
lib/std/crypto/aes_ocb.zig+1-2| ... | ... | @@ -236,10 +236,9 @@ fn AesOcb(comptime Aes: anytype) type { |
| 236 | 236 | } |
| 237 | 237 | var e = xorBlocks(xorBlocks(sum, offset), lx.dol); |
| 238 | 238 | aes_enc_ctx.encrypt(&e, &e); |
| 239 | var computed_tag = xorBlocks(e, hash(aes_enc_ctx, &lx, ad)); | |
| 239 | const computed_tag = xorBlocks(e, hash(aes_enc_ctx, &lx, ad)); | |
| 240 | 240 | const verify = crypto.timing_safe.eql([tag_length]u8, computed_tag, tag); |
| 241 | 241 | if (!verify) { |
| 242 | crypto.secureZero(u8, &computed_tag); | |
| 243 | 242 | @memset(m, undefined); |
| 244 | 243 | return error.AuthenticationFailed; |
| 245 | 244 | } |
lib/std/crypto/aes_siv.zig-2| ... | ... | @@ -211,7 +211,6 @@ fn AesSiv(comptime Aes: anytype) type { |
| 211 | 211 | // Verify tag |
| 212 | 212 | const verify = crypto.timing_safe.eql([tag_length]u8, computed_tag, tag); |
| 213 | 213 | if (!verify) { |
| 214 | crypto.secureZero(u8, &computed_tag); | |
| 215 | 214 | @memset(m, undefined); |
| 216 | 215 | return error.AuthenticationFailed; |
| 217 | 216 | } |
| ... | ... | @@ -290,7 +289,6 @@ fn AesSiv(comptime Aes: anytype) type { |
| 290 | 289 | // Verify tag |
| 291 | 290 | const verify = crypto.timing_safe.eql([tag_length]u8, computed_tag, tag); |
| 292 | 291 | if (!verify) { |
| 293 | crypto.secureZero(u8, &computed_tag); | |
| 294 | 292 | @memset(m, undefined); |
| 295 | 293 | return error.AuthenticationFailed; |
| 296 | 294 | } |
lib/std/crypto/bcrypt.zig+2-3| ... | ... | @@ -556,8 +556,7 @@ const pbkdf_prf = struct { |
| 556 | 556 | std.mem.writeInt(u32, out[4 * i ..][0..4], v, .little); |
| 557 | 557 | } |
| 558 | 558 | |
| 559 | // zap | |
| 560 | crypto.secureZero(u32, &cdata); | |
| 559 | // Clear the key schedule, which is already stored in memory. | |
| 561 | 560 | crypto.secureZero(u32, &state.subkeys); |
| 562 | 561 | |
| 563 | 562 | return out; |
| ... | ... | @@ -611,8 +610,8 @@ pub fn opensshKdf(pass: []const u8, salt: []const u8, key: []u8, rounds: u32) !v |
| 611 | 610 | key[dest] = tmp[i]; |
| 612 | 611 | } else amt; |
| 613 | 612 | } |
| 613 | // Unlike these buffers, tmp2 can stay in registers; wiping it can force an extra copy into memory. | |
| 614 | 614 | crypto.secureZero(u8, &tmp); |
| 615 | crypto.secureZero(u8, &tmp2); | |
| 616 | 615 | crypto.secureZero(u8, &sha2pass); |
| 617 | 616 | } |
| 618 | 617 |
lib/std/crypto/chacha20.zig-1| ... | ... | @@ -711,7 +711,6 @@ fn ChaChaPoly1305(comptime rounds_nb: usize) type { |
| 711 | 711 | |
| 712 | 712 | const verify = crypto.timing_safe.eql([tag_length]u8, computed_tag, tag); |
| 713 | 713 | if (!verify) { |
| 714 | crypto.secureZero(u8, &computed_tag); | |
| 715 | 714 | @memset(m, undefined); |
| 716 | 715 | return error.AuthenticationFailed; |
| 717 | 716 | } |
lib/std/crypto/isap.zig+1-5| ... | ... | @@ -78,7 +78,6 @@ pub const IsapA128A = struct { |
| 78 | 78 | |
| 79 | 79 | var out: [out_len]u8 = undefined; |
| 80 | 80 | isap.st.extractBytes(&out); |
| 81 | isap.st.secureZero(); | |
| 82 | 81 | return out; |
| 83 | 82 | } |
| 84 | 83 | |
| ... | ... | @@ -106,7 +105,6 @@ pub const IsapA128A = struct { |
| 106 | 105 | |
| 107 | 106 | var tag: [16]u8 = undefined; |
| 108 | 107 | isap.st.extractBytes(&tag); |
| 109 | isap.st.secureZero(); | |
| 110 | 108 | return tag; |
| 111 | 109 | } |
| 112 | 110 | |
| ... | ... | @@ -139,7 +137,6 @@ pub const IsapA128A = struct { |
| 139 | 137 | break; |
| 140 | 138 | } |
| 141 | 139 | } |
| 142 | isap.st.secureZero(); | |
| 143 | 140 | } |
| 144 | 141 | |
| 145 | 142 | pub fn encrypt(c: []u8, tag: *[tag_length]u8, m: []const u8, ad: []const u8, npub: [nonce_length]u8, key: [key_length]u8) void { |
| ... | ... | @@ -157,10 +154,9 @@ pub const IsapA128A = struct { |
| 157 | 154 | /// |
| 158 | 155 | /// Contents of `m` are undefined if an error is returned. |
| 159 | 156 | pub fn decrypt(m: []u8, c: []const u8, tag: [tag_length]u8, ad: []const u8, npub: [nonce_length]u8, key: [key_length]u8) AuthenticationError!void { |
| 160 | var computed_tag = mac(c, ad, npub, key); | |
| 157 | const computed_tag = mac(c, ad, npub, key); | |
| 161 | 158 | const verify = crypto.timing_safe.eql([tag_length]u8, computed_tag, tag); |
| 162 | 159 | if (!verify) { |
| 163 | crypto.secureZero(u8, &computed_tag); | |
| 164 | 160 | @memset(m, undefined); |
| 165 | 161 | return error.AuthenticationFailed; |
| 166 | 162 | } |
lib/std/crypto/salsa20.zig-1| ... | ... | @@ -436,7 +436,6 @@ pub const XSalsa20Poly1305 = struct { |
| 436 | 436 | |
| 437 | 437 | const verify = crypto.timing_safe.eql([tag_length]u8, computed_tag, tag); |
| 438 | 438 | if (!verify) { |
| 439 | crypto.secureZero(u8, &computed_tag); | |
| 440 | 439 | @memset(m, undefined); |
| 441 | 440 | return error.AuthenticationFailed; |
| 442 | 441 | } |