Add Crypto::Secret::Stateless

This commit is contained in:
Didactic Drunk 2021-06-14 12:07:31 -07:00
parent 472ed1fc37
commit df977f18e8
3 changed files with 78 additions and 35 deletions

View File

@ -1,10 +1,12 @@
require "./stateless"
# A not very secret secret # A not very secret secret
# #
# Not locked in memory # Not locked in memory
# Not access protected # Not access protected
# No guard pages # No guard pages
struct Crypto::Secret::Not struct Crypto::Secret::Not
include Crypto::Secret include Crypto::Secret::Stateless
def self.new(size) def self.new(size)
new Bytes.new(size) new Bytes.new(size)

View File

@ -1,13 +1,12 @@
require "crypto/subtle" require "crypto/subtle"
lib LibC lib LibC
fun explicit_bzero(Void*, LibC::SizeT) : Int fun explicit_bzero(Void*, LibC::SizeT) : Void
end end
struct Slice(T) struct Slice(T)
def wipe def wipe
r = LibC.explicit_bzero slice.to_unsafe, slice.bytesize LibC.explicit_bzero to_unsafe, bytesize
raise RunTimeError.from_errno("explicit_bzero") if r != 0
end end
end end
@ -21,41 +20,21 @@ module Crypto::Secret
class Error < Exception class Error < Exception
class KeyWiped < Error class KeyWiped < Error
end end
end
def readwrite class InvalidStateTransition < Error
end end
# Yields a Slice that is readable and writable # Check RLIMIT_MEMLOCK if you receive this
# class OutOfMemory < Error
# `slice` is only available within the block
#
# Not thread safe
def readwrite
to_slice do |slice|
yield slice
end end
end end
def readonly enum State
end Cloning
Wiped
# Yields a Slice that is readable possibly writable depending on the prior protection level and underlying implementation Noaccess
# Don't write to it Readonly
# Readwrite
# Not thread safe
def readonly
to_slice do |slice|
yield slice
end
end
def noaccess
end
# Not thread safe
def noaccess
yield
end end
# For debugging. # For debugging.
@ -66,7 +45,7 @@ module Crypto::Secret
def wipe def wipe
readwrite do |slice| readwrite do |slice|
slice.wipe wipe_impl slice
end end
end end
@ -105,6 +84,10 @@ module Crypto::Secret
io << self.class.to_s << "(***SECRET***)" io << self.class.to_s << "(***SECRET***)"
end end
abstract def readwrite
abstract def readonly
abstract def noaccess
abstract def to_slice(& : Bytes -> Nil) abstract def to_slice(& : Bytes -> Nil)
abstract def bytesize : Int32 abstract def bytesize : Int32
@ -119,4 +102,8 @@ module Crypto::Secret
{{object.id}}.bytesize {{object.id}}.bytesize
end end
end end
def wipe_impl(slice : Bytes) : Nil
slice.wipe
end
end end

View File

@ -0,0 +1,54 @@
require "./secret"
# Provides a 0 overhead implementation of [#readwrite, #readonly, #noaccess, #reset] with no protection
#
# Data is still erased when out of scope
module Crypto::Secret::Stateless
include Crypto::Secret
# Not thread safe
def readwrite
end
# Yields a Slice that is readable and writable
#
# `slice` is only available within the block
#
# Not thread safe
def readwrite
to_slice do |slice|
yield slice
end
end
# Not thread safe
def readonly
end
# Yields a Slice that is readable possibly writable depending on the prior protection level and underlying implementation
# Don't write to it
#
# Not thread safe
def readonly
to_slice do |slice|
yield slice
end
end
# Not thread safe
def noaccess
end
# Not thread safe
def noaccess
yield
end
# Not thread safe
def reset
end
def finalize
wipe
end
end