salty 0.2.0-alpha.2

Small, sweet, swift Ed25519 signatures for microcontrollers
Documentation
/*                          =======================
  ============================ C/C++ HEADER FILE =============================
                            =======================

    \file bigint_types.h

    \Author B. Haase, Endress + Hauser Conducta GmbH & Co. KG

    License: CC0 1.0 (http://creativecommons.org/publicdomain/zero/1.0/legalcode)
  ============================================================================*/

#ifndef BIGINT_NUM_TYPES_HEADER_
#define BIGINT_NUM_TYPES_HEADER_

/*---------------------------------------------------------------------------*/
/*                               INCLUDES                                    */
/*---------------------------------------------------------------------------*/

#include "crypto_target_config.h"


/*---------------------------------------------------------------------------*/
/*                         DEFINITIONS AND MACROS                            */
/*---------------------------------------------------------------------------*/

/*---------------------------------------------------------------------------*/
/*                         TYPEDEFS AND STRUCTURES                           */
/*---------------------------------------------------------------------------*/

// Note that it's important to define the unit8 as first union member, so that
// an array of uint8_t may be used as initializer.
typedef union UN_64bitValue_
{
    uint8_t  as_uint8_t  [8];
    uint16_t as_uint16_t [4];
    uint32_t as_uint32_t [2];
    uint64_t as_uint64_t [1];
} UN_64bitValue;

// Note that it's important to define the unit8 as first union member, so that
// an array of uint8_t may be used as initializer.
typedef union UN_96bitValue_
{
    uint8_t  as_uint8_t[12];
    uint16_t as_uint16_t[6];
    uint32_t as_uint32_t[3];
    uint64_t as_uint64_t[1];
} UN_96bitValue;

// Note that it's important to define the unit8 as first union member, so that
// an array of uint8_t may be used as initializer.
typedef union UN_128bitValue_
{
    uint8_t         as_uint8_t[16];
    uint16_t        as_uint16_t[8];
    uint32_t        as_uint32_t[4];
    uint64_t        as_uint64_t[2];
    UN_64bitValue as_64_bitValue[2];
} UN_128bitValue;

// Note that it's important to define the unit8 as first union member, so that
// an array of uint8_t may be used as initializer.
typedef union UN_136bitValue_
{
    uint8_t          as_uint8_t[17];
    uint16_t         as_uint16_t[8];
    uint32_t         as_uint32_t[4];
    uint64_t         as_uint64_t[2];
    UN_64bitValue  as_64_bitValue[2];
    UN_128bitValue as_128_bitValue[1];
} UN_136bitValue;

// Note that it's important to define the unit8 as first union member, so that
// an array of uint8_t may be used as initializer.
typedef union UN_192bitValue_
{
    uint8_t          as_uint8_t[24];
    uint16_t         as_uint16_t[12];
    uint32_t         as_uint32_t[6];
    uint64_t         as_uint64_t[3];
    UN_64bitValue  as_64_bitValue[3];
    UN_128bitValue as_128_bitValue[1];
} UN_192bitValue;

// Note that it's important to define the unit8 as first union member, so that
// an array of uint8_t may be used as initializer.
typedef union UN_256bitValue_
{
    uint8_t          as_uint8_t[32];
    uint16_t         as_uint16_t[16];
    uint32_t         as_uint32_t[8];
    UN_64bitValue  as_64_bitValue_t[4];
    uint64_t         as_uint64_t[4];
    UN_128bitValue as_128_bitValue[2];
} UN_256bitValue;

// Note that it's important to define the unit8 as first union member, so that
// an array of uint8_t may be used as initializer.
typedef union UN_272bitValue_
{
    uint8_t          as_uint8_t[34];
    uint16_t         as_uint16_t[17];
    uint32_t         as_uint32_t[8];
    UN_64bitValue  as_64_bitValue[4];
    uint64_t         as_uint64_t[4];
    UN_128bitValue as_128_bitValue[2];
    UN_256bitValue as_256_bitValue[1];
} UN_272bitValue;

// Note that it's important to define the unit8 as first union member, so that
// an array of uint8_t may be used as initializer.
typedef union UN_288bitValue_
{
    uint8_t          as_uint8_t[36];
    uint16_t         as_uint16_t[18];
    uint32_t         as_uint32_t[9];
    UN_64bitValue  as_64_bitValue[4];
    uint64_t         as_uint64_t[4];
    UN_128bitValue as_128_bitValue[2];
    UN_256bitValue as_256_bitValue[1];
} UN_288bitValue;

// Note that it's important to define the unit8 as first union member, so that
// an array of uint8_t may be used as initializer.
typedef union UN_384bitValue_
{
    uint8_t          as_uint8_t[48];
    uint16_t         as_uint16_t[24];
    uint32_t         as_uint32_t[12];
    UN_64bitValue  as_64_bitValue[6];
    uint64_t         as_uint64_t[6];
    UN_128bitValue as_128_bitValue[3];
    UN_256bitValue as_256_bitValue[1];
} UN_384bitValue;

// Note that it's important to define the unit8 as first union member, so that
// an array of uint8_t may be used as initializer.
typedef union UN_512bitValue_
{
    uint8_t          as_uint8_t[64];
    uint16_t         as_uint16_t[32];
    uint32_t         as_uint32_t[16];
    uint64_t         as_uint64_t[8];
    UN_128bitValue as_128_bitValue[4];
    UN_256bitValue as_256_bitValue[2];
} UN_512bitValue;

