Constant-time primitives

This folder holds:

  • the constant-time primitives, implemented as distinct types to have the compiler enforce proper usage
  • extended precision multiplication and division primitives
  • assembly primitives
  • intrinsics

Security

⚠: Hardware assumptions

Constantine assumes that multiplication is implemented constant-time in hardware.

If this is not the case, you SHOULD strongly reconsider your hardware choice or reimplement multiplication with constant-time guarantees (at the cost of speed and code-size)

⚠: Currently division and modulo operations are unsafe and uses hardware division. No known CPU implements division in constant-time. A constant-time alternative will be provided.

While extremely slow, division and modulo are only used on random or user inputs to constrain them to the prime field of the elliptic curves. Constantine internals are built to avoid costly constant-time divisions.

Performance and code size

It is recommended to prefer Clang, MSVC or ICC over GCC if possible. GCC code is significantly slower and bigger for multiprecision arithmetic even when using dedicated intrinsics.

See https://gcc.godbolt.org/z/2h768y

#include <stdint.h>
#include <x86intrin.h>

void add256(uint64_t a[4], uint64_t b[4]){
  uint8_t carry = 0;
  for (int i = 0; i < 4; ++i)
    carry = _addcarry_u64(carry, a[i], b[i], &a[i]);
}

GCC

add256:
        movq    (%rsi), %rax
        addq    (%rdi), %rax
        setc    %dl
        movq    %rax, (%rdi)
        movq    8(%rdi), %rax
        addb    $-1, %dl
        adcq    8(%rsi), %rax
        setc    %dl
        movq    %rax, 8(%rdi)
        movq    16(%rdi), %rax
        addb    $-1, %dl
        adcq    16(%rsi), %rax
        setc    %dl
        movq    %rax, 16(%rdi)
        movq    24(%rsi), %rax
        addb    $-1, %dl
        adcq    %rax, 24(%rdi)
        ret

Clang

add256:
        movq    (%rsi), %rax
        addq    %rax, (%rdi)
        movq    8(%rsi), %rax
        adcq    %rax, 8(%rdi)
        movq    16(%rsi), %rax
        adcq    %rax, 16(%rdi)
        movq    24(%rsi), %rax
        adcq    %rax, 24(%rdi)
        retq

Inline assembly

Using inline assembly will sacrifice code readability, portability, auditability and maintainability. That said the performance might be worth it.