pqc/crypto_kem/hqc-rmrs-256/avx2/reed_solomon.c

745 lines
44 KiB
C
Raw Permalink Normal View History

2020-09-07 19:23:34 +01:00
#include "fft.h"
#include "gf.h"
#include "parameters.h"
#include "parsing.h"
2020-09-07 19:23:34 +01:00
#include "reed_solomon.h"
#include <stdint.h>
#include <stdio.h>
#include <string.h>
/**
* @file reed_solomon.c
* Constant time implementation of Reed-Solomon codes
*/
static void compute_syndromes(uint16_t *syndromes, uint8_t *cdw);
2020-09-11 23:19:10 +01:00
static uint16_t compute_elp(uint16_t *sigma, const uint16_t *syndromes);
2020-09-07 19:23:34 +01:00
static void compute_roots(uint8_t *error, uint16_t *sigma);
2020-09-11 23:19:10 +01:00
static void compute_z_poly(uint16_t *z, const uint16_t *sigma, uint16_t degree, const uint16_t *syndromes);
2020-09-07 19:23:34 +01:00
static void compute_error_values(uint16_t *error_values, const uint16_t *z, const uint8_t *error);
static void correct_errors(uint8_t *cdw, const uint16_t *error_values);
2020-10-26 02:17:30 +00:00
static const __m256i alpha_ij256_1[89] = {
{0x0010000800040002, 0x001d008000400020, 0x00cd00e80074003a, 0x004c002600130087},
{0x001d004000100004, 0x004c001300cd0074, 0x008f00ea00b4002d, 0x009d006000180006},
{0x00cd003a00400008, 0x008f0075002d0026, 0x002500270060000c, 0x004600c100b50035},
{0x004c00cd001d0010, 0x009d0018008f00b4, 0x004600ee006a0025, 0x005f00b9005d0014},
{0x00b4002600740020, 0x006a009c00600003, 0x00b900a0000500c1, 0x00fd000f005e00be},
{0x008f002d00cd0040, 0x004600b500250060, 0x0065006100b90050, 0x00d900df006b0078},
{0x0018007500130080, 0x005d008c00b5009c, 0x006b003c005e00a1, 0x0081001a004300a3},
{0x009d008f004c001d, 0x005f005d0046006a, 0x00d900fe00fd0065, 0x0085003b0081000d},
{0x0025000c002d003a, 0x006500a1005000c1, 0x00d0008600df00e7, 0x00a800a9006600ed},
{0x006a006000b40074, 0x00fd005e00b90005, 0x003b0067001100df, 0x00e600550084002e},
{0x00ee002700ea00e8, 0x00fe003c006100a0, 0x00b8007600670086, 0x00e3009100390054},
{0x00460025008f00cd, 0x00d9006b006500b9, 0x00a800b8003b00d0, 0x0082009600fc00e4},
{0x0014003500060087, 0x000d00a3007800be, 0x00e40054002e00ed, 0x00510064006200e5},
{0x005d00b500180013, 0x00810043006b005e, 0x00fc003900840066, 0x0012005900c80062},
{0x00b900c100600026, 0x003b001a00df000f, 0x00960091005500a9, 0x002c002400590064},
{0x005f0046009d004c, 0x0085008100d900fd, 0x008200e300e600a8, 0x0002002c00120051},
{0x0099000a004e0098, 0x004f0093004400d6, 0x00dd00dc00d70092, 0x00980001000b0045},
{0x006500500025002d, 0x00a8006600d000df, 0x00c30007009600bf, 0x0027002600ad00fb},
{0x001e00ba0094005a, 0x0049006d003e00e2, 0x003d00a200ae00b3, 0x008c006000e80083},
{0x00fd00b9006a00b4, 0x00e60084003b0011, 0x002c00ac001c0096, 0x00be00c100030020},
{0x006b00a100b50075, 0x00fc00290066001a, 0x00ad00f500590057, 0x00e700b90035002d},
{0x00fe006100ee00ea, 0x00e3003900b80067, 0x003a00b000ac0007, 0x00af000f002800c0},
{0x005b002f009f00c9, 0x009500d10021007c, 0x0075004700f400a6, 0x001f00df00c200ee},
{0x00d900650046008f, 0x008200fc00a8003b, 0x0027003a002c00c3, 0x0017001a00e700ba},
{0x0011000f00050003, 0x001c00ff00550033, 0x00c100b4006c0024, 0x004d003b00e2005e},
{0x000d007800140006, 0x0051006200e4002e, 0x00ba00c0002000fb, 0x00d100a900bd00bb},
{0x00d000e70050000c, 0x00c3005700bf00a9, 0x002f00b50026007d, 0x00db005500c500d9},
{0x0081006b005d0018, 0x001200c800fc0084, 0x00e70028000300ad, 0x00190091009e00bd},
{0x00f8007f00690030, 0x00f700e000f1004d, 0x00b6005f009c0040, 0x00a2009600aa00ec},
{0x003b00df00b90060, 0x002c005900960055, 0x001a000f00c10026, 0x00240064009100a9},
{0x009700b600de00c0, 0x001b009b006e0072, 0x00ed00b100a0008f, 0x00580059004b0052},
{0x008500d9005f009d, 0x00020012008200e6, 0x001700af00be0027, 0x00040024001900d1},
{0x00b8008600610027, 0x003a00f500070091, 0x001500d0000f00b5, 0x002d002c00a600f1},
{0x004f00440099004e, 0x0098000b00dd00d7, 0x0092009300d6000a, 0x004e0001004500dc},
{0x0084001a005e009c, 0x000300e9005900ff, 0x0091002e00e200b9, 0x0005002600eb001c},
{0x00a800d000650025, 0x002700ad00c30096, 0x00db0015001a002f, 0x00610060003600f2},
{0x005200ce0089004a, 0x00d40010008a0037, 0x00570049007c0078, 0x00d300c1001d0048},
{0x0049003e001e0094, 0x008c00e8003d00ae, 0x003800630033007f, 0x004300b900ea0016},
{0x00e400ed00780035, 0x00ba002d00fb0064, 0x00f200f100a900d9, 0x003e000f002500ad},
{0x00e6003b00fd006a, 0x00be0003002c001c, 0x00240037004d001a, 0x002e00df00050074},
{0x00c600c500d300d4, 0x00ca009d00cf00a7, 0x008b00c80072003e, 0x009a001a005f00c9},
{0x00fc0066006b00b5, 0x00e7003500ad0059, 0x003600a6009100c5, 0x00bf003b00780025},
{0x007b001700b10077, 0x00e1009f000800ef, 0x0040002b00ff00b8, 0x00ab00a9005b008c},
{0x00e300b800fe00ee, 0x00af0028003a00ac, 0x002d007a00370015, 0x00320055003400de},
{0x009600a900df00c1, 0x001a00b900260024, 0x0060002c00640055, 0x00590091003b000f},
{0x00950021005b009f, 0x001f00c2007500f4, 0x00b500d800a70073, 0x0048009600da00fe},
{0x00a5001500710023, 0x00760089000c00eb, 0x0050008000ef00fc, 0x00b0006400520022},
{0x008200a800d90046, 0x001700e70027002c, 0x0061002d002400db, 0x0008005900bf003e},
{0x00c800290043008c, 0x009e00fe003500e9, 0x0078003000eb006e, 0x005a002400e300cc},
{0x001c005500110005, 0x004d00e200c1006c, 0x00df006a00e90064, 0x009c002c00ae0084},
{0x00dd00920044000a, 0x00920044000a0001, 0x0044000a000100dd, 0x000a000100dd0092},
{0x005100e4000d0014, 0x00d100bd00ba0020, 0x003e00de007400f2, 0x00c20026002b003f},
{0x0079007300340028, 0x00e500f800a10074, 0x006600ca00b4008a, 0x00bb006000f7004b},
{0x00c300bf00d00050, 0x00db00c5002f0026, 0x0021006b006000f5, 0x008600c100cf0082},
{0x00ac0091006700a0, 0x0037002e000f00b4, 0x005500e2006a002c, 0x007c00b9002000a7},
{0x001200fc0081005d, 0x0019009e00e70003, 0x00bf003400050036, 0x005c000f005a002b},
{0x003d00b3003e00ba, 0x003800a8007f0060, 0x00f100ed00b90008, 0x002900df002700f5},
{0x00f700f100f80069, 0x00a200aa00b6009c, 0x006e0085005e00cd, 0x0063001a002300fa},
{0x00cb00db00c700d2, 0x009b00b70086006a, 0x0007004200fd0075, 0x004b003b006f0004},
{0x002c0096003b00b9, 0x00240091001a00c1, 0x0059005500df0060, 0x006400a9000f0026},
{0x00fa00c400ec006f, 0x00f3007b00ce0005, 0x008a00d100110035, 0x00b2005500e10018},
{0x001b006e009700de, 0x0058004b00ed00a0, 0x00fb007b00670046, 0x00900091008800d4},
{0x00ad0057006600a1, 0x0036006e00c500b9, 0x00cf00c4003b00ba, 0x007d009600ed0050},
{0x000200820085005f, 0x00040019001700be, 0x00080032002e0061, 0x00100064005c00c2},
{0x00200064002e00be, 0x0074001c00a9005e, 0x002600a70084000f, 0x00b40059004d00fd},
{0x003a000700b80061, 0x002d00a60015000f, 0x000c00c30055006b, 0x00250024007300b6},
{0x0087003800da00c2, 0x000600f9002900fd, 0x0035009000e600b6, 0x0014002c00f60034},
{0x009800dd004f0099, 0x004e0045009200d6, 0x000a000b00d70044, 0x0099000100dc0093},
{0x007500a60021002f, 0x00b5003d007300df, 0x00a10036009600ce, 0x006b0026003800b8},
{0x000300590084005e, 0x000500eb009100e2, 0x000f002000ae003b, 0x0011006000ef004d},
{0x003000f2002a00bc, 0x006900b000b30011, 0x007f004c001c0017, 0x00f800c1007a00b7},
{0x002700c300a80065, 0x0061003600db001a, 0x0086000c00590021, 0x00b800b9007d00b3},
{0x004a0056009a00ca, 0x0089000200c40067, 0x00ce009400ac0029, 0x0052000f00040095},
{0x00d4008a00520089, 0x00d3001d0057007c, 0x00c5008c00f400e4, 0x00c600df004c008d},
{0x00c100240055000f, 0x00df00260064003b, 0x00a900b9002c0091, 0x0096001a00600059},
{0x008c003d0049001e, 0x004300ea00380033, 0x002900bc006c00f1, 0x00c8003b00ee0009},
{0x002800f50039003c, 0x0034003000a6002e, 0x007300d3002000c4, 0x007900a9006900cb},
{0x00ba00fb00e40078, 0x003e002500f200a9, 0x00b300b600260082, 0x003d005500650036},
{0x006f008b00b700f0, 0x00ec007700560084, 0x00c4000d00030038, 0x00fa009100b10080},
{0x00be002c00e600fd, 0x002e00050024004d, 0x0064007c009c0059, 0x00200096001100b4},
{0x002f007d00bf00e7, 0x002100ba00f50055, 0x00a6006600c10056, 0x00750064003e0027},
{0x00ca00cf00c600d3, 0x009a005f008b0072, 0x0056009e00a0003d, 0x004a00590085009f},
{0x003c0036003f00bb, 0x003900bc007d00e6, 0x00f5005200be008b, 0x00280024002a00d2},
{0x00e700ad00fc006b, 0x00bf007800360091, 0x007d0073000f00cf, 0x002f002c00e40065},
{0x00d6000100d700d6, 0x00d700d6000100d7, 0x000100d700d60001, 0x00d6000100d700d6},
{0x00e10008007b00b1, 0x00ab005b004000ff, 0x00cd003100e2003a, 0x0022002600950043},
{0x00b6004000f1007f, 0x006e008600cd0096, 0x008f0082001a002d, 0x00ed0060000700ce},
{0x00af003a00e300fe, 0x00320034002d0037, 0x002500e0007c000c, 0x006d00c100790097},
{0x002200cd00ab00e1, 0x0070001f008f00ae, 0x004600f900330025, 0x00a400b90048009e}
};
static const __m256i alpha_ij256_2[89] = {
{0x00b4005a002d0098, 0x008f00c900ea0075, 0x0018000c00060003, 0x009d00c000600030},
{0x006a00940025004e, 0x0046009f00ee00b5, 0x005d005000140005, 0x005f00de00b90069},
{0x00b900ba0050000a, 0x0065002f006100a1, 0x006b00e70078000f, 0x00d900b600df007f},
{0x00fd001e00650099, 0x00d9005b00fe006b, 0x008100d0000d0011, 0x00850097003b00f8},
{0x001100e200df00d6, 0x003b007c0067001a, 0x008400a9002e0033, 0x00e600720055004d},
{0x003b003e00d00044, 0x00a8002100b80066, 0x00fc00bf00e40055, 0x0082006e009600f1},
{0x0084006d00660093, 0x00fc00d100390029, 0x00c80057006200ff, 0x0012009b005900e0},
{0x00e6004900a8004f, 0x0082009500e300fc, 0x001200c30051001c, 0x0002001b002c00f7},
{0x009600b300bf0092, 0x00c300a600070057, 0x00ad007d00fb0024, 0x0027008f00260040},
{0x001c00ae009600d7, 0x002c00f400ac0059, 0x000300260020006c, 0x00be00a000c1009c},
{0x00ac00a2000700dc, 0x003a004700b000f5, 0x002800b500c000b4, 0x00af00b1000f005f},
{0x002c003d00c300dd, 0x00270075003a00ad, 0x00e7002f00ba00c1, 0x001700ed001a00b6},
{0x0020008300fb0045, 0x00ba00ee00c0002d, 0x00bd00d900bb005e, 0x00d1005200a900ec},
{0x000300e800ad000b, 0x00e700c200280035, 0x009e00c500bd00e2, 0x0019004b009100aa},
{0x00c1006000260001, 0x001a00df000f00b9, 0x0091005500a9003b, 0x0024005900640096},
{0x00be008c00270098, 0x0017001f00af00e7, 0x001900db00d1004d, 0x00040058002400a2},
{0x00d60099000a004e, 0x0092004f00930044, 0x004500dd00dc00d7, 0x004e00980001000b},
{0x001a007f002f000a, 0x00db0073001500c5, 0x003600f500f20064, 0x00610046006000cd},
{0x00330034007f0099, 0x00380062006300a8, 0x00ea0008001600ac, 0x004300f000b900d4},
{0x004d0033001a00d6, 0x002400a700370091, 0x00050060007400e9, 0x002e006700df005e},
{0x009100a800c50044, 0x0036003d00a6006e, 0x007800ba00250026, 0x00bf0015003b0086},
{0x0037006300150093, 0x002d00d8007a00a6, 0x0034006b00de006a, 0x0032007b00550085},
{0x00a700620073004f, 0x00b5005a00d8003d, 0x00da00ce00fe00be, 0x004800e0009600d5},
{0x0024003800db0092, 0x006100b5002d0036, 0x00bf0021003e00df, 0x000800fb0059006e},
{0x00e900ac006400d7, 0x00df00be006a0026, 0x00ae00910084007c, 0x009c0074002c00ef},
{0x0074001600f200dc, 0x003e00fe00de0025, 0x002b0082003f0084, 0x00c200d4002600fa},
{0x0060000800f500dd, 0x002100ce006b00ba, 0x00cf005600820091, 0x0086006500c1002d},
{0x000500ea00360045, 0x00bf00da00340078, 0x005a00cf002b00ae, 0x005c0088000f0023},
{0x005e00d400cd000b, 0x006e00d500850086, 0x0023002d00fa00ef, 0x006300da001a001e},
{0x00df00b900600001, 0x005900960055003b, 0x000f00c10026002c, 0x0064009100a9001a},
{0x006700f000460098, 0x00fb00e0007b0015, 0x0088006500d40074, 0x009000c8009100da},
{0x002e00430061004e, 0x00080048003200bf, 0x005c008600c2009c, 0x0010009000640063},
{0x005500ed006b000a, 0x000c003600c300c4, 0x0073006600b600b9, 0x0025000800240082},
{0x00d7004f00440099, 0x000a0098000b00dd, 0x00dc0092009300d6, 0x0099004e00010045},
{0x00ae0072003b00d6, 0x000f006a00200024, 0x00ef0096004d0067, 0x001100be0060006c},
{0x005900f100210044, 0x008600a1000c00cf, 0x007d00a600b300a9, 0x00b800d900b9008f},
{0x00f4001900e40093, 0x00c500b1008c00cd, 0x004c00fb008d00e6, 0x00c600cc00df0028},
{0x006c007900f1004f, 0x002900bd00bc0027, 0x00ee004000090037, 0x00c800b7003b00d3},
{0x002600f500820092, 0x00b300b800b60050, 0x0065002700360059, 0x003d0057005500ce},
{0x009c006c005900d7, 0x00640072007c000f, 0x001100b900b400eb, 0x002000ac00960084},
{0x00a00013003d00dc, 0x005600ab009e00d9, 0x0085007f009f0020, 0x004a00d8005900e5},
{0x000f002700cf00dd, 0x007d0038007300ed, 0x00e4003e00650060, 0x002f000c002c0007},
{0x00e20014003a0045, 0x00cd001200310021, 0x00950015004300a0, 0x0022006900260090},
{0x007c00bc000c000b, 0x0025008300e00073, 0x007900fc009700fd, 0x006d00e100c10002},
{0x00a900df00c10001, 0x00b9002600240096, 0x002c00640055001a, 0x0091003b000f0060},
{0x007200bd00a10098, 0x006b009400830038, 0x0087008a00e3002e, 0x008d00aa001a00d2},
{0x00ff008500e7004e, 0x00d0006f0013008a, 0x00d4003600700072, 0x007a006200a900fe},
{0x006400290086000a, 0x00b8006b0025007d, 0x002f0075003d0096, 0x004000f2009100ed},
{0x00ef003f00ed0099, 0x00e400680069003a, 0x00af0046008e00a7, 0x009400fa0064009a},
{0x00eb003700a900d6, 0x0096002e00fd0060, 0x0033000f000300f4, 0x005e00b4002400ff},
{0x000100dd00920044, 0x00dd00920044000a, 0x00920044000a0001, 0x0044000a000100dd},
{0x00b4000900b30093, 0x003d00e300970065, 0x00310017003c0003, 0x00da00d3006000f3},
{0x006a00b00057004f, 0x00ad000e009a00b6, 0x00a200e400880005, 0x003f001f00b90080},
{0x00b9004000a60092, 0x0075008a00fc003e, 0x008b00c40017000f, 0x000700a800df0025},
{0x00fd0003002400d7, 0x00c100e900ae00a9, 0x0074005900720011, 0x00f400ff003b00be},
{0x001100ee007d00dc, 0x002f0087007900e4, 0x0094008b00310033, 0x0080005300550071},
{0x003b00a1004000dd, 0x00b6002500fb00db, 0x0061003a00a60055, 0x0035008b009600c5},
{0x008400d3008f0045, 0x00ed00d200020007, 0x0071002500f300ff, 0x00bc008700590049},
{0x00e6002200b5000b, 0x001500d300c90056, 0x00ec00a10010001c, 0x008800ee002c0031},
{0x0096003b00b90001, 0x0091001a00c1002c, 0x005500df00600024, 0x00a9000f00260059},
{0x001c004200780098, 0x0057008500c20040, 0x00ab00ed005d006c, 0x007e003400c10016},
{0x00ac00b700d9004e, 0x00f200aa00e1000c, 0x005300a800d300b4, 0x000e009e000f0087},
{0x002c00db003e000a, 0x008b00f100ce0046, 0x00fb00b300d000c1, 0x00f500fc001a00b5},
{0x002000c800b80099, 0x0040008d006d002f, 0x0080000700da005e, 0x001d000e00a900bc},
{0x000300ef005500d6, 0x006000ac007200df, 0x009c002400e600e2, 0x006a00f400910011},
{0x00c100fb00fc0044, 0x0050007d00db00ce, 0x00a100ad006e003b, 0x0065004000640017},
{0x00be0047006e0093, 0x007800e8000e00b8, 0x00a3008f0079004d, 0x000d004a002400b7},
{0x00d6009800dd004f, 0x0044004e00450092, 0x0093000a000b00d7, 0x004f0099000100dc},
{0x001a0025008a0092, 0x006600ba007d00f1, 0x00290078003a0064, 0x00fc0086006000c3},
{0x003300a0002c00d7, 0x005500fd00740064, 0x00ff001a009c00ac, 0x001c002e00b900e9},
{0x004d0089000800dc, 0x00f10088009d00c3, 0x00e000b8006f00e9, 0x00f700d100df005a},
{0x009100b6007500dd, 0x000700660050008b, 0x00f50073007f0026, 0x003a0082003b0046},
{0x0037008100350045, 0x008a00a4001e0008, 0x0010006e001f006a, 0x00d400090055003c},
{0x00a7005c00ba000b, 0x00cf007b0043008f, 0x009d00f2004200be, 0x00ca008e00960034},
{0x00240055000f0001, 0x00260064003b00c1, 0x00b9002c009100df, 0x001a0060005900a9},
{0x00e900e500b60098, 0x0035002b002a0061, 0x00fe00cd0041007c, 0x009e006f002c00c6},
{0x007400a500ce004e, 0x00a1005800c6007f, 0x00f80035009b0084, 0x00e5005b00260019},
{0x006000a60017000a, 0x007f003a006e00d0, 0x00a80061007d0091, 0x003800c500c1008a},
{0x0005004800290099, 0x00ce009d00510017, 0x007b00b6001300ae, 0x00f30039000f00d8},
{0x005e00e9009100d6, 0x00a900a000f40055, 0x001c003b006a00ef, 0x00740037001a0003},
{0x00df003a00c40044, 0x0073007800ad00b3, 0x003d00290061002c, 0x00b500c300a90050},
{0x0067001800380093, 0x00c40022005a0082, 0x000200f1005b0074, 0x00890083009100bb},
{0x002e00230056004f, 0x00a6009700d400f2, 0x0030003800c7009c, 0x003400c900640081},
{0x00550061008b0092, 0x00f5002900a100fb, 0x00ba003d00a800b9, 0x0021005000240015},
{0x00d700d6000100d7, 0x000100d700d60001, 0x00d6000100d700d6, 0x00d700d6000100d7},
{0x00ae000d002d00dc, 0x008f001900680075, 0x001f000c00c80067, 0x007000f80060000e},
{0x005900c5002500dd, 0x004600c3001700b5, 0x00150050008a00a9, 0x00fb002900b9003d},
{0x00f4002a00500045, 0x0065001600aa00a1, 0x00e500e7001b00e6, 0x00e800ab00df0004},
{0x006c00d10065000b, 0x00d9008000f6006b, 0x008d00d0005a0037, 0x007700a2003b00c0}
};
static const __m256i alpha_ij256_3[89] = {
{0x0025009c004e0027, 0x006a00350094004a, 0x00ee007700b500d4, 0x00460023009f00c1},
{0x0065005e00990061, 0x00fd0078001e0089, 0x00fe00b1006b00d3, 0x00d90071005b00df},
{0x00d0001a00440086, 0x003b00ed003e00ce, 0x00b80017006600c5, 0x00a80015002100a9},
{0x00a80084004f00b8, 0x00e600e400490052, 0x00e3007b00fc00c6, 0x008200a500950096},
{0x009600ff00d70091, 0x001c006400ae0037, 0x00ac00ef005900a7, 0x002c00eb00f40024},
{0x00c3005900dd0007, 0x002c00fb003d008a, 0x003a000800ad00cf, 0x0027000c00750026},
{0x00ad00e9000b00f5, 0x0003002d00e80010, 0x0028009f0035009d, 0x00e7008900c200b9},
{0x002700030098003a, 0x00be00ba008c00d4, 0x00af00e100e700ca, 0x00170076001f001a},
{0x002f00b9000a00b5, 0x001a00d9007f0078, 0x001500b800c5003e, 0x00db00fc00730055},
{0x001a00e200d6000f, 0x004d00a90033007c, 0x003700ff00910072, 0x002400ef00a70064},
{0x0015002e009300d0, 0x003700f100630049, 0x007a002b00a600c8, 0x002d008000d8002c},
{0x00db009100920015, 0x002400f200380057, 0x002d00400036008b, 0x0061005000b50060},
{0x00f2001c00dc00f1, 0x007400ad00160048, 0x00de008c002500c9, 0x003e002200fe000f},
{0x003600eb004500a6, 0x0005002500ea001d, 0x0034005b0078005f, 0x00bf005200da003b},
{0x006000260001002c, 0x00df000f00b900c1, 0x005500a9003b001a, 0x0059006400960091},
{0x00610005004e002d, 0x002e003e004300d3, 0x003200ab00bf009a, 0x000800b000480059},
{0x004400d60099000a, 0x00d70092004f0093, 0x000b004500dd00dc, 0x000a004e00980001},
{0x0021003b0044006b, 0x0059008200f100e4, 0x000c003a00cf003d, 0x008600e700a100c1},
{0x00f10072004f00ed, 0x006c00f500790019, 0x00bc001400270013, 0x0029008500bd00df},
{0x005900ae00d70055, 0x009c0026006c00f4, 0x007c00e2000f00a0, 0x006400ff007200a9},
{0x00cf002400dd00c4, 0x000f0050002700cd, 0x0073002100ed00d9, 0x007d008a00380096},
{0x000c0020000b00c3, 0x007c00b600bc008c, 0x00e000310073009e, 0x0025001300830024},
{0x00a1006a00980036, 0x007200b800bd00b1, 0x00830012003800ab, 0x006b006f00940026},
{0x0086000f000a000c, 0x006400b3002900c5, 0x002500cd007d0056, 0x00b800d0006b00b9},
{0x00a9006700d600b9, 0x00eb0059003700e6, 0x00fd00a000600020, 0x00960072002e001a},
{0x00b3004d009300b6, 0x00b400360009008d, 0x009700430065009f, 0x003d007000e30055},
{0x00a6009600920066, 0x00b90027004000fb, 0x00fc0015003e007f, 0x00750036008a0064},
{0x007d00ef00dc0073, 0x0011006500ee004c, 0x0079009500e40085, 0x002f00d40087002c},
{0x008f006c00450082, 0x008400ce00d30028, 0x00020090000700e5, 0x00ed00fe00d20060},
{0x00b9006000010024, 0x00960055003b00df, 0x00c10026002c0059, 0x009100a9001a000f},
{0x00d900be004e0008, 0x00ac005700b700cc, 0x00e10069000c00d8, 0x00f2006200aa003b},
{0x00b8001100990025, 0x0020003d00c800c6, 0x006d0022002f004a, 0x0040007a008d0091},
{0x00fc00a90044002f, 0x00c100cd00fb0038, 0x00db00a800ce0078, 0x00500075007d0059},
{0x00dd00d7004f0044, 0x00d6000a0098000b, 0x004500dc00920093, 0x00440099004e0001},
{0x002c00a700d700a9, 0x003300df00a000b4, 0x007400f4006400e6, 0x0055007c00fd00c1},
{0x0075002c00dd00fc, 0x0091001700b600ba, 0x0050002d008b0038, 0x000700bf006600df},
{0x00ba00b4000b0038, 0x00a700fc005c0071, 0x0043006f008f00b0, 0x00cf00a2007b00a9},
{0x00b600a0009800fb, 0x00e900a600e5005c, 0x002a000d00610018, 0x00350002002b0096},
{0x001700df000a00cd, 0x006000cf00a600fc, 0x006e002900d0002f, 0x007f0046003a0024},
{0x0091003300d600c1, 0x005e006000e900a7, 0x00f400ae00550067, 0x00a900e200a00026},
{0x003800e600930078, 0x0067002f001800b0, 0x005a00f3008200aa, 0x00c4002a002200b9},
{0x008b0064009200ce, 0x005500d00061008f, 0x00a1007500fb0082, 0x00f500570029001a},
{0x002d00f400dc00a8, 0x00ae0029000d006f, 0x0068005f007500f3, 0x008f00cb00190055},
{0x00500074004500db, 0x00f4006e002a0043, 0x00aa006800a1005a, 0x0065001800160064},
{0x00df00c100010059, 0x00260024009600a9, 0x00640055001a00b9, 0x003b000f0060002c},
{0x006600fd004e007d, 0x00a0003a002b007b, 0x0016001900290022, 0x00fc00ec001e0060},
{0x00bf007c00990075, 0x00e20046000200a2, 0x001800cb0057002a, 0x00c300e500ec000f},
{0x0007005500440050, 0x00a9007f003500cf, 0x0065008f00f500c4, 0x003a00c300fc003b},
{0x00fb0037004f007f, 0x00ff0066003c0018, 0x00f800c2002d0012, 0x00ba001d00f90091},
{0x002600ac00d7003b, 0x00ef0091007c00be, 0x00e6006700b90074, 0x001a00a000200059},
{0x000a000100dd0092, 0x000100dd00920044, 0x00dd00920044000a, 0x00920044000a0001},
{0x007f009c000b006e, 0x006a007d00410042, 0x001b00c800a8005b, 0x003800a400af00c1},
{0x00c5005e00980056, 0x00fd000c007a00e3, 0x004a0016006e006d, 0x003600c8005400df},
{0x0073001a000a00ad, 0x003b006100cd00f2, 0x00e7000c003d00f1, 0x00b5007d005700a9},
{0x0064008400d60060, 0x00e6001a0005006c, 0x0033005e002600ef, 0x00df009c00eb0096},
{0x00f500ff009300a1, 0x001c00a800fe009d, 0x00e5001f00ba0002, 0x002100d300060024},
{0x00cd0059009200d9, 0x002c00c40066002f, 0x00f200e4008600b5, 0x006e001700650026},
{0x004600e900dc0017, 0x0003008a00c60034, 0x0004000e001500bb, 0x00fb00e300c700b9},
{0x006b0003004500bf, 0x00be004000700054, 0x009f00b000c40097, 0x000c000900c6001a},
{0x003b00b900010064, 0x001a00c1002c0096, 0x00df006000240091, 0x000f002600590055},
{0x00e400e2004e003d, 0x004d006b00c9009b, 0x00da00ca00cd0053, 0x00c500de00020064},
{0x0082002e00990040, 0x003700c5006f008e, 0x00ab00f800500083, 0x00b300bd0023002c},
{0x003d009100440035, 0x002400bf00860025, 0x008a007300d90027, 0x005600e400b60060},
{0x003a001c004f0065, 0x00740038009e00ca, 0x00e8007000210089, 0x00cd00e00042000f},
{0x00c100eb00d7001a, 0x0005002c00ff0067, 0x00a000e90096007c, 0x00b9006c0037003b},
{0x00e7002600dd0021, 0x00df008f00f20029, 0x00860027008a00e4, 0x00d000b500f50091},
{0x00ed0005000b00b3, 0x002e00a100d80095, 0x0054001e003a008d, 0x00e400e100ea0059},
{0x009200d6009800dd, 0x00d70044004e0045, 0x00dc0093000a000b, 0x00dd004f00990001},
{0x0057003b000a008b, 0x0059001500650008, 0x00f500bf00b6008f, 0x00ad00c4003e00c1},
{0x0024007200d60026, 0x006c00960067006a, 0x00b400a700a900be, 0x00c100f400e600df},
{0x004000ae00930046, 0x009c00560052003c, 0x005f001b00db0034, 0x00b600ea005300a9},
{0x00b50024009200e7, 0x000f0008006e003e, 0x00d0002500560029, 0x0015002f00ad0096},
{0x0078002000dc003e, 0x007c00b5001200aa, 0x004900f0004000a5, 0x005700f800770024},
{0x003e006a00450029, 0x007200e7008000a5, 0x00c800ec0046007a, 0x008b006300e10026},
{0x0055000f00010096, 0x0064003b00c10024, 0x002c009100df0026, 0x0060005900a900b9},
{0x006e0067004e00f2, 0x00eb007300bb0080, 0x0030005100b8005d, 0x007800040031001a},
{0x008a004d009900cf, 0x00b40007007600ee, 0x00ca00d800f100af, 0x0066008c00900055},
{0x000800960044008f, 0x00b9008b007300e7, 0x00ed003500c30021, 0x00f100d9002d0064},
{0x003500ef004f00ba, 0x00110075008d00c7, 0x00d100d30008004b, 0x008a0054005f002c},
{0x000f006c00d700df, 0x008400b900eb0072, 0x00a7003300c100ac, 0x002600ae00670060},
{0x00ce006000dd00c5, 0x00960086002d0082, 0x003600fc007f0040, 0x00a1008b00e4000f},
{0x002900be000b00e4, 0x00ac0021005d007a, 0x009400b200170023, 0x00ce00300070003b},
{0x00c4001100980057, 0x002000db007100e8, 0x00d3008e00b300fe, 0x0073001e001b0091},
{0x005600a9000a008a, 0x00c100c300b80046, 0x006600b500f20017, 0x00a600c500350059},
{0x000100d700d60001, 0x00d6000100d700d6, 0x00d700d6000100d7, 0x000100d700d60001},
{0x002500a700930027, 0x00330035005100ec, 0x00f9008500b500b2, 0x0046009b005c00c1},
{0x0065002c00920061, 0x0091007800cf0073, 0x000800b3006b00ad, 0x00d9003a00db00df},
{0x00d000b400dc0086, 0x00a700ed003000c8, 0x002300f900660094, 0x00a8005d000900a9},
{0x00a800a0004500b8, 0x00e900e400c200f3, 0x00a3000400fc00f0, 0x0082008800130096}
};
static const __m256i alpha_ij256_4[89] = {
{0x0014000a0005008c, 0x005d00a000500028, 0x00000000006900ba, 0x0000000000000000},
{0x000d004400110043, 0x0081006700d00034, 0x0000000000f8003e, 0x0000000000000000},
{0x00e4009200550029, 0x00fc009100bf0073, 0x0000000000f100b3, 0x0000000000000000},
{0x005100dd001c00c8, 0x001200ac00c30079, 0x0000000000f7003d, 0x0000000000000000},
{0x00200001006c00e9, 0x000300b400260074, 0x00000000009c0060, 0x0000000000000000},
{0x00ba000a00c10035, 0x00e7000f002f00a1, 0x0000000000b6007f, 0x0000000000000000},
{0x00bd004400e200fe, 0x009e002e00c500f8, 0x0000000000aa00a8, 0x0000000000000000},
{0x00d10092004d009e, 0x0019003700db00e5, 0x0000000000a20038, 0x0000000000000000},
{0x00f200dd0064006e, 0x0036002c00f5008a, 0x0000000000cd0008, 0x0000000000000000},
{0x0074000100e900eb, 0x0005006a006000b4, 0x00000000005e00b9, 0x0000000000000000},
{0x00de000a006a0030, 0x003400e2006b00ca, 0x00000000008500ed, 0x0000000000000000},
{0x003e004400df0078, 0x00bf005500210066, 0x00000000006e00f1, 0x0000000000000000},
{0x003f0092008400cc, 0x002b00a70082004b, 0x0000000000fa00f5, 0x0000000000000000},
{0x002b00dd00ae00e3, 0x005a002000cf00f7, 0x0000000000230027, 0x0000000000000000},
{0x00260001002c0024, 0x000f00b900c10060, 0x00000000001a00df, 0x0000000000000000},
{0x00c2000a009c005a, 0x005c007c008600bb, 0x0000000000630029, 0x0000000000000000},
{0x0093004400d60099, 0x00dc00d70092004f, 0x00000000004500dd, 0x0000000000000000},
{0x00b3009200a900ed, 0x007d002400a60057, 0x00000000008f0040, 0x0000000000000000},
{0x000900dd0037003f, 0x00ee0003004000b0, 0x0000000000d300a1, 0x0000000000000000},
{0x00b4000100eb00ef, 0x001100fd00b9006a, 0x000000000084003b, 0x0000000000000000},
{0x0065000a0060003a, 0x00e400a9003e00b6, 0x00000000000700db, 0x0000000000000000},
{0x0097004400fd0069, 0x007900ae00fc009a, 0x00000000000200fb, 0x0000000000000000},
{0x00e30092002e0068, 0x008700e9008a000e, 0x0000000000d20025, 0x0000000000000000},
{0x003d00dd009600e4, 0x002f00c1007500ad, 0x0000000000ed00b6, 0x0000000000000000},
{0x0003000100f400a7, 0x00330011000f0005, 0x0000000000ff0055, 0x0000000000000000},
{0x003c000a0003008e, 0x0031007200170088, 0x0000000000f300a6, 0x0000000000000000},
{0x00170044000f0046, 0x008b005900c400e4, 0x000000000025003a, 0x0000000000000000},
{0x00310092003300af, 0x00940074008b00a2, 0x0000000000710061, 0x0000000000000000},
{0x00f300dd00ff009a, 0x007100be00250080, 0x00000000004900c5, 0x0000000000000000},
{0x0060000100240064, 0x0055003b00df00b9, 0x0000000000590096, 0x0000000000000000},
{0x00d3000a00b400fa, 0x005300ff00a8001f, 0x000000000087008b, 0x0000000000000000},
{0x00da0044005e0094, 0x008000f40007003f, 0x0000000000bc0035, 0x0000000000000000},
{0x006e0092003b007f, 0x00a1006000ad0056, 0x00000000001700d9, 0x0000000000000000},
{0x000b00dd00d7004f, 0x009300d6000a0098, 0x0000000000dc0092, 0x0000000000000000},
{0x009c000100ac0037, 0x00ff0084001a005e, 0x0000000000e90059, 0x0000000000000000},
{0x007f000a002600fb, 0x00f50064007300c5, 0x00000000004600cd, 0x0000000000000000},
{0x0042004400be0018, 0x009d006c00f200e3, 0x000000000034002f, 0x0000000000000000},
{0x00410092007c003c, 0x00fe000500cd007a, 0x0000000000c60066, 0x0000000000000000},
{0x007d00dd00910066, 0x00a8001a0061000c, 0x00000000008a00c4, 0x0000000000000000},
{0x006a000100ef00ff, 0x001c00e6003b00fd, 0x000000000003002c, 0x0000000000000000},
{0x005b000a00740012, 0x000200ef00f1006d, 0x0000000000bb00b5, 0x0000000000000000},
{0x00a8004400b9002d, 0x00ba0026003d006e, 0x0000000000150086, 0x0000000000000000},
{0x00c80092006700c2, 0x001f005e000c0016, 0x00000000000e00e4, 0x0000000000000000},
{0x001b00dd00e600f8, 0x00e5003300e7004a, 0x00000000000400f2, 0x0000000000000000},
{0x00c1000100590091, 0x0024009600a900df, 0x0000000000b90026, 0x0000000000000000},
{0x00af000a002000f9, 0x000600eb00570054, 0x0000000000c70065, 0x0000000000000000},
{0x00a4004400a0001d, 0x00d3009c007d00c8, 0x0000000000e30017, 0x0000000000000000},
{0x00380092001a00ba, 0x002100df00b50036, 0x0000000000fb006e, 0x0000000000000000},
{0x004700dd00720034, 0x0032004d00d90023, 0x00000000004a007d, 0x0000000000000000},
{0x0005000100a70072, 0x006c001c00550011, 0x0000000000e200c1, 0x0000000000000000},
{0x0044000a000100dd, 0x000a000100dd0092, 0x0000000000920044, 0x0000000000000000},
{0x0039004400050047, 0x006800a000080053, 0x0000000000b20073, 0x0000000000000000},
{0x0053009200110023, 0x0063006700ba0010, 0x00000000001300c3, 0x0000000000000000},
{0x000800dd005500d9, 0x0056009100ce00ba, 0x000000000065002d, 0x0000000000000000},
{0x00a00001001c004d, 0x00b400ac00910067, 0x00000000002e000f, 0x0000000000000000},
{0x0068000a006c0032, 0x001e00b400560063, 0x0000000000a500b8, 0x0000000000000000},
{0x0073004400c1007d, 0x00b8000f002d00c3, 0x0000000000cf0057, 0x0000000000000000},
{0x00b2009200e2004a, 0x00a5002e00650013, 0x00000000008c00cf, 0x0000000000000000},
{0x001d00dd004d00b1, 0x00fa0037006600c2, 0x0000000000680046, 0x0000000000000000},
{0x00b90001006400a9, 0x00c1002c0096003b, 0x000000000091001a, 0x0000000000000000},
{0x0081000a00e90095, 0x0022006a00fb00f6, 0x00000000000900bf, 0x0000000000000000},
{0x00c60044006a00f3, 0x00d500e200270048, 0x0000000000060056, 0x0000000000000000},
{0x00c3009200df000c, 0x00f20055007f008f, 0x00000000006b0075, 0x0000000000000000},
{0x008700dd0084001e, 0x001300a70015003c, 0x00000000002a0078, 0x0000000000000000},
{0x00be000100ae0033, 0x005e00200064002e, 0x00000000001c00a9, 0x0000000000000000},
{0x00ed000a002c00f1, 0x006600b9003600c4, 0x0000000000080082, 0x0000000000000000},
{0x00e50044009c0009, 0x0062007c004600cb, 0x00000000006f0036, 0x0000000000000000},
{0x0045009200d60098, 0x000b00d70044004e, 0x000000000093000a, 0x0000000000000000},
{0x002d00dd00a90061, 0x0035002400e4007f, 0x0000000000db00d0, 0x0000000000000000},
{0x005e00010037007c, 0x00e2000300590084, 0x0000000000eb0091, 0x0000000000000000},
{0x00ec000a00eb00c6, 0x00aa00fd003a0019, 0x000000000094008a, 0x0000000000000000},
{0x00f10044006000f2, 0x00a600a900a100cf, 0x0000000000d9008f, 0x0000000000000000},
{0x0048009200fd0080, 0x001d00ae00ed00ee, 0x00000000003900e7, 0x0000000000000000},
{0x00c900dd002e005d, 0x005f00e900b300af, 0x0000000000790021, 0x0000000000000000},
{0x000f00010096001a, 0x003b00c100240055, 0x0000000000260064, 0x0000000000000000},
{0x00cc000a00f40039, 0x00e30011008f00e0, 0x0000000000ca00ad, 0x0000000000000000},
{0x004b0044000300e0, 0x00f7007200780002, 0x00000000005c0050, 0x0000000000000000},
{0x00f50092000f00ad, 0x0027005900b80050, 0x00000000005700ce, 0x0000000000000000},
{0x001800dd0033009f, 0x00e10074006e0068, 0x00000000008300fc, 0x0000000000000000},
{0x00fd000100ff00e2, 0x004d00be002c00e6, 0x0000000000050024, 0x0000000000000000},
{0x00b8000a002400a8, 0x0038003b003500f2, 0x0000000000d0000c, 0x0000000000000000},
{0x0095004400b40019, 0x000400ff00b600e8, 0x00000000003f006b, 0x0000000000000000},
{0x00cb0092005e00b0, 0x006900f40029005f, 0x0000000000120015, 0x0000000000000000},
{0x002700dd003b0025, 0x003e0060003800ed, 0x00000000000c0007, 0x0000000000000000},
{0x00d6000100d700d6, 0x00d700d6000100d7, 0x0000000000d60001, 0x0000000000000000},
{0x009e000a00ac00da, 0x0048008400500009, 0x00000000005400ba, 0x0000000000000000},
{0x00570044002600c4, 0x000c006400d00075, 0x000000000038003e, 0x0000000000000000},
{0x0058009200be00f7, 0x00bb006c00bf0089, 0x00000000001000b3, 0x0000000000000000},
{0x009400dd007c0006, 0x0042000500c300cc, 0x0000000000de003d, 0x0000000000000000}
};
2020-09-07 19:23:34 +01:00
/**
* @brief Encodes a message message of PARAM_K bits to a Reed-Solomon codeword codeword of PARAM_N1 bytes
*
* Following @cite lin1983error (Chapter 4 - Cyclic Codes),
* We perform a systematic encoding using a linear (PARAM_N1 - PARAM_K)-stage shift register
* with feedback connections based on the generator polynomial PARAM_RS_POLY of the Reed-Solomon code.
*
* @param[out] cdw Array of size VEC_N1_SIZE_64 receiving the encoded message
* @param[in] msg Array of size VEC_K_SIZE_64 storing the message
*/
void PQCLEAN_HQCRMRS256_AVX2_reed_solomon_encode(uint8_t *cdw, const uint8_t *msg) {
2020-10-26 02:17:30 +00:00
size_t i, k;
2020-09-07 19:23:34 +01:00
uint8_t gate_value = 0;
2020-09-14 20:45:24 +01:00
uint8_t prev, x;
2020-09-07 19:23:34 +01:00
2020-10-26 02:17:30 +00:00
union {
uint16_t arr16[16 * CEIL_DIVIDE(PARAM_G, 16)];
__m256i dummy;
} tmp = {0};
union {
uint16_t arr16[16 * CEIL_DIVIDE(PARAM_G, 16)];
__m256i dummy;
} PARAM_RS_POLY = {{ RS_POLY_COEFS }};
__m256i *tmp256 = (__m256i *)tmp.arr16;
__m256i *param256 = (__m256i *)PARAM_RS_POLY.arr16;
2020-09-07 19:23:34 +01:00
2020-09-14 20:45:24 +01:00
for (i = 0; i < PARAM_K; ++i) {
2020-09-14 21:45:04 +01:00
gate_value = (uint8_t) (msg[PARAM_K - 1 - i] ^ cdw[PARAM_N1 - PARAM_K - 1]);
2020-10-26 02:17:30 +00:00
_mm256_storeu_si256(&tmp256[0], PQCLEAN_HQCRMRS256_AVX2_gf_mul_vect(_mm256_set1_epi16(gate_value), param256[0]));
_mm256_storeu_si256(&tmp256[1], PQCLEAN_HQCRMRS256_AVX2_gf_mul_vect(_mm256_set1_epi16(gate_value), param256[1]));
_mm256_storeu_si256(&tmp256[2], PQCLEAN_HQCRMRS256_AVX2_gf_mul_vect(_mm256_set1_epi16(gate_value), param256[2]));
_mm256_storeu_si256(&tmp256[3], PQCLEAN_HQCRMRS256_AVX2_gf_mul_vect(_mm256_set1_epi16(gate_value), param256[3]));
2020-09-07 19:23:34 +01:00
2020-09-14 20:45:24 +01:00
prev = 0;
for (k = 0; k < PARAM_N1 - PARAM_K; k++) {
x = cdw[k];
2020-10-26 02:17:30 +00:00
cdw[k] = (uint8_t) (prev ^ tmp.arr16[k]);
2020-09-14 20:45:24 +01:00
prev = x;
2020-09-07 19:23:34 +01:00
}
}
memcpy(cdw + PARAM_N1 - PARAM_K, msg, PARAM_K);
2020-09-07 19:23:34 +01:00
}
/**
* @brief Computes 2 * PARAM_DELTA syndromes
*
* @param[out] syndromes Array of size 2 * PARAM_DELTA receiving the computed syndromes
* @param[in] cdw Array of size PARAM_N1 storing the received vector
*/
void compute_syndromes(uint16_t *syndromes, uint8_t *cdw) {
2020-10-26 02:17:30 +00:00
__m256i *syndromes256 = (__m256i *) syndromes;
__m256i last_syndromes256;
syndromes256[0] = _mm256_set1_epi16(cdw[0]);
for (size_t i = 0; i < PARAM_N1 - 1; ++i) {
syndromes256[0] ^= PQCLEAN_HQCRMRS256_AVX2_gf_mul_vect(_mm256_set1_epi16(cdw[i + 1]), alpha_ij256_1[i]);
2020-09-07 19:23:34 +01:00
}
2020-10-26 02:17:30 +00:00
syndromes256[1] = _mm256_set1_epi16(cdw[0]);
for (size_t i = 0; i < PARAM_N1 - 1; ++i) {
syndromes256[1] ^= PQCLEAN_HQCRMRS256_AVX2_gf_mul_vect(_mm256_set1_epi16(cdw[i + 1]), alpha_ij256_2[i]);
}
syndromes256[2] = _mm256_set1_epi16(cdw[0]);
for (size_t i = 0; i < PARAM_N1 - 1; ++i) {
syndromes256[2] ^= PQCLEAN_HQCRMRS256_AVX2_gf_mul_vect(_mm256_set1_epi16(cdw[i + 1]), alpha_ij256_3[i]);
}
last_syndromes256 = _mm256_set1_epi16(cdw[0]);
for (size_t i = 0; i < PARAM_N1 - 1; ++i) {
last_syndromes256 ^= PQCLEAN_HQCRMRS256_AVX2_gf_mul_vect(_mm256_set1_epi16(cdw[i + 1]), alpha_ij256_4[i]);
}
__m128i *s128 = (__m128i *) &last_syndromes256;
_mm_store_si128((__m128i *) (syndromes + 48), *s128);
uint32_t *s12 = (uint32_t *) (syndromes + 56);
uint32_t *s32 = ((uint32_t *) &last_syndromes256) + 4;
s12[0] = *s32;
2020-09-07 19:23:34 +01:00
}
/**
* @brief Computes the error locator polynomial (ELP) sigma
*
* This is a constant time implementation of Berlekamp's simplified algorithm (see @cite lin1983error (Chapter 6 - BCH Codes). <br>
* We use the letter p for rho which is initialized at -1. <br>
* The array X_sigma_p represents the polynomial X^(mu-rho)*sigma_p(X). <br>
* Instead of maintaining a list of sigmas, we update in place both sigma and X_sigma_p. <br>
* sigma_copy serves as a temporary save of sigma in case X_sigma_p needs to be updated. <br>
* We can properly correct only if the degree of sigma does not exceed PARAM_DELTA.
* This means only the first PARAM_DELTA + 1 coefficients of sigma are of value
* and we only need to save its first PARAM_DELTA - 1 coefficients.
*
* @returns the degree of the ELP sigma
* @param[out] sigma Array of size (at least) PARAM_DELTA receiving the ELP
* @param[in] syndromes Array of size (at least) 2*PARAM_DELTA storing the syndromes
*/
2020-09-11 23:19:10 +01:00
static uint16_t compute_elp(uint16_t *sigma, const uint16_t *syndromes) {
uint16_t deg_sigma = 0;
uint16_t deg_sigma_p = 0;
uint16_t deg_sigma_copy = 0;
2020-09-07 19:23:34 +01:00
uint16_t sigma_copy[PARAM_DELTA + 1] = {0};
uint16_t X_sigma_p[PARAM_DELTA + 1] = {0, 1};
2020-09-14 20:45:24 +01:00
uint16_t pp = (uint16_t) -1; // 2*rho
2020-09-07 19:23:34 +01:00
uint16_t d_p = 1;
uint16_t d = syndromes[0];
2020-09-11 23:19:10 +01:00
uint16_t mask1, mask2, mask12;
uint16_t deg_X, deg_X_sigma_p;
uint16_t dd;
uint16_t mu;
uint16_t i;
sigma[0] = 1;
for (mu = 0; (mu < (2 * PARAM_DELTA)); ++mu) {
2020-09-07 19:23:34 +01:00
// Save sigma in case we need it to update X_sigma_p
memcpy(sigma_copy, sigma, 2 * (PARAM_DELTA));
deg_sigma_copy = deg_sigma;
2020-09-11 23:19:10 +01:00
dd = PQCLEAN_HQCRMRS256_AVX2_gf_mul(d, PQCLEAN_HQCRMRS256_AVX2_gf_inverse(d_p));
2020-09-07 19:23:34 +01:00
2020-09-11 23:19:10 +01:00
for (i = 1; (i <= mu + 1) && (i <= PARAM_DELTA); ++i) {
2020-09-07 19:23:34 +01:00
sigma[i] ^= PQCLEAN_HQCRMRS256_AVX2_gf_mul(dd, X_sigma_p[i]);
}
2020-09-11 23:19:10 +01:00
deg_X = mu - pp;
deg_X_sigma_p = deg_X + deg_sigma_p;
2020-09-07 19:23:34 +01:00
// mask1 = 0xffff if(d != 0) and 0 otherwise
2020-09-11 23:19:10 +01:00
mask1 = -((uint16_t) - d >> 15);
2020-09-07 19:23:34 +01:00
// mask2 = 0xffff if(deg_X_sigma_p > deg_sigma) and 0 otherwise
2020-09-11 23:19:10 +01:00
mask2 = -((uint16_t) (deg_sigma - deg_X_sigma_p) >> 15);
2020-09-07 19:23:34 +01:00
// mask12 = 0xffff if the deg_sigma increased and 0 otherwise
2020-09-11 23:19:10 +01:00
mask12 = mask1 & mask2;
deg_sigma ^= mask12 & (deg_X_sigma_p ^ deg_sigma);
2020-09-07 19:23:34 +01:00
if (mu == (2 * PARAM_DELTA - 1)) {
break;
}
2020-09-11 23:19:10 +01:00
pp ^= mask12 & (mu ^ pp);
d_p ^= mask12 & (d ^ d_p);
for (i = PARAM_DELTA; i; --i) {
2020-09-07 19:23:34 +01:00
X_sigma_p[i] = (mask12 & sigma_copy[i - 1]) ^ (~mask12 & X_sigma_p[i - 1]);
}
2020-09-11 23:19:10 +01:00
deg_sigma_p ^= mask12 & (deg_sigma_copy ^ deg_sigma_p);
2020-09-07 19:23:34 +01:00
d = syndromes[mu + 1];
2020-09-11 23:19:10 +01:00
for (i = 1; (i <= mu + 1) && (i <= PARAM_DELTA); ++i) {
2020-09-07 19:23:34 +01:00
d ^= PQCLEAN_HQCRMRS256_AVX2_gf_mul(sigma[i], syndromes[mu + 1 - i]);
}
}
return deg_sigma;
}
/**
* @brief Computes the error polynomial error from the error locator polynomial sigma
*
* See function PQCLEAN_HQCRMRS256_AVX2_fft for more details.
*
* @param[out] error Array of 2^PARAM_M elements receiving the error polynomial
* @param[out] error_compact Array of PARAM_DELTA + PARAM_N1 elements receiving a compact representation of the vector error
* @param[in] sigma Array of 2^PARAM_FFT elements storing the error locator polynomial
*/
static void compute_roots(uint8_t *error, uint16_t *sigma) {
uint16_t w[1 << PARAM_M] = {0};
PQCLEAN_HQCRMRS256_AVX2_fft(w, sigma, PARAM_DELTA + 1);
PQCLEAN_HQCRMRS256_AVX2_fft_retrieve_error_poly(error, w);
}
/**
* @brief Computes the polynomial z(x)
*
* See @cite lin1983error (Chapter 6 - BCH Codes) for more details.
*
* @param[out] z Array of PARAM_DELTA + 1 elements receiving the polynomial z(x)
* @param[in] sigma Array of 2^PARAM_FFT elements storing the error locator polynomial
* @param[in] degree Integer that is the degree of polynomial sigma
* @param[in] syndromes Array of 2 * PARAM_DELTA storing the syndromes
*/
2020-09-11 23:19:10 +01:00
static void compute_z_poly(uint16_t *z, const uint16_t *sigma, uint16_t degree, const uint16_t *syndromes) {
size_t i, j;
uint16_t mask;
2020-09-07 19:23:34 +01:00
z[0] = 1;
2020-09-11 23:19:10 +01:00
for (i = 1; i < PARAM_DELTA + 1; ++i) {
mask = -((uint16_t) (i - degree - 1) >> 15);
z[i] = mask & sigma[i];
2020-09-07 19:23:34 +01:00
}
z[1] ^= syndromes[0];
2020-09-11 23:19:10 +01:00
for (i = 2; i <= PARAM_DELTA; ++i) {
mask = -((uint16_t) (i - degree - 1) >> 15);
z[i] ^= mask & syndromes[i - 1];
2020-09-07 19:23:34 +01:00
2020-09-11 23:19:10 +01:00
for (j = 1; j < i; ++j) {
z[i] ^= mask & PQCLEAN_HQCRMRS256_AVX2_gf_mul(sigma[j], syndromes[i - j - 1]);
2020-09-07 19:23:34 +01:00
}
}
}
/**
* @brief Computes the error values
*
* See @cite lin1983error (Chapter 6 - BCH Codes) for more details.
*
* @param[out] error_values Array of PARAM_DELTA elements receiving the error values
* @param[in] z Array of PARAM_DELTA + 1 elements storing the polynomial z(x)
* @param[in] z_degree Integer that is the degree of polynomial z(x)
* @param[in] error_compact Array of PARAM_DELTA + PARAM_N1 storing compact representation of the error
*/
static void compute_error_values(uint16_t *error_values, const uint16_t *z, const uint8_t *error) {
uint16_t beta_j[PARAM_DELTA] = {0};
uint16_t e_j[PARAM_DELTA] = {0};
2020-09-15 15:33:06 +01:00
uint16_t delta_counter;
2020-09-07 19:23:34 +01:00
uint16_t delta_real_value;
2020-09-15 15:33:06 +01:00
uint16_t found;
uint16_t mask1;
uint16_t mask2;
uint16_t tmp1;
uint16_t tmp2;
uint16_t inverse;
uint16_t inverse_power_j;
2020-09-07 19:23:34 +01:00
// Compute the beta_{j_i} page 31 of the documentation
2020-09-15 15:33:06 +01:00
delta_counter = 0;
2020-09-10 21:36:42 +01:00
for (size_t i = 0; i < PARAM_N1; i++) {
2020-09-15 15:33:06 +01:00
found = 0;
mask1 = (uint16_t) (-((int32_t)error[i]) >> 31); // error[i] != 0
for (size_t j = 0; j < PARAM_DELTA; j++) {
mask2 = ~((uint16_t) (-((int32_t) j ^ delta_counter) >> 31)); // j == delta_counter
beta_j[j] += mask1 & mask2 & gf_exp[i];
found += mask1 & mask2 & 1;
2020-09-07 19:23:34 +01:00
}
delta_counter += found;
}
delta_real_value = delta_counter;
// Compute the e_{j_i} page 31 of the documentation
2020-09-10 21:36:42 +01:00
for (size_t i = 0; i < PARAM_DELTA; ++i) {
2020-09-15 15:33:06 +01:00
tmp1 = 1;
tmp2 = 1;
inverse = PQCLEAN_HQCRMRS256_AVX2_gf_inverse(beta_j[i]);
inverse_power_j = 1;
2020-09-07 19:23:34 +01:00
2020-09-10 21:36:42 +01:00
for (size_t j = 1; j <= PARAM_DELTA; ++j) {
2020-09-07 19:23:34 +01:00
inverse_power_j = PQCLEAN_HQCRMRS256_AVX2_gf_mul(inverse_power_j, inverse);
tmp1 ^= PQCLEAN_HQCRMRS256_AVX2_gf_mul(inverse_power_j, z[j]);
}
2020-09-10 21:36:42 +01:00
for (size_t k = 1; k < PARAM_DELTA; ++k) {
2020-09-07 19:23:34 +01:00
tmp2 = PQCLEAN_HQCRMRS256_AVX2_gf_mul(tmp2, (1 ^ PQCLEAN_HQCRMRS256_AVX2_gf_mul(inverse, beta_j[(i + k) % PARAM_DELTA])));
}
2020-09-15 15:33:06 +01:00
mask1 = (uint16_t) (((int16_t) i - delta_real_value) >> 15); // i < delta_real_value
e_j[i] = mask1 & PQCLEAN_HQCRMRS256_AVX2_gf_mul(tmp1, PQCLEAN_HQCRMRS256_AVX2_gf_inverse(tmp2));
2020-09-07 19:23:34 +01:00
}
// Place the delta e_{j_i} values at the right coordinates of the output vector
delta_counter = 0;
2020-09-10 21:36:42 +01:00
for (size_t i = 0; i < PARAM_N1; ++i) {
2020-09-15 15:33:06 +01:00
found = 0;
mask1 = (uint16_t) (-((int32_t)error[i]) >> 31); // error[i] != 0
2020-09-10 21:36:42 +01:00
for (size_t j = 0; j < PARAM_DELTA; j++) {
2020-09-15 15:33:06 +01:00
mask2 = ~((uint16_t) (-((int32_t) j ^ delta_counter) >> 31)); // j == delta_counter
error_values[i] += mask1 & mask2 & e_j[j];
found += mask1 & mask2 & 1;
2020-09-07 19:23:34 +01:00
}
delta_counter += found;
}
}
/**
* @brief Correct the errors
*
* @param[out] cdw Array of PARAM_N1 elements receiving the corrected vector
* @param[in] error Array of the error vector
* @param[in] error_values Array of PARAM_DELTA elements storing the error values
*/
static void correct_errors(uint8_t *cdw, const uint16_t *error_values) {
2020-09-10 21:36:42 +01:00
for (size_t i = 0; i < PARAM_N1; ++i) {
2020-09-07 19:23:34 +01:00
cdw[i] ^= error_values[i];
}
}
/**
* @brief Decodes the received word
*
* This function relies on six steps:
* <ol>
* <li> The first step, is the computation of the 2*PARAM_DELTA syndromes.
* <li> The second step is the computation of the error-locator polynomial sigma.
* <li> The third step, done by additive FFT, is finding the error-locator numbers by calculating the roots of the polynomial sigma and takings their inverses.
* <li> The fourth step, is the polynomial z(x).
* <li> The fifth step, is the computation of the error values.
* <li> The sixth step is the correction of the errors in the received polynomial.
* </ol>
* For a more complete picture on Reed-Solomon decoding, see Shu. Lin and Daniel J. Costello in Error Control Coding: Fundamentals and Applications @cite lin1983error
*
* @param[out] msg Array of size VEC_K_SIZE_64 receiving the decoded message
* @param[in] cdw Array of size VEC_N1_SIZE_64 storing the received word
*/
void PQCLEAN_HQCRMRS256_AVX2_reed_solomon_decode(uint8_t *msg, uint8_t *cdw) {
2020-09-07 19:23:34 +01:00
uint16_t syndromes[2 * PARAM_DELTA] = {0};
uint16_t sigma[1 << PARAM_FFT] = {0};
uint8_t error[1 << PARAM_M] = {0};
uint16_t z[PARAM_N1] = {0};
uint16_t error_values[PARAM_N1] = {0};
2020-09-11 23:19:10 +01:00
uint16_t deg;
2020-09-07 19:23:34 +01:00
// Calculate the 2*PARAM_DELTA syndromes
compute_syndromes(syndromes, cdw);
2020-09-07 19:23:34 +01:00
// Compute the error locator polynomial sigma
// Sigma's degree is at most PARAM_DELTA but the FFT requires the extra room
2020-09-11 23:19:10 +01:00
deg = compute_elp(sigma, syndromes);
2020-09-07 19:23:34 +01:00
// Compute the error polynomial error
compute_roots(error, sigma);
// Compute the polynomial z(x)
compute_z_poly(z, sigma, deg, syndromes);
// Compute the error values
compute_error_values(error_values, z, error);
// Correct the errors
correct_errors(cdw, error_values);
2020-09-07 19:23:34 +01:00
// Retrieve the message from the decoded codeword
memcpy(msg, cdw + (PARAM_G - 1), PARAM_K);
2020-09-07 19:23:34 +01:00
}