Logging: The GenericLog
Datatype
CryptoSideChannel.Logging.GenericLog
— Typestruct GenericLog{U,S,T}
val::T
end
The GenericLog
datatype behaves like an integer, but additionally logs a trace of all values contained. Technically, this type appends a reduced value to an array every time a operation is performed on it.
Type Arguments
T
is the underlying type that our type should mimic.T
may be a primitive integer type (likeUInt8
orInt
), or any integer-like type (for example, another instance ofGenericLog
or aMasked
integer).U
should be a container holding a reduction function. The purpose of this reduction function is to preprocess values of the underlying type for logging. Most commonly, only a value derived from the underlying value should be logged, like the Hamming weight or the least significant bit. Such a derived value can be computed with the reduction function. Further details can be found at Reduction functions.S
is a closure returning the array where values should be logged to. Note thatS
must be a bits type. This can only be the case if the array returned byS
is a global variable.
Most operations on integers can also be performed on instances of GenericLog
. By default, this includes the most common operations like calculations, array accesses, and more. However, it is easy to extend this functionality to other methods if desired. See the chapter on Defining new methods for GenericLog
types for more details.
It may be useful to extract the content of a GenericLog
type, for example, at the end of a cryptographic calculation.
CryptoSideChannel.Logging.extractValue
— FunctionextractValue(a::GenericLog)
extractValue(a::Integer)
Extracts the internal value from the GenericLog
datatype. Behaves like the identity function if an Integer
value is passed.
Reduction functions
A reduction function for a GenericLog
over base type T
should take any value of type T
, and produce any result that eventually is logged. Reasonable choices for reduction functions could be a model of side-channel emissions. For example, the Hamming weight could be a possible model which is already pre-defined. The following types with commonly used reduction functions are already pre-defined:
There are already several logging datatypes pre-defined. Creating instances of those types is as easy as specifying a closure returning the logging destination, and the underlying value.
Pre-defined logging types
The following logging types are already pre-defined:
CryptoSideChannel.Logging.HammingWeightLog
— FunctionHammingWeightLog(val, stream)
Creates a logging datatype that logs the Hamming weight of the underlying value.
Arguments
val
: the value that should be wrapped around.stream
: A closure returning the array that should be logged to. Note thatstream
must be abits
type.
Example
julia> trace = [];
julia> closure = () -> trace;
julia> a = Logging.HammingWeightLog(42, closure)
Log{Int64, 42}
julia> b = a + 1
Log{Int64, 43}
julia> c = a - 42
Log{Int64, 0}
julia> trace
2-element Vector{Any}:
4
0
Notice that $(43)_{10} = (101011)_2$. Hence, the Hamming weight of $43$ is $4$.
CryptoSideChannel.Logging.FullLog
— FunctionFullLog(val, stream)
Creates a logging datatype that logs the full underlying value.
Arguments
val
: the value that should be wrapped around.stream
: A closure returning the array that should be logged to. Note thatstream
must be abits
type.
Example
julia> trace = [];
julia> closure = () -> trace;
julia> a = Logging.FullLog(42, closure)
Log{Int64, 42}
julia> b = a + 1
Log{Int64, 43}
julia> c = a - 42
Log{Int64, 0}
julia> trace
2-element Vector{Any}:
43
0
CryptoSideChannel.Logging.SingleBitLog
— FunctionSingleBitLog(val, stream, bit)
Creates a logging datatype that logs the value of a single bit of the underlying value. The bit that is logged is selected with the bit
argument.
Arguments
val
: the value that should be wrapped around.stream
: A closure returning the array that should be logged to. Note thatstream
must be abits
type.bit
: The position of the bit that should be logged, where0
is the least significant bit.
CryptoSideChannel.Logging.StochasticLog
— Functionfunction StochasticLog(val, stream, template_for_value, noise_for_value)
Constructs a logging datatype that logs vectors.
Arguments
val
: The value the logging datatype should hold.stream
: A closure to the array that should be logged to.mean_for_value
must be a function returning the vector $\mean{x}_m$ for a value $m$.noise_for_value
is a function returning aMvNormal
distribution with zero mean. This distribution represents the noise. For each value, a random vector is sampled from this noise and added to the respective mean.
Using custom reduction functions
Besides the pre-defined types, this framework allows free choices of reduction functions, hence providing great flexibility. To define custom reduction functions, the SingleFunctionLog
interface should be used. With this type, it is possible to specify a custom function that takes the intermemdiate value and output the reduced result.
CryptoSideChannel.Logging.SingleFunctionLog
— Typeabstract type SingleFunctionLog{F} <: LogFunction end
A wrapper for simple reduction functions that take a single argument and outputs a reduced value.
For example, it is possible to define the HammingWeightLog
based on this method as follows:
HammingWeightLog(val, stream) =
GenericLog{SingleFunctionLog{Base.count_ones},stream,typeof(val)}(val)
Defining new methods for GenericLog
types
All basic operations provided by the Julia standard library can also be executed on GenericLog
types. However, there may be the need for custom operations, e.g. defined by a third-party library. Implementing a new binary operation on GenericLog
consists of defining the following three methods:
function Base.$op(a::GenericLog{U,S}, b::GenericLog) where {U,S}
res = Base.$op(extractValue(a), extractValue(b))
result = GenericLog{U,S,typeof(res)}(res)
push!(typeof(b).parameters[2](), logValue(result))
result
end
Base.$op(a::Integer, b::GenericLog{U,S}) where {U,S} = ...
Base.$op(a::GenericLog{U,S}, b::Integer) where {U,S} = ...