| ... | ... | @@ -138,8 +138,10 @@ pub fn Ecdsa(comptime C: type, comptime H: type) type { |
| 138 | 138 | /// The function returns a slice, that can be shorter than der_encoded_length_max. |
| 139 | 139 | pub fn toDer(sig: Signature, buf: *[der_encoded_length_max]u8) []u8 { |
| 140 | 140 | var w: std.Io.Writer = .fixed(buf); |
| 141 | | const sig_r = mem.trimStart(u8, &sig.r, &.{0}); |
| 142 | | const sig_s = mem.trimStart(u8, &sig.s, &.{0}); |
| 141 | const trimmed_r = mem.trimStart(u8, &sig.r, &.{0}); |
| 142 | const trimmed_s = mem.trimStart(u8, &sig.s, &.{0}); |
| 143 | const sig_r: []const u8 = if (trimmed_r.len == 0) &.{0} else trimmed_r; |
| 144 | const sig_s: []const u8 = if (trimmed_s.len == 0) &.{0} else trimmed_s; |
| 143 | 145 | const r_len = @as(u8, @intCast(sig_r.len + (sig_r[0] >> 7))); |
| 144 | 146 | const s_len = @as(u8, @intCast(sig_s.len + (sig_s[0] >> 7))); |
| 145 | 147 | const seq_len = @as(u8, @intCast(2 + r_len + 2 + s_len)); |
| ... | ... | @@ -171,7 +173,8 @@ pub fn Ecdsa(comptime C: type, comptime H: type) type { |
| 171 | 173 | } |
| 172 | 174 | const out_slice = out[out.len - expected_len ..]; |
| 173 | 175 | reader.readSliceAll(out_slice) catch return error.InvalidEncoding; |
| 174 | | if (@intFromBool(has_top_bit) != out[0] >> 7) return error.InvalidEncoding; |
| 176 | if (@intFromBool(has_top_bit) != out_slice[0] >> 7) return error.InvalidEncoding; |
| 177 | if (expected_len > 1 and out_slice[0] == 0 and out_slice[1] >> 7 == 0) return error.InvalidEncoding; |
| 175 | 178 | } |
| 176 | 179 | |
| 177 | 180 | /// Create a signature from a DER representation. |
| ... | ... | @@ -534,6 +537,23 @@ test "Prehashed message operations" { |
| 534 | 537 | try sig.verify(msg, kp.public_key); |
| 535 | 538 | } |
| 536 | 539 | |
| 540 | test "DER decoding edge cases" { |
| 541 | const Scheme = EcdsaP256Sha256; |
| 542 | const negative_r = [_]u8{ 0x30, 0x06, 0x02, 0x01, 0x80, 0x02, 0x01, 0x01 }; |
| 543 | const padded_r = [_]u8{ 0x30, 0x07, 0x02, 0x02, 0x00, 0x01, 0x02, 0x01, 0x01 }; |
| 544 | try testing.expectError(error.InvalidEncoding, Scheme.Signature.fromDer(&negative_r)); |
| 545 | try testing.expectError(error.InvalidEncoding, Scheme.Signature.fromDer(&padded_r)); |
| 546 | |
| 547 | const raw: [Scheme.Signature.encoded_length]u8 = @splat(0); |
| 548 | const sig = Scheme.Signature.fromBytes(raw); |
| 549 | var der: [Scheme.Signature.der_encoded_length_max]u8 = undefined; |
| 550 | try testing.expectEqualSlices( |
| 551 | u8, |
| 552 | &.{ 0x30, 0x06, 0x02, 0x01, 0x00, 0x02, 0x01, 0x00 }, |
| 553 | sig.toDer(&der), |
| 554 | ); |
| 555 | } |
| 556 | |
| 537 | 557 | const TestVector = struct { |
| 538 | 558 | key: []const u8, |
| 539 | 559 | msg: []const u8, |