TlsInitializationFailed thrown on http request

Hello Zig community,

I am currently in the process of learning Zig, a language that I have come to love. However, I have encountered a roadblock in the form of a TlsInitializationFailed error. I’ve provided a sample code snippet below that reproduces this error.

At the moment, I am using zig 0.12.0-dev.167+dd6a9caea on WSL2, which is running Ubuntu. I suspect that Zig uses openssl under the hood, and this could potentially be the cause of the error. My current openssl version is 3.0.2-0ubuntu1.10.

Thank you for any assistance or insights you can provide.

const std = @import("std");

const http = std.http;
const allocator = std.heap.page_allocator;
const log = std.debug.print;

pub fn main() !void {
    var client: http.Client = .{ .allocator = allocator };
    defer client.deinit();

    var request = try client.request(http.Method.GET, try std.Uri.parse("https://pacstall.dev/api/packages/1password-cli-bin"), .{ .allocator = allocator }, .{}); // <<-- fails here
    defer request.deinit();
    try request.start();
    try request.wait();
    log("response {}\n", .{request.response.status});
}

Here’s the stacktrace:

error: TlsInitializationFailed
/home/saenai/Library/zig-linux-x86_64-0.12.0/lib/std/crypto/tls.zig:200:9: 0x3b248e in toError (main)
        return switch (alert) {
        ^
/home/saenai/Library/zig-linux-x86_64-0.12.0/lib/std/crypto/tls/Client.zig:255:17: 0x38da47 in init__anon_10436 (main)
                try desc.toError();
                ^
/home/saenai/Library/zig-linux-x86_64-0.12.0/lib/std/http/Client.zig:912:103: 0x2cadde in connectUnproxied (main)
            conn.data.tls_client.* = std.crypto.tls.Client.init(stream, client.ca_bundle, host) catch return error.TlsInitializationFailed;
                                                                                                      ^
/home/saenai/Library/zig-linux-x86_64-0.12.0/lib/std/http/Client.zig:947:9: 0x291af6 in connect (main)
        return client.connectUnproxied(host, port, protocol);
        ^
/home/saenai/Library/zig-linux-x86_64-0.12.0/lib/std/http/Client.zig:1012:44: 0x28b0ba in request (main)
    const conn = options.connection orelse try client.connect(host, port, protocol);
                                           ^
/home/saenai/Code/zig-app/src/main.zig:11:19: 0x28a519 in main (main)
    var request = try client.request(http.Method.GET, try std.Uri.parse("https://pacstall.dev/api/packages/1password-cli-bin"), .{ .allocator = allocator }, .{});

Edit:
I’ve tested other URIs like https://jsonplaceholder.typicode.com/todos/1, and they work. But I’m still unsure why it’s not working for pacstall.dev, as the domain certificate is valid. Any help is appreciated.

1 Like

I understand zig’s current TLS implementation only supports TLS 1.3.

You can ascertain that there is a difference between the two URLs like this:

$ curl -v https://jsonplaceholder.typicode.com/todos/1 2>&1 | egrep 'SSL connection using TLS'
* SSL connection using TLSv1.3 / AEAD-CHACHA20-POLY1305-SHA256

$ curl -v https://pacstall.dev/api/packages/1password-cli-bin 2>&1 | egrep 'SSL connection using TLS'
* SSL connection using TLSv1.2 / ECDHE-RSA-AES256-GCM-SHA384
3 Likes

@gonzo OK. so I do have TLSv1.3, but I’m still getting this error in zig 0.12:

curl -v https://finance.melroy.org 2>&1 | egrep ‘SSL connection using TLS’

  • SSL connection using TLSv1.3 / TLS_AES_256_GCM_SHA384

Yes TLS_AES_256_GCM_SHA384 is recommended.

When running my program I get:

error: TlsInitializationFailed
/usr/lib/zig/std/crypto/tls.zig:200:9: 0x3fe73e in toError (rambam)
        return switch (alert) {
        ^
/usr/lib/zig/std/crypto/tls/Client.zig:255:17: 0x3b3bf5 in init__anon_10018 (rambam)
                try desc.toError();
                ^
/usr/lib/zig/std/http/Client.zig:1192:99: 0x2eec6b in connectTcp (rambam)
        conn.data.tls_client.* = std.crypto.tls.Client.init(stream, client.ca_bundle, host) catch return error.TlsInitializationFailed;
                                                                                                  ^
/usr/lib/zig/std/http/Client.zig:1356:5: 0x2ab838 in connect (rambam)
    return client.connectTcp(host, port, protocol);
    ^
/usr/lib/zig/std/http/Client.zig:1435:44: 0x2a14dc in open (rambam)
    const conn = options.connection orelse try client.connect(host, port, protocol);
                                           ^
/media/melroy/Data/Projects/rambam/src/main.zig:31:19: 0x2a06a4 in main (rambam)
    var request = try client.open(.GET, uri, headers, .{});

My code snippet:

    var client = http.Client{ .allocator = allocator };
    // If client goes out of scope, we call: deinit
    defer client.deinit();

    // Let's go..
    // Parse the URI.
    const uri = std.Uri.parse("https://finance.melroy.org/v1/cryptos/quote/BCH?quote_currency=USD") catch unreachable;

    // Create the headers that will be sent to the server.
    var headers = std.http.Headers{ .allocator = allocator };
    defer headers.deinit();

    // Accept anything (example header).
    try headers.append("accept", "*/*");

    // Make the connection to the server.
    // TODO: Maybe use fetch?
    var request = try client.open(.GET, uri, headers, .{});
    defer request.deinit();

    // Wait for the server to send use a response.
    try request.wait();

I wish I could be of more assistance @melroy89 but I am not using network calls with zig at all.

Just as a data point, I get a different cipher for your URL:

$ curl -v 'https://finance.melroy.org' 2>&1 | egrep 'SSL connection using TLS'                                        
* SSL connection using TLSv1.3 / AEAD-CHACHA20-POLY1305-SHA256

Good luck!

1 Like

Maybe different curl versions or whatever the reason might be. I’m running Nginx server with the following approved ciphers (so I do support more ciphers and I support both TLSv1.2 as well as TLSv1.3 as you can see):

ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;
ssl_prefer_server_ciphers off;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
ssl_session_tickets on;