From 7b5380f9a81ad259a810d6bc965b206f37a8efeb Mon Sep 17 00:00:00 2001 From: "Joe Richey joerichey@google.com" Date: Wed, 10 Jan 2018 20:24:15 -0800 Subject: [PATCH 1/2] Limit the amount of RAM that will be used Fixes #73. Adds maxMemoryBytes as 128MiB and cleans up the helper functions/variables to make it more clear which values are a number of bytes, and which values are a number of KiB. --- actions/config.go | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/actions/config.go b/actions/config.go index 81f6e4f3..7884bed9 100644 --- a/actions/config.go +++ b/actions/config.go @@ -48,6 +48,10 @@ const ( configPermissions = 0644 // Config file should be created for writing and not already exist createFlags = os.O_CREATE | os.O_WRONLY | os.O_EXCL + // 128 MiB is a large enough amount of memory to make the password hash + // very difficult to brute force on specialized hardware, but small + // enough to work on most GNU/Linux systems. + maxMemoryBytes = 128 * 1024 * 1024 ) var ( @@ -163,15 +167,15 @@ func getHashingCosts(target time.Duration) (*metadata.HashingCosts, error) { } // Now we start doubling the costs until we reach the target. - maxMemory := ramLimit() + memoryKiBLimit := memoryBytesLimit() / 1024 for { // Store a copy of the previous costs costsPrev := *costs tPrev := t // Double the memory up to the max, then the double the time. - if costs.Memory < maxMemory { - costs.Memory = util.MinInt64(2*costs.Memory, maxMemory) + if costs.Memory < memoryKiBLimit { + costs.Memory = util.MinInt64(2*costs.Memory, memoryKiBLimit) } else { costs.Time *= 2 } @@ -196,15 +200,17 @@ func getHashingCosts(target time.Duration) (*metadata.HashingCosts, error) { } } -// ramLimit returns the maximum amount of RAM (in kB) we will use for passphrase -// hashing. Right now it is simply half of the total RAM on the system. -func ramLimit() int64 { +// memoryBytesLimit returns the maximum amount of memory we will use for +// passphrase hashing. This will never be more than a reasonable maximum (for +// compatibility) or half the available system RAM. +func memoryBytesLimit() int64 { + // The sysinfo syscall only fails if given a bad address var info unix.Sysinfo_t err := unix.Sysinfo(&info) - // The sysinfo syscall only fails if given a bad address util.NeverError(err) - // Use half the RAM and convert to kiB. - return int64(info.Totalram / 1024 / 2) + + totalRAMBytes := int64(info.Totalram) + return util.MinInt64(totalRAMBytes / 2, maxMemoryBytes) } // betweenCosts returns a cost between a and b. Specifically, it returns the From a507228a795328d88c9c1ad4fd31fcfef639fa0f Mon Sep 17 00:00:00 2001 From: "Joe Richey joerichey@google.com" Date: Wed, 10 Jan 2018 20:37:25 -0800 Subject: [PATCH 2/2] Format files correctly --- actions/config.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/actions/config.go b/actions/config.go index 7884bed9..6bc52399 100644 --- a/actions/config.go +++ b/actions/config.go @@ -210,7 +210,7 @@ func memoryBytesLimit() int64 { util.NeverError(err) totalRAMBytes := int64(info.Totalram) - return util.MinInt64(totalRAMBytes / 2, maxMemoryBytes) + return util.MinInt64(totalRAMBytes/2, maxMemoryBytes) } // betweenCosts returns a cost between a and b. Specifically, it returns the