-
-
Notifications
You must be signed in to change notification settings - Fork 235
Protect locally stored Acount Code on disk with system api #3508
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
Mabeeck
wants to merge
31
commits into
PixelGuys:master
Choose a base branch
from
Mabeeck:windows-CryptProtectData
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
31 commits
Select commit
Hold shift + click to select a range
355794b
Add a Cubyz protection api and integrate it
Mabeeck 7aa8be7
Lots of things
Mabeeck 5e6f73c
Format
Mabeeck 5201c5c
All hail The Linter!
Mabeeck c47ab58
Microslop
Mabeeck 9185e3e
Add tests and improve unprotect error detection
Mabeeck 8fc9cc6
Improve Tests and errordetection
Mabeeck a1b7390
Improve based on received criticism
Mabeeck acbe6a6
Format
Mabeeck 9a2d5e5
Move protect struct into authentication.zig
Mabeeck c0e64ea
Use Impl structs
Mabeeck 549329d
Couple simple changes
Mabeeck 2542404
Get rid of constCast in tests
Mabeeck 2cc59af
Change Test
Mabeeck 872f803
No more quiet fallback on abnormal failure
Mabeeck 4125aad
Use allocator.dupe instead of @memcpy
Mabeeck 3efe858
Get rid of complex defers in decryptFromPassword
Mabeeck bb85a85
Initialize blob directly
Mabeeck aec7238
Add checkbox
Mabeeck 7b6f395
Move protections struct to separate file
Mabeeck b129ee7
Make canProtect a const bool
Mabeeck f4e4036
Change names to fit naming convention
Mabeeck a9cb849
Get rid of unnecessary pub
Mabeeck ba419a5
Update authentication.zig
Mabeeck 6d245a9
Update authentication.zig
Mabeeck b0f5648
Update encrypt_with_password.zig
Mabeeck 354ea9e
Remove error.Unsupported
Mabeeck 3717831
Mini naming change
Mabeeck 728c5a7
Remove "Please report to maintainers" notice
Mabeeck fd469e5
Increase window hight
Mabeeck b01321c
Move defer
Mabeeck File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,113 @@ | ||
| const std = @import("std"); | ||
|
|
||
| const main = @import("main"); | ||
| const NeverFailingAllocator = main.heap.NeverFailingAllocator; | ||
| const builtin = @import("builtin"); | ||
|
|
||
| const c = @import("c"); | ||
|
|
||
| const impl = switch (builtin.os.tag) { | ||
| .windows => windows_impl, | ||
| else => no_impl, | ||
| }; | ||
|
|
||
| pub const canProtect: bool = impl.canProtect; | ||
|
|
||
| pub fn protect(allocator: NeverFailingAllocator, data: []const u8) error{SystemError}![]u8 { | ||
| return impl.protect(allocator, data); | ||
| } | ||
|
|
||
| pub fn unprotect(allocator: NeverFailingAllocator, data: []const u8) error{ SystemError, Invalid }![]u8 { | ||
|
Mabeeck marked this conversation as resolved.
|
||
| return impl.unprotect(allocator, data); | ||
| } | ||
|
|
||
| const no_impl = struct { | ||
| const canProtect = false; | ||
|
|
||
| fn protect(_: NeverFailingAllocator, _: []const u8) error{SystemError}![]u8 { | ||
| @panic("Protection API not implemented on this device. Always check protection.canProtect before trying to use this API."); | ||
| } | ||
|
|
||
| fn unprotect(_: NeverFailingAllocator, _: []const u8) error{ SystemError, Invalid }![]u8 { | ||
| return error.Invalid; | ||
| } | ||
| }; | ||
|
|
||
| const windows_impl = struct { | ||
| const canProtect = true; | ||
|
|
||
| fn protect(allocator: NeverFailingAllocator, data: []const u8) error{SystemError}![]u8 { | ||
| var plainblob: c.DATA_BLOB = .{ | ||
| .cbData = @intCast(data.len), | ||
| .pbData = @constCast(data.ptr), | ||
| }; | ||
| var cipherblob: c.DATA_BLOB = undefined; | ||
| if (c.CryptProtectData(&plainblob, null, null, null, null, 0, &cipherblob) == 0) { | ||
| std.log.err("CryptProtectData syscall failed. Errorcode: {}. This should never happen.", .{c.GetLastError()}); | ||
| return error.SystemError; | ||
| } | ||
| defer if (c.LocalFree(cipherblob.pbData) != null) std.log.err("LocalFree syscall failed to free previously allocated memory. Errorcode: {}. This should never happen.", .{c.GetLastError()}); | ||
| return allocator.dupe(u8, cipherblob.pbData[0..cipherblob.cbData]); | ||
| } | ||
|
|
||
| fn unprotect(allocator: NeverFailingAllocator, data: []const u8) error{ SystemError, Invalid }![]u8 { | ||
| var plainblob: c.DATA_BLOB = undefined; | ||
| var cipherblob: c.DATA_BLOB = .{ | ||
| .cbData = @intCast(data.len), | ||
| .pbData = @constCast(data.ptr), | ||
| }; | ||
| if (c.CryptUnprotectData(&cipherblob, null, null, null, null, 0, &plainblob) == 0) { | ||
| const err = c.GetLastError(); | ||
| switch (err) { | ||
| c.ERROR_INVALID_DATA, c.ERROR_INVALID_PARAMETER => return error.Invalid, | ||
| else => { | ||
| std.log.err("CryptUnprotectData syscall failed. Errorcode: {}", .{err}); | ||
| return error.SystemError; | ||
| }, | ||
| } | ||
| } | ||
| var pbDataSlice: []u8 = undefined; | ||
| pbDataSlice.len = plainblob.cbData; | ||
| pbDataSlice.ptr = plainblob.pbData; | ||
| defer { | ||
| std.crypto.secureZero(u8, pbDataSlice); | ||
| if (c.LocalFree(plainblob.pbData) != null) std.log.err("LocalFree syscall failed to free previously allocated memory. Errorcode: {}. This should never happen.", .{c.GetLastError()}); | ||
| } | ||
| return allocator.dupe(u8, plainblob.pbData[0..plainblob.cbData]); | ||
| } | ||
| }; | ||
|
|
||
| test "slice==unprotect(protect(slice))" { | ||
| if (canProtect) { | ||
| const slices: [5][]const u8 = .{"TestdwadadÖOUWHdöouHIOSUdhöoUHNWLJDKNOÖPAHUIwdoöJKNSdlkjöwuHOÖIhso8zpo9IKj", "Test", "Testd", "", "WIJDp8iU)(du098UÜ=JHd0ü8hz=Ü(HJ0isidjowi8h=(Z\"ß08IJUISdhd0w98hdoi8uoIWUJDoikjsoIKHJOwiuhdOISHNdo9i8H(UIHNASUJhdnbiuJBWGiudjhbIAKUJHnbsiudjkhiWUAHNIUDshjliuAHELIUHFILUHNIUJBDIUHwiuHushoujhdiiuwhIUHsouhdUHwiuhdUAHLsuidhlHU)"}; | ||
| for (slices) |slice| { | ||
| const protected = try protect(main.stackAllocator, slice); | ||
| defer main.stackAllocator.free(protected); | ||
| const unprotected = try unprotect(main.stackAllocator, protected); | ||
| defer main.stackAllocator.free(unprotected); | ||
| try std.testing.expectEqualSlices(u8, slice, unprotected); | ||
| } | ||
| } else { | ||
| return error.SkipZigTest; | ||
| } | ||
| } | ||
|
|
||
| test "Unprotect fails on unsupported platforms" { | ||
| const slice = "Test"; | ||
| if (!canProtect) { | ||
| try std.testing.expectError(error.Invalid, unprotect(main.stackAllocator, slice)); | ||
| } else { | ||
| return error.SkipZigTest; | ||
| } | ||
| } | ||
|
|
||
| test "Unprotect fails when supplied with garbage" { | ||
| if (canProtect) { | ||
| const slices: [5][]const u8 = .{"TestdwadadÖOUWHdöouHIOSUdhöoUHNWLJDKNOÖPAHUIwdoöJKNSdlkjöwuHOÖIhso8zpo9IKj", "Test", "Testd", "", "WIJDp8iU)(du098UÜ=JHd0ü8hz=Ü(HJ0isidjowi8h=(Z\"ß08IJUISdhd0w98hdoi8uoIWUJDoikjsoIKHJOwiuhdOISHNdo9i8H(UIHNASUJhdnbiuJBWGiudjhbIAKUJHnbsiudjkhiWUAHNIUDshjliuAHELIUHFILUHNIUJBDIUHwiuHushoujhdiiuwhIUHsouhdUHwiuhdUAHLsuidhlHU)"}; | ||
| for (slices) |slice| { | ||
| try std.testing.expectError(error.Invalid, unprotect(main.stackAllocator, slice)); | ||
| } | ||
| } else { | ||
| return error.SkipZigTest; | ||
| } | ||
| } | ||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this is too generic. Protection from theft can mean a lot of things.
I'd suggest to find a non-dev on the discord server to work together on this. Or maybe @ikabod-kee could help here.
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does this work? Or maybe "Prevent loading on different devices"? I have also asked on discord. Will change once I have further improvement ideas.