From 3bc172c70bc48c88110476b3a8f076f36671ea51 Mon Sep 17 00:00:00 2001 From: Laytan Laats Date: Sat, 2 Dec 2023 21:37:55 +0100 Subject: [PATCH 1/6] add crypto.rand_bytes for Darwin and FreeBSD --- core/crypto/rand_darwin_and_bsd.odin | 12 ++++++++++++ core/crypto/rand_generic.odin | 7 +++---- core/crypto/rand_openbsd.odin | 12 ------------ 3 files changed, 15 insertions(+), 16 deletions(-) create mode 100644 core/crypto/rand_darwin_and_bsd.odin delete mode 100644 core/crypto/rand_openbsd.odin diff --git a/core/crypto/rand_darwin_and_bsd.odin b/core/crypto/rand_darwin_and_bsd.odin new file mode 100644 index 000000000..aea7e2953 --- /dev/null +++ b/core/crypto/rand_darwin_and_bsd.odin @@ -0,0 +1,12 @@ +//+build freebsd, openbsd, darwin +package crypto + +foreign import libc "system:c" + +foreign libc { + arc4random_buf :: proc(buf: [^]byte, nbytes: uint) --- +} + +_rand_bytes :: proc(dst: []byte) { + arc4random_buf(raw_data(dst), len(dst)) +} diff --git a/core/crypto/rand_generic.odin b/core/crypto/rand_generic.odin index fde91f85a..b8bf900cd 100644 --- a/core/crypto/rand_generic.odin +++ b/core/crypto/rand_generic.odin @@ -1,7 +1,6 @@ +//+build !linux !windows !openbsd !freebsd !darwin !js package crypto -when ODIN_OS != .Linux && ODIN_OS != .OpenBSD && ODIN_OS != .Windows && ODIN_OS != .JS { - _rand_bytes :: proc(dst: []byte) { - unimplemented("crypto: rand_bytes not supported on this OS") - } +_rand_bytes :: proc(dst: []byte) { + unimplemented("crypto: rand_bytes not supported on this OS") } diff --git a/core/crypto/rand_openbsd.odin b/core/crypto/rand_openbsd.odin deleted file mode 100644 index bae97e8f0..000000000 --- a/core/crypto/rand_openbsd.odin +++ /dev/null @@ -1,12 +0,0 @@ -package crypto - -import "core:c" - -foreign import libc "system:c" -foreign libc { - arc4random_buf :: proc "c" (buf: rawptr, nbytes: c.size_t) --- -} - -_rand_bytes :: proc (dst: []byte) { - arc4random_buf(raw_data(dst), len(dst)) -} From 91cf0826c18531213bc91a432ac67e21b26f74ab Mon Sep 17 00:00:00 2001 From: Laytan Laats Date: Sun, 3 Dec 2023 20:43:46 +0100 Subject: [PATCH 2/6] use `Security.framework` with `SecRandomCopyBytes` for rand_bytes on darwin --- core/crypto/rand_darwin.odin | 11 +++++++++++ core/crypto/rand_darwin_and_bsd.odin | 2 +- core/sys/darwin/security.odin | 24 ++++++++++++++++++++++++ 3 files changed, 36 insertions(+), 1 deletion(-) create mode 100644 core/crypto/rand_darwin.odin create mode 100644 core/sys/darwin/security.odin diff --git a/core/crypto/rand_darwin.odin b/core/crypto/rand_darwin.odin new file mode 100644 index 000000000..f7978c3fa --- /dev/null +++ b/core/crypto/rand_darwin.odin @@ -0,0 +1,11 @@ +package crypto + +import "core:fmt" +import "core:sys/darwin" + +_rand_bytes :: proc(dst: []byte) { + res := darwin.SecRandomCopyBytes(count=len(dst), bytes=raw_data(dst)) + if res != .Success { + panic(fmt.tprintf("crypto/rand_bytes: SecRandomCopyBytes returned non-zero result: %v", res)) + } +} diff --git a/core/crypto/rand_darwin_and_bsd.odin b/core/crypto/rand_darwin_and_bsd.odin index aea7e2953..8e2be1d95 100644 --- a/core/crypto/rand_darwin_and_bsd.odin +++ b/core/crypto/rand_darwin_and_bsd.odin @@ -1,4 +1,4 @@ -//+build freebsd, openbsd, darwin +//+build freebsd, openbsd package crypto foreign import libc "system:c" diff --git a/core/sys/darwin/security.odin b/core/sys/darwin/security.odin new file mode 100644 index 000000000..4f9789326 --- /dev/null +++ b/core/sys/darwin/security.odin @@ -0,0 +1,24 @@ +//+build darwin +package darwin + +foreign import security "system:Security.framework" + +// A reference to a random number generator. +SecRandomRef :: distinct rawptr + +OSStatus :: distinct i32 + +errSec :: enum OSStatus { + Success = 0, // No error. + Unimplemented = -4, // Function or operation not implemented. + + // Many more... +} + +foreign security { + // Synonym for nil, uses a cryptographically secure random number generator. + kSecRandomDefault: SecRandomRef + + // Generates an array of cryptographically secure random bytes. + SecRandomCopyBytes :: proc(rnd: SecRandomRef = kSecRandomDefault, count: uint, bytes: [^]byte) -> errSec --- +} From 32a4a5e6017df4eec3d6380beff5c7dca5077cb4 Mon Sep 17 00:00:00 2001 From: Laytan Laats Date: Sun, 3 Dec 2023 21:01:06 +0100 Subject: [PATCH 3/6] remove darwin from bsd filename --- core/crypto/{rand_darwin_and_bsd.odin => rand_bsd.odin} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename core/crypto/{rand_darwin_and_bsd.odin => rand_bsd.odin} (100%) diff --git a/core/crypto/rand_darwin_and_bsd.odin b/core/crypto/rand_bsd.odin similarity index 100% rename from core/crypto/rand_darwin_and_bsd.odin rename to core/crypto/rand_bsd.odin From 0d413b81364d57c569bcc35c2f9ac6e0c215cab8 Mon Sep 17 00:00:00 2001 From: Laytan Laats Date: Sun, 3 Dec 2023 22:32:24 +0100 Subject: [PATCH 4/6] implement part of core foundation framework bindings for err message --- core/crypto/rand_darwin.odin | 3 +- core/sys/darwin/core_foundation.odin | 98 ++++++++++++++++++++++++++++ core/sys/darwin/darwin.odin | 4 ++ core/sys/darwin/security.odin | 2 + 4 files changed, 106 insertions(+), 1 deletion(-) create mode 100644 core/sys/darwin/core_foundation.odin create mode 100644 core/sys/darwin/darwin.odin diff --git a/core/crypto/rand_darwin.odin b/core/crypto/rand_darwin.odin index f7978c3fa..ec44c1491 100644 --- a/core/crypto/rand_darwin.odin +++ b/core/crypto/rand_darwin.odin @@ -6,6 +6,7 @@ import "core:sys/darwin" _rand_bytes :: proc(dst: []byte) { res := darwin.SecRandomCopyBytes(count=len(dst), bytes=raw_data(dst)) if res != .Success { - panic(fmt.tprintf("crypto/rand_bytes: SecRandomCopyBytes returned non-zero result: %v", res)) + msg := darwin.CFStringCopyToOdinString(darwin.SecCopyErrorMessageString(res)) + panic(fmt.tprintf("crypto/rand_bytes: SecRandomCopyBytes returned non-zero result: %v %s", res, msg)) } } diff --git a/core/sys/darwin/core_foundation.odin b/core/sys/darwin/core_foundation.odin new file mode 100644 index 000000000..eafe1a1f3 --- /dev/null +++ b/core/sys/darwin/core_foundation.odin @@ -0,0 +1,98 @@ +//+build darwin +package darwin + +import "core:runtime" + +foreign import core_foundation "system:CoreFoundation.framework" + +CFTypeRef :: distinct rawptr + +CFStringRef :: distinct CFTypeRef + +CFIndex :: int + +CFRange :: struct { + location: CFIndex, + length: CFIndex, +} + +CFStringEncoding :: enum u32 { + ASCII = 1, + NEXTSTEP = 2, + JapaneseEUC = 3, + UTF8 = 4, + ISOLatin1 = 5, + Symbol = 6, + NonLossyASCII = 7, + ShiftJIS = 8, + ISOLatin2 = 9, + Unicode = 10, + WindowsCP1251 = 11, + WindowsCP1252 = 12, + WindowsCP1253 = 13, + WindowsCP1254 = 14, + WindowsCP1250 = 15, + ISO2022JP = 21, + MacOSRoman = 30, + + UTF16 = Unicode, + + UTF16BigEndian = 0x90000100, + UTF16LittleEndian = 0x94000100, + + UTF32 = 0x8c000100, + UTF32BigEndian = 0x98000100, + UTF32LittleEndian = 0x9c000100, +} + +foreign core_foundation { + // Copies the character contents of a string to a local C string buffer after converting the characters to a given encoding. + CFStringGetCString :: proc(theString: CFStringRef, buffer: [^]byte, bufferSize: CFIndex, encoding: CFStringEncoding) -> Bool --- + + // Returns the number (in terms of UTF-16 code pairs) of Unicode characters in a string. + CFStringGetLength :: proc(theString: CFStringRef) -> CFIndex --- + + // Returns the maximum number of bytes a string of a specified length (in Unicode characters) will take up if encoded in a specified encoding. + CFStringGetMaximumSizeForEncoding :: proc(length: CFIndex, encoding: CFStringEncoding) -> CFIndex --- + + // Fetches a range of the characters from a string into a byte buffer after converting the characters to a specified encoding. + CFStringGetBytes :: proc( + thestring: CFStringRef, + range: CFRange, + encoding: CFStringEncoding, + lossByte: u8, + isExternalRepresentation: Bool, + buffer: [^]byte, + maxBufLen: CFIndex, + usedBufLen: ^CFIndex, + ) -> CFIndex --- + + // Releases a Core Foundation object. + @(link_name="CFRelease") + _CFRelease :: proc(cf: CFTypeRef) --- +} + +// Releases a Core Foundation object. +CFRelease :: proc { + CFReleaseString, +} + +// Releases a Core Foundation string. +CFReleaseString :: #force_inline proc(theString: CFStringRef) { + _CFRelease(CFTypeRef(theString)) +} + +CFStringCopyToOdinString :: proc(theString: CFStringRef, allocator := context.allocator) -> (str: string, ok: bool) #optional_ok { + length := CFStringGetLength(theString) + max := CFStringGetMaximumSizeForEncoding(length, .UTF8) + + buf, err := make([]byte, max, allocator) + if err != nil { return } + + raw_str := runtime.Raw_String{ + data = raw_data(buf), + } + CFStringGetBytes(theString, {0, length}, .UTF8, 0, false, raw_data(buf), max, &raw_str.len) + + return transmute(string)raw_str, true +} diff --git a/core/sys/darwin/darwin.odin b/core/sys/darwin/darwin.odin new file mode 100644 index 000000000..0b3efb1f5 --- /dev/null +++ b/core/sys/darwin/darwin.odin @@ -0,0 +1,4 @@ +//+build darwin +package darwin + +Bool :: b8 diff --git a/core/sys/darwin/security.odin b/core/sys/darwin/security.odin index 4f9789326..0c58260e7 100644 --- a/core/sys/darwin/security.odin +++ b/core/sys/darwin/security.odin @@ -21,4 +21,6 @@ foreign security { // Generates an array of cryptographically secure random bytes. SecRandomCopyBytes :: proc(rnd: SecRandomRef = kSecRandomDefault, count: uint, bytes: [^]byte) -> errSec --- + + SecCopyErrorMessageString :: proc(status: errSec, reserved: rawptr = nil) -> CFStringRef --- } From 88e6980b132cbe14426fc1e91e19385bc4748a02 Mon Sep 17 00:00:00 2001 From: Laytan Laats Date: Mon, 18 Dec 2023 13:42:34 +0100 Subject: [PATCH 5/6] fix build tags --- core/crypto/rand_generic.odin | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/core/crypto/rand_generic.odin b/core/crypto/rand_generic.odin index b8bf900cd..bf7abbbe2 100644 --- a/core/crypto/rand_generic.odin +++ b/core/crypto/rand_generic.odin @@ -1,4 +1,9 @@ -//+build !linux !windows !openbsd !freebsd !darwin !js +//+build !linux +//+build !windows +//+build !openbsd +//+build !freebsd +//+build !darwin +//+build !js package crypto _rand_bytes :: proc(dst: []byte) { From de41c2256d98e8b2e2742e6fd7266bdc2a5e970d Mon Sep 17 00:00:00 2001 From: Ed Yu Date: Mon, 4 Mar 2024 10:14:51 -0800 Subject: [PATCH 6/6] For invmod, b has to be > 1, fix a logic typo --- core/math/big/internal.odin | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/core/math/big/internal.odin b/core/math/big/internal.odin index 829cbf0e2..35c95f465 100644 --- a/core/math/big/internal.odin +++ b/core/math/big/internal.odin @@ -2046,9 +2046,9 @@ internal_int_inverse_modulo :: proc(dest, a, b: ^Int, allocator := context.alloc if internal_is_positive(a) && internal_eq(b, 1) { return internal_zero(dest) } /* - `b` cannot be negative and has to be > 1 + `b` cannot be negative and b has to be > 1 */ - if internal_is_negative(b) || internal_gt(b, 1) { return .Invalid_Argument } + if internal_is_negative(b) || !internal_gt(b, 1) { return .Invalid_Argument } /* If the modulus is odd we can use a faster routine instead. @@ -2954,4 +2954,4 @@ internal_zero_unused :: proc { internal_int_zero_unused, } /* ========================== End of low-level routines ========================== -*/ \ No newline at end of file +*/