// Note that it's important to define the unit8 as first union member, so that
// an array of uint8_t may be used as initializer.
typedef union UN_576bitValue_
{
    uint8_t          as_uint8_t[72];
    uint16_t         as_uint16_t[36];
    uint32_t         as_uint32_t[18];
    uint64_t         as_uint64_t[9];
    UN_128bitValue as_128_bitValue[4];
    UN_256bitValue as_256_bitValue[2];
    UN_512bitValue as_512_bitValue[1];
} UN_576bitValue;

#ifdef CRYPTO_HAS_ASM_MPY_96
#define multiply96x96 multiply96x96_asm
#else
#define multiply96x96 multiply96x96_c
#endif

void
multiply96x96(
    UN_192bitValue*      result,
    const UN_96bitValue* x,
    const UN_96bitValue* y
);

#ifdef CRYPTO_HAS_ASM_SQR_96
#define square96 square96_asm
#else
#define square96 square96_c
#endif

void
square96(
    UN_192bitValue*      result,
    const UN_96bitValue* x
);

#ifdef CRYPTO_HAS_ASM_MPY_128
#define multiply128x128 multiply128x128_asm
#else
#define multiply128x128 multiply128x128_c
#endif

void
multiply128x128(
    UN_256bitValue*       result,
    const UN_128bitValue* x,
    const UN_128bitValue* y
);

void
multiply288x288(
    UN_576bitValue*       r,
    const UN_288bitValue* x,
    const UN_288bitValue* y
);

void
multiply136x136(
    UN_272bitValue*       r,
    const UN_136bitValue* x,
    const UN_136bitValue* y
);

void
conditionalMove_192bitValue(
    UN_192bitValue*       r,
    const UN_192bitValue* x,
    uint8_t                 b
);

FORCE_INLINE static uint64_t
multiply16x32(
    uint16_t x,
    uint32_t y
)
{
    uint64_t r = ((uint32_t)x) * ((uint16_t)y);

    r += ((uint64_t)(((uint16_t)x) * (y >> 16))) << 16;
    return r;
}

void
cpy_192bitvalue(
    UN_192bitValue*       dest,
    const UN_192bitValue* source
);

#ifdef CRYPTO_HAS_ASM_SQR_128
#define square128 square128_asm
#else
#define square128 square128_c
#endif

void
square128(
    UN_256bitValue*       result,
    const UN_128bitValue* x
);


#ifdef CRYPTO_HAS_ASM_SQR_192
#define square192 square192_asm
#else
#define square192 square192_c
#endif

void square192 (
    UN_384bitValue* result,
    const UN_192bitValue* x);


#ifdef CRYPTO_HAS_ASM_MPY_192
#define multiply192x192 multiply192x192_asm
#else
#define multiply192x192 multiply192x192_c
#endif

void
multiply192x192(
    UN_384bitValue*       result,
    const UN_192bitValue* x,
    const UN_192bitValue* y
);


#ifdef CRYPTO_HAS_ASM_MPY_256
#define multiply256x256 multiply256x256_asm
#else
#define multiply256x256 multiply256x256_c
#endif

void
multiply256x256(
    UN_512bitValue*       result,
    const UN_256bitValue* x,
    const UN_256bitValue* y
);

#ifdef CRYPTO_HAS_ASM_SQR_256
#define square256 square256_asm
#else
#define square256 square256_c
#endif

void
square256(
    UN_512bitValue*       result,
    const UN_256bitValue* x
);

void
setone_256bitvalue(
    UN_256bitValue* dest
);

void
setzero_256bitvalue(
    UN_256bitValue* dest
);

void
cpy_256bitvalue(
    UN_256bitValue*       dest,
    const UN_256bitValue* source
);

/// Gets an uint8_t as third parameter that shall be zero or one.
void
conditionalMove_256bitValue(
    UN_256bitValue*       r,
    const UN_256bitValue* x,
    uint8_t                 b
);

FORCE_INLINE static void
swapPointersConditionally(
    void **p1,
    void **p2,
    uint8_t condition
);

FORCE_INLINE static void
swapPointersConditionally (void **p1, void **p2, uint8_t condition)
{
    // Secure version of this code:
    //
    // if (condition)
    // {
    //     void *temp;
    //     temp = *p2;
    //     *p2 = *p1;
    //     *p1 = temp;
    // }

    uintptr_t val1 = (uintptr_t) *p1;
    uintptr_t val2 = (uintptr_t) *p2;
    uintptr_t temp = val2 ^ val1;

    val1 ^= condition * temp;
    val2 ^= condition * temp;
    *p1 = (void *) val1;
    *p2 = (void *) val2;
}


FORCE_INLINE static uint8_t
isNegative(
    signed char b
)
{
    // use a sequence that is constant time and not optimized away by the compiler.
    volatile uint16_t x = b;
    x >>= 15; /* 1: yes; 0: no */
    return (uint8_t) x;
};

void shiftLeftOne(UN_256bitValue* val);
void shiftRightOne(UN_256bitValue* val);
uint32_t isEqual_256bitvalue(const UN_256bitValue* x, const UN_256bitValue* y);
int greaterThan(const UN_256bitValue* x, const UN_256bitValue* y);


#endif // NUM_TYPES_HEADER_