Logging: The GenericLog Datatype

CryptoSideChannel.Logging.GenericLogType
struct 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 (like UInt8 or Int), or any integer-like type (for example, another instance of GenericLog or a Masked 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 that S must be a bits type. This can only be the case if the array returned by S is a global variable.
source

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.extractValueFunction
extractValue(a::GenericLog)
extractValue(a::Integer)

Extracts the internal value from the GenericLog datatype. Behaves like the identity function if an Integer value is passed.

source

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.HammingWeightLogFunction
HammingWeightLog(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 that stream must be a bits 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$.

source
CryptoSideChannel.Logging.FullLogFunction
FullLog(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 that stream must be a bits 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
source
CryptoSideChannel.Logging.SingleBitLogFunction
SingleBitLog(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 that stream must be a bits type.
  • bit: The position of the bit that should be logged, where 0 is the least significant bit.
source
CryptoSideChannel.Logging.StochasticLogFunction
function 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 a MvNormal 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.
source

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.

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} = ...