Path: blob/main/contrib/bearssl/src/ec/ec_c25519_i15.c
39507 views
/*1* Copyright (c) 2017 Thomas Pornin <[email protected]>2*3* Permission is hereby granted, free of charge, to any person obtaining4* a copy of this software and associated documentation files (the5* "Software"), to deal in the Software without restriction, including6* without limitation the rights to use, copy, modify, merge, publish,7* distribute, sublicense, and/or sell copies of the Software, and to8* permit persons to whom the Software is furnished to do so, subject to9* the following conditions:10*11* The above copyright notice and this permission notice shall be12* included in all copies or substantial portions of the Software.13*14* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,15* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF16* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND17* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS18* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN19* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN20* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE21* SOFTWARE.22*/2324#include "inner.h"2526/*27* Parameters for the field:28* - field modulus p = 2^255-1929* - R^2 mod p (R = 2^(15k) for the smallest k such that R >= p)30*/3132static const uint16_t C255_P[] = {330x0110,340x7FED, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF,350x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF,360x7FFF37};3839#define P0I 0x4A1B4041static const uint16_t C255_R2[] = {420x0110,430x0169, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,440x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,450x000046};4748/* obsolete49#include <stdio.h>50#include <stdlib.h>51static void52print_int_mont(const char *name, const uint16_t *x)53{54uint16_t y[18];55unsigned char tmp[32];56size_t u;5758printf("%s = ", name);59memcpy(y, x, sizeof y);60br_i15_from_monty(y, C255_P, P0I);61br_i15_encode(tmp, sizeof tmp, y);62for (u = 0; u < sizeof tmp; u ++) {63printf("%02X", tmp[u]);64}65printf("\n");66}67*/6869static const uint16_t C255_A24[] = {700x0110,710x45D3, 0x0046, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,720x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,730x000074};7576static const unsigned char GEN[] = {770x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,780x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,790x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,800x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0081};8283static const unsigned char ORDER[] = {840x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,850xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,860xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,870xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF88};8990static const unsigned char *91api_generator(int curve, size_t *len)92{93(void)curve;94*len = 32;95return GEN;96}9798static const unsigned char *99api_order(int curve, size_t *len)100{101(void)curve;102*len = 32;103return ORDER;104}105106static size_t107api_xoff(int curve, size_t *len)108{109(void)curve;110*len = 32;111return 0;112}113114static void115cswap(uint16_t *a, uint16_t *b, uint32_t ctl)116{117int i;118119ctl = -ctl;120for (i = 0; i < 18; i ++) {121uint32_t aw, bw, tw;122123aw = a[i];124bw = b[i];125tw = ctl & (aw ^ bw);126a[i] = aw ^ tw;127b[i] = bw ^ tw;128}129}130131static void132c255_add(uint16_t *d, const uint16_t *a, const uint16_t *b)133{134uint32_t ctl;135uint16_t t[18];136137memcpy(t, a, sizeof t);138ctl = br_i15_add(t, b, 1);139ctl |= NOT(br_i15_sub(t, C255_P, 0));140br_i15_sub(t, C255_P, ctl);141memcpy(d, t, sizeof t);142}143144static void145c255_sub(uint16_t *d, const uint16_t *a, const uint16_t *b)146{147uint16_t t[18];148149memcpy(t, a, sizeof t);150br_i15_add(t, C255_P, br_i15_sub(t, b, 1));151memcpy(d, t, sizeof t);152}153154static void155c255_mul(uint16_t *d, const uint16_t *a, const uint16_t *b)156{157uint16_t t[18];158159br_i15_montymul(t, a, b, C255_P, P0I);160memcpy(d, t, sizeof t);161}162163static void164byteswap(unsigned char *G)165{166int i;167168for (i = 0; i < 16; i ++) {169unsigned char t;170171t = G[i];172G[i] = G[31 - i];173G[31 - i] = t;174}175}176177static uint32_t178api_mul(unsigned char *G, size_t Glen,179const unsigned char *kb, size_t kblen, int curve)180{181#define ILEN (18 * sizeof(uint16_t))182183/*184* The a[] and b[] arrays have an extra word to allow for185* decoding without using br_i15_decode_reduce().186*/187uint16_t x1[18], x2[18], x3[18], z2[18], z3[18];188uint16_t a[19], aa[18], b[19], bb[18];189uint16_t c[18], d[18], e[18], da[18], cb[18];190unsigned char k[32];191uint32_t swap;192int i;193194(void)curve;195196/*197* Points are encoded over exactly 32 bytes. Multipliers must fit198* in 32 bytes as well.199* RFC 7748 mandates that the high bit of the last point byte must200* be ignored/cleared.201*/202if (Glen != 32 || kblen > 32) {203return 0;204}205G[31] &= 0x7F;206207/*208* Byteswap the point encoding, because it uses little-endian, and209* the generic decoding routine uses big-endian.210*/211byteswap(G);212213/*214* Decode the point ('u' coordinate). This should be reduced215* modulo p, but we prefer to avoid the dependency on216* br_i15_decode_reduce(). Instead, we use br_i15_decode_mod()217* with a synthetic modulus of value 2^255 (this must work218* since G was truncated to 255 bits), then use a conditional219* subtraction. We use br_i15_decode_mod() and not220* br_i15_decode(), because the ec_prime_i15 implementation uses221* the former but not the latter.222* br_i15_decode_reduce(a, G, 32, C255_P);223*/224br_i15_zero(b, 0x111);225b[18] = 1;226br_i15_decode_mod(a, G, 32, b);227a[0] = 0x110;228br_i15_sub(a, C255_P, NOT(br_i15_sub(a, C255_P, 0)));229230/*231* Initialise variables x1, x2, z2, x3 and z3. We set all of them232* into Montgomery representation.233*/234br_i15_montymul(x1, a, C255_R2, C255_P, P0I);235memcpy(x3, x1, ILEN);236br_i15_zero(z2, C255_P[0]);237memcpy(x2, z2, ILEN);238x2[1] = 19;239memcpy(z3, x2, ILEN);240241memset(k, 0, (sizeof k) - kblen);242memcpy(k + (sizeof k) - kblen, kb, kblen);243k[31] &= 0xF8;244k[0] &= 0x7F;245k[0] |= 0x40;246247/* obsolete248print_int_mont("x1", x1);249*/250251swap = 0;252for (i = 254; i >= 0; i --) {253uint32_t kt;254255kt = (k[31 - (i >> 3)] >> (i & 7)) & 1;256swap ^= kt;257cswap(x2, x3, swap);258cswap(z2, z3, swap);259swap = kt;260261/* obsolete262print_int_mont("x2", x2);263print_int_mont("z2", z2);264print_int_mont("x3", x3);265print_int_mont("z3", z3);266*/267268c255_add(a, x2, z2);269c255_mul(aa, a, a);270c255_sub(b, x2, z2);271c255_mul(bb, b, b);272c255_sub(e, aa, bb);273c255_add(c, x3, z3);274c255_sub(d, x3, z3);275c255_mul(da, d, a);276c255_mul(cb, c, b);277278/* obsolete279print_int_mont("a ", a);280print_int_mont("aa", aa);281print_int_mont("b ", b);282print_int_mont("bb", bb);283print_int_mont("e ", e);284print_int_mont("c ", c);285print_int_mont("d ", d);286print_int_mont("da", da);287print_int_mont("cb", cb);288*/289290c255_add(x3, da, cb);291c255_mul(x3, x3, x3);292c255_sub(z3, da, cb);293c255_mul(z3, z3, z3);294c255_mul(z3, z3, x1);295c255_mul(x2, aa, bb);296c255_mul(z2, C255_A24, e);297c255_add(z2, z2, aa);298c255_mul(z2, e, z2);299300/* obsolete301print_int_mont("x2", x2);302print_int_mont("z2", z2);303print_int_mont("x3", x3);304print_int_mont("z3", z3);305*/306}307cswap(x2, x3, swap);308cswap(z2, z3, swap);309310/*311* Inverse z2 with a modular exponentiation. This is a simple312* square-and-multiply algorithm; we mutualise most non-squarings313* since the exponent contains almost only ones.314*/315memcpy(a, z2, ILEN);316for (i = 0; i < 15; i ++) {317c255_mul(a, a, a);318c255_mul(a, a, z2);319}320memcpy(b, a, ILEN);321for (i = 0; i < 14; i ++) {322int j;323324for (j = 0; j < 16; j ++) {325c255_mul(b, b, b);326}327c255_mul(b, b, a);328}329for (i = 14; i >= 0; i --) {330c255_mul(b, b, b);331if ((0xFFEB >> i) & 1) {332c255_mul(b, z2, b);333}334}335c255_mul(b, x2, b);336337/*338* To avoid a dependency on br_i15_from_monty(), we use a339* Montgomery multiplication with 1.340* memcpy(x2, b, ILEN);341* br_i15_from_monty(x2, C255_P, P0I);342*/343br_i15_zero(a, C255_P[0]);344a[1] = 1;345br_i15_montymul(x2, a, b, C255_P, P0I);346347br_i15_encode(G, 32, x2);348byteswap(G);349return 1;350351#undef ILEN352}353354static size_t355api_mulgen(unsigned char *R,356const unsigned char *x, size_t xlen, int curve)357{358const unsigned char *G;359size_t Glen;360361G = api_generator(curve, &Glen);362memcpy(R, G, Glen);363api_mul(R, Glen, x, xlen, curve);364return Glen;365}366367static uint32_t368api_muladd(unsigned char *A, const unsigned char *B, size_t len,369const unsigned char *x, size_t xlen,370const unsigned char *y, size_t ylen, int curve)371{372/*373* We don't implement this method, since it is used for ECDSA374* only, and there is no ECDSA over Curve25519 (which instead375* uses EdDSA).376*/377(void)A;378(void)B;379(void)len;380(void)x;381(void)xlen;382(void)y;383(void)ylen;384(void)curve;385return 0;386}387388/* see bearssl_ec.h */389const br_ec_impl br_ec_c25519_i15 = {390(uint32_t)0x20000000,391&api_generator,392&api_order,393&api_xoff,394&api_mul,395&api_mulgen,396&api_muladd397};398399400