Commit graph

102 commits

Author SHA1 Message Date
D-Berg
a98d2540ae std.mem: remove deprecated functions 2025-11-30 16:44:19 +01:00
Andrew Kelley
47aa5a70a5 std: updating to std.Io interface
got the build runner compiling
2025-10-29 06:20:48 -07:00
marximimus
07b6dbf8ca std.crypto.tls.Client: fix infinite loop in std.Io.Writer.writeAll 2025-10-09 12:34:34 -07:00
Frank Denis
12a58087a4
Fix TLS 1.2 client key exchange to use negotiated named group (#25007)
The TLS 1.2 implementation was incorrectly hardcoded to always send the
secp256r1 public key in the client key exchange message, regardless of
which elliptic curve the server actually negotiated.

This caused TLS handshake failures with servers that preferred other curves
like X25519.

This fix:

- Tracks the negotiated named group from the server key exchange message
- Dynamically selects the correct public key (X25519, secp256r1, or
  secp384r1) based on what the server negotiated
- Properly constructs the client key exchange message with the
  appropriate key size for each curve type

Fixes TLS 1.2 connections to servers like ziglang.freetls.fastly.net
that prefer X25519 over secp256r1.
2025-08-27 11:18:40 +02:00
Andrew Kelley
a0f9a5e78d std: more reliable HTTP and TLS networking
* std.Io.Reader: fix confused semantics of rebase. Before it was
  ambiguous whether it was supposed to be based on end or seek. Now it
  is clearly based on seek, with an added assertion for clarity.

* std.crypto.tls.Client: fix panic due to not enough buffer size
  available. Also, avoid unnecessary rebasing.

* std.http.Reader: introduce max_head_len to limit HTTP header length.
  This prevents crash in underlying reader which may require a minimum
  buffer length.

* std.http.Client: choose better buffer sizes for streams and TLS
  client. Crucially, the buffer shared by HTTP reader and TLS client
  needs to be big enough for all http headers *and* the max TLS record
  size. Bump HTTP header size default from 4K to 8K.

fixes #24872

I have noticed however that there are still fetch problems
2025-08-16 00:16:15 -07:00
Andrew Kelley
8721efece4 std.crypto.tls.Client: always write to buffer
simplifies the logic & makes it respect limit
2025-08-07 19:55:40 -07:00
Andrew Kelley
46b34949c3 TLS, HTTP, and package fetching fixes
* TLS: add missing assert for output buffer length requirement
* TLS: add missing flushes
* TLS: add flush implementation
* TLS: finish drain implementation
* HTTP: correct buffer sizes for TLS
* HTTP: expose a getReadError method on Connection
* HTTP: add missing flush on sendBodyComplete
* Fetch: remove unwanted deinit
* Fetch: improve error reporting
2025-08-07 10:04:52 -07:00
Andrew Kelley
3837862e52 fix 32-bit builds 2025-08-07 10:04:52 -07:00
Andrew Kelley
e2d81bf6c0 http fixes 2025-08-07 10:04:29 -07:00
Andrew Kelley
28190cc404 std.crypto.tls: rework for new std.Io API 2025-08-07 10:04:29 -07:00
Andrew Kelley
e7b18a7ce6 std.crypto: remove inline from most functions
To quote the language reference,

It is generally better to let the compiler decide when to inline a
function, except for these scenarios:

* To change how many stack frames are in the call stack, for debugging
  purposes.
* To force comptime-ness of the arguments to propagate to the return
  value of the function, as in the above example.
* Real world performance measurements demand it. Don't guess!

Note that inline actually restricts what the compiler is allowed to do.
This can harm binary size, compilation speed, and even runtime
performance.

`zig run lib/std/crypto/benchmark.zig -OReleaseFast`
[-before-] vs {+after+}

              md5:        [-990-]        {+998+} MiB/s
             sha1:       [-1144-]       {+1140+} MiB/s
           sha256:       [-2267-]       {+2275+} MiB/s
           sha512:        [-762-]        {+767+} MiB/s
         sha3-256:        [-680-]        {+683+} MiB/s
         sha3-512:        [-362-]        {+363+} MiB/s
        shake-128:        [-835-]        {+839+} MiB/s
        shake-256:        [-680-]        {+681+} MiB/s
   turboshake-128:       [-1567-]       {+1570+} MiB/s
   turboshake-256:       [-1276-]       {+1282+} MiB/s
          blake2s:        [-778-]        {+789+} MiB/s
          blake2b:       [-1071-]       {+1086+} MiB/s
           blake3:       [-1148-]       {+1137+} MiB/s
            ghash:      [-10044-]      {+10033+} MiB/s
          polyval:       [-9726-]      {+10033+} MiB/s
         poly1305:       [-2486-]       {+2703+} MiB/s
         hmac-md5:        [-991-]        {+998+} MiB/s
        hmac-sha1:       [-1134-]       {+1137+} MiB/s
      hmac-sha256:       [-2265-]       {+2288+} MiB/s
      hmac-sha512:        [-765-]        {+764+} MiB/s
      siphash-2-4:       [-4410-]       {+4438+} MiB/s
      siphash-1-3:       [-7144-]       {+7225+} MiB/s
   siphash128-2-4:       [-4397-]       {+4449+} MiB/s
   siphash128-1-3:       [-7281-]       {+7374+} MiB/s
  aegis-128x4 mac:      [-73385-]      {+74523+} MiB/s
  aegis-256x4 mac:      [-30160-]      {+30539+} MiB/s
  aegis-128x2 mac:      [-66662-]      {+67267+} MiB/s
  aegis-256x2 mac:      [-16812-]      {+16806+} MiB/s
   aegis-128l mac:      [-33876-]      {+34055+} MiB/s
    aegis-256 mac:       [-8993-]       {+9087+} MiB/s
         aes-cmac:       2036 MiB/s
           x25519:      [-20670-]      {+16844+} exchanges/s
          ed25519:      [-29763-]      {+29576+} signatures/s
       ecdsa-p256:       [-4762-]       {+4900+} signatures/s
       ecdsa-p384:       [-1465-]       {+1500+} signatures/s
  ecdsa-secp256k1:       [-5643-]       {+5769+} signatures/s
          ed25519:      [-21926-]      {+21721+} verifications/s
          ed25519:      [-51200-]      {+50880+} verifications/s (batch)
 chacha20Poly1305:       [-1189-]       {+1109+} MiB/s
xchacha20Poly1305:       [-1196-]       {+1107+} MiB/s
 xchacha8Poly1305:       [-1466-]       {+1555+} MiB/s
 xsalsa20Poly1305:        [-660-]        {+620+} MiB/s
      aegis-128x4:      [-76389-]      {+78181+} MiB/s
      aegis-128x2:      [-53946-]      {+53495+} MiB/s
       aegis-128l:      [-27219-]      {+25621+} MiB/s
      aegis-256x4:      [-49351-]      {+49542+} MiB/s
      aegis-256x2:      [-32390-]      {+32366+} MiB/s
        aegis-256:       [-8881-]       {+8944+} MiB/s
       aes128-gcm:       [-6095-]       {+6205+} MiB/s
       aes256-gcm:       [-5306-]       {+5427+} MiB/s
       aes128-ocb:       [-8529-]      {+13974+} MiB/s
       aes256-ocb:       [-7241-]       {+9442+} MiB/s
        isapa128a:        [-204-]        {+214+} MiB/s
    aes128-single:  [-133857882-]  {+134170944+} ops/s
    aes256-single:   [-96306962-]   {+96408639+} ops/s
         aes128-8: [-1083210101-] {+1073727253+} ops/s
         aes256-8:  [-762042466-]  {+767091778+} ops/s
           bcrypt:      0.009 s/ops
           scrypt:      [-0.018-]      {+0.017+} s/ops
           argon2:      [-0.037-]      {+0.060+} s/ops
      kyber512d00:     [-206057-]     {+205779+} encaps/s
      kyber768d00:     [-156074-]     {+150711+} encaps/s
     kyber1024d00:     [-116626-]     {+115469+} encaps/s
      kyber512d00:     [-181149-]     {+182046+} decaps/s
      kyber768d00:     [-136965-]     {+135676+} decaps/s
     kyber1024d00:     [-101307-]     {+100643+} decaps/s
      kyber512d00:     [-123624-]     {+123375+} keygen/s
      kyber768d00:      [-69465-]      {+70828+} keygen/s
     kyber1024d00:      [-43117-]      {+43208+} keygen/s
2025-07-13 18:26:13 +02:00
Andrew Kelley
0e37ff0d59 std.fmt: breaking API changes
added adapter to AnyWriter and GenericWriter to help bridge the gap
between old and new API

make std.testing.expectFmt work at compile-time

std.fmt no longer has a dependency on std.unicode. Formatted printing
was never properly unicode-aware. Now it no longer pretends to be.

Breakage/deprecations:
* std.fs.File.reader -> std.fs.File.deprecatedReader
* std.fs.File.writer -> std.fs.File.deprecatedWriter
* std.io.GenericReader -> std.io.Reader
* std.io.GenericWriter -> std.io.Writer
* std.io.AnyReader -> std.io.Reader
* std.io.AnyWriter -> std.io.Writer
* std.fmt.format -> std.fmt.deprecatedFormat
* std.fmt.fmtSliceEscapeLower -> std.ascii.hexEscape
* std.fmt.fmtSliceEscapeUpper -> std.ascii.hexEscape
* std.fmt.fmtSliceHexLower -> {x}
* std.fmt.fmtSliceHexUpper -> {X}
* std.fmt.fmtIntSizeDec -> {B}
* std.fmt.fmtIntSizeBin -> {Bi}
* std.fmt.fmtDuration -> {D}
* std.fmt.fmtDurationSigned -> {D}
* {} -> {f} when there is a format method
* format method signature
  - anytype -> *std.io.Writer
  - inferred error set -> error{WriteFailed}
  - options -> (deleted)
* std.fmt.Formatted
  - now takes context type explicitly
  - no fmt string
2025-07-07 22:43:51 -07:00
Shun Sakai
5fc4448e45 chore(std.mem): Rename trimLeft and trimRight
Rename `trimLeft` to `trimStart`, and `trimRight` to `trimEnd`.
`trimLeft` and `trimRight` functions remain as deprecated aliases for
these new names.
2025-04-27 18:03:59 +09:00
Roman Frołow
37bbe7e930 typo: was issues -> was issued 2025-03-15 12:14:00 +01:00
Andrew Kelley
eb3c7f5706 zig build fmt 2025-02-22 17:09:20 -08:00
Jacob Young
7c713251ca x86_64: looped instructions 2025-01-16 20:42:08 -05:00
Frank Denis
8a00bd4ce6
std.crypto: make the key pair API creation consistent (#21955)
Our key pair creation API was ugly and inconsistent between ecdsa
keys and other keys.

The same `generate()` function can now be used to generate key pairs,
and that function cannot fail.

For deterministic keys, a `generateDeterministic()` function is
available for all key types.

Fix comments and compilation of the benchmark by the way.

Fixes #21002
2024-11-19 18:05:09 +01:00
Jacob Young
75adba7cb9 std.crypto.tls: add support for secp384r1 key share 2024-11-07 20:25:26 -05:00
Jacob Young
a4e88abf04 std.crypto.tls: advertise all supported signature algorithms 2024-11-07 20:25:26 -05:00
Jacob Young
fbaefcaa94 std.crypto.tls: support the same key sizes as certificate verification 2024-11-07 20:25:26 -05:00
Jacob Young
a6ede7ba86 std.crypto.tls: support handshake fragments 2024-11-07 20:25:26 -05:00
Jacob Young
de53e6e4f2 std.crypto.tls: improve debuggability of encrypted connections
By default, programs built in debug mode that open a https connection
will append secrets to the file specified in the SSLKEYLOGFILE
environment variable to allow protocol debugging by external programs.
2024-11-07 20:25:26 -05:00
Jacob Young
d86a8aedd5 std.crypto.tls: increase handshake buffer sizes 2024-11-07 20:25:26 -05:00
Jacob Young
485f20a10a std.crypto.tls: remove hardcoded initial loop
This was preventing TLSv1.2 from working in some cases, because servers
are allowed to send multiple handshake messages in the first handshake
record, whereas this inital loop was assuming that it only contained a
server hello.
2024-11-07 20:25:26 -05:00
Jacob Young
90a761c186 std.crypto.tls: make verify data checks timing safe 2024-11-07 20:25:26 -05:00
Jacob Young
7afb277725 std.crypto.tls: fix x25519_ml_kem768 key share
This is mostly nfc cleanup as I was bisecting the client hello to find
the problematic part, and the only bug fix ended up being

    key_share.x25519_kp.public_key ++
    key_share.ml_kem768_kp.public_key.toBytes()

to

    key_share.ml_kem768_kp.public_key.toBytes() ++
    key_share.x25519_kp.public_key)

and the same swap in `KeyShare.exchange` as per some random blog that
says "a hybrid keyshare, constructed by concatenating the public KEM key
with the public X25519 key".  I also note that based on the same blog
post, there was a draft version of this method that indeed had these
values swapped, and that used to be supported by this code, but it was
not properly fixed up when this code was updated from the draft spec.

Closes #21747
2024-11-07 20:25:26 -05:00
Jacob Young
7f20c78c95 std.crypto: delete new functions that are only used once 2024-11-07 20:25:26 -05:00
Jacob Young
4466f145d6 std.crypto.tls: support more key share params
This condition is already checked less restrictively in
`KeyShare.exchange`.
2024-11-07 20:25:26 -05:00
Jacob Young
e184b15a66 std.crypto.tls: fix fetching https://nginx.org
Note that the removed `error.TlsIllegalParameter` case is still caught
below when it is compared to a fixed-length string, but after checking
the proper protocol version requirement first.
2024-11-07 20:25:26 -05:00
Jacob Young
c2a779ae79 std.crypto.tls: implement TLSv1.2 2024-11-07 20:25:26 -05:00
Frank Denis
c062c532d7 Add post-quantum key agreement X25519MLKEM768
X25519MLKEM768 replaces X25519Kyber768Draft00 now that NIST has
released ML-KEM.

IANA has assigned the codepoint 0x11ec:
https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#tls-parameters-8
2024-09-24 13:18:32 -07:00
Igor Anić
aa73bb6bc9
tls.Client: implement record padding (#20558)
On decryption tls client should remove zero byte padding after the
content type field. This padding is rarely used, the only site (from the
list of top domains) that I found using it is `tutanota.com`.

From [RFC](https://datatracker.ietf.org/doc/html/rfc8446#section-5.4):
> All encrypted TLS records can be padded.
> Padding is a string of zero-valued bytes appended to the ContentType
field before encryption.
> the receiving implementation scans the field from the end toward the
beginning until it finds a non-zero octet. This non-zero octet is the
content type of the message.

Currently we can't connect to that site:
```
$ zig run main.zig -- tutanota.com
error: TlsInitializationFailed
/usr/local/zig/zig-linux-x86_64-0.14.0-dev.208+854e86c56/lib/std/crypto/tls/Client.zig:476:45: 0x121fbed in init__anon_10331 (http_get_std)
                if (inner_ct != .handshake) return error.TlsUnexpectedMessage;
                                            ^
/usr/local/zig/zig-linux-x86_64-0.14.0-dev.208+854e86c56/lib/std/http/Client.zig:1357:99: 0x1161f0b in connectTcp (http_get_std)
        conn.data.tls_client.* = std.crypto.tls.Client.init(stream, client.ca_bundle, host) catch return error.TlsInitializationFailed;
                                                                                                  ^
/usr/local/zig/zig-linux-x86_64-0.14.0-dev.208+854e86c56/lib/std/http/Client.zig:1492:14: 0x11271e1 in connect (http_get_std)
    } orelse return client.connectTcp(host, port, protocol);
             ^
/usr/local/zig/zig-linux-x86_64-0.14.0-dev.208+854e86c56/lib/std/http/Client.zig:1640:9: 0x111a24e in open (http_get_std)
        try client.connect(valid_uri.host.?.raw, uriPort(valid_uri, protocol), protocol);
        ^
/home/ianic/Code/tls.zig/example/http_get_std.zig:28:19: 0x1118f8c in main (http_get_std)
        var req = try client.open(.GET, uri, .{ .server_header_buffer = &server_header_buffer });
                  ^
```
using this example:

```zig
const std = @import("std");

pub fn main() !void {
    var gpa = std.heap.GeneralPurposeAllocator(.{}){};
    const allocator = gpa.allocator();

    const args = try std.process.argsAlloc(allocator);
    defer std.process.argsFree(allocator, args);

    if (args.len > 1) {
        const domain = args[1];

        var client: std.http.Client = .{ .allocator = allocator };
        defer client.deinit();

        // Add https:// prefix if needed
        const url = brk: {
            const scheme = "https://";
            if (domain.len >= scheme.len and std.mem.eql(u8, domain[0..scheme.len], scheme))
                break :brk domain;

            var url_buf: [128]u8 = undefined;
            break :brk try std.fmt.bufPrint(&url_buf, "https://{s}", .{domain});
        };

        const uri = try std.Uri.parse(url);
        var server_header_buffer: [16 * 1024]u8 = undefined;
        var req = try client.open(.GET, uri, .{ .server_header_buffer = &server_header_buffer });
        defer req.deinit();

        try req.send();
        try req.wait();
    }
}
```
2024-07-21 01:19:36 -07:00
Igor Anić
ca752c61c0 tls.Client: fix out of bounds panic
When calculating how much ciphertext from the stream can fit into
user and internal buffers we should also take into account ciphertext
data which are already in internal buffer.

Fixes: 15226

Tested with
[this](https://github.com/ziglang/zig/issues/15226#issuecomment-2218809140).
Using client with different read buffers until I, hopefully, understood
what is happening.

Not relevant to this fix, but this
[part](95d9292a7a/lib/std/crypto/tls/Client.zig (L988-L991))
is still mystery to me. Why we don't use free_size in buf_cap
calculation. Seems like rudiment from previous implementation without iovec.
2024-07-12 03:07:15 -04:00
Jora Troosh
13070448f5
std: fix typos (#20560) 2024-07-09 14:25:42 -07:00
Nameless
aecd9cc6d1 std.posix.iovec: use .base and .len instead of .iov_base and .iov_len 2024-04-28 00:20:30 -07:00
Andrew Kelley
cd62005f19 extract std.posix from std.os
closes #5019
2024-03-19 11:45:09 -07:00
Jacob Young
eaa6218f09 x86_64: fix errors compiling the compiler
This fixes issues targetting both `x86_64-linux` and `x86_64-macos` with
the self-hosted backend.
2024-02-04 22:58:38 -05:00
Jacob Young
5e791e8e07 tls: support ed25519 signatures
Which were claimed to be supported during the handshake but were not
actually implemented.
2024-02-02 17:27:26 -08:00
melonedo
9b0da5ccef Fix TLS record overflow by limiting inner record length to 2^14
Per last paragraph of RFC 8446, Section 5.2, the length of the inner content of an encrypted record must not exceed 2^14 + 1, while that of the whole encrypted record must not exceed 2^14 + 256.
2024-01-16 14:58:56 -08:00
Purrie
c4a1b54ebe tls client interface consistency fix
Client for tls was using a function that wasn't declared on the
interface for it. The issue wasn't apparent because net stream
implemented that function.

I changed it to keep the interface promise of what's required to be
compatible with the tls client functionality.
2024-01-16 13:02:00 -08:00
Frank Denis
f276bb107e verify_buffer is not expected to be sentinel-terminated 2023-12-01 20:04:52 +01:00
Frank Denis
9831dc9e0c TLS: The 0x1306 TLS identifier was updated to TLS_AEGIS_256_SHA512
Following the recommendations from [1], the AEGIS specification
and the TLS registry [2] were updated to recommend SHA512 for the
traffic secrets.

[1] https://eprint.iacr.org/2023/913.pdf
[2] https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#tls-parameters-4
2023-12-01 18:00:15 +01:00
mlugg
51595d6b75
lib: correct unnecessary uses of 'var' 2023-11-19 09:55:07 +00:00
Andrew Kelley
3fc6fc6812 std.builtin.Endian: make the tags lower case
Let's take this breaking change opportunity to fix the style of this
enum.
2023-10-31 21:37:35 -04:00
Jacob Young
d890e81761 mem: fix ub in writeInt
Use inline to vastly simplify the exposed API.  This allows a
comptime-known endian parameter to be propogated, making extra functions
for a specific endianness completely unnecessary.
2023-10-31 21:37:35 -04:00
Nameless
e1c37f70d4
std.http.Client: store *Connection instead of a pool node, buffer writes 2023-10-21 20:52:58 -05:00
dec05eba
2e424e019f Client.zig: support rsa_pss_rsae_sha384 and rsa_pss_rsae_sha512
This fixes HTTP GET to https://www.iana.org/domains/reserved
for example
2023-07-06 18:36:15 -07:00
Jacob Young
8239d3b358 crypto: recoup storage in tls.Client.partially_read_buffer 2023-06-26 21:05:08 -04:00
Jacob Young
eb8881a538 crypto: cleanup unneeded uses of @as in tls.Client 2023-06-26 21:05:08 -04:00
mlugg
f26dda2117 all: migrate code to new cast builtin syntax
Most of this migration was performed automatically with `zig fmt`. There
were a few exceptions which I had to manually fix:

* `@alignCast` and `@addrSpaceCast` cannot be automatically rewritten
* `@truncate`'s fixup is incorrect for vectors
* Test cases are not formatted, and their error locations change
2023-06-24 16:56:39 -07:00