From ea0e03d4fdd70f4442419ebf56a9059affe1c75c Mon Sep 17 00:00:00 2001 From: serg Date: Thu, 22 Aug 2024 17:49:40 +0300 Subject: [PATCH 1/3] add tests for `sha1` and `sha256` --- build.zig | 24 +++++++++++ tests/main.zig | 3 ++ tests/sha.zig | 114 +++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 141 insertions(+) create mode 100644 tests/main.zig create mode 100644 tests/sha.zig diff --git a/build.zig b/build.zig index 4cdbd47..713ecd2 100644 --- a/build.zig +++ b/build.zig @@ -304,6 +304,30 @@ pub fn build(b: *std.Build) !void { example_run.step.dependOn(&examples_install.step); examples_step.dependOn(&example_run.step); } + + const tests_step = b.step("run-tests", "Tests"); + { + const tests = b.addTest(.{ + .root_source_file = b.path("tests/main.zig"), + .target = target, + .optimize = optimize, + .link_libc = true, + }); + + const fixture = b.addOptions(); + fixture.addOptionPath("resources", libgit_src.path("tests/resources")); + + tests.root_module.addOptions("fixture", fixture); + + tests.addConfigHeader(features); + tests.addIncludePath(libgit_src.path("include")); + tests.addIncludePath(libgit_src.path("src/util")); + + tests.linkLibrary(lib); + + const tests_run = b.addRunArtifact(tests); + tests_step.dependOn(&tests_run.step); + } } const libgit_sources = [_][]const u8{ diff --git a/tests/main.zig b/tests/main.zig new file mode 100644 index 0000000..7997590 --- /dev/null +++ b/tests/main.zig @@ -0,0 +1,3 @@ +test { + _ = @import("sha.zig"); +} diff --git a/tests/sha.zig b/tests/sha.zig new file mode 100644 index 0000000..1fbd959 --- /dev/null +++ b/tests/sha.zig @@ -0,0 +1,114 @@ +const std = @import("std"); +const testing = std.testing; + +const c = @cImport({ + @cInclude("hash.h"); +}); + +const fixture = @import("fixture"); + +fn calcHashFile( + allocator: std.mem.Allocator, + filename: []const u8, + comptime algorithm: c.git_hash_algorithm_t, +) ![]u8 { + const file = try std.fs.openFileAbsolute( + filename, + .{}, + ); + defer file.close(); + + const size: usize = switch (algorithm) { + c.GIT_HASH_ALGORITHM_SHA1 => c.GIT_HASH_SHA1_SIZE, + c.GIT_HASH_ALGORITHM_SHA256 => c.GIT_HASH_SHA256_SIZE, + else => unreachable, + }; + const actual = try allocator.alloc(u8, size); + + var r: c_int = undefined; + var ctx: c.git_hash_ctx = undefined; + r = c.git_hash_ctx_init(&ctx, algorithm); + if (r != 0) return error.Unexpected; + defer c.git_hash_ctx_cleanup(&ctx); + + const reader = file.reader(); + while (true) { + var buf: [2048]u8 = undefined; + const len = try reader.read(&buf); + if (len == 0) break; + r = c.git_hash_update(&ctx, &buf, len); + if (r != 0) return error.Unexpected; + } + + r = c.git_hash_final(actual.ptr, &ctx); + if (r != 0) return error.Unexpected; + + return actual; +} + +test "sha1" { + const expect = [c.GIT_HASH_SHA1_SIZE]u8{ + 0x4e, 0x72, 0x67, 0x9e, 0x3e, 0xa4, 0xd0, 0x4e, + 0x0c, 0x64, 0x2f, 0x02, 0x9e, 0x61, 0xeb, 0x80, + 0x56, 0xc7, 0xed, 0x94, + }; + const actual = try calcHashFile( + testing.allocator, + fixture.resources ++ "/sha1/hello_c", + c.GIT_HASH_ALGORITHM_SHA1, + ); + defer testing.allocator.free(actual); + + try testing.expectEqualSlices(u8, &expect, actual); +} + +test "sha256 empty" { + const expect = [c.GIT_HASH_SHA256_SIZE]u8{ + 0xe3, 0xb0, 0xc4, 0x42, 0x98, 0xfc, 0x1c, 0x14, + 0x9a, 0xfb, 0xf4, 0xc8, 0x99, 0x6f, 0xb9, 0x24, + 0x27, 0xae, 0x41, 0xe4, 0x64, 0x9b, 0x93, 0x4c, + 0xa4, 0x95, 0x99, 0x1b, 0x78, 0x52, 0xb8, 0x55, + }; + const actual = try calcHashFile( + testing.allocator, + fixture.resources ++ "/sha1/empty", + c.GIT_HASH_ALGORITHM_SHA256, + ); + defer testing.allocator.free(actual); + + try testing.expectEqualSlices(u8, &expect, actual); +} + +test "sha256 hello" { + const expect = [c.GIT_HASH_SHA256_SIZE]u8{ + 0xaa, 0x32, 0x7f, 0xae, 0x5c, 0x91, 0x58, 0x3a, + 0x4f, 0xb6, 0x54, 0xcc, 0xb6, 0xc2, 0xb1, 0x0c, + 0x77, 0xd7, 0x49, 0xc9, 0x91, 0x2a, 0x8d, 0x6b, + 0x47, 0x26, 0x13, 0xc0, 0xa0, 0x4b, 0x4d, 0xad, + }; + const actual = try calcHashFile( + testing.allocator, + fixture.resources ++ "/sha1/hello_c", + c.GIT_HASH_ALGORITHM_SHA256, + ); + defer testing.allocator.free(actual); + + try testing.expectEqualSlices(u8, &expect, actual); +} + +test "sha256 pdf" { + const expect = [c.GIT_HASH_SHA256_SIZE]u8{ + 0x2b, 0xb7, 0x87, 0xa7, 0x3e, 0x37, 0x35, 0x2f, + 0x92, 0x38, 0x3a, 0xbe, 0x7e, 0x29, 0x02, 0x93, + 0x6d, 0x10, 0x59, 0xad, 0x9f, 0x1b, 0xa6, 0xda, + 0xaa, 0x9c, 0x1e, 0x58, 0xee, 0x69, 0x70, 0xd0, + }; + const actual = try calcHashFile( + testing.allocator, + fixture.resources ++ "/sha1/shattered-1.pdf", + c.GIT_HASH_ALGORITHM_SHA256, + ); + defer testing.allocator.free(actual); + + try testing.expectEqualSlices(u8, &expect, actual); +} From df5e267b339c2fb333d90331e7a0fae8906a6efb Mon Sep 17 00:00:00 2001 From: serg Date: Thu, 22 Aug 2024 20:11:20 +0300 Subject: [PATCH 2/3] add openssl --- build.zig | 97 +++++++++++++++++++++++++++++++++++++++------------ build.zig.zon | 6 +++- 2 files changed, 80 insertions(+), 23 deletions(-) diff --git a/build.zig b/build.zig index 713ecd2..a6bbef5 100644 --- a/build.zig +++ b/build.zig @@ -40,6 +40,11 @@ pub fn build(b: *std.Build) !void { "-fno-sanitize=undefined", }; + const openssl = switch (target.result.os.tag) { + .linux => b.option(bool, "enable-openssl", "Enable OpenSSL support") orelse false, + else => false, + }; + if (target.result.os.tag == .windows) { lib.linkSystemLibrary("winhttp"); lib.linkSystemLibrary("rpcrt4"); @@ -61,20 +66,37 @@ pub fn build(b: *std.Build) !void { lib.addWin32ResourceFile(.{ .file = libgit_src.path("src/libgit2/git2.rc") }); lib.addCSourceFiles(.{ .root = libgit_root, .files = &util_win32_sources, .flags = &flags }); } else { - // mbedTLS https and SHA backend - lib.linkSystemLibrary("mbedtls"); - lib.linkSystemLibrary("mbedcrypto"); - lib.linkSystemLibrary("mbedx509"); - features.addValues(.{ - .GIT_HTTPS = 1, - .GIT_MBEDTLS = 1, - .GIT_SHA1_MBEDTLS = 1, - .GIT_SHA256_MBEDTLS = 1, - - .GIT_USE_FUTIMENS = 1, - .GIT_IO_POLL = 1, - .GIT_IO_SELECT = 1, - }); + if (openssl) { + // OpenSSL backend + const openssl_dep = b.dependency("openssl", .{}); + const openssl_lib = openssl_dep.artifact("openssl"); + lib.linkLibrary(openssl_lib); + features.addValues(.{ + .GIT_HTTPS = 1, + .GIT_OPENSSL = 1, + .GIT_SHA1_OPENSSL = 1, + .GIT_SHA256_OPENSSL = 1, + + .GIT_USE_FUTIMENS = 1, + .GIT_IO_POLL = 1, + .GIT_IO_SELECT = 1, + }); + } else { + // mbedTLS https and SHA backend + lib.linkSystemLibrary("mbedtls"); + lib.linkSystemLibrary("mbedcrypto"); + lib.linkSystemLibrary("mbedx509"); + features.addValues(.{ + .GIT_HTTPS = 1, + .GIT_MBEDTLS = 1, + .GIT_SHA1_MBEDTLS = 1, + .GIT_SHA256_MBEDTLS = 1, + + .GIT_USE_FUTIMENS = 1, + .GIT_IO_POLL = 1, + .GIT_IO_SELECT = 1, + }); + } // ntlmclient { @@ -85,15 +107,30 @@ pub fn build(b: *std.Build) !void { .link_libc = true, }); ntlm.addIncludePath(libgit_src.path("deps/ntlmclient")); + if (openssl) addOpenSSLHeaders(ntlm); + + const ntlm_cflags = .{ + "-Wno-implicit-fallthrough", + "-DNTLM_STATIC=1", + "-DUNICODE_BUILTIN=1", + if (openssl) + "-DCRYPT_OPENSSL" + else + "-DCRYPT_MBEDTLS", + }; ntlm.addCSourceFiles(.{ .root = libgit_root, .files = &ntlm_sources, - .flags = &.{ - "-Wno-implicit-fallthrough", - "-DNTLM_STATIC=1", - "-DUNICODE_BUILTIN=1", - "-DCRYPT_MBEDTLS", + .flags = &ntlm_cflags, + }); + ntlm.addCSourceFiles(.{ + .root = libgit_root, + .files = if (openssl) &.{ + "deps/ntlmclient/crypt_openssl.c", + } else &.{ + "deps/ntlmclient/crypt_mbedtls.c", }, + .flags = &ntlm_cflags, }); lib.linkLibrary(ntlm); @@ -106,6 +143,15 @@ pub fn build(b: *std.Build) !void { .files = &util_unix_sources, .flags = &flags, }); + lib.addCSourceFiles(.{ + .root = libgit_root, + .files = if (openssl) &.{ + "src/util/hash/openssl.c", + } else &.{ + "src/util/hash/mbedtls.c", + }, + .flags = &flags, + }); } if (b.option(bool, "enable-ssh", "Enable SSH support") orelse false) { @@ -249,6 +295,7 @@ pub fn build(b: *std.Build) !void { cli.addIncludePath(libgit_src.path("include")); cli.addIncludePath(libgit_src.path("src/util")); cli.addIncludePath(libgit_src.path("src/cli")); + if (openssl) addOpenSSLHeaders(cli); if (target.result.os.tag == .windows) cli.addCSourceFiles(.{ .root = libgit_root, .files = &cli_win32_sources }) @@ -293,6 +340,7 @@ pub fn build(b: *std.Build) !void { }); exe.addIncludePath(libgit_src.path("include")); + if (openssl) addOpenSSLHeaders(exe); exe.linkLibrary(lib); // independent install step so you can easily access the binary @@ -322,6 +370,7 @@ pub fn build(b: *std.Build) !void { tests.addConfigHeader(features); tests.addIncludePath(libgit_src.path("include")); tests.addIncludePath(libgit_src.path("src/util")); + if (openssl) addOpenSSLHeaders(tests); tests.linkLibrary(lib); @@ -330,6 +379,13 @@ pub fn build(b: *std.Build) !void { } } +fn addOpenSSLHeaders(compile: *std.Build.Step.Compile) void { + const b = compile.step.owner; + const openssl_dep = b.dependency("openssl", .{}); + const openssl_lib = openssl_dep.artifact("openssl"); + compile.addIncludePath(openssl_lib.getEmittedIncludeTree()); +} + const libgit_sources = [_][]const u8{ "src/libgit2/annotated_commit.c", "src/libgit2/apply.c", @@ -502,8 +558,6 @@ const util_unix_sources = [_][]const u8{ "src/util/unix/map.c", "src/util/unix/process.c", "src/util/unix/realpath.c", - - "src/util/hash/mbedtls.c", }; const util_win32_sources = [_][]const u8{ @@ -579,7 +633,6 @@ const xdiff_sources = [_][]const u8{ const ntlm_sources = [_][]const u8{ "deps/ntlmclient/crypt_builtin_md4.c", - "deps/ntlmclient/crypt_mbedtls.c", "deps/ntlmclient/ntlm.c", "deps/ntlmclient/unicode_builtin.c", "deps/ntlmclient/util.c", diff --git a/build.zig.zon b/build.zig.zon index 41a2db8..4701602 100644 --- a/build.zig.zon +++ b/build.zig.zon @@ -6,7 +6,11 @@ .libgit2 = .{ .url = "https://github.com/libgit2/libgit2/archive/refs/tags/v1.8.1.tar.gz", .hash = "12208db692747f305b79ecfb3ac69e691d0b9584383ec4bcb0eb07b62b73de77b1cf", - } + }, + .openssl = .{ + .url = "https://github.com/allyourcodebase/openssl/archive/refs/tags/3.3.1-1.tar.gz", + .hash = "12207c40cefa38fe90e4230dfba2e5c76b37e1ee36602512cad8ff0501f892002a65", + }, }, .paths = .{ "build.zig", From 7d29a7fc9b32476524e48309de32b53727f0d824 Mon Sep 17 00:00:00 2001 From: Julian <29632054+Parzival-3141@users.noreply.github.com> Date: Sat, 31 Aug 2024 19:09:48 -0400 Subject: [PATCH 3/3] openssl option logic --- build.zig | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/build.zig b/build.zig index a6bbef5..638f4c0 100644 --- a/build.zig +++ b/build.zig @@ -40,12 +40,14 @@ pub fn build(b: *std.Build) !void { "-fno-sanitize=undefined", }; - const openssl = switch (target.result.os.tag) { - .linux => b.option(bool, "enable-openssl", "Enable OpenSSL support") orelse false, - else => false, - }; + const openssl = b.option(bool, "enable-openssl", "Use OpenSSL instead of MbedTLS") orelse false; if (target.result.os.tag == .windows) { + if (openssl) { + std.log.err("OpenSSL option unsupported on Windows", .{}); + return; + } + lib.linkSystemLibrary("winhttp"); lib.linkSystemLibrary("rpcrt4"); lib.linkSystemLibrary("crypt32");