Skip to content

Commit 1476225

Browse files
Merge pull request #1 from sergpolkin/openssl
Add openssl support
2 parents 7b8579f + 7d29a7f commit 1476225

File tree

4 files changed

+223
-23
lines changed

4 files changed

+223
-23
lines changed

build.zig

Lines changed: 101 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,14 @@ pub fn build(b: *std.Build) !void {
4040
"-fno-sanitize=undefined",
4141
};
4242

43+
const openssl = b.option(bool, "enable-openssl", "Use OpenSSL instead of MbedTLS") orelse false;
44+
4345
if (target.result.os.tag == .windows) {
46+
if (openssl) {
47+
std.log.err("OpenSSL option unsupported on Windows", .{});
48+
return;
49+
}
50+
4451
lib.linkSystemLibrary("winhttp");
4552
lib.linkSystemLibrary("rpcrt4");
4653
lib.linkSystemLibrary("crypt32");
@@ -61,20 +68,37 @@ pub fn build(b: *std.Build) !void {
6168
lib.addWin32ResourceFile(.{ .file = libgit_src.path("src/libgit2/git2.rc") });
6269
lib.addCSourceFiles(.{ .root = libgit_root, .files = &util_win32_sources, .flags = &flags });
6370
} else {
64-
// mbedTLS https and SHA backend
65-
lib.linkSystemLibrary("mbedtls");
66-
lib.linkSystemLibrary("mbedcrypto");
67-
lib.linkSystemLibrary("mbedx509");
68-
features.addValues(.{
69-
.GIT_HTTPS = 1,
70-
.GIT_MBEDTLS = 1,
71-
.GIT_SHA1_MBEDTLS = 1,
72-
.GIT_SHA256_MBEDTLS = 1,
73-
74-
.GIT_USE_FUTIMENS = 1,
75-
.GIT_IO_POLL = 1,
76-
.GIT_IO_SELECT = 1,
77-
});
71+
if (openssl) {
72+
// OpenSSL backend
73+
const openssl_dep = b.dependency("openssl", .{});
74+
const openssl_lib = openssl_dep.artifact("openssl");
75+
lib.linkLibrary(openssl_lib);
76+
features.addValues(.{
77+
.GIT_HTTPS = 1,
78+
.GIT_OPENSSL = 1,
79+
.GIT_SHA1_OPENSSL = 1,
80+
.GIT_SHA256_OPENSSL = 1,
81+
82+
.GIT_USE_FUTIMENS = 1,
83+
.GIT_IO_POLL = 1,
84+
.GIT_IO_SELECT = 1,
85+
});
86+
} else {
87+
// mbedTLS https and SHA backend
88+
lib.linkSystemLibrary("mbedtls");
89+
lib.linkSystemLibrary("mbedcrypto");
90+
lib.linkSystemLibrary("mbedx509");
91+
features.addValues(.{
92+
.GIT_HTTPS = 1,
93+
.GIT_MBEDTLS = 1,
94+
.GIT_SHA1_MBEDTLS = 1,
95+
.GIT_SHA256_MBEDTLS = 1,
96+
97+
.GIT_USE_FUTIMENS = 1,
98+
.GIT_IO_POLL = 1,
99+
.GIT_IO_SELECT = 1,
100+
});
101+
}
78102

79103
// ntlmclient
80104
{
@@ -85,15 +109,30 @@ pub fn build(b: *std.Build) !void {
85109
.link_libc = true,
86110
});
87111
ntlm.addIncludePath(libgit_src.path("deps/ntlmclient"));
112+
if (openssl) addOpenSSLHeaders(ntlm);
113+
114+
const ntlm_cflags = .{
115+
"-Wno-implicit-fallthrough",
116+
"-DNTLM_STATIC=1",
117+
"-DUNICODE_BUILTIN=1",
118+
if (openssl)
119+
"-DCRYPT_OPENSSL"
120+
else
121+
"-DCRYPT_MBEDTLS",
122+
};
88123
ntlm.addCSourceFiles(.{
89124
.root = libgit_root,
90125
.files = &ntlm_sources,
91-
.flags = &.{
92-
"-Wno-implicit-fallthrough",
93-
"-DNTLM_STATIC=1",
94-
"-DUNICODE_BUILTIN=1",
95-
"-DCRYPT_MBEDTLS",
126+
.flags = &ntlm_cflags,
127+
});
128+
ntlm.addCSourceFiles(.{
129+
.root = libgit_root,
130+
.files = if (openssl) &.{
131+
"deps/ntlmclient/crypt_openssl.c",
132+
} else &.{
133+
"deps/ntlmclient/crypt_mbedtls.c",
96134
},
135+
.flags = &ntlm_cflags,
97136
});
98137

99138
lib.linkLibrary(ntlm);
@@ -106,6 +145,15 @@ pub fn build(b: *std.Build) !void {
106145
.files = &util_unix_sources,
107146
.flags = &flags,
108147
});
148+
lib.addCSourceFiles(.{
149+
.root = libgit_root,
150+
.files = if (openssl) &.{
151+
"src/util/hash/openssl.c",
152+
} else &.{
153+
"src/util/hash/mbedtls.c",
154+
},
155+
.flags = &flags,
156+
});
109157
}
110158

111159
if (b.option(bool, "enable-ssh", "Enable SSH support") orelse false) {
@@ -249,6 +297,7 @@ pub fn build(b: *std.Build) !void {
249297
cli.addIncludePath(libgit_src.path("include"));
250298
cli.addIncludePath(libgit_src.path("src/util"));
251299
cli.addIncludePath(libgit_src.path("src/cli"));
300+
if (openssl) addOpenSSLHeaders(cli);
252301

253302
if (target.result.os.tag == .windows)
254303
cli.addCSourceFiles(.{ .root = libgit_root, .files = &cli_win32_sources })
@@ -293,6 +342,7 @@ pub fn build(b: *std.Build) !void {
293342
});
294343

295344
exe.addIncludePath(libgit_src.path("include"));
345+
if (openssl) addOpenSSLHeaders(exe);
296346
exe.linkLibrary(lib);
297347

298348
// independent install step so you can easily access the binary
@@ -304,6 +354,38 @@ pub fn build(b: *std.Build) !void {
304354
example_run.step.dependOn(&examples_install.step);
305355
examples_step.dependOn(&example_run.step);
306356
}
357+
358+
const tests_step = b.step("run-tests", "Tests");
359+
{
360+
const tests = b.addTest(.{
361+
.root_source_file = b.path("tests/main.zig"),
362+
.target = target,
363+
.optimize = optimize,
364+
.link_libc = true,
365+
});
366+
367+
const fixture = b.addOptions();
368+
fixture.addOptionPath("resources", libgit_src.path("tests/resources"));
369+
370+
tests.root_module.addOptions("fixture", fixture);
371+
372+
tests.addConfigHeader(features);
373+
tests.addIncludePath(libgit_src.path("include"));
374+
tests.addIncludePath(libgit_src.path("src/util"));
375+
if (openssl) addOpenSSLHeaders(tests);
376+
377+
tests.linkLibrary(lib);
378+
379+
const tests_run = b.addRunArtifact(tests);
380+
tests_step.dependOn(&tests_run.step);
381+
}
382+
}
383+
384+
fn addOpenSSLHeaders(compile: *std.Build.Step.Compile) void {
385+
const b = compile.step.owner;
386+
const openssl_dep = b.dependency("openssl", .{});
387+
const openssl_lib = openssl_dep.artifact("openssl");
388+
compile.addIncludePath(openssl_lib.getEmittedIncludeTree());
307389
}
308390

309391
const libgit_sources = [_][]const u8{
@@ -478,8 +560,6 @@ const util_unix_sources = [_][]const u8{
478560
"src/util/unix/map.c",
479561
"src/util/unix/process.c",
480562
"src/util/unix/realpath.c",
481-
482-
"src/util/hash/mbedtls.c",
483563
};
484564

485565
const util_win32_sources = [_][]const u8{
@@ -555,7 +635,6 @@ const xdiff_sources = [_][]const u8{
555635

556636
const ntlm_sources = [_][]const u8{
557637
"deps/ntlmclient/crypt_builtin_md4.c",
558-
"deps/ntlmclient/crypt_mbedtls.c",
559638
"deps/ntlmclient/ntlm.c",
560639
"deps/ntlmclient/unicode_builtin.c",
561640
"deps/ntlmclient/util.c",

build.zig.zon

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,11 @@
66
.libgit2 = .{
77
.url = "https://github.com/libgit2/libgit2/archive/refs/tags/v1.8.1.tar.gz",
88
.hash = "12208db692747f305b79ecfb3ac69e691d0b9584383ec4bcb0eb07b62b73de77b1cf",
9-
}
9+
},
10+
.openssl = .{
11+
.url = "https://github.com/allyourcodebase/openssl/archive/refs/tags/3.3.1-1.tar.gz",
12+
.hash = "12207c40cefa38fe90e4230dfba2e5c76b37e1ee36602512cad8ff0501f892002a65",
13+
},
1014
},
1115
.paths = .{
1216
"build.zig",

tests/main.zig

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
test {
2+
_ = @import("sha.zig");
3+
}

tests/sha.zig

Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
const std = @import("std");
2+
const testing = std.testing;
3+
4+
const c = @cImport({
5+
@cInclude("hash.h");
6+
});
7+
8+
const fixture = @import("fixture");
9+
10+
fn calcHashFile(
11+
allocator: std.mem.Allocator,
12+
filename: []const u8,
13+
comptime algorithm: c.git_hash_algorithm_t,
14+
) ![]u8 {
15+
const file = try std.fs.openFileAbsolute(
16+
filename,
17+
.{},
18+
);
19+
defer file.close();
20+
21+
const size: usize = switch (algorithm) {
22+
c.GIT_HASH_ALGORITHM_SHA1 => c.GIT_HASH_SHA1_SIZE,
23+
c.GIT_HASH_ALGORITHM_SHA256 => c.GIT_HASH_SHA256_SIZE,
24+
else => unreachable,
25+
};
26+
const actual = try allocator.alloc(u8, size);
27+
28+
var r: c_int = undefined;
29+
var ctx: c.git_hash_ctx = undefined;
30+
r = c.git_hash_ctx_init(&ctx, algorithm);
31+
if (r != 0) return error.Unexpected;
32+
defer c.git_hash_ctx_cleanup(&ctx);
33+
34+
const reader = file.reader();
35+
while (true) {
36+
var buf: [2048]u8 = undefined;
37+
const len = try reader.read(&buf);
38+
if (len == 0) break;
39+
r = c.git_hash_update(&ctx, &buf, len);
40+
if (r != 0) return error.Unexpected;
41+
}
42+
43+
r = c.git_hash_final(actual.ptr, &ctx);
44+
if (r != 0) return error.Unexpected;
45+
46+
return actual;
47+
}
48+
49+
test "sha1" {
50+
const expect = [c.GIT_HASH_SHA1_SIZE]u8{
51+
0x4e, 0x72, 0x67, 0x9e, 0x3e, 0xa4, 0xd0, 0x4e,
52+
0x0c, 0x64, 0x2f, 0x02, 0x9e, 0x61, 0xeb, 0x80,
53+
0x56, 0xc7, 0xed, 0x94,
54+
};
55+
const actual = try calcHashFile(
56+
testing.allocator,
57+
fixture.resources ++ "/sha1/hello_c",
58+
c.GIT_HASH_ALGORITHM_SHA1,
59+
);
60+
defer testing.allocator.free(actual);
61+
62+
try testing.expectEqualSlices(u8, &expect, actual);
63+
}
64+
65+
test "sha256 empty" {
66+
const expect = [c.GIT_HASH_SHA256_SIZE]u8{
67+
0xe3, 0xb0, 0xc4, 0x42, 0x98, 0xfc, 0x1c, 0x14,
68+
0x9a, 0xfb, 0xf4, 0xc8, 0x99, 0x6f, 0xb9, 0x24,
69+
0x27, 0xae, 0x41, 0xe4, 0x64, 0x9b, 0x93, 0x4c,
70+
0xa4, 0x95, 0x99, 0x1b, 0x78, 0x52, 0xb8, 0x55,
71+
};
72+
const actual = try calcHashFile(
73+
testing.allocator,
74+
fixture.resources ++ "/sha1/empty",
75+
c.GIT_HASH_ALGORITHM_SHA256,
76+
);
77+
defer testing.allocator.free(actual);
78+
79+
try testing.expectEqualSlices(u8, &expect, actual);
80+
}
81+
82+
test "sha256 hello" {
83+
const expect = [c.GIT_HASH_SHA256_SIZE]u8{
84+
0xaa, 0x32, 0x7f, 0xae, 0x5c, 0x91, 0x58, 0x3a,
85+
0x4f, 0xb6, 0x54, 0xcc, 0xb6, 0xc2, 0xb1, 0x0c,
86+
0x77, 0xd7, 0x49, 0xc9, 0x91, 0x2a, 0x8d, 0x6b,
87+
0x47, 0x26, 0x13, 0xc0, 0xa0, 0x4b, 0x4d, 0xad,
88+
};
89+
const actual = try calcHashFile(
90+
testing.allocator,
91+
fixture.resources ++ "/sha1/hello_c",
92+
c.GIT_HASH_ALGORITHM_SHA256,
93+
);
94+
defer testing.allocator.free(actual);
95+
96+
try testing.expectEqualSlices(u8, &expect, actual);
97+
}
98+
99+
test "sha256 pdf" {
100+
const expect = [c.GIT_HASH_SHA256_SIZE]u8{
101+
0x2b, 0xb7, 0x87, 0xa7, 0x3e, 0x37, 0x35, 0x2f,
102+
0x92, 0x38, 0x3a, 0xbe, 0x7e, 0x29, 0x02, 0x93,
103+
0x6d, 0x10, 0x59, 0xad, 0x9f, 0x1b, 0xa6, 0xda,
104+
0xaa, 0x9c, 0x1e, 0x58, 0xee, 0x69, 0x70, 0xd0,
105+
};
106+
const actual = try calcHashFile(
107+
testing.allocator,
108+
fixture.resources ++ "/sha1/shattered-1.pdf",
109+
c.GIT_HASH_ALGORITHM_SHA256,
110+
);
111+
defer testing.allocator.free(actual);
112+
113+
try testing.expectEqualSlices(u8, &expect, actual);
114+
}

0 commit comments

Comments
 (0)