Logging: The GenericLog Datatype
CryptoSideChannel.Logging.GenericLog — Typestruct GenericLog{U,S,T}
val::T
endThe 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
Tis the underlying type that our type should mimic.Tmay be a primitive integer type (likeUInt8orInt), or any integer-like type (for example, another instance ofGenericLogor aMaskedinteger).Ushould 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.Sis a closure returning the array where values should be logged to. Note thatSmust be a bits type. This can only be the case if the array returned bySis 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 thatstreammust be abitstype.
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
0Notice 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 thatstreammust be abitstype.
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
0CryptoSideChannel.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 thatstreammust be abitstype.bit: The position of the bit that should be logged, where0is 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_valuemust be a function returning the vector $\mean{x}_m$ for a value $m$.noise_for_valueis a function returning aMvNormaldistribution 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 endA 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} = ...