diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..47b24b6 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,5 @@ +root = true + +[**.{cc,js}] +indent_style = space +indent_size = 2 diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..a0bd546 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,77 @@ +name: CI + +on: + push: + pull_request: + +jobs: + test-native: + runs-on: ${{matrix.os}} + strategy: + fail-fast: false + matrix: + os: [ubuntu-latest, macOS-latest] + node-version: [16.x, 18.x, 19.x, 20.x] + steps: + - name: Checkout + uses: actions/checkout@v3 + - name: Set up Node.js ${{matrix.node-version}} + uses: actions/setup-node@v3 + with: + node-version: ${{matrix.node-version}} + - name: Build + run: npm install + - name: Test + run: npm test + build-wasm: + runs-on: ubuntu-latest + env: + NODE_VERSION: 18.x + EMSDK_VERSION: 3.1.14 + steps: + - name: Checkout + uses: actions/checkout@v3 + - name: Set up Node.js ${{env.NODE_VERSION}} + uses: actions/setup-node@v3 + with: + node-version: ${{env.NODE_VERSION}} + - name: Set up Emscripten SDK ${{env.EMSDK_VERSION}} + uses: mymindstorm/setup-emsdk@v12 + with: + version: ${{env.EMSDK_VERSION}} + - name: Install dependencies + run: npm install --ignore-scripts + - name: Build WebAssembly module + run: npm run build-wasm + - name: Upload build output + uses: actions/upload-artifact@v3 + with: + name: wasm-gen + path: | + wasm/mceliece.wasm + wasm/mceliece_constants.js + if-no-files-found: error + test-wasm: + needs: build-wasm + runs-on: ${{matrix.os}} + strategy: + fail-fast: false + matrix: + os: [ubuntu-latest, macOS-latest, windows-latest] + node-version: [16.x, 18.x, 19.x, 20.x] + steps: + - name: Checkout + uses: actions/checkout@v3 + - name: Set up Node.js ${{matrix.node-version}} + uses: actions/setup-node@v3 + with: + node-version: ${{matrix.node-version}} + - name: Install dependencies + run: npm install --ignore-scripts + - name: Download WebAssembly module + uses: actions/download-artifact@v3 + with: + name: wasm-gen + path: wasm + - name: Test + run: npm test diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..305ba10 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +build/ +node_modules/ +wasm/mceliece.wasm +wasm/mceliece_constants.js diff --git a/README.md b/README.md new file mode 100644 index 0000000..b249a39 --- /dev/null +++ b/README.md @@ -0,0 +1,88 @@ +# mceliece-nist + +This package provides Node.js bindings for the reference implementation that is +part of the [NIST submission](https://classic.mceliece.org/nist.html) by +Bernstein et al. + +This version is based on the round-4 submission `mceliece-20221023`. +See [`deps/mceliece`](deps/mceliece). + +## Installation + +Installation should work as usual: + +```sh +npm i mceliece-nist +``` + +## Example + +```javascript +const { McEliece } = require('mceliece-nist'); + +const kem = new McEliece('mceliece8192128'); +const { publicKey, privateKey } = kem.keypair(); + +const { key, encryptedKey } = kem.generateKey(publicKey); +console.log(`Bob is using the key ${key.toString('hex')}`); + +const receivedKey = kem.decryptKey(privateKey, encryptedKey); +console.log(`Alice is using the key ${receivedKey.toString('hex')}`); +``` + +## API + +The package exports a single class, `McEliece`. + +### Class `McEliece` + +#### `new McEliece(algorithm)` + +Creates a new instance using the specified algorithm. `algorithm` must be one of +the values contained in `McEliece.supportedAlgorithms`. + +#### `McEliece.supportedAlgorithms` + +This static field is an array of all supported algorithms. + +#### `instance.keySize` + +The (maximum) key size in bytes that this instance can encapsulate. + +#### `instance.encryptedKeySize` + +The size of the encapsulated key in bytes. + +#### `instance.publicKeySize` + +The size of the public key in bytes. + +#### `instance.privateKeySize` + +The size of the private key in bytes. + +#### `instance.keypair([callback])` + +Creates and returns a new key pair `{ publicKey, privateKey }`. Both keys will +be returned as `Buffer`s. + +If `callback` is a function, `keypair` immediately returns `undefined` and calls +`callback(err, { publicKey, privateKey })` as soon as a new keypair has been +generated. + +#### `instance.generateKey(publicKey)` + +Generates a new symmetric key and encrypts it using the given `publicKey`. +Returns `{ key, encryptedKey }`, both objects will be `Buffer`s. + +#### `instance.decryptKey(privateKey, encryptedKey[, callback])` + +Decrypts the `encryptedKey` that was returned by +`instance.generateKey(publicKey)` and returns the decrypted key as a `Buffer`. + +If `callback` is a function, `decryptKey` immediately returns `undefined` and +calls `callback(err, key)` as soon as the key has been decrypted. + +## License + +This project is distributed under the ISC license. diff --git a/binding.gyp b/binding.gyp new file mode 100644 index 0000000..4c0f002 --- /dev/null +++ b/binding.gyp @@ -0,0 +1,20 @@ +{ + "targets": [ + { + "target_name": "node_mceliece", + "sources": ["node_mceliece.cc"], + "include_dirs": [ + " $target" + mkdir -p `dirname $target` + emcc -std=c11 -Oz -Ikem/$id/subroutines -fvisibility=default $variables -c $source -o $target + done +} + +implementations=`ls -1 kem | while read id; do if [ -d "kem/$id" ]; then echo $id; fi; done` +rm -rf $obj_dir +for id in $implementations; do + compile_algorithm $id +done + +all_exports=`(echo -n '["_malloc","_free"'; for impl in $implementations; do + echo -n ",\"_crypto_kem_${impl}_ref_keypair\"" + echo -n ",\"_crypto_kem_${impl}_ref_enc\"" + echo -n ",\"_crypto_kem_${impl}_ref_dec\"" +done; echo -n ']') | sed 's/,\]/]/'` + +echo "Linking" +all_objs=`find $obj_dir -type f -name '*.bc'` +emcc -std=c11 -Oz $all_objs -o $build_dir/mceliece.wasm -s EXPORTED_FUNCTIONS="$all_exports" -s ERROR_ON_UNDEFINED_SYMBOLS=0 -s WASM=1 --no-entry + +echo "Converting header" +( + echo -e "'use strict';\n" + echo 'module.exports = {' + cat kem/mceliece*/crypto_kem_mceliece*.h | sort | grep -P '#define crypto_kem_mceliece([0-9f]+)_ref' | sed -e 's/#define / /g;' | sed -E 's/ ([0-9]+)/: \1,/g' + echo '};' +) > $build_dir/mceliece_constants.js + +echo "Cleaning up" +rm -rf $obj_dir diff --git a/deps/mceliece/extract-kem-from-nist-submission b/deps/mceliece/extract-kem-from-nist-submission new file mode 100755 index 0000000..e5e0405 --- /dev/null +++ b/deps/mceliece/extract-kem-from-nist-submission @@ -0,0 +1,111 @@ +#!/bin/bash +set -euo pipefail +shopt -s inherit_errexit + +# Remove the old implementation. +rm -rf kem + +archive=mceliece-20221023 +archfile=$archive.tar.gz + +echo -n "md5: "; md5sum $archfile | cut -c 1-32 +echo -n "sha1: "; sha1sum $archfile | cut -c 1-40 +echo -n "sha256: "; sha256sum $archfile | cut -c 1-64 +echo + +# Extract the reference implementation. +tar -xf $archfile $archive/Reference_Implementation/kem/ --strip-components=2 + +prepare_algorithm() { + echo "Preparing $id" + add_header $1 + add_gyp $1 + patch_files $1 +} + +add_header() { + id=$1 + echo "#include \"kem/$id/crypto_kem_$id.h\"" >> mceliece.h + echo "- Added $id to mceliece.h" +} + +add_gyp() { + id=$1 + + variables=("CRYPTO_NAMESPACE(x)=pqcrypto_kem_${id}_##x" \ + "_CRYPTO_NAMESPACE(x)=_pqcrypto_kem_${id}_##x") + + ( + echo " {" + echo " 'target_name': 'only_$id'," + echo " 'type': 'static_library'," + echo " 'sources': [" + find kem/$id -maxdepth 1 -type f -name '*.c' | sort | while read source; do + echo " '$source'," + done + echo " ]," + echo " 'include_dirs': [" + echo " 'kem/$id/subroutines'," + echo " ]," + echo " 'defines': [" + for def in ${variables[@]}; do + echo " '$def'," + done + echo " ]," + echo " 'cflags': ['-fPIC', '-Wno-unused-function']" + echo " }," + ) >> binding.gyp + + echo "- Added $id to binding.gyp" +} + +patch_files() { + id=$1 + + ( + # Non-source files. + find kem/$id/ -type f ! -name '*.c' ! -name '*.h' + # Only required for the NIST submission. + echo kem/$id/nist + # Irrelevant header files. + echo kem/$id/api.h + ) | while read f; do + rm -r "$f" + echo "- Removed $f" + done + + find kem/$id -type f \( -name '*.c' -o -name '*.h' \) | while read source; do + oldsha=$(sha1sum "$source") + sed -i 's=="../../mceliece_externals.h"=g; s="nist/rng.h"="../../mceliece_externals.h"=g' $source + newsha=$(sha1sum "$source") + if [ "$oldsha" != "$newsha" ]; then + echo "- Patched $source" + fi + done +} + +rm -f mceliece.h + +implementations=`ls -1 kem | while read id; do if [ -d "kem/$id" ]; then echo $id; fi; done | sort` +( + echo "{" + echo " 'targets': [" + echo " {" + echo " 'target_name': 'mceliece'," + echo " 'type': 'none'," + echo " 'dependencies': [" + for impl in $implementations; do + echo " 'only_$impl'," + done + echo " ]" + echo " }," +) > binding.gyp + +for id in $implementations; do + prepare_algorithm $id +done + +( + echo " ]" + echo "}" +) >> binding.gyp diff --git a/deps/mceliece/kem/mceliece348864/benes.c b/deps/mceliece/kem/mceliece348864/benes.c new file mode 100644 index 0000000..8de8ef5 --- /dev/null +++ b/deps/mceliece/kem/mceliece348864/benes.c @@ -0,0 +1,145 @@ +/* + This file is for Benes network related functions + + For the implementation strategy, see + https://eprint.iacr.org/2017/793.pdf +*/ + +#include "util.h" +#include "transpose.h" +#include "params.h" +#include "benes.h" + +/* one layer of the benes network */ +static void layer(uint64_t * data, uint64_t * bits, int lgs) +{ + int i, j, s; + + uint64_t d; + + s = 1 << lgs; + + for (i = 0; i < 64; i += s*2) + for (j = i; j < i+s; j++) + { + + d = (data[j+0] ^ data[j+s]); + d &= (*bits++); + data[j+0] ^= d; + data[j+s] ^= d; + } +} + +/* input: r, sequence of bits to be permuted */ +/* bits, condition bits of the Benes network */ +/* rev, 0 for normal application; !0 for inverse */ +/* output: r, permuted bits */ +void apply_benes(unsigned char * r, const unsigned char * bits, int rev) +{ + int i; + + const unsigned char *cond_ptr; + int inc, low; + + uint64_t bs[64]; + uint64_t cond[64]; + + // + + for (i = 0; i < 64; i++) + { + bs[i] = load8(r + i*8); + } + + if (rev == 0) + { + inc = 256; + cond_ptr = bits; + } + else + { + inc = -256; + cond_ptr = bits + (2*GFBITS-2)*256; + } + + // + + transpose_64x64(bs, bs); + + for (low = 0; low <= 5; low++) + { + for (i = 0; i < 64; i++) cond[i] = load4(cond_ptr + i*4); + transpose_64x64(cond, cond); + layer(bs, cond, low); + cond_ptr += inc; + } + + transpose_64x64(bs, bs); + + for (low = 0; low <= 5; low++) + { + for (i = 0; i < 32; i++) cond[i] = load8(cond_ptr + i*8); + layer(bs, cond, low); + cond_ptr += inc; + } + for (low = 4; low >= 0; low--) + { + for (i = 0; i < 32; i++) cond[i] = load8(cond_ptr + i*8); + layer(bs, cond, low); + cond_ptr += inc; + } + + transpose_64x64(bs, bs); + + for (low = 5; low >= 0; low--) + { + for (i = 0; i < 64; i++) cond[i] = load4(cond_ptr + i*4); + transpose_64x64(cond, cond); + layer(bs, cond, low); + cond_ptr += inc; + } + + transpose_64x64(bs, bs); + + // + + for (i = 0; i < 64; i++) + { + store8(r + i*8, bs[i]); + } +} + +/* input: condition bits c */ +/* output: support s */ +void support_gen(gf * s, const unsigned char *c) +{ + gf a; + int i, j; + unsigned char L[ GFBITS ][ (1 << GFBITS)/8 ]; + + for (i = 0; i < GFBITS; i++) + for (j = 0; j < (1 << GFBITS)/8; j++) + L[i][j] = 0; + + for (i = 0; i < (1 << GFBITS); i++) + { + a = bitrev((gf) i); + + for (j = 0; j < GFBITS; j++) + L[j][ i/8 ] |= ((a >> j) & 1) << (i%8); + } + + for (j = 0; j < GFBITS; j++) + apply_benes(L[j], c, 0); + + for (i = 0; i < SYS_N; i++) + { + s[i] = 0; + for (j = GFBITS-1; j >= 0; j--) + { + s[i] <<= 1; + s[i] |= (L[j][i/8] >> (i%8)) & 1; + } + } +} + diff --git a/deps/mceliece/kem/mceliece348864/benes.h b/deps/mceliece/kem/mceliece348864/benes.h new file mode 100644 index 0000000..c2ef35a --- /dev/null +++ b/deps/mceliece/kem/mceliece348864/benes.h @@ -0,0 +1,16 @@ +/* + This file is for Benes network related functions +*/ + +#ifndef BENES_H +#define BENES_H +#define apply_benes CRYPTO_NAMESPACE(apply_benes) +#define support_gen CRYPTO_NAMESPACE(support_gen) + +#include "gf.h" + +void apply_benes(unsigned char *, const unsigned char *, int); +void support_gen(gf *, const unsigned char *); + +#endif + diff --git a/deps/mceliece/kem/mceliece348864/bm.c b/deps/mceliece/kem/mceliece348864/bm.c new file mode 100644 index 0000000..056a734 --- /dev/null +++ b/deps/mceliece/kem/mceliece348864/bm.c @@ -0,0 +1,72 @@ +/* + This file is for the Berlekamp-Massey algorithm + see http://crypto.stanford.edu/~mironov/cs359/massey.pdf +*/ + +#include "params.h" +#include "gf.h" +#include "bm.h" + +#define min(a, b) ((a < b) ? a : b) + +/* the Berlekamp-Massey algorithm */ +/* input: s, sequence of field elements */ +/* output: out, minimal polynomial of s */ +void bm(gf *out, gf *s) +{ + int i; + + uint16_t N = 0; + uint16_t L = 0; + uint16_t mle; + uint16_t mne; + + gf T[ SYS_T+1 ]; + gf C[ SYS_T+1 ]; + gf B[ SYS_T+1 ]; + + gf b = 1, d, f; + + // + + for (i = 0; i < SYS_T+1; i++) + C[i] = B[i] = 0; + + B[1] = C[0] = 1; + + // + + for (N = 0; N < 2 * SYS_T; N++) + { + d = 0; + + for (i = 0; i <= min(N, SYS_T); i++) + d ^= gf_mul(C[i], s[ N-i]); + + mne = d; mne -= 1; mne >>= 15; mne -= 1; + mle = N; mle -= 2*L; mle >>= 15; mle -= 1; + mle &= mne; + + for (i = 0; i <= SYS_T; i++) + T[i] = C[i]; + + f = gf_frac(b, d); + + for (i = 0; i <= SYS_T; i++) + C[i] ^= gf_mul(f, B[i]) & mne; + + L = (L & ~mle) | ((N+1-L) & mle); + + for (i = 0; i <= SYS_T; i++) + B[i] = (B[i] & ~mle) | (T[i] & mle); + + b = (b & ~mle) | (d & mle); + + for (i = SYS_T; i >= 1; i--) B[i] = B[i-1]; + B[0] = 0; + } + + for (i = 0; i <= SYS_T; i++) + out[i] = C[ SYS_T-i ]; +} + diff --git a/deps/mceliece/kem/mceliece348864/bm.h b/deps/mceliece/kem/mceliece348864/bm.h new file mode 100644 index 0000000..73d5c6c --- /dev/null +++ b/deps/mceliece/kem/mceliece348864/bm.h @@ -0,0 +1,13 @@ +/* + This file is for the Berlekamp-Massey algorithm + see http://crypto.stanford.edu/~mironov/cs359/massey.pdf +*/ + +#ifndef BM_H +#define BM_H +#define bm CRYPTO_NAMESPACE(bm) + +void bm(gf *, gf *); + +#endif + diff --git a/deps/mceliece/kem/mceliece348864/controlbits.c b/deps/mceliece/kem/mceliece348864/controlbits.c new file mode 100644 index 0000000..db9db9c --- /dev/null +++ b/deps/mceliece/kem/mceliece348864/controlbits.c @@ -0,0 +1,220 @@ +/* This file is for implementing the Nassimi-Sahni algorithm */ +/* See David Nassimi, Sartaj Sahni "Parallel algorithms to set up the Benes permutationnetwork" */ +/* See also https://cr.yp.to/papers/controlbits-20200923.pdf */ + +#include +#include "crypto_declassify.h" +#include "controlbits.h" +#include "int32_sort.h" +typedef int16_t int16; +typedef int32_t int32; +#include "crypto_int32.h" +#define int32_min crypto_int32_min +#include "crypto_int16.h" + +/* parameters: 1 <= w <= 14; n = 2^w */ +/* input: permutation pi of {0,1,...,n-1} */ +/* output: (2m-1)n/2 control bits at positions pos,pos+step,... */ +/* output position pos is by definition 1&(out[pos/8]>>(pos&7)) */ +/* caller must 0-initialize positions first */ +/* temp must have space for int32[2*n] */ +static void cbrecursion(unsigned char *out,long long pos,long long step,const int16 *pi,long long w,long long n,int32 *temp) +{ +#define A temp +#define B (temp+n) +#define q ((int16 *) (temp+n+n/4)) +/* q can start anywhere between temp+n and temp+n/2 */ + + long long x,i,j,k; + + if (w == 1) { + out[pos>>3] ^= pi[0]<<(pos&7); + return; + } + + for (x = 0;x < n;++x) A[x] = ((pi[x]^1)<<16)|pi[x^1]; + int32_sort(A,n); /* A = (id<<16)+pibar */ + + for (x = 0;x < n;++x) { + int32 Ax = A[x]; + int32 px = Ax&0xffff; + int32 cx = int32_min(px,x); + B[x] = (px<<16)|cx; + } + /* B = (p<<16)+c */ + + for (x = 0;x < n;++x) A[x] = (A[x]<<16)|x; /* A = (pibar<<16)+id */ + int32_sort(A,n); /* A = (id<<16)+pibar^-1 */ + + for (x = 0;x < n;++x) A[x] = (A[x]<<16)+(B[x]>>16); /* A = (pibar^(-1)<<16)+pibar */ + int32_sort(A,n); /* A = (id<<16)+pibar^2 */ + + if (w <= 10) { + for (x = 0;x < n;++x) B[x] = ((A[x]&0xffff)<<10)|(B[x]&0x3ff); + + for (i = 1;i < w-1;++i) { + /* B = (p<<10)+c */ + + for (x = 0;x < n;++x) A[x] = ((B[x]&~0x3ff)<<6)|x; /* A = (p<<16)+id */ + int32_sort(A,n); /* A = (id<<16)+p^{-1} */ + + for (x = 0;x < n;++x) A[x] = (A[x]<<20)|B[x]; /* A = (p^{-1}<<20)+(p<<10)+c */ + int32_sort(A,n); /* A = (id<<20)+(pp<<10)+cp */ + + for (x = 0;x < n;++x) { + int32 ppcpx = A[x]&0xfffff; + int32 ppcx = (A[x]&0xffc00)|(B[x]&0x3ff); + B[x] = int32_min(ppcx,ppcpx); + } + } + for (x = 0;x < n;++x) B[x] &= 0x3ff; + } else { + for (x = 0;x < n;++x) B[x] = (A[x]<<16)|(B[x]&0xffff); + + for (i = 1;i < w-1;++i) { + /* B = (p<<16)+c */ + + for (x = 0;x < n;++x) A[x] = (B[x]&~0xffff)|x; + int32_sort(A,n); /* A = (id<<16)+p^(-1) */ + + for (x = 0;x < n;++x) A[x] = (A[x]<<16)|(B[x]&0xffff); + /* A = p^(-1)<<16+c */ + + if (i < w-2) { + for (x = 0;x < n;++x) B[x] = (A[x]&~0xffff)|(B[x]>>16); + /* B = (p^(-1)<<16)+p */ + int32_sort(B,n); /* B = (id<<16)+p^(-2) */ + for (x = 0;x < n;++x) B[x] = (B[x]<<16)|(A[x]&0xffff); + /* B = (p^(-2)<<16)+c */ + } + + int32_sort(A,n); + /* A = id<<16+cp */ + for (x = 0;x < n;++x) { + int32 cpx = (B[x]&~0xffff)|(A[x]&0xffff); + B[x] = int32_min(B[x],cpx); + } + } + for (x = 0;x < n;++x) B[x] &= 0xffff; + } + + for (x = 0;x < n;++x) A[x] = (((int32)pi[x])<<16)+x; + int32_sort(A,n); /* A = (id<<16)+pi^(-1) */ + + for (j = 0;j < n/2;++j) { + long long x = 2*j; + int32 fj = B[x]&1; /* f[j] */ + int32 Fx = x+fj; /* F[x] */ + int32 Fx1 = Fx^1; /* F[x+1] */ + + out[pos>>3] ^= fj<<(pos&7); + pos += step; + + B[x] = (A[x]<<16)|Fx; + B[x+1] = (A[x+1]<<16)|Fx1; + } + /* B = (pi^(-1)<<16)+F */ + + int32_sort(B,n); /* B = (id<<16)+F(pi) */ + + pos += (2*w-3)*step*(n/2); + + for (k = 0;k < n/2;++k) { + long long y = 2*k; + int32 lk = B[y]&1; /* l[k] */ + int32 Ly = y+lk; /* L[y] */ + int32 Ly1 = Ly^1; /* L[y+1] */ + + out[pos>>3] ^= lk<<(pos&7); + pos += step; + + A[y] = (Ly<<16)|(B[y]&0xffff); + A[y+1] = (Ly1<<16)|(B[y+1]&0xffff); + } + /* A = (L<<16)+F(pi) */ + + int32_sort(A,n); /* A = (id<<16)+F(pi(L)) = (id<<16)+M */ + + pos -= (2*w-2)*step*(n/2); + + for (j = 0;j < n/2;++j) { + q[j] = (A[2*j]&0xffff)>>1; + q[j+n/2] = (A[2*j+1]&0xffff)>>1; + } + + cbrecursion(out,pos,step*2,q,w-1,n/2,temp); + cbrecursion(out,pos+step,step*2,q+n/2,w-1,n/2,temp); +} + +/* input: p, an array of int16 */ +/* input: n, length of p */ +/* input: s, meaning that stride-2^s cswaps are performed */ +/* input: cb, the control bits */ +/* output: the result of apply the control bits to p */ +static void layer(int16_t *p, const unsigned char *cb, int s, int n) +{ + int i, j; + int stride = 1 << s; + int index = 0; + int16_t d, m; + + for (i = 0; i < n; i += stride*2) + { + for (j = 0; j < stride; j++) + { + d = p[ i+j ] ^ p[ i+j+stride ]; + m = (cb[ index >> 3 ] >> (index & 7)) & 1; + m = -m; + d &= m; + p[ i+j ] ^= d; + p[ i+j+stride ] ^= d; + index++; + } + } +} + +/* parameters: 1 <= w <= 14; n = 2^w */ +/* input: permutation pi of {0,1,...,n-1} */ +/* output: (2m-1)n/2 control bits at positions 0,1,... */ +/* output position pos is by definition 1&(out[pos/8]>>(pos&7)) */ +void controlbitsfrompermutation(unsigned char *out,const int16 *pi,long long w,long long n) +{ + int32 temp[2*n]; + int16 pi_test[n], diff; + int i; + unsigned char *ptr; + + while (1) + { + memset(out,0,(((2*w-1)*n/2)+7)/8); + cbrecursion(out,0,1,pi,w,n,temp); + + // check for correctness + + for (i = 0; i < n; i++) + pi_test[i] = i; + + ptr = out; + for (i = 0; i < w; i++) + { + layer(pi_test, ptr, i, n); + ptr += n >> 4; + } + + for (i = w-2; i >= 0; i--) + { + layer(pi_test, ptr, i, n); + ptr += n >> 4; + } + + diff = 0; + for (i = 0; i < n; i++) + diff |= pi[i] ^ pi_test[i]; + + diff = crypto_int16_nonzero_mask(diff); + crypto_declassify(&diff,sizeof diff); + if (diff == 0) + break; + } +} + diff --git a/deps/mceliece/kem/mceliece348864/controlbits.h b/deps/mceliece/kem/mceliece348864/controlbits.h new file mode 100644 index 0000000..8ddd210 --- /dev/null +++ b/deps/mceliece/kem/mceliece348864/controlbits.h @@ -0,0 +1,14 @@ +/* This file is for implementing the Nassimi-Sahni algorithm */ +/* See David Nassimi, Sartaj Sahni "Parallel algorithms to set up the Benes permutationnetwork" */ +/* See also https://cr.yp.to/papers/controlbits-20200923.pdf */ + +#ifndef CONTROLBITS_H +#define CONTROLBITS_H + +#define controlbitsfrompermutation CRYPTO_NAMESPACE(controlbitsfrompermutation) + +#include + +extern void controlbitsfrompermutation(unsigned char *,const int16_t *,long long,long long); + +#endif diff --git a/deps/mceliece/kem/mceliece348864/crypto_hash.h b/deps/mceliece/kem/mceliece348864/crypto_hash.h new file mode 100644 index 0000000..b7c1086 --- /dev/null +++ b/deps/mceliece/kem/mceliece348864/crypto_hash.h @@ -0,0 +1,10 @@ +/* This file uses SHAKE256 implemented in the Keccak Code Package */ + +#include "../../mceliece_externals.h" + +#define crypto_hash_32b(out,in,inlen) \ + SHAKE256(out,32,in,inlen) + +#define shake(out,outlen,in,inlen) \ + SHAKE256(out,outlen,in,inlen) + diff --git a/deps/mceliece/kem/mceliece348864/crypto_kem.h b/deps/mceliece/kem/mceliece348864/crypto_kem.h new file mode 100644 index 0000000..2fb3f59 --- /dev/null +++ b/deps/mceliece/kem/mceliece348864/crypto_kem.h @@ -0,0 +1,15 @@ +#ifndef crypto_kem_H +#define crypto_kem_H + +#include "crypto_kem_mceliece348864.h" + +#define crypto_kem_keypair crypto_kem_mceliece348864_keypair +#define crypto_kem_enc crypto_kem_mceliece348864_enc +#define crypto_kem_dec crypto_kem_mceliece348864_dec +#define crypto_kem_PUBLICKEYBYTES crypto_kem_mceliece348864_PUBLICKEYBYTES +#define crypto_kem_SECRETKEYBYTES crypto_kem_mceliece348864_SECRETKEYBYTES +#define crypto_kem_BYTES crypto_kem_mceliece348864_BYTES +#define crypto_kem_CIPHERTEXTBYTES crypto_kem_mceliece348864_CIPHERTEXTBYTES +#define crypto_kem_PRIMITIVE "mceliece348864" + +#endif diff --git a/deps/mceliece/kem/mceliece348864/crypto_kem_mceliece348864.h b/deps/mceliece/kem/mceliece348864/crypto_kem_mceliece348864.h new file mode 100644 index 0000000..ab61730 --- /dev/null +++ b/deps/mceliece/kem/mceliece348864/crypto_kem_mceliece348864.h @@ -0,0 +1,28 @@ +#ifndef crypto_kem_mceliece348864_H +#define crypto_kem_mceliece348864_H + +#define crypto_kem_mceliece348864_ref_PUBLICKEYBYTES 261120 +#define crypto_kem_mceliece348864_ref_SECRETKEYBYTES 6492 +#define crypto_kem_mceliece348864_ref_CIPHERTEXTBYTES 96 +#define crypto_kem_mceliece348864_ref_BYTES 32 + + +#ifdef __cplusplus +extern "C" { +#endif +extern int crypto_kem_mceliece348864_ref_keypair(unsigned char *,unsigned char *); +extern int crypto_kem_mceliece348864_ref_enc(unsigned char *,unsigned char *,const unsigned char *); +extern int crypto_kem_mceliece348864_ref_dec(unsigned char *,const unsigned char *,const unsigned char *); +#ifdef __cplusplus +} +#endif + +#define crypto_kem_mceliece348864_keypair crypto_kem_mceliece348864_ref_keypair +#define crypto_kem_mceliece348864_enc crypto_kem_mceliece348864_ref_enc +#define crypto_kem_mceliece348864_dec crypto_kem_mceliece348864_ref_dec +#define crypto_kem_mceliece348864_PUBLICKEYBYTES crypto_kem_mceliece348864_ref_PUBLICKEYBYTES +#define crypto_kem_mceliece348864_SECRETKEYBYTES crypto_kem_mceliece348864_ref_SECRETKEYBYTES +#define crypto_kem_mceliece348864_BYTES crypto_kem_mceliece348864_ref_BYTES +#define crypto_kem_mceliece348864_CIPHERTEXTBYTES crypto_kem_mceliece348864_ref_CIPHERTEXTBYTES + +#endif diff --git a/deps/mceliece/kem/mceliece348864/decrypt.c b/deps/mceliece/kem/mceliece348864/decrypt.c new file mode 100644 index 0000000..c4cc6de --- /dev/null +++ b/deps/mceliece/kem/mceliece348864/decrypt.c @@ -0,0 +1,93 @@ +/* + This file is for Niederreiter decryption +*/ + +#include +#include "decrypt.h" + +#include "params.h" +#include "benes.h" +#include "util.h" +#include "synd.h" +#include "root.h" +#include "gf.h" +#include "bm.h" + +/* Niederreiter decryption with the Berlekamp decoder */ +/* intput: sk, secret key */ +/* c, ciphertext */ +/* output: e, error vector */ +/* return: 0 for success; 1 for failure */ +int decrypt(unsigned char *e, const unsigned char *sk, const unsigned char *c) +{ + int i, w = 0; + uint16_t check; + + unsigned char r[ SYS_N/8 ]; + + gf g[ SYS_T+1 ]; + gf L[ SYS_N ]; + + gf s[ SYS_T*2 ]; + gf s_cmp[ SYS_T*2 ]; + gf locator[ SYS_T+1 ]; + gf images[ SYS_N ]; + + gf t; + + // + + for (i = 0; i < SYND_BYTES; i++) r[i] = c[i]; + for (i = SYND_BYTES; i < SYS_N/8; i++) r[i] = 0; + + for (i = 0; i < SYS_T; i++) { g[i] = load_gf(sk); sk += 2; } g[ SYS_T ] = 1; + + support_gen(L, sk); + + synd(s, g, L, r); + + bm(locator, s); + + root(images, locator, L); + + // + + for (i = 0; i < SYS_N/8; i++) + e[i] = 0; + + for (i = 0; i < SYS_N; i++) + { + t = gf_iszero(images[i]) & 1; + + e[ i/8 ] |= t << (i%8); + w += t; + + } + +#ifdef KAT + { + int k; + printf("decrypt e: positions"); + for (k = 0;k < SYS_N;++k) + if (e[k/8] & (1 << (k&7))) + printf(" %d",k); + printf("\n"); + } +#endif + + synd(s_cmp, g, L, e); + + // + + check = w; + check ^= SYS_T; + + for (i = 0; i < SYS_T*2; i++) + check |= s[i] ^ s_cmp[i]; + + check -= 1; + check >>= 15; + + return check ^ 1; +} + diff --git a/deps/mceliece/kem/mceliece348864/decrypt.h b/deps/mceliece/kem/mceliece348864/decrypt.h new file mode 100644 index 0000000..266a5cd --- /dev/null +++ b/deps/mceliece/kem/mceliece348864/decrypt.h @@ -0,0 +1,12 @@ +/* + This file is for Nieddereiter decryption +*/ + +#ifndef DECRYPT_H +#define DECRYPT_H +#define decrypt CRYPTO_NAMESPACE(decrypt) + +int decrypt(unsigned char *, const unsigned char *, const unsigned char *); + +#endif + diff --git a/deps/mceliece/kem/mceliece348864/encrypt.c b/deps/mceliece/kem/mceliece348864/encrypt.c new file mode 100644 index 0000000..4823d2f --- /dev/null +++ b/deps/mceliece/kem/mceliece348864/encrypt.c @@ -0,0 +1,161 @@ +/* + This file is for Niederreiter encryption +*/ + +#include "encrypt.h" + +#include "util.h" +#include "params.h" +#include "randombytes.h" + +#include +#include +#include +#include + +#include "gf.h" +#include "crypto_declassify.h" +#include "crypto_uint16.h" +#include "crypto_uint32.h" + +static inline crypto_uint16 uint16_is_smaller_declassify(uint16_t t,uint16_t u) +{ + crypto_uint16 mask = crypto_uint16_smaller_mask(t,u); + crypto_declassify(&mask,sizeof mask); + return mask; +} + +static inline crypto_uint32 uint32_is_equal_declassify(uint32_t t,uint32_t u) +{ + crypto_uint32 mask = crypto_uint32_equal_mask(t,u); + crypto_declassify(&mask,sizeof mask); + return mask; +} + +static inline unsigned char same_mask(uint16_t x, uint16_t y) +{ + uint32_t mask; + + mask = x ^ y; + mask -= 1; + mask >>= 31; + mask = -mask; + + return mask & 0xFF; +} + +/* output: e, an error vector of weight t */ +static void gen_e(unsigned char *e) +{ + int i, j, eq, count; + + union + { + uint16_t nums[ SYS_T*2 ]; + unsigned char bytes[ SYS_T*2 * sizeof(uint16_t) ]; + } buf; + + uint16_t ind[ SYS_T ]; + unsigned char mask; + unsigned char val[ SYS_T ]; + + while (1) + { + randombytes(buf.bytes, sizeof(buf)); + + for (i = 0; i < SYS_T*2; i++) + buf.nums[i] = load_gf(buf.bytes + i*2); + + // moving and counting indices in the correct range + + count = 0; + for (i = 0; i < SYS_T*2 && count < SYS_T; i++) + if (uint16_is_smaller_declassify(buf.nums[i],SYS_N)) + ind[ count++ ] = buf.nums[i]; + + if (count < SYS_T) continue; + + // check for repetition + + eq = 0; + + for (i = 1; i < SYS_T; i++) + for (j = 0; j < i; j++) + if (uint32_is_equal_declassify(ind[i],ind[j])) + eq = 1; + + if (eq == 0) + break; + } + + for (j = 0; j < SYS_T; j++) + val[j] = 1 << (ind[j] & 7); + + for (i = 0; i < SYS_N/8; i++) + { + e[i] = 0; + + for (j = 0; j < SYS_T; j++) + { + mask = same_mask(i, (ind[j] >> 3)); + + e[i] |= val[j] & mask; + } + } +} + +/* input: public key pk, error vector e */ +/* output: syndrome s */ +static void syndrome(unsigned char *s, const unsigned char *pk, unsigned char *e) +{ + unsigned char b, row[SYS_N/8]; + const unsigned char *pk_ptr = pk; + + int i, j; + + for (i = 0; i < SYND_BYTES; i++) + s[i] = 0; + + for (i = 0; i < PK_NROWS; i++) + { + for (j = 0; j < SYS_N/8; j++) + row[j] = 0; + + for (j = 0; j < PK_ROW_BYTES; j++) + row[ SYS_N/8 - PK_ROW_BYTES + j ] = pk_ptr[j]; + + row[i/8] |= 1 << (i%8); + + b = 0; + for (j = 0; j < SYS_N/8; j++) + b ^= row[j] & e[j]; + + b ^= b >> 4; + b ^= b >> 2; + b ^= b >> 1; + b &= 1; + + s[ i/8 ] |= (b << (i%8)); + + pk_ptr += PK_ROW_BYTES; + } +} + +void encrypt(unsigned char *s, const unsigned char *pk, unsigned char *e) +{ + gen_e(e); + +#ifdef KAT + { + int k; + printf("encrypt e: positions"); + for (k = 0;k < SYS_N;++k) + if (e[k/8] & (1 << (k&7))) + printf(" %d",k); + printf("\n"); + } +#endif + + syndrome(s, pk, e); +} + diff --git a/deps/mceliece/kem/mceliece348864/encrypt.h b/deps/mceliece/kem/mceliece348864/encrypt.h new file mode 100644 index 0000000..8edd7a6 --- /dev/null +++ b/deps/mceliece/kem/mceliece348864/encrypt.h @@ -0,0 +1,12 @@ +/* + This file is for Niederreiter encryption +*/ + +#ifndef ENCRYPT_H +#define ENCRYPT_H +#define encrypt CRYPTO_NAMESPACE(encrypt) + +void encrypt(unsigned char *, const unsigned char *, unsigned char *); + +#endif + diff --git a/deps/mceliece/kem/mceliece348864/gf.c b/deps/mceliece/kem/mceliece348864/gf.c new file mode 100644 index 0000000..5284a41 --- /dev/null +++ b/deps/mceliece/kem/mceliece348864/gf.c @@ -0,0 +1,141 @@ +/* + This file is for functions for field arithmetic +*/ + +#include "gf.h" + +#include "params.h" + +gf gf_iszero(gf a) +{ + uint32_t t = a; + + t -= 1; + t >>= 19; + + return (gf) t; +} + +gf gf_add(gf in0, gf in1) +{ + return in0 ^ in1; +} + +gf gf_mul(gf in0, gf in1) +{ + int i; + + uint32_t tmp; + uint32_t t0; + uint32_t t1; + uint32_t t; + + t0 = in0; + t1 = in1; + + tmp = t0 * (t1 & 1); + + for (i = 1; i < GFBITS; i++) + tmp ^= (t0 * (t1 & (1 << i))); + + t = tmp & 0x7FC000; + tmp ^= t >> 9; + tmp ^= t >> 12; + + t = tmp & 0x3000; + tmp ^= t >> 9; + tmp ^= t >> 12; + + return tmp & ((1 << GFBITS)-1); +} + +/* input: field element in */ +/* return: in^2 */ +static inline gf gf_sq(gf in) +{ + const uint32_t B[] = {0x55555555, 0x33333333, 0x0F0F0F0F, 0x00FF00FF}; + + uint32_t x = in; + uint32_t t; + + x = (x | (x << 8)) & B[3]; + x = (x | (x << 4)) & B[2]; + x = (x | (x << 2)) & B[1]; + x = (x | (x << 1)) & B[0]; + + t = x & 0x7FC000; + x ^= t >> 9; + x ^= t >> 12; + + t = x & 0x3000; + x ^= t >> 9; + x ^= t >> 12; + + return x & ((1 << GFBITS)-1); +} + +gf gf_inv(gf in) +{ + gf tmp_11; + gf tmp_1111; + + gf out = in; + + out = gf_sq(out); + tmp_11 = gf_mul(out, in); // 11 + + out = gf_sq(tmp_11); + out = gf_sq(out); + tmp_1111 = gf_mul(out, tmp_11); // 1111 + + out = gf_sq(tmp_1111); + out = gf_sq(out); + out = gf_sq(out); + out = gf_sq(out); + out = gf_mul(out, tmp_1111); // 11111111 + + out = gf_sq(out); + out = gf_sq(out); + out = gf_mul(out, tmp_11); // 1111111111 + + out = gf_sq(out); + out = gf_mul(out, in); // 11111111111 + + return gf_sq(out); // 111111111110 +} + +/* input: field element den, num */ +/* return: (num/den) */ +gf gf_frac(gf den, gf num) +{ + return gf_mul(gf_inv(den), num); +} + +/* input: in0, in1 in GF((2^m)^t)*/ +/* output: out = in0*in1 */ +void GF_mul(gf *out, gf *in0, gf *in1) +{ + int i, j; + + gf prod[ SYS_T*2-1 ]; + + for (i = 0; i < SYS_T*2-1; i++) + prod[i] = 0; + + for (i = 0; i < SYS_T; i++) + for (j = 0; j < SYS_T; j++) + prod[i+j] ^= gf_mul(in0[i], in1[j]); + + // + + for (i = (SYS_T-1)*2; i >= SYS_T; i--) + { + prod[i - SYS_T + 3] ^= prod[i]; + prod[i - SYS_T + 1] ^= prod[i]; + prod[i - SYS_T + 0] ^= gf_mul(prod[i], (gf) 2); + } + + for (i = 0; i < SYS_T; i++) + out[i] = prod[i]; +} + diff --git a/deps/mceliece/kem/mceliece348864/gf.h b/deps/mceliece/kem/mceliece348864/gf.h new file mode 100644 index 0000000..f62209d --- /dev/null +++ b/deps/mceliece/kem/mceliece348864/gf.h @@ -0,0 +1,27 @@ +/* + This file is for functions for field arithmetic +*/ + +#ifndef GF_H +#define GF_H +#define gf_add CRYPTO_NAMESPACE(gf_add) +#define gf_frac CRYPTO_NAMESPACE(gf_frac) +#define gf_inv CRYPTO_NAMESPACE(gf_inv) +#define gf_iszero CRYPTO_NAMESPACE(gf_iszero) +#define gf_mul CRYPTO_NAMESPACE(gf_mul) +#define GF_mul CRYPTO_NAMESPACE(GF_mul) + +#include + +typedef uint16_t gf; + +gf gf_iszero(gf); +gf gf_add(gf, gf); +gf gf_mul(gf, gf); +gf gf_frac(gf, gf); +gf gf_inv(gf); + +void GF_mul(gf *, gf *, gf *); + +#endif + diff --git a/deps/mceliece/kem/mceliece348864/int32_sort.h b/deps/mceliece/kem/mceliece348864/int32_sort.h new file mode 100644 index 0000000..a431af2 --- /dev/null +++ b/deps/mceliece/kem/mceliece348864/int32_sort.h @@ -0,0 +1,46 @@ +#ifndef int32_sort_h +#define int32_sort_h + +#define int32_sort CRYPTO_NAMESPACE(int32_sort) + +#include + +#define int32_MINMAX(a,b) \ +do { \ + int32_t ab = b ^ a; \ + int32_t c = b - a; \ + c ^= ab & (c ^ b); \ + c >>= 31; \ + c &= ab; \ + a ^= c; \ + b ^= c; \ +} while(0) + +static void int32_sort(int32_t *x,long long n) +{ + long long top,p,q,r,i; + + if (n < 2) return; + top = 1; + while (top < n - top) top += top; + + for (p = top;p > 0;p >>= 1) { + for (i = 0;i < n - p;++i) + if (!(i & p)) + int32_MINMAX(x[i],x[i+p]); + i = 0; + for (q = top;q > p;q >>= 1) { + for (;i < n - q;++i) { + if (!(i & p)) { + int32_t a = x[i + p]; + for (r = q;r > p;r >>= 1) + int32_MINMAX(a,x[i+r]); + x[i + p] = a; + } + } + } + } +} + +#endif + diff --git a/deps/mceliece/kem/mceliece348864/operations.c b/deps/mceliece/kem/mceliece348864/operations.c new file mode 100644 index 0000000..d05e774 --- /dev/null +++ b/deps/mceliece/kem/mceliece348864/operations.c @@ -0,0 +1,146 @@ +#include "operations.h" + +#include "controlbits.h" +#include "randombytes.h" +#include "crypto_hash.h" +#include "encrypt.h" +#include "decrypt.h" +#include "params.h" +#include "sk_gen.h" +#include "pk_gen.h" +#include "util.h" + +#include +#include + +int crypto_kem_enc( + unsigned char *c, + unsigned char *key, + const unsigned char *pk +) +{ + unsigned char e[ SYS_N/8 ]; + unsigned char one_ec[ 1 + SYS_N/8 + SYND_BYTES ] = {1}; + + // + + encrypt(c, pk, e); + + memcpy(one_ec + 1, e, SYS_N/8); + memcpy(one_ec + 1 + SYS_N/8, c, SYND_BYTES); + + crypto_hash_32b(key, one_ec, sizeof(one_ec)); + + return 0; +} + +int crypto_kem_dec( + unsigned char *key, + const unsigned char *c, + const unsigned char *sk +) +{ + int i; + + unsigned char ret_decrypt = 0; + + uint16_t m; + + unsigned char e[ SYS_N/8 ]; + unsigned char preimage[ 1 + SYS_N/8 + SYND_BYTES ]; + unsigned char *x = preimage; + const unsigned char *s = sk + 40 + IRR_BYTES + COND_BYTES; + + // + + ret_decrypt = decrypt(e, sk + 40, c); + + m = ret_decrypt; + m -= 1; + m >>= 8; + + *x++ = m & 1; + for (i = 0; i < SYS_N/8; i++) + *x++ = (~m & s[i]) | (m & e[i]); + + for (i = 0; i < SYND_BYTES; i++) + *x++ = c[i]; + + crypto_hash_32b(key, preimage, sizeof(preimage)); + + return 0; +} + +int crypto_kem_keypair +( + unsigned char *pk, + unsigned char *sk +) +{ + int i; + unsigned char seed[ 33 ] = {64}; + unsigned char r[ SYS_N/8 + (1 << GFBITS)*sizeof(uint32_t) + SYS_T*2 + 32 ]; + unsigned char *rp, *skp; + + gf f[ SYS_T ]; // element in GF(2^mt) + gf irr[ SYS_T ]; // Goppa polynomial + uint32_t perm[ 1 << GFBITS ]; // random permutation as 32-bit integers + int16_t pi[ 1 << GFBITS ]; // random permutation + + randombytes(seed+1, 32); + + while (1) + { + rp = &r[ sizeof(r)-32 ]; + skp = sk; + + // expanding and updating the seed + + shake(r, sizeof(r), seed, 33); + memcpy(skp, seed+1, 32); + skp += 32 + 8; + memcpy(seed+1, &r[ sizeof(r)-32 ], 32); + + // generating irreducible polynomial + + rp -= sizeof(f); + + for (i = 0; i < SYS_T; i++) + f[i] = load_gf(rp + i*2); + + if (genpoly_gen(irr, f)) + continue; + + for (i = 0; i < SYS_T; i++) + store_gf(skp + i*2, irr[i]); + + skp += IRR_BYTES; + + // generating permutation + + rp -= sizeof(perm); + + for (i = 0; i < (1 << GFBITS); i++) + perm[i] = load4(rp + i*4); + + if (pk_gen(pk, skp - IRR_BYTES, perm, pi)) + continue; + + controlbitsfrompermutation(skp, pi, GFBITS, 1 << GFBITS); + skp += COND_BYTES; + + // storing the random string s + + rp -= SYS_N/8; + memcpy(skp, rp, SYS_N/8); + + // storing positions of the 32 pivots + + store8(sk + 32, 0xFFFFFFFF); + + break; + } + + return 0; +} + diff --git a/deps/mceliece/kem/mceliece348864/operations.h b/deps/mceliece/kem/mceliece348864/operations.h new file mode 100644 index 0000000..bf65502 --- /dev/null +++ b/deps/mceliece/kem/mceliece348864/operations.h @@ -0,0 +1,25 @@ +#ifndef OPERATIONS_H +#define OPERATIONS_H + +#include "crypto_kem.h" + +int crypto_kem_enc( + unsigned char *c, + unsigned char *key, + const unsigned char *pk +); + +int crypto_kem_dec( + unsigned char *key, + const unsigned char *c, + const unsigned char *sk +); + +int crypto_kem_keypair +( + unsigned char *pk, + unsigned char *sk +); + +#endif + diff --git a/deps/mceliece/kem/mceliece348864/params.h b/deps/mceliece/kem/mceliece348864/params.h new file mode 100644 index 0000000..7bd8e44 --- /dev/null +++ b/deps/mceliece/kem/mceliece348864/params.h @@ -0,0 +1,20 @@ +#ifndef PARAMS_H +#define PARAMS_H + +#define GFBITS 12 +#define SYS_N 3488 +#define SYS_T 64 + +#define COND_BYTES ((1 << (GFBITS-4))*(2*GFBITS - 1)) +#define IRR_BYTES (SYS_T * 2) + +#define PK_NROWS (SYS_T*GFBITS) +#define PK_NCOLS (SYS_N - PK_NROWS) +#define PK_ROW_BYTES ((PK_NCOLS + 7)/8) + +#define SYND_BYTES ((PK_NROWS + 7)/8) + +#define GFMASK ((1 << GFBITS) - 1) + +#endif + diff --git a/deps/mceliece/kem/mceliece348864/pk_gen.c b/deps/mceliece/kem/mceliece348864/pk_gen.c new file mode 100644 index 0000000..d42ab25 --- /dev/null +++ b/deps/mceliece/kem/mceliece348864/pk_gen.c @@ -0,0 +1,151 @@ +/* + This file is for public-key generation +*/ + +#include +#include +#include +#include + +#include "controlbits.h" +#include "uint64_sort.h" +#include "pk_gen.h" +#include "params.h" +#include "benes.h" +#include "root.h" +#include "util.h" +#include "crypto_declassify.h" +#include "crypto_uint64.h" + +static crypto_uint64 uint64_is_equal_declassify(uint64_t t,uint64_t u) +{ + crypto_uint64 mask = crypto_uint64_equal_mask(t,u); + crypto_declassify(&mask,sizeof mask); + return mask; +} + +static crypto_uint64 uint64_is_zero_declassify(uint64_t t) +{ + crypto_uint64 mask = crypto_uint64_zero_mask(t); + crypto_declassify(&mask,sizeof mask); + return mask; +} + +/* input: secret key sk */ +/* output: public key pk */ +int pk_gen(unsigned char * pk, unsigned char * sk, uint32_t * perm, int16_t * pi) +{ + int i, j, k; + int row, c; + + uint64_t buf[ 1 << GFBITS ]; + + unsigned char mat[ PK_NROWS ][ SYS_N/8 ]; + unsigned char mask; + unsigned char b; + + gf g[ SYS_T+1 ]; // Goppa polynomial + gf L[ SYS_N ]; // support + gf inv[ SYS_N ]; + + // + + g[ SYS_T ] = 1; + + for (i = 0; i < SYS_T; i++) { g[i] = load_gf(sk); sk += 2; } + + for (i = 0; i < (1 << GFBITS); i++) + { + buf[i] = perm[i]; + buf[i] <<= 31; + buf[i] |= i; + } + + uint64_sort(buf, 1 << GFBITS); + + for (i = 1; i < (1 << GFBITS); i++) + if (uint64_is_equal_declassify(buf[i-1] >> 31,buf[i] >> 31)) + return -1; + + for (i = 0; i < (1 << GFBITS); i++) pi[i] = buf[i] & GFMASK; + for (i = 0; i < SYS_N; i++) L[i] = bitrev(pi[i]); + + // filling the matrix + + root(inv, g, L); + + for (i = 0; i < SYS_N; i++) + inv[i] = gf_inv(inv[i]); + + for (i = 0; i < PK_NROWS; i++) + for (j = 0; j < SYS_N/8; j++) + mat[i][j] = 0; + + for (i = 0; i < SYS_T; i++) + { + for (j = 0; j < SYS_N; j+=8) + for (k = 0; k < GFBITS; k++) + { + b = (inv[j+7] >> k) & 1; b <<= 1; + b |= (inv[j+6] >> k) & 1; b <<= 1; + b |= (inv[j+5] >> k) & 1; b <<= 1; + b |= (inv[j+4] >> k) & 1; b <<= 1; + b |= (inv[j+3] >> k) & 1; b <<= 1; + b |= (inv[j+2] >> k) & 1; b <<= 1; + b |= (inv[j+1] >> k) & 1; b <<= 1; + b |= (inv[j+0] >> k) & 1; + + mat[ i*GFBITS + k ][ j/8 ] = b; + } + + for (j = 0; j < SYS_N; j++) + inv[j] = gf_mul(inv[j], L[j]); + + } + + // gaussian elimination + + for (i = 0; i < (PK_NROWS + 7) / 8; i++) + for (j = 0; j < 8; j++) + { + row = i*8 + j; + + if (row >= PK_NROWS) + break; + + for (k = row + 1; k < PK_NROWS; k++) + { + mask = mat[ row ][ i ] ^ mat[ k ][ i ]; + mask >>= j; + mask &= 1; + mask = -mask; + + for (c = 0; c < SYS_N/8; c++) + mat[ row ][ c ] ^= mat[ k ][ c ] & mask; + } + + if ( uint64_is_zero_declassify((mat[ row ][ i ] >> j) & 1) ) // return if not systematic + { + return -1; + } + + for (k = 0; k < PK_NROWS; k++) + { + if (k != row) + { + mask = mat[ k ][ i ] >> j; + mask &= 1; + mask = -mask; + + for (c = 0; c < SYS_N/8; c++) + mat[ k ][ c ] ^= mat[ row ][ c ] & mask; + } + } + } + + for (i = 0; i < PK_NROWS; i++) + memcpy(pk + i*PK_ROW_BYTES, mat[i] + PK_NROWS/8, PK_ROW_BYTES); + + return 0; +} + diff --git a/deps/mceliece/kem/mceliece348864/pk_gen.h b/deps/mceliece/kem/mceliece348864/pk_gen.h new file mode 100644 index 0000000..eec43a7 --- /dev/null +++ b/deps/mceliece/kem/mceliece348864/pk_gen.h @@ -0,0 +1,14 @@ +/* + This file is for public-key generation +*/ + +#ifndef PK_GEN_H +#define PK_GEN_H +#define pk_gen CRYPTO_NAMESPACE(pk_gen) + +#include "gf.h" + +int pk_gen(unsigned char *, unsigned char *, uint32_t *, int16_t *); + +#endif + diff --git a/deps/mceliece/kem/mceliece348864/randombytes.h b/deps/mceliece/kem/mceliece348864/randombytes.h new file mode 100644 index 0000000..7e59351 --- /dev/null +++ b/deps/mceliece/kem/mceliece348864/randombytes.h @@ -0,0 +1 @@ +#include "../../mceliece_externals.h" diff --git a/deps/mceliece/kem/mceliece348864/root.c b/deps/mceliece/kem/mceliece348864/root.c new file mode 100644 index 0000000..1c1b634 --- /dev/null +++ b/deps/mceliece/kem/mceliece348864/root.c @@ -0,0 +1,38 @@ +/* + This file is for evaluating a polynomial at one or more field elements +*/ + +#include "root.h" +#include "params.h" +#include "gf.h" + +#include + +/* input: polynomial f and field element a */ +/* return f(a) */ +gf eval(gf *f, gf a) +{ + int i; + gf r; + + r = f[ SYS_T ]; + + for (i = SYS_T-1; i >= 0; i--) + { + r = gf_mul(r, a); + r = gf_add(r, f[i]); + } + + return r; +} + +/* input: polynomial f and list of field elements L */ +/* output: out = [ f(a) for a in L ] */ +void root(gf *out, gf *f, gf *L) +{ + int i; + + for (i = 0; i < SYS_N; i++) + out[i] = eval(f, L[i]); +} + diff --git a/deps/mceliece/kem/mceliece348864/root.h b/deps/mceliece/kem/mceliece348864/root.h new file mode 100644 index 0000000..42516e4 --- /dev/null +++ b/deps/mceliece/kem/mceliece348864/root.h @@ -0,0 +1,16 @@ +/* + This file is for evaluating a polynomial at one or more field elements +*/ + +#ifndef ROOT_H +#define ROOT_H +#define eval CRYPTO_NAMESPACE(eval) +#define root CRYPTO_NAMESPACE(root) + +#include "gf.h" + +gf eval(gf *, gf); +void root(gf *, gf *, gf *); + +#endif + diff --git a/deps/mceliece/kem/mceliece348864/sk_gen.c b/deps/mceliece/kem/mceliece348864/sk_gen.c new file mode 100644 index 0000000..340cc9a --- /dev/null +++ b/deps/mceliece/kem/mceliece348864/sk_gen.c @@ -0,0 +1,85 @@ +/* + This file is for secret-key generation +*/ + +#include "sk_gen.h" + +#include "randombytes.h" +#include "controlbits.h" +#include "params.h" +#include "util.h" +#include "gf.h" +#include "crypto_declassify.h" +#include "crypto_uint16.h" + +static inline crypto_uint16 gf_is_zero_declassify(gf t) +{ + crypto_uint16 mask = crypto_uint16_zero_mask(t); + crypto_declassify(&mask,sizeof mask); + return mask; +} + +/* input: f, element in GF((2^m)^t) */ +/* output: out, minimal polynomial of f */ +/* return: 0 for success and -1 for failure */ +int genpoly_gen(gf *out, gf *f) +{ + int i, j, k, c; + + gf mat[ SYS_T+1 ][ SYS_T ]; + gf mask, inv, t; + + // fill matrix + + mat[0][0] = 1; + + for (i = 1; i < SYS_T; i++) + mat[0][i] = 0; + + for (i = 0; i < SYS_T; i++) + mat[1][i] = f[i]; + + for (j = 2; j <= SYS_T; j++) + GF_mul(mat[j], mat[j-1], f); + + // gaussian + + for (j = 0; j < SYS_T; j++) + { + for (k = j + 1; k < SYS_T; k++) + { + mask = gf_iszero(mat[ j ][ j ]); + + for (c = j; c < SYS_T + 1; c++) + mat[ c ][ j ] ^= mat[ c ][ k ] & mask; + + } + + if ( gf_is_zero_declassify(mat[ j ][ j ]) ) // return if not systematic + { + return -1; + } + + inv = gf_inv(mat[j][j]); + + for (c = j; c < SYS_T + 1; c++) + mat[ c ][ j ] = gf_mul(mat[ c ][ j ], inv) ; + + for (k = 0; k < SYS_T; k++) + { + if (k != j) + { + t = mat[ j ][ k ]; + + for (c = j; c < SYS_T + 1; c++) + mat[ c ][ k ] ^= gf_mul(mat[ c ][ j ], t); + } + } + } + + for (i = 0; i < SYS_T; i++) + out[i] = mat[ SYS_T ][ i ]; + + return 0; +} + diff --git a/deps/mceliece/kem/mceliece348864/sk_gen.h b/deps/mceliece/kem/mceliece348864/sk_gen.h new file mode 100644 index 0000000..e319703 --- /dev/null +++ b/deps/mceliece/kem/mceliece348864/sk_gen.h @@ -0,0 +1,18 @@ +/* + This file is for secret-key generation +*/ + +#ifndef SK_GEN_H +#define SK_GEN_H +#define genpoly_gen CRYPTO_NAMESPACE(genpoly_gen) +#define perm_check CRYPTO_NAMESPACE(perm_check) + +#include "gf.h" + +#include + +int genpoly_gen(gf *, gf *); +int perm_check(uint32_t *); + +#endif + diff --git a/deps/mceliece/kem/mceliece348864/subroutines/crypto_declassify.h b/deps/mceliece/kem/mceliece348864/subroutines/crypto_declassify.h new file mode 100644 index 0000000..8d84209 --- /dev/null +++ b/deps/mceliece/kem/mceliece348864/subroutines/crypto_declassify.h @@ -0,0 +1,8 @@ +#ifndef crypto_declassify_h +#define crypto_declassify_h + +static void crypto_declassify(void *x,unsigned long long n) +{ +} + +#endif diff --git a/deps/mceliece/kem/mceliece348864/subroutines/crypto_int16.h b/deps/mceliece/kem/mceliece348864/subroutines/crypto_int16.h new file mode 100644 index 0000000..72bbf52 --- /dev/null +++ b/deps/mceliece/kem/mceliece348864/subroutines/crypto_int16.h @@ -0,0 +1,81 @@ +#ifndef crypto_int16_h +#define crypto_int16_h + +#include +typedef int16_t crypto_int16; + +static crypto_int16 crypto_int16_negative_mask(crypto_int16 crypto_int16_x) +{ + return crypto_int16_x >> 15; +} + +static crypto_int16 crypto_int16_nonzero_mask(crypto_int16 crypto_int16_x) +{ + return crypto_int16_negative_mask(crypto_int16_x) | crypto_int16_negative_mask(-crypto_int16_x); +} + +static crypto_int16 crypto_int16_zero_mask(crypto_int16 crypto_int16_x) +{ + return ~crypto_int16_nonzero_mask(crypto_int16_x); +} + +static crypto_int16 crypto_int16_positive_mask(crypto_int16 crypto_int16_x) +{ + crypto_int16 crypto_int16_z = -crypto_int16_x; + crypto_int16_z ^= crypto_int16_x & crypto_int16_z; + return crypto_int16_negative_mask(crypto_int16_z); +} + +static crypto_int16 crypto_int16_unequal_mask(crypto_int16 crypto_int16_x,crypto_int16 crypto_int16_y) +{ + crypto_int16 crypto_int16_xy = crypto_int16_x ^ crypto_int16_y; + return crypto_int16_nonzero_mask(crypto_int16_xy); +} + +static crypto_int16 crypto_int16_equal_mask(crypto_int16 crypto_int16_x,crypto_int16 crypto_int16_y) +{ + return ~crypto_int16_unequal_mask(crypto_int16_x,crypto_int16_y); +} + +static crypto_int16 crypto_int16_smaller_mask(crypto_int16 crypto_int16_x,crypto_int16 crypto_int16_y) +{ + crypto_int16 crypto_int16_xy = crypto_int16_x ^ crypto_int16_y; + crypto_int16 crypto_int16_z = crypto_int16_x - crypto_int16_y; + crypto_int16_z ^= crypto_int16_xy & (crypto_int16_z ^ crypto_int16_x); + return crypto_int16_negative_mask(crypto_int16_z); +} + +static crypto_int16 crypto_int16_min(crypto_int16 crypto_int16_x,crypto_int16 crypto_int16_y) +{ + crypto_int16 crypto_int16_xy = crypto_int16_y ^ crypto_int16_x; + crypto_int16 crypto_int16_z = crypto_int16_y - crypto_int16_x; + crypto_int16_z ^= crypto_int16_xy & (crypto_int16_z ^ crypto_int16_y); + crypto_int16_z = crypto_int16_negative_mask(crypto_int16_z); + crypto_int16_z &= crypto_int16_xy; + return crypto_int16_x ^ crypto_int16_z; +} + +static crypto_int16 crypto_int16_max(crypto_int16 crypto_int16_x,crypto_int16 crypto_int16_y) +{ + crypto_int16 crypto_int16_xy = crypto_int16_y ^ crypto_int16_x; + crypto_int16 crypto_int16_z = crypto_int16_y - crypto_int16_x; + crypto_int16_z ^= crypto_int16_xy & (crypto_int16_z ^ crypto_int16_y); + crypto_int16_z = crypto_int16_negative_mask(crypto_int16_z); + crypto_int16_z &= crypto_int16_xy; + return crypto_int16_y ^ crypto_int16_z; +} + +static void crypto_int16_minmax(crypto_int16 *crypto_int16_a,crypto_int16 *crypto_int16_b) +{ + crypto_int16 crypto_int16_x = *crypto_int16_a; + crypto_int16 crypto_int16_y = *crypto_int16_b; + crypto_int16 crypto_int16_xy = crypto_int16_y ^ crypto_int16_x; + crypto_int16 crypto_int16_z = crypto_int16_y - crypto_int16_x; + crypto_int16_z ^= crypto_int16_xy & (crypto_int16_z ^ crypto_int16_y); + crypto_int16_z = crypto_int16_negative_mask(crypto_int16_z); + crypto_int16_z &= crypto_int16_xy; + *crypto_int16_a = crypto_int16_x ^ crypto_int16_z; + *crypto_int16_b = crypto_int16_y ^ crypto_int16_z; +} + +#endif diff --git a/deps/mceliece/kem/mceliece348864/subroutines/crypto_int32.h b/deps/mceliece/kem/mceliece348864/subroutines/crypto_int32.h new file mode 100644 index 0000000..c22f735 --- /dev/null +++ b/deps/mceliece/kem/mceliece348864/subroutines/crypto_int32.h @@ -0,0 +1,81 @@ +#ifndef crypto_int32_h +#define crypto_int32_h + +#include +typedef int32_t crypto_int32; + +static crypto_int32 crypto_int32_negative_mask(crypto_int32 crypto_int32_x) +{ + return crypto_int32_x >> 31; +} + +static crypto_int32 crypto_int32_nonzero_mask(crypto_int32 crypto_int32_x) +{ + return crypto_int32_negative_mask(crypto_int32_x) | crypto_int32_negative_mask(-crypto_int32_x); +} + +static crypto_int32 crypto_int32_zero_mask(crypto_int32 crypto_int32_x) +{ + return ~crypto_int32_nonzero_mask(crypto_int32_x); +} + +static crypto_int32 crypto_int32_positive_mask(crypto_int32 crypto_int32_x) +{ + crypto_int32 crypto_int32_z = -crypto_int32_x; + crypto_int32_z ^= crypto_int32_x & crypto_int32_z; + return crypto_int32_negative_mask(crypto_int32_z); +} + +static crypto_int32 crypto_int32_unequal_mask(crypto_int32 crypto_int32_x,crypto_int32 crypto_int32_y) +{ + crypto_int32 crypto_int32_xy = crypto_int32_x ^ crypto_int32_y; + return crypto_int32_nonzero_mask(crypto_int32_xy); +} + +static crypto_int32 crypto_int32_equal_mask(crypto_int32 crypto_int32_x,crypto_int32 crypto_int32_y) +{ + return ~crypto_int32_unequal_mask(crypto_int32_x,crypto_int32_y); +} + +static crypto_int32 crypto_int32_smaller_mask(crypto_int32 crypto_int32_x,crypto_int32 crypto_int32_y) +{ + crypto_int32 crypto_int32_xy = crypto_int32_x ^ crypto_int32_y; + crypto_int32 crypto_int32_z = crypto_int32_x - crypto_int32_y; + crypto_int32_z ^= crypto_int32_xy & (crypto_int32_z ^ crypto_int32_x); + return crypto_int32_negative_mask(crypto_int32_z); +} + +static crypto_int32 crypto_int32_min(crypto_int32 crypto_int32_x,crypto_int32 crypto_int32_y) +{ + crypto_int32 crypto_int32_xy = crypto_int32_y ^ crypto_int32_x; + crypto_int32 crypto_int32_z = crypto_int32_y - crypto_int32_x; + crypto_int32_z ^= crypto_int32_xy & (crypto_int32_z ^ crypto_int32_y); + crypto_int32_z = crypto_int32_negative_mask(crypto_int32_z); + crypto_int32_z &= crypto_int32_xy; + return crypto_int32_x ^ crypto_int32_z; +} + +static crypto_int32 crypto_int32_max(crypto_int32 crypto_int32_x,crypto_int32 crypto_int32_y) +{ + crypto_int32 crypto_int32_xy = crypto_int32_y ^ crypto_int32_x; + crypto_int32 crypto_int32_z = crypto_int32_y - crypto_int32_x; + crypto_int32_z ^= crypto_int32_xy & (crypto_int32_z ^ crypto_int32_y); + crypto_int32_z = crypto_int32_negative_mask(crypto_int32_z); + crypto_int32_z &= crypto_int32_xy; + return crypto_int32_y ^ crypto_int32_z; +} + +static void crypto_int32_minmax(crypto_int32 *crypto_int32_a,crypto_int32 *crypto_int32_b) +{ + crypto_int32 crypto_int32_x = *crypto_int32_a; + crypto_int32 crypto_int32_y = *crypto_int32_b; + crypto_int32 crypto_int32_xy = crypto_int32_y ^ crypto_int32_x; + crypto_int32 crypto_int32_z = crypto_int32_y - crypto_int32_x; + crypto_int32_z ^= crypto_int32_xy & (crypto_int32_z ^ crypto_int32_y); + crypto_int32_z = crypto_int32_negative_mask(crypto_int32_z); + crypto_int32_z &= crypto_int32_xy; + *crypto_int32_a = crypto_int32_x ^ crypto_int32_z; + *crypto_int32_b = crypto_int32_y ^ crypto_int32_z; +} + +#endif diff --git a/deps/mceliece/kem/mceliece348864/subroutines/crypto_uint16.h b/deps/mceliece/kem/mceliece348864/subroutines/crypto_uint16.h new file mode 100644 index 0000000..f0ebbbf --- /dev/null +++ b/deps/mceliece/kem/mceliece348864/subroutines/crypto_uint16.h @@ -0,0 +1,76 @@ +#ifndef crypto_uint16_h +#define crypto_uint16_h + +#include +typedef uint16_t crypto_uint16; + +typedef int16_t crypto_uint16_signed; + +static crypto_uint16_signed crypto_uint16_signed_negative_mask(crypto_uint16_signed crypto_uint16_signed_x) +{ + return crypto_uint16_signed_x >> 15; +} + +static crypto_uint16 crypto_uint16_nonzero_mask(crypto_uint16 crypto_uint16_x) +{ + return crypto_uint16_signed_negative_mask(crypto_uint16_x) | crypto_uint16_signed_negative_mask(-crypto_uint16_x); +} + +static crypto_uint16 crypto_uint16_zero_mask(crypto_uint16 crypto_uint16_x) +{ + return ~crypto_uint16_nonzero_mask(crypto_uint16_x); +} + +static crypto_uint16 crypto_uint16_unequal_mask(crypto_uint16 crypto_uint16_x,crypto_uint16 crypto_uint16_y) +{ + crypto_uint16 crypto_uint16_xy = crypto_uint16_x ^ crypto_uint16_y; + return crypto_uint16_nonzero_mask(crypto_uint16_xy); +} + +static crypto_uint16 crypto_uint16_equal_mask(crypto_uint16 crypto_uint16_x,crypto_uint16 crypto_uint16_y) +{ + return ~crypto_uint16_unequal_mask(crypto_uint16_x,crypto_uint16_y); +} + +static crypto_uint16 crypto_uint16_smaller_mask(crypto_uint16 crypto_uint16_x,crypto_uint16 crypto_uint16_y) +{ + crypto_uint16 crypto_uint16_xy = crypto_uint16_x ^ crypto_uint16_y; + crypto_uint16 crypto_uint16_z = crypto_uint16_x - crypto_uint16_y; + crypto_uint16_z ^= crypto_uint16_xy & (crypto_uint16_z ^ crypto_uint16_x ^ (((crypto_uint16) 1) << 15)); + return crypto_uint16_signed_negative_mask(crypto_uint16_z); +} + +static crypto_uint16 crypto_uint16_min(crypto_uint16 crypto_uint16_x,crypto_uint16 crypto_uint16_y) +{ + crypto_uint16 crypto_uint16_xy = crypto_uint16_y ^ crypto_uint16_x; + crypto_uint16 crypto_uint16_z = crypto_uint16_y - crypto_uint16_x; + crypto_uint16_z ^= crypto_uint16_xy & (crypto_uint16_z ^ crypto_uint16_y ^ (((crypto_uint16) 1) << 15)); + crypto_uint16_z = crypto_uint16_signed_negative_mask(crypto_uint16_z); + crypto_uint16_z &= crypto_uint16_xy; + return crypto_uint16_x ^ crypto_uint16_z; +} + +static crypto_uint16 crypto_uint16_max(crypto_uint16 crypto_uint16_x,crypto_uint16 crypto_uint16_y) +{ + crypto_uint16 crypto_uint16_xy = crypto_uint16_y ^ crypto_uint16_x; + crypto_uint16 crypto_uint16_z = crypto_uint16_y - crypto_uint16_x; + crypto_uint16_z ^= crypto_uint16_xy & (crypto_uint16_z ^ crypto_uint16_y ^ (((crypto_uint16) 1) << 15)); + crypto_uint16_z = crypto_uint16_signed_negative_mask(crypto_uint16_z); + crypto_uint16_z &= crypto_uint16_xy; + return crypto_uint16_y ^ crypto_uint16_z; +} + +static void crypto_uint16_minmax(crypto_uint16 *crypto_uint16_a,crypto_uint16 *crypto_uint16_b) +{ + crypto_uint16 crypto_uint16_x = *crypto_uint16_a; + crypto_uint16 crypto_uint16_y = *crypto_uint16_b; + crypto_uint16 crypto_uint16_xy = crypto_uint16_y ^ crypto_uint16_x; + crypto_uint16 crypto_uint16_z = crypto_uint16_y - crypto_uint16_x; + crypto_uint16_z ^= crypto_uint16_xy & (crypto_uint16_z ^ crypto_uint16_y ^ (((crypto_uint16) 1) << 15)); + crypto_uint16_z = crypto_uint16_signed_negative_mask(crypto_uint16_z); + crypto_uint16_z &= crypto_uint16_xy; + *crypto_uint16_a = crypto_uint16_x ^ crypto_uint16_z; + *crypto_uint16_b = crypto_uint16_y ^ crypto_uint16_z; +} + +#endif diff --git a/deps/mceliece/kem/mceliece348864/subroutines/crypto_uint32.h b/deps/mceliece/kem/mceliece348864/subroutines/crypto_uint32.h new file mode 100644 index 0000000..3f39d62 --- /dev/null +++ b/deps/mceliece/kem/mceliece348864/subroutines/crypto_uint32.h @@ -0,0 +1,76 @@ +#ifndef crypto_uint32_h +#define crypto_uint32_h + +#include +typedef uint32_t crypto_uint32; + +typedef int32_t crypto_uint32_signed; + +static crypto_uint32_signed crypto_uint32_signed_negative_mask(crypto_uint32_signed crypto_uint32_signed_x) +{ + return crypto_uint32_signed_x >> 31; +} + +static crypto_uint32 crypto_uint32_nonzero_mask(crypto_uint32 crypto_uint32_x) +{ + return crypto_uint32_signed_negative_mask(crypto_uint32_x) | crypto_uint32_signed_negative_mask(-crypto_uint32_x); +} + +static crypto_uint32 crypto_uint32_zero_mask(crypto_uint32 crypto_uint32_x) +{ + return ~crypto_uint32_nonzero_mask(crypto_uint32_x); +} + +static crypto_uint32 crypto_uint32_unequal_mask(crypto_uint32 crypto_uint32_x,crypto_uint32 crypto_uint32_y) +{ + crypto_uint32 crypto_uint32_xy = crypto_uint32_x ^ crypto_uint32_y; + return crypto_uint32_nonzero_mask(crypto_uint32_xy); +} + +static crypto_uint32 crypto_uint32_equal_mask(crypto_uint32 crypto_uint32_x,crypto_uint32 crypto_uint32_y) +{ + return ~crypto_uint32_unequal_mask(crypto_uint32_x,crypto_uint32_y); +} + +static crypto_uint32 crypto_uint32_smaller_mask(crypto_uint32 crypto_uint32_x,crypto_uint32 crypto_uint32_y) +{ + crypto_uint32 crypto_uint32_xy = crypto_uint32_x ^ crypto_uint32_y; + crypto_uint32 crypto_uint32_z = crypto_uint32_x - crypto_uint32_y; + crypto_uint32_z ^= crypto_uint32_xy & (crypto_uint32_z ^ crypto_uint32_x ^ (((crypto_uint32) 1) << 31)); + return crypto_uint32_signed_negative_mask(crypto_uint32_z); +} + +static crypto_uint32 crypto_uint32_min(crypto_uint32 crypto_uint32_x,crypto_uint32 crypto_uint32_y) +{ + crypto_uint32 crypto_uint32_xy = crypto_uint32_y ^ crypto_uint32_x; + crypto_uint32 crypto_uint32_z = crypto_uint32_y - crypto_uint32_x; + crypto_uint32_z ^= crypto_uint32_xy & (crypto_uint32_z ^ crypto_uint32_y ^ (((crypto_uint32) 1) << 31)); + crypto_uint32_z = crypto_uint32_signed_negative_mask(crypto_uint32_z); + crypto_uint32_z &= crypto_uint32_xy; + return crypto_uint32_x ^ crypto_uint32_z; +} + +static crypto_uint32 crypto_uint32_max(crypto_uint32 crypto_uint32_x,crypto_uint32 crypto_uint32_y) +{ + crypto_uint32 crypto_uint32_xy = crypto_uint32_y ^ crypto_uint32_x; + crypto_uint32 crypto_uint32_z = crypto_uint32_y - crypto_uint32_x; + crypto_uint32_z ^= crypto_uint32_xy & (crypto_uint32_z ^ crypto_uint32_y ^ (((crypto_uint32) 1) << 31)); + crypto_uint32_z = crypto_uint32_signed_negative_mask(crypto_uint32_z); + crypto_uint32_z &= crypto_uint32_xy; + return crypto_uint32_y ^ crypto_uint32_z; +} + +static void crypto_uint32_minmax(crypto_uint32 *crypto_uint32_a,crypto_uint32 *crypto_uint32_b) +{ + crypto_uint32 crypto_uint32_x = *crypto_uint32_a; + crypto_uint32 crypto_uint32_y = *crypto_uint32_b; + crypto_uint32 crypto_uint32_xy = crypto_uint32_y ^ crypto_uint32_x; + crypto_uint32 crypto_uint32_z = crypto_uint32_y - crypto_uint32_x; + crypto_uint32_z ^= crypto_uint32_xy & (crypto_uint32_z ^ crypto_uint32_y ^ (((crypto_uint32) 1) << 31)); + crypto_uint32_z = crypto_uint32_signed_negative_mask(crypto_uint32_z); + crypto_uint32_z &= crypto_uint32_xy; + *crypto_uint32_a = crypto_uint32_x ^ crypto_uint32_z; + *crypto_uint32_b = crypto_uint32_y ^ crypto_uint32_z; +} + +#endif diff --git a/deps/mceliece/kem/mceliece348864/subroutines/crypto_uint64.h b/deps/mceliece/kem/mceliece348864/subroutines/crypto_uint64.h new file mode 100644 index 0000000..42e2be9 --- /dev/null +++ b/deps/mceliece/kem/mceliece348864/subroutines/crypto_uint64.h @@ -0,0 +1,76 @@ +#ifndef crypto_uint64_h +#define crypto_uint64_h + +#include +typedef uint64_t crypto_uint64; + +typedef int64_t crypto_uint64_signed; + +static crypto_uint64_signed crypto_uint64_signed_negative_mask(crypto_uint64_signed crypto_uint64_signed_x) +{ + return crypto_uint64_signed_x >> 63; +} + +static crypto_uint64 crypto_uint64_nonzero_mask(crypto_uint64 crypto_uint64_x) +{ + return crypto_uint64_signed_negative_mask(crypto_uint64_x) | crypto_uint64_signed_negative_mask(-crypto_uint64_x); +} + +static crypto_uint64 crypto_uint64_zero_mask(crypto_uint64 crypto_uint64_x) +{ + return ~crypto_uint64_nonzero_mask(crypto_uint64_x); +} + +static crypto_uint64 crypto_uint64_unequal_mask(crypto_uint64 crypto_uint64_x,crypto_uint64 crypto_uint64_y) +{ + crypto_uint64 crypto_uint64_xy = crypto_uint64_x ^ crypto_uint64_y; + return crypto_uint64_nonzero_mask(crypto_uint64_xy); +} + +static crypto_uint64 crypto_uint64_equal_mask(crypto_uint64 crypto_uint64_x,crypto_uint64 crypto_uint64_y) +{ + return ~crypto_uint64_unequal_mask(crypto_uint64_x,crypto_uint64_y); +} + +static crypto_uint64 crypto_uint64_smaller_mask(crypto_uint64 crypto_uint64_x,crypto_uint64 crypto_uint64_y) +{ + crypto_uint64 crypto_uint64_xy = crypto_uint64_x ^ crypto_uint64_y; + crypto_uint64 crypto_uint64_z = crypto_uint64_x - crypto_uint64_y; + crypto_uint64_z ^= crypto_uint64_xy & (crypto_uint64_z ^ crypto_uint64_x ^ (((crypto_uint64) 1) << 63)); + return crypto_uint64_signed_negative_mask(crypto_uint64_z); +} + +static crypto_uint64 crypto_uint64_min(crypto_uint64 crypto_uint64_x,crypto_uint64 crypto_uint64_y) +{ + crypto_uint64 crypto_uint64_xy = crypto_uint64_y ^ crypto_uint64_x; + crypto_uint64 crypto_uint64_z = crypto_uint64_y - crypto_uint64_x; + crypto_uint64_z ^= crypto_uint64_xy & (crypto_uint64_z ^ crypto_uint64_y ^ (((crypto_uint64) 1) << 63)); + crypto_uint64_z = crypto_uint64_signed_negative_mask(crypto_uint64_z); + crypto_uint64_z &= crypto_uint64_xy; + return crypto_uint64_x ^ crypto_uint64_z; +} + +static crypto_uint64 crypto_uint64_max(crypto_uint64 crypto_uint64_x,crypto_uint64 crypto_uint64_y) +{ + crypto_uint64 crypto_uint64_xy = crypto_uint64_y ^ crypto_uint64_x; + crypto_uint64 crypto_uint64_z = crypto_uint64_y - crypto_uint64_x; + crypto_uint64_z ^= crypto_uint64_xy & (crypto_uint64_z ^ crypto_uint64_y ^ (((crypto_uint64) 1) << 63)); + crypto_uint64_z = crypto_uint64_signed_negative_mask(crypto_uint64_z); + crypto_uint64_z &= crypto_uint64_xy; + return crypto_uint64_y ^ crypto_uint64_z; +} + +static void crypto_uint64_minmax(crypto_uint64 *crypto_uint64_a,crypto_uint64 *crypto_uint64_b) +{ + crypto_uint64 crypto_uint64_x = *crypto_uint64_a; + crypto_uint64 crypto_uint64_y = *crypto_uint64_b; + crypto_uint64 crypto_uint64_xy = crypto_uint64_y ^ crypto_uint64_x; + crypto_uint64 crypto_uint64_z = crypto_uint64_y - crypto_uint64_x; + crypto_uint64_z ^= crypto_uint64_xy & (crypto_uint64_z ^ crypto_uint64_y ^ (((crypto_uint64) 1) << 63)); + crypto_uint64_z = crypto_uint64_signed_negative_mask(crypto_uint64_z); + crypto_uint64_z &= crypto_uint64_xy; + *crypto_uint64_a = crypto_uint64_x ^ crypto_uint64_z; + *crypto_uint64_b = crypto_uint64_y ^ crypto_uint64_z; +} + +#endif diff --git a/deps/mceliece/kem/mceliece348864/synd.c b/deps/mceliece/kem/mceliece348864/synd.c new file mode 100644 index 0000000..c945647 --- /dev/null +++ b/deps/mceliece/kem/mceliece348864/synd.c @@ -0,0 +1,36 @@ +/* + This file is for syndrome computation +*/ + +#include "synd.h" + +#include "params.h" +#include "root.h" + +#include + +/* input: Goppa polynomial f, support L, received word r */ +/* output: out, the syndrome of length 2t */ +void synd(gf *out, gf *f, gf *L, unsigned char *r) +{ + int i, j; + gf e, e_inv, c; + + for (j = 0; j < 2*SYS_T; j++) + out[j] = 0; + + for (i = 0; i < SYS_N; i++) + { + c = (r[i/8] >> (i%8)) & 1; + + e = eval(f, L[i]); + e_inv = gf_inv(gf_mul(e,e)); + + for (j = 0; j < 2*SYS_T; j++) + { + out[j] = gf_add(out[j], gf_mul(e_inv, c)); + e_inv = gf_mul(e_inv, L[i]); + } + } +} + diff --git a/deps/mceliece/kem/mceliece348864/synd.h b/deps/mceliece/kem/mceliece348864/synd.h new file mode 100644 index 0000000..9331406 --- /dev/null +++ b/deps/mceliece/kem/mceliece348864/synd.h @@ -0,0 +1,14 @@ +/* + This file is for syndrome computation +*/ + +#ifndef SYND_H +#define SYND_H +#define synd CRYPTO_NAMESPACE(synd) + +#include "gf.h" + +void synd(gf *, gf *, gf *, unsigned char *); + +#endif + diff --git a/deps/mceliece/kem/mceliece348864/transpose.c b/deps/mceliece/kem/mceliece348864/transpose.c new file mode 100644 index 0000000..0da2bc5 --- /dev/null +++ b/deps/mceliece/kem/mceliece348864/transpose.c @@ -0,0 +1,43 @@ +/* + This file is for matrix transposition +*/ + +#include "transpose.h" + +#include + +/* input: in, a 64x64 matrix over GF(2) */ +/* output: out, transpose of in */ +void transpose_64x64(uint64_t * out, uint64_t * in) +{ + int i, j, s, d; + + uint64_t x, y; + uint64_t masks[6][2] = { + {0x5555555555555555, 0xAAAAAAAAAAAAAAAA}, + {0x3333333333333333, 0xCCCCCCCCCCCCCCCC}, + {0x0F0F0F0F0F0F0F0F, 0xF0F0F0F0F0F0F0F0}, + {0x00FF00FF00FF00FF, 0xFF00FF00FF00FF00}, + {0x0000FFFF0000FFFF, 0xFFFF0000FFFF0000}, + {0x00000000FFFFFFFF, 0xFFFFFFFF00000000} + }; + + for (i = 0; i < 64; i++) + out[i] = in[i]; + + for (d = 5; d >= 0; d--) + { + s = 1 << d; + + for (i = 0; i < 64; i += s*2) + for (j = i; j < i+s; j++) + { + x = (out[j] & masks[d][0]) | ((out[j+s] & masks[d][0]) << s); + y = ((out[j] & masks[d][1]) >> s) | (out[j+s] & masks[d][1]); + + out[j+0] = x; + out[j+s] = y; + } + } +} + diff --git a/deps/mceliece/kem/mceliece348864/transpose.h b/deps/mceliece/kem/mceliece348864/transpose.h new file mode 100644 index 0000000..31e5b96 --- /dev/null +++ b/deps/mceliece/kem/mceliece348864/transpose.h @@ -0,0 +1,14 @@ +/* + This file is for matrix transposition +*/ + +#ifndef TRANSPOSE_H +#define TRANSPOSE_H +#define transpose_64x64 CRYPTO_NAMESPACE(transpose_64x64) + +#include + +void transpose_64x64(uint64_t *, uint64_t *); + +#endif + diff --git a/deps/mceliece/kem/mceliece348864/uint64_sort.h b/deps/mceliece/kem/mceliece348864/uint64_sort.h new file mode 100644 index 0000000..2fb100c --- /dev/null +++ b/deps/mceliece/kem/mceliece348864/uint64_sort.h @@ -0,0 +1,45 @@ +#ifndef uint64_sort_h +#define uint64_sort_h + +#define int64_sort CRYPTO_NAMESPACE(int64_sort) + +#include + +#define uint64_MINMAX(a,b) \ +do { \ + uint64_t c = b - a; \ + c >>= 63; \ + c = -c; \ + c &= a ^ b; \ + a ^= c; \ + b ^= c; \ +} while(0) + +static void uint64_sort(uint64_t *x,long long n) +{ + long long top,p,q,r,i; + + if (n < 2) return; + top = 1; + while (top < n - top) top += top; + + for (p = top;p > 0;p >>= 1) { + for (i = 0;i < n - p;++i) + if (!(i & p)) + uint64_MINMAX(x[i],x[i+p]); + i = 0; + for (q = top;q > p;q >>= 1) { + for (;i < n - q;++i) { + if (!(i & p)) { + uint64_t a = x[i + p]; + for (r = q;r > p;r >>= 1) + uint64_MINMAX(a,x[i+r]); + x[i + p] = a; + } + } + } + } +} + +#endif + diff --git a/deps/mceliece/kem/mceliece348864/util.c b/deps/mceliece/kem/mceliece348864/util.c new file mode 100644 index 0000000..bb4c82a --- /dev/null +++ b/deps/mceliece/kem/mceliece348864/util.c @@ -0,0 +1,75 @@ +/* + This file is for loading/storing data in a little-endian fashion +*/ + +#include "util.h" + +#include "params.h" + +void store_gf(unsigned char *dest, gf a) +{ + dest[0] = a & 0xFF; + dest[1] = a >> 8; +} + +uint16_t load_gf(const unsigned char *src) +{ + uint16_t a; + + a = src[1]; + a <<= 8; + a |= src[0]; + + return a & GFMASK; +} + +uint32_t load4(const unsigned char * in) +{ + int i; + uint32_t ret = in[3]; + + for (i = 2; i >= 0; i--) + { + ret <<= 8; + ret |= in[i]; + } + + return ret; +} + +void store8(unsigned char *out, uint64_t in) +{ + out[0] = (in >> 0x00) & 0xFF; + out[1] = (in >> 0x08) & 0xFF; + out[2] = (in >> 0x10) & 0xFF; + out[3] = (in >> 0x18) & 0xFF; + out[4] = (in >> 0x20) & 0xFF; + out[5] = (in >> 0x28) & 0xFF; + out[6] = (in >> 0x30) & 0xFF; + out[7] = (in >> 0x38) & 0xFF; +} + +uint64_t load8(const unsigned char * in) +{ + int i; + uint64_t ret = in[7]; + + for (i = 6; i >= 0; i--) + { + ret <<= 8; + ret |= in[i]; + } + + return ret; +} + +gf bitrev(gf a) +{ + a = ((a & 0x00FF) << 8) | ((a & 0xFF00) >> 8); + a = ((a & 0x0F0F) << 4) | ((a & 0xF0F0) >> 4); + a = ((a & 0x3333) << 2) | ((a & 0xCCCC) >> 2); + a = ((a & 0x5555) << 1) | ((a & 0xAAAA) >> 1); + + return a >> 4; +} + diff --git a/deps/mceliece/kem/mceliece348864/util.h b/deps/mceliece/kem/mceliece348864/util.h new file mode 100644 index 0000000..5800430 --- /dev/null +++ b/deps/mceliece/kem/mceliece348864/util.h @@ -0,0 +1,28 @@ +/* + This file is for loading/storing data in a little-endian fashion +*/ + +#ifndef UTIL_H +#define UTIL_H +#define bitrev CRYPTO_NAMESPACE(bitrev) +#define load4 CRYPTO_NAMESPACE(load4) +#define load8 CRYPTO_NAMESPACE(load8) +#define load_gf CRYPTO_NAMESPACE(load_gf) +#define store8 CRYPTO_NAMESPACE(store8) +#define store_gf CRYPTO_NAMESPACE(store_gf) + +#include "gf.h" +#include + +void store_gf(unsigned char *, gf); +uint16_t load_gf(const unsigned char *); + +uint32_t load4(const unsigned char *); + +void store8(unsigned char *, uint64_t ); +uint64_t load8(const unsigned char *); + +gf bitrev(gf); + +#endif + diff --git a/deps/mceliece/kem/mceliece348864f/benes.c b/deps/mceliece/kem/mceliece348864f/benes.c new file mode 100644 index 0000000..8de8ef5 --- /dev/null +++ b/deps/mceliece/kem/mceliece348864f/benes.c @@ -0,0 +1,145 @@ +/* + This file is for Benes network related functions + + For the implementation strategy, see + https://eprint.iacr.org/2017/793.pdf +*/ + +#include "util.h" +#include "transpose.h" +#include "params.h" +#include "benes.h" + +/* one layer of the benes network */ +static void layer(uint64_t * data, uint64_t * bits, int lgs) +{ + int i, j, s; + + uint64_t d; + + s = 1 << lgs; + + for (i = 0; i < 64; i += s*2) + for (j = i; j < i+s; j++) + { + + d = (data[j+0] ^ data[j+s]); + d &= (*bits++); + data[j+0] ^= d; + data[j+s] ^= d; + } +} + +/* input: r, sequence of bits to be permuted */ +/* bits, condition bits of the Benes network */ +/* rev, 0 for normal application; !0 for inverse */ +/* output: r, permuted bits */ +void apply_benes(unsigned char * r, const unsigned char * bits, int rev) +{ + int i; + + const unsigned char *cond_ptr; + int inc, low; + + uint64_t bs[64]; + uint64_t cond[64]; + + // + + for (i = 0; i < 64; i++) + { + bs[i] = load8(r + i*8); + } + + if (rev == 0) + { + inc = 256; + cond_ptr = bits; + } + else + { + inc = -256; + cond_ptr = bits + (2*GFBITS-2)*256; + } + + // + + transpose_64x64(bs, bs); + + for (low = 0; low <= 5; low++) + { + for (i = 0; i < 64; i++) cond[i] = load4(cond_ptr + i*4); + transpose_64x64(cond, cond); + layer(bs, cond, low); + cond_ptr += inc; + } + + transpose_64x64(bs, bs); + + for (low = 0; low <= 5; low++) + { + for (i = 0; i < 32; i++) cond[i] = load8(cond_ptr + i*8); + layer(bs, cond, low); + cond_ptr += inc; + } + for (low = 4; low >= 0; low--) + { + for (i = 0; i < 32; i++) cond[i] = load8(cond_ptr + i*8); + layer(bs, cond, low); + cond_ptr += inc; + } + + transpose_64x64(bs, bs); + + for (low = 5; low >= 0; low--) + { + for (i = 0; i < 64; i++) cond[i] = load4(cond_ptr + i*4); + transpose_64x64(cond, cond); + layer(bs, cond, low); + cond_ptr += inc; + } + + transpose_64x64(bs, bs); + + // + + for (i = 0; i < 64; i++) + { + store8(r + i*8, bs[i]); + } +} + +/* input: condition bits c */ +/* output: support s */ +void support_gen(gf * s, const unsigned char *c) +{ + gf a; + int i, j; + unsigned char L[ GFBITS ][ (1 << GFBITS)/8 ]; + + for (i = 0; i < GFBITS; i++) + for (j = 0; j < (1 << GFBITS)/8; j++) + L[i][j] = 0; + + for (i = 0; i < (1 << GFBITS); i++) + { + a = bitrev((gf) i); + + for (j = 0; j < GFBITS; j++) + L[j][ i/8 ] |= ((a >> j) & 1) << (i%8); + } + + for (j = 0; j < GFBITS; j++) + apply_benes(L[j], c, 0); + + for (i = 0; i < SYS_N; i++) + { + s[i] = 0; + for (j = GFBITS-1; j >= 0; j--) + { + s[i] <<= 1; + s[i] |= (L[j][i/8] >> (i%8)) & 1; + } + } +} + diff --git a/deps/mceliece/kem/mceliece348864f/benes.h b/deps/mceliece/kem/mceliece348864f/benes.h new file mode 100644 index 0000000..c2ef35a --- /dev/null +++ b/deps/mceliece/kem/mceliece348864f/benes.h @@ -0,0 +1,16 @@ +/* + This file is for Benes network related functions +*/ + +#ifndef BENES_H +#define BENES_H +#define apply_benes CRYPTO_NAMESPACE(apply_benes) +#define support_gen CRYPTO_NAMESPACE(support_gen) + +#include "gf.h" + +void apply_benes(unsigned char *, const unsigned char *, int); +void support_gen(gf *, const unsigned char *); + +#endif + diff --git a/deps/mceliece/kem/mceliece348864f/bm.c b/deps/mceliece/kem/mceliece348864f/bm.c new file mode 100644 index 0000000..056a734 --- /dev/null +++ b/deps/mceliece/kem/mceliece348864f/bm.c @@ -0,0 +1,72 @@ +/* + This file is for the Berlekamp-Massey algorithm + see http://crypto.stanford.edu/~mironov/cs359/massey.pdf +*/ + +#include "params.h" +#include "gf.h" +#include "bm.h" + +#define min(a, b) ((a < b) ? a : b) + +/* the Berlekamp-Massey algorithm */ +/* input: s, sequence of field elements */ +/* output: out, minimal polynomial of s */ +void bm(gf *out, gf *s) +{ + int i; + + uint16_t N = 0; + uint16_t L = 0; + uint16_t mle; + uint16_t mne; + + gf T[ SYS_T+1 ]; + gf C[ SYS_T+1 ]; + gf B[ SYS_T+1 ]; + + gf b = 1, d, f; + + // + + for (i = 0; i < SYS_T+1; i++) + C[i] = B[i] = 0; + + B[1] = C[0] = 1; + + // + + for (N = 0; N < 2 * SYS_T; N++) + { + d = 0; + + for (i = 0; i <= min(N, SYS_T); i++) + d ^= gf_mul(C[i], s[ N-i]); + + mne = d; mne -= 1; mne >>= 15; mne -= 1; + mle = N; mle -= 2*L; mle >>= 15; mle -= 1; + mle &= mne; + + for (i = 0; i <= SYS_T; i++) + T[i] = C[i]; + + f = gf_frac(b, d); + + for (i = 0; i <= SYS_T; i++) + C[i] ^= gf_mul(f, B[i]) & mne; + + L = (L & ~mle) | ((N+1-L) & mle); + + for (i = 0; i <= SYS_T; i++) + B[i] = (B[i] & ~mle) | (T[i] & mle); + + b = (b & ~mle) | (d & mle); + + for (i = SYS_T; i >= 1; i--) B[i] = B[i-1]; + B[0] = 0; + } + + for (i = 0; i <= SYS_T; i++) + out[i] = C[ SYS_T-i ]; +} + diff --git a/deps/mceliece/kem/mceliece348864f/bm.h b/deps/mceliece/kem/mceliece348864f/bm.h new file mode 100644 index 0000000..73d5c6c --- /dev/null +++ b/deps/mceliece/kem/mceliece348864f/bm.h @@ -0,0 +1,13 @@ +/* + This file is for the Berlekamp-Massey algorithm + see http://crypto.stanford.edu/~mironov/cs359/massey.pdf +*/ + +#ifndef BM_H +#define BM_H +#define bm CRYPTO_NAMESPACE(bm) + +void bm(gf *, gf *); + +#endif + diff --git a/deps/mceliece/kem/mceliece348864f/controlbits.c b/deps/mceliece/kem/mceliece348864f/controlbits.c new file mode 100644 index 0000000..db9db9c --- /dev/null +++ b/deps/mceliece/kem/mceliece348864f/controlbits.c @@ -0,0 +1,220 @@ +/* This file is for implementing the Nassimi-Sahni algorithm */ +/* See David Nassimi, Sartaj Sahni "Parallel algorithms to set up the Benes permutationnetwork" */ +/* See also https://cr.yp.to/papers/controlbits-20200923.pdf */ + +#include +#include "crypto_declassify.h" +#include "controlbits.h" +#include "int32_sort.h" +typedef int16_t int16; +typedef int32_t int32; +#include "crypto_int32.h" +#define int32_min crypto_int32_min +#include "crypto_int16.h" + +/* parameters: 1 <= w <= 14; n = 2^w */ +/* input: permutation pi of {0,1,...,n-1} */ +/* output: (2m-1)n/2 control bits at positions pos,pos+step,... */ +/* output position pos is by definition 1&(out[pos/8]>>(pos&7)) */ +/* caller must 0-initialize positions first */ +/* temp must have space for int32[2*n] */ +static void cbrecursion(unsigned char *out,long long pos,long long step,const int16 *pi,long long w,long long n,int32 *temp) +{ +#define A temp +#define B (temp+n) +#define q ((int16 *) (temp+n+n/4)) +/* q can start anywhere between temp+n and temp+n/2 */ + + long long x,i,j,k; + + if (w == 1) { + out[pos>>3] ^= pi[0]<<(pos&7); + return; + } + + for (x = 0;x < n;++x) A[x] = ((pi[x]^1)<<16)|pi[x^1]; + int32_sort(A,n); /* A = (id<<16)+pibar */ + + for (x = 0;x < n;++x) { + int32 Ax = A[x]; + int32 px = Ax&0xffff; + int32 cx = int32_min(px,x); + B[x] = (px<<16)|cx; + } + /* B = (p<<16)+c */ + + for (x = 0;x < n;++x) A[x] = (A[x]<<16)|x; /* A = (pibar<<16)+id */ + int32_sort(A,n); /* A = (id<<16)+pibar^-1 */ + + for (x = 0;x < n;++x) A[x] = (A[x]<<16)+(B[x]>>16); /* A = (pibar^(-1)<<16)+pibar */ + int32_sort(A,n); /* A = (id<<16)+pibar^2 */ + + if (w <= 10) { + for (x = 0;x < n;++x) B[x] = ((A[x]&0xffff)<<10)|(B[x]&0x3ff); + + for (i = 1;i < w-1;++i) { + /* B = (p<<10)+c */ + + for (x = 0;x < n;++x) A[x] = ((B[x]&~0x3ff)<<6)|x; /* A = (p<<16)+id */ + int32_sort(A,n); /* A = (id<<16)+p^{-1} */ + + for (x = 0;x < n;++x) A[x] = (A[x]<<20)|B[x]; /* A = (p^{-1}<<20)+(p<<10)+c */ + int32_sort(A,n); /* A = (id<<20)+(pp<<10)+cp */ + + for (x = 0;x < n;++x) { + int32 ppcpx = A[x]&0xfffff; + int32 ppcx = (A[x]&0xffc00)|(B[x]&0x3ff); + B[x] = int32_min(ppcx,ppcpx); + } + } + for (x = 0;x < n;++x) B[x] &= 0x3ff; + } else { + for (x = 0;x < n;++x) B[x] = (A[x]<<16)|(B[x]&0xffff); + + for (i = 1;i < w-1;++i) { + /* B = (p<<16)+c */ + + for (x = 0;x < n;++x) A[x] = (B[x]&~0xffff)|x; + int32_sort(A,n); /* A = (id<<16)+p^(-1) */ + + for (x = 0;x < n;++x) A[x] = (A[x]<<16)|(B[x]&0xffff); + /* A = p^(-1)<<16+c */ + + if (i < w-2) { + for (x = 0;x < n;++x) B[x] = (A[x]&~0xffff)|(B[x]>>16); + /* B = (p^(-1)<<16)+p */ + int32_sort(B,n); /* B = (id<<16)+p^(-2) */ + for (x = 0;x < n;++x) B[x] = (B[x]<<16)|(A[x]&0xffff); + /* B = (p^(-2)<<16)+c */ + } + + int32_sort(A,n); + /* A = id<<16+cp */ + for (x = 0;x < n;++x) { + int32 cpx = (B[x]&~0xffff)|(A[x]&0xffff); + B[x] = int32_min(B[x],cpx); + } + } + for (x = 0;x < n;++x) B[x] &= 0xffff; + } + + for (x = 0;x < n;++x) A[x] = (((int32)pi[x])<<16)+x; + int32_sort(A,n); /* A = (id<<16)+pi^(-1) */ + + for (j = 0;j < n/2;++j) { + long long x = 2*j; + int32 fj = B[x]&1; /* f[j] */ + int32 Fx = x+fj; /* F[x] */ + int32 Fx1 = Fx^1; /* F[x+1] */ + + out[pos>>3] ^= fj<<(pos&7); + pos += step; + + B[x] = (A[x]<<16)|Fx; + B[x+1] = (A[x+1]<<16)|Fx1; + } + /* B = (pi^(-1)<<16)+F */ + + int32_sort(B,n); /* B = (id<<16)+F(pi) */ + + pos += (2*w-3)*step*(n/2); + + for (k = 0;k < n/2;++k) { + long long y = 2*k; + int32 lk = B[y]&1; /* l[k] */ + int32 Ly = y+lk; /* L[y] */ + int32 Ly1 = Ly^1; /* L[y+1] */ + + out[pos>>3] ^= lk<<(pos&7); + pos += step; + + A[y] = (Ly<<16)|(B[y]&0xffff); + A[y+1] = (Ly1<<16)|(B[y+1]&0xffff); + } + /* A = (L<<16)+F(pi) */ + + int32_sort(A,n); /* A = (id<<16)+F(pi(L)) = (id<<16)+M */ + + pos -= (2*w-2)*step*(n/2); + + for (j = 0;j < n/2;++j) { + q[j] = (A[2*j]&0xffff)>>1; + q[j+n/2] = (A[2*j+1]&0xffff)>>1; + } + + cbrecursion(out,pos,step*2,q,w-1,n/2,temp); + cbrecursion(out,pos+step,step*2,q+n/2,w-1,n/2,temp); +} + +/* input: p, an array of int16 */ +/* input: n, length of p */ +/* input: s, meaning that stride-2^s cswaps are performed */ +/* input: cb, the control bits */ +/* output: the result of apply the control bits to p */ +static void layer(int16_t *p, const unsigned char *cb, int s, int n) +{ + int i, j; + int stride = 1 << s; + int index = 0; + int16_t d, m; + + for (i = 0; i < n; i += stride*2) + { + for (j = 0; j < stride; j++) + { + d = p[ i+j ] ^ p[ i+j+stride ]; + m = (cb[ index >> 3 ] >> (index & 7)) & 1; + m = -m; + d &= m; + p[ i+j ] ^= d; + p[ i+j+stride ] ^= d; + index++; + } + } +} + +/* parameters: 1 <= w <= 14; n = 2^w */ +/* input: permutation pi of {0,1,...,n-1} */ +/* output: (2m-1)n/2 control bits at positions 0,1,... */ +/* output position pos is by definition 1&(out[pos/8]>>(pos&7)) */ +void controlbitsfrompermutation(unsigned char *out,const int16 *pi,long long w,long long n) +{ + int32 temp[2*n]; + int16 pi_test[n], diff; + int i; + unsigned char *ptr; + + while (1) + { + memset(out,0,(((2*w-1)*n/2)+7)/8); + cbrecursion(out,0,1,pi,w,n,temp); + + // check for correctness + + for (i = 0; i < n; i++) + pi_test[i] = i; + + ptr = out; + for (i = 0; i < w; i++) + { + layer(pi_test, ptr, i, n); + ptr += n >> 4; + } + + for (i = w-2; i >= 0; i--) + { + layer(pi_test, ptr, i, n); + ptr += n >> 4; + } + + diff = 0; + for (i = 0; i < n; i++) + diff |= pi[i] ^ pi_test[i]; + + diff = crypto_int16_nonzero_mask(diff); + crypto_declassify(&diff,sizeof diff); + if (diff == 0) + break; + } +} + diff --git a/deps/mceliece/kem/mceliece348864f/controlbits.h b/deps/mceliece/kem/mceliece348864f/controlbits.h new file mode 100644 index 0000000..8ddd210 --- /dev/null +++ b/deps/mceliece/kem/mceliece348864f/controlbits.h @@ -0,0 +1,14 @@ +/* This file is for implementing the Nassimi-Sahni algorithm */ +/* See David Nassimi, Sartaj Sahni "Parallel algorithms to set up the Benes permutationnetwork" */ +/* See also https://cr.yp.to/papers/controlbits-20200923.pdf */ + +#ifndef CONTROLBITS_H +#define CONTROLBITS_H + +#define controlbitsfrompermutation CRYPTO_NAMESPACE(controlbitsfrompermutation) + +#include + +extern void controlbitsfrompermutation(unsigned char *,const int16_t *,long long,long long); + +#endif diff --git a/deps/mceliece/kem/mceliece348864f/crypto_hash.h b/deps/mceliece/kem/mceliece348864f/crypto_hash.h new file mode 100644 index 0000000..b7c1086 --- /dev/null +++ b/deps/mceliece/kem/mceliece348864f/crypto_hash.h @@ -0,0 +1,10 @@ +/* This file uses SHAKE256 implemented in the Keccak Code Package */ + +#include "../../mceliece_externals.h" + +#define crypto_hash_32b(out,in,inlen) \ + SHAKE256(out,32,in,inlen) + +#define shake(out,outlen,in,inlen) \ + SHAKE256(out,outlen,in,inlen) + diff --git a/deps/mceliece/kem/mceliece348864f/crypto_kem.h b/deps/mceliece/kem/mceliece348864f/crypto_kem.h new file mode 100644 index 0000000..db08717 --- /dev/null +++ b/deps/mceliece/kem/mceliece348864f/crypto_kem.h @@ -0,0 +1,15 @@ +#ifndef crypto_kem_H +#define crypto_kem_H + +#include "crypto_kem_mceliece348864f.h" + +#define crypto_kem_keypair crypto_kem_mceliece348864f_keypair +#define crypto_kem_enc crypto_kem_mceliece348864f_enc +#define crypto_kem_dec crypto_kem_mceliece348864f_dec +#define crypto_kem_PUBLICKEYBYTES crypto_kem_mceliece348864f_PUBLICKEYBYTES +#define crypto_kem_SECRETKEYBYTES crypto_kem_mceliece348864f_SECRETKEYBYTES +#define crypto_kem_BYTES crypto_kem_mceliece348864f_BYTES +#define crypto_kem_CIPHERTEXTBYTES crypto_kem_mceliece348864f_CIPHERTEXTBYTES +#define crypto_kem_PRIMITIVE "mceliece348864f" + +#endif diff --git a/deps/mceliece/kem/mceliece348864f/crypto_kem_mceliece348864f.h b/deps/mceliece/kem/mceliece348864f/crypto_kem_mceliece348864f.h new file mode 100644 index 0000000..b1ee66f --- /dev/null +++ b/deps/mceliece/kem/mceliece348864f/crypto_kem_mceliece348864f.h @@ -0,0 +1,28 @@ +#ifndef crypto_kem_mceliece348864f_H +#define crypto_kem_mceliece348864f_H + +#define crypto_kem_mceliece348864f_ref_PUBLICKEYBYTES 261120 +#define crypto_kem_mceliece348864f_ref_SECRETKEYBYTES 6492 +#define crypto_kem_mceliece348864f_ref_CIPHERTEXTBYTES 96 +#define crypto_kem_mceliece348864f_ref_BYTES 32 + + +#ifdef __cplusplus +extern "C" { +#endif +extern int crypto_kem_mceliece348864f_ref_keypair(unsigned char *,unsigned char *); +extern int crypto_kem_mceliece348864f_ref_enc(unsigned char *,unsigned char *,const unsigned char *); +extern int crypto_kem_mceliece348864f_ref_dec(unsigned char *,const unsigned char *,const unsigned char *); +#ifdef __cplusplus +} +#endif + +#define crypto_kem_mceliece348864f_keypair crypto_kem_mceliece348864f_ref_keypair +#define crypto_kem_mceliece348864f_enc crypto_kem_mceliece348864f_ref_enc +#define crypto_kem_mceliece348864f_dec crypto_kem_mceliece348864f_ref_dec +#define crypto_kem_mceliece348864f_PUBLICKEYBYTES crypto_kem_mceliece348864f_ref_PUBLICKEYBYTES +#define crypto_kem_mceliece348864f_SECRETKEYBYTES crypto_kem_mceliece348864f_ref_SECRETKEYBYTES +#define crypto_kem_mceliece348864f_BYTES crypto_kem_mceliece348864f_ref_BYTES +#define crypto_kem_mceliece348864f_CIPHERTEXTBYTES crypto_kem_mceliece348864f_ref_CIPHERTEXTBYTES + +#endif diff --git a/deps/mceliece/kem/mceliece348864f/decrypt.c b/deps/mceliece/kem/mceliece348864f/decrypt.c new file mode 100644 index 0000000..c4cc6de --- /dev/null +++ b/deps/mceliece/kem/mceliece348864f/decrypt.c @@ -0,0 +1,93 @@ +/* + This file is for Niederreiter decryption +*/ + +#include +#include "decrypt.h" + +#include "params.h" +#include "benes.h" +#include "util.h" +#include "synd.h" +#include "root.h" +#include "gf.h" +#include "bm.h" + +/* Niederreiter decryption with the Berlekamp decoder */ +/* intput: sk, secret key */ +/* c, ciphertext */ +/* output: e, error vector */ +/* return: 0 for success; 1 for failure */ +int decrypt(unsigned char *e, const unsigned char *sk, const unsigned char *c) +{ + int i, w = 0; + uint16_t check; + + unsigned char r[ SYS_N/8 ]; + + gf g[ SYS_T+1 ]; + gf L[ SYS_N ]; + + gf s[ SYS_T*2 ]; + gf s_cmp[ SYS_T*2 ]; + gf locator[ SYS_T+1 ]; + gf images[ SYS_N ]; + + gf t; + + // + + for (i = 0; i < SYND_BYTES; i++) r[i] = c[i]; + for (i = SYND_BYTES; i < SYS_N/8; i++) r[i] = 0; + + for (i = 0; i < SYS_T; i++) { g[i] = load_gf(sk); sk += 2; } g[ SYS_T ] = 1; + + support_gen(L, sk); + + synd(s, g, L, r); + + bm(locator, s); + + root(images, locator, L); + + // + + for (i = 0; i < SYS_N/8; i++) + e[i] = 0; + + for (i = 0; i < SYS_N; i++) + { + t = gf_iszero(images[i]) & 1; + + e[ i/8 ] |= t << (i%8); + w += t; + + } + +#ifdef KAT + { + int k; + printf("decrypt e: positions"); + for (k = 0;k < SYS_N;++k) + if (e[k/8] & (1 << (k&7))) + printf(" %d",k); + printf("\n"); + } +#endif + + synd(s_cmp, g, L, e); + + // + + check = w; + check ^= SYS_T; + + for (i = 0; i < SYS_T*2; i++) + check |= s[i] ^ s_cmp[i]; + + check -= 1; + check >>= 15; + + return check ^ 1; +} + diff --git a/deps/mceliece/kem/mceliece348864f/decrypt.h b/deps/mceliece/kem/mceliece348864f/decrypt.h new file mode 100644 index 0000000..266a5cd --- /dev/null +++ b/deps/mceliece/kem/mceliece348864f/decrypt.h @@ -0,0 +1,12 @@ +/* + This file is for Nieddereiter decryption +*/ + +#ifndef DECRYPT_H +#define DECRYPT_H +#define decrypt CRYPTO_NAMESPACE(decrypt) + +int decrypt(unsigned char *, const unsigned char *, const unsigned char *); + +#endif + diff --git a/deps/mceliece/kem/mceliece348864f/encrypt.c b/deps/mceliece/kem/mceliece348864f/encrypt.c new file mode 100644 index 0000000..4823d2f --- /dev/null +++ b/deps/mceliece/kem/mceliece348864f/encrypt.c @@ -0,0 +1,161 @@ +/* + This file is for Niederreiter encryption +*/ + +#include "encrypt.h" + +#include "util.h" +#include "params.h" +#include "randombytes.h" + +#include +#include +#include +#include + +#include "gf.h" +#include "crypto_declassify.h" +#include "crypto_uint16.h" +#include "crypto_uint32.h" + +static inline crypto_uint16 uint16_is_smaller_declassify(uint16_t t,uint16_t u) +{ + crypto_uint16 mask = crypto_uint16_smaller_mask(t,u); + crypto_declassify(&mask,sizeof mask); + return mask; +} + +static inline crypto_uint32 uint32_is_equal_declassify(uint32_t t,uint32_t u) +{ + crypto_uint32 mask = crypto_uint32_equal_mask(t,u); + crypto_declassify(&mask,sizeof mask); + return mask; +} + +static inline unsigned char same_mask(uint16_t x, uint16_t y) +{ + uint32_t mask; + + mask = x ^ y; + mask -= 1; + mask >>= 31; + mask = -mask; + + return mask & 0xFF; +} + +/* output: e, an error vector of weight t */ +static void gen_e(unsigned char *e) +{ + int i, j, eq, count; + + union + { + uint16_t nums[ SYS_T*2 ]; + unsigned char bytes[ SYS_T*2 * sizeof(uint16_t) ]; + } buf; + + uint16_t ind[ SYS_T ]; + unsigned char mask; + unsigned char val[ SYS_T ]; + + while (1) + { + randombytes(buf.bytes, sizeof(buf)); + + for (i = 0; i < SYS_T*2; i++) + buf.nums[i] = load_gf(buf.bytes + i*2); + + // moving and counting indices in the correct range + + count = 0; + for (i = 0; i < SYS_T*2 && count < SYS_T; i++) + if (uint16_is_smaller_declassify(buf.nums[i],SYS_N)) + ind[ count++ ] = buf.nums[i]; + + if (count < SYS_T) continue; + + // check for repetition + + eq = 0; + + for (i = 1; i < SYS_T; i++) + for (j = 0; j < i; j++) + if (uint32_is_equal_declassify(ind[i],ind[j])) + eq = 1; + + if (eq == 0) + break; + } + + for (j = 0; j < SYS_T; j++) + val[j] = 1 << (ind[j] & 7); + + for (i = 0; i < SYS_N/8; i++) + { + e[i] = 0; + + for (j = 0; j < SYS_T; j++) + { + mask = same_mask(i, (ind[j] >> 3)); + + e[i] |= val[j] & mask; + } + } +} + +/* input: public key pk, error vector e */ +/* output: syndrome s */ +static void syndrome(unsigned char *s, const unsigned char *pk, unsigned char *e) +{ + unsigned char b, row[SYS_N/8]; + const unsigned char *pk_ptr = pk; + + int i, j; + + for (i = 0; i < SYND_BYTES; i++) + s[i] = 0; + + for (i = 0; i < PK_NROWS; i++) + { + for (j = 0; j < SYS_N/8; j++) + row[j] = 0; + + for (j = 0; j < PK_ROW_BYTES; j++) + row[ SYS_N/8 - PK_ROW_BYTES + j ] = pk_ptr[j]; + + row[i/8] |= 1 << (i%8); + + b = 0; + for (j = 0; j < SYS_N/8; j++) + b ^= row[j] & e[j]; + + b ^= b >> 4; + b ^= b >> 2; + b ^= b >> 1; + b &= 1; + + s[ i/8 ] |= (b << (i%8)); + + pk_ptr += PK_ROW_BYTES; + } +} + +void encrypt(unsigned char *s, const unsigned char *pk, unsigned char *e) +{ + gen_e(e); + +#ifdef KAT + { + int k; + printf("encrypt e: positions"); + for (k = 0;k < SYS_N;++k) + if (e[k/8] & (1 << (k&7))) + printf(" %d",k); + printf("\n"); + } +#endif + + syndrome(s, pk, e); +} + diff --git a/deps/mceliece/kem/mceliece348864f/encrypt.h b/deps/mceliece/kem/mceliece348864f/encrypt.h new file mode 100644 index 0000000..8edd7a6 --- /dev/null +++ b/deps/mceliece/kem/mceliece348864f/encrypt.h @@ -0,0 +1,12 @@ +/* + This file is for Niederreiter encryption +*/ + +#ifndef ENCRYPT_H +#define ENCRYPT_H +#define encrypt CRYPTO_NAMESPACE(encrypt) + +void encrypt(unsigned char *, const unsigned char *, unsigned char *); + +#endif + diff --git a/deps/mceliece/kem/mceliece348864f/gf.c b/deps/mceliece/kem/mceliece348864f/gf.c new file mode 100644 index 0000000..5284a41 --- /dev/null +++ b/deps/mceliece/kem/mceliece348864f/gf.c @@ -0,0 +1,141 @@ +/* + This file is for functions for field arithmetic +*/ + +#include "gf.h" + +#include "params.h" + +gf gf_iszero(gf a) +{ + uint32_t t = a; + + t -= 1; + t >>= 19; + + return (gf) t; +} + +gf gf_add(gf in0, gf in1) +{ + return in0 ^ in1; +} + +gf gf_mul(gf in0, gf in1) +{ + int i; + + uint32_t tmp; + uint32_t t0; + uint32_t t1; + uint32_t t; + + t0 = in0; + t1 = in1; + + tmp = t0 * (t1 & 1); + + for (i = 1; i < GFBITS; i++) + tmp ^= (t0 * (t1 & (1 << i))); + + t = tmp & 0x7FC000; + tmp ^= t >> 9; + tmp ^= t >> 12; + + t = tmp & 0x3000; + tmp ^= t >> 9; + tmp ^= t >> 12; + + return tmp & ((1 << GFBITS)-1); +} + +/* input: field element in */ +/* return: in^2 */ +static inline gf gf_sq(gf in) +{ + const uint32_t B[] = {0x55555555, 0x33333333, 0x0F0F0F0F, 0x00FF00FF}; + + uint32_t x = in; + uint32_t t; + + x = (x | (x << 8)) & B[3]; + x = (x | (x << 4)) & B[2]; + x = (x | (x << 2)) & B[1]; + x = (x | (x << 1)) & B[0]; + + t = x & 0x7FC000; + x ^= t >> 9; + x ^= t >> 12; + + t = x & 0x3000; + x ^= t >> 9; + x ^= t >> 12; + + return x & ((1 << GFBITS)-1); +} + +gf gf_inv(gf in) +{ + gf tmp_11; + gf tmp_1111; + + gf out = in; + + out = gf_sq(out); + tmp_11 = gf_mul(out, in); // 11 + + out = gf_sq(tmp_11); + out = gf_sq(out); + tmp_1111 = gf_mul(out, tmp_11); // 1111 + + out = gf_sq(tmp_1111); + out = gf_sq(out); + out = gf_sq(out); + out = gf_sq(out); + out = gf_mul(out, tmp_1111); // 11111111 + + out = gf_sq(out); + out = gf_sq(out); + out = gf_mul(out, tmp_11); // 1111111111 + + out = gf_sq(out); + out = gf_mul(out, in); // 11111111111 + + return gf_sq(out); // 111111111110 +} + +/* input: field element den, num */ +/* return: (num/den) */ +gf gf_frac(gf den, gf num) +{ + return gf_mul(gf_inv(den), num); +} + +/* input: in0, in1 in GF((2^m)^t)*/ +/* output: out = in0*in1 */ +void GF_mul(gf *out, gf *in0, gf *in1) +{ + int i, j; + + gf prod[ SYS_T*2-1 ]; + + for (i = 0; i < SYS_T*2-1; i++) + prod[i] = 0; + + for (i = 0; i < SYS_T; i++) + for (j = 0; j < SYS_T; j++) + prod[i+j] ^= gf_mul(in0[i], in1[j]); + + // + + for (i = (SYS_T-1)*2; i >= SYS_T; i--) + { + prod[i - SYS_T + 3] ^= prod[i]; + prod[i - SYS_T + 1] ^= prod[i]; + prod[i - SYS_T + 0] ^= gf_mul(prod[i], (gf) 2); + } + + for (i = 0; i < SYS_T; i++) + out[i] = prod[i]; +} + diff --git a/deps/mceliece/kem/mceliece348864f/gf.h b/deps/mceliece/kem/mceliece348864f/gf.h new file mode 100644 index 0000000..f62209d --- /dev/null +++ b/deps/mceliece/kem/mceliece348864f/gf.h @@ -0,0 +1,27 @@ +/* + This file is for functions for field arithmetic +*/ + +#ifndef GF_H +#define GF_H +#define gf_add CRYPTO_NAMESPACE(gf_add) +#define gf_frac CRYPTO_NAMESPACE(gf_frac) +#define gf_inv CRYPTO_NAMESPACE(gf_inv) +#define gf_iszero CRYPTO_NAMESPACE(gf_iszero) +#define gf_mul CRYPTO_NAMESPACE(gf_mul) +#define GF_mul CRYPTO_NAMESPACE(GF_mul) + +#include + +typedef uint16_t gf; + +gf gf_iszero(gf); +gf gf_add(gf, gf); +gf gf_mul(gf, gf); +gf gf_frac(gf, gf); +gf gf_inv(gf); + +void GF_mul(gf *, gf *, gf *); + +#endif + diff --git a/deps/mceliece/kem/mceliece348864f/int32_sort.h b/deps/mceliece/kem/mceliece348864f/int32_sort.h new file mode 100644 index 0000000..a431af2 --- /dev/null +++ b/deps/mceliece/kem/mceliece348864f/int32_sort.h @@ -0,0 +1,46 @@ +#ifndef int32_sort_h +#define int32_sort_h + +#define int32_sort CRYPTO_NAMESPACE(int32_sort) + +#include + +#define int32_MINMAX(a,b) \ +do { \ + int32_t ab = b ^ a; \ + int32_t c = b - a; \ + c ^= ab & (c ^ b); \ + c >>= 31; \ + c &= ab; \ + a ^= c; \ + b ^= c; \ +} while(0) + +static void int32_sort(int32_t *x,long long n) +{ + long long top,p,q,r,i; + + if (n < 2) return; + top = 1; + while (top < n - top) top += top; + + for (p = top;p > 0;p >>= 1) { + for (i = 0;i < n - p;++i) + if (!(i & p)) + int32_MINMAX(x[i],x[i+p]); + i = 0; + for (q = top;q > p;q >>= 1) { + for (;i < n - q;++i) { + if (!(i & p)) { + int32_t a = x[i + p]; + for (r = q;r > p;r >>= 1) + int32_MINMAX(a,x[i+r]); + x[i + p] = a; + } + } + } + } +} + +#endif + diff --git a/deps/mceliece/kem/mceliece348864f/operations.c b/deps/mceliece/kem/mceliece348864f/operations.c new file mode 100644 index 0000000..bb605b1 --- /dev/null +++ b/deps/mceliece/kem/mceliece348864f/operations.c @@ -0,0 +1,147 @@ +#include "operations.h" + +#include "controlbits.h" +#include "randombytes.h" +#include "crypto_hash.h" +#include "encrypt.h" +#include "decrypt.h" +#include "params.h" +#include "sk_gen.h" +#include "pk_gen.h" +#include "util.h" + +#include +#include + +int crypto_kem_enc( + unsigned char *c, + unsigned char *key, + const unsigned char *pk +) +{ + unsigned char e[ SYS_N/8 ]; + unsigned char one_ec[ 1 + SYS_N/8 + SYND_BYTES ] = {1}; + + // + + encrypt(c, pk, e); + + memcpy(one_ec + 1, e, SYS_N/8); + memcpy(one_ec + 1 + SYS_N/8, c, SYND_BYTES); + + crypto_hash_32b(key, one_ec, sizeof(one_ec)); + + return 0; +} + +int crypto_kem_dec( + unsigned char *key, + const unsigned char *c, + const unsigned char *sk +) +{ + int i; + + unsigned char ret_decrypt = 0; + + uint16_t m; + + unsigned char e[ SYS_N/8 ]; + unsigned char preimage[ 1 + SYS_N/8 + SYND_BYTES ]; + unsigned char *x = preimage; + const unsigned char *s = sk + 40 + IRR_BYTES + COND_BYTES; + + // + + ret_decrypt = decrypt(e, sk + 40, c); + + m = ret_decrypt; + m -= 1; + m >>= 8; + + *x++ = m & 1; + for (i = 0; i < SYS_N/8; i++) + *x++ = (~m & s[i]) | (m & e[i]); + + for (i = 0; i < SYND_BYTES; i++) + *x++ = c[i]; + + crypto_hash_32b(key, preimage, sizeof(preimage)); + + return 0; +} + +int crypto_kem_keypair +( + unsigned char *pk, + unsigned char *sk +) +{ + int i; + unsigned char seed[ 33 ] = {64}; + unsigned char r[ SYS_N/8 + (1 << GFBITS)*sizeof(uint32_t) + SYS_T*2 + 32 ]; + unsigned char *rp, *skp; + uint64_t pivots; + + gf f[ SYS_T ]; // element in GF(2^mt) + gf irr[ SYS_T ]; // Goppa polynomial + uint32_t perm[ 1 << GFBITS ]; // random permutation as 32-bit integers + int16_t pi[ 1 << GFBITS ]; // random permutation + + randombytes(seed+1, 32); + + while (1) + { + rp = &r[ sizeof(r)-32 ]; + skp = sk; + + // expanding and updating the seed + + shake(r, sizeof(r), seed, 33); + memcpy(skp, seed+1, 32); + skp += 32 + 8; + memcpy(seed+1, &r[ sizeof(r)-32 ], 32); + + // generating irreducible polynomial + + rp -= sizeof(f); + + for (i = 0; i < SYS_T; i++) + f[i] = load_gf(rp + i*2); + + if (genpoly_gen(irr, f)) + continue; + + for (i = 0; i < SYS_T; i++) + store_gf(skp + i*2, irr[i]); + + skp += IRR_BYTES; + + // generating permutation + + rp -= sizeof(perm); + + for (i = 0; i < (1 << GFBITS); i++) + perm[i] = load4(rp + i*4); + + if (pk_gen(pk, skp - IRR_BYTES, perm, pi, &pivots)) + continue; + + controlbitsfrompermutation(skp, pi, GFBITS, 1 << GFBITS); + skp += COND_BYTES; + + // storing the random string s + + rp -= SYS_N/8; + memcpy(skp, rp, SYS_N/8); + + // storing positions of the 32 pivots + + store8(sk + 32, pivots); + + break; + } + + return 0; +} + diff --git a/deps/mceliece/kem/mceliece348864f/operations.h b/deps/mceliece/kem/mceliece348864f/operations.h new file mode 100644 index 0000000..bf65502 --- /dev/null +++ b/deps/mceliece/kem/mceliece348864f/operations.h @@ -0,0 +1,25 @@ +#ifndef OPERATIONS_H +#define OPERATIONS_H + +#include "crypto_kem.h" + +int crypto_kem_enc( + unsigned char *c, + unsigned char *key, + const unsigned char *pk +); + +int crypto_kem_dec( + unsigned char *key, + const unsigned char *c, + const unsigned char *sk +); + +int crypto_kem_keypair +( + unsigned char *pk, + unsigned char *sk +); + +#endif + diff --git a/deps/mceliece/kem/mceliece348864f/params.h b/deps/mceliece/kem/mceliece348864f/params.h new file mode 100644 index 0000000..7bd8e44 --- /dev/null +++ b/deps/mceliece/kem/mceliece348864f/params.h @@ -0,0 +1,20 @@ +#ifndef PARAMS_H +#define PARAMS_H + +#define GFBITS 12 +#define SYS_N 3488 +#define SYS_T 64 + +#define COND_BYTES ((1 << (GFBITS-4))*(2*GFBITS - 1)) +#define IRR_BYTES (SYS_T * 2) + +#define PK_NROWS (SYS_T*GFBITS) +#define PK_NCOLS (SYS_N - PK_NROWS) +#define PK_ROW_BYTES ((PK_NCOLS + 7)/8) + +#define SYND_BYTES ((PK_NROWS + 7)/8) + +#define GFMASK ((1 << GFBITS) - 1) + +#endif + diff --git a/deps/mceliece/kem/mceliece348864f/pk_gen.c b/deps/mceliece/kem/mceliece348864f/pk_gen.c new file mode 100644 index 0000000..5c65a2c --- /dev/null +++ b/deps/mceliece/kem/mceliece348864f/pk_gen.c @@ -0,0 +1,252 @@ +/* + This file is for public-key generation +*/ + +#include +#include +#include +#include + +#include "controlbits.h" +#include "uint64_sort.h" +#include "pk_gen.h" +#include "params.h" +#include "benes.h" +#include "root.h" +#include "util.h" +#include "crypto_declassify.h" +#include "crypto_uint64.h" + +static crypto_uint64 uint64_is_equal_declassify(uint64_t t,uint64_t u) +{ + crypto_uint64 mask = crypto_uint64_equal_mask(t,u); + crypto_declassify(&mask,sizeof mask); + return mask; +} + +static crypto_uint64 uint64_is_zero_declassify(uint64_t t) +{ + crypto_uint64 mask = crypto_uint64_zero_mask(t); + crypto_declassify(&mask,sizeof mask); + return mask; +} + +#define min(a, b) ((a < b) ? a : b) + +/* return number of trailing zeros of the non-zero input in */ +static inline int ctz(uint64_t in) +{ + int i, b, m = 0, r = 0; + + for (i = 0; i < 64; i++) + { + b = (in >> i) & 1; + m |= b; + r += (m^1) & (b^1); + } + + return r; +} + +static inline uint64_t same_mask(uint16_t x, uint16_t y) +{ + uint64_t mask; + + mask = x ^ y; + mask -= 1; + mask >>= 63; + mask = -mask; + + return mask; +} + +static int mov_columns(uint8_t mat[][ SYS_N/8 ], int16_t * pi, uint64_t * pivots) +{ + int i, j, k, s, block_idx, row; + uint64_t buf[64], ctz_list[32], t, d, mask, one = 1; + + row = PK_NROWS - 32; + block_idx = row/8; + + // extract the 32x64 matrix + + for (i = 0; i < 32; i++) + buf[i] = load8( &mat[ row + i ][ block_idx ] ); + + // compute the column indices of pivots by Gaussian elimination. + // the indices are stored in ctz_list + + *pivots = 0; + + for (i = 0; i < 32; i++) + { + t = buf[i]; + for (j = i+1; j < 32; j++) + t |= buf[j]; + + if (uint64_is_zero_declassify(t)) return -1; // return if buf is not full rank + + ctz_list[i] = s = ctz(t); + *pivots |= one << ctz_list[i]; + + for (j = i+1; j < 32; j++) { mask = (buf[i] >> s) & 1; mask -= 1; buf[i] ^= buf[j] & mask; } + for (j = i+1; j < 32; j++) { mask = (buf[j] >> s) & 1; mask = -mask; buf[j] ^= buf[i] & mask; } + } + + // updating permutation + + for (j = 0; j < 32; j++) + for (k = j+1; k < 64; k++) + { + d = pi[ row + j ] ^ pi[ row + k ]; + d &= same_mask(k, ctz_list[j]); + pi[ row + j ] ^= d; + pi[ row + k ] ^= d; + } + + // moving columns of mat according to the column indices of pivots + + for (i = 0; i < PK_NROWS; i++) + { + t = load8( &mat[ i ][ block_idx ] ); + + for (j = 0; j < 32; j++) + { + d = t >> j; + d ^= t >> ctz_list[j]; + d &= 1; + + t ^= d << ctz_list[j]; + t ^= d << j; + } + + store8( &mat[ i ][ block_idx ], t ); + } + + return 0; +} + +/* input: secret key sk */ +/* output: public key pk */ +int pk_gen(unsigned char * pk, unsigned char * sk, uint32_t * perm, int16_t * pi, uint64_t * pivots) +{ + int i, j, k; + int row, c; + + uint64_t buf[ 1 << GFBITS ]; + + unsigned char mat[ PK_NROWS ][ SYS_N/8 ]; + unsigned char mask; + unsigned char b; + + gf g[ SYS_T+1 ]; // Goppa polynomial + gf L[ SYS_N ]; // support + gf inv[ SYS_N ]; + + // + + g[ SYS_T ] = 1; + + for (i = 0; i < SYS_T; i++) { g[i] = load_gf(sk); sk += 2; } + + for (i = 0; i < (1 << GFBITS); i++) + { + buf[i] = perm[i]; + buf[i] <<= 31; + buf[i] |= i; + } + + uint64_sort(buf, 1 << GFBITS); + + for (i = 1; i < (1 << GFBITS); i++) + if (uint64_is_equal_declassify(buf[i-1] >> 31,buf[i] >> 31)) + return -1; + + for (i = 0; i < (1 << GFBITS); i++) pi[i] = buf[i] & GFMASK; + for (i = 0; i < SYS_N; i++) L[i] = bitrev(pi[i]); + + // filling the matrix + + root(inv, g, L); + + for (i = 0; i < SYS_N; i++) + inv[i] = gf_inv(inv[i]); + + for (i = 0; i < PK_NROWS; i++) + for (j = 0; j < SYS_N/8; j++) + mat[i][j] = 0; + + for (i = 0; i < SYS_T; i++) + { + for (j = 0; j < SYS_N; j+=8) + for (k = 0; k < GFBITS; k++) + { + b = (inv[j+7] >> k) & 1; b <<= 1; + b |= (inv[j+6] >> k) & 1; b <<= 1; + b |= (inv[j+5] >> k) & 1; b <<= 1; + b |= (inv[j+4] >> k) & 1; b <<= 1; + b |= (inv[j+3] >> k) & 1; b <<= 1; + b |= (inv[j+2] >> k) & 1; b <<= 1; + b |= (inv[j+1] >> k) & 1; b <<= 1; + b |= (inv[j+0] >> k) & 1; + + mat[ i*GFBITS + k ][ j/8 ] = b; + } + + for (j = 0; j < SYS_N; j++) + inv[j] = gf_mul(inv[j], L[j]); + + } + + // gaussian elimination + + for (i = 0; i < (PK_NROWS + 7) / 8; i++) + for (j = 0; j < 8; j++) + { + row = i*8 + j; + + if (row >= PK_NROWS) + break; + + if (row == PK_NROWS - 32) + { + if (mov_columns(mat, pi, pivots)) + return -1; + } + + for (k = row + 1; k < PK_NROWS; k++) + { + mask = mat[ row ][ i ] ^ mat[ k ][ i ]; + mask >>= j; + mask &= 1; + mask = -mask; + + for (c = 0; c < SYS_N/8; c++) + mat[ row ][ c ] ^= mat[ k ][ c ] & mask; + } + + if ( uint64_is_zero_declassify((mat[ row ][ i ] >> j) & 1) ) // return if not systematic + { + return -1; + } + + for (k = 0; k < PK_NROWS; k++) + { + if (k != row) + { + mask = mat[ k ][ i ] >> j; + mask &= 1; + mask = -mask; + + for (c = 0; c < SYS_N/8; c++) + mat[ k ][ c ] ^= mat[ row ][ c ] & mask; + } + } + } + + for (i = 0; i < PK_NROWS; i++) + memcpy(pk + i*PK_ROW_BYTES, mat[i] + PK_NROWS/8, PK_ROW_BYTES); + + return 0; +} + diff --git a/deps/mceliece/kem/mceliece348864f/pk_gen.h b/deps/mceliece/kem/mceliece348864f/pk_gen.h new file mode 100644 index 0000000..96b7e7b --- /dev/null +++ b/deps/mceliece/kem/mceliece348864f/pk_gen.h @@ -0,0 +1,14 @@ +/* + This file is for public-key generation +*/ + +#ifndef PK_GEN_H +#define PK_GEN_H +#define pk_gen CRYPTO_NAMESPACE(pk_gen) + +#include "gf.h" + +int pk_gen(unsigned char *, unsigned char *, uint32_t *, int16_t *, uint64_t *); + +#endif + diff --git a/deps/mceliece/kem/mceliece348864f/randombytes.h b/deps/mceliece/kem/mceliece348864f/randombytes.h new file mode 100644 index 0000000..7e59351 --- /dev/null +++ b/deps/mceliece/kem/mceliece348864f/randombytes.h @@ -0,0 +1 @@ +#include "../../mceliece_externals.h" diff --git a/deps/mceliece/kem/mceliece348864f/root.c b/deps/mceliece/kem/mceliece348864f/root.c new file mode 100644 index 0000000..1c1b634 --- /dev/null +++ b/deps/mceliece/kem/mceliece348864f/root.c @@ -0,0 +1,38 @@ +/* + This file is for evaluating a polynomial at one or more field elements +*/ + +#include "root.h" +#include "params.h" +#include "gf.h" + +#include + +/* input: polynomial f and field element a */ +/* return f(a) */ +gf eval(gf *f, gf a) +{ + int i; + gf r; + + r = f[ SYS_T ]; + + for (i = SYS_T-1; i >= 0; i--) + { + r = gf_mul(r, a); + r = gf_add(r, f[i]); + } + + return r; +} + +/* input: polynomial f and list of field elements L */ +/* output: out = [ f(a) for a in L ] */ +void root(gf *out, gf *f, gf *L) +{ + int i; + + for (i = 0; i < SYS_N; i++) + out[i] = eval(f, L[i]); +} + diff --git a/deps/mceliece/kem/mceliece348864f/root.h b/deps/mceliece/kem/mceliece348864f/root.h new file mode 100644 index 0000000..42516e4 --- /dev/null +++ b/deps/mceliece/kem/mceliece348864f/root.h @@ -0,0 +1,16 @@ +/* + This file is for evaluating a polynomial at one or more field elements +*/ + +#ifndef ROOT_H +#define ROOT_H +#define eval CRYPTO_NAMESPACE(eval) +#define root CRYPTO_NAMESPACE(root) + +#include "gf.h" + +gf eval(gf *, gf); +void root(gf *, gf *, gf *); + +#endif + diff --git a/deps/mceliece/kem/mceliece348864f/sk_gen.c b/deps/mceliece/kem/mceliece348864f/sk_gen.c new file mode 100644 index 0000000..340cc9a --- /dev/null +++ b/deps/mceliece/kem/mceliece348864f/sk_gen.c @@ -0,0 +1,85 @@ +/* + This file is for secret-key generation +*/ + +#include "sk_gen.h" + +#include "randombytes.h" +#include "controlbits.h" +#include "params.h" +#include "util.h" +#include "gf.h" +#include "crypto_declassify.h" +#include "crypto_uint16.h" + +static inline crypto_uint16 gf_is_zero_declassify(gf t) +{ + crypto_uint16 mask = crypto_uint16_zero_mask(t); + crypto_declassify(&mask,sizeof mask); + return mask; +} + +/* input: f, element in GF((2^m)^t) */ +/* output: out, minimal polynomial of f */ +/* return: 0 for success and -1 for failure */ +int genpoly_gen(gf *out, gf *f) +{ + int i, j, k, c; + + gf mat[ SYS_T+1 ][ SYS_T ]; + gf mask, inv, t; + + // fill matrix + + mat[0][0] = 1; + + for (i = 1; i < SYS_T; i++) + mat[0][i] = 0; + + for (i = 0; i < SYS_T; i++) + mat[1][i] = f[i]; + + for (j = 2; j <= SYS_T; j++) + GF_mul(mat[j], mat[j-1], f); + + // gaussian + + for (j = 0; j < SYS_T; j++) + { + for (k = j + 1; k < SYS_T; k++) + { + mask = gf_iszero(mat[ j ][ j ]); + + for (c = j; c < SYS_T + 1; c++) + mat[ c ][ j ] ^= mat[ c ][ k ] & mask; + + } + + if ( gf_is_zero_declassify(mat[ j ][ j ]) ) // return if not systematic + { + return -1; + } + + inv = gf_inv(mat[j][j]); + + for (c = j; c < SYS_T + 1; c++) + mat[ c ][ j ] = gf_mul(mat[ c ][ j ], inv) ; + + for (k = 0; k < SYS_T; k++) + { + if (k != j) + { + t = mat[ j ][ k ]; + + for (c = j; c < SYS_T + 1; c++) + mat[ c ][ k ] ^= gf_mul(mat[ c ][ j ], t); + } + } + } + + for (i = 0; i < SYS_T; i++) + out[i] = mat[ SYS_T ][ i ]; + + return 0; +} + diff --git a/deps/mceliece/kem/mceliece348864f/sk_gen.h b/deps/mceliece/kem/mceliece348864f/sk_gen.h new file mode 100644 index 0000000..e319703 --- /dev/null +++ b/deps/mceliece/kem/mceliece348864f/sk_gen.h @@ -0,0 +1,18 @@ +/* + This file is for secret-key generation +*/ + +#ifndef SK_GEN_H +#define SK_GEN_H +#define genpoly_gen CRYPTO_NAMESPACE(genpoly_gen) +#define perm_check CRYPTO_NAMESPACE(perm_check) + +#include "gf.h" + +#include + +int genpoly_gen(gf *, gf *); +int perm_check(uint32_t *); + +#endif + diff --git a/deps/mceliece/kem/mceliece348864f/subroutines/crypto_declassify.h b/deps/mceliece/kem/mceliece348864f/subroutines/crypto_declassify.h new file mode 100644 index 0000000..8d84209 --- /dev/null +++ b/deps/mceliece/kem/mceliece348864f/subroutines/crypto_declassify.h @@ -0,0 +1,8 @@ +#ifndef crypto_declassify_h +#define crypto_declassify_h + +static void crypto_declassify(void *x,unsigned long long n) +{ +} + +#endif diff --git a/deps/mceliece/kem/mceliece348864f/subroutines/crypto_int16.h b/deps/mceliece/kem/mceliece348864f/subroutines/crypto_int16.h new file mode 100644 index 0000000..72bbf52 --- /dev/null +++ b/deps/mceliece/kem/mceliece348864f/subroutines/crypto_int16.h @@ -0,0 +1,81 @@ +#ifndef crypto_int16_h +#define crypto_int16_h + +#include +typedef int16_t crypto_int16; + +static crypto_int16 crypto_int16_negative_mask(crypto_int16 crypto_int16_x) +{ + return crypto_int16_x >> 15; +} + +static crypto_int16 crypto_int16_nonzero_mask(crypto_int16 crypto_int16_x) +{ + return crypto_int16_negative_mask(crypto_int16_x) | crypto_int16_negative_mask(-crypto_int16_x); +} + +static crypto_int16 crypto_int16_zero_mask(crypto_int16 crypto_int16_x) +{ + return ~crypto_int16_nonzero_mask(crypto_int16_x); +} + +static crypto_int16 crypto_int16_positive_mask(crypto_int16 crypto_int16_x) +{ + crypto_int16 crypto_int16_z = -crypto_int16_x; + crypto_int16_z ^= crypto_int16_x & crypto_int16_z; + return crypto_int16_negative_mask(crypto_int16_z); +} + +static crypto_int16 crypto_int16_unequal_mask(crypto_int16 crypto_int16_x,crypto_int16 crypto_int16_y) +{ + crypto_int16 crypto_int16_xy = crypto_int16_x ^ crypto_int16_y; + return crypto_int16_nonzero_mask(crypto_int16_xy); +} + +static crypto_int16 crypto_int16_equal_mask(crypto_int16 crypto_int16_x,crypto_int16 crypto_int16_y) +{ + return ~crypto_int16_unequal_mask(crypto_int16_x,crypto_int16_y); +} + +static crypto_int16 crypto_int16_smaller_mask(crypto_int16 crypto_int16_x,crypto_int16 crypto_int16_y) +{ + crypto_int16 crypto_int16_xy = crypto_int16_x ^ crypto_int16_y; + crypto_int16 crypto_int16_z = crypto_int16_x - crypto_int16_y; + crypto_int16_z ^= crypto_int16_xy & (crypto_int16_z ^ crypto_int16_x); + return crypto_int16_negative_mask(crypto_int16_z); +} + +static crypto_int16 crypto_int16_min(crypto_int16 crypto_int16_x,crypto_int16 crypto_int16_y) +{ + crypto_int16 crypto_int16_xy = crypto_int16_y ^ crypto_int16_x; + crypto_int16 crypto_int16_z = crypto_int16_y - crypto_int16_x; + crypto_int16_z ^= crypto_int16_xy & (crypto_int16_z ^ crypto_int16_y); + crypto_int16_z = crypto_int16_negative_mask(crypto_int16_z); + crypto_int16_z &= crypto_int16_xy; + return crypto_int16_x ^ crypto_int16_z; +} + +static crypto_int16 crypto_int16_max(crypto_int16 crypto_int16_x,crypto_int16 crypto_int16_y) +{ + crypto_int16 crypto_int16_xy = crypto_int16_y ^ crypto_int16_x; + crypto_int16 crypto_int16_z = crypto_int16_y - crypto_int16_x; + crypto_int16_z ^= crypto_int16_xy & (crypto_int16_z ^ crypto_int16_y); + crypto_int16_z = crypto_int16_negative_mask(crypto_int16_z); + crypto_int16_z &= crypto_int16_xy; + return crypto_int16_y ^ crypto_int16_z; +} + +static void crypto_int16_minmax(crypto_int16 *crypto_int16_a,crypto_int16 *crypto_int16_b) +{ + crypto_int16 crypto_int16_x = *crypto_int16_a; + crypto_int16 crypto_int16_y = *crypto_int16_b; + crypto_int16 crypto_int16_xy = crypto_int16_y ^ crypto_int16_x; + crypto_int16 crypto_int16_z = crypto_int16_y - crypto_int16_x; + crypto_int16_z ^= crypto_int16_xy & (crypto_int16_z ^ crypto_int16_y); + crypto_int16_z = crypto_int16_negative_mask(crypto_int16_z); + crypto_int16_z &= crypto_int16_xy; + *crypto_int16_a = crypto_int16_x ^ crypto_int16_z; + *crypto_int16_b = crypto_int16_y ^ crypto_int16_z; +} + +#endif diff --git a/deps/mceliece/kem/mceliece348864f/subroutines/crypto_int32.h b/deps/mceliece/kem/mceliece348864f/subroutines/crypto_int32.h new file mode 100644 index 0000000..c22f735 --- /dev/null +++ b/deps/mceliece/kem/mceliece348864f/subroutines/crypto_int32.h @@ -0,0 +1,81 @@ +#ifndef crypto_int32_h +#define crypto_int32_h + +#include +typedef int32_t crypto_int32; + +static crypto_int32 crypto_int32_negative_mask(crypto_int32 crypto_int32_x) +{ + return crypto_int32_x >> 31; +} + +static crypto_int32 crypto_int32_nonzero_mask(crypto_int32 crypto_int32_x) +{ + return crypto_int32_negative_mask(crypto_int32_x) | crypto_int32_negative_mask(-crypto_int32_x); +} + +static crypto_int32 crypto_int32_zero_mask(crypto_int32 crypto_int32_x) +{ + return ~crypto_int32_nonzero_mask(crypto_int32_x); +} + +static crypto_int32 crypto_int32_positive_mask(crypto_int32 crypto_int32_x) +{ + crypto_int32 crypto_int32_z = -crypto_int32_x; + crypto_int32_z ^= crypto_int32_x & crypto_int32_z; + return crypto_int32_negative_mask(crypto_int32_z); +} + +static crypto_int32 crypto_int32_unequal_mask(crypto_int32 crypto_int32_x,crypto_int32 crypto_int32_y) +{ + crypto_int32 crypto_int32_xy = crypto_int32_x ^ crypto_int32_y; + return crypto_int32_nonzero_mask(crypto_int32_xy); +} + +static crypto_int32 crypto_int32_equal_mask(crypto_int32 crypto_int32_x,crypto_int32 crypto_int32_y) +{ + return ~crypto_int32_unequal_mask(crypto_int32_x,crypto_int32_y); +} + +static crypto_int32 crypto_int32_smaller_mask(crypto_int32 crypto_int32_x,crypto_int32 crypto_int32_y) +{ + crypto_int32 crypto_int32_xy = crypto_int32_x ^ crypto_int32_y; + crypto_int32 crypto_int32_z = crypto_int32_x - crypto_int32_y; + crypto_int32_z ^= crypto_int32_xy & (crypto_int32_z ^ crypto_int32_x); + return crypto_int32_negative_mask(crypto_int32_z); +} + +static crypto_int32 crypto_int32_min(crypto_int32 crypto_int32_x,crypto_int32 crypto_int32_y) +{ + crypto_int32 crypto_int32_xy = crypto_int32_y ^ crypto_int32_x; + crypto_int32 crypto_int32_z = crypto_int32_y - crypto_int32_x; + crypto_int32_z ^= crypto_int32_xy & (crypto_int32_z ^ crypto_int32_y); + crypto_int32_z = crypto_int32_negative_mask(crypto_int32_z); + crypto_int32_z &= crypto_int32_xy; + return crypto_int32_x ^ crypto_int32_z; +} + +static crypto_int32 crypto_int32_max(crypto_int32 crypto_int32_x,crypto_int32 crypto_int32_y) +{ + crypto_int32 crypto_int32_xy = crypto_int32_y ^ crypto_int32_x; + crypto_int32 crypto_int32_z = crypto_int32_y - crypto_int32_x; + crypto_int32_z ^= crypto_int32_xy & (crypto_int32_z ^ crypto_int32_y); + crypto_int32_z = crypto_int32_negative_mask(crypto_int32_z); + crypto_int32_z &= crypto_int32_xy; + return crypto_int32_y ^ crypto_int32_z; +} + +static void crypto_int32_minmax(crypto_int32 *crypto_int32_a,crypto_int32 *crypto_int32_b) +{ + crypto_int32 crypto_int32_x = *crypto_int32_a; + crypto_int32 crypto_int32_y = *crypto_int32_b; + crypto_int32 crypto_int32_xy = crypto_int32_y ^ crypto_int32_x; + crypto_int32 crypto_int32_z = crypto_int32_y - crypto_int32_x; + crypto_int32_z ^= crypto_int32_xy & (crypto_int32_z ^ crypto_int32_y); + crypto_int32_z = crypto_int32_negative_mask(crypto_int32_z); + crypto_int32_z &= crypto_int32_xy; + *crypto_int32_a = crypto_int32_x ^ crypto_int32_z; + *crypto_int32_b = crypto_int32_y ^ crypto_int32_z; +} + +#endif diff --git a/deps/mceliece/kem/mceliece348864f/subroutines/crypto_uint16.h b/deps/mceliece/kem/mceliece348864f/subroutines/crypto_uint16.h new file mode 100644 index 0000000..f0ebbbf --- /dev/null +++ b/deps/mceliece/kem/mceliece348864f/subroutines/crypto_uint16.h @@ -0,0 +1,76 @@ +#ifndef crypto_uint16_h +#define crypto_uint16_h + +#include +typedef uint16_t crypto_uint16; + +typedef int16_t crypto_uint16_signed; + +static crypto_uint16_signed crypto_uint16_signed_negative_mask(crypto_uint16_signed crypto_uint16_signed_x) +{ + return crypto_uint16_signed_x >> 15; +} + +static crypto_uint16 crypto_uint16_nonzero_mask(crypto_uint16 crypto_uint16_x) +{ + return crypto_uint16_signed_negative_mask(crypto_uint16_x) | crypto_uint16_signed_negative_mask(-crypto_uint16_x); +} + +static crypto_uint16 crypto_uint16_zero_mask(crypto_uint16 crypto_uint16_x) +{ + return ~crypto_uint16_nonzero_mask(crypto_uint16_x); +} + +static crypto_uint16 crypto_uint16_unequal_mask(crypto_uint16 crypto_uint16_x,crypto_uint16 crypto_uint16_y) +{ + crypto_uint16 crypto_uint16_xy = crypto_uint16_x ^ crypto_uint16_y; + return crypto_uint16_nonzero_mask(crypto_uint16_xy); +} + +static crypto_uint16 crypto_uint16_equal_mask(crypto_uint16 crypto_uint16_x,crypto_uint16 crypto_uint16_y) +{ + return ~crypto_uint16_unequal_mask(crypto_uint16_x,crypto_uint16_y); +} + +static crypto_uint16 crypto_uint16_smaller_mask(crypto_uint16 crypto_uint16_x,crypto_uint16 crypto_uint16_y) +{ + crypto_uint16 crypto_uint16_xy = crypto_uint16_x ^ crypto_uint16_y; + crypto_uint16 crypto_uint16_z = crypto_uint16_x - crypto_uint16_y; + crypto_uint16_z ^= crypto_uint16_xy & (crypto_uint16_z ^ crypto_uint16_x ^ (((crypto_uint16) 1) << 15)); + return crypto_uint16_signed_negative_mask(crypto_uint16_z); +} + +static crypto_uint16 crypto_uint16_min(crypto_uint16 crypto_uint16_x,crypto_uint16 crypto_uint16_y) +{ + crypto_uint16 crypto_uint16_xy = crypto_uint16_y ^ crypto_uint16_x; + crypto_uint16 crypto_uint16_z = crypto_uint16_y - crypto_uint16_x; + crypto_uint16_z ^= crypto_uint16_xy & (crypto_uint16_z ^ crypto_uint16_y ^ (((crypto_uint16) 1) << 15)); + crypto_uint16_z = crypto_uint16_signed_negative_mask(crypto_uint16_z); + crypto_uint16_z &= crypto_uint16_xy; + return crypto_uint16_x ^ crypto_uint16_z; +} + +static crypto_uint16 crypto_uint16_max(crypto_uint16 crypto_uint16_x,crypto_uint16 crypto_uint16_y) +{ + crypto_uint16 crypto_uint16_xy = crypto_uint16_y ^ crypto_uint16_x; + crypto_uint16 crypto_uint16_z = crypto_uint16_y - crypto_uint16_x; + crypto_uint16_z ^= crypto_uint16_xy & (crypto_uint16_z ^ crypto_uint16_y ^ (((crypto_uint16) 1) << 15)); + crypto_uint16_z = crypto_uint16_signed_negative_mask(crypto_uint16_z); + crypto_uint16_z &= crypto_uint16_xy; + return crypto_uint16_y ^ crypto_uint16_z; +} + +static void crypto_uint16_minmax(crypto_uint16 *crypto_uint16_a,crypto_uint16 *crypto_uint16_b) +{ + crypto_uint16 crypto_uint16_x = *crypto_uint16_a; + crypto_uint16 crypto_uint16_y = *crypto_uint16_b; + crypto_uint16 crypto_uint16_xy = crypto_uint16_y ^ crypto_uint16_x; + crypto_uint16 crypto_uint16_z = crypto_uint16_y - crypto_uint16_x; + crypto_uint16_z ^= crypto_uint16_xy & (crypto_uint16_z ^ crypto_uint16_y ^ (((crypto_uint16) 1) << 15)); + crypto_uint16_z = crypto_uint16_signed_negative_mask(crypto_uint16_z); + crypto_uint16_z &= crypto_uint16_xy; + *crypto_uint16_a = crypto_uint16_x ^ crypto_uint16_z; + *crypto_uint16_b = crypto_uint16_y ^ crypto_uint16_z; +} + +#endif diff --git a/deps/mceliece/kem/mceliece348864f/subroutines/crypto_uint32.h b/deps/mceliece/kem/mceliece348864f/subroutines/crypto_uint32.h new file mode 100644 index 0000000..3f39d62 --- /dev/null +++ b/deps/mceliece/kem/mceliece348864f/subroutines/crypto_uint32.h @@ -0,0 +1,76 @@ +#ifndef crypto_uint32_h +#define crypto_uint32_h + +#include +typedef uint32_t crypto_uint32; + +typedef int32_t crypto_uint32_signed; + +static crypto_uint32_signed crypto_uint32_signed_negative_mask(crypto_uint32_signed crypto_uint32_signed_x) +{ + return crypto_uint32_signed_x >> 31; +} + +static crypto_uint32 crypto_uint32_nonzero_mask(crypto_uint32 crypto_uint32_x) +{ + return crypto_uint32_signed_negative_mask(crypto_uint32_x) | crypto_uint32_signed_negative_mask(-crypto_uint32_x); +} + +static crypto_uint32 crypto_uint32_zero_mask(crypto_uint32 crypto_uint32_x) +{ + return ~crypto_uint32_nonzero_mask(crypto_uint32_x); +} + +static crypto_uint32 crypto_uint32_unequal_mask(crypto_uint32 crypto_uint32_x,crypto_uint32 crypto_uint32_y) +{ + crypto_uint32 crypto_uint32_xy = crypto_uint32_x ^ crypto_uint32_y; + return crypto_uint32_nonzero_mask(crypto_uint32_xy); +} + +static crypto_uint32 crypto_uint32_equal_mask(crypto_uint32 crypto_uint32_x,crypto_uint32 crypto_uint32_y) +{ + return ~crypto_uint32_unequal_mask(crypto_uint32_x,crypto_uint32_y); +} + +static crypto_uint32 crypto_uint32_smaller_mask(crypto_uint32 crypto_uint32_x,crypto_uint32 crypto_uint32_y) +{ + crypto_uint32 crypto_uint32_xy = crypto_uint32_x ^ crypto_uint32_y; + crypto_uint32 crypto_uint32_z = crypto_uint32_x - crypto_uint32_y; + crypto_uint32_z ^= crypto_uint32_xy & (crypto_uint32_z ^ crypto_uint32_x ^ (((crypto_uint32) 1) << 31)); + return crypto_uint32_signed_negative_mask(crypto_uint32_z); +} + +static crypto_uint32 crypto_uint32_min(crypto_uint32 crypto_uint32_x,crypto_uint32 crypto_uint32_y) +{ + crypto_uint32 crypto_uint32_xy = crypto_uint32_y ^ crypto_uint32_x; + crypto_uint32 crypto_uint32_z = crypto_uint32_y - crypto_uint32_x; + crypto_uint32_z ^= crypto_uint32_xy & (crypto_uint32_z ^ crypto_uint32_y ^ (((crypto_uint32) 1) << 31)); + crypto_uint32_z = crypto_uint32_signed_negative_mask(crypto_uint32_z); + crypto_uint32_z &= crypto_uint32_xy; + return crypto_uint32_x ^ crypto_uint32_z; +} + +static crypto_uint32 crypto_uint32_max(crypto_uint32 crypto_uint32_x,crypto_uint32 crypto_uint32_y) +{ + crypto_uint32 crypto_uint32_xy = crypto_uint32_y ^ crypto_uint32_x; + crypto_uint32 crypto_uint32_z = crypto_uint32_y - crypto_uint32_x; + crypto_uint32_z ^= crypto_uint32_xy & (crypto_uint32_z ^ crypto_uint32_y ^ (((crypto_uint32) 1) << 31)); + crypto_uint32_z = crypto_uint32_signed_negative_mask(crypto_uint32_z); + crypto_uint32_z &= crypto_uint32_xy; + return crypto_uint32_y ^ crypto_uint32_z; +} + +static void crypto_uint32_minmax(crypto_uint32 *crypto_uint32_a,crypto_uint32 *crypto_uint32_b) +{ + crypto_uint32 crypto_uint32_x = *crypto_uint32_a; + crypto_uint32 crypto_uint32_y = *crypto_uint32_b; + crypto_uint32 crypto_uint32_xy = crypto_uint32_y ^ crypto_uint32_x; + crypto_uint32 crypto_uint32_z = crypto_uint32_y - crypto_uint32_x; + crypto_uint32_z ^= crypto_uint32_xy & (crypto_uint32_z ^ crypto_uint32_y ^ (((crypto_uint32) 1) << 31)); + crypto_uint32_z = crypto_uint32_signed_negative_mask(crypto_uint32_z); + crypto_uint32_z &= crypto_uint32_xy; + *crypto_uint32_a = crypto_uint32_x ^ crypto_uint32_z; + *crypto_uint32_b = crypto_uint32_y ^ crypto_uint32_z; +} + +#endif diff --git a/deps/mceliece/kem/mceliece348864f/subroutines/crypto_uint64.h b/deps/mceliece/kem/mceliece348864f/subroutines/crypto_uint64.h new file mode 100644 index 0000000..42e2be9 --- /dev/null +++ b/deps/mceliece/kem/mceliece348864f/subroutines/crypto_uint64.h @@ -0,0 +1,76 @@ +#ifndef crypto_uint64_h +#define crypto_uint64_h + +#include +typedef uint64_t crypto_uint64; + +typedef int64_t crypto_uint64_signed; + +static crypto_uint64_signed crypto_uint64_signed_negative_mask(crypto_uint64_signed crypto_uint64_signed_x) +{ + return crypto_uint64_signed_x >> 63; +} + +static crypto_uint64 crypto_uint64_nonzero_mask(crypto_uint64 crypto_uint64_x) +{ + return crypto_uint64_signed_negative_mask(crypto_uint64_x) | crypto_uint64_signed_negative_mask(-crypto_uint64_x); +} + +static crypto_uint64 crypto_uint64_zero_mask(crypto_uint64 crypto_uint64_x) +{ + return ~crypto_uint64_nonzero_mask(crypto_uint64_x); +} + +static crypto_uint64 crypto_uint64_unequal_mask(crypto_uint64 crypto_uint64_x,crypto_uint64 crypto_uint64_y) +{ + crypto_uint64 crypto_uint64_xy = crypto_uint64_x ^ crypto_uint64_y; + return crypto_uint64_nonzero_mask(crypto_uint64_xy); +} + +static crypto_uint64 crypto_uint64_equal_mask(crypto_uint64 crypto_uint64_x,crypto_uint64 crypto_uint64_y) +{ + return ~crypto_uint64_unequal_mask(crypto_uint64_x,crypto_uint64_y); +} + +static crypto_uint64 crypto_uint64_smaller_mask(crypto_uint64 crypto_uint64_x,crypto_uint64 crypto_uint64_y) +{ + crypto_uint64 crypto_uint64_xy = crypto_uint64_x ^ crypto_uint64_y; + crypto_uint64 crypto_uint64_z = crypto_uint64_x - crypto_uint64_y; + crypto_uint64_z ^= crypto_uint64_xy & (crypto_uint64_z ^ crypto_uint64_x ^ (((crypto_uint64) 1) << 63)); + return crypto_uint64_signed_negative_mask(crypto_uint64_z); +} + +static crypto_uint64 crypto_uint64_min(crypto_uint64 crypto_uint64_x,crypto_uint64 crypto_uint64_y) +{ + crypto_uint64 crypto_uint64_xy = crypto_uint64_y ^ crypto_uint64_x; + crypto_uint64 crypto_uint64_z = crypto_uint64_y - crypto_uint64_x; + crypto_uint64_z ^= crypto_uint64_xy & (crypto_uint64_z ^ crypto_uint64_y ^ (((crypto_uint64) 1) << 63)); + crypto_uint64_z = crypto_uint64_signed_negative_mask(crypto_uint64_z); + crypto_uint64_z &= crypto_uint64_xy; + return crypto_uint64_x ^ crypto_uint64_z; +} + +static crypto_uint64 crypto_uint64_max(crypto_uint64 crypto_uint64_x,crypto_uint64 crypto_uint64_y) +{ + crypto_uint64 crypto_uint64_xy = crypto_uint64_y ^ crypto_uint64_x; + crypto_uint64 crypto_uint64_z = crypto_uint64_y - crypto_uint64_x; + crypto_uint64_z ^= crypto_uint64_xy & (crypto_uint64_z ^ crypto_uint64_y ^ (((crypto_uint64) 1) << 63)); + crypto_uint64_z = crypto_uint64_signed_negative_mask(crypto_uint64_z); + crypto_uint64_z &= crypto_uint64_xy; + return crypto_uint64_y ^ crypto_uint64_z; +} + +static void crypto_uint64_minmax(crypto_uint64 *crypto_uint64_a,crypto_uint64 *crypto_uint64_b) +{ + crypto_uint64 crypto_uint64_x = *crypto_uint64_a; + crypto_uint64 crypto_uint64_y = *crypto_uint64_b; + crypto_uint64 crypto_uint64_xy = crypto_uint64_y ^ crypto_uint64_x; + crypto_uint64 crypto_uint64_z = crypto_uint64_y - crypto_uint64_x; + crypto_uint64_z ^= crypto_uint64_xy & (crypto_uint64_z ^ crypto_uint64_y ^ (((crypto_uint64) 1) << 63)); + crypto_uint64_z = crypto_uint64_signed_negative_mask(crypto_uint64_z); + crypto_uint64_z &= crypto_uint64_xy; + *crypto_uint64_a = crypto_uint64_x ^ crypto_uint64_z; + *crypto_uint64_b = crypto_uint64_y ^ crypto_uint64_z; +} + +#endif diff --git a/deps/mceliece/kem/mceliece348864f/synd.c b/deps/mceliece/kem/mceliece348864f/synd.c new file mode 100644 index 0000000..c945647 --- /dev/null +++ b/deps/mceliece/kem/mceliece348864f/synd.c @@ -0,0 +1,36 @@ +/* + This file is for syndrome computation +*/ + +#include "synd.h" + +#include "params.h" +#include "root.h" + +#include + +/* input: Goppa polynomial f, support L, received word r */ +/* output: out, the syndrome of length 2t */ +void synd(gf *out, gf *f, gf *L, unsigned char *r) +{ + int i, j; + gf e, e_inv, c; + + for (j = 0; j < 2*SYS_T; j++) + out[j] = 0; + + for (i = 0; i < SYS_N; i++) + { + c = (r[i/8] >> (i%8)) & 1; + + e = eval(f, L[i]); + e_inv = gf_inv(gf_mul(e,e)); + + for (j = 0; j < 2*SYS_T; j++) + { + out[j] = gf_add(out[j], gf_mul(e_inv, c)); + e_inv = gf_mul(e_inv, L[i]); + } + } +} + diff --git a/deps/mceliece/kem/mceliece348864f/synd.h b/deps/mceliece/kem/mceliece348864f/synd.h new file mode 100644 index 0000000..9331406 --- /dev/null +++ b/deps/mceliece/kem/mceliece348864f/synd.h @@ -0,0 +1,14 @@ +/* + This file is for syndrome computation +*/ + +#ifndef SYND_H +#define SYND_H +#define synd CRYPTO_NAMESPACE(synd) + +#include "gf.h" + +void synd(gf *, gf *, gf *, unsigned char *); + +#endif + diff --git a/deps/mceliece/kem/mceliece348864f/transpose.c b/deps/mceliece/kem/mceliece348864f/transpose.c new file mode 100644 index 0000000..0da2bc5 --- /dev/null +++ b/deps/mceliece/kem/mceliece348864f/transpose.c @@ -0,0 +1,43 @@ +/* + This file is for matrix transposition +*/ + +#include "transpose.h" + +#include + +/* input: in, a 64x64 matrix over GF(2) */ +/* output: out, transpose of in */ +void transpose_64x64(uint64_t * out, uint64_t * in) +{ + int i, j, s, d; + + uint64_t x, y; + uint64_t masks[6][2] = { + {0x5555555555555555, 0xAAAAAAAAAAAAAAAA}, + {0x3333333333333333, 0xCCCCCCCCCCCCCCCC}, + {0x0F0F0F0F0F0F0F0F, 0xF0F0F0F0F0F0F0F0}, + {0x00FF00FF00FF00FF, 0xFF00FF00FF00FF00}, + {0x0000FFFF0000FFFF, 0xFFFF0000FFFF0000}, + {0x00000000FFFFFFFF, 0xFFFFFFFF00000000} + }; + + for (i = 0; i < 64; i++) + out[i] = in[i]; + + for (d = 5; d >= 0; d--) + { + s = 1 << d; + + for (i = 0; i < 64; i += s*2) + for (j = i; j < i+s; j++) + { + x = (out[j] & masks[d][0]) | ((out[j+s] & masks[d][0]) << s); + y = ((out[j] & masks[d][1]) >> s) | (out[j+s] & masks[d][1]); + + out[j+0] = x; + out[j+s] = y; + } + } +} + diff --git a/deps/mceliece/kem/mceliece348864f/transpose.h b/deps/mceliece/kem/mceliece348864f/transpose.h new file mode 100644 index 0000000..31e5b96 --- /dev/null +++ b/deps/mceliece/kem/mceliece348864f/transpose.h @@ -0,0 +1,14 @@ +/* + This file is for matrix transposition +*/ + +#ifndef TRANSPOSE_H +#define TRANSPOSE_H +#define transpose_64x64 CRYPTO_NAMESPACE(transpose_64x64) + +#include + +void transpose_64x64(uint64_t *, uint64_t *); + +#endif + diff --git a/deps/mceliece/kem/mceliece348864f/uint64_sort.h b/deps/mceliece/kem/mceliece348864f/uint64_sort.h new file mode 100644 index 0000000..2fb100c --- /dev/null +++ b/deps/mceliece/kem/mceliece348864f/uint64_sort.h @@ -0,0 +1,45 @@ +#ifndef uint64_sort_h +#define uint64_sort_h + +#define int64_sort CRYPTO_NAMESPACE(int64_sort) + +#include + +#define uint64_MINMAX(a,b) \ +do { \ + uint64_t c = b - a; \ + c >>= 63; \ + c = -c; \ + c &= a ^ b; \ + a ^= c; \ + b ^= c; \ +} while(0) + +static void uint64_sort(uint64_t *x,long long n) +{ + long long top,p,q,r,i; + + if (n < 2) return; + top = 1; + while (top < n - top) top += top; + + for (p = top;p > 0;p >>= 1) { + for (i = 0;i < n - p;++i) + if (!(i & p)) + uint64_MINMAX(x[i],x[i+p]); + i = 0; + for (q = top;q > p;q >>= 1) { + for (;i < n - q;++i) { + if (!(i & p)) { + uint64_t a = x[i + p]; + for (r = q;r > p;r >>= 1) + uint64_MINMAX(a,x[i+r]); + x[i + p] = a; + } + } + } + } +} + +#endif + diff --git a/deps/mceliece/kem/mceliece348864f/util.c b/deps/mceliece/kem/mceliece348864f/util.c new file mode 100644 index 0000000..bb4c82a --- /dev/null +++ b/deps/mceliece/kem/mceliece348864f/util.c @@ -0,0 +1,75 @@ +/* + This file is for loading/storing data in a little-endian fashion +*/ + +#include "util.h" + +#include "params.h" + +void store_gf(unsigned char *dest, gf a) +{ + dest[0] = a & 0xFF; + dest[1] = a >> 8; +} + +uint16_t load_gf(const unsigned char *src) +{ + uint16_t a; + + a = src[1]; + a <<= 8; + a |= src[0]; + + return a & GFMASK; +} + +uint32_t load4(const unsigned char * in) +{ + int i; + uint32_t ret = in[3]; + + for (i = 2; i >= 0; i--) + { + ret <<= 8; + ret |= in[i]; + } + + return ret; +} + +void store8(unsigned char *out, uint64_t in) +{ + out[0] = (in >> 0x00) & 0xFF; + out[1] = (in >> 0x08) & 0xFF; + out[2] = (in >> 0x10) & 0xFF; + out[3] = (in >> 0x18) & 0xFF; + out[4] = (in >> 0x20) & 0xFF; + out[5] = (in >> 0x28) & 0xFF; + out[6] = (in >> 0x30) & 0xFF; + out[7] = (in >> 0x38) & 0xFF; +} + +uint64_t load8(const unsigned char * in) +{ + int i; + uint64_t ret = in[7]; + + for (i = 6; i >= 0; i--) + { + ret <<= 8; + ret |= in[i]; + } + + return ret; +} + +gf bitrev(gf a) +{ + a = ((a & 0x00FF) << 8) | ((a & 0xFF00) >> 8); + a = ((a & 0x0F0F) << 4) | ((a & 0xF0F0) >> 4); + a = ((a & 0x3333) << 2) | ((a & 0xCCCC) >> 2); + a = ((a & 0x5555) << 1) | ((a & 0xAAAA) >> 1); + + return a >> 4; +} + diff --git a/deps/mceliece/kem/mceliece348864f/util.h b/deps/mceliece/kem/mceliece348864f/util.h new file mode 100644 index 0000000..5800430 --- /dev/null +++ b/deps/mceliece/kem/mceliece348864f/util.h @@ -0,0 +1,28 @@ +/* + This file is for loading/storing data in a little-endian fashion +*/ + +#ifndef UTIL_H +#define UTIL_H +#define bitrev CRYPTO_NAMESPACE(bitrev) +#define load4 CRYPTO_NAMESPACE(load4) +#define load8 CRYPTO_NAMESPACE(load8) +#define load_gf CRYPTO_NAMESPACE(load_gf) +#define store8 CRYPTO_NAMESPACE(store8) +#define store_gf CRYPTO_NAMESPACE(store_gf) + +#include "gf.h" +#include + +void store_gf(unsigned char *, gf); +uint16_t load_gf(const unsigned char *); + +uint32_t load4(const unsigned char *); + +void store8(unsigned char *, uint64_t ); +uint64_t load8(const unsigned char *); + +gf bitrev(gf); + +#endif + diff --git a/deps/mceliece/kem/mceliece460896/benes.c b/deps/mceliece/kem/mceliece460896/benes.c new file mode 100644 index 0000000..3b4e710 --- /dev/null +++ b/deps/mceliece/kem/mceliece460896/benes.c @@ -0,0 +1,181 @@ +/* + This file is for Benes network related functions + + For the implementation strategy, see + https://eprint.iacr.org/2017/793.pdf +*/ + +#include "util.h" +#include "transpose.h" +#include "params.h" +#include "benes.h" + +/* middle layers of the benes network */ +static void layer_in(uint64_t data[2][64], uint64_t * bits, int lgs) +{ + int i, j, s; + + uint64_t d; + + s = 1 << lgs; + + for (i = 0; i < 64; i += s*2) + for (j = i; j < i+s; j++) + { + + d = (data[0][j+0] ^ data[0][j+s]); + d &= (*bits++); + data[0][j+0] ^= d; + data[0][j+s] ^= d; + + d = (data[1][j+0] ^ data[1][j+s]); + d &= (*bits++); + data[1][j+0] ^= d; + data[1][j+s] ^= d; + } +} + +/* first and last layers of the benes network */ +static void layer_ex(uint64_t * data, uint64_t * bits, int lgs) +{ + int i, j, s; + + uint64_t d; + + s = 1 << lgs; + + for (i = 0; i < 128; i += s*2) + for (j = i; j < i+s; j++) + { + + d = (data[j+0] ^ data[j+s]); + d &= (*bits++); + data[j+0] ^= d; + data[j+s] ^= d; + } +} + +/* input: r, sequence of bits to be permuted */ +/* bits, condition bits of the Benes network */ +/* rev, 0 for normal application; !0 for inverse */ +/* output: r, permuted bits */ +void apply_benes(unsigned char * r, const unsigned char * bits, int rev) +{ + int i, iter, inc; + + unsigned char *r_ptr = r; + const unsigned char *bits_ptr; + + uint64_t r_int_v[2][64]; + uint64_t r_int_h[2][64]; + uint64_t b_int_v[64]; + uint64_t b_int_h[64]; + + // + + if (rev) { bits_ptr = bits + 12288; inc = -1024; } + else { bits_ptr = bits; inc = 0; } + + for (i = 0; i < 64; i++) + { + r_int_v[0][i] = load8(r_ptr + i*16 + 0); + r_int_v[1][i] = load8(r_ptr + i*16 + 8); + } + + transpose_64x64(r_int_h[0], r_int_v[0]); + transpose_64x64(r_int_h[1], r_int_v[1]); + + for (iter = 0; iter <= 6; iter++) + { + for (i = 0; i < 64; i++) + { + b_int_v[i] = load8(bits_ptr); bits_ptr += 8; + } + + bits_ptr += inc; + + transpose_64x64(b_int_h, b_int_v); + + layer_ex(r_int_h[0], b_int_h, iter); + } + + transpose_64x64(r_int_v[0], r_int_h[0]); + transpose_64x64(r_int_v[1], r_int_h[1]); + + for (iter = 0; iter <= 5; iter++) + { + for (i = 0; i < 64; i++) { b_int_v[i] = load8(bits_ptr); bits_ptr += 8; } + bits_ptr += inc; + + layer_in(r_int_v, b_int_v, iter); + } + + for (iter = 4; iter >= 0; iter--) + { + for (i = 0; i < 64; i++) { b_int_v[i] = load8(bits_ptr); bits_ptr += 8; } + bits_ptr += inc; + + layer_in(r_int_v, b_int_v, iter); + } + + transpose_64x64(r_int_h[0], r_int_v[0]); + transpose_64x64(r_int_h[1], r_int_v[1]); + + for (iter = 6; iter >= 0; iter--) + { + for (i = 0; i < 64; i++) + { + b_int_v[i] = load8(bits_ptr); bits_ptr += 8; + } + + bits_ptr += inc; + + transpose_64x64(b_int_h, b_int_v); + + layer_ex(r_int_h[0], b_int_h, iter); + } + + transpose_64x64(r_int_v[0], r_int_h[0]); + transpose_64x64(r_int_v[1], r_int_h[1]); + + for (i = 0; i < 64; i++) + { + store8(r_ptr + i*16 + 0, r_int_v[0][i]); + store8(r_ptr + i*16 + 8, r_int_v[1][i]); + } +} + +/* input: condition bits c */ +/* output: support s */ +void support_gen(gf * s, const unsigned char *c) +{ + gf a; + int i, j; + unsigned char L[ GFBITS ][ (1 << GFBITS)/8 ]; + + for (i = 0; i < GFBITS; i++) + for (j = 0; j < (1 << GFBITS)/8; j++) + L[i][j] = 0; + + for (i = 0; i < (1 << GFBITS); i++) + { + a = bitrev((gf) i); + + for (j = 0; j < GFBITS; j++) + L[j][ i/8 ] |= ((a >> j) & 1) << (i%8); + } + + for (j = 0; j < GFBITS; j++) + apply_benes(L[j], c, 0); + + for (i = 0; i < SYS_N; i++) + { + s[i] = 0; + for (j = GFBITS-1; j >= 0; j--) + { + s[i] <<= 1; + s[i] |= (L[j][i/8] >> (i%8)) & 1; + } + } +} + diff --git a/deps/mceliece/kem/mceliece460896/benes.h b/deps/mceliece/kem/mceliece460896/benes.h new file mode 100644 index 0000000..c2ef35a --- /dev/null +++ b/deps/mceliece/kem/mceliece460896/benes.h @@ -0,0 +1,16 @@ +/* + This file is for Benes network related functions +*/ + +#ifndef BENES_H +#define BENES_H +#define apply_benes CRYPTO_NAMESPACE(apply_benes) +#define support_gen CRYPTO_NAMESPACE(support_gen) + +#include "gf.h" + +void apply_benes(unsigned char *, const unsigned char *, int); +void support_gen(gf *, const unsigned char *); + +#endif + diff --git a/deps/mceliece/kem/mceliece460896/bm.c b/deps/mceliece/kem/mceliece460896/bm.c new file mode 100644 index 0000000..056a734 --- /dev/null +++ b/deps/mceliece/kem/mceliece460896/bm.c @@ -0,0 +1,72 @@ +/* + This file is for the Berlekamp-Massey algorithm + see http://crypto.stanford.edu/~mironov/cs359/massey.pdf +*/ + +#include "params.h" +#include "gf.h" +#include "bm.h" + +#define min(a, b) ((a < b) ? a : b) + +/* the Berlekamp-Massey algorithm */ +/* input: s, sequence of field elements */ +/* output: out, minimal polynomial of s */ +void bm(gf *out, gf *s) +{ + int i; + + uint16_t N = 0; + uint16_t L = 0; + uint16_t mle; + uint16_t mne; + + gf T[ SYS_T+1 ]; + gf C[ SYS_T+1 ]; + gf B[ SYS_T+1 ]; + + gf b = 1, d, f; + + // + + for (i = 0; i < SYS_T+1; i++) + C[i] = B[i] = 0; + + B[1] = C[0] = 1; + + // + + for (N = 0; N < 2 * SYS_T; N++) + { + d = 0; + + for (i = 0; i <= min(N, SYS_T); i++) + d ^= gf_mul(C[i], s[ N-i]); + + mne = d; mne -= 1; mne >>= 15; mne -= 1; + mle = N; mle -= 2*L; mle >>= 15; mle -= 1; + mle &= mne; + + for (i = 0; i <= SYS_T; i++) + T[i] = C[i]; + + f = gf_frac(b, d); + + for (i = 0; i <= SYS_T; i++) + C[i] ^= gf_mul(f, B[i]) & mne; + + L = (L & ~mle) | ((N+1-L) & mle); + + for (i = 0; i <= SYS_T; i++) + B[i] = (B[i] & ~mle) | (T[i] & mle); + + b = (b & ~mle) | (d & mle); + + for (i = SYS_T; i >= 1; i--) B[i] = B[i-1]; + B[0] = 0; + } + + for (i = 0; i <= SYS_T; i++) + out[i] = C[ SYS_T-i ]; +} + diff --git a/deps/mceliece/kem/mceliece460896/bm.h b/deps/mceliece/kem/mceliece460896/bm.h new file mode 100644 index 0000000..73d5c6c --- /dev/null +++ b/deps/mceliece/kem/mceliece460896/bm.h @@ -0,0 +1,13 @@ +/* + This file is for the Berlekamp-Massey algorithm + see http://crypto.stanford.edu/~mironov/cs359/massey.pdf +*/ + +#ifndef BM_H +#define BM_H +#define bm CRYPTO_NAMESPACE(bm) + +void bm(gf *, gf *); + +#endif + diff --git a/deps/mceliece/kem/mceliece460896/controlbits.c b/deps/mceliece/kem/mceliece460896/controlbits.c new file mode 100644 index 0000000..db9db9c --- /dev/null +++ b/deps/mceliece/kem/mceliece460896/controlbits.c @@ -0,0 +1,220 @@ +/* This file is for implementing the Nassimi-Sahni algorithm */ +/* See David Nassimi, Sartaj Sahni "Parallel algorithms to set up the Benes permutationnetwork" */ +/* See also https://cr.yp.to/papers/controlbits-20200923.pdf */ + +#include +#include "crypto_declassify.h" +#include "controlbits.h" +#include "int32_sort.h" +typedef int16_t int16; +typedef int32_t int32; +#include "crypto_int32.h" +#define int32_min crypto_int32_min +#include "crypto_int16.h" + +/* parameters: 1 <= w <= 14; n = 2^w */ +/* input: permutation pi of {0,1,...,n-1} */ +/* output: (2m-1)n/2 control bits at positions pos,pos+step,... */ +/* output position pos is by definition 1&(out[pos/8]>>(pos&7)) */ +/* caller must 0-initialize positions first */ +/* temp must have space for int32[2*n] */ +static void cbrecursion(unsigned char *out,long long pos,long long step,const int16 *pi,long long w,long long n,int32 *temp) +{ +#define A temp +#define B (temp+n) +#define q ((int16 *) (temp+n+n/4)) +/* q can start anywhere between temp+n and temp+n/2 */ + + long long x,i,j,k; + + if (w == 1) { + out[pos>>3] ^= pi[0]<<(pos&7); + return; + } + + for (x = 0;x < n;++x) A[x] = ((pi[x]^1)<<16)|pi[x^1]; + int32_sort(A,n); /* A = (id<<16)+pibar */ + + for (x = 0;x < n;++x) { + int32 Ax = A[x]; + int32 px = Ax&0xffff; + int32 cx = int32_min(px,x); + B[x] = (px<<16)|cx; + } + /* B = (p<<16)+c */ + + for (x = 0;x < n;++x) A[x] = (A[x]<<16)|x; /* A = (pibar<<16)+id */ + int32_sort(A,n); /* A = (id<<16)+pibar^-1 */ + + for (x = 0;x < n;++x) A[x] = (A[x]<<16)+(B[x]>>16); /* A = (pibar^(-1)<<16)+pibar */ + int32_sort(A,n); /* A = (id<<16)+pibar^2 */ + + if (w <= 10) { + for (x = 0;x < n;++x) B[x] = ((A[x]&0xffff)<<10)|(B[x]&0x3ff); + + for (i = 1;i < w-1;++i) { + /* B = (p<<10)+c */ + + for (x = 0;x < n;++x) A[x] = ((B[x]&~0x3ff)<<6)|x; /* A = (p<<16)+id */ + int32_sort(A,n); /* A = (id<<16)+p^{-1} */ + + for (x = 0;x < n;++x) A[x] = (A[x]<<20)|B[x]; /* A = (p^{-1}<<20)+(p<<10)+c */ + int32_sort(A,n); /* A = (id<<20)+(pp<<10)+cp */ + + for (x = 0;x < n;++x) { + int32 ppcpx = A[x]&0xfffff; + int32 ppcx = (A[x]&0xffc00)|(B[x]&0x3ff); + B[x] = int32_min(ppcx,ppcpx); + } + } + for (x = 0;x < n;++x) B[x] &= 0x3ff; + } else { + for (x = 0;x < n;++x) B[x] = (A[x]<<16)|(B[x]&0xffff); + + for (i = 1;i < w-1;++i) { + /* B = (p<<16)+c */ + + for (x = 0;x < n;++x) A[x] = (B[x]&~0xffff)|x; + int32_sort(A,n); /* A = (id<<16)+p^(-1) */ + + for (x = 0;x < n;++x) A[x] = (A[x]<<16)|(B[x]&0xffff); + /* A = p^(-1)<<16+c */ + + if (i < w-2) { + for (x = 0;x < n;++x) B[x] = (A[x]&~0xffff)|(B[x]>>16); + /* B = (p^(-1)<<16)+p */ + int32_sort(B,n); /* B = (id<<16)+p^(-2) */ + for (x = 0;x < n;++x) B[x] = (B[x]<<16)|(A[x]&0xffff); + /* B = (p^(-2)<<16)+c */ + } + + int32_sort(A,n); + /* A = id<<16+cp */ + for (x = 0;x < n;++x) { + int32 cpx = (B[x]&~0xffff)|(A[x]&0xffff); + B[x] = int32_min(B[x],cpx); + } + } + for (x = 0;x < n;++x) B[x] &= 0xffff; + } + + for (x = 0;x < n;++x) A[x] = (((int32)pi[x])<<16)+x; + int32_sort(A,n); /* A = (id<<16)+pi^(-1) */ + + for (j = 0;j < n/2;++j) { + long long x = 2*j; + int32 fj = B[x]&1; /* f[j] */ + int32 Fx = x+fj; /* F[x] */ + int32 Fx1 = Fx^1; /* F[x+1] */ + + out[pos>>3] ^= fj<<(pos&7); + pos += step; + + B[x] = (A[x]<<16)|Fx; + B[x+1] = (A[x+1]<<16)|Fx1; + } + /* B = (pi^(-1)<<16)+F */ + + int32_sort(B,n); /* B = (id<<16)+F(pi) */ + + pos += (2*w-3)*step*(n/2); + + for (k = 0;k < n/2;++k) { + long long y = 2*k; + int32 lk = B[y]&1; /* l[k] */ + int32 Ly = y+lk; /* L[y] */ + int32 Ly1 = Ly^1; /* L[y+1] */ + + out[pos>>3] ^= lk<<(pos&7); + pos += step; + + A[y] = (Ly<<16)|(B[y]&0xffff); + A[y+1] = (Ly1<<16)|(B[y+1]&0xffff); + } + /* A = (L<<16)+F(pi) */ + + int32_sort(A,n); /* A = (id<<16)+F(pi(L)) = (id<<16)+M */ + + pos -= (2*w-2)*step*(n/2); + + for (j = 0;j < n/2;++j) { + q[j] = (A[2*j]&0xffff)>>1; + q[j+n/2] = (A[2*j+1]&0xffff)>>1; + } + + cbrecursion(out,pos,step*2,q,w-1,n/2,temp); + cbrecursion(out,pos+step,step*2,q+n/2,w-1,n/2,temp); +} + +/* input: p, an array of int16 */ +/* input: n, length of p */ +/* input: s, meaning that stride-2^s cswaps are performed */ +/* input: cb, the control bits */ +/* output: the result of apply the control bits to p */ +static void layer(int16_t *p, const unsigned char *cb, int s, int n) +{ + int i, j; + int stride = 1 << s; + int index = 0; + int16_t d, m; + + for (i = 0; i < n; i += stride*2) + { + for (j = 0; j < stride; j++) + { + d = p[ i+j ] ^ p[ i+j+stride ]; + m = (cb[ index >> 3 ] >> (index & 7)) & 1; + m = -m; + d &= m; + p[ i+j ] ^= d; + p[ i+j+stride ] ^= d; + index++; + } + } +} + +/* parameters: 1 <= w <= 14; n = 2^w */ +/* input: permutation pi of {0,1,...,n-1} */ +/* output: (2m-1)n/2 control bits at positions 0,1,... */ +/* output position pos is by definition 1&(out[pos/8]>>(pos&7)) */ +void controlbitsfrompermutation(unsigned char *out,const int16 *pi,long long w,long long n) +{ + int32 temp[2*n]; + int16 pi_test[n], diff; + int i; + unsigned char *ptr; + + while (1) + { + memset(out,0,(((2*w-1)*n/2)+7)/8); + cbrecursion(out,0,1,pi,w,n,temp); + + // check for correctness + + for (i = 0; i < n; i++) + pi_test[i] = i; + + ptr = out; + for (i = 0; i < w; i++) + { + layer(pi_test, ptr, i, n); + ptr += n >> 4; + } + + for (i = w-2; i >= 0; i--) + { + layer(pi_test, ptr, i, n); + ptr += n >> 4; + } + + diff = 0; + for (i = 0; i < n; i++) + diff |= pi[i] ^ pi_test[i]; + + diff = crypto_int16_nonzero_mask(diff); + crypto_declassify(&diff,sizeof diff); + if (diff == 0) + break; + } +} + diff --git a/deps/mceliece/kem/mceliece460896/controlbits.h b/deps/mceliece/kem/mceliece460896/controlbits.h new file mode 100644 index 0000000..8ddd210 --- /dev/null +++ b/deps/mceliece/kem/mceliece460896/controlbits.h @@ -0,0 +1,14 @@ +/* This file is for implementing the Nassimi-Sahni algorithm */ +/* See David Nassimi, Sartaj Sahni "Parallel algorithms to set up the Benes permutationnetwork" */ +/* See also https://cr.yp.to/papers/controlbits-20200923.pdf */ + +#ifndef CONTROLBITS_H +#define CONTROLBITS_H + +#define controlbitsfrompermutation CRYPTO_NAMESPACE(controlbitsfrompermutation) + +#include + +extern void controlbitsfrompermutation(unsigned char *,const int16_t *,long long,long long); + +#endif diff --git a/deps/mceliece/kem/mceliece460896/crypto_hash.h b/deps/mceliece/kem/mceliece460896/crypto_hash.h new file mode 100644 index 0000000..b7c1086 --- /dev/null +++ b/deps/mceliece/kem/mceliece460896/crypto_hash.h @@ -0,0 +1,10 @@ +/* This file uses SHAKE256 implemented in the Keccak Code Package */ + +#include "../../mceliece_externals.h" + +#define crypto_hash_32b(out,in,inlen) \ + SHAKE256(out,32,in,inlen) + +#define shake(out,outlen,in,inlen) \ + SHAKE256(out,outlen,in,inlen) + diff --git a/deps/mceliece/kem/mceliece460896/crypto_kem.h b/deps/mceliece/kem/mceliece460896/crypto_kem.h new file mode 100644 index 0000000..18592c1 --- /dev/null +++ b/deps/mceliece/kem/mceliece460896/crypto_kem.h @@ -0,0 +1,15 @@ +#ifndef crypto_kem_H +#define crypto_kem_H + +#include "crypto_kem_mceliece460896.h" + +#define crypto_kem_keypair crypto_kem_mceliece460896_keypair +#define crypto_kem_enc crypto_kem_mceliece460896_enc +#define crypto_kem_dec crypto_kem_mceliece460896_dec +#define crypto_kem_PUBLICKEYBYTES crypto_kem_mceliece460896_PUBLICKEYBYTES +#define crypto_kem_SECRETKEYBYTES crypto_kem_mceliece460896_SECRETKEYBYTES +#define crypto_kem_BYTES crypto_kem_mceliece460896_BYTES +#define crypto_kem_CIPHERTEXTBYTES crypto_kem_mceliece460896_CIPHERTEXTBYTES +#define crypto_kem_PRIMITIVE "mceliece460896" + +#endif diff --git a/deps/mceliece/kem/mceliece460896/crypto_kem_mceliece460896.h b/deps/mceliece/kem/mceliece460896/crypto_kem_mceliece460896.h new file mode 100644 index 0000000..9fb1e56 --- /dev/null +++ b/deps/mceliece/kem/mceliece460896/crypto_kem_mceliece460896.h @@ -0,0 +1,28 @@ +#ifndef crypto_kem_mceliece460896_H +#define crypto_kem_mceliece460896_H + +#define crypto_kem_mceliece460896_ref_PUBLICKEYBYTES 524160 +#define crypto_kem_mceliece460896_ref_SECRETKEYBYTES 13608 +#define crypto_kem_mceliece460896_ref_CIPHERTEXTBYTES 156 +#define crypto_kem_mceliece460896_ref_BYTES 32 + + +#ifdef __cplusplus +extern "C" { +#endif +extern int crypto_kem_mceliece460896_ref_keypair(unsigned char *,unsigned char *); +extern int crypto_kem_mceliece460896_ref_enc(unsigned char *,unsigned char *,const unsigned char *); +extern int crypto_kem_mceliece460896_ref_dec(unsigned char *,const unsigned char *,const unsigned char *); +#ifdef __cplusplus +} +#endif + +#define crypto_kem_mceliece460896_keypair crypto_kem_mceliece460896_ref_keypair +#define crypto_kem_mceliece460896_enc crypto_kem_mceliece460896_ref_enc +#define crypto_kem_mceliece460896_dec crypto_kem_mceliece460896_ref_dec +#define crypto_kem_mceliece460896_PUBLICKEYBYTES crypto_kem_mceliece460896_ref_PUBLICKEYBYTES +#define crypto_kem_mceliece460896_SECRETKEYBYTES crypto_kem_mceliece460896_ref_SECRETKEYBYTES +#define crypto_kem_mceliece460896_BYTES crypto_kem_mceliece460896_ref_BYTES +#define crypto_kem_mceliece460896_CIPHERTEXTBYTES crypto_kem_mceliece460896_ref_CIPHERTEXTBYTES + +#endif diff --git a/deps/mceliece/kem/mceliece460896/decrypt.c b/deps/mceliece/kem/mceliece460896/decrypt.c new file mode 100644 index 0000000..c4cc6de --- /dev/null +++ b/deps/mceliece/kem/mceliece460896/decrypt.c @@ -0,0 +1,93 @@ +/* + This file is for Niederreiter decryption +*/ + +#include +#include "decrypt.h" + +#include "params.h" +#include "benes.h" +#include "util.h" +#include "synd.h" +#include "root.h" +#include "gf.h" +#include "bm.h" + +/* Niederreiter decryption with the Berlekamp decoder */ +/* intput: sk, secret key */ +/* c, ciphertext */ +/* output: e, error vector */ +/* return: 0 for success; 1 for failure */ +int decrypt(unsigned char *e, const unsigned char *sk, const unsigned char *c) +{ + int i, w = 0; + uint16_t check; + + unsigned char r[ SYS_N/8 ]; + + gf g[ SYS_T+1 ]; + gf L[ SYS_N ]; + + gf s[ SYS_T*2 ]; + gf s_cmp[ SYS_T*2 ]; + gf locator[ SYS_T+1 ]; + gf images[ SYS_N ]; + + gf t; + + // + + for (i = 0; i < SYND_BYTES; i++) r[i] = c[i]; + for (i = SYND_BYTES; i < SYS_N/8; i++) r[i] = 0; + + for (i = 0; i < SYS_T; i++) { g[i] = load_gf(sk); sk += 2; } g[ SYS_T ] = 1; + + support_gen(L, sk); + + synd(s, g, L, r); + + bm(locator, s); + + root(images, locator, L); + + // + + for (i = 0; i < SYS_N/8; i++) + e[i] = 0; + + for (i = 0; i < SYS_N; i++) + { + t = gf_iszero(images[i]) & 1; + + e[ i/8 ] |= t << (i%8); + w += t; + + } + +#ifdef KAT + { + int k; + printf("decrypt e: positions"); + for (k = 0;k < SYS_N;++k) + if (e[k/8] & (1 << (k&7))) + printf(" %d",k); + printf("\n"); + } +#endif + + synd(s_cmp, g, L, e); + + // + + check = w; + check ^= SYS_T; + + for (i = 0; i < SYS_T*2; i++) + check |= s[i] ^ s_cmp[i]; + + check -= 1; + check >>= 15; + + return check ^ 1; +} + diff --git a/deps/mceliece/kem/mceliece460896/decrypt.h b/deps/mceliece/kem/mceliece460896/decrypt.h new file mode 100644 index 0000000..266a5cd --- /dev/null +++ b/deps/mceliece/kem/mceliece460896/decrypt.h @@ -0,0 +1,12 @@ +/* + This file is for Nieddereiter decryption +*/ + +#ifndef DECRYPT_H +#define DECRYPT_H +#define decrypt CRYPTO_NAMESPACE(decrypt) + +int decrypt(unsigned char *, const unsigned char *, const unsigned char *); + +#endif + diff --git a/deps/mceliece/kem/mceliece460896/encrypt.c b/deps/mceliece/kem/mceliece460896/encrypt.c new file mode 100644 index 0000000..4823d2f --- /dev/null +++ b/deps/mceliece/kem/mceliece460896/encrypt.c @@ -0,0 +1,161 @@ +/* + This file is for Niederreiter encryption +*/ + +#include "encrypt.h" + +#include "util.h" +#include "params.h" +#include "randombytes.h" + +#include +#include +#include +#include + +#include "gf.h" +#include "crypto_declassify.h" +#include "crypto_uint16.h" +#include "crypto_uint32.h" + +static inline crypto_uint16 uint16_is_smaller_declassify(uint16_t t,uint16_t u) +{ + crypto_uint16 mask = crypto_uint16_smaller_mask(t,u); + crypto_declassify(&mask,sizeof mask); + return mask; +} + +static inline crypto_uint32 uint32_is_equal_declassify(uint32_t t,uint32_t u) +{ + crypto_uint32 mask = crypto_uint32_equal_mask(t,u); + crypto_declassify(&mask,sizeof mask); + return mask; +} + +static inline unsigned char same_mask(uint16_t x, uint16_t y) +{ + uint32_t mask; + + mask = x ^ y; + mask -= 1; + mask >>= 31; + mask = -mask; + + return mask & 0xFF; +} + +/* output: e, an error vector of weight t */ +static void gen_e(unsigned char *e) +{ + int i, j, eq, count; + + union + { + uint16_t nums[ SYS_T*2 ]; + unsigned char bytes[ SYS_T*2 * sizeof(uint16_t) ]; + } buf; + + uint16_t ind[ SYS_T ]; + unsigned char mask; + unsigned char val[ SYS_T ]; + + while (1) + { + randombytes(buf.bytes, sizeof(buf)); + + for (i = 0; i < SYS_T*2; i++) + buf.nums[i] = load_gf(buf.bytes + i*2); + + // moving and counting indices in the correct range + + count = 0; + for (i = 0; i < SYS_T*2 && count < SYS_T; i++) + if (uint16_is_smaller_declassify(buf.nums[i],SYS_N)) + ind[ count++ ] = buf.nums[i]; + + if (count < SYS_T) continue; + + // check for repetition + + eq = 0; + + for (i = 1; i < SYS_T; i++) + for (j = 0; j < i; j++) + if (uint32_is_equal_declassify(ind[i],ind[j])) + eq = 1; + + if (eq == 0) + break; + } + + for (j = 0; j < SYS_T; j++) + val[j] = 1 << (ind[j] & 7); + + for (i = 0; i < SYS_N/8; i++) + { + e[i] = 0; + + for (j = 0; j < SYS_T; j++) + { + mask = same_mask(i, (ind[j] >> 3)); + + e[i] |= val[j] & mask; + } + } +} + +/* input: public key pk, error vector e */ +/* output: syndrome s */ +static void syndrome(unsigned char *s, const unsigned char *pk, unsigned char *e) +{ + unsigned char b, row[SYS_N/8]; + const unsigned char *pk_ptr = pk; + + int i, j; + + for (i = 0; i < SYND_BYTES; i++) + s[i] = 0; + + for (i = 0; i < PK_NROWS; i++) + { + for (j = 0; j < SYS_N/8; j++) + row[j] = 0; + + for (j = 0; j < PK_ROW_BYTES; j++) + row[ SYS_N/8 - PK_ROW_BYTES + j ] = pk_ptr[j]; + + row[i/8] |= 1 << (i%8); + + b = 0; + for (j = 0; j < SYS_N/8; j++) + b ^= row[j] & e[j]; + + b ^= b >> 4; + b ^= b >> 2; + b ^= b >> 1; + b &= 1; + + s[ i/8 ] |= (b << (i%8)); + + pk_ptr += PK_ROW_BYTES; + } +} + +void encrypt(unsigned char *s, const unsigned char *pk, unsigned char *e) +{ + gen_e(e); + +#ifdef KAT + { + int k; + printf("encrypt e: positions"); + for (k = 0;k < SYS_N;++k) + if (e[k/8] & (1 << (k&7))) + printf(" %d",k); + printf("\n"); + } +#endif + + syndrome(s, pk, e); +} + diff --git a/deps/mceliece/kem/mceliece460896/encrypt.h b/deps/mceliece/kem/mceliece460896/encrypt.h new file mode 100644 index 0000000..8edd7a6 --- /dev/null +++ b/deps/mceliece/kem/mceliece460896/encrypt.h @@ -0,0 +1,12 @@ +/* + This file is for Niederreiter encryption +*/ + +#ifndef ENCRYPT_H +#define ENCRYPT_H +#define encrypt CRYPTO_NAMESPACE(encrypt) + +void encrypt(unsigned char *, const unsigned char *, unsigned char *); + +#endif + diff --git a/deps/mceliece/kem/mceliece460896/gf.c b/deps/mceliece/kem/mceliece460896/gf.c new file mode 100644 index 0000000..ce28327 --- /dev/null +++ b/deps/mceliece/kem/mceliece460896/gf.c @@ -0,0 +1,215 @@ +/* + This file is for functions for field arithmetic +*/ + +#include "gf.h" + +#include "params.h" + +gf gf_iszero(gf a) +{ + uint32_t t = a; + + t -= 1; + t >>= 19; + + return (gf) t; +} + +gf gf_add(gf in0, gf in1) +{ + return in0 ^ in1; +} + +gf gf_mul(gf in0, gf in1) +{ + int i; + + uint64_t tmp; + uint64_t t0; + uint64_t t1; + uint64_t t; + + t0 = in0; + t1 = in1; + + tmp = t0 * (t1 & 1); + + for (i = 1; i < GFBITS; i++) + tmp ^= (t0 * (t1 & (1 << i))); + + // + + t = tmp & 0x1FF0000; + tmp ^= (t >> 9) ^ (t >> 10) ^ (t >> 12) ^ (t >> 13); + + t = tmp & 0x000E000; + tmp ^= (t >> 9) ^ (t >> 10) ^ (t >> 12) ^ (t >> 13); + + return tmp & GFMASK; +} + +/* input: field element in */ +/* return: (in^2)^2 */ +static inline gf gf_sq2(gf in) +{ + int i; + + const uint64_t B[] = {0x1111111111111111, + 0x0303030303030303, + 0x000F000F000F000F, + 0x000000FF000000FF}; + + const uint64_t M[] = {0x0001FF0000000000, + 0x000000FF80000000, + 0x000000007FC00000, + 0x00000000003FE000}; + + uint64_t x = in; + uint64_t t; + + x = (x | (x << 24)) & B[3]; + x = (x | (x << 12)) & B[2]; + x = (x | (x << 6)) & B[1]; + x = (x | (x << 3)) & B[0]; + + for (i = 0; i < 4; i++) + { + t = x & M[i]; + x ^= (t >> 9) ^ (t >> 10) ^ (t >> 12) ^ (t >> 13); + } + + return x & GFMASK; +} + +/* input: field element in, m */ +/* return: (in^2)*m */ +static inline gf gf_sqmul(gf in, gf m) +{ + int i; + + uint64_t x; + uint64_t t0; + uint64_t t1; + uint64_t t; + + const uint64_t M[] = {0x0000001FF0000000, + 0x000000000FF80000, + 0x000000000007E000}; + + t0 = in; + t1 = m; + + x = (t1 << 6) * (t0 & (1 << 6)); + + t0 ^= (t0 << 7); + + x ^= (t1 * (t0 & (0x04001))); + x ^= (t1 * (t0 & (0x08002))) << 1; + x ^= (t1 * (t0 & (0x10004))) << 2; + x ^= (t1 * (t0 & (0x20008))) << 3; + x ^= (t1 * (t0 & (0x40010))) << 4; + x ^= (t1 * (t0 & (0x80020))) << 5; + + for (i = 0; i < 3; i++) + { + t = x & M[i]; + x ^= (t >> 9) ^ (t >> 10) ^ (t >> 12) ^ (t >> 13); + } + + return x & GFMASK; +} + +/* input: field element in, m */ +/* return: ((in^2)^2)*m */ +static inline gf gf_sq2mul(gf in, gf m) +{ + int i; + + uint64_t x; + uint64_t t0; + uint64_t t1; + uint64_t t; + + const uint64_t M[] = {0x1FF0000000000000, + 0x000FF80000000000, + 0x000007FC00000000, + 0x00000003FE000000, + 0x0000000001FE0000, + 0x000000000001E000}; + + t0 = in; + t1 = m; + + x = (t1 << 18) * (t0 & (1 << 6)); + + t0 ^= (t0 << 21); + + x ^= (t1 * (t0 & (0x010000001))); + x ^= (t1 * (t0 & (0x020000002))) << 3; + x ^= (t1 * (t0 & (0x040000004))) << 6; + x ^= (t1 * (t0 & (0x080000008))) << 9; + x ^= (t1 * (t0 & (0x100000010))) << 12; + x ^= (t1 * (t0 & (0x200000020))) << 15; + + for (i = 0; i < 6; i++) + { + t = x & M[i]; + x ^= (t >> 9) ^ (t >> 10) ^ (t >> 12) ^ (t >> 13); + } + + return x & GFMASK; +} + +/* input: field element den, num */ +/* return: (num/den) */ +gf gf_frac(gf den, gf num) +{ + gf tmp_11; + gf tmp_1111; + gf out; + + tmp_11 = gf_sqmul(den, den); // ^11 + tmp_1111 = gf_sq2mul(tmp_11, tmp_11); // ^1111 + out = gf_sq2(tmp_1111); + out = gf_sq2mul(out, tmp_1111); // ^11111111 + out = gf_sq2(out); + out = gf_sq2mul(out, tmp_1111); // ^111111111111 + + return gf_sqmul(out, num); // ^1111111111110 = ^-1 +} + +gf gf_inv(gf den) +{ + return gf_frac(den, ((gf) 1)); +} + +/* input: in0, in1 in GF((2^m)^t)*/ +/* output: out = in0*in1 */ +void GF_mul(gf *out, gf *in0, gf *in1) +{ + int i, j; + + gf prod[ SYS_T*2-1 ]; + + for (i = 0; i < SYS_T*2-1; i++) + prod[i] = 0; + + for (i = 0; i < SYS_T; i++) + for (j = 0; j < SYS_T; j++) + prod[i+j] ^= gf_mul(in0[i], in1[j]); + + // + + for (i = (SYS_T-1)*2; i >= SYS_T; i--) + { + prod[i - SYS_T + 10] ^= prod[i]; + prod[i - SYS_T + 9] ^= prod[i]; + prod[i - SYS_T + 6] ^= prod[i]; + prod[i - SYS_T + 0] ^= prod[i]; + } + + for (i = 0; i < SYS_T; i++) + out[i] = prod[i]; +} + diff --git a/deps/mceliece/kem/mceliece460896/gf.h b/deps/mceliece/kem/mceliece460896/gf.h new file mode 100644 index 0000000..f62209d --- /dev/null +++ b/deps/mceliece/kem/mceliece460896/gf.h @@ -0,0 +1,27 @@ +/* + This file is for functions for field arithmetic +*/ + +#ifndef GF_H +#define GF_H +#define gf_add CRYPTO_NAMESPACE(gf_add) +#define gf_frac CRYPTO_NAMESPACE(gf_frac) +#define gf_inv CRYPTO_NAMESPACE(gf_inv) +#define gf_iszero CRYPTO_NAMESPACE(gf_iszero) +#define gf_mul CRYPTO_NAMESPACE(gf_mul) +#define GF_mul CRYPTO_NAMESPACE(GF_mul) + +#include + +typedef uint16_t gf; + +gf gf_iszero(gf); +gf gf_add(gf, gf); +gf gf_mul(gf, gf); +gf gf_frac(gf, gf); +gf gf_inv(gf); + +void GF_mul(gf *, gf *, gf *); + +#endif + diff --git a/deps/mceliece/kem/mceliece460896/int32_sort.h b/deps/mceliece/kem/mceliece460896/int32_sort.h new file mode 100644 index 0000000..a431af2 --- /dev/null +++ b/deps/mceliece/kem/mceliece460896/int32_sort.h @@ -0,0 +1,46 @@ +#ifndef int32_sort_h +#define int32_sort_h + +#define int32_sort CRYPTO_NAMESPACE(int32_sort) + +#include + +#define int32_MINMAX(a,b) \ +do { \ + int32_t ab = b ^ a; \ + int32_t c = b - a; \ + c ^= ab & (c ^ b); \ + c >>= 31; \ + c &= ab; \ + a ^= c; \ + b ^= c; \ +} while(0) + +static void int32_sort(int32_t *x,long long n) +{ + long long top,p,q,r,i; + + if (n < 2) return; + top = 1; + while (top < n - top) top += top; + + for (p = top;p > 0;p >>= 1) { + for (i = 0;i < n - p;++i) + if (!(i & p)) + int32_MINMAX(x[i],x[i+p]); + i = 0; + for (q = top;q > p;q >>= 1) { + for (;i < n - q;++i) { + if (!(i & p)) { + int32_t a = x[i + p]; + for (r = q;r > p;r >>= 1) + int32_MINMAX(a,x[i+r]); + x[i + p] = a; + } + } + } + } +} + +#endif + diff --git a/deps/mceliece/kem/mceliece460896/operations.c b/deps/mceliece/kem/mceliece460896/operations.c new file mode 100644 index 0000000..d05e774 --- /dev/null +++ b/deps/mceliece/kem/mceliece460896/operations.c @@ -0,0 +1,146 @@ +#include "operations.h" + +#include "controlbits.h" +#include "randombytes.h" +#include "crypto_hash.h" +#include "encrypt.h" +#include "decrypt.h" +#include "params.h" +#include "sk_gen.h" +#include "pk_gen.h" +#include "util.h" + +#include +#include + +int crypto_kem_enc( + unsigned char *c, + unsigned char *key, + const unsigned char *pk +) +{ + unsigned char e[ SYS_N/8 ]; + unsigned char one_ec[ 1 + SYS_N/8 + SYND_BYTES ] = {1}; + + // + + encrypt(c, pk, e); + + memcpy(one_ec + 1, e, SYS_N/8); + memcpy(one_ec + 1 + SYS_N/8, c, SYND_BYTES); + + crypto_hash_32b(key, one_ec, sizeof(one_ec)); + + return 0; +} + +int crypto_kem_dec( + unsigned char *key, + const unsigned char *c, + const unsigned char *sk +) +{ + int i; + + unsigned char ret_decrypt = 0; + + uint16_t m; + + unsigned char e[ SYS_N/8 ]; + unsigned char preimage[ 1 + SYS_N/8 + SYND_BYTES ]; + unsigned char *x = preimage; + const unsigned char *s = sk + 40 + IRR_BYTES + COND_BYTES; + + // + + ret_decrypt = decrypt(e, sk + 40, c); + + m = ret_decrypt; + m -= 1; + m >>= 8; + + *x++ = m & 1; + for (i = 0; i < SYS_N/8; i++) + *x++ = (~m & s[i]) | (m & e[i]); + + for (i = 0; i < SYND_BYTES; i++) + *x++ = c[i]; + + crypto_hash_32b(key, preimage, sizeof(preimage)); + + return 0; +} + +int crypto_kem_keypair +( + unsigned char *pk, + unsigned char *sk +) +{ + int i; + unsigned char seed[ 33 ] = {64}; + unsigned char r[ SYS_N/8 + (1 << GFBITS)*sizeof(uint32_t) + SYS_T*2 + 32 ]; + unsigned char *rp, *skp; + + gf f[ SYS_T ]; // element in GF(2^mt) + gf irr[ SYS_T ]; // Goppa polynomial + uint32_t perm[ 1 << GFBITS ]; // random permutation as 32-bit integers + int16_t pi[ 1 << GFBITS ]; // random permutation + + randombytes(seed+1, 32); + + while (1) + { + rp = &r[ sizeof(r)-32 ]; + skp = sk; + + // expanding and updating the seed + + shake(r, sizeof(r), seed, 33); + memcpy(skp, seed+1, 32); + skp += 32 + 8; + memcpy(seed+1, &r[ sizeof(r)-32 ], 32); + + // generating irreducible polynomial + + rp -= sizeof(f); + + for (i = 0; i < SYS_T; i++) + f[i] = load_gf(rp + i*2); + + if (genpoly_gen(irr, f)) + continue; + + for (i = 0; i < SYS_T; i++) + store_gf(skp + i*2, irr[i]); + + skp += IRR_BYTES; + + // generating permutation + + rp -= sizeof(perm); + + for (i = 0; i < (1 << GFBITS); i++) + perm[i] = load4(rp + i*4); + + if (pk_gen(pk, skp - IRR_BYTES, perm, pi)) + continue; + + controlbitsfrompermutation(skp, pi, GFBITS, 1 << GFBITS); + skp += COND_BYTES; + + // storing the random string s + + rp -= SYS_N/8; + memcpy(skp, rp, SYS_N/8); + + // storing positions of the 32 pivots + + store8(sk + 32, 0xFFFFFFFF); + + break; + } + + return 0; +} + diff --git a/deps/mceliece/kem/mceliece460896/operations.h b/deps/mceliece/kem/mceliece460896/operations.h new file mode 100644 index 0000000..bf65502 --- /dev/null +++ b/deps/mceliece/kem/mceliece460896/operations.h @@ -0,0 +1,25 @@ +#ifndef OPERATIONS_H +#define OPERATIONS_H + +#include "crypto_kem.h" + +int crypto_kem_enc( + unsigned char *c, + unsigned char *key, + const unsigned char *pk +); + +int crypto_kem_dec( + unsigned char *key, + const unsigned char *c, + const unsigned char *sk +); + +int crypto_kem_keypair +( + unsigned char *pk, + unsigned char *sk +); + +#endif + diff --git a/deps/mceliece/kem/mceliece460896/params.h b/deps/mceliece/kem/mceliece460896/params.h new file mode 100644 index 0000000..c6682ba --- /dev/null +++ b/deps/mceliece/kem/mceliece460896/params.h @@ -0,0 +1,20 @@ +#ifndef PARAMS_H +#define PARAMS_H + +#define GFBITS 13 +#define SYS_N 4608 +#define SYS_T 96 + +#define COND_BYTES ((1 << (GFBITS-4))*(2*GFBITS - 1)) +#define IRR_BYTES (SYS_T * 2) + +#define PK_NROWS (SYS_T*GFBITS) +#define PK_NCOLS (SYS_N - PK_NROWS) +#define PK_ROW_BYTES ((PK_NCOLS + 7)/8) + +#define SYND_BYTES ((PK_NROWS + 7)/8) + +#define GFMASK ((1 << GFBITS) - 1) + +#endif + diff --git a/deps/mceliece/kem/mceliece460896/pk_gen.c b/deps/mceliece/kem/mceliece460896/pk_gen.c new file mode 100644 index 0000000..d42ab25 --- /dev/null +++ b/deps/mceliece/kem/mceliece460896/pk_gen.c @@ -0,0 +1,151 @@ +/* + This file is for public-key generation +*/ + +#include +#include +#include +#include + +#include "controlbits.h" +#include "uint64_sort.h" +#include "pk_gen.h" +#include "params.h" +#include "benes.h" +#include "root.h" +#include "util.h" +#include "crypto_declassify.h" +#include "crypto_uint64.h" + +static crypto_uint64 uint64_is_equal_declassify(uint64_t t,uint64_t u) +{ + crypto_uint64 mask = crypto_uint64_equal_mask(t,u); + crypto_declassify(&mask,sizeof mask); + return mask; +} + +static crypto_uint64 uint64_is_zero_declassify(uint64_t t) +{ + crypto_uint64 mask = crypto_uint64_zero_mask(t); + crypto_declassify(&mask,sizeof mask); + return mask; +} + +/* input: secret key sk */ +/* output: public key pk */ +int pk_gen(unsigned char * pk, unsigned char * sk, uint32_t * perm, int16_t * pi) +{ + int i, j, k; + int row, c; + + uint64_t buf[ 1 << GFBITS ]; + + unsigned char mat[ PK_NROWS ][ SYS_N/8 ]; + unsigned char mask; + unsigned char b; + + gf g[ SYS_T+1 ]; // Goppa polynomial + gf L[ SYS_N ]; // support + gf inv[ SYS_N ]; + + // + + g[ SYS_T ] = 1; + + for (i = 0; i < SYS_T; i++) { g[i] = load_gf(sk); sk += 2; } + + for (i = 0; i < (1 << GFBITS); i++) + { + buf[i] = perm[i]; + buf[i] <<= 31; + buf[i] |= i; + } + + uint64_sort(buf, 1 << GFBITS); + + for (i = 1; i < (1 << GFBITS); i++) + if (uint64_is_equal_declassify(buf[i-1] >> 31,buf[i] >> 31)) + return -1; + + for (i = 0; i < (1 << GFBITS); i++) pi[i] = buf[i] & GFMASK; + for (i = 0; i < SYS_N; i++) L[i] = bitrev(pi[i]); + + // filling the matrix + + root(inv, g, L); + + for (i = 0; i < SYS_N; i++) + inv[i] = gf_inv(inv[i]); + + for (i = 0; i < PK_NROWS; i++) + for (j = 0; j < SYS_N/8; j++) + mat[i][j] = 0; + + for (i = 0; i < SYS_T; i++) + { + for (j = 0; j < SYS_N; j+=8) + for (k = 0; k < GFBITS; k++) + { + b = (inv[j+7] >> k) & 1; b <<= 1; + b |= (inv[j+6] >> k) & 1; b <<= 1; + b |= (inv[j+5] >> k) & 1; b <<= 1; + b |= (inv[j+4] >> k) & 1; b <<= 1; + b |= (inv[j+3] >> k) & 1; b <<= 1; + b |= (inv[j+2] >> k) & 1; b <<= 1; + b |= (inv[j+1] >> k) & 1; b <<= 1; + b |= (inv[j+0] >> k) & 1; + + mat[ i*GFBITS + k ][ j/8 ] = b; + } + + for (j = 0; j < SYS_N; j++) + inv[j] = gf_mul(inv[j], L[j]); + + } + + // gaussian elimination + + for (i = 0; i < (PK_NROWS + 7) / 8; i++) + for (j = 0; j < 8; j++) + { + row = i*8 + j; + + if (row >= PK_NROWS) + break; + + for (k = row + 1; k < PK_NROWS; k++) + { + mask = mat[ row ][ i ] ^ mat[ k ][ i ]; + mask >>= j; + mask &= 1; + mask = -mask; + + for (c = 0; c < SYS_N/8; c++) + mat[ row ][ c ] ^= mat[ k ][ c ] & mask; + } + + if ( uint64_is_zero_declassify((mat[ row ][ i ] >> j) & 1) ) // return if not systematic + { + return -1; + } + + for (k = 0; k < PK_NROWS; k++) + { + if (k != row) + { + mask = mat[ k ][ i ] >> j; + mask &= 1; + mask = -mask; + + for (c = 0; c < SYS_N/8; c++) + mat[ k ][ c ] ^= mat[ row ][ c ] & mask; + } + } + } + + for (i = 0; i < PK_NROWS; i++) + memcpy(pk + i*PK_ROW_BYTES, mat[i] + PK_NROWS/8, PK_ROW_BYTES); + + return 0; +} + diff --git a/deps/mceliece/kem/mceliece460896/pk_gen.h b/deps/mceliece/kem/mceliece460896/pk_gen.h new file mode 100644 index 0000000..eec43a7 --- /dev/null +++ b/deps/mceliece/kem/mceliece460896/pk_gen.h @@ -0,0 +1,14 @@ +/* + This file is for public-key generation +*/ + +#ifndef PK_GEN_H +#define PK_GEN_H +#define pk_gen CRYPTO_NAMESPACE(pk_gen) + +#include "gf.h" + +int pk_gen(unsigned char *, unsigned char *, uint32_t *, int16_t *); + +#endif + diff --git a/deps/mceliece/kem/mceliece460896/randombytes.h b/deps/mceliece/kem/mceliece460896/randombytes.h new file mode 100644 index 0000000..7e59351 --- /dev/null +++ b/deps/mceliece/kem/mceliece460896/randombytes.h @@ -0,0 +1 @@ +#include "../../mceliece_externals.h" diff --git a/deps/mceliece/kem/mceliece460896/root.c b/deps/mceliece/kem/mceliece460896/root.c new file mode 100644 index 0000000..1c1b634 --- /dev/null +++ b/deps/mceliece/kem/mceliece460896/root.c @@ -0,0 +1,38 @@ +/* + This file is for evaluating a polynomial at one or more field elements +*/ + +#include "root.h" +#include "params.h" +#include "gf.h" + +#include + +/* input: polynomial f and field element a */ +/* return f(a) */ +gf eval(gf *f, gf a) +{ + int i; + gf r; + + r = f[ SYS_T ]; + + for (i = SYS_T-1; i >= 0; i--) + { + r = gf_mul(r, a); + r = gf_add(r, f[i]); + } + + return r; +} + +/* input: polynomial f and list of field elements L */ +/* output: out = [ f(a) for a in L ] */ +void root(gf *out, gf *f, gf *L) +{ + int i; + + for (i = 0; i < SYS_N; i++) + out[i] = eval(f, L[i]); +} + diff --git a/deps/mceliece/kem/mceliece460896/root.h b/deps/mceliece/kem/mceliece460896/root.h new file mode 100644 index 0000000..42516e4 --- /dev/null +++ b/deps/mceliece/kem/mceliece460896/root.h @@ -0,0 +1,16 @@ +/* + This file is for evaluating a polynomial at one or more field elements +*/ + +#ifndef ROOT_H +#define ROOT_H +#define eval CRYPTO_NAMESPACE(eval) +#define root CRYPTO_NAMESPACE(root) + +#include "gf.h" + +gf eval(gf *, gf); +void root(gf *, gf *, gf *); + +#endif + diff --git a/deps/mceliece/kem/mceliece460896/sk_gen.c b/deps/mceliece/kem/mceliece460896/sk_gen.c new file mode 100644 index 0000000..340cc9a --- /dev/null +++ b/deps/mceliece/kem/mceliece460896/sk_gen.c @@ -0,0 +1,85 @@ +/* + This file is for secret-key generation +*/ + +#include "sk_gen.h" + +#include "randombytes.h" +#include "controlbits.h" +#include "params.h" +#include "util.h" +#include "gf.h" +#include "crypto_declassify.h" +#include "crypto_uint16.h" + +static inline crypto_uint16 gf_is_zero_declassify(gf t) +{ + crypto_uint16 mask = crypto_uint16_zero_mask(t); + crypto_declassify(&mask,sizeof mask); + return mask; +} + +/* input: f, element in GF((2^m)^t) */ +/* output: out, minimal polynomial of f */ +/* return: 0 for success and -1 for failure */ +int genpoly_gen(gf *out, gf *f) +{ + int i, j, k, c; + + gf mat[ SYS_T+1 ][ SYS_T ]; + gf mask, inv, t; + + // fill matrix + + mat[0][0] = 1; + + for (i = 1; i < SYS_T; i++) + mat[0][i] = 0; + + for (i = 0; i < SYS_T; i++) + mat[1][i] = f[i]; + + for (j = 2; j <= SYS_T; j++) + GF_mul(mat[j], mat[j-1], f); + + // gaussian + + for (j = 0; j < SYS_T; j++) + { + for (k = j + 1; k < SYS_T; k++) + { + mask = gf_iszero(mat[ j ][ j ]); + + for (c = j; c < SYS_T + 1; c++) + mat[ c ][ j ] ^= mat[ c ][ k ] & mask; + + } + + if ( gf_is_zero_declassify(mat[ j ][ j ]) ) // return if not systematic + { + return -1; + } + + inv = gf_inv(mat[j][j]); + + for (c = j; c < SYS_T + 1; c++) + mat[ c ][ j ] = gf_mul(mat[ c ][ j ], inv) ; + + for (k = 0; k < SYS_T; k++) + { + if (k != j) + { + t = mat[ j ][ k ]; + + for (c = j; c < SYS_T + 1; c++) + mat[ c ][ k ] ^= gf_mul(mat[ c ][ j ], t); + } + } + } + + for (i = 0; i < SYS_T; i++) + out[i] = mat[ SYS_T ][ i ]; + + return 0; +} + diff --git a/deps/mceliece/kem/mceliece460896/sk_gen.h b/deps/mceliece/kem/mceliece460896/sk_gen.h new file mode 100644 index 0000000..e319703 --- /dev/null +++ b/deps/mceliece/kem/mceliece460896/sk_gen.h @@ -0,0 +1,18 @@ +/* + This file is for secret-key generation +*/ + +#ifndef SK_GEN_H +#define SK_GEN_H +#define genpoly_gen CRYPTO_NAMESPACE(genpoly_gen) +#define perm_check CRYPTO_NAMESPACE(perm_check) + +#include "gf.h" + +#include + +int genpoly_gen(gf *, gf *); +int perm_check(uint32_t *); + +#endif + diff --git a/deps/mceliece/kem/mceliece460896/subroutines/crypto_declassify.h b/deps/mceliece/kem/mceliece460896/subroutines/crypto_declassify.h new file mode 100644 index 0000000..8d84209 --- /dev/null +++ b/deps/mceliece/kem/mceliece460896/subroutines/crypto_declassify.h @@ -0,0 +1,8 @@ +#ifndef crypto_declassify_h +#define crypto_declassify_h + +static void crypto_declassify(void *x,unsigned long long n) +{ +} + +#endif diff --git a/deps/mceliece/kem/mceliece460896/subroutines/crypto_int16.h b/deps/mceliece/kem/mceliece460896/subroutines/crypto_int16.h new file mode 100644 index 0000000..72bbf52 --- /dev/null +++ b/deps/mceliece/kem/mceliece460896/subroutines/crypto_int16.h @@ -0,0 +1,81 @@ +#ifndef crypto_int16_h +#define crypto_int16_h + +#include +typedef int16_t crypto_int16; + +static crypto_int16 crypto_int16_negative_mask(crypto_int16 crypto_int16_x) +{ + return crypto_int16_x >> 15; +} + +static crypto_int16 crypto_int16_nonzero_mask(crypto_int16 crypto_int16_x) +{ + return crypto_int16_negative_mask(crypto_int16_x) | crypto_int16_negative_mask(-crypto_int16_x); +} + +static crypto_int16 crypto_int16_zero_mask(crypto_int16 crypto_int16_x) +{ + return ~crypto_int16_nonzero_mask(crypto_int16_x); +} + +static crypto_int16 crypto_int16_positive_mask(crypto_int16 crypto_int16_x) +{ + crypto_int16 crypto_int16_z = -crypto_int16_x; + crypto_int16_z ^= crypto_int16_x & crypto_int16_z; + return crypto_int16_negative_mask(crypto_int16_z); +} + +static crypto_int16 crypto_int16_unequal_mask(crypto_int16 crypto_int16_x,crypto_int16 crypto_int16_y) +{ + crypto_int16 crypto_int16_xy = crypto_int16_x ^ crypto_int16_y; + return crypto_int16_nonzero_mask(crypto_int16_xy); +} + +static crypto_int16 crypto_int16_equal_mask(crypto_int16 crypto_int16_x,crypto_int16 crypto_int16_y) +{ + return ~crypto_int16_unequal_mask(crypto_int16_x,crypto_int16_y); +} + +static crypto_int16 crypto_int16_smaller_mask(crypto_int16 crypto_int16_x,crypto_int16 crypto_int16_y) +{ + crypto_int16 crypto_int16_xy = crypto_int16_x ^ crypto_int16_y; + crypto_int16 crypto_int16_z = crypto_int16_x - crypto_int16_y; + crypto_int16_z ^= crypto_int16_xy & (crypto_int16_z ^ crypto_int16_x); + return crypto_int16_negative_mask(crypto_int16_z); +} + +static crypto_int16 crypto_int16_min(crypto_int16 crypto_int16_x,crypto_int16 crypto_int16_y) +{ + crypto_int16 crypto_int16_xy = crypto_int16_y ^ crypto_int16_x; + crypto_int16 crypto_int16_z = crypto_int16_y - crypto_int16_x; + crypto_int16_z ^= crypto_int16_xy & (crypto_int16_z ^ crypto_int16_y); + crypto_int16_z = crypto_int16_negative_mask(crypto_int16_z); + crypto_int16_z &= crypto_int16_xy; + return crypto_int16_x ^ crypto_int16_z; +} + +static crypto_int16 crypto_int16_max(crypto_int16 crypto_int16_x,crypto_int16 crypto_int16_y) +{ + crypto_int16 crypto_int16_xy = crypto_int16_y ^ crypto_int16_x; + crypto_int16 crypto_int16_z = crypto_int16_y - crypto_int16_x; + crypto_int16_z ^= crypto_int16_xy & (crypto_int16_z ^ crypto_int16_y); + crypto_int16_z = crypto_int16_negative_mask(crypto_int16_z); + crypto_int16_z &= crypto_int16_xy; + return crypto_int16_y ^ crypto_int16_z; +} + +static void crypto_int16_minmax(crypto_int16 *crypto_int16_a,crypto_int16 *crypto_int16_b) +{ + crypto_int16 crypto_int16_x = *crypto_int16_a; + crypto_int16 crypto_int16_y = *crypto_int16_b; + crypto_int16 crypto_int16_xy = crypto_int16_y ^ crypto_int16_x; + crypto_int16 crypto_int16_z = crypto_int16_y - crypto_int16_x; + crypto_int16_z ^= crypto_int16_xy & (crypto_int16_z ^ crypto_int16_y); + crypto_int16_z = crypto_int16_negative_mask(crypto_int16_z); + crypto_int16_z &= crypto_int16_xy; + *crypto_int16_a = crypto_int16_x ^ crypto_int16_z; + *crypto_int16_b = crypto_int16_y ^ crypto_int16_z; +} + +#endif diff --git a/deps/mceliece/kem/mceliece460896/subroutines/crypto_int32.h b/deps/mceliece/kem/mceliece460896/subroutines/crypto_int32.h new file mode 100644 index 0000000..c22f735 --- /dev/null +++ b/deps/mceliece/kem/mceliece460896/subroutines/crypto_int32.h @@ -0,0 +1,81 @@ +#ifndef crypto_int32_h +#define crypto_int32_h + +#include +typedef int32_t crypto_int32; + +static crypto_int32 crypto_int32_negative_mask(crypto_int32 crypto_int32_x) +{ + return crypto_int32_x >> 31; +} + +static crypto_int32 crypto_int32_nonzero_mask(crypto_int32 crypto_int32_x) +{ + return crypto_int32_negative_mask(crypto_int32_x) | crypto_int32_negative_mask(-crypto_int32_x); +} + +static crypto_int32 crypto_int32_zero_mask(crypto_int32 crypto_int32_x) +{ + return ~crypto_int32_nonzero_mask(crypto_int32_x); +} + +static crypto_int32 crypto_int32_positive_mask(crypto_int32 crypto_int32_x) +{ + crypto_int32 crypto_int32_z = -crypto_int32_x; + crypto_int32_z ^= crypto_int32_x & crypto_int32_z; + return crypto_int32_negative_mask(crypto_int32_z); +} + +static crypto_int32 crypto_int32_unequal_mask(crypto_int32 crypto_int32_x,crypto_int32 crypto_int32_y) +{ + crypto_int32 crypto_int32_xy = crypto_int32_x ^ crypto_int32_y; + return crypto_int32_nonzero_mask(crypto_int32_xy); +} + +static crypto_int32 crypto_int32_equal_mask(crypto_int32 crypto_int32_x,crypto_int32 crypto_int32_y) +{ + return ~crypto_int32_unequal_mask(crypto_int32_x,crypto_int32_y); +} + +static crypto_int32 crypto_int32_smaller_mask(crypto_int32 crypto_int32_x,crypto_int32 crypto_int32_y) +{ + crypto_int32 crypto_int32_xy = crypto_int32_x ^ crypto_int32_y; + crypto_int32 crypto_int32_z = crypto_int32_x - crypto_int32_y; + crypto_int32_z ^= crypto_int32_xy & (crypto_int32_z ^ crypto_int32_x); + return crypto_int32_negative_mask(crypto_int32_z); +} + +static crypto_int32 crypto_int32_min(crypto_int32 crypto_int32_x,crypto_int32 crypto_int32_y) +{ + crypto_int32 crypto_int32_xy = crypto_int32_y ^ crypto_int32_x; + crypto_int32 crypto_int32_z = crypto_int32_y - crypto_int32_x; + crypto_int32_z ^= crypto_int32_xy & (crypto_int32_z ^ crypto_int32_y); + crypto_int32_z = crypto_int32_negative_mask(crypto_int32_z); + crypto_int32_z &= crypto_int32_xy; + return crypto_int32_x ^ crypto_int32_z; +} + +static crypto_int32 crypto_int32_max(crypto_int32 crypto_int32_x,crypto_int32 crypto_int32_y) +{ + crypto_int32 crypto_int32_xy = crypto_int32_y ^ crypto_int32_x; + crypto_int32 crypto_int32_z = crypto_int32_y - crypto_int32_x; + crypto_int32_z ^= crypto_int32_xy & (crypto_int32_z ^ crypto_int32_y); + crypto_int32_z = crypto_int32_negative_mask(crypto_int32_z); + crypto_int32_z &= crypto_int32_xy; + return crypto_int32_y ^ crypto_int32_z; +} + +static void crypto_int32_minmax(crypto_int32 *crypto_int32_a,crypto_int32 *crypto_int32_b) +{ + crypto_int32 crypto_int32_x = *crypto_int32_a; + crypto_int32 crypto_int32_y = *crypto_int32_b; + crypto_int32 crypto_int32_xy = crypto_int32_y ^ crypto_int32_x; + crypto_int32 crypto_int32_z = crypto_int32_y - crypto_int32_x; + crypto_int32_z ^= crypto_int32_xy & (crypto_int32_z ^ crypto_int32_y); + crypto_int32_z = crypto_int32_negative_mask(crypto_int32_z); + crypto_int32_z &= crypto_int32_xy; + *crypto_int32_a = crypto_int32_x ^ crypto_int32_z; + *crypto_int32_b = crypto_int32_y ^ crypto_int32_z; +} + +#endif diff --git a/deps/mceliece/kem/mceliece460896/subroutines/crypto_uint16.h b/deps/mceliece/kem/mceliece460896/subroutines/crypto_uint16.h new file mode 100644 index 0000000..f0ebbbf --- /dev/null +++ b/deps/mceliece/kem/mceliece460896/subroutines/crypto_uint16.h @@ -0,0 +1,76 @@ +#ifndef crypto_uint16_h +#define crypto_uint16_h + +#include +typedef uint16_t crypto_uint16; + +typedef int16_t crypto_uint16_signed; + +static crypto_uint16_signed crypto_uint16_signed_negative_mask(crypto_uint16_signed crypto_uint16_signed_x) +{ + return crypto_uint16_signed_x >> 15; +} + +static crypto_uint16 crypto_uint16_nonzero_mask(crypto_uint16 crypto_uint16_x) +{ + return crypto_uint16_signed_negative_mask(crypto_uint16_x) | crypto_uint16_signed_negative_mask(-crypto_uint16_x); +} + +static crypto_uint16 crypto_uint16_zero_mask(crypto_uint16 crypto_uint16_x) +{ + return ~crypto_uint16_nonzero_mask(crypto_uint16_x); +} + +static crypto_uint16 crypto_uint16_unequal_mask(crypto_uint16 crypto_uint16_x,crypto_uint16 crypto_uint16_y) +{ + crypto_uint16 crypto_uint16_xy = crypto_uint16_x ^ crypto_uint16_y; + return crypto_uint16_nonzero_mask(crypto_uint16_xy); +} + +static crypto_uint16 crypto_uint16_equal_mask(crypto_uint16 crypto_uint16_x,crypto_uint16 crypto_uint16_y) +{ + return ~crypto_uint16_unequal_mask(crypto_uint16_x,crypto_uint16_y); +} + +static crypto_uint16 crypto_uint16_smaller_mask(crypto_uint16 crypto_uint16_x,crypto_uint16 crypto_uint16_y) +{ + crypto_uint16 crypto_uint16_xy = crypto_uint16_x ^ crypto_uint16_y; + crypto_uint16 crypto_uint16_z = crypto_uint16_x - crypto_uint16_y; + crypto_uint16_z ^= crypto_uint16_xy & (crypto_uint16_z ^ crypto_uint16_x ^ (((crypto_uint16) 1) << 15)); + return crypto_uint16_signed_negative_mask(crypto_uint16_z); +} + +static crypto_uint16 crypto_uint16_min(crypto_uint16 crypto_uint16_x,crypto_uint16 crypto_uint16_y) +{ + crypto_uint16 crypto_uint16_xy = crypto_uint16_y ^ crypto_uint16_x; + crypto_uint16 crypto_uint16_z = crypto_uint16_y - crypto_uint16_x; + crypto_uint16_z ^= crypto_uint16_xy & (crypto_uint16_z ^ crypto_uint16_y ^ (((crypto_uint16) 1) << 15)); + crypto_uint16_z = crypto_uint16_signed_negative_mask(crypto_uint16_z); + crypto_uint16_z &= crypto_uint16_xy; + return crypto_uint16_x ^ crypto_uint16_z; +} + +static crypto_uint16 crypto_uint16_max(crypto_uint16 crypto_uint16_x,crypto_uint16 crypto_uint16_y) +{ + crypto_uint16 crypto_uint16_xy = crypto_uint16_y ^ crypto_uint16_x; + crypto_uint16 crypto_uint16_z = crypto_uint16_y - crypto_uint16_x; + crypto_uint16_z ^= crypto_uint16_xy & (crypto_uint16_z ^ crypto_uint16_y ^ (((crypto_uint16) 1) << 15)); + crypto_uint16_z = crypto_uint16_signed_negative_mask(crypto_uint16_z); + crypto_uint16_z &= crypto_uint16_xy; + return crypto_uint16_y ^ crypto_uint16_z; +} + +static void crypto_uint16_minmax(crypto_uint16 *crypto_uint16_a,crypto_uint16 *crypto_uint16_b) +{ + crypto_uint16 crypto_uint16_x = *crypto_uint16_a; + crypto_uint16 crypto_uint16_y = *crypto_uint16_b; + crypto_uint16 crypto_uint16_xy = crypto_uint16_y ^ crypto_uint16_x; + crypto_uint16 crypto_uint16_z = crypto_uint16_y - crypto_uint16_x; + crypto_uint16_z ^= crypto_uint16_xy & (crypto_uint16_z ^ crypto_uint16_y ^ (((crypto_uint16) 1) << 15)); + crypto_uint16_z = crypto_uint16_signed_negative_mask(crypto_uint16_z); + crypto_uint16_z &= crypto_uint16_xy; + *crypto_uint16_a = crypto_uint16_x ^ crypto_uint16_z; + *crypto_uint16_b = crypto_uint16_y ^ crypto_uint16_z; +} + +#endif diff --git a/deps/mceliece/kem/mceliece460896/subroutines/crypto_uint32.h b/deps/mceliece/kem/mceliece460896/subroutines/crypto_uint32.h new file mode 100644 index 0000000..3f39d62 --- /dev/null +++ b/deps/mceliece/kem/mceliece460896/subroutines/crypto_uint32.h @@ -0,0 +1,76 @@ +#ifndef crypto_uint32_h +#define crypto_uint32_h + +#include +typedef uint32_t crypto_uint32; + +typedef int32_t crypto_uint32_signed; + +static crypto_uint32_signed crypto_uint32_signed_negative_mask(crypto_uint32_signed crypto_uint32_signed_x) +{ + return crypto_uint32_signed_x >> 31; +} + +static crypto_uint32 crypto_uint32_nonzero_mask(crypto_uint32 crypto_uint32_x) +{ + return crypto_uint32_signed_negative_mask(crypto_uint32_x) | crypto_uint32_signed_negative_mask(-crypto_uint32_x); +} + +static crypto_uint32 crypto_uint32_zero_mask(crypto_uint32 crypto_uint32_x) +{ + return ~crypto_uint32_nonzero_mask(crypto_uint32_x); +} + +static crypto_uint32 crypto_uint32_unequal_mask(crypto_uint32 crypto_uint32_x,crypto_uint32 crypto_uint32_y) +{ + crypto_uint32 crypto_uint32_xy = crypto_uint32_x ^ crypto_uint32_y; + return crypto_uint32_nonzero_mask(crypto_uint32_xy); +} + +static crypto_uint32 crypto_uint32_equal_mask(crypto_uint32 crypto_uint32_x,crypto_uint32 crypto_uint32_y) +{ + return ~crypto_uint32_unequal_mask(crypto_uint32_x,crypto_uint32_y); +} + +static crypto_uint32 crypto_uint32_smaller_mask(crypto_uint32 crypto_uint32_x,crypto_uint32 crypto_uint32_y) +{ + crypto_uint32 crypto_uint32_xy = crypto_uint32_x ^ crypto_uint32_y; + crypto_uint32 crypto_uint32_z = crypto_uint32_x - crypto_uint32_y; + crypto_uint32_z ^= crypto_uint32_xy & (crypto_uint32_z ^ crypto_uint32_x ^ (((crypto_uint32) 1) << 31)); + return crypto_uint32_signed_negative_mask(crypto_uint32_z); +} + +static crypto_uint32 crypto_uint32_min(crypto_uint32 crypto_uint32_x,crypto_uint32 crypto_uint32_y) +{ + crypto_uint32 crypto_uint32_xy = crypto_uint32_y ^ crypto_uint32_x; + crypto_uint32 crypto_uint32_z = crypto_uint32_y - crypto_uint32_x; + crypto_uint32_z ^= crypto_uint32_xy & (crypto_uint32_z ^ crypto_uint32_y ^ (((crypto_uint32) 1) << 31)); + crypto_uint32_z = crypto_uint32_signed_negative_mask(crypto_uint32_z); + crypto_uint32_z &= crypto_uint32_xy; + return crypto_uint32_x ^ crypto_uint32_z; +} + +static crypto_uint32 crypto_uint32_max(crypto_uint32 crypto_uint32_x,crypto_uint32 crypto_uint32_y) +{ + crypto_uint32 crypto_uint32_xy = crypto_uint32_y ^ crypto_uint32_x; + crypto_uint32 crypto_uint32_z = crypto_uint32_y - crypto_uint32_x; + crypto_uint32_z ^= crypto_uint32_xy & (crypto_uint32_z ^ crypto_uint32_y ^ (((crypto_uint32) 1) << 31)); + crypto_uint32_z = crypto_uint32_signed_negative_mask(crypto_uint32_z); + crypto_uint32_z &= crypto_uint32_xy; + return crypto_uint32_y ^ crypto_uint32_z; +} + +static void crypto_uint32_minmax(crypto_uint32 *crypto_uint32_a,crypto_uint32 *crypto_uint32_b) +{ + crypto_uint32 crypto_uint32_x = *crypto_uint32_a; + crypto_uint32 crypto_uint32_y = *crypto_uint32_b; + crypto_uint32 crypto_uint32_xy = crypto_uint32_y ^ crypto_uint32_x; + crypto_uint32 crypto_uint32_z = crypto_uint32_y - crypto_uint32_x; + crypto_uint32_z ^= crypto_uint32_xy & (crypto_uint32_z ^ crypto_uint32_y ^ (((crypto_uint32) 1) << 31)); + crypto_uint32_z = crypto_uint32_signed_negative_mask(crypto_uint32_z); + crypto_uint32_z &= crypto_uint32_xy; + *crypto_uint32_a = crypto_uint32_x ^ crypto_uint32_z; + *crypto_uint32_b = crypto_uint32_y ^ crypto_uint32_z; +} + +#endif diff --git a/deps/mceliece/kem/mceliece460896/subroutines/crypto_uint64.h b/deps/mceliece/kem/mceliece460896/subroutines/crypto_uint64.h new file mode 100644 index 0000000..42e2be9 --- /dev/null +++ b/deps/mceliece/kem/mceliece460896/subroutines/crypto_uint64.h @@ -0,0 +1,76 @@ +#ifndef crypto_uint64_h +#define crypto_uint64_h + +#include +typedef uint64_t crypto_uint64; + +typedef int64_t crypto_uint64_signed; + +static crypto_uint64_signed crypto_uint64_signed_negative_mask(crypto_uint64_signed crypto_uint64_signed_x) +{ + return crypto_uint64_signed_x >> 63; +} + +static crypto_uint64 crypto_uint64_nonzero_mask(crypto_uint64 crypto_uint64_x) +{ + return crypto_uint64_signed_negative_mask(crypto_uint64_x) | crypto_uint64_signed_negative_mask(-crypto_uint64_x); +} + +static crypto_uint64 crypto_uint64_zero_mask(crypto_uint64 crypto_uint64_x) +{ + return ~crypto_uint64_nonzero_mask(crypto_uint64_x); +} + +static crypto_uint64 crypto_uint64_unequal_mask(crypto_uint64 crypto_uint64_x,crypto_uint64 crypto_uint64_y) +{ + crypto_uint64 crypto_uint64_xy = crypto_uint64_x ^ crypto_uint64_y; + return crypto_uint64_nonzero_mask(crypto_uint64_xy); +} + +static crypto_uint64 crypto_uint64_equal_mask(crypto_uint64 crypto_uint64_x,crypto_uint64 crypto_uint64_y) +{ + return ~crypto_uint64_unequal_mask(crypto_uint64_x,crypto_uint64_y); +} + +static crypto_uint64 crypto_uint64_smaller_mask(crypto_uint64 crypto_uint64_x,crypto_uint64 crypto_uint64_y) +{ + crypto_uint64 crypto_uint64_xy = crypto_uint64_x ^ crypto_uint64_y; + crypto_uint64 crypto_uint64_z = crypto_uint64_x - crypto_uint64_y; + crypto_uint64_z ^= crypto_uint64_xy & (crypto_uint64_z ^ crypto_uint64_x ^ (((crypto_uint64) 1) << 63)); + return crypto_uint64_signed_negative_mask(crypto_uint64_z); +} + +static crypto_uint64 crypto_uint64_min(crypto_uint64 crypto_uint64_x,crypto_uint64 crypto_uint64_y) +{ + crypto_uint64 crypto_uint64_xy = crypto_uint64_y ^ crypto_uint64_x; + crypto_uint64 crypto_uint64_z = crypto_uint64_y - crypto_uint64_x; + crypto_uint64_z ^= crypto_uint64_xy & (crypto_uint64_z ^ crypto_uint64_y ^ (((crypto_uint64) 1) << 63)); + crypto_uint64_z = crypto_uint64_signed_negative_mask(crypto_uint64_z); + crypto_uint64_z &= crypto_uint64_xy; + return crypto_uint64_x ^ crypto_uint64_z; +} + +static crypto_uint64 crypto_uint64_max(crypto_uint64 crypto_uint64_x,crypto_uint64 crypto_uint64_y) +{ + crypto_uint64 crypto_uint64_xy = crypto_uint64_y ^ crypto_uint64_x; + crypto_uint64 crypto_uint64_z = crypto_uint64_y - crypto_uint64_x; + crypto_uint64_z ^= crypto_uint64_xy & (crypto_uint64_z ^ crypto_uint64_y ^ (((crypto_uint64) 1) << 63)); + crypto_uint64_z = crypto_uint64_signed_negative_mask(crypto_uint64_z); + crypto_uint64_z &= crypto_uint64_xy; + return crypto_uint64_y ^ crypto_uint64_z; +} + +static void crypto_uint64_minmax(crypto_uint64 *crypto_uint64_a,crypto_uint64 *crypto_uint64_b) +{ + crypto_uint64 crypto_uint64_x = *crypto_uint64_a; + crypto_uint64 crypto_uint64_y = *crypto_uint64_b; + crypto_uint64 crypto_uint64_xy = crypto_uint64_y ^ crypto_uint64_x; + crypto_uint64 crypto_uint64_z = crypto_uint64_y - crypto_uint64_x; + crypto_uint64_z ^= crypto_uint64_xy & (crypto_uint64_z ^ crypto_uint64_y ^ (((crypto_uint64) 1) << 63)); + crypto_uint64_z = crypto_uint64_signed_negative_mask(crypto_uint64_z); + crypto_uint64_z &= crypto_uint64_xy; + *crypto_uint64_a = crypto_uint64_x ^ crypto_uint64_z; + *crypto_uint64_b = crypto_uint64_y ^ crypto_uint64_z; +} + +#endif diff --git a/deps/mceliece/kem/mceliece460896/synd.c b/deps/mceliece/kem/mceliece460896/synd.c new file mode 100644 index 0000000..c945647 --- /dev/null +++ b/deps/mceliece/kem/mceliece460896/synd.c @@ -0,0 +1,36 @@ +/* + This file is for syndrome computation +*/ + +#include "synd.h" + +#include "params.h" +#include "root.h" + +#include + +/* input: Goppa polynomial f, support L, received word r */ +/* output: out, the syndrome of length 2t */ +void synd(gf *out, gf *f, gf *L, unsigned char *r) +{ + int i, j; + gf e, e_inv, c; + + for (j = 0; j < 2*SYS_T; j++) + out[j] = 0; + + for (i = 0; i < SYS_N; i++) + { + c = (r[i/8] >> (i%8)) & 1; + + e = eval(f, L[i]); + e_inv = gf_inv(gf_mul(e,e)); + + for (j = 0; j < 2*SYS_T; j++) + { + out[j] = gf_add(out[j], gf_mul(e_inv, c)); + e_inv = gf_mul(e_inv, L[i]); + } + } +} + diff --git a/deps/mceliece/kem/mceliece460896/synd.h b/deps/mceliece/kem/mceliece460896/synd.h new file mode 100644 index 0000000..9331406 --- /dev/null +++ b/deps/mceliece/kem/mceliece460896/synd.h @@ -0,0 +1,14 @@ +/* + This file is for syndrome computation +*/ + +#ifndef SYND_H +#define SYND_H +#define synd CRYPTO_NAMESPACE(synd) + +#include "gf.h" + +void synd(gf *, gf *, gf *, unsigned char *); + +#endif + diff --git a/deps/mceliece/kem/mceliece460896/transpose.c b/deps/mceliece/kem/mceliece460896/transpose.c new file mode 100644 index 0000000..0da2bc5 --- /dev/null +++ b/deps/mceliece/kem/mceliece460896/transpose.c @@ -0,0 +1,43 @@ +/* + This file is for matrix transposition +*/ + +#include "transpose.h" + +#include + +/* input: in, a 64x64 matrix over GF(2) */ +/* output: out, transpose of in */ +void transpose_64x64(uint64_t * out, uint64_t * in) +{ + int i, j, s, d; + + uint64_t x, y; + uint64_t masks[6][2] = { + {0x5555555555555555, 0xAAAAAAAAAAAAAAAA}, + {0x3333333333333333, 0xCCCCCCCCCCCCCCCC}, + {0x0F0F0F0F0F0F0F0F, 0xF0F0F0F0F0F0F0F0}, + {0x00FF00FF00FF00FF, 0xFF00FF00FF00FF00}, + {0x0000FFFF0000FFFF, 0xFFFF0000FFFF0000}, + {0x00000000FFFFFFFF, 0xFFFFFFFF00000000} + }; + + for (i = 0; i < 64; i++) + out[i] = in[i]; + + for (d = 5; d >= 0; d--) + { + s = 1 << d; + + for (i = 0; i < 64; i += s*2) + for (j = i; j < i+s; j++) + { + x = (out[j] & masks[d][0]) | ((out[j+s] & masks[d][0]) << s); + y = ((out[j] & masks[d][1]) >> s) | (out[j+s] & masks[d][1]); + + out[j+0] = x; + out[j+s] = y; + } + } +} + diff --git a/deps/mceliece/kem/mceliece460896/transpose.h b/deps/mceliece/kem/mceliece460896/transpose.h new file mode 100644 index 0000000..31e5b96 --- /dev/null +++ b/deps/mceliece/kem/mceliece460896/transpose.h @@ -0,0 +1,14 @@ +/* + This file is for matrix transposition +*/ + +#ifndef TRANSPOSE_H +#define TRANSPOSE_H +#define transpose_64x64 CRYPTO_NAMESPACE(transpose_64x64) + +#include + +void transpose_64x64(uint64_t *, uint64_t *); + +#endif + diff --git a/deps/mceliece/kem/mceliece460896/uint64_sort.h b/deps/mceliece/kem/mceliece460896/uint64_sort.h new file mode 100644 index 0000000..2fb100c --- /dev/null +++ b/deps/mceliece/kem/mceliece460896/uint64_sort.h @@ -0,0 +1,45 @@ +#ifndef uint64_sort_h +#define uint64_sort_h + +#define int64_sort CRYPTO_NAMESPACE(int64_sort) + +#include + +#define uint64_MINMAX(a,b) \ +do { \ + uint64_t c = b - a; \ + c >>= 63; \ + c = -c; \ + c &= a ^ b; \ + a ^= c; \ + b ^= c; \ +} while(0) + +static void uint64_sort(uint64_t *x,long long n) +{ + long long top,p,q,r,i; + + if (n < 2) return; + top = 1; + while (top < n - top) top += top; + + for (p = top;p > 0;p >>= 1) { + for (i = 0;i < n - p;++i) + if (!(i & p)) + uint64_MINMAX(x[i],x[i+p]); + i = 0; + for (q = top;q > p;q >>= 1) { + for (;i < n - q;++i) { + if (!(i & p)) { + uint64_t a = x[i + p]; + for (r = q;r > p;r >>= 1) + uint64_MINMAX(a,x[i+r]); + x[i + p] = a; + } + } + } + } +} + +#endif + diff --git a/deps/mceliece/kem/mceliece460896/util.c b/deps/mceliece/kem/mceliece460896/util.c new file mode 100644 index 0000000..1679168 --- /dev/null +++ b/deps/mceliece/kem/mceliece460896/util.c @@ -0,0 +1,75 @@ +/* + This file is for loading/storing data in a little-endian fashion +*/ + +#include "util.h" + +#include "params.h" + +void store_gf(unsigned char *dest, gf a) +{ + dest[0] = a & 0xFF; + dest[1] = a >> 8; +} + +uint16_t load_gf(const unsigned char *src) +{ + uint16_t a; + + a = src[1]; + a <<= 8; + a |= src[0]; + + return a & GFMASK; +} + +uint32_t load4(const unsigned char * in) +{ + int i; + uint32_t ret = in[3]; + + for (i = 2; i >= 0; i--) + { + ret <<= 8; + ret |= in[i]; + } + + return ret; +} + +void store8(unsigned char *out, uint64_t in) +{ + out[0] = (in >> 0x00) & 0xFF; + out[1] = (in >> 0x08) & 0xFF; + out[2] = (in >> 0x10) & 0xFF; + out[3] = (in >> 0x18) & 0xFF; + out[4] = (in >> 0x20) & 0xFF; + out[5] = (in >> 0x28) & 0xFF; + out[6] = (in >> 0x30) & 0xFF; + out[7] = (in >> 0x38) & 0xFF; +} + +uint64_t load8(const unsigned char * in) +{ + int i; + uint64_t ret = in[7]; + + for (i = 6; i >= 0; i--) + { + ret <<= 8; + ret |= in[i]; + } + + return ret; +} + +gf bitrev(gf a) +{ + a = ((a & 0x00FF) << 8) | ((a & 0xFF00) >> 8); + a = ((a & 0x0F0F) << 4) | ((a & 0xF0F0) >> 4); + a = ((a & 0x3333) << 2) | ((a & 0xCCCC) >> 2); + a = ((a & 0x5555) << 1) | ((a & 0xAAAA) >> 1); + + return a >> 3; +} + diff --git a/deps/mceliece/kem/mceliece460896/util.h b/deps/mceliece/kem/mceliece460896/util.h new file mode 100644 index 0000000..d610bee --- /dev/null +++ b/deps/mceliece/kem/mceliece460896/util.h @@ -0,0 +1,27 @@ +/* + This file is for loading/storing data in a little-endian fashion +*/ + +#ifndef UTIL_H +#define UTIL_H +#define bitrev CRYPTO_NAMESPACE(bitrev) +#define load4 CRYPTO_NAMESPACE(load4) +#define load8 CRYPTO_NAMESPACE(load8) +#define load_gf CRYPTO_NAMESPACE(load_gf) +#define store8 CRYPTO_NAMESPACE(store8) +#define store_gf CRYPTO_NAMESPACE(store_gf) + +#include "gf.h" +#include + +void store_gf(unsigned char *, gf); +uint16_t load_gf(const unsigned char *); +uint32_t load4(const unsigned char *); + +void store8(unsigned char *, uint64_t ); +uint64_t load8(const unsigned char *); + +gf bitrev(gf); + +#endif + diff --git a/deps/mceliece/kem/mceliece460896f/benes.c b/deps/mceliece/kem/mceliece460896f/benes.c new file mode 100644 index 0000000..3b4e710 --- /dev/null +++ b/deps/mceliece/kem/mceliece460896f/benes.c @@ -0,0 +1,181 @@ +/* + This file is for Benes network related functions + + For the implementation strategy, see + https://eprint.iacr.org/2017/793.pdf +*/ + +#include "util.h" +#include "transpose.h" +#include "params.h" +#include "benes.h" + +/* middle layers of the benes network */ +static void layer_in(uint64_t data[2][64], uint64_t * bits, int lgs) +{ + int i, j, s; + + uint64_t d; + + s = 1 << lgs; + + for (i = 0; i < 64; i += s*2) + for (j = i; j < i+s; j++) + { + + d = (data[0][j+0] ^ data[0][j+s]); + d &= (*bits++); + data[0][j+0] ^= d; + data[0][j+s] ^= d; + + d = (data[1][j+0] ^ data[1][j+s]); + d &= (*bits++); + data[1][j+0] ^= d; + data[1][j+s] ^= d; + } +} + +/* first and last layers of the benes network */ +static void layer_ex(uint64_t * data, uint64_t * bits, int lgs) +{ + int i, j, s; + + uint64_t d; + + s = 1 << lgs; + + for (i = 0; i < 128; i += s*2) + for (j = i; j < i+s; j++) + { + + d = (data[j+0] ^ data[j+s]); + d &= (*bits++); + data[j+0] ^= d; + data[j+s] ^= d; + } +} + +/* input: r, sequence of bits to be permuted */ +/* bits, condition bits of the Benes network */ +/* rev, 0 for normal application; !0 for inverse */ +/* output: r, permuted bits */ +void apply_benes(unsigned char * r, const unsigned char * bits, int rev) +{ + int i, iter, inc; + + unsigned char *r_ptr = r; + const unsigned char *bits_ptr; + + uint64_t r_int_v[2][64]; + uint64_t r_int_h[2][64]; + uint64_t b_int_v[64]; + uint64_t b_int_h[64]; + + // + + if (rev) { bits_ptr = bits + 12288; inc = -1024; } + else { bits_ptr = bits; inc = 0; } + + for (i = 0; i < 64; i++) + { + r_int_v[0][i] = load8(r_ptr + i*16 + 0); + r_int_v[1][i] = load8(r_ptr + i*16 + 8); + } + + transpose_64x64(r_int_h[0], r_int_v[0]); + transpose_64x64(r_int_h[1], r_int_v[1]); + + for (iter = 0; iter <= 6; iter++) + { + for (i = 0; i < 64; i++) + { + b_int_v[i] = load8(bits_ptr); bits_ptr += 8; + } + + bits_ptr += inc; + + transpose_64x64(b_int_h, b_int_v); + + layer_ex(r_int_h[0], b_int_h, iter); + } + + transpose_64x64(r_int_v[0], r_int_h[0]); + transpose_64x64(r_int_v[1], r_int_h[1]); + + for (iter = 0; iter <= 5; iter++) + { + for (i = 0; i < 64; i++) { b_int_v[i] = load8(bits_ptr); bits_ptr += 8; } + bits_ptr += inc; + + layer_in(r_int_v, b_int_v, iter); + } + + for (iter = 4; iter >= 0; iter--) + { + for (i = 0; i < 64; i++) { b_int_v[i] = load8(bits_ptr); bits_ptr += 8; } + bits_ptr += inc; + + layer_in(r_int_v, b_int_v, iter); + } + + transpose_64x64(r_int_h[0], r_int_v[0]); + transpose_64x64(r_int_h[1], r_int_v[1]); + + for (iter = 6; iter >= 0; iter--) + { + for (i = 0; i < 64; i++) + { + b_int_v[i] = load8(bits_ptr); bits_ptr += 8; + } + + bits_ptr += inc; + + transpose_64x64(b_int_h, b_int_v); + + layer_ex(r_int_h[0], b_int_h, iter); + } + + transpose_64x64(r_int_v[0], r_int_h[0]); + transpose_64x64(r_int_v[1], r_int_h[1]); + + for (i = 0; i < 64; i++) + { + store8(r_ptr + i*16 + 0, r_int_v[0][i]); + store8(r_ptr + i*16 + 8, r_int_v[1][i]); + } +} + +/* input: condition bits c */ +/* output: support s */ +void support_gen(gf * s, const unsigned char *c) +{ + gf a; + int i, j; + unsigned char L[ GFBITS ][ (1 << GFBITS)/8 ]; + + for (i = 0; i < GFBITS; i++) + for (j = 0; j < (1 << GFBITS)/8; j++) + L[i][j] = 0; + + for (i = 0; i < (1 << GFBITS); i++) + { + a = bitrev((gf) i); + + for (j = 0; j < GFBITS; j++) + L[j][ i/8 ] |= ((a >> j) & 1) << (i%8); + } + + for (j = 0; j < GFBITS; j++) + apply_benes(L[j], c, 0); + + for (i = 0; i < SYS_N; i++) + { + s[i] = 0; + for (j = GFBITS-1; j >= 0; j--) + { + s[i] <<= 1; + s[i] |= (L[j][i/8] >> (i%8)) & 1; + } + } +} + diff --git a/deps/mceliece/kem/mceliece460896f/benes.h b/deps/mceliece/kem/mceliece460896f/benes.h new file mode 100644 index 0000000..c2ef35a --- /dev/null +++ b/deps/mceliece/kem/mceliece460896f/benes.h @@ -0,0 +1,16 @@ +/* + This file is for Benes network related functions +*/ + +#ifndef BENES_H +#define BENES_H +#define apply_benes CRYPTO_NAMESPACE(apply_benes) +#define support_gen CRYPTO_NAMESPACE(support_gen) + +#include "gf.h" + +void apply_benes(unsigned char *, const unsigned char *, int); +void support_gen(gf *, const unsigned char *); + +#endif + diff --git a/deps/mceliece/kem/mceliece460896f/bm.c b/deps/mceliece/kem/mceliece460896f/bm.c new file mode 100644 index 0000000..056a734 --- /dev/null +++ b/deps/mceliece/kem/mceliece460896f/bm.c @@ -0,0 +1,72 @@ +/* + This file is for the Berlekamp-Massey algorithm + see http://crypto.stanford.edu/~mironov/cs359/massey.pdf +*/ + +#include "params.h" +#include "gf.h" +#include "bm.h" + +#define min(a, b) ((a < b) ? a : b) + +/* the Berlekamp-Massey algorithm */ +/* input: s, sequence of field elements */ +/* output: out, minimal polynomial of s */ +void bm(gf *out, gf *s) +{ + int i; + + uint16_t N = 0; + uint16_t L = 0; + uint16_t mle; + uint16_t mne; + + gf T[ SYS_T+1 ]; + gf C[ SYS_T+1 ]; + gf B[ SYS_T+1 ]; + + gf b = 1, d, f; + + // + + for (i = 0; i < SYS_T+1; i++) + C[i] = B[i] = 0; + + B[1] = C[0] = 1; + + // + + for (N = 0; N < 2 * SYS_T; N++) + { + d = 0; + + for (i = 0; i <= min(N, SYS_T); i++) + d ^= gf_mul(C[i], s[ N-i]); + + mne = d; mne -= 1; mne >>= 15; mne -= 1; + mle = N; mle -= 2*L; mle >>= 15; mle -= 1; + mle &= mne; + + for (i = 0; i <= SYS_T; i++) + T[i] = C[i]; + + f = gf_frac(b, d); + + for (i = 0; i <= SYS_T; i++) + C[i] ^= gf_mul(f, B[i]) & mne; + + L = (L & ~mle) | ((N+1-L) & mle); + + for (i = 0; i <= SYS_T; i++) + B[i] = (B[i] & ~mle) | (T[i] & mle); + + b = (b & ~mle) | (d & mle); + + for (i = SYS_T; i >= 1; i--) B[i] = B[i-1]; + B[0] = 0; + } + + for (i = 0; i <= SYS_T; i++) + out[i] = C[ SYS_T-i ]; +} + diff --git a/deps/mceliece/kem/mceliece460896f/bm.h b/deps/mceliece/kem/mceliece460896f/bm.h new file mode 100644 index 0000000..73d5c6c --- /dev/null +++ b/deps/mceliece/kem/mceliece460896f/bm.h @@ -0,0 +1,13 @@ +/* + This file is for the Berlekamp-Massey algorithm + see http://crypto.stanford.edu/~mironov/cs359/massey.pdf +*/ + +#ifndef BM_H +#define BM_H +#define bm CRYPTO_NAMESPACE(bm) + +void bm(gf *, gf *); + +#endif + diff --git a/deps/mceliece/kem/mceliece460896f/controlbits.c b/deps/mceliece/kem/mceliece460896f/controlbits.c new file mode 100644 index 0000000..db9db9c --- /dev/null +++ b/deps/mceliece/kem/mceliece460896f/controlbits.c @@ -0,0 +1,220 @@ +/* This file is for implementing the Nassimi-Sahni algorithm */ +/* See David Nassimi, Sartaj Sahni "Parallel algorithms to set up the Benes permutationnetwork" */ +/* See also https://cr.yp.to/papers/controlbits-20200923.pdf */ + +#include +#include "crypto_declassify.h" +#include "controlbits.h" +#include "int32_sort.h" +typedef int16_t int16; +typedef int32_t int32; +#include "crypto_int32.h" +#define int32_min crypto_int32_min +#include "crypto_int16.h" + +/* parameters: 1 <= w <= 14; n = 2^w */ +/* input: permutation pi of {0,1,...,n-1} */ +/* output: (2m-1)n/2 control bits at positions pos,pos+step,... */ +/* output position pos is by definition 1&(out[pos/8]>>(pos&7)) */ +/* caller must 0-initialize positions first */ +/* temp must have space for int32[2*n] */ +static void cbrecursion(unsigned char *out,long long pos,long long step,const int16 *pi,long long w,long long n,int32 *temp) +{ +#define A temp +#define B (temp+n) +#define q ((int16 *) (temp+n+n/4)) +/* q can start anywhere between temp+n and temp+n/2 */ + + long long x,i,j,k; + + if (w == 1) { + out[pos>>3] ^= pi[0]<<(pos&7); + return; + } + + for (x = 0;x < n;++x) A[x] = ((pi[x]^1)<<16)|pi[x^1]; + int32_sort(A,n); /* A = (id<<16)+pibar */ + + for (x = 0;x < n;++x) { + int32 Ax = A[x]; + int32 px = Ax&0xffff; + int32 cx = int32_min(px,x); + B[x] = (px<<16)|cx; + } + /* B = (p<<16)+c */ + + for (x = 0;x < n;++x) A[x] = (A[x]<<16)|x; /* A = (pibar<<16)+id */ + int32_sort(A,n); /* A = (id<<16)+pibar^-1 */ + + for (x = 0;x < n;++x) A[x] = (A[x]<<16)+(B[x]>>16); /* A = (pibar^(-1)<<16)+pibar */ + int32_sort(A,n); /* A = (id<<16)+pibar^2 */ + + if (w <= 10) { + for (x = 0;x < n;++x) B[x] = ((A[x]&0xffff)<<10)|(B[x]&0x3ff); + + for (i = 1;i < w-1;++i) { + /* B = (p<<10)+c */ + + for (x = 0;x < n;++x) A[x] = ((B[x]&~0x3ff)<<6)|x; /* A = (p<<16)+id */ + int32_sort(A,n); /* A = (id<<16)+p^{-1} */ + + for (x = 0;x < n;++x) A[x] = (A[x]<<20)|B[x]; /* A = (p^{-1}<<20)+(p<<10)+c */ + int32_sort(A,n); /* A = (id<<20)+(pp<<10)+cp */ + + for (x = 0;x < n;++x) { + int32 ppcpx = A[x]&0xfffff; + int32 ppcx = (A[x]&0xffc00)|(B[x]&0x3ff); + B[x] = int32_min(ppcx,ppcpx); + } + } + for (x = 0;x < n;++x) B[x] &= 0x3ff; + } else { + for (x = 0;x < n;++x) B[x] = (A[x]<<16)|(B[x]&0xffff); + + for (i = 1;i < w-1;++i) { + /* B = (p<<16)+c */ + + for (x = 0;x < n;++x) A[x] = (B[x]&~0xffff)|x; + int32_sort(A,n); /* A = (id<<16)+p^(-1) */ + + for (x = 0;x < n;++x) A[x] = (A[x]<<16)|(B[x]&0xffff); + /* A = p^(-1)<<16+c */ + + if (i < w-2) { + for (x = 0;x < n;++x) B[x] = (A[x]&~0xffff)|(B[x]>>16); + /* B = (p^(-1)<<16)+p */ + int32_sort(B,n); /* B = (id<<16)+p^(-2) */ + for (x = 0;x < n;++x) B[x] = (B[x]<<16)|(A[x]&0xffff); + /* B = (p^(-2)<<16)+c */ + } + + int32_sort(A,n); + /* A = id<<16+cp */ + for (x = 0;x < n;++x) { + int32 cpx = (B[x]&~0xffff)|(A[x]&0xffff); + B[x] = int32_min(B[x],cpx); + } + } + for (x = 0;x < n;++x) B[x] &= 0xffff; + } + + for (x = 0;x < n;++x) A[x] = (((int32)pi[x])<<16)+x; + int32_sort(A,n); /* A = (id<<16)+pi^(-1) */ + + for (j = 0;j < n/2;++j) { + long long x = 2*j; + int32 fj = B[x]&1; /* f[j] */ + int32 Fx = x+fj; /* F[x] */ + int32 Fx1 = Fx^1; /* F[x+1] */ + + out[pos>>3] ^= fj<<(pos&7); + pos += step; + + B[x] = (A[x]<<16)|Fx; + B[x+1] = (A[x+1]<<16)|Fx1; + } + /* B = (pi^(-1)<<16)+F */ + + int32_sort(B,n); /* B = (id<<16)+F(pi) */ + + pos += (2*w-3)*step*(n/2); + + for (k = 0;k < n/2;++k) { + long long y = 2*k; + int32 lk = B[y]&1; /* l[k] */ + int32 Ly = y+lk; /* L[y] */ + int32 Ly1 = Ly^1; /* L[y+1] */ + + out[pos>>3] ^= lk<<(pos&7); + pos += step; + + A[y] = (Ly<<16)|(B[y]&0xffff); + A[y+1] = (Ly1<<16)|(B[y+1]&0xffff); + } + /* A = (L<<16)+F(pi) */ + + int32_sort(A,n); /* A = (id<<16)+F(pi(L)) = (id<<16)+M */ + + pos -= (2*w-2)*step*(n/2); + + for (j = 0;j < n/2;++j) { + q[j] = (A[2*j]&0xffff)>>1; + q[j+n/2] = (A[2*j+1]&0xffff)>>1; + } + + cbrecursion(out,pos,step*2,q,w-1,n/2,temp); + cbrecursion(out,pos+step,step*2,q+n/2,w-1,n/2,temp); +} + +/* input: p, an array of int16 */ +/* input: n, length of p */ +/* input: s, meaning that stride-2^s cswaps are performed */ +/* input: cb, the control bits */ +/* output: the result of apply the control bits to p */ +static void layer(int16_t *p, const unsigned char *cb, int s, int n) +{ + int i, j; + int stride = 1 << s; + int index = 0; + int16_t d, m; + + for (i = 0; i < n; i += stride*2) + { + for (j = 0; j < stride; j++) + { + d = p[ i+j ] ^ p[ i+j+stride ]; + m = (cb[ index >> 3 ] >> (index & 7)) & 1; + m = -m; + d &= m; + p[ i+j ] ^= d; + p[ i+j+stride ] ^= d; + index++; + } + } +} + +/* parameters: 1 <= w <= 14; n = 2^w */ +/* input: permutation pi of {0,1,...,n-1} */ +/* output: (2m-1)n/2 control bits at positions 0,1,... */ +/* output position pos is by definition 1&(out[pos/8]>>(pos&7)) */ +void controlbitsfrompermutation(unsigned char *out,const int16 *pi,long long w,long long n) +{ + int32 temp[2*n]; + int16 pi_test[n], diff; + int i; + unsigned char *ptr; + + while (1) + { + memset(out,0,(((2*w-1)*n/2)+7)/8); + cbrecursion(out,0,1,pi,w,n,temp); + + // check for correctness + + for (i = 0; i < n; i++) + pi_test[i] = i; + + ptr = out; + for (i = 0; i < w; i++) + { + layer(pi_test, ptr, i, n); + ptr += n >> 4; + } + + for (i = w-2; i >= 0; i--) + { + layer(pi_test, ptr, i, n); + ptr += n >> 4; + } + + diff = 0; + for (i = 0; i < n; i++) + diff |= pi[i] ^ pi_test[i]; + + diff = crypto_int16_nonzero_mask(diff); + crypto_declassify(&diff,sizeof diff); + if (diff == 0) + break; + } +} + diff --git a/deps/mceliece/kem/mceliece460896f/controlbits.h b/deps/mceliece/kem/mceliece460896f/controlbits.h new file mode 100644 index 0000000..8ddd210 --- /dev/null +++ b/deps/mceliece/kem/mceliece460896f/controlbits.h @@ -0,0 +1,14 @@ +/* This file is for implementing the Nassimi-Sahni algorithm */ +/* See David Nassimi, Sartaj Sahni "Parallel algorithms to set up the Benes permutationnetwork" */ +/* See also https://cr.yp.to/papers/controlbits-20200923.pdf */ + +#ifndef CONTROLBITS_H +#define CONTROLBITS_H + +#define controlbitsfrompermutation CRYPTO_NAMESPACE(controlbitsfrompermutation) + +#include + +extern void controlbitsfrompermutation(unsigned char *,const int16_t *,long long,long long); + +#endif diff --git a/deps/mceliece/kem/mceliece460896f/crypto_hash.h b/deps/mceliece/kem/mceliece460896f/crypto_hash.h new file mode 100644 index 0000000..b7c1086 --- /dev/null +++ b/deps/mceliece/kem/mceliece460896f/crypto_hash.h @@ -0,0 +1,10 @@ +/* This file uses SHAKE256 implemented in the Keccak Code Package */ + +#include "../../mceliece_externals.h" + +#define crypto_hash_32b(out,in,inlen) \ + SHAKE256(out,32,in,inlen) + +#define shake(out,outlen,in,inlen) \ + SHAKE256(out,outlen,in,inlen) + diff --git a/deps/mceliece/kem/mceliece460896f/crypto_kem.h b/deps/mceliece/kem/mceliece460896f/crypto_kem.h new file mode 100644 index 0000000..6fa4e82 --- /dev/null +++ b/deps/mceliece/kem/mceliece460896f/crypto_kem.h @@ -0,0 +1,15 @@ +#ifndef crypto_kem_H +#define crypto_kem_H + +#include "crypto_kem_mceliece460896f.h" + +#define crypto_kem_keypair crypto_kem_mceliece460896f_keypair +#define crypto_kem_enc crypto_kem_mceliece460896f_enc +#define crypto_kem_dec crypto_kem_mceliece460896f_dec +#define crypto_kem_PUBLICKEYBYTES crypto_kem_mceliece460896f_PUBLICKEYBYTES +#define crypto_kem_SECRETKEYBYTES crypto_kem_mceliece460896f_SECRETKEYBYTES +#define crypto_kem_BYTES crypto_kem_mceliece460896f_BYTES +#define crypto_kem_CIPHERTEXTBYTES crypto_kem_mceliece460896f_CIPHERTEXTBYTES +#define crypto_kem_PRIMITIVE "mceliece460896f" + +#endif diff --git a/deps/mceliece/kem/mceliece460896f/crypto_kem_mceliece460896f.h b/deps/mceliece/kem/mceliece460896f/crypto_kem_mceliece460896f.h new file mode 100644 index 0000000..3abac82 --- /dev/null +++ b/deps/mceliece/kem/mceliece460896f/crypto_kem_mceliece460896f.h @@ -0,0 +1,28 @@ +#ifndef crypto_kem_mceliece460896f_H +#define crypto_kem_mceliece460896f_H + +#define crypto_kem_mceliece460896f_ref_PUBLICKEYBYTES 524160 +#define crypto_kem_mceliece460896f_ref_SECRETKEYBYTES 13608 +#define crypto_kem_mceliece460896f_ref_CIPHERTEXTBYTES 156 +#define crypto_kem_mceliece460896f_ref_BYTES 32 + + +#ifdef __cplusplus +extern "C" { +#endif +extern int crypto_kem_mceliece460896f_ref_keypair(unsigned char *,unsigned char *); +extern int crypto_kem_mceliece460896f_ref_enc(unsigned char *,unsigned char *,const unsigned char *); +extern int crypto_kem_mceliece460896f_ref_dec(unsigned char *,const unsigned char *,const unsigned char *); +#ifdef __cplusplus +} +#endif + +#define crypto_kem_mceliece460896f_keypair crypto_kem_mceliece460896f_ref_keypair +#define crypto_kem_mceliece460896f_enc crypto_kem_mceliece460896f_ref_enc +#define crypto_kem_mceliece460896f_dec crypto_kem_mceliece460896f_ref_dec +#define crypto_kem_mceliece460896f_PUBLICKEYBYTES crypto_kem_mceliece460896f_ref_PUBLICKEYBYTES +#define crypto_kem_mceliece460896f_SECRETKEYBYTES crypto_kem_mceliece460896f_ref_SECRETKEYBYTES +#define crypto_kem_mceliece460896f_BYTES crypto_kem_mceliece460896f_ref_BYTES +#define crypto_kem_mceliece460896f_CIPHERTEXTBYTES crypto_kem_mceliece460896f_ref_CIPHERTEXTBYTES + +#endif diff --git a/deps/mceliece/kem/mceliece460896f/decrypt.c b/deps/mceliece/kem/mceliece460896f/decrypt.c new file mode 100644 index 0000000..c4cc6de --- /dev/null +++ b/deps/mceliece/kem/mceliece460896f/decrypt.c @@ -0,0 +1,93 @@ +/* + This file is for Niederreiter decryption +*/ + +#include +#include "decrypt.h" + +#include "params.h" +#include "benes.h" +#include "util.h" +#include "synd.h" +#include "root.h" +#include "gf.h" +#include "bm.h" + +/* Niederreiter decryption with the Berlekamp decoder */ +/* intput: sk, secret key */ +/* c, ciphertext */ +/* output: e, error vector */ +/* return: 0 for success; 1 for failure */ +int decrypt(unsigned char *e, const unsigned char *sk, const unsigned char *c) +{ + int i, w = 0; + uint16_t check; + + unsigned char r[ SYS_N/8 ]; + + gf g[ SYS_T+1 ]; + gf L[ SYS_N ]; + + gf s[ SYS_T*2 ]; + gf s_cmp[ SYS_T*2 ]; + gf locator[ SYS_T+1 ]; + gf images[ SYS_N ]; + + gf t; + + // + + for (i = 0; i < SYND_BYTES; i++) r[i] = c[i]; + for (i = SYND_BYTES; i < SYS_N/8; i++) r[i] = 0; + + for (i = 0; i < SYS_T; i++) { g[i] = load_gf(sk); sk += 2; } g[ SYS_T ] = 1; + + support_gen(L, sk); + + synd(s, g, L, r); + + bm(locator, s); + + root(images, locator, L); + + // + + for (i = 0; i < SYS_N/8; i++) + e[i] = 0; + + for (i = 0; i < SYS_N; i++) + { + t = gf_iszero(images[i]) & 1; + + e[ i/8 ] |= t << (i%8); + w += t; + + } + +#ifdef KAT + { + int k; + printf("decrypt e: positions"); + for (k = 0;k < SYS_N;++k) + if (e[k/8] & (1 << (k&7))) + printf(" %d",k); + printf("\n"); + } +#endif + + synd(s_cmp, g, L, e); + + // + + check = w; + check ^= SYS_T; + + for (i = 0; i < SYS_T*2; i++) + check |= s[i] ^ s_cmp[i]; + + check -= 1; + check >>= 15; + + return check ^ 1; +} + diff --git a/deps/mceliece/kem/mceliece460896f/decrypt.h b/deps/mceliece/kem/mceliece460896f/decrypt.h new file mode 100644 index 0000000..266a5cd --- /dev/null +++ b/deps/mceliece/kem/mceliece460896f/decrypt.h @@ -0,0 +1,12 @@ +/* + This file is for Nieddereiter decryption +*/ + +#ifndef DECRYPT_H +#define DECRYPT_H +#define decrypt CRYPTO_NAMESPACE(decrypt) + +int decrypt(unsigned char *, const unsigned char *, const unsigned char *); + +#endif + diff --git a/deps/mceliece/kem/mceliece460896f/encrypt.c b/deps/mceliece/kem/mceliece460896f/encrypt.c new file mode 100644 index 0000000..4823d2f --- /dev/null +++ b/deps/mceliece/kem/mceliece460896f/encrypt.c @@ -0,0 +1,161 @@ +/* + This file is for Niederreiter encryption +*/ + +#include "encrypt.h" + +#include "util.h" +#include "params.h" +#include "randombytes.h" + +#include +#include +#include +#include + +#include "gf.h" +#include "crypto_declassify.h" +#include "crypto_uint16.h" +#include "crypto_uint32.h" + +static inline crypto_uint16 uint16_is_smaller_declassify(uint16_t t,uint16_t u) +{ + crypto_uint16 mask = crypto_uint16_smaller_mask(t,u); + crypto_declassify(&mask,sizeof mask); + return mask; +} + +static inline crypto_uint32 uint32_is_equal_declassify(uint32_t t,uint32_t u) +{ + crypto_uint32 mask = crypto_uint32_equal_mask(t,u); + crypto_declassify(&mask,sizeof mask); + return mask; +} + +static inline unsigned char same_mask(uint16_t x, uint16_t y) +{ + uint32_t mask; + + mask = x ^ y; + mask -= 1; + mask >>= 31; + mask = -mask; + + return mask & 0xFF; +} + +/* output: e, an error vector of weight t */ +static void gen_e(unsigned char *e) +{ + int i, j, eq, count; + + union + { + uint16_t nums[ SYS_T*2 ]; + unsigned char bytes[ SYS_T*2 * sizeof(uint16_t) ]; + } buf; + + uint16_t ind[ SYS_T ]; + unsigned char mask; + unsigned char val[ SYS_T ]; + + while (1) + { + randombytes(buf.bytes, sizeof(buf)); + + for (i = 0; i < SYS_T*2; i++) + buf.nums[i] = load_gf(buf.bytes + i*2); + + // moving and counting indices in the correct range + + count = 0; + for (i = 0; i < SYS_T*2 && count < SYS_T; i++) + if (uint16_is_smaller_declassify(buf.nums[i],SYS_N)) + ind[ count++ ] = buf.nums[i]; + + if (count < SYS_T) continue; + + // check for repetition + + eq = 0; + + for (i = 1; i < SYS_T; i++) + for (j = 0; j < i; j++) + if (uint32_is_equal_declassify(ind[i],ind[j])) + eq = 1; + + if (eq == 0) + break; + } + + for (j = 0; j < SYS_T; j++) + val[j] = 1 << (ind[j] & 7); + + for (i = 0; i < SYS_N/8; i++) + { + e[i] = 0; + + for (j = 0; j < SYS_T; j++) + { + mask = same_mask(i, (ind[j] >> 3)); + + e[i] |= val[j] & mask; + } + } +} + +/* input: public key pk, error vector e */ +/* output: syndrome s */ +static void syndrome(unsigned char *s, const unsigned char *pk, unsigned char *e) +{ + unsigned char b, row[SYS_N/8]; + const unsigned char *pk_ptr = pk; + + int i, j; + + for (i = 0; i < SYND_BYTES; i++) + s[i] = 0; + + for (i = 0; i < PK_NROWS; i++) + { + for (j = 0; j < SYS_N/8; j++) + row[j] = 0; + + for (j = 0; j < PK_ROW_BYTES; j++) + row[ SYS_N/8 - PK_ROW_BYTES + j ] = pk_ptr[j]; + + row[i/8] |= 1 << (i%8); + + b = 0; + for (j = 0; j < SYS_N/8; j++) + b ^= row[j] & e[j]; + + b ^= b >> 4; + b ^= b >> 2; + b ^= b >> 1; + b &= 1; + + s[ i/8 ] |= (b << (i%8)); + + pk_ptr += PK_ROW_BYTES; + } +} + +void encrypt(unsigned char *s, const unsigned char *pk, unsigned char *e) +{ + gen_e(e); + +#ifdef KAT + { + int k; + printf("encrypt e: positions"); + for (k = 0;k < SYS_N;++k) + if (e[k/8] & (1 << (k&7))) + printf(" %d",k); + printf("\n"); + } +#endif + + syndrome(s, pk, e); +} + diff --git a/deps/mceliece/kem/mceliece460896f/encrypt.h b/deps/mceliece/kem/mceliece460896f/encrypt.h new file mode 100644 index 0000000..8edd7a6 --- /dev/null +++ b/deps/mceliece/kem/mceliece460896f/encrypt.h @@ -0,0 +1,12 @@ +/* + This file is for Niederreiter encryption +*/ + +#ifndef ENCRYPT_H +#define ENCRYPT_H +#define encrypt CRYPTO_NAMESPACE(encrypt) + +void encrypt(unsigned char *, const unsigned char *, unsigned char *); + +#endif + diff --git a/deps/mceliece/kem/mceliece460896f/gf.c b/deps/mceliece/kem/mceliece460896f/gf.c new file mode 100644 index 0000000..ce28327 --- /dev/null +++ b/deps/mceliece/kem/mceliece460896f/gf.c @@ -0,0 +1,215 @@ +/* + This file is for functions for field arithmetic +*/ + +#include "gf.h" + +#include "params.h" + +gf gf_iszero(gf a) +{ + uint32_t t = a; + + t -= 1; + t >>= 19; + + return (gf) t; +} + +gf gf_add(gf in0, gf in1) +{ + return in0 ^ in1; +} + +gf gf_mul(gf in0, gf in1) +{ + int i; + + uint64_t tmp; + uint64_t t0; + uint64_t t1; + uint64_t t; + + t0 = in0; + t1 = in1; + + tmp = t0 * (t1 & 1); + + for (i = 1; i < GFBITS; i++) + tmp ^= (t0 * (t1 & (1 << i))); + + // + + t = tmp & 0x1FF0000; + tmp ^= (t >> 9) ^ (t >> 10) ^ (t >> 12) ^ (t >> 13); + + t = tmp & 0x000E000; + tmp ^= (t >> 9) ^ (t >> 10) ^ (t >> 12) ^ (t >> 13); + + return tmp & GFMASK; +} + +/* input: field element in */ +/* return: (in^2)^2 */ +static inline gf gf_sq2(gf in) +{ + int i; + + const uint64_t B[] = {0x1111111111111111, + 0x0303030303030303, + 0x000F000F000F000F, + 0x000000FF000000FF}; + + const uint64_t M[] = {0x0001FF0000000000, + 0x000000FF80000000, + 0x000000007FC00000, + 0x00000000003FE000}; + + uint64_t x = in; + uint64_t t; + + x = (x | (x << 24)) & B[3]; + x = (x | (x << 12)) & B[2]; + x = (x | (x << 6)) & B[1]; + x = (x | (x << 3)) & B[0]; + + for (i = 0; i < 4; i++) + { + t = x & M[i]; + x ^= (t >> 9) ^ (t >> 10) ^ (t >> 12) ^ (t >> 13); + } + + return x & GFMASK; +} + +/* input: field element in, m */ +/* return: (in^2)*m */ +static inline gf gf_sqmul(gf in, gf m) +{ + int i; + + uint64_t x; + uint64_t t0; + uint64_t t1; + uint64_t t; + + const uint64_t M[] = {0x0000001FF0000000, + 0x000000000FF80000, + 0x000000000007E000}; + + t0 = in; + t1 = m; + + x = (t1 << 6) * (t0 & (1 << 6)); + + t0 ^= (t0 << 7); + + x ^= (t1 * (t0 & (0x04001))); + x ^= (t1 * (t0 & (0x08002))) << 1; + x ^= (t1 * (t0 & (0x10004))) << 2; + x ^= (t1 * (t0 & (0x20008))) << 3; + x ^= (t1 * (t0 & (0x40010))) << 4; + x ^= (t1 * (t0 & (0x80020))) << 5; + + for (i = 0; i < 3; i++) + { + t = x & M[i]; + x ^= (t >> 9) ^ (t >> 10) ^ (t >> 12) ^ (t >> 13); + } + + return x & GFMASK; +} + +/* input: field element in, m */ +/* return: ((in^2)^2)*m */ +static inline gf gf_sq2mul(gf in, gf m) +{ + int i; + + uint64_t x; + uint64_t t0; + uint64_t t1; + uint64_t t; + + const uint64_t M[] = {0x1FF0000000000000, + 0x000FF80000000000, + 0x000007FC00000000, + 0x00000003FE000000, + 0x0000000001FE0000, + 0x000000000001E000}; + + t0 = in; + t1 = m; + + x = (t1 << 18) * (t0 & (1 << 6)); + + t0 ^= (t0 << 21); + + x ^= (t1 * (t0 & (0x010000001))); + x ^= (t1 * (t0 & (0x020000002))) << 3; + x ^= (t1 * (t0 & (0x040000004))) << 6; + x ^= (t1 * (t0 & (0x080000008))) << 9; + x ^= (t1 * (t0 & (0x100000010))) << 12; + x ^= (t1 * (t0 & (0x200000020))) << 15; + + for (i = 0; i < 6; i++) + { + t = x & M[i]; + x ^= (t >> 9) ^ (t >> 10) ^ (t >> 12) ^ (t >> 13); + } + + return x & GFMASK; +} + +/* input: field element den, num */ +/* return: (num/den) */ +gf gf_frac(gf den, gf num) +{ + gf tmp_11; + gf tmp_1111; + gf out; + + tmp_11 = gf_sqmul(den, den); // ^11 + tmp_1111 = gf_sq2mul(tmp_11, tmp_11); // ^1111 + out = gf_sq2(tmp_1111); + out = gf_sq2mul(out, tmp_1111); // ^11111111 + out = gf_sq2(out); + out = gf_sq2mul(out, tmp_1111); // ^111111111111 + + return gf_sqmul(out, num); // ^1111111111110 = ^-1 +} + +gf gf_inv(gf den) +{ + return gf_frac(den, ((gf) 1)); +} + +/* input: in0, in1 in GF((2^m)^t)*/ +/* output: out = in0*in1 */ +void GF_mul(gf *out, gf *in0, gf *in1) +{ + int i, j; + + gf prod[ SYS_T*2-1 ]; + + for (i = 0; i < SYS_T*2-1; i++) + prod[i] = 0; + + for (i = 0; i < SYS_T; i++) + for (j = 0; j < SYS_T; j++) + prod[i+j] ^= gf_mul(in0[i], in1[j]); + + // + + for (i = (SYS_T-1)*2; i >= SYS_T; i--) + { + prod[i - SYS_T + 10] ^= prod[i]; + prod[i - SYS_T + 9] ^= prod[i]; + prod[i - SYS_T + 6] ^= prod[i]; + prod[i - SYS_T + 0] ^= prod[i]; + } + + for (i = 0; i < SYS_T; i++) + out[i] = prod[i]; +} + diff --git a/deps/mceliece/kem/mceliece460896f/gf.h b/deps/mceliece/kem/mceliece460896f/gf.h new file mode 100644 index 0000000..f62209d --- /dev/null +++ b/deps/mceliece/kem/mceliece460896f/gf.h @@ -0,0 +1,27 @@ +/* + This file is for functions for field arithmetic +*/ + +#ifndef GF_H +#define GF_H +#define gf_add CRYPTO_NAMESPACE(gf_add) +#define gf_frac CRYPTO_NAMESPACE(gf_frac) +#define gf_inv CRYPTO_NAMESPACE(gf_inv) +#define gf_iszero CRYPTO_NAMESPACE(gf_iszero) +#define gf_mul CRYPTO_NAMESPACE(gf_mul) +#define GF_mul CRYPTO_NAMESPACE(GF_mul) + +#include + +typedef uint16_t gf; + +gf gf_iszero(gf); +gf gf_add(gf, gf); +gf gf_mul(gf, gf); +gf gf_frac(gf, gf); +gf gf_inv(gf); + +void GF_mul(gf *, gf *, gf *); + +#endif + diff --git a/deps/mceliece/kem/mceliece460896f/int32_sort.h b/deps/mceliece/kem/mceliece460896f/int32_sort.h new file mode 100644 index 0000000..a431af2 --- /dev/null +++ b/deps/mceliece/kem/mceliece460896f/int32_sort.h @@ -0,0 +1,46 @@ +#ifndef int32_sort_h +#define int32_sort_h + +#define int32_sort CRYPTO_NAMESPACE(int32_sort) + +#include + +#define int32_MINMAX(a,b) \ +do { \ + int32_t ab = b ^ a; \ + int32_t c = b - a; \ + c ^= ab & (c ^ b); \ + c >>= 31; \ + c &= ab; \ + a ^= c; \ + b ^= c; \ +} while(0) + +static void int32_sort(int32_t *x,long long n) +{ + long long top,p,q,r,i; + + if (n < 2) return; + top = 1; + while (top < n - top) top += top; + + for (p = top;p > 0;p >>= 1) { + for (i = 0;i < n - p;++i) + if (!(i & p)) + int32_MINMAX(x[i],x[i+p]); + i = 0; + for (q = top;q > p;q >>= 1) { + for (;i < n - q;++i) { + if (!(i & p)) { + int32_t a = x[i + p]; + for (r = q;r > p;r >>= 1) + int32_MINMAX(a,x[i+r]); + x[i + p] = a; + } + } + } + } +} + +#endif + diff --git a/deps/mceliece/kem/mceliece460896f/operations.c b/deps/mceliece/kem/mceliece460896f/operations.c new file mode 100644 index 0000000..bb605b1 --- /dev/null +++ b/deps/mceliece/kem/mceliece460896f/operations.c @@ -0,0 +1,147 @@ +#include "operations.h" + +#include "controlbits.h" +#include "randombytes.h" +#include "crypto_hash.h" +#include "encrypt.h" +#include "decrypt.h" +#include "params.h" +#include "sk_gen.h" +#include "pk_gen.h" +#include "util.h" + +#include +#include + +int crypto_kem_enc( + unsigned char *c, + unsigned char *key, + const unsigned char *pk +) +{ + unsigned char e[ SYS_N/8 ]; + unsigned char one_ec[ 1 + SYS_N/8 + SYND_BYTES ] = {1}; + + // + + encrypt(c, pk, e); + + memcpy(one_ec + 1, e, SYS_N/8); + memcpy(one_ec + 1 + SYS_N/8, c, SYND_BYTES); + + crypto_hash_32b(key, one_ec, sizeof(one_ec)); + + return 0; +} + +int crypto_kem_dec( + unsigned char *key, + const unsigned char *c, + const unsigned char *sk +) +{ + int i; + + unsigned char ret_decrypt = 0; + + uint16_t m; + + unsigned char e[ SYS_N/8 ]; + unsigned char preimage[ 1 + SYS_N/8 + SYND_BYTES ]; + unsigned char *x = preimage; + const unsigned char *s = sk + 40 + IRR_BYTES + COND_BYTES; + + // + + ret_decrypt = decrypt(e, sk + 40, c); + + m = ret_decrypt; + m -= 1; + m >>= 8; + + *x++ = m & 1; + for (i = 0; i < SYS_N/8; i++) + *x++ = (~m & s[i]) | (m & e[i]); + + for (i = 0; i < SYND_BYTES; i++) + *x++ = c[i]; + + crypto_hash_32b(key, preimage, sizeof(preimage)); + + return 0; +} + +int crypto_kem_keypair +( + unsigned char *pk, + unsigned char *sk +) +{ + int i; + unsigned char seed[ 33 ] = {64}; + unsigned char r[ SYS_N/8 + (1 << GFBITS)*sizeof(uint32_t) + SYS_T*2 + 32 ]; + unsigned char *rp, *skp; + uint64_t pivots; + + gf f[ SYS_T ]; // element in GF(2^mt) + gf irr[ SYS_T ]; // Goppa polynomial + uint32_t perm[ 1 << GFBITS ]; // random permutation as 32-bit integers + int16_t pi[ 1 << GFBITS ]; // random permutation + + randombytes(seed+1, 32); + + while (1) + { + rp = &r[ sizeof(r)-32 ]; + skp = sk; + + // expanding and updating the seed + + shake(r, sizeof(r), seed, 33); + memcpy(skp, seed+1, 32); + skp += 32 + 8; + memcpy(seed+1, &r[ sizeof(r)-32 ], 32); + + // generating irreducible polynomial + + rp -= sizeof(f); + + for (i = 0; i < SYS_T; i++) + f[i] = load_gf(rp + i*2); + + if (genpoly_gen(irr, f)) + continue; + + for (i = 0; i < SYS_T; i++) + store_gf(skp + i*2, irr[i]); + + skp += IRR_BYTES; + + // generating permutation + + rp -= sizeof(perm); + + for (i = 0; i < (1 << GFBITS); i++) + perm[i] = load4(rp + i*4); + + if (pk_gen(pk, skp - IRR_BYTES, perm, pi, &pivots)) + continue; + + controlbitsfrompermutation(skp, pi, GFBITS, 1 << GFBITS); + skp += COND_BYTES; + + // storing the random string s + + rp -= SYS_N/8; + memcpy(skp, rp, SYS_N/8); + + // storing positions of the 32 pivots + + store8(sk + 32, pivots); + + break; + } + + return 0; +} + diff --git a/deps/mceliece/kem/mceliece460896f/operations.h b/deps/mceliece/kem/mceliece460896f/operations.h new file mode 100644 index 0000000..bf65502 --- /dev/null +++ b/deps/mceliece/kem/mceliece460896f/operations.h @@ -0,0 +1,25 @@ +#ifndef OPERATIONS_H +#define OPERATIONS_H + +#include "crypto_kem.h" + +int crypto_kem_enc( + unsigned char *c, + unsigned char *key, + const unsigned char *pk +); + +int crypto_kem_dec( + unsigned char *key, + const unsigned char *c, + const unsigned char *sk +); + +int crypto_kem_keypair +( + unsigned char *pk, + unsigned char *sk +); + +#endif + diff --git a/deps/mceliece/kem/mceliece460896f/params.h b/deps/mceliece/kem/mceliece460896f/params.h new file mode 100644 index 0000000..c6682ba --- /dev/null +++ b/deps/mceliece/kem/mceliece460896f/params.h @@ -0,0 +1,20 @@ +#ifndef PARAMS_H +#define PARAMS_H + +#define GFBITS 13 +#define SYS_N 4608 +#define SYS_T 96 + +#define COND_BYTES ((1 << (GFBITS-4))*(2*GFBITS - 1)) +#define IRR_BYTES (SYS_T * 2) + +#define PK_NROWS (SYS_T*GFBITS) +#define PK_NCOLS (SYS_N - PK_NROWS) +#define PK_ROW_BYTES ((PK_NCOLS + 7)/8) + +#define SYND_BYTES ((PK_NROWS + 7)/8) + +#define GFMASK ((1 << GFBITS) - 1) + +#endif + diff --git a/deps/mceliece/kem/mceliece460896f/pk_gen.c b/deps/mceliece/kem/mceliece460896f/pk_gen.c new file mode 100644 index 0000000..4b4d730 --- /dev/null +++ b/deps/mceliece/kem/mceliece460896f/pk_gen.c @@ -0,0 +1,252 @@ +/* + This file is for public-key generation +*/ + +#include +#include +#include +#include + +#include "controlbits.h" +#include "uint64_sort.h" +#include "pk_gen.h" +#include "params.h" +#include "benes.h" +#include "root.h" +#include "util.h" +#include "crypto_declassify.h" +#include "crypto_uint64.h" + +static crypto_uint64 uint64_is_equal_declassify(uint64_t t,uint64_t u) +{ + crypto_uint64 mask = crypto_uint64_equal_mask(t,u); + crypto_declassify(&mask,sizeof mask); + return mask; +} + +static crypto_uint64 uint64_is_zero_declassify(uint64_t t) +{ + crypto_uint64 mask = crypto_uint64_zero_mask(t); + crypto_declassify(&mask,sizeof mask); + return mask; +} + +#define min(a, b) ((a < b) ? a : b) + +/* return number of trailing zeros of the non-zero input in */ +static inline int ctz(uint64_t in) +{ + int i, b, m = 0, r = 0; + + for (i = 0; i < 64; i++) + { + b = (in >> i) & 1; + m |= b; + r += (m^1) & (b^1); + } + + return r; +} + +static inline uint64_t same_mask(uint16_t x, uint16_t y) +{ + uint64_t mask; + + mask = x ^ y; + mask -= 1; + mask >>= 63; + mask = -mask; + + return mask; +} + +static int mov_columns(uint8_t mat[][ SYS_N/8 ], int16_t * pi, uint64_t * pivots) +{ + int i, j, k, s, block_idx, row; + uint64_t buf[64], ctz_list[32], t, d, mask, one = 1; + + row = PK_NROWS - 32; + block_idx = row/8; + + // extract the 32x64 matrix + + for (i = 0; i < 32; i++) + buf[i] = load8( &mat[ row + i ][ block_idx ] ); + + // compute the column indices of pivots by Gaussian elimination. + // the indices are stored in ctz_list + + *pivots = 0; + + for (i = 0; i < 32; i++) + { + t = buf[i]; + for (j = i+1; j < 32; j++) + t |= buf[j]; + + if (uint64_is_zero_declassify(t)) return -1; // return if buf is not full rank + + ctz_list[i] = s = ctz(t); + *pivots |= one << ctz_list[i]; + + for (j = i+1; j < 32; j++) { mask = (buf[i] >> s) & 1; mask -= 1; buf[i] ^= buf[j] & mask; } + for (j = i+1; j < 32; j++) { mask = (buf[j] >> s) & 1; mask = -mask; buf[j] ^= buf[i] & mask; } + } + + // updating permutation + + for (j = 0; j < 32; j++) + for (k = j+1; k < 64; k++) + { + d = pi[ row + j ] ^ pi[ row + k ]; + d &= same_mask(k, ctz_list[j]); + pi[ row + j ] ^= d; + pi[ row + k ] ^= d; + } + + // moving columns of mat according to the column indices of pivots + + for (i = 0; i < PK_NROWS; i++) + { + t = load8( &mat[ i ][ block_idx ] ); + + for (j = 0; j < 32; j++) + { + d = t >> j; + d ^= t >> ctz_list[j]; + d &= 1; + + t ^= d << ctz_list[j]; + t ^= d << j; + } + + store8( &mat[ i ][ block_idx ], t ); + } + + return 0; +} + +/* input: secret key sk */ +/* output: public key pk */ +int pk_gen(unsigned char * pk, unsigned char * sk, uint32_t * perm, int16_t * pi, uint64_t * pivots) +{ + int i, j, k; + int row, c; + + uint64_t buf[ 1 << GFBITS ]; + + unsigned char mat[ PK_NROWS ][ SYS_N/8 ]; + unsigned char mask; + unsigned char b; + + gf g[ SYS_T+1 ]; // Goppa polynomial + gf L[ SYS_N ]; // support + gf inv[ SYS_N ]; + + // + + g[ SYS_T ] = 1; + + for (i = 0; i < SYS_T; i++) { g[i] = load_gf(sk); sk += 2; } + + for (i = 0; i < (1 << GFBITS); i++) + { + buf[i] = perm[i]; + buf[i] <<= 31; + buf[i] |= i; + } + + uint64_sort(buf, 1 << GFBITS); + + for (i = 1; i < (1 << GFBITS); i++) + if (uint64_is_equal_declassify(buf[i-1] >> 31,buf[i] >> 31)) + return -1; + + for (i = 0; i < (1 << GFBITS); i++) pi[i] = buf[i] & GFMASK; + for (i = 0; i < SYS_N; i++) L[i] = bitrev(pi[i]); + + // filling the matrix + + root(inv, g, L); + + for (i = 0; i < SYS_N; i++) + inv[i] = gf_inv(inv[i]); + + for (i = 0; i < PK_NROWS; i++) + for (j = 0; j < SYS_N/8; j++) + mat[i][j] = 0; + + for (i = 0; i < SYS_T; i++) + { + for (j = 0; j < SYS_N; j+=8) + for (k = 0; k < GFBITS; k++) + { + b = (inv[j+7] >> k) & 1; b <<= 1; + b |= (inv[j+6] >> k) & 1; b <<= 1; + b |= (inv[j+5] >> k) & 1; b <<= 1; + b |= (inv[j+4] >> k) & 1; b <<= 1; + b |= (inv[j+3] >> k) & 1; b <<= 1; + b |= (inv[j+2] >> k) & 1; b <<= 1; + b |= (inv[j+1] >> k) & 1; b <<= 1; + b |= (inv[j+0] >> k) & 1; + + mat[ i*GFBITS + k ][ j/8 ] = b; + } + + for (j = 0; j < SYS_N; j++) + inv[j] = gf_mul(inv[j], L[j]); + + } + + // gaussian elimination + + for (i = 0; i < (PK_NROWS + 7) / 8; i++) + for (j = 0; j < 8; j++) + { + row = i*8 + j; + + if (row >= PK_NROWS) + break; + + if (row == PK_NROWS - 32) + { + if (mov_columns(mat, pi, pivots)) + return -1; + } + + for (k = row + 1; k < PK_NROWS; k++) + { + mask = mat[ row ][ i ] ^ mat[ k ][ i ]; + mask >>= j; + mask &= 1; + mask = -mask; + + for (c = 0; c < SYS_N/8; c++) + mat[ row ][ c ] ^= mat[ k ][ c ] & mask; + } + + if ( uint64_is_zero_declassify((mat[ row ][ i ] >> j) & 1) ) // return if not systematic + { + return -1; + } + + for (k = 0; k < PK_NROWS; k++) + { + if (k != row) + { + mask = mat[ k ][ i ] >> j; + mask &= 1; + mask = -mask; + + for (c = 0; c < SYS_N/8; c++) + mat[ k ][ c ] ^= mat[ row ][ c ] & mask; + } + } + } + + for (i = 0; i < PK_NROWS; i++) + memcpy(pk + i*PK_ROW_BYTES, mat[i] + PK_NROWS/8, PK_ROW_BYTES); + + return 0; +} + diff --git a/deps/mceliece/kem/mceliece460896f/pk_gen.h b/deps/mceliece/kem/mceliece460896f/pk_gen.h new file mode 100644 index 0000000..96b7e7b --- /dev/null +++ b/deps/mceliece/kem/mceliece460896f/pk_gen.h @@ -0,0 +1,14 @@ +/* + This file is for public-key generation +*/ + +#ifndef PK_GEN_H +#define PK_GEN_H +#define pk_gen CRYPTO_NAMESPACE(pk_gen) + +#include "gf.h" + +int pk_gen(unsigned char *, unsigned char *, uint32_t *, int16_t *, uint64_t *); + +#endif + diff --git a/deps/mceliece/kem/mceliece460896f/randombytes.h b/deps/mceliece/kem/mceliece460896f/randombytes.h new file mode 100644 index 0000000..7e59351 --- /dev/null +++ b/deps/mceliece/kem/mceliece460896f/randombytes.h @@ -0,0 +1 @@ +#include "../../mceliece_externals.h" diff --git a/deps/mceliece/kem/mceliece460896f/root.c b/deps/mceliece/kem/mceliece460896f/root.c new file mode 100644 index 0000000..1c1b634 --- /dev/null +++ b/deps/mceliece/kem/mceliece460896f/root.c @@ -0,0 +1,38 @@ +/* + This file is for evaluating a polynomial at one or more field elements +*/ + +#include "root.h" +#include "params.h" +#include "gf.h" + +#include + +/* input: polynomial f and field element a */ +/* return f(a) */ +gf eval(gf *f, gf a) +{ + int i; + gf r; + + r = f[ SYS_T ]; + + for (i = SYS_T-1; i >= 0; i--) + { + r = gf_mul(r, a); + r = gf_add(r, f[i]); + } + + return r; +} + +/* input: polynomial f and list of field elements L */ +/* output: out = [ f(a) for a in L ] */ +void root(gf *out, gf *f, gf *L) +{ + int i; + + for (i = 0; i < SYS_N; i++) + out[i] = eval(f, L[i]); +} + diff --git a/deps/mceliece/kem/mceliece460896f/root.h b/deps/mceliece/kem/mceliece460896f/root.h new file mode 100644 index 0000000..42516e4 --- /dev/null +++ b/deps/mceliece/kem/mceliece460896f/root.h @@ -0,0 +1,16 @@ +/* + This file is for evaluating a polynomial at one or more field elements +*/ + +#ifndef ROOT_H +#define ROOT_H +#define eval CRYPTO_NAMESPACE(eval) +#define root CRYPTO_NAMESPACE(root) + +#include "gf.h" + +gf eval(gf *, gf); +void root(gf *, gf *, gf *); + +#endif + diff --git a/deps/mceliece/kem/mceliece460896f/sk_gen.c b/deps/mceliece/kem/mceliece460896f/sk_gen.c new file mode 100644 index 0000000..340cc9a --- /dev/null +++ b/deps/mceliece/kem/mceliece460896f/sk_gen.c @@ -0,0 +1,85 @@ +/* + This file is for secret-key generation +*/ + +#include "sk_gen.h" + +#include "randombytes.h" +#include "controlbits.h" +#include "params.h" +#include "util.h" +#include "gf.h" +#include "crypto_declassify.h" +#include "crypto_uint16.h" + +static inline crypto_uint16 gf_is_zero_declassify(gf t) +{ + crypto_uint16 mask = crypto_uint16_zero_mask(t); + crypto_declassify(&mask,sizeof mask); + return mask; +} + +/* input: f, element in GF((2^m)^t) */ +/* output: out, minimal polynomial of f */ +/* return: 0 for success and -1 for failure */ +int genpoly_gen(gf *out, gf *f) +{ + int i, j, k, c; + + gf mat[ SYS_T+1 ][ SYS_T ]; + gf mask, inv, t; + + // fill matrix + + mat[0][0] = 1; + + for (i = 1; i < SYS_T; i++) + mat[0][i] = 0; + + for (i = 0; i < SYS_T; i++) + mat[1][i] = f[i]; + + for (j = 2; j <= SYS_T; j++) + GF_mul(mat[j], mat[j-1], f); + + // gaussian + + for (j = 0; j < SYS_T; j++) + { + for (k = j + 1; k < SYS_T; k++) + { + mask = gf_iszero(mat[ j ][ j ]); + + for (c = j; c < SYS_T + 1; c++) + mat[ c ][ j ] ^= mat[ c ][ k ] & mask; + + } + + if ( gf_is_zero_declassify(mat[ j ][ j ]) ) // return if not systematic + { + return -1; + } + + inv = gf_inv(mat[j][j]); + + for (c = j; c < SYS_T + 1; c++) + mat[ c ][ j ] = gf_mul(mat[ c ][ j ], inv) ; + + for (k = 0; k < SYS_T; k++) + { + if (k != j) + { + t = mat[ j ][ k ]; + + for (c = j; c < SYS_T + 1; c++) + mat[ c ][ k ] ^= gf_mul(mat[ c ][ j ], t); + } + } + } + + for (i = 0; i < SYS_T; i++) + out[i] = mat[ SYS_T ][ i ]; + + return 0; +} + diff --git a/deps/mceliece/kem/mceliece460896f/sk_gen.h b/deps/mceliece/kem/mceliece460896f/sk_gen.h new file mode 100644 index 0000000..e319703 --- /dev/null +++ b/deps/mceliece/kem/mceliece460896f/sk_gen.h @@ -0,0 +1,18 @@ +/* + This file is for secret-key generation +*/ + +#ifndef SK_GEN_H +#define SK_GEN_H +#define genpoly_gen CRYPTO_NAMESPACE(genpoly_gen) +#define perm_check CRYPTO_NAMESPACE(perm_check) + +#include "gf.h" + +#include + +int genpoly_gen(gf *, gf *); +int perm_check(uint32_t *); + +#endif + diff --git a/deps/mceliece/kem/mceliece460896f/subroutines/crypto_declassify.h b/deps/mceliece/kem/mceliece460896f/subroutines/crypto_declassify.h new file mode 100644 index 0000000..8d84209 --- /dev/null +++ b/deps/mceliece/kem/mceliece460896f/subroutines/crypto_declassify.h @@ -0,0 +1,8 @@ +#ifndef crypto_declassify_h +#define crypto_declassify_h + +static void crypto_declassify(void *x,unsigned long long n) +{ +} + +#endif diff --git a/deps/mceliece/kem/mceliece460896f/subroutines/crypto_int16.h b/deps/mceliece/kem/mceliece460896f/subroutines/crypto_int16.h new file mode 100644 index 0000000..72bbf52 --- /dev/null +++ b/deps/mceliece/kem/mceliece460896f/subroutines/crypto_int16.h @@ -0,0 +1,81 @@ +#ifndef crypto_int16_h +#define crypto_int16_h + +#include +typedef int16_t crypto_int16; + +static crypto_int16 crypto_int16_negative_mask(crypto_int16 crypto_int16_x) +{ + return crypto_int16_x >> 15; +} + +static crypto_int16 crypto_int16_nonzero_mask(crypto_int16 crypto_int16_x) +{ + return crypto_int16_negative_mask(crypto_int16_x) | crypto_int16_negative_mask(-crypto_int16_x); +} + +static crypto_int16 crypto_int16_zero_mask(crypto_int16 crypto_int16_x) +{ + return ~crypto_int16_nonzero_mask(crypto_int16_x); +} + +static crypto_int16 crypto_int16_positive_mask(crypto_int16 crypto_int16_x) +{ + crypto_int16 crypto_int16_z = -crypto_int16_x; + crypto_int16_z ^= crypto_int16_x & crypto_int16_z; + return crypto_int16_negative_mask(crypto_int16_z); +} + +static crypto_int16 crypto_int16_unequal_mask(crypto_int16 crypto_int16_x,crypto_int16 crypto_int16_y) +{ + crypto_int16 crypto_int16_xy = crypto_int16_x ^ crypto_int16_y; + return crypto_int16_nonzero_mask(crypto_int16_xy); +} + +static crypto_int16 crypto_int16_equal_mask(crypto_int16 crypto_int16_x,crypto_int16 crypto_int16_y) +{ + return ~crypto_int16_unequal_mask(crypto_int16_x,crypto_int16_y); +} + +static crypto_int16 crypto_int16_smaller_mask(crypto_int16 crypto_int16_x,crypto_int16 crypto_int16_y) +{ + crypto_int16 crypto_int16_xy = crypto_int16_x ^ crypto_int16_y; + crypto_int16 crypto_int16_z = crypto_int16_x - crypto_int16_y; + crypto_int16_z ^= crypto_int16_xy & (crypto_int16_z ^ crypto_int16_x); + return crypto_int16_negative_mask(crypto_int16_z); +} + +static crypto_int16 crypto_int16_min(crypto_int16 crypto_int16_x,crypto_int16 crypto_int16_y) +{ + crypto_int16 crypto_int16_xy = crypto_int16_y ^ crypto_int16_x; + crypto_int16 crypto_int16_z = crypto_int16_y - crypto_int16_x; + crypto_int16_z ^= crypto_int16_xy & (crypto_int16_z ^ crypto_int16_y); + crypto_int16_z = crypto_int16_negative_mask(crypto_int16_z); + crypto_int16_z &= crypto_int16_xy; + return crypto_int16_x ^ crypto_int16_z; +} + +static crypto_int16 crypto_int16_max(crypto_int16 crypto_int16_x,crypto_int16 crypto_int16_y) +{ + crypto_int16 crypto_int16_xy = crypto_int16_y ^ crypto_int16_x; + crypto_int16 crypto_int16_z = crypto_int16_y - crypto_int16_x; + crypto_int16_z ^= crypto_int16_xy & (crypto_int16_z ^ crypto_int16_y); + crypto_int16_z = crypto_int16_negative_mask(crypto_int16_z); + crypto_int16_z &= crypto_int16_xy; + return crypto_int16_y ^ crypto_int16_z; +} + +static void crypto_int16_minmax(crypto_int16 *crypto_int16_a,crypto_int16 *crypto_int16_b) +{ + crypto_int16 crypto_int16_x = *crypto_int16_a; + crypto_int16 crypto_int16_y = *crypto_int16_b; + crypto_int16 crypto_int16_xy = crypto_int16_y ^ crypto_int16_x; + crypto_int16 crypto_int16_z = crypto_int16_y - crypto_int16_x; + crypto_int16_z ^= crypto_int16_xy & (crypto_int16_z ^ crypto_int16_y); + crypto_int16_z = crypto_int16_negative_mask(crypto_int16_z); + crypto_int16_z &= crypto_int16_xy; + *crypto_int16_a = crypto_int16_x ^ crypto_int16_z; + *crypto_int16_b = crypto_int16_y ^ crypto_int16_z; +} + +#endif diff --git a/deps/mceliece/kem/mceliece460896f/subroutines/crypto_int32.h b/deps/mceliece/kem/mceliece460896f/subroutines/crypto_int32.h new file mode 100644 index 0000000..c22f735 --- /dev/null +++ b/deps/mceliece/kem/mceliece460896f/subroutines/crypto_int32.h @@ -0,0 +1,81 @@ +#ifndef crypto_int32_h +#define crypto_int32_h + +#include +typedef int32_t crypto_int32; + +static crypto_int32 crypto_int32_negative_mask(crypto_int32 crypto_int32_x) +{ + return crypto_int32_x >> 31; +} + +static crypto_int32 crypto_int32_nonzero_mask(crypto_int32 crypto_int32_x) +{ + return crypto_int32_negative_mask(crypto_int32_x) | crypto_int32_negative_mask(-crypto_int32_x); +} + +static crypto_int32 crypto_int32_zero_mask(crypto_int32 crypto_int32_x) +{ + return ~crypto_int32_nonzero_mask(crypto_int32_x); +} + +static crypto_int32 crypto_int32_positive_mask(crypto_int32 crypto_int32_x) +{ + crypto_int32 crypto_int32_z = -crypto_int32_x; + crypto_int32_z ^= crypto_int32_x & crypto_int32_z; + return crypto_int32_negative_mask(crypto_int32_z); +} + +static crypto_int32 crypto_int32_unequal_mask(crypto_int32 crypto_int32_x,crypto_int32 crypto_int32_y) +{ + crypto_int32 crypto_int32_xy = crypto_int32_x ^ crypto_int32_y; + return crypto_int32_nonzero_mask(crypto_int32_xy); +} + +static crypto_int32 crypto_int32_equal_mask(crypto_int32 crypto_int32_x,crypto_int32 crypto_int32_y) +{ + return ~crypto_int32_unequal_mask(crypto_int32_x,crypto_int32_y); +} + +static crypto_int32 crypto_int32_smaller_mask(crypto_int32 crypto_int32_x,crypto_int32 crypto_int32_y) +{ + crypto_int32 crypto_int32_xy = crypto_int32_x ^ crypto_int32_y; + crypto_int32 crypto_int32_z = crypto_int32_x - crypto_int32_y; + crypto_int32_z ^= crypto_int32_xy & (crypto_int32_z ^ crypto_int32_x); + return crypto_int32_negative_mask(crypto_int32_z); +} + +static crypto_int32 crypto_int32_min(crypto_int32 crypto_int32_x,crypto_int32 crypto_int32_y) +{ + crypto_int32 crypto_int32_xy = crypto_int32_y ^ crypto_int32_x; + crypto_int32 crypto_int32_z = crypto_int32_y - crypto_int32_x; + crypto_int32_z ^= crypto_int32_xy & (crypto_int32_z ^ crypto_int32_y); + crypto_int32_z = crypto_int32_negative_mask(crypto_int32_z); + crypto_int32_z &= crypto_int32_xy; + return crypto_int32_x ^ crypto_int32_z; +} + +static crypto_int32 crypto_int32_max(crypto_int32 crypto_int32_x,crypto_int32 crypto_int32_y) +{ + crypto_int32 crypto_int32_xy = crypto_int32_y ^ crypto_int32_x; + crypto_int32 crypto_int32_z = crypto_int32_y - crypto_int32_x; + crypto_int32_z ^= crypto_int32_xy & (crypto_int32_z ^ crypto_int32_y); + crypto_int32_z = crypto_int32_negative_mask(crypto_int32_z); + crypto_int32_z &= crypto_int32_xy; + return crypto_int32_y ^ crypto_int32_z; +} + +static void crypto_int32_minmax(crypto_int32 *crypto_int32_a,crypto_int32 *crypto_int32_b) +{ + crypto_int32 crypto_int32_x = *crypto_int32_a; + crypto_int32 crypto_int32_y = *crypto_int32_b; + crypto_int32 crypto_int32_xy = crypto_int32_y ^ crypto_int32_x; + crypto_int32 crypto_int32_z = crypto_int32_y - crypto_int32_x; + crypto_int32_z ^= crypto_int32_xy & (crypto_int32_z ^ crypto_int32_y); + crypto_int32_z = crypto_int32_negative_mask(crypto_int32_z); + crypto_int32_z &= crypto_int32_xy; + *crypto_int32_a = crypto_int32_x ^ crypto_int32_z; + *crypto_int32_b = crypto_int32_y ^ crypto_int32_z; +} + +#endif diff --git a/deps/mceliece/kem/mceliece460896f/subroutines/crypto_uint16.h b/deps/mceliece/kem/mceliece460896f/subroutines/crypto_uint16.h new file mode 100644 index 0000000..f0ebbbf --- /dev/null +++ b/deps/mceliece/kem/mceliece460896f/subroutines/crypto_uint16.h @@ -0,0 +1,76 @@ +#ifndef crypto_uint16_h +#define crypto_uint16_h + +#include +typedef uint16_t crypto_uint16; + +typedef int16_t crypto_uint16_signed; + +static crypto_uint16_signed crypto_uint16_signed_negative_mask(crypto_uint16_signed crypto_uint16_signed_x) +{ + return crypto_uint16_signed_x >> 15; +} + +static crypto_uint16 crypto_uint16_nonzero_mask(crypto_uint16 crypto_uint16_x) +{ + return crypto_uint16_signed_negative_mask(crypto_uint16_x) | crypto_uint16_signed_negative_mask(-crypto_uint16_x); +} + +static crypto_uint16 crypto_uint16_zero_mask(crypto_uint16 crypto_uint16_x) +{ + return ~crypto_uint16_nonzero_mask(crypto_uint16_x); +} + +static crypto_uint16 crypto_uint16_unequal_mask(crypto_uint16 crypto_uint16_x,crypto_uint16 crypto_uint16_y) +{ + crypto_uint16 crypto_uint16_xy = crypto_uint16_x ^ crypto_uint16_y; + return crypto_uint16_nonzero_mask(crypto_uint16_xy); +} + +static crypto_uint16 crypto_uint16_equal_mask(crypto_uint16 crypto_uint16_x,crypto_uint16 crypto_uint16_y) +{ + return ~crypto_uint16_unequal_mask(crypto_uint16_x,crypto_uint16_y); +} + +static crypto_uint16 crypto_uint16_smaller_mask(crypto_uint16 crypto_uint16_x,crypto_uint16 crypto_uint16_y) +{ + crypto_uint16 crypto_uint16_xy = crypto_uint16_x ^ crypto_uint16_y; + crypto_uint16 crypto_uint16_z = crypto_uint16_x - crypto_uint16_y; + crypto_uint16_z ^= crypto_uint16_xy & (crypto_uint16_z ^ crypto_uint16_x ^ (((crypto_uint16) 1) << 15)); + return crypto_uint16_signed_negative_mask(crypto_uint16_z); +} + +static crypto_uint16 crypto_uint16_min(crypto_uint16 crypto_uint16_x,crypto_uint16 crypto_uint16_y) +{ + crypto_uint16 crypto_uint16_xy = crypto_uint16_y ^ crypto_uint16_x; + crypto_uint16 crypto_uint16_z = crypto_uint16_y - crypto_uint16_x; + crypto_uint16_z ^= crypto_uint16_xy & (crypto_uint16_z ^ crypto_uint16_y ^ (((crypto_uint16) 1) << 15)); + crypto_uint16_z = crypto_uint16_signed_negative_mask(crypto_uint16_z); + crypto_uint16_z &= crypto_uint16_xy; + return crypto_uint16_x ^ crypto_uint16_z; +} + +static crypto_uint16 crypto_uint16_max(crypto_uint16 crypto_uint16_x,crypto_uint16 crypto_uint16_y) +{ + crypto_uint16 crypto_uint16_xy = crypto_uint16_y ^ crypto_uint16_x; + crypto_uint16 crypto_uint16_z = crypto_uint16_y - crypto_uint16_x; + crypto_uint16_z ^= crypto_uint16_xy & (crypto_uint16_z ^ crypto_uint16_y ^ (((crypto_uint16) 1) << 15)); + crypto_uint16_z = crypto_uint16_signed_negative_mask(crypto_uint16_z); + crypto_uint16_z &= crypto_uint16_xy; + return crypto_uint16_y ^ crypto_uint16_z; +} + +static void crypto_uint16_minmax(crypto_uint16 *crypto_uint16_a,crypto_uint16 *crypto_uint16_b) +{ + crypto_uint16 crypto_uint16_x = *crypto_uint16_a; + crypto_uint16 crypto_uint16_y = *crypto_uint16_b; + crypto_uint16 crypto_uint16_xy = crypto_uint16_y ^ crypto_uint16_x; + crypto_uint16 crypto_uint16_z = crypto_uint16_y - crypto_uint16_x; + crypto_uint16_z ^= crypto_uint16_xy & (crypto_uint16_z ^ crypto_uint16_y ^ (((crypto_uint16) 1) << 15)); + crypto_uint16_z = crypto_uint16_signed_negative_mask(crypto_uint16_z); + crypto_uint16_z &= crypto_uint16_xy; + *crypto_uint16_a = crypto_uint16_x ^ crypto_uint16_z; + *crypto_uint16_b = crypto_uint16_y ^ crypto_uint16_z; +} + +#endif diff --git a/deps/mceliece/kem/mceliece460896f/subroutines/crypto_uint32.h b/deps/mceliece/kem/mceliece460896f/subroutines/crypto_uint32.h new file mode 100644 index 0000000..3f39d62 --- /dev/null +++ b/deps/mceliece/kem/mceliece460896f/subroutines/crypto_uint32.h @@ -0,0 +1,76 @@ +#ifndef crypto_uint32_h +#define crypto_uint32_h + +#include +typedef uint32_t crypto_uint32; + +typedef int32_t crypto_uint32_signed; + +static crypto_uint32_signed crypto_uint32_signed_negative_mask(crypto_uint32_signed crypto_uint32_signed_x) +{ + return crypto_uint32_signed_x >> 31; +} + +static crypto_uint32 crypto_uint32_nonzero_mask(crypto_uint32 crypto_uint32_x) +{ + return crypto_uint32_signed_negative_mask(crypto_uint32_x) | crypto_uint32_signed_negative_mask(-crypto_uint32_x); +} + +static crypto_uint32 crypto_uint32_zero_mask(crypto_uint32 crypto_uint32_x) +{ + return ~crypto_uint32_nonzero_mask(crypto_uint32_x); +} + +static crypto_uint32 crypto_uint32_unequal_mask(crypto_uint32 crypto_uint32_x,crypto_uint32 crypto_uint32_y) +{ + crypto_uint32 crypto_uint32_xy = crypto_uint32_x ^ crypto_uint32_y; + return crypto_uint32_nonzero_mask(crypto_uint32_xy); +} + +static crypto_uint32 crypto_uint32_equal_mask(crypto_uint32 crypto_uint32_x,crypto_uint32 crypto_uint32_y) +{ + return ~crypto_uint32_unequal_mask(crypto_uint32_x,crypto_uint32_y); +} + +static crypto_uint32 crypto_uint32_smaller_mask(crypto_uint32 crypto_uint32_x,crypto_uint32 crypto_uint32_y) +{ + crypto_uint32 crypto_uint32_xy = crypto_uint32_x ^ crypto_uint32_y; + crypto_uint32 crypto_uint32_z = crypto_uint32_x - crypto_uint32_y; + crypto_uint32_z ^= crypto_uint32_xy & (crypto_uint32_z ^ crypto_uint32_x ^ (((crypto_uint32) 1) << 31)); + return crypto_uint32_signed_negative_mask(crypto_uint32_z); +} + +static crypto_uint32 crypto_uint32_min(crypto_uint32 crypto_uint32_x,crypto_uint32 crypto_uint32_y) +{ + crypto_uint32 crypto_uint32_xy = crypto_uint32_y ^ crypto_uint32_x; + crypto_uint32 crypto_uint32_z = crypto_uint32_y - crypto_uint32_x; + crypto_uint32_z ^= crypto_uint32_xy & (crypto_uint32_z ^ crypto_uint32_y ^ (((crypto_uint32) 1) << 31)); + crypto_uint32_z = crypto_uint32_signed_negative_mask(crypto_uint32_z); + crypto_uint32_z &= crypto_uint32_xy; + return crypto_uint32_x ^ crypto_uint32_z; +} + +static crypto_uint32 crypto_uint32_max(crypto_uint32 crypto_uint32_x,crypto_uint32 crypto_uint32_y) +{ + crypto_uint32 crypto_uint32_xy = crypto_uint32_y ^ crypto_uint32_x; + crypto_uint32 crypto_uint32_z = crypto_uint32_y - crypto_uint32_x; + crypto_uint32_z ^= crypto_uint32_xy & (crypto_uint32_z ^ crypto_uint32_y ^ (((crypto_uint32) 1) << 31)); + crypto_uint32_z = crypto_uint32_signed_negative_mask(crypto_uint32_z); + crypto_uint32_z &= crypto_uint32_xy; + return crypto_uint32_y ^ crypto_uint32_z; +} + +static void crypto_uint32_minmax(crypto_uint32 *crypto_uint32_a,crypto_uint32 *crypto_uint32_b) +{ + crypto_uint32 crypto_uint32_x = *crypto_uint32_a; + crypto_uint32 crypto_uint32_y = *crypto_uint32_b; + crypto_uint32 crypto_uint32_xy = crypto_uint32_y ^ crypto_uint32_x; + crypto_uint32 crypto_uint32_z = crypto_uint32_y - crypto_uint32_x; + crypto_uint32_z ^= crypto_uint32_xy & (crypto_uint32_z ^ crypto_uint32_y ^ (((crypto_uint32) 1) << 31)); + crypto_uint32_z = crypto_uint32_signed_negative_mask(crypto_uint32_z); + crypto_uint32_z &= crypto_uint32_xy; + *crypto_uint32_a = crypto_uint32_x ^ crypto_uint32_z; + *crypto_uint32_b = crypto_uint32_y ^ crypto_uint32_z; +} + +#endif diff --git a/deps/mceliece/kem/mceliece460896f/subroutines/crypto_uint64.h b/deps/mceliece/kem/mceliece460896f/subroutines/crypto_uint64.h new file mode 100644 index 0000000..42e2be9 --- /dev/null +++ b/deps/mceliece/kem/mceliece460896f/subroutines/crypto_uint64.h @@ -0,0 +1,76 @@ +#ifndef crypto_uint64_h +#define crypto_uint64_h + +#include +typedef uint64_t crypto_uint64; + +typedef int64_t crypto_uint64_signed; + +static crypto_uint64_signed crypto_uint64_signed_negative_mask(crypto_uint64_signed crypto_uint64_signed_x) +{ + return crypto_uint64_signed_x >> 63; +} + +static crypto_uint64 crypto_uint64_nonzero_mask(crypto_uint64 crypto_uint64_x) +{ + return crypto_uint64_signed_negative_mask(crypto_uint64_x) | crypto_uint64_signed_negative_mask(-crypto_uint64_x); +} + +static crypto_uint64 crypto_uint64_zero_mask(crypto_uint64 crypto_uint64_x) +{ + return ~crypto_uint64_nonzero_mask(crypto_uint64_x); +} + +static crypto_uint64 crypto_uint64_unequal_mask(crypto_uint64 crypto_uint64_x,crypto_uint64 crypto_uint64_y) +{ + crypto_uint64 crypto_uint64_xy = crypto_uint64_x ^ crypto_uint64_y; + return crypto_uint64_nonzero_mask(crypto_uint64_xy); +} + +static crypto_uint64 crypto_uint64_equal_mask(crypto_uint64 crypto_uint64_x,crypto_uint64 crypto_uint64_y) +{ + return ~crypto_uint64_unequal_mask(crypto_uint64_x,crypto_uint64_y); +} + +static crypto_uint64 crypto_uint64_smaller_mask(crypto_uint64 crypto_uint64_x,crypto_uint64 crypto_uint64_y) +{ + crypto_uint64 crypto_uint64_xy = crypto_uint64_x ^ crypto_uint64_y; + crypto_uint64 crypto_uint64_z = crypto_uint64_x - crypto_uint64_y; + crypto_uint64_z ^= crypto_uint64_xy & (crypto_uint64_z ^ crypto_uint64_x ^ (((crypto_uint64) 1) << 63)); + return crypto_uint64_signed_negative_mask(crypto_uint64_z); +} + +static crypto_uint64 crypto_uint64_min(crypto_uint64 crypto_uint64_x,crypto_uint64 crypto_uint64_y) +{ + crypto_uint64 crypto_uint64_xy = crypto_uint64_y ^ crypto_uint64_x; + crypto_uint64 crypto_uint64_z = crypto_uint64_y - crypto_uint64_x; + crypto_uint64_z ^= crypto_uint64_xy & (crypto_uint64_z ^ crypto_uint64_y ^ (((crypto_uint64) 1) << 63)); + crypto_uint64_z = crypto_uint64_signed_negative_mask(crypto_uint64_z); + crypto_uint64_z &= crypto_uint64_xy; + return crypto_uint64_x ^ crypto_uint64_z; +} + +static crypto_uint64 crypto_uint64_max(crypto_uint64 crypto_uint64_x,crypto_uint64 crypto_uint64_y) +{ + crypto_uint64 crypto_uint64_xy = crypto_uint64_y ^ crypto_uint64_x; + crypto_uint64 crypto_uint64_z = crypto_uint64_y - crypto_uint64_x; + crypto_uint64_z ^= crypto_uint64_xy & (crypto_uint64_z ^ crypto_uint64_y ^ (((crypto_uint64) 1) << 63)); + crypto_uint64_z = crypto_uint64_signed_negative_mask(crypto_uint64_z); + crypto_uint64_z &= crypto_uint64_xy; + return crypto_uint64_y ^ crypto_uint64_z; +} + +static void crypto_uint64_minmax(crypto_uint64 *crypto_uint64_a,crypto_uint64 *crypto_uint64_b) +{ + crypto_uint64 crypto_uint64_x = *crypto_uint64_a; + crypto_uint64 crypto_uint64_y = *crypto_uint64_b; + crypto_uint64 crypto_uint64_xy = crypto_uint64_y ^ crypto_uint64_x; + crypto_uint64 crypto_uint64_z = crypto_uint64_y - crypto_uint64_x; + crypto_uint64_z ^= crypto_uint64_xy & (crypto_uint64_z ^ crypto_uint64_y ^ (((crypto_uint64) 1) << 63)); + crypto_uint64_z = crypto_uint64_signed_negative_mask(crypto_uint64_z); + crypto_uint64_z &= crypto_uint64_xy; + *crypto_uint64_a = crypto_uint64_x ^ crypto_uint64_z; + *crypto_uint64_b = crypto_uint64_y ^ crypto_uint64_z; +} + +#endif diff --git a/deps/mceliece/kem/mceliece460896f/synd.c b/deps/mceliece/kem/mceliece460896f/synd.c new file mode 100644 index 0000000..c945647 --- /dev/null +++ b/deps/mceliece/kem/mceliece460896f/synd.c @@ -0,0 +1,36 @@ +/* + This file is for syndrome computation +*/ + +#include "synd.h" + +#include "params.h" +#include "root.h" + +#include + +/* input: Goppa polynomial f, support L, received word r */ +/* output: out, the syndrome of length 2t */ +void synd(gf *out, gf *f, gf *L, unsigned char *r) +{ + int i, j; + gf e, e_inv, c; + + for (j = 0; j < 2*SYS_T; j++) + out[j] = 0; + + for (i = 0; i < SYS_N; i++) + { + c = (r[i/8] >> (i%8)) & 1; + + e = eval(f, L[i]); + e_inv = gf_inv(gf_mul(e,e)); + + for (j = 0; j < 2*SYS_T; j++) + { + out[j] = gf_add(out[j], gf_mul(e_inv, c)); + e_inv = gf_mul(e_inv, L[i]); + } + } +} + diff --git a/deps/mceliece/kem/mceliece460896f/synd.h b/deps/mceliece/kem/mceliece460896f/synd.h new file mode 100644 index 0000000..9331406 --- /dev/null +++ b/deps/mceliece/kem/mceliece460896f/synd.h @@ -0,0 +1,14 @@ +/* + This file is for syndrome computation +*/ + +#ifndef SYND_H +#define SYND_H +#define synd CRYPTO_NAMESPACE(synd) + +#include "gf.h" + +void synd(gf *, gf *, gf *, unsigned char *); + +#endif + diff --git a/deps/mceliece/kem/mceliece460896f/transpose.c b/deps/mceliece/kem/mceliece460896f/transpose.c new file mode 100644 index 0000000..0da2bc5 --- /dev/null +++ b/deps/mceliece/kem/mceliece460896f/transpose.c @@ -0,0 +1,43 @@ +/* + This file is for matrix transposition +*/ + +#include "transpose.h" + +#include + +/* input: in, a 64x64 matrix over GF(2) */ +/* output: out, transpose of in */ +void transpose_64x64(uint64_t * out, uint64_t * in) +{ + int i, j, s, d; + + uint64_t x, y; + uint64_t masks[6][2] = { + {0x5555555555555555, 0xAAAAAAAAAAAAAAAA}, + {0x3333333333333333, 0xCCCCCCCCCCCCCCCC}, + {0x0F0F0F0F0F0F0F0F, 0xF0F0F0F0F0F0F0F0}, + {0x00FF00FF00FF00FF, 0xFF00FF00FF00FF00}, + {0x0000FFFF0000FFFF, 0xFFFF0000FFFF0000}, + {0x00000000FFFFFFFF, 0xFFFFFFFF00000000} + }; + + for (i = 0; i < 64; i++) + out[i] = in[i]; + + for (d = 5; d >= 0; d--) + { + s = 1 << d; + + for (i = 0; i < 64; i += s*2) + for (j = i; j < i+s; j++) + { + x = (out[j] & masks[d][0]) | ((out[j+s] & masks[d][0]) << s); + y = ((out[j] & masks[d][1]) >> s) | (out[j+s] & masks[d][1]); + + out[j+0] = x; + out[j+s] = y; + } + } +} + diff --git a/deps/mceliece/kem/mceliece460896f/transpose.h b/deps/mceliece/kem/mceliece460896f/transpose.h new file mode 100644 index 0000000..31e5b96 --- /dev/null +++ b/deps/mceliece/kem/mceliece460896f/transpose.h @@ -0,0 +1,14 @@ +/* + This file is for matrix transposition +*/ + +#ifndef TRANSPOSE_H +#define TRANSPOSE_H +#define transpose_64x64 CRYPTO_NAMESPACE(transpose_64x64) + +#include + +void transpose_64x64(uint64_t *, uint64_t *); + +#endif + diff --git a/deps/mceliece/kem/mceliece460896f/uint64_sort.h b/deps/mceliece/kem/mceliece460896f/uint64_sort.h new file mode 100644 index 0000000..2fb100c --- /dev/null +++ b/deps/mceliece/kem/mceliece460896f/uint64_sort.h @@ -0,0 +1,45 @@ +#ifndef uint64_sort_h +#define uint64_sort_h + +#define int64_sort CRYPTO_NAMESPACE(int64_sort) + +#include + +#define uint64_MINMAX(a,b) \ +do { \ + uint64_t c = b - a; \ + c >>= 63; \ + c = -c; \ + c &= a ^ b; \ + a ^= c; \ + b ^= c; \ +} while(0) + +static void uint64_sort(uint64_t *x,long long n) +{ + long long top,p,q,r,i; + + if (n < 2) return; + top = 1; + while (top < n - top) top += top; + + for (p = top;p > 0;p >>= 1) { + for (i = 0;i < n - p;++i) + if (!(i & p)) + uint64_MINMAX(x[i],x[i+p]); + i = 0; + for (q = top;q > p;q >>= 1) { + for (;i < n - q;++i) { + if (!(i & p)) { + uint64_t a = x[i + p]; + for (r = q;r > p;r >>= 1) + uint64_MINMAX(a,x[i+r]); + x[i + p] = a; + } + } + } + } +} + +#endif + diff --git a/deps/mceliece/kem/mceliece460896f/util.c b/deps/mceliece/kem/mceliece460896f/util.c new file mode 100644 index 0000000..1679168 --- /dev/null +++ b/deps/mceliece/kem/mceliece460896f/util.c @@ -0,0 +1,75 @@ +/* + This file is for loading/storing data in a little-endian fashion +*/ + +#include "util.h" + +#include "params.h" + +void store_gf(unsigned char *dest, gf a) +{ + dest[0] = a & 0xFF; + dest[1] = a >> 8; +} + +uint16_t load_gf(const unsigned char *src) +{ + uint16_t a; + + a = src[1]; + a <<= 8; + a |= src[0]; + + return a & GFMASK; +} + +uint32_t load4(const unsigned char * in) +{ + int i; + uint32_t ret = in[3]; + + for (i = 2; i >= 0; i--) + { + ret <<= 8; + ret |= in[i]; + } + + return ret; +} + +void store8(unsigned char *out, uint64_t in) +{ + out[0] = (in >> 0x00) & 0xFF; + out[1] = (in >> 0x08) & 0xFF; + out[2] = (in >> 0x10) & 0xFF; + out[3] = (in >> 0x18) & 0xFF; + out[4] = (in >> 0x20) & 0xFF; + out[5] = (in >> 0x28) & 0xFF; + out[6] = (in >> 0x30) & 0xFF; + out[7] = (in >> 0x38) & 0xFF; +} + +uint64_t load8(const unsigned char * in) +{ + int i; + uint64_t ret = in[7]; + + for (i = 6; i >= 0; i--) + { + ret <<= 8; + ret |= in[i]; + } + + return ret; +} + +gf bitrev(gf a) +{ + a = ((a & 0x00FF) << 8) | ((a & 0xFF00) >> 8); + a = ((a & 0x0F0F) << 4) | ((a & 0xF0F0) >> 4); + a = ((a & 0x3333) << 2) | ((a & 0xCCCC) >> 2); + a = ((a & 0x5555) << 1) | ((a & 0xAAAA) >> 1); + + return a >> 3; +} + diff --git a/deps/mceliece/kem/mceliece460896f/util.h b/deps/mceliece/kem/mceliece460896f/util.h new file mode 100644 index 0000000..d610bee --- /dev/null +++ b/deps/mceliece/kem/mceliece460896f/util.h @@ -0,0 +1,27 @@ +/* + This file is for loading/storing data in a little-endian fashion +*/ + +#ifndef UTIL_H +#define UTIL_H +#define bitrev CRYPTO_NAMESPACE(bitrev) +#define load4 CRYPTO_NAMESPACE(load4) +#define load8 CRYPTO_NAMESPACE(load8) +#define load_gf CRYPTO_NAMESPACE(load_gf) +#define store8 CRYPTO_NAMESPACE(store8) +#define store_gf CRYPTO_NAMESPACE(store_gf) + +#include "gf.h" +#include + +void store_gf(unsigned char *, gf); +uint16_t load_gf(const unsigned char *); +uint32_t load4(const unsigned char *); + +void store8(unsigned char *, uint64_t ); +uint64_t load8(const unsigned char *); + +gf bitrev(gf); + +#endif + diff --git a/deps/mceliece/kem/mceliece6688128/benes.c b/deps/mceliece/kem/mceliece6688128/benes.c new file mode 100644 index 0000000..3b4e710 --- /dev/null +++ b/deps/mceliece/kem/mceliece6688128/benes.c @@ -0,0 +1,181 @@ +/* + This file is for Benes network related functions + + For the implementation strategy, see + https://eprint.iacr.org/2017/793.pdf +*/ + +#include "util.h" +#include "transpose.h" +#include "params.h" +#include "benes.h" + +/* middle layers of the benes network */ +static void layer_in(uint64_t data[2][64], uint64_t * bits, int lgs) +{ + int i, j, s; + + uint64_t d; + + s = 1 << lgs; + + for (i = 0; i < 64; i += s*2) + for (j = i; j < i+s; j++) + { + + d = (data[0][j+0] ^ data[0][j+s]); + d &= (*bits++); + data[0][j+0] ^= d; + data[0][j+s] ^= d; + + d = (data[1][j+0] ^ data[1][j+s]); + d &= (*bits++); + data[1][j+0] ^= d; + data[1][j+s] ^= d; + } +} + +/* first and last layers of the benes network */ +static void layer_ex(uint64_t * data, uint64_t * bits, int lgs) +{ + int i, j, s; + + uint64_t d; + + s = 1 << lgs; + + for (i = 0; i < 128; i += s*2) + for (j = i; j < i+s; j++) + { + + d = (data[j+0] ^ data[j+s]); + d &= (*bits++); + data[j+0] ^= d; + data[j+s] ^= d; + } +} + +/* input: r, sequence of bits to be permuted */ +/* bits, condition bits of the Benes network */ +/* rev, 0 for normal application; !0 for inverse */ +/* output: r, permuted bits */ +void apply_benes(unsigned char * r, const unsigned char * bits, int rev) +{ + int i, iter, inc; + + unsigned char *r_ptr = r; + const unsigned char *bits_ptr; + + uint64_t r_int_v[2][64]; + uint64_t r_int_h[2][64]; + uint64_t b_int_v[64]; + uint64_t b_int_h[64]; + + // + + if (rev) { bits_ptr = bits + 12288; inc = -1024; } + else { bits_ptr = bits; inc = 0; } + + for (i = 0; i < 64; i++) + { + r_int_v[0][i] = load8(r_ptr + i*16 + 0); + r_int_v[1][i] = load8(r_ptr + i*16 + 8); + } + + transpose_64x64(r_int_h[0], r_int_v[0]); + transpose_64x64(r_int_h[1], r_int_v[1]); + + for (iter = 0; iter <= 6; iter++) + { + for (i = 0; i < 64; i++) + { + b_int_v[i] = load8(bits_ptr); bits_ptr += 8; + } + + bits_ptr += inc; + + transpose_64x64(b_int_h, b_int_v); + + layer_ex(r_int_h[0], b_int_h, iter); + } + + transpose_64x64(r_int_v[0], r_int_h[0]); + transpose_64x64(r_int_v[1], r_int_h[1]); + + for (iter = 0; iter <= 5; iter++) + { + for (i = 0; i < 64; i++) { b_int_v[i] = load8(bits_ptr); bits_ptr += 8; } + bits_ptr += inc; + + layer_in(r_int_v, b_int_v, iter); + } + + for (iter = 4; iter >= 0; iter--) + { + for (i = 0; i < 64; i++) { b_int_v[i] = load8(bits_ptr); bits_ptr += 8; } + bits_ptr += inc; + + layer_in(r_int_v, b_int_v, iter); + } + + transpose_64x64(r_int_h[0], r_int_v[0]); + transpose_64x64(r_int_h[1], r_int_v[1]); + + for (iter = 6; iter >= 0; iter--) + { + for (i = 0; i < 64; i++) + { + b_int_v[i] = load8(bits_ptr); bits_ptr += 8; + } + + bits_ptr += inc; + + transpose_64x64(b_int_h, b_int_v); + + layer_ex(r_int_h[0], b_int_h, iter); + } + + transpose_64x64(r_int_v[0], r_int_h[0]); + transpose_64x64(r_int_v[1], r_int_h[1]); + + for (i = 0; i < 64; i++) + { + store8(r_ptr + i*16 + 0, r_int_v[0][i]); + store8(r_ptr + i*16 + 8, r_int_v[1][i]); + } +} + +/* input: condition bits c */ +/* output: support s */ +void support_gen(gf * s, const unsigned char *c) +{ + gf a; + int i, j; + unsigned char L[ GFBITS ][ (1 << GFBITS)/8 ]; + + for (i = 0; i < GFBITS; i++) + for (j = 0; j < (1 << GFBITS)/8; j++) + L[i][j] = 0; + + for (i = 0; i < (1 << GFBITS); i++) + { + a = bitrev((gf) i); + + for (j = 0; j < GFBITS; j++) + L[j][ i/8 ] |= ((a >> j) & 1) << (i%8); + } + + for (j = 0; j < GFBITS; j++) + apply_benes(L[j], c, 0); + + for (i = 0; i < SYS_N; i++) + { + s[i] = 0; + for (j = GFBITS-1; j >= 0; j--) + { + s[i] <<= 1; + s[i] |= (L[j][i/8] >> (i%8)) & 1; + } + } +} + diff --git a/deps/mceliece/kem/mceliece6688128/benes.h b/deps/mceliece/kem/mceliece6688128/benes.h new file mode 100644 index 0000000..c2ef35a --- /dev/null +++ b/deps/mceliece/kem/mceliece6688128/benes.h @@ -0,0 +1,16 @@ +/* + This file is for Benes network related functions +*/ + +#ifndef BENES_H +#define BENES_H +#define apply_benes CRYPTO_NAMESPACE(apply_benes) +#define support_gen CRYPTO_NAMESPACE(support_gen) + +#include "gf.h" + +void apply_benes(unsigned char *, const unsigned char *, int); +void support_gen(gf *, const unsigned char *); + +#endif + diff --git a/deps/mceliece/kem/mceliece6688128/bm.c b/deps/mceliece/kem/mceliece6688128/bm.c new file mode 100644 index 0000000..056a734 --- /dev/null +++ b/deps/mceliece/kem/mceliece6688128/bm.c @@ -0,0 +1,72 @@ +/* + This file is for the Berlekamp-Massey algorithm + see http://crypto.stanford.edu/~mironov/cs359/massey.pdf +*/ + +#include "params.h" +#include "gf.h" +#include "bm.h" + +#define min(a, b) ((a < b) ? a : b) + +/* the Berlekamp-Massey algorithm */ +/* input: s, sequence of field elements */ +/* output: out, minimal polynomial of s */ +void bm(gf *out, gf *s) +{ + int i; + + uint16_t N = 0; + uint16_t L = 0; + uint16_t mle; + uint16_t mne; + + gf T[ SYS_T+1 ]; + gf C[ SYS_T+1 ]; + gf B[ SYS_T+1 ]; + + gf b = 1, d, f; + + // + + for (i = 0; i < SYS_T+1; i++) + C[i] = B[i] = 0; + + B[1] = C[0] = 1; + + // + + for (N = 0; N < 2 * SYS_T; N++) + { + d = 0; + + for (i = 0; i <= min(N, SYS_T); i++) + d ^= gf_mul(C[i], s[ N-i]); + + mne = d; mne -= 1; mne >>= 15; mne -= 1; + mle = N; mle -= 2*L; mle >>= 15; mle -= 1; + mle &= mne; + + for (i = 0; i <= SYS_T; i++) + T[i] = C[i]; + + f = gf_frac(b, d); + + for (i = 0; i <= SYS_T; i++) + C[i] ^= gf_mul(f, B[i]) & mne; + + L = (L & ~mle) | ((N+1-L) & mle); + + for (i = 0; i <= SYS_T; i++) + B[i] = (B[i] & ~mle) | (T[i] & mle); + + b = (b & ~mle) | (d & mle); + + for (i = SYS_T; i >= 1; i--) B[i] = B[i-1]; + B[0] = 0; + } + + for (i = 0; i <= SYS_T; i++) + out[i] = C[ SYS_T-i ]; +} + diff --git a/deps/mceliece/kem/mceliece6688128/bm.h b/deps/mceliece/kem/mceliece6688128/bm.h new file mode 100644 index 0000000..73d5c6c --- /dev/null +++ b/deps/mceliece/kem/mceliece6688128/bm.h @@ -0,0 +1,13 @@ +/* + This file is for the Berlekamp-Massey algorithm + see http://crypto.stanford.edu/~mironov/cs359/massey.pdf +*/ + +#ifndef BM_H +#define BM_H +#define bm CRYPTO_NAMESPACE(bm) + +void bm(gf *, gf *); + +#endif + diff --git a/deps/mceliece/kem/mceliece6688128/controlbits.c b/deps/mceliece/kem/mceliece6688128/controlbits.c new file mode 100644 index 0000000..db9db9c --- /dev/null +++ b/deps/mceliece/kem/mceliece6688128/controlbits.c @@ -0,0 +1,220 @@ +/* This file is for implementing the Nassimi-Sahni algorithm */ +/* See David Nassimi, Sartaj Sahni "Parallel algorithms to set up the Benes permutationnetwork" */ +/* See also https://cr.yp.to/papers/controlbits-20200923.pdf */ + +#include +#include "crypto_declassify.h" +#include "controlbits.h" +#include "int32_sort.h" +typedef int16_t int16; +typedef int32_t int32; +#include "crypto_int32.h" +#define int32_min crypto_int32_min +#include "crypto_int16.h" + +/* parameters: 1 <= w <= 14; n = 2^w */ +/* input: permutation pi of {0,1,...,n-1} */ +/* output: (2m-1)n/2 control bits at positions pos,pos+step,... */ +/* output position pos is by definition 1&(out[pos/8]>>(pos&7)) */ +/* caller must 0-initialize positions first */ +/* temp must have space for int32[2*n] */ +static void cbrecursion(unsigned char *out,long long pos,long long step,const int16 *pi,long long w,long long n,int32 *temp) +{ +#define A temp +#define B (temp+n) +#define q ((int16 *) (temp+n+n/4)) +/* q can start anywhere between temp+n and temp+n/2 */ + + long long x,i,j,k; + + if (w == 1) { + out[pos>>3] ^= pi[0]<<(pos&7); + return; + } + + for (x = 0;x < n;++x) A[x] = ((pi[x]^1)<<16)|pi[x^1]; + int32_sort(A,n); /* A = (id<<16)+pibar */ + + for (x = 0;x < n;++x) { + int32 Ax = A[x]; + int32 px = Ax&0xffff; + int32 cx = int32_min(px,x); + B[x] = (px<<16)|cx; + } + /* B = (p<<16)+c */ + + for (x = 0;x < n;++x) A[x] = (A[x]<<16)|x; /* A = (pibar<<16)+id */ + int32_sort(A,n); /* A = (id<<16)+pibar^-1 */ + + for (x = 0;x < n;++x) A[x] = (A[x]<<16)+(B[x]>>16); /* A = (pibar^(-1)<<16)+pibar */ + int32_sort(A,n); /* A = (id<<16)+pibar^2 */ + + if (w <= 10) { + for (x = 0;x < n;++x) B[x] = ((A[x]&0xffff)<<10)|(B[x]&0x3ff); + + for (i = 1;i < w-1;++i) { + /* B = (p<<10)+c */ + + for (x = 0;x < n;++x) A[x] = ((B[x]&~0x3ff)<<6)|x; /* A = (p<<16)+id */ + int32_sort(A,n); /* A = (id<<16)+p^{-1} */ + + for (x = 0;x < n;++x) A[x] = (A[x]<<20)|B[x]; /* A = (p^{-1}<<20)+(p<<10)+c */ + int32_sort(A,n); /* A = (id<<20)+(pp<<10)+cp */ + + for (x = 0;x < n;++x) { + int32 ppcpx = A[x]&0xfffff; + int32 ppcx = (A[x]&0xffc00)|(B[x]&0x3ff); + B[x] = int32_min(ppcx,ppcpx); + } + } + for (x = 0;x < n;++x) B[x] &= 0x3ff; + } else { + for (x = 0;x < n;++x) B[x] = (A[x]<<16)|(B[x]&0xffff); + + for (i = 1;i < w-1;++i) { + /* B = (p<<16)+c */ + + for (x = 0;x < n;++x) A[x] = (B[x]&~0xffff)|x; + int32_sort(A,n); /* A = (id<<16)+p^(-1) */ + + for (x = 0;x < n;++x) A[x] = (A[x]<<16)|(B[x]&0xffff); + /* A = p^(-1)<<16+c */ + + if (i < w-2) { + for (x = 0;x < n;++x) B[x] = (A[x]&~0xffff)|(B[x]>>16); + /* B = (p^(-1)<<16)+p */ + int32_sort(B,n); /* B = (id<<16)+p^(-2) */ + for (x = 0;x < n;++x) B[x] = (B[x]<<16)|(A[x]&0xffff); + /* B = (p^(-2)<<16)+c */ + } + + int32_sort(A,n); + /* A = id<<16+cp */ + for (x = 0;x < n;++x) { + int32 cpx = (B[x]&~0xffff)|(A[x]&0xffff); + B[x] = int32_min(B[x],cpx); + } + } + for (x = 0;x < n;++x) B[x] &= 0xffff; + } + + for (x = 0;x < n;++x) A[x] = (((int32)pi[x])<<16)+x; + int32_sort(A,n); /* A = (id<<16)+pi^(-1) */ + + for (j = 0;j < n/2;++j) { + long long x = 2*j; + int32 fj = B[x]&1; /* f[j] */ + int32 Fx = x+fj; /* F[x] */ + int32 Fx1 = Fx^1; /* F[x+1] */ + + out[pos>>3] ^= fj<<(pos&7); + pos += step; + + B[x] = (A[x]<<16)|Fx; + B[x+1] = (A[x+1]<<16)|Fx1; + } + /* B = (pi^(-1)<<16)+F */ + + int32_sort(B,n); /* B = (id<<16)+F(pi) */ + + pos += (2*w-3)*step*(n/2); + + for (k = 0;k < n/2;++k) { + long long y = 2*k; + int32 lk = B[y]&1; /* l[k] */ + int32 Ly = y+lk; /* L[y] */ + int32 Ly1 = Ly^1; /* L[y+1] */ + + out[pos>>3] ^= lk<<(pos&7); + pos += step; + + A[y] = (Ly<<16)|(B[y]&0xffff); + A[y+1] = (Ly1<<16)|(B[y+1]&0xffff); + } + /* A = (L<<16)+F(pi) */ + + int32_sort(A,n); /* A = (id<<16)+F(pi(L)) = (id<<16)+M */ + + pos -= (2*w-2)*step*(n/2); + + for (j = 0;j < n/2;++j) { + q[j] = (A[2*j]&0xffff)>>1; + q[j+n/2] = (A[2*j+1]&0xffff)>>1; + } + + cbrecursion(out,pos,step*2,q,w-1,n/2,temp); + cbrecursion(out,pos+step,step*2,q+n/2,w-1,n/2,temp); +} + +/* input: p, an array of int16 */ +/* input: n, length of p */ +/* input: s, meaning that stride-2^s cswaps are performed */ +/* input: cb, the control bits */ +/* output: the result of apply the control bits to p */ +static void layer(int16_t *p, const unsigned char *cb, int s, int n) +{ + int i, j; + int stride = 1 << s; + int index = 0; + int16_t d, m; + + for (i = 0; i < n; i += stride*2) + { + for (j = 0; j < stride; j++) + { + d = p[ i+j ] ^ p[ i+j+stride ]; + m = (cb[ index >> 3 ] >> (index & 7)) & 1; + m = -m; + d &= m; + p[ i+j ] ^= d; + p[ i+j+stride ] ^= d; + index++; + } + } +} + +/* parameters: 1 <= w <= 14; n = 2^w */ +/* input: permutation pi of {0,1,...,n-1} */ +/* output: (2m-1)n/2 control bits at positions 0,1,... */ +/* output position pos is by definition 1&(out[pos/8]>>(pos&7)) */ +void controlbitsfrompermutation(unsigned char *out,const int16 *pi,long long w,long long n) +{ + int32 temp[2*n]; + int16 pi_test[n], diff; + int i; + unsigned char *ptr; + + while (1) + { + memset(out,0,(((2*w-1)*n/2)+7)/8); + cbrecursion(out,0,1,pi,w,n,temp); + + // check for correctness + + for (i = 0; i < n; i++) + pi_test[i] = i; + + ptr = out; + for (i = 0; i < w; i++) + { + layer(pi_test, ptr, i, n); + ptr += n >> 4; + } + + for (i = w-2; i >= 0; i--) + { + layer(pi_test, ptr, i, n); + ptr += n >> 4; + } + + diff = 0; + for (i = 0; i < n; i++) + diff |= pi[i] ^ pi_test[i]; + + diff = crypto_int16_nonzero_mask(diff); + crypto_declassify(&diff,sizeof diff); + if (diff == 0) + break; + } +} + diff --git a/deps/mceliece/kem/mceliece6688128/controlbits.h b/deps/mceliece/kem/mceliece6688128/controlbits.h new file mode 100644 index 0000000..8ddd210 --- /dev/null +++ b/deps/mceliece/kem/mceliece6688128/controlbits.h @@ -0,0 +1,14 @@ +/* This file is for implementing the Nassimi-Sahni algorithm */ +/* See David Nassimi, Sartaj Sahni "Parallel algorithms to set up the Benes permutationnetwork" */ +/* See also https://cr.yp.to/papers/controlbits-20200923.pdf */ + +#ifndef CONTROLBITS_H +#define CONTROLBITS_H + +#define controlbitsfrompermutation CRYPTO_NAMESPACE(controlbitsfrompermutation) + +#include + +extern void controlbitsfrompermutation(unsigned char *,const int16_t *,long long,long long); + +#endif diff --git a/deps/mceliece/kem/mceliece6688128/crypto_hash.h b/deps/mceliece/kem/mceliece6688128/crypto_hash.h new file mode 100644 index 0000000..b7c1086 --- /dev/null +++ b/deps/mceliece/kem/mceliece6688128/crypto_hash.h @@ -0,0 +1,10 @@ +/* This file uses SHAKE256 implemented in the Keccak Code Package */ + +#include "../../mceliece_externals.h" + +#define crypto_hash_32b(out,in,inlen) \ + SHAKE256(out,32,in,inlen) + +#define shake(out,outlen,in,inlen) \ + SHAKE256(out,outlen,in,inlen) + diff --git a/deps/mceliece/kem/mceliece6688128/crypto_kem.h b/deps/mceliece/kem/mceliece6688128/crypto_kem.h new file mode 100644 index 0000000..48320a5 --- /dev/null +++ b/deps/mceliece/kem/mceliece6688128/crypto_kem.h @@ -0,0 +1,15 @@ +#ifndef crypto_kem_H +#define crypto_kem_H + +#include "crypto_kem_mceliece6688128.h" + +#define crypto_kem_keypair crypto_kem_mceliece6688128_keypair +#define crypto_kem_enc crypto_kem_mceliece6688128_enc +#define crypto_kem_dec crypto_kem_mceliece6688128_dec +#define crypto_kem_PUBLICKEYBYTES crypto_kem_mceliece6688128_PUBLICKEYBYTES +#define crypto_kem_SECRETKEYBYTES crypto_kem_mceliece6688128_SECRETKEYBYTES +#define crypto_kem_BYTES crypto_kem_mceliece6688128_BYTES +#define crypto_kem_CIPHERTEXTBYTES crypto_kem_mceliece6688128_CIPHERTEXTBYTES +#define crypto_kem_PRIMITIVE "mceliece6688128" + +#endif diff --git a/deps/mceliece/kem/mceliece6688128/crypto_kem_mceliece6688128.h b/deps/mceliece/kem/mceliece6688128/crypto_kem_mceliece6688128.h new file mode 100644 index 0000000..75fae0d --- /dev/null +++ b/deps/mceliece/kem/mceliece6688128/crypto_kem_mceliece6688128.h @@ -0,0 +1,28 @@ +#ifndef crypto_kem_mceliece6688128_H +#define crypto_kem_mceliece6688128_H + +#define crypto_kem_mceliece6688128_ref_PUBLICKEYBYTES 1044992 +#define crypto_kem_mceliece6688128_ref_SECRETKEYBYTES 13932 +#define crypto_kem_mceliece6688128_ref_CIPHERTEXTBYTES 208 +#define crypto_kem_mceliece6688128_ref_BYTES 32 + + +#ifdef __cplusplus +extern "C" { +#endif +extern int crypto_kem_mceliece6688128_ref_keypair(unsigned char *,unsigned char *); +extern int crypto_kem_mceliece6688128_ref_enc(unsigned char *,unsigned char *,const unsigned char *); +extern int crypto_kem_mceliece6688128_ref_dec(unsigned char *,const unsigned char *,const unsigned char *); +#ifdef __cplusplus +} +#endif + +#define crypto_kem_mceliece6688128_keypair crypto_kem_mceliece6688128_ref_keypair +#define crypto_kem_mceliece6688128_enc crypto_kem_mceliece6688128_ref_enc +#define crypto_kem_mceliece6688128_dec crypto_kem_mceliece6688128_ref_dec +#define crypto_kem_mceliece6688128_PUBLICKEYBYTES crypto_kem_mceliece6688128_ref_PUBLICKEYBYTES +#define crypto_kem_mceliece6688128_SECRETKEYBYTES crypto_kem_mceliece6688128_ref_SECRETKEYBYTES +#define crypto_kem_mceliece6688128_BYTES crypto_kem_mceliece6688128_ref_BYTES +#define crypto_kem_mceliece6688128_CIPHERTEXTBYTES crypto_kem_mceliece6688128_ref_CIPHERTEXTBYTES + +#endif diff --git a/deps/mceliece/kem/mceliece6688128/decrypt.c b/deps/mceliece/kem/mceliece6688128/decrypt.c new file mode 100644 index 0000000..c4cc6de --- /dev/null +++ b/deps/mceliece/kem/mceliece6688128/decrypt.c @@ -0,0 +1,93 @@ +/* + This file is for Niederreiter decryption +*/ + +#include +#include "decrypt.h" + +#include "params.h" +#include "benes.h" +#include "util.h" +#include "synd.h" +#include "root.h" +#include "gf.h" +#include "bm.h" + +/* Niederreiter decryption with the Berlekamp decoder */ +/* intput: sk, secret key */ +/* c, ciphertext */ +/* output: e, error vector */ +/* return: 0 for success; 1 for failure */ +int decrypt(unsigned char *e, const unsigned char *sk, const unsigned char *c) +{ + int i, w = 0; + uint16_t check; + + unsigned char r[ SYS_N/8 ]; + + gf g[ SYS_T+1 ]; + gf L[ SYS_N ]; + + gf s[ SYS_T*2 ]; + gf s_cmp[ SYS_T*2 ]; + gf locator[ SYS_T+1 ]; + gf images[ SYS_N ]; + + gf t; + + // + + for (i = 0; i < SYND_BYTES; i++) r[i] = c[i]; + for (i = SYND_BYTES; i < SYS_N/8; i++) r[i] = 0; + + for (i = 0; i < SYS_T; i++) { g[i] = load_gf(sk); sk += 2; } g[ SYS_T ] = 1; + + support_gen(L, sk); + + synd(s, g, L, r); + + bm(locator, s); + + root(images, locator, L); + + // + + for (i = 0; i < SYS_N/8; i++) + e[i] = 0; + + for (i = 0; i < SYS_N; i++) + { + t = gf_iszero(images[i]) & 1; + + e[ i/8 ] |= t << (i%8); + w += t; + + } + +#ifdef KAT + { + int k; + printf("decrypt e: positions"); + for (k = 0;k < SYS_N;++k) + if (e[k/8] & (1 << (k&7))) + printf(" %d",k); + printf("\n"); + } +#endif + + synd(s_cmp, g, L, e); + + // + + check = w; + check ^= SYS_T; + + for (i = 0; i < SYS_T*2; i++) + check |= s[i] ^ s_cmp[i]; + + check -= 1; + check >>= 15; + + return check ^ 1; +} + diff --git a/deps/mceliece/kem/mceliece6688128/decrypt.h b/deps/mceliece/kem/mceliece6688128/decrypt.h new file mode 100644 index 0000000..266a5cd --- /dev/null +++ b/deps/mceliece/kem/mceliece6688128/decrypt.h @@ -0,0 +1,12 @@ +/* + This file is for Nieddereiter decryption +*/ + +#ifndef DECRYPT_H +#define DECRYPT_H +#define decrypt CRYPTO_NAMESPACE(decrypt) + +int decrypt(unsigned char *, const unsigned char *, const unsigned char *); + +#endif + diff --git a/deps/mceliece/kem/mceliece6688128/encrypt.c b/deps/mceliece/kem/mceliece6688128/encrypt.c new file mode 100644 index 0000000..4823d2f --- /dev/null +++ b/deps/mceliece/kem/mceliece6688128/encrypt.c @@ -0,0 +1,161 @@ +/* + This file is for Niederreiter encryption +*/ + +#include "encrypt.h" + +#include "util.h" +#include "params.h" +#include "randombytes.h" + +#include +#include +#include +#include + +#include "gf.h" +#include "crypto_declassify.h" +#include "crypto_uint16.h" +#include "crypto_uint32.h" + +static inline crypto_uint16 uint16_is_smaller_declassify(uint16_t t,uint16_t u) +{ + crypto_uint16 mask = crypto_uint16_smaller_mask(t,u); + crypto_declassify(&mask,sizeof mask); + return mask; +} + +static inline crypto_uint32 uint32_is_equal_declassify(uint32_t t,uint32_t u) +{ + crypto_uint32 mask = crypto_uint32_equal_mask(t,u); + crypto_declassify(&mask,sizeof mask); + return mask; +} + +static inline unsigned char same_mask(uint16_t x, uint16_t y) +{ + uint32_t mask; + + mask = x ^ y; + mask -= 1; + mask >>= 31; + mask = -mask; + + return mask & 0xFF; +} + +/* output: e, an error vector of weight t */ +static void gen_e(unsigned char *e) +{ + int i, j, eq, count; + + union + { + uint16_t nums[ SYS_T*2 ]; + unsigned char bytes[ SYS_T*2 * sizeof(uint16_t) ]; + } buf; + + uint16_t ind[ SYS_T ]; + unsigned char mask; + unsigned char val[ SYS_T ]; + + while (1) + { + randombytes(buf.bytes, sizeof(buf)); + + for (i = 0; i < SYS_T*2; i++) + buf.nums[i] = load_gf(buf.bytes + i*2); + + // moving and counting indices in the correct range + + count = 0; + for (i = 0; i < SYS_T*2 && count < SYS_T; i++) + if (uint16_is_smaller_declassify(buf.nums[i],SYS_N)) + ind[ count++ ] = buf.nums[i]; + + if (count < SYS_T) continue; + + // check for repetition + + eq = 0; + + for (i = 1; i < SYS_T; i++) + for (j = 0; j < i; j++) + if (uint32_is_equal_declassify(ind[i],ind[j])) + eq = 1; + + if (eq == 0) + break; + } + + for (j = 0; j < SYS_T; j++) + val[j] = 1 << (ind[j] & 7); + + for (i = 0; i < SYS_N/8; i++) + { + e[i] = 0; + + for (j = 0; j < SYS_T; j++) + { + mask = same_mask(i, (ind[j] >> 3)); + + e[i] |= val[j] & mask; + } + } +} + +/* input: public key pk, error vector e */ +/* output: syndrome s */ +static void syndrome(unsigned char *s, const unsigned char *pk, unsigned char *e) +{ + unsigned char b, row[SYS_N/8]; + const unsigned char *pk_ptr = pk; + + int i, j; + + for (i = 0; i < SYND_BYTES; i++) + s[i] = 0; + + for (i = 0; i < PK_NROWS; i++) + { + for (j = 0; j < SYS_N/8; j++) + row[j] = 0; + + for (j = 0; j < PK_ROW_BYTES; j++) + row[ SYS_N/8 - PK_ROW_BYTES + j ] = pk_ptr[j]; + + row[i/8] |= 1 << (i%8); + + b = 0; + for (j = 0; j < SYS_N/8; j++) + b ^= row[j] & e[j]; + + b ^= b >> 4; + b ^= b >> 2; + b ^= b >> 1; + b &= 1; + + s[ i/8 ] |= (b << (i%8)); + + pk_ptr += PK_ROW_BYTES; + } +} + +void encrypt(unsigned char *s, const unsigned char *pk, unsigned char *e) +{ + gen_e(e); + +#ifdef KAT + { + int k; + printf("encrypt e: positions"); + for (k = 0;k < SYS_N;++k) + if (e[k/8] & (1 << (k&7))) + printf(" %d",k); + printf("\n"); + } +#endif + + syndrome(s, pk, e); +} + diff --git a/deps/mceliece/kem/mceliece6688128/encrypt.h b/deps/mceliece/kem/mceliece6688128/encrypt.h new file mode 100644 index 0000000..8edd7a6 --- /dev/null +++ b/deps/mceliece/kem/mceliece6688128/encrypt.h @@ -0,0 +1,12 @@ +/* + This file is for Niederreiter encryption +*/ + +#ifndef ENCRYPT_H +#define ENCRYPT_H +#define encrypt CRYPTO_NAMESPACE(encrypt) + +void encrypt(unsigned char *, const unsigned char *, unsigned char *); + +#endif + diff --git a/deps/mceliece/kem/mceliece6688128/gf.c b/deps/mceliece/kem/mceliece6688128/gf.c new file mode 100644 index 0000000..159a286 --- /dev/null +++ b/deps/mceliece/kem/mceliece6688128/gf.c @@ -0,0 +1,215 @@ +/* + This file is for functions for field arithmetic +*/ + +#include "gf.h" + +#include "params.h" + +gf gf_iszero(gf a) +{ + uint32_t t = a; + + t -= 1; + t >>= 19; + + return (gf) t; +} + +gf gf_add(gf in0, gf in1) +{ + return in0 ^ in1; +} + +gf gf_mul(gf in0, gf in1) +{ + int i; + + uint64_t tmp; + uint64_t t0; + uint64_t t1; + uint64_t t; + + t0 = in0; + t1 = in1; + + tmp = t0 * (t1 & 1); + + for (i = 1; i < GFBITS; i++) + tmp ^= (t0 * (t1 & (1 << i))); + + // + + t = tmp & 0x1FF0000; + tmp ^= (t >> 9) ^ (t >> 10) ^ (t >> 12) ^ (t >> 13); + + t = tmp & 0x000E000; + tmp ^= (t >> 9) ^ (t >> 10) ^ (t >> 12) ^ (t >> 13); + + return tmp & GFMASK; +} + +/* input: field element in */ +/* return: (in^2)^2 */ +static inline gf gf_sq2(gf in) +{ + int i; + + const uint64_t B[] = {0x1111111111111111, + 0x0303030303030303, + 0x000F000F000F000F, + 0x000000FF000000FF}; + + const uint64_t M[] = {0x0001FF0000000000, + 0x000000FF80000000, + 0x000000007FC00000, + 0x00000000003FE000}; + + uint64_t x = in; + uint64_t t; + + x = (x | (x << 24)) & B[3]; + x = (x | (x << 12)) & B[2]; + x = (x | (x << 6)) & B[1]; + x = (x | (x << 3)) & B[0]; + + for (i = 0; i < 4; i++) + { + t = x & M[i]; + x ^= (t >> 9) ^ (t >> 10) ^ (t >> 12) ^ (t >> 13); + } + + return x & GFMASK; +} + +/* input: field element in, m */ +/* return: (in^2)*m */ +static inline gf gf_sqmul(gf in, gf m) +{ + int i; + + uint64_t x; + uint64_t t0; + uint64_t t1; + uint64_t t; + + const uint64_t M[] = {0x0000001FF0000000, + 0x000000000FF80000, + 0x000000000007E000}; + + t0 = in; + t1 = m; + + x = (t1 << 6) * (t0 & (1 << 6)); + + t0 ^= (t0 << 7); + + x ^= (t1 * (t0 & (0x04001))); + x ^= (t1 * (t0 & (0x08002))) << 1; + x ^= (t1 * (t0 & (0x10004))) << 2; + x ^= (t1 * (t0 & (0x20008))) << 3; + x ^= (t1 * (t0 & (0x40010))) << 4; + x ^= (t1 * (t0 & (0x80020))) << 5; + + for (i = 0; i < 3; i++) + { + t = x & M[i]; + x ^= (t >> 9) ^ (t >> 10) ^ (t >> 12) ^ (t >> 13); + } + + return x & GFMASK; +} + +/* input: field element in, m */ +/* return: ((in^2)^2)*m */ +static inline gf gf_sq2mul(gf in, gf m) +{ + int i; + + uint64_t x; + uint64_t t0; + uint64_t t1; + uint64_t t; + + const uint64_t M[] = {0x1FF0000000000000, + 0x000FF80000000000, + 0x000007FC00000000, + 0x00000003FE000000, + 0x0000000001FE0000, + 0x000000000001E000}; + + t0 = in; + t1 = m; + + x = (t1 << 18) * (t0 & (1 << 6)); + + t0 ^= (t0 << 21); + + x ^= (t1 * (t0 & (0x010000001))); + x ^= (t1 * (t0 & (0x020000002))) << 3; + x ^= (t1 * (t0 & (0x040000004))) << 6; + x ^= (t1 * (t0 & (0x080000008))) << 9; + x ^= (t1 * (t0 & (0x100000010))) << 12; + x ^= (t1 * (t0 & (0x200000020))) << 15; + + for (i = 0; i < 6; i++) + { + t = x & M[i]; + x ^= (t >> 9) ^ (t >> 10) ^ (t >> 12) ^ (t >> 13); + } + + return x & GFMASK; +} + +/* input: field element den, num */ +/* return: (num/den) */ +gf gf_frac(gf den, gf num) +{ + gf tmp_11; + gf tmp_1111; + gf out; + + tmp_11 = gf_sqmul(den, den); // ^11 + tmp_1111 = gf_sq2mul(tmp_11, tmp_11); // ^1111 + out = gf_sq2(tmp_1111); + out = gf_sq2mul(out, tmp_1111); // ^11111111 + out = gf_sq2(out); + out = gf_sq2mul(out, tmp_1111); // ^111111111111 + + return gf_sqmul(out, num); // ^1111111111110 = ^-1 +} + +gf gf_inv(gf den) +{ + return gf_frac(den, ((gf) 1)); +} + +/* input: in0, in1 in GF((2^m)^t)*/ +/* output: out = in0*in1 */ +void GF_mul(gf *out, gf *in0, gf *in1) +{ + int i, j; + + gf prod[ SYS_T*2-1 ]; + + for (i = 0; i < SYS_T*2-1; i++) + prod[i] = 0; + + for (i = 0; i < SYS_T; i++) + for (j = 0; j < SYS_T; j++) + prod[i+j] ^= gf_mul(in0[i], in1[j]); + + // + + for (i = (SYS_T-1)*2; i >= SYS_T; i--) + { + prod[i - SYS_T + 7] ^= prod[i]; + prod[i - SYS_T + 2] ^= prod[i]; + prod[i - SYS_T + 1] ^= prod[i]; + prod[i - SYS_T + 0] ^= prod[i]; + } + + for (i = 0; i < SYS_T; i++) + out[i] = prod[i]; +} + diff --git a/deps/mceliece/kem/mceliece6688128/gf.h b/deps/mceliece/kem/mceliece6688128/gf.h new file mode 100644 index 0000000..f62209d --- /dev/null +++ b/deps/mceliece/kem/mceliece6688128/gf.h @@ -0,0 +1,27 @@ +/* + This file is for functions for field arithmetic +*/ + +#ifndef GF_H +#define GF_H +#define gf_add CRYPTO_NAMESPACE(gf_add) +#define gf_frac CRYPTO_NAMESPACE(gf_frac) +#define gf_inv CRYPTO_NAMESPACE(gf_inv) +#define gf_iszero CRYPTO_NAMESPACE(gf_iszero) +#define gf_mul CRYPTO_NAMESPACE(gf_mul) +#define GF_mul CRYPTO_NAMESPACE(GF_mul) + +#include + +typedef uint16_t gf; + +gf gf_iszero(gf); +gf gf_add(gf, gf); +gf gf_mul(gf, gf); +gf gf_frac(gf, gf); +gf gf_inv(gf); + +void GF_mul(gf *, gf *, gf *); + +#endif + diff --git a/deps/mceliece/kem/mceliece6688128/int32_sort.h b/deps/mceliece/kem/mceliece6688128/int32_sort.h new file mode 100644 index 0000000..a431af2 --- /dev/null +++ b/deps/mceliece/kem/mceliece6688128/int32_sort.h @@ -0,0 +1,46 @@ +#ifndef int32_sort_h +#define int32_sort_h + +#define int32_sort CRYPTO_NAMESPACE(int32_sort) + +#include + +#define int32_MINMAX(a,b) \ +do { \ + int32_t ab = b ^ a; \ + int32_t c = b - a; \ + c ^= ab & (c ^ b); \ + c >>= 31; \ + c &= ab; \ + a ^= c; \ + b ^= c; \ +} while(0) + +static void int32_sort(int32_t *x,long long n) +{ + long long top,p,q,r,i; + + if (n < 2) return; + top = 1; + while (top < n - top) top += top; + + for (p = top;p > 0;p >>= 1) { + for (i = 0;i < n - p;++i) + if (!(i & p)) + int32_MINMAX(x[i],x[i+p]); + i = 0; + for (q = top;q > p;q >>= 1) { + for (;i < n - q;++i) { + if (!(i & p)) { + int32_t a = x[i + p]; + for (r = q;r > p;r >>= 1) + int32_MINMAX(a,x[i+r]); + x[i + p] = a; + } + } + } + } +} + +#endif + diff --git a/deps/mceliece/kem/mceliece6688128/operations.c b/deps/mceliece/kem/mceliece6688128/operations.c new file mode 100644 index 0000000..d05e774 --- /dev/null +++ b/deps/mceliece/kem/mceliece6688128/operations.c @@ -0,0 +1,146 @@ +#include "operations.h" + +#include "controlbits.h" +#include "randombytes.h" +#include "crypto_hash.h" +#include "encrypt.h" +#include "decrypt.h" +#include "params.h" +#include "sk_gen.h" +#include "pk_gen.h" +#include "util.h" + +#include +#include + +int crypto_kem_enc( + unsigned char *c, + unsigned char *key, + const unsigned char *pk +) +{ + unsigned char e[ SYS_N/8 ]; + unsigned char one_ec[ 1 + SYS_N/8 + SYND_BYTES ] = {1}; + + // + + encrypt(c, pk, e); + + memcpy(one_ec + 1, e, SYS_N/8); + memcpy(one_ec + 1 + SYS_N/8, c, SYND_BYTES); + + crypto_hash_32b(key, one_ec, sizeof(one_ec)); + + return 0; +} + +int crypto_kem_dec( + unsigned char *key, + const unsigned char *c, + const unsigned char *sk +) +{ + int i; + + unsigned char ret_decrypt = 0; + + uint16_t m; + + unsigned char e[ SYS_N/8 ]; + unsigned char preimage[ 1 + SYS_N/8 + SYND_BYTES ]; + unsigned char *x = preimage; + const unsigned char *s = sk + 40 + IRR_BYTES + COND_BYTES; + + // + + ret_decrypt = decrypt(e, sk + 40, c); + + m = ret_decrypt; + m -= 1; + m >>= 8; + + *x++ = m & 1; + for (i = 0; i < SYS_N/8; i++) + *x++ = (~m & s[i]) | (m & e[i]); + + for (i = 0; i < SYND_BYTES; i++) + *x++ = c[i]; + + crypto_hash_32b(key, preimage, sizeof(preimage)); + + return 0; +} + +int crypto_kem_keypair +( + unsigned char *pk, + unsigned char *sk +) +{ + int i; + unsigned char seed[ 33 ] = {64}; + unsigned char r[ SYS_N/8 + (1 << GFBITS)*sizeof(uint32_t) + SYS_T*2 + 32 ]; + unsigned char *rp, *skp; + + gf f[ SYS_T ]; // element in GF(2^mt) + gf irr[ SYS_T ]; // Goppa polynomial + uint32_t perm[ 1 << GFBITS ]; // random permutation as 32-bit integers + int16_t pi[ 1 << GFBITS ]; // random permutation + + randombytes(seed+1, 32); + + while (1) + { + rp = &r[ sizeof(r)-32 ]; + skp = sk; + + // expanding and updating the seed + + shake(r, sizeof(r), seed, 33); + memcpy(skp, seed+1, 32); + skp += 32 + 8; + memcpy(seed+1, &r[ sizeof(r)-32 ], 32); + + // generating irreducible polynomial + + rp -= sizeof(f); + + for (i = 0; i < SYS_T; i++) + f[i] = load_gf(rp + i*2); + + if (genpoly_gen(irr, f)) + continue; + + for (i = 0; i < SYS_T; i++) + store_gf(skp + i*2, irr[i]); + + skp += IRR_BYTES; + + // generating permutation + + rp -= sizeof(perm); + + for (i = 0; i < (1 << GFBITS); i++) + perm[i] = load4(rp + i*4); + + if (pk_gen(pk, skp - IRR_BYTES, perm, pi)) + continue; + + controlbitsfrompermutation(skp, pi, GFBITS, 1 << GFBITS); + skp += COND_BYTES; + + // storing the random string s + + rp -= SYS_N/8; + memcpy(skp, rp, SYS_N/8); + + // storing positions of the 32 pivots + + store8(sk + 32, 0xFFFFFFFF); + + break; + } + + return 0; +} + diff --git a/deps/mceliece/kem/mceliece6688128/operations.h b/deps/mceliece/kem/mceliece6688128/operations.h new file mode 100644 index 0000000..bf65502 --- /dev/null +++ b/deps/mceliece/kem/mceliece6688128/operations.h @@ -0,0 +1,25 @@ +#ifndef OPERATIONS_H +#define OPERATIONS_H + +#include "crypto_kem.h" + +int crypto_kem_enc( + unsigned char *c, + unsigned char *key, + const unsigned char *pk +); + +int crypto_kem_dec( + unsigned char *key, + const unsigned char *c, + const unsigned char *sk +); + +int crypto_kem_keypair +( + unsigned char *pk, + unsigned char *sk +); + +#endif + diff --git a/deps/mceliece/kem/mceliece6688128/params.h b/deps/mceliece/kem/mceliece6688128/params.h new file mode 100644 index 0000000..147d579 --- /dev/null +++ b/deps/mceliece/kem/mceliece6688128/params.h @@ -0,0 +1,20 @@ +#ifndef PARAMS_H +#define PARAMS_H + +#define GFBITS 13 +#define SYS_N 6688 +#define SYS_T 128 + +#define COND_BYTES ((1 << (GFBITS-4))*(2*GFBITS - 1)) +#define IRR_BYTES (SYS_T * 2) + +#define PK_NROWS (SYS_T*GFBITS) +#define PK_NCOLS (SYS_N - PK_NROWS) +#define PK_ROW_BYTES ((PK_NCOLS + 7)/8) + +#define SYND_BYTES ((PK_NROWS + 7)/8) + +#define GFMASK ((1 << GFBITS) - 1) + +#endif + diff --git a/deps/mceliece/kem/mceliece6688128/pk_gen.c b/deps/mceliece/kem/mceliece6688128/pk_gen.c new file mode 100644 index 0000000..d42ab25 --- /dev/null +++ b/deps/mceliece/kem/mceliece6688128/pk_gen.c @@ -0,0 +1,151 @@ +/* + This file is for public-key generation +*/ + +#include +#include +#include +#include + +#include "controlbits.h" +#include "uint64_sort.h" +#include "pk_gen.h" +#include "params.h" +#include "benes.h" +#include "root.h" +#include "util.h" +#include "crypto_declassify.h" +#include "crypto_uint64.h" + +static crypto_uint64 uint64_is_equal_declassify(uint64_t t,uint64_t u) +{ + crypto_uint64 mask = crypto_uint64_equal_mask(t,u); + crypto_declassify(&mask,sizeof mask); + return mask; +} + +static crypto_uint64 uint64_is_zero_declassify(uint64_t t) +{ + crypto_uint64 mask = crypto_uint64_zero_mask(t); + crypto_declassify(&mask,sizeof mask); + return mask; +} + +/* input: secret key sk */ +/* output: public key pk */ +int pk_gen(unsigned char * pk, unsigned char * sk, uint32_t * perm, int16_t * pi) +{ + int i, j, k; + int row, c; + + uint64_t buf[ 1 << GFBITS ]; + + unsigned char mat[ PK_NROWS ][ SYS_N/8 ]; + unsigned char mask; + unsigned char b; + + gf g[ SYS_T+1 ]; // Goppa polynomial + gf L[ SYS_N ]; // support + gf inv[ SYS_N ]; + + // + + g[ SYS_T ] = 1; + + for (i = 0; i < SYS_T; i++) { g[i] = load_gf(sk); sk += 2; } + + for (i = 0; i < (1 << GFBITS); i++) + { + buf[i] = perm[i]; + buf[i] <<= 31; + buf[i] |= i; + } + + uint64_sort(buf, 1 << GFBITS); + + for (i = 1; i < (1 << GFBITS); i++) + if (uint64_is_equal_declassify(buf[i-1] >> 31,buf[i] >> 31)) + return -1; + + for (i = 0; i < (1 << GFBITS); i++) pi[i] = buf[i] & GFMASK; + for (i = 0; i < SYS_N; i++) L[i] = bitrev(pi[i]); + + // filling the matrix + + root(inv, g, L); + + for (i = 0; i < SYS_N; i++) + inv[i] = gf_inv(inv[i]); + + for (i = 0; i < PK_NROWS; i++) + for (j = 0; j < SYS_N/8; j++) + mat[i][j] = 0; + + for (i = 0; i < SYS_T; i++) + { + for (j = 0; j < SYS_N; j+=8) + for (k = 0; k < GFBITS; k++) + { + b = (inv[j+7] >> k) & 1; b <<= 1; + b |= (inv[j+6] >> k) & 1; b <<= 1; + b |= (inv[j+5] >> k) & 1; b <<= 1; + b |= (inv[j+4] >> k) & 1; b <<= 1; + b |= (inv[j+3] >> k) & 1; b <<= 1; + b |= (inv[j+2] >> k) & 1; b <<= 1; + b |= (inv[j+1] >> k) & 1; b <<= 1; + b |= (inv[j+0] >> k) & 1; + + mat[ i*GFBITS + k ][ j/8 ] = b; + } + + for (j = 0; j < SYS_N; j++) + inv[j] = gf_mul(inv[j], L[j]); + + } + + // gaussian elimination + + for (i = 0; i < (PK_NROWS + 7) / 8; i++) + for (j = 0; j < 8; j++) + { + row = i*8 + j; + + if (row >= PK_NROWS) + break; + + for (k = row + 1; k < PK_NROWS; k++) + { + mask = mat[ row ][ i ] ^ mat[ k ][ i ]; + mask >>= j; + mask &= 1; + mask = -mask; + + for (c = 0; c < SYS_N/8; c++) + mat[ row ][ c ] ^= mat[ k ][ c ] & mask; + } + + if ( uint64_is_zero_declassify((mat[ row ][ i ] >> j) & 1) ) // return if not systematic + { + return -1; + } + + for (k = 0; k < PK_NROWS; k++) + { + if (k != row) + { + mask = mat[ k ][ i ] >> j; + mask &= 1; + mask = -mask; + + for (c = 0; c < SYS_N/8; c++) + mat[ k ][ c ] ^= mat[ row ][ c ] & mask; + } + } + } + + for (i = 0; i < PK_NROWS; i++) + memcpy(pk + i*PK_ROW_BYTES, mat[i] + PK_NROWS/8, PK_ROW_BYTES); + + return 0; +} + diff --git a/deps/mceliece/kem/mceliece6688128/pk_gen.h b/deps/mceliece/kem/mceliece6688128/pk_gen.h new file mode 100644 index 0000000..eec43a7 --- /dev/null +++ b/deps/mceliece/kem/mceliece6688128/pk_gen.h @@ -0,0 +1,14 @@ +/* + This file is for public-key generation +*/ + +#ifndef PK_GEN_H +#define PK_GEN_H +#define pk_gen CRYPTO_NAMESPACE(pk_gen) + +#include "gf.h" + +int pk_gen(unsigned char *, unsigned char *, uint32_t *, int16_t *); + +#endif + diff --git a/deps/mceliece/kem/mceliece6688128/randombytes.h b/deps/mceliece/kem/mceliece6688128/randombytes.h new file mode 100644 index 0000000..7e59351 --- /dev/null +++ b/deps/mceliece/kem/mceliece6688128/randombytes.h @@ -0,0 +1 @@ +#include "../../mceliece_externals.h" diff --git a/deps/mceliece/kem/mceliece6688128/root.c b/deps/mceliece/kem/mceliece6688128/root.c new file mode 100644 index 0000000..1c1b634 --- /dev/null +++ b/deps/mceliece/kem/mceliece6688128/root.c @@ -0,0 +1,38 @@ +/* + This file is for evaluating a polynomial at one or more field elements +*/ + +#include "root.h" +#include "params.h" +#include "gf.h" + +#include + +/* input: polynomial f and field element a */ +/* return f(a) */ +gf eval(gf *f, gf a) +{ + int i; + gf r; + + r = f[ SYS_T ]; + + for (i = SYS_T-1; i >= 0; i--) + { + r = gf_mul(r, a); + r = gf_add(r, f[i]); + } + + return r; +} + +/* input: polynomial f and list of field elements L */ +/* output: out = [ f(a) for a in L ] */ +void root(gf *out, gf *f, gf *L) +{ + int i; + + for (i = 0; i < SYS_N; i++) + out[i] = eval(f, L[i]); +} + diff --git a/deps/mceliece/kem/mceliece6688128/root.h b/deps/mceliece/kem/mceliece6688128/root.h new file mode 100644 index 0000000..42516e4 --- /dev/null +++ b/deps/mceliece/kem/mceliece6688128/root.h @@ -0,0 +1,16 @@ +/* + This file is for evaluating a polynomial at one or more field elements +*/ + +#ifndef ROOT_H +#define ROOT_H +#define eval CRYPTO_NAMESPACE(eval) +#define root CRYPTO_NAMESPACE(root) + +#include "gf.h" + +gf eval(gf *, gf); +void root(gf *, gf *, gf *); + +#endif + diff --git a/deps/mceliece/kem/mceliece6688128/sk_gen.c b/deps/mceliece/kem/mceliece6688128/sk_gen.c new file mode 100644 index 0000000..340cc9a --- /dev/null +++ b/deps/mceliece/kem/mceliece6688128/sk_gen.c @@ -0,0 +1,85 @@ +/* + This file is for secret-key generation +*/ + +#include "sk_gen.h" + +#include "randombytes.h" +#include "controlbits.h" +#include "params.h" +#include "util.h" +#include "gf.h" +#include "crypto_declassify.h" +#include "crypto_uint16.h" + +static inline crypto_uint16 gf_is_zero_declassify(gf t) +{ + crypto_uint16 mask = crypto_uint16_zero_mask(t); + crypto_declassify(&mask,sizeof mask); + return mask; +} + +/* input: f, element in GF((2^m)^t) */ +/* output: out, minimal polynomial of f */ +/* return: 0 for success and -1 for failure */ +int genpoly_gen(gf *out, gf *f) +{ + int i, j, k, c; + + gf mat[ SYS_T+1 ][ SYS_T ]; + gf mask, inv, t; + + // fill matrix + + mat[0][0] = 1; + + for (i = 1; i < SYS_T; i++) + mat[0][i] = 0; + + for (i = 0; i < SYS_T; i++) + mat[1][i] = f[i]; + + for (j = 2; j <= SYS_T; j++) + GF_mul(mat[j], mat[j-1], f); + + // gaussian + + for (j = 0; j < SYS_T; j++) + { + for (k = j + 1; k < SYS_T; k++) + { + mask = gf_iszero(mat[ j ][ j ]); + + for (c = j; c < SYS_T + 1; c++) + mat[ c ][ j ] ^= mat[ c ][ k ] & mask; + + } + + if ( gf_is_zero_declassify(mat[ j ][ j ]) ) // return if not systematic + { + return -1; + } + + inv = gf_inv(mat[j][j]); + + for (c = j; c < SYS_T + 1; c++) + mat[ c ][ j ] = gf_mul(mat[ c ][ j ], inv) ; + + for (k = 0; k < SYS_T; k++) + { + if (k != j) + { + t = mat[ j ][ k ]; + + for (c = j; c < SYS_T + 1; c++) + mat[ c ][ k ] ^= gf_mul(mat[ c ][ j ], t); + } + } + } + + for (i = 0; i < SYS_T; i++) + out[i] = mat[ SYS_T ][ i ]; + + return 0; +} + diff --git a/deps/mceliece/kem/mceliece6688128/sk_gen.h b/deps/mceliece/kem/mceliece6688128/sk_gen.h new file mode 100644 index 0000000..e319703 --- /dev/null +++ b/deps/mceliece/kem/mceliece6688128/sk_gen.h @@ -0,0 +1,18 @@ +/* + This file is for secret-key generation +*/ + +#ifndef SK_GEN_H +#define SK_GEN_H +#define genpoly_gen CRYPTO_NAMESPACE(genpoly_gen) +#define perm_check CRYPTO_NAMESPACE(perm_check) + +#include "gf.h" + +#include + +int genpoly_gen(gf *, gf *); +int perm_check(uint32_t *); + +#endif + diff --git a/deps/mceliece/kem/mceliece6688128/subroutines/crypto_declassify.h b/deps/mceliece/kem/mceliece6688128/subroutines/crypto_declassify.h new file mode 100644 index 0000000..8d84209 --- /dev/null +++ b/deps/mceliece/kem/mceliece6688128/subroutines/crypto_declassify.h @@ -0,0 +1,8 @@ +#ifndef crypto_declassify_h +#define crypto_declassify_h + +static void crypto_declassify(void *x,unsigned long long n) +{ +} + +#endif diff --git a/deps/mceliece/kem/mceliece6688128/subroutines/crypto_int16.h b/deps/mceliece/kem/mceliece6688128/subroutines/crypto_int16.h new file mode 100644 index 0000000..72bbf52 --- /dev/null +++ b/deps/mceliece/kem/mceliece6688128/subroutines/crypto_int16.h @@ -0,0 +1,81 @@ +#ifndef crypto_int16_h +#define crypto_int16_h + +#include +typedef int16_t crypto_int16; + +static crypto_int16 crypto_int16_negative_mask(crypto_int16 crypto_int16_x) +{ + return crypto_int16_x >> 15; +} + +static crypto_int16 crypto_int16_nonzero_mask(crypto_int16 crypto_int16_x) +{ + return crypto_int16_negative_mask(crypto_int16_x) | crypto_int16_negative_mask(-crypto_int16_x); +} + +static crypto_int16 crypto_int16_zero_mask(crypto_int16 crypto_int16_x) +{ + return ~crypto_int16_nonzero_mask(crypto_int16_x); +} + +static crypto_int16 crypto_int16_positive_mask(crypto_int16 crypto_int16_x) +{ + crypto_int16 crypto_int16_z = -crypto_int16_x; + crypto_int16_z ^= crypto_int16_x & crypto_int16_z; + return crypto_int16_negative_mask(crypto_int16_z); +} + +static crypto_int16 crypto_int16_unequal_mask(crypto_int16 crypto_int16_x,crypto_int16 crypto_int16_y) +{ + crypto_int16 crypto_int16_xy = crypto_int16_x ^ crypto_int16_y; + return crypto_int16_nonzero_mask(crypto_int16_xy); +} + +static crypto_int16 crypto_int16_equal_mask(crypto_int16 crypto_int16_x,crypto_int16 crypto_int16_y) +{ + return ~crypto_int16_unequal_mask(crypto_int16_x,crypto_int16_y); +} + +static crypto_int16 crypto_int16_smaller_mask(crypto_int16 crypto_int16_x,crypto_int16 crypto_int16_y) +{ + crypto_int16 crypto_int16_xy = crypto_int16_x ^ crypto_int16_y; + crypto_int16 crypto_int16_z = crypto_int16_x - crypto_int16_y; + crypto_int16_z ^= crypto_int16_xy & (crypto_int16_z ^ crypto_int16_x); + return crypto_int16_negative_mask(crypto_int16_z); +} + +static crypto_int16 crypto_int16_min(crypto_int16 crypto_int16_x,crypto_int16 crypto_int16_y) +{ + crypto_int16 crypto_int16_xy = crypto_int16_y ^ crypto_int16_x; + crypto_int16 crypto_int16_z = crypto_int16_y - crypto_int16_x; + crypto_int16_z ^= crypto_int16_xy & (crypto_int16_z ^ crypto_int16_y); + crypto_int16_z = crypto_int16_negative_mask(crypto_int16_z); + crypto_int16_z &= crypto_int16_xy; + return crypto_int16_x ^ crypto_int16_z; +} + +static crypto_int16 crypto_int16_max(crypto_int16 crypto_int16_x,crypto_int16 crypto_int16_y) +{ + crypto_int16 crypto_int16_xy = crypto_int16_y ^ crypto_int16_x; + crypto_int16 crypto_int16_z = crypto_int16_y - crypto_int16_x; + crypto_int16_z ^= crypto_int16_xy & (crypto_int16_z ^ crypto_int16_y); + crypto_int16_z = crypto_int16_negative_mask(crypto_int16_z); + crypto_int16_z &= crypto_int16_xy; + return crypto_int16_y ^ crypto_int16_z; +} + +static void crypto_int16_minmax(crypto_int16 *crypto_int16_a,crypto_int16 *crypto_int16_b) +{ + crypto_int16 crypto_int16_x = *crypto_int16_a; + crypto_int16 crypto_int16_y = *crypto_int16_b; + crypto_int16 crypto_int16_xy = crypto_int16_y ^ crypto_int16_x; + crypto_int16 crypto_int16_z = crypto_int16_y - crypto_int16_x; + crypto_int16_z ^= crypto_int16_xy & (crypto_int16_z ^ crypto_int16_y); + crypto_int16_z = crypto_int16_negative_mask(crypto_int16_z); + crypto_int16_z &= crypto_int16_xy; + *crypto_int16_a = crypto_int16_x ^ crypto_int16_z; + *crypto_int16_b = crypto_int16_y ^ crypto_int16_z; +} + +#endif diff --git a/deps/mceliece/kem/mceliece6688128/subroutines/crypto_int32.h b/deps/mceliece/kem/mceliece6688128/subroutines/crypto_int32.h new file mode 100644 index 0000000..c22f735 --- /dev/null +++ b/deps/mceliece/kem/mceliece6688128/subroutines/crypto_int32.h @@ -0,0 +1,81 @@ +#ifndef crypto_int32_h +#define crypto_int32_h + +#include +typedef int32_t crypto_int32; + +static crypto_int32 crypto_int32_negative_mask(crypto_int32 crypto_int32_x) +{ + return crypto_int32_x >> 31; +} + +static crypto_int32 crypto_int32_nonzero_mask(crypto_int32 crypto_int32_x) +{ + return crypto_int32_negative_mask(crypto_int32_x) | crypto_int32_negative_mask(-crypto_int32_x); +} + +static crypto_int32 crypto_int32_zero_mask(crypto_int32 crypto_int32_x) +{ + return ~crypto_int32_nonzero_mask(crypto_int32_x); +} + +static crypto_int32 crypto_int32_positive_mask(crypto_int32 crypto_int32_x) +{ + crypto_int32 crypto_int32_z = -crypto_int32_x; + crypto_int32_z ^= crypto_int32_x & crypto_int32_z; + return crypto_int32_negative_mask(crypto_int32_z); +} + +static crypto_int32 crypto_int32_unequal_mask(crypto_int32 crypto_int32_x,crypto_int32 crypto_int32_y) +{ + crypto_int32 crypto_int32_xy = crypto_int32_x ^ crypto_int32_y; + return crypto_int32_nonzero_mask(crypto_int32_xy); +} + +static crypto_int32 crypto_int32_equal_mask(crypto_int32 crypto_int32_x,crypto_int32 crypto_int32_y) +{ + return ~crypto_int32_unequal_mask(crypto_int32_x,crypto_int32_y); +} + +static crypto_int32 crypto_int32_smaller_mask(crypto_int32 crypto_int32_x,crypto_int32 crypto_int32_y) +{ + crypto_int32 crypto_int32_xy = crypto_int32_x ^ crypto_int32_y; + crypto_int32 crypto_int32_z = crypto_int32_x - crypto_int32_y; + crypto_int32_z ^= crypto_int32_xy & (crypto_int32_z ^ crypto_int32_x); + return crypto_int32_negative_mask(crypto_int32_z); +} + +static crypto_int32 crypto_int32_min(crypto_int32 crypto_int32_x,crypto_int32 crypto_int32_y) +{ + crypto_int32 crypto_int32_xy = crypto_int32_y ^ crypto_int32_x; + crypto_int32 crypto_int32_z = crypto_int32_y - crypto_int32_x; + crypto_int32_z ^= crypto_int32_xy & (crypto_int32_z ^ crypto_int32_y); + crypto_int32_z = crypto_int32_negative_mask(crypto_int32_z); + crypto_int32_z &= crypto_int32_xy; + return crypto_int32_x ^ crypto_int32_z; +} + +static crypto_int32 crypto_int32_max(crypto_int32 crypto_int32_x,crypto_int32 crypto_int32_y) +{ + crypto_int32 crypto_int32_xy = crypto_int32_y ^ crypto_int32_x; + crypto_int32 crypto_int32_z = crypto_int32_y - crypto_int32_x; + crypto_int32_z ^= crypto_int32_xy & (crypto_int32_z ^ crypto_int32_y); + crypto_int32_z = crypto_int32_negative_mask(crypto_int32_z); + crypto_int32_z &= crypto_int32_xy; + return crypto_int32_y ^ crypto_int32_z; +} + +static void crypto_int32_minmax(crypto_int32 *crypto_int32_a,crypto_int32 *crypto_int32_b) +{ + crypto_int32 crypto_int32_x = *crypto_int32_a; + crypto_int32 crypto_int32_y = *crypto_int32_b; + crypto_int32 crypto_int32_xy = crypto_int32_y ^ crypto_int32_x; + crypto_int32 crypto_int32_z = crypto_int32_y - crypto_int32_x; + crypto_int32_z ^= crypto_int32_xy & (crypto_int32_z ^ crypto_int32_y); + crypto_int32_z = crypto_int32_negative_mask(crypto_int32_z); + crypto_int32_z &= crypto_int32_xy; + *crypto_int32_a = crypto_int32_x ^ crypto_int32_z; + *crypto_int32_b = crypto_int32_y ^ crypto_int32_z; +} + +#endif diff --git a/deps/mceliece/kem/mceliece6688128/subroutines/crypto_uint16.h b/deps/mceliece/kem/mceliece6688128/subroutines/crypto_uint16.h new file mode 100644 index 0000000..f0ebbbf --- /dev/null +++ b/deps/mceliece/kem/mceliece6688128/subroutines/crypto_uint16.h @@ -0,0 +1,76 @@ +#ifndef crypto_uint16_h +#define crypto_uint16_h + +#include +typedef uint16_t crypto_uint16; + +typedef int16_t crypto_uint16_signed; + +static crypto_uint16_signed crypto_uint16_signed_negative_mask(crypto_uint16_signed crypto_uint16_signed_x) +{ + return crypto_uint16_signed_x >> 15; +} + +static crypto_uint16 crypto_uint16_nonzero_mask(crypto_uint16 crypto_uint16_x) +{ + return crypto_uint16_signed_negative_mask(crypto_uint16_x) | crypto_uint16_signed_negative_mask(-crypto_uint16_x); +} + +static crypto_uint16 crypto_uint16_zero_mask(crypto_uint16 crypto_uint16_x) +{ + return ~crypto_uint16_nonzero_mask(crypto_uint16_x); +} + +static crypto_uint16 crypto_uint16_unequal_mask(crypto_uint16 crypto_uint16_x,crypto_uint16 crypto_uint16_y) +{ + crypto_uint16 crypto_uint16_xy = crypto_uint16_x ^ crypto_uint16_y; + return crypto_uint16_nonzero_mask(crypto_uint16_xy); +} + +static crypto_uint16 crypto_uint16_equal_mask(crypto_uint16 crypto_uint16_x,crypto_uint16 crypto_uint16_y) +{ + return ~crypto_uint16_unequal_mask(crypto_uint16_x,crypto_uint16_y); +} + +static crypto_uint16 crypto_uint16_smaller_mask(crypto_uint16 crypto_uint16_x,crypto_uint16 crypto_uint16_y) +{ + crypto_uint16 crypto_uint16_xy = crypto_uint16_x ^ crypto_uint16_y; + crypto_uint16 crypto_uint16_z = crypto_uint16_x - crypto_uint16_y; + crypto_uint16_z ^= crypto_uint16_xy & (crypto_uint16_z ^ crypto_uint16_x ^ (((crypto_uint16) 1) << 15)); + return crypto_uint16_signed_negative_mask(crypto_uint16_z); +} + +static crypto_uint16 crypto_uint16_min(crypto_uint16 crypto_uint16_x,crypto_uint16 crypto_uint16_y) +{ + crypto_uint16 crypto_uint16_xy = crypto_uint16_y ^ crypto_uint16_x; + crypto_uint16 crypto_uint16_z = crypto_uint16_y - crypto_uint16_x; + crypto_uint16_z ^= crypto_uint16_xy & (crypto_uint16_z ^ crypto_uint16_y ^ (((crypto_uint16) 1) << 15)); + crypto_uint16_z = crypto_uint16_signed_negative_mask(crypto_uint16_z); + crypto_uint16_z &= crypto_uint16_xy; + return crypto_uint16_x ^ crypto_uint16_z; +} + +static crypto_uint16 crypto_uint16_max(crypto_uint16 crypto_uint16_x,crypto_uint16 crypto_uint16_y) +{ + crypto_uint16 crypto_uint16_xy = crypto_uint16_y ^ crypto_uint16_x; + crypto_uint16 crypto_uint16_z = crypto_uint16_y - crypto_uint16_x; + crypto_uint16_z ^= crypto_uint16_xy & (crypto_uint16_z ^ crypto_uint16_y ^ (((crypto_uint16) 1) << 15)); + crypto_uint16_z = crypto_uint16_signed_negative_mask(crypto_uint16_z); + crypto_uint16_z &= crypto_uint16_xy; + return crypto_uint16_y ^ crypto_uint16_z; +} + +static void crypto_uint16_minmax(crypto_uint16 *crypto_uint16_a,crypto_uint16 *crypto_uint16_b) +{ + crypto_uint16 crypto_uint16_x = *crypto_uint16_a; + crypto_uint16 crypto_uint16_y = *crypto_uint16_b; + crypto_uint16 crypto_uint16_xy = crypto_uint16_y ^ crypto_uint16_x; + crypto_uint16 crypto_uint16_z = crypto_uint16_y - crypto_uint16_x; + crypto_uint16_z ^= crypto_uint16_xy & (crypto_uint16_z ^ crypto_uint16_y ^ (((crypto_uint16) 1) << 15)); + crypto_uint16_z = crypto_uint16_signed_negative_mask(crypto_uint16_z); + crypto_uint16_z &= crypto_uint16_xy; + *crypto_uint16_a = crypto_uint16_x ^ crypto_uint16_z; + *crypto_uint16_b = crypto_uint16_y ^ crypto_uint16_z; +} + +#endif diff --git a/deps/mceliece/kem/mceliece6688128/subroutines/crypto_uint32.h b/deps/mceliece/kem/mceliece6688128/subroutines/crypto_uint32.h new file mode 100644 index 0000000..3f39d62 --- /dev/null +++ b/deps/mceliece/kem/mceliece6688128/subroutines/crypto_uint32.h @@ -0,0 +1,76 @@ +#ifndef crypto_uint32_h +#define crypto_uint32_h + +#include +typedef uint32_t crypto_uint32; + +typedef int32_t crypto_uint32_signed; + +static crypto_uint32_signed crypto_uint32_signed_negative_mask(crypto_uint32_signed crypto_uint32_signed_x) +{ + return crypto_uint32_signed_x >> 31; +} + +static crypto_uint32 crypto_uint32_nonzero_mask(crypto_uint32 crypto_uint32_x) +{ + return crypto_uint32_signed_negative_mask(crypto_uint32_x) | crypto_uint32_signed_negative_mask(-crypto_uint32_x); +} + +static crypto_uint32 crypto_uint32_zero_mask(crypto_uint32 crypto_uint32_x) +{ + return ~crypto_uint32_nonzero_mask(crypto_uint32_x); +} + +static crypto_uint32 crypto_uint32_unequal_mask(crypto_uint32 crypto_uint32_x,crypto_uint32 crypto_uint32_y) +{ + crypto_uint32 crypto_uint32_xy = crypto_uint32_x ^ crypto_uint32_y; + return crypto_uint32_nonzero_mask(crypto_uint32_xy); +} + +static crypto_uint32 crypto_uint32_equal_mask(crypto_uint32 crypto_uint32_x,crypto_uint32 crypto_uint32_y) +{ + return ~crypto_uint32_unequal_mask(crypto_uint32_x,crypto_uint32_y); +} + +static crypto_uint32 crypto_uint32_smaller_mask(crypto_uint32 crypto_uint32_x,crypto_uint32 crypto_uint32_y) +{ + crypto_uint32 crypto_uint32_xy = crypto_uint32_x ^ crypto_uint32_y; + crypto_uint32 crypto_uint32_z = crypto_uint32_x - crypto_uint32_y; + crypto_uint32_z ^= crypto_uint32_xy & (crypto_uint32_z ^ crypto_uint32_x ^ (((crypto_uint32) 1) << 31)); + return crypto_uint32_signed_negative_mask(crypto_uint32_z); +} + +static crypto_uint32 crypto_uint32_min(crypto_uint32 crypto_uint32_x,crypto_uint32 crypto_uint32_y) +{ + crypto_uint32 crypto_uint32_xy = crypto_uint32_y ^ crypto_uint32_x; + crypto_uint32 crypto_uint32_z = crypto_uint32_y - crypto_uint32_x; + crypto_uint32_z ^= crypto_uint32_xy & (crypto_uint32_z ^ crypto_uint32_y ^ (((crypto_uint32) 1) << 31)); + crypto_uint32_z = crypto_uint32_signed_negative_mask(crypto_uint32_z); + crypto_uint32_z &= crypto_uint32_xy; + return crypto_uint32_x ^ crypto_uint32_z; +} + +static crypto_uint32 crypto_uint32_max(crypto_uint32 crypto_uint32_x,crypto_uint32 crypto_uint32_y) +{ + crypto_uint32 crypto_uint32_xy = crypto_uint32_y ^ crypto_uint32_x; + crypto_uint32 crypto_uint32_z = crypto_uint32_y - crypto_uint32_x; + crypto_uint32_z ^= crypto_uint32_xy & (crypto_uint32_z ^ crypto_uint32_y ^ (((crypto_uint32) 1) << 31)); + crypto_uint32_z = crypto_uint32_signed_negative_mask(crypto_uint32_z); + crypto_uint32_z &= crypto_uint32_xy; + return crypto_uint32_y ^ crypto_uint32_z; +} + +static void crypto_uint32_minmax(crypto_uint32 *crypto_uint32_a,crypto_uint32 *crypto_uint32_b) +{ + crypto_uint32 crypto_uint32_x = *crypto_uint32_a; + crypto_uint32 crypto_uint32_y = *crypto_uint32_b; + crypto_uint32 crypto_uint32_xy = crypto_uint32_y ^ crypto_uint32_x; + crypto_uint32 crypto_uint32_z = crypto_uint32_y - crypto_uint32_x; + crypto_uint32_z ^= crypto_uint32_xy & (crypto_uint32_z ^ crypto_uint32_y ^ (((crypto_uint32) 1) << 31)); + crypto_uint32_z = crypto_uint32_signed_negative_mask(crypto_uint32_z); + crypto_uint32_z &= crypto_uint32_xy; + *crypto_uint32_a = crypto_uint32_x ^ crypto_uint32_z; + *crypto_uint32_b = crypto_uint32_y ^ crypto_uint32_z; +} + +#endif diff --git a/deps/mceliece/kem/mceliece6688128/subroutines/crypto_uint64.h b/deps/mceliece/kem/mceliece6688128/subroutines/crypto_uint64.h new file mode 100644 index 0000000..42e2be9 --- /dev/null +++ b/deps/mceliece/kem/mceliece6688128/subroutines/crypto_uint64.h @@ -0,0 +1,76 @@ +#ifndef crypto_uint64_h +#define crypto_uint64_h + +#include +typedef uint64_t crypto_uint64; + +typedef int64_t crypto_uint64_signed; + +static crypto_uint64_signed crypto_uint64_signed_negative_mask(crypto_uint64_signed crypto_uint64_signed_x) +{ + return crypto_uint64_signed_x >> 63; +} + +static crypto_uint64 crypto_uint64_nonzero_mask(crypto_uint64 crypto_uint64_x) +{ + return crypto_uint64_signed_negative_mask(crypto_uint64_x) | crypto_uint64_signed_negative_mask(-crypto_uint64_x); +} + +static crypto_uint64 crypto_uint64_zero_mask(crypto_uint64 crypto_uint64_x) +{ + return ~crypto_uint64_nonzero_mask(crypto_uint64_x); +} + +static crypto_uint64 crypto_uint64_unequal_mask(crypto_uint64 crypto_uint64_x,crypto_uint64 crypto_uint64_y) +{ + crypto_uint64 crypto_uint64_xy = crypto_uint64_x ^ crypto_uint64_y; + return crypto_uint64_nonzero_mask(crypto_uint64_xy); +} + +static crypto_uint64 crypto_uint64_equal_mask(crypto_uint64 crypto_uint64_x,crypto_uint64 crypto_uint64_y) +{ + return ~crypto_uint64_unequal_mask(crypto_uint64_x,crypto_uint64_y); +} + +static crypto_uint64 crypto_uint64_smaller_mask(crypto_uint64 crypto_uint64_x,crypto_uint64 crypto_uint64_y) +{ + crypto_uint64 crypto_uint64_xy = crypto_uint64_x ^ crypto_uint64_y; + crypto_uint64 crypto_uint64_z = crypto_uint64_x - crypto_uint64_y; + crypto_uint64_z ^= crypto_uint64_xy & (crypto_uint64_z ^ crypto_uint64_x ^ (((crypto_uint64) 1) << 63)); + return crypto_uint64_signed_negative_mask(crypto_uint64_z); +} + +static crypto_uint64 crypto_uint64_min(crypto_uint64 crypto_uint64_x,crypto_uint64 crypto_uint64_y) +{ + crypto_uint64 crypto_uint64_xy = crypto_uint64_y ^ crypto_uint64_x; + crypto_uint64 crypto_uint64_z = crypto_uint64_y - crypto_uint64_x; + crypto_uint64_z ^= crypto_uint64_xy & (crypto_uint64_z ^ crypto_uint64_y ^ (((crypto_uint64) 1) << 63)); + crypto_uint64_z = crypto_uint64_signed_negative_mask(crypto_uint64_z); + crypto_uint64_z &= crypto_uint64_xy; + return crypto_uint64_x ^ crypto_uint64_z; +} + +static crypto_uint64 crypto_uint64_max(crypto_uint64 crypto_uint64_x,crypto_uint64 crypto_uint64_y) +{ + crypto_uint64 crypto_uint64_xy = crypto_uint64_y ^ crypto_uint64_x; + crypto_uint64 crypto_uint64_z = crypto_uint64_y - crypto_uint64_x; + crypto_uint64_z ^= crypto_uint64_xy & (crypto_uint64_z ^ crypto_uint64_y ^ (((crypto_uint64) 1) << 63)); + crypto_uint64_z = crypto_uint64_signed_negative_mask(crypto_uint64_z); + crypto_uint64_z &= crypto_uint64_xy; + return crypto_uint64_y ^ crypto_uint64_z; +} + +static void crypto_uint64_minmax(crypto_uint64 *crypto_uint64_a,crypto_uint64 *crypto_uint64_b) +{ + crypto_uint64 crypto_uint64_x = *crypto_uint64_a; + crypto_uint64 crypto_uint64_y = *crypto_uint64_b; + crypto_uint64 crypto_uint64_xy = crypto_uint64_y ^ crypto_uint64_x; + crypto_uint64 crypto_uint64_z = crypto_uint64_y - crypto_uint64_x; + crypto_uint64_z ^= crypto_uint64_xy & (crypto_uint64_z ^ crypto_uint64_y ^ (((crypto_uint64) 1) << 63)); + crypto_uint64_z = crypto_uint64_signed_negative_mask(crypto_uint64_z); + crypto_uint64_z &= crypto_uint64_xy; + *crypto_uint64_a = crypto_uint64_x ^ crypto_uint64_z; + *crypto_uint64_b = crypto_uint64_y ^ crypto_uint64_z; +} + +#endif diff --git a/deps/mceliece/kem/mceliece6688128/synd.c b/deps/mceliece/kem/mceliece6688128/synd.c new file mode 100644 index 0000000..c945647 --- /dev/null +++ b/deps/mceliece/kem/mceliece6688128/synd.c @@ -0,0 +1,36 @@ +/* + This file is for syndrome computation +*/ + +#include "synd.h" + +#include "params.h" +#include "root.h" + +#include + +/* input: Goppa polynomial f, support L, received word r */ +/* output: out, the syndrome of length 2t */ +void synd(gf *out, gf *f, gf *L, unsigned char *r) +{ + int i, j; + gf e, e_inv, c; + + for (j = 0; j < 2*SYS_T; j++) + out[j] = 0; + + for (i = 0; i < SYS_N; i++) + { + c = (r[i/8] >> (i%8)) & 1; + + e = eval(f, L[i]); + e_inv = gf_inv(gf_mul(e,e)); + + for (j = 0; j < 2*SYS_T; j++) + { + out[j] = gf_add(out[j], gf_mul(e_inv, c)); + e_inv = gf_mul(e_inv, L[i]); + } + } +} + diff --git a/deps/mceliece/kem/mceliece6688128/synd.h b/deps/mceliece/kem/mceliece6688128/synd.h new file mode 100644 index 0000000..9331406 --- /dev/null +++ b/deps/mceliece/kem/mceliece6688128/synd.h @@ -0,0 +1,14 @@ +/* + This file is for syndrome computation +*/ + +#ifndef SYND_H +#define SYND_H +#define synd CRYPTO_NAMESPACE(synd) + +#include "gf.h" + +void synd(gf *, gf *, gf *, unsigned char *); + +#endif + diff --git a/deps/mceliece/kem/mceliece6688128/transpose.c b/deps/mceliece/kem/mceliece6688128/transpose.c new file mode 100644 index 0000000..0da2bc5 --- /dev/null +++ b/deps/mceliece/kem/mceliece6688128/transpose.c @@ -0,0 +1,43 @@ +/* + This file is for matrix transposition +*/ + +#include "transpose.h" + +#include + +/* input: in, a 64x64 matrix over GF(2) */ +/* output: out, transpose of in */ +void transpose_64x64(uint64_t * out, uint64_t * in) +{ + int i, j, s, d; + + uint64_t x, y; + uint64_t masks[6][2] = { + {0x5555555555555555, 0xAAAAAAAAAAAAAAAA}, + {0x3333333333333333, 0xCCCCCCCCCCCCCCCC}, + {0x0F0F0F0F0F0F0F0F, 0xF0F0F0F0F0F0F0F0}, + {0x00FF00FF00FF00FF, 0xFF00FF00FF00FF00}, + {0x0000FFFF0000FFFF, 0xFFFF0000FFFF0000}, + {0x00000000FFFFFFFF, 0xFFFFFFFF00000000} + }; + + for (i = 0; i < 64; i++) + out[i] = in[i]; + + for (d = 5; d >= 0; d--) + { + s = 1 << d; + + for (i = 0; i < 64; i += s*2) + for (j = i; j < i+s; j++) + { + x = (out[j] & masks[d][0]) | ((out[j+s] & masks[d][0]) << s); + y = ((out[j] & masks[d][1]) >> s) | (out[j+s] & masks[d][1]); + + out[j+0] = x; + out[j+s] = y; + } + } +} + diff --git a/deps/mceliece/kem/mceliece6688128/transpose.h b/deps/mceliece/kem/mceliece6688128/transpose.h new file mode 100644 index 0000000..31e5b96 --- /dev/null +++ b/deps/mceliece/kem/mceliece6688128/transpose.h @@ -0,0 +1,14 @@ +/* + This file is for matrix transposition +*/ + +#ifndef TRANSPOSE_H +#define TRANSPOSE_H +#define transpose_64x64 CRYPTO_NAMESPACE(transpose_64x64) + +#include + +void transpose_64x64(uint64_t *, uint64_t *); + +#endif + diff --git a/deps/mceliece/kem/mceliece6688128/uint64_sort.h b/deps/mceliece/kem/mceliece6688128/uint64_sort.h new file mode 100644 index 0000000..2fb100c --- /dev/null +++ b/deps/mceliece/kem/mceliece6688128/uint64_sort.h @@ -0,0 +1,45 @@ +#ifndef uint64_sort_h +#define uint64_sort_h + +#define int64_sort CRYPTO_NAMESPACE(int64_sort) + +#include + +#define uint64_MINMAX(a,b) \ +do { \ + uint64_t c = b - a; \ + c >>= 63; \ + c = -c; \ + c &= a ^ b; \ + a ^= c; \ + b ^= c; \ +} while(0) + +static void uint64_sort(uint64_t *x,long long n) +{ + long long top,p,q,r,i; + + if (n < 2) return; + top = 1; + while (top < n - top) top += top; + + for (p = top;p > 0;p >>= 1) { + for (i = 0;i < n - p;++i) + if (!(i & p)) + uint64_MINMAX(x[i],x[i+p]); + i = 0; + for (q = top;q > p;q >>= 1) { + for (;i < n - q;++i) { + if (!(i & p)) { + uint64_t a = x[i + p]; + for (r = q;r > p;r >>= 1) + uint64_MINMAX(a,x[i+r]); + x[i + p] = a; + } + } + } + } +} + +#endif + diff --git a/deps/mceliece/kem/mceliece6688128/util.c b/deps/mceliece/kem/mceliece6688128/util.c new file mode 100644 index 0000000..1679168 --- /dev/null +++ b/deps/mceliece/kem/mceliece6688128/util.c @@ -0,0 +1,75 @@ +/* + This file is for loading/storing data in a little-endian fashion +*/ + +#include "util.h" + +#include "params.h" + +void store_gf(unsigned char *dest, gf a) +{ + dest[0] = a & 0xFF; + dest[1] = a >> 8; +} + +uint16_t load_gf(const unsigned char *src) +{ + uint16_t a; + + a = src[1]; + a <<= 8; + a |= src[0]; + + return a & GFMASK; +} + +uint32_t load4(const unsigned char * in) +{ + int i; + uint32_t ret = in[3]; + + for (i = 2; i >= 0; i--) + { + ret <<= 8; + ret |= in[i]; + } + + return ret; +} + +void store8(unsigned char *out, uint64_t in) +{ + out[0] = (in >> 0x00) & 0xFF; + out[1] = (in >> 0x08) & 0xFF; + out[2] = (in >> 0x10) & 0xFF; + out[3] = (in >> 0x18) & 0xFF; + out[4] = (in >> 0x20) & 0xFF; + out[5] = (in >> 0x28) & 0xFF; + out[6] = (in >> 0x30) & 0xFF; + out[7] = (in >> 0x38) & 0xFF; +} + +uint64_t load8(const unsigned char * in) +{ + int i; + uint64_t ret = in[7]; + + for (i = 6; i >= 0; i--) + { + ret <<= 8; + ret |= in[i]; + } + + return ret; +} + +gf bitrev(gf a) +{ + a = ((a & 0x00FF) << 8) | ((a & 0xFF00) >> 8); + a = ((a & 0x0F0F) << 4) | ((a & 0xF0F0) >> 4); + a = ((a & 0x3333) << 2) | ((a & 0xCCCC) >> 2); + a = ((a & 0x5555) << 1) | ((a & 0xAAAA) >> 1); + + return a >> 3; +} + diff --git a/deps/mceliece/kem/mceliece6688128/util.h b/deps/mceliece/kem/mceliece6688128/util.h new file mode 100644 index 0000000..d610bee --- /dev/null +++ b/deps/mceliece/kem/mceliece6688128/util.h @@ -0,0 +1,27 @@ +/* + This file is for loading/storing data in a little-endian fashion +*/ + +#ifndef UTIL_H +#define UTIL_H +#define bitrev CRYPTO_NAMESPACE(bitrev) +#define load4 CRYPTO_NAMESPACE(load4) +#define load8 CRYPTO_NAMESPACE(load8) +#define load_gf CRYPTO_NAMESPACE(load_gf) +#define store8 CRYPTO_NAMESPACE(store8) +#define store_gf CRYPTO_NAMESPACE(store_gf) + +#include "gf.h" +#include + +void store_gf(unsigned char *, gf); +uint16_t load_gf(const unsigned char *); +uint32_t load4(const unsigned char *); + +void store8(unsigned char *, uint64_t ); +uint64_t load8(const unsigned char *); + +gf bitrev(gf); + +#endif + diff --git a/deps/mceliece/kem/mceliece6688128f/benes.c b/deps/mceliece/kem/mceliece6688128f/benes.c new file mode 100644 index 0000000..3b4e710 --- /dev/null +++ b/deps/mceliece/kem/mceliece6688128f/benes.c @@ -0,0 +1,181 @@ +/* + This file is for Benes network related functions + + For the implementation strategy, see + https://eprint.iacr.org/2017/793.pdf +*/ + +#include "util.h" +#include "transpose.h" +#include "params.h" +#include "benes.h" + +/* middle layers of the benes network */ +static void layer_in(uint64_t data[2][64], uint64_t * bits, int lgs) +{ + int i, j, s; + + uint64_t d; + + s = 1 << lgs; + + for (i = 0; i < 64; i += s*2) + for (j = i; j < i+s; j++) + { + + d = (data[0][j+0] ^ data[0][j+s]); + d &= (*bits++); + data[0][j+0] ^= d; + data[0][j+s] ^= d; + + d = (data[1][j+0] ^ data[1][j+s]); + d &= (*bits++); + data[1][j+0] ^= d; + data[1][j+s] ^= d; + } +} + +/* first and last layers of the benes network */ +static void layer_ex(uint64_t * data, uint64_t * bits, int lgs) +{ + int i, j, s; + + uint64_t d; + + s = 1 << lgs; + + for (i = 0; i < 128; i += s*2) + for (j = i; j < i+s; j++) + { + + d = (data[j+0] ^ data[j+s]); + d &= (*bits++); + data[j+0] ^= d; + data[j+s] ^= d; + } +} + +/* input: r, sequence of bits to be permuted */ +/* bits, condition bits of the Benes network */ +/* rev, 0 for normal application; !0 for inverse */ +/* output: r, permuted bits */ +void apply_benes(unsigned char * r, const unsigned char * bits, int rev) +{ + int i, iter, inc; + + unsigned char *r_ptr = r; + const unsigned char *bits_ptr; + + uint64_t r_int_v[2][64]; + uint64_t r_int_h[2][64]; + uint64_t b_int_v[64]; + uint64_t b_int_h[64]; + + // + + if (rev) { bits_ptr = bits + 12288; inc = -1024; } + else { bits_ptr = bits; inc = 0; } + + for (i = 0; i < 64; i++) + { + r_int_v[0][i] = load8(r_ptr + i*16 + 0); + r_int_v[1][i] = load8(r_ptr + i*16 + 8); + } + + transpose_64x64(r_int_h[0], r_int_v[0]); + transpose_64x64(r_int_h[1], r_int_v[1]); + + for (iter = 0; iter <= 6; iter++) + { + for (i = 0; i < 64; i++) + { + b_int_v[i] = load8(bits_ptr); bits_ptr += 8; + } + + bits_ptr += inc; + + transpose_64x64(b_int_h, b_int_v); + + layer_ex(r_int_h[0], b_int_h, iter); + } + + transpose_64x64(r_int_v[0], r_int_h[0]); + transpose_64x64(r_int_v[1], r_int_h[1]); + + for (iter = 0; iter <= 5; iter++) + { + for (i = 0; i < 64; i++) { b_int_v[i] = load8(bits_ptr); bits_ptr += 8; } + bits_ptr += inc; + + layer_in(r_int_v, b_int_v, iter); + } + + for (iter = 4; iter >= 0; iter--) + { + for (i = 0; i < 64; i++) { b_int_v[i] = load8(bits_ptr); bits_ptr += 8; } + bits_ptr += inc; + + layer_in(r_int_v, b_int_v, iter); + } + + transpose_64x64(r_int_h[0], r_int_v[0]); + transpose_64x64(r_int_h[1], r_int_v[1]); + + for (iter = 6; iter >= 0; iter--) + { + for (i = 0; i < 64; i++) + { + b_int_v[i] = load8(bits_ptr); bits_ptr += 8; + } + + bits_ptr += inc; + + transpose_64x64(b_int_h, b_int_v); + + layer_ex(r_int_h[0], b_int_h, iter); + } + + transpose_64x64(r_int_v[0], r_int_h[0]); + transpose_64x64(r_int_v[1], r_int_h[1]); + + for (i = 0; i < 64; i++) + { + store8(r_ptr + i*16 + 0, r_int_v[0][i]); + store8(r_ptr + i*16 + 8, r_int_v[1][i]); + } +} + +/* input: condition bits c */ +/* output: support s */ +void support_gen(gf * s, const unsigned char *c) +{ + gf a; + int i, j; + unsigned char L[ GFBITS ][ (1 << GFBITS)/8 ]; + + for (i = 0; i < GFBITS; i++) + for (j = 0; j < (1 << GFBITS)/8; j++) + L[i][j] = 0; + + for (i = 0; i < (1 << GFBITS); i++) + { + a = bitrev((gf) i); + + for (j = 0; j < GFBITS; j++) + L[j][ i/8 ] |= ((a >> j) & 1) << (i%8); + } + + for (j = 0; j < GFBITS; j++) + apply_benes(L[j], c, 0); + + for (i = 0; i < SYS_N; i++) + { + s[i] = 0; + for (j = GFBITS-1; j >= 0; j--) + { + s[i] <<= 1; + s[i] |= (L[j][i/8] >> (i%8)) & 1; + } + } +} + diff --git a/deps/mceliece/kem/mceliece6688128f/benes.h b/deps/mceliece/kem/mceliece6688128f/benes.h new file mode 100644 index 0000000..c2ef35a --- /dev/null +++ b/deps/mceliece/kem/mceliece6688128f/benes.h @@ -0,0 +1,16 @@ +/* + This file is for Benes network related functions +*/ + +#ifndef BENES_H +#define BENES_H +#define apply_benes CRYPTO_NAMESPACE(apply_benes) +#define support_gen CRYPTO_NAMESPACE(support_gen) + +#include "gf.h" + +void apply_benes(unsigned char *, const unsigned char *, int); +void support_gen(gf *, const unsigned char *); + +#endif + diff --git a/deps/mceliece/kem/mceliece6688128f/bm.c b/deps/mceliece/kem/mceliece6688128f/bm.c new file mode 100644 index 0000000..056a734 --- /dev/null +++ b/deps/mceliece/kem/mceliece6688128f/bm.c @@ -0,0 +1,72 @@ +/* + This file is for the Berlekamp-Massey algorithm + see http://crypto.stanford.edu/~mironov/cs359/massey.pdf +*/ + +#include "params.h" +#include "gf.h" +#include "bm.h" + +#define min(a, b) ((a < b) ? a : b) + +/* the Berlekamp-Massey algorithm */ +/* input: s, sequence of field elements */ +/* output: out, minimal polynomial of s */ +void bm(gf *out, gf *s) +{ + int i; + + uint16_t N = 0; + uint16_t L = 0; + uint16_t mle; + uint16_t mne; + + gf T[ SYS_T+1 ]; + gf C[ SYS_T+1 ]; + gf B[ SYS_T+1 ]; + + gf b = 1, d, f; + + // + + for (i = 0; i < SYS_T+1; i++) + C[i] = B[i] = 0; + + B[1] = C[0] = 1; + + // + + for (N = 0; N < 2 * SYS_T; N++) + { + d = 0; + + for (i = 0; i <= min(N, SYS_T); i++) + d ^= gf_mul(C[i], s[ N-i]); + + mne = d; mne -= 1; mne >>= 15; mne -= 1; + mle = N; mle -= 2*L; mle >>= 15; mle -= 1; + mle &= mne; + + for (i = 0; i <= SYS_T; i++) + T[i] = C[i]; + + f = gf_frac(b, d); + + for (i = 0; i <= SYS_T; i++) + C[i] ^= gf_mul(f, B[i]) & mne; + + L = (L & ~mle) | ((N+1-L) & mle); + + for (i = 0; i <= SYS_T; i++) + B[i] = (B[i] & ~mle) | (T[i] & mle); + + b = (b & ~mle) | (d & mle); + + for (i = SYS_T; i >= 1; i--) B[i] = B[i-1]; + B[0] = 0; + } + + for (i = 0; i <= SYS_T; i++) + out[i] = C[ SYS_T-i ]; +} + diff --git a/deps/mceliece/kem/mceliece6688128f/bm.h b/deps/mceliece/kem/mceliece6688128f/bm.h new file mode 100644 index 0000000..73d5c6c --- /dev/null +++ b/deps/mceliece/kem/mceliece6688128f/bm.h @@ -0,0 +1,13 @@ +/* + This file is for the Berlekamp-Massey algorithm + see http://crypto.stanford.edu/~mironov/cs359/massey.pdf +*/ + +#ifndef BM_H +#define BM_H +#define bm CRYPTO_NAMESPACE(bm) + +void bm(gf *, gf *); + +#endif + diff --git a/deps/mceliece/kem/mceliece6688128f/controlbits.c b/deps/mceliece/kem/mceliece6688128f/controlbits.c new file mode 100644 index 0000000..db9db9c --- /dev/null +++ b/deps/mceliece/kem/mceliece6688128f/controlbits.c @@ -0,0 +1,220 @@ +/* This file is for implementing the Nassimi-Sahni algorithm */ +/* See David Nassimi, Sartaj Sahni "Parallel algorithms to set up the Benes permutationnetwork" */ +/* See also https://cr.yp.to/papers/controlbits-20200923.pdf */ + +#include +#include "crypto_declassify.h" +#include "controlbits.h" +#include "int32_sort.h" +typedef int16_t int16; +typedef int32_t int32; +#include "crypto_int32.h" +#define int32_min crypto_int32_min +#include "crypto_int16.h" + +/* parameters: 1 <= w <= 14; n = 2^w */ +/* input: permutation pi of {0,1,...,n-1} */ +/* output: (2m-1)n/2 control bits at positions pos,pos+step,... */ +/* output position pos is by definition 1&(out[pos/8]>>(pos&7)) */ +/* caller must 0-initialize positions first */ +/* temp must have space for int32[2*n] */ +static void cbrecursion(unsigned char *out,long long pos,long long step,const int16 *pi,long long w,long long n,int32 *temp) +{ +#define A temp +#define B (temp+n) +#define q ((int16 *) (temp+n+n/4)) +/* q can start anywhere between temp+n and temp+n/2 */ + + long long x,i,j,k; + + if (w == 1) { + out[pos>>3] ^= pi[0]<<(pos&7); + return; + } + + for (x = 0;x < n;++x) A[x] = ((pi[x]^1)<<16)|pi[x^1]; + int32_sort(A,n); /* A = (id<<16)+pibar */ + + for (x = 0;x < n;++x) { + int32 Ax = A[x]; + int32 px = Ax&0xffff; + int32 cx = int32_min(px,x); + B[x] = (px<<16)|cx; + } + /* B = (p<<16)+c */ + + for (x = 0;x < n;++x) A[x] = (A[x]<<16)|x; /* A = (pibar<<16)+id */ + int32_sort(A,n); /* A = (id<<16)+pibar^-1 */ + + for (x = 0;x < n;++x) A[x] = (A[x]<<16)+(B[x]>>16); /* A = (pibar^(-1)<<16)+pibar */ + int32_sort(A,n); /* A = (id<<16)+pibar^2 */ + + if (w <= 10) { + for (x = 0;x < n;++x) B[x] = ((A[x]&0xffff)<<10)|(B[x]&0x3ff); + + for (i = 1;i < w-1;++i) { + /* B = (p<<10)+c */ + + for (x = 0;x < n;++x) A[x] = ((B[x]&~0x3ff)<<6)|x; /* A = (p<<16)+id */ + int32_sort(A,n); /* A = (id<<16)+p^{-1} */ + + for (x = 0;x < n;++x) A[x] = (A[x]<<20)|B[x]; /* A = (p^{-1}<<20)+(p<<10)+c */ + int32_sort(A,n); /* A = (id<<20)+(pp<<10)+cp */ + + for (x = 0;x < n;++x) { + int32 ppcpx = A[x]&0xfffff; + int32 ppcx = (A[x]&0xffc00)|(B[x]&0x3ff); + B[x] = int32_min(ppcx,ppcpx); + } + } + for (x = 0;x < n;++x) B[x] &= 0x3ff; + } else { + for (x = 0;x < n;++x) B[x] = (A[x]<<16)|(B[x]&0xffff); + + for (i = 1;i < w-1;++i) { + /* B = (p<<16)+c */ + + for (x = 0;x < n;++x) A[x] = (B[x]&~0xffff)|x; + int32_sort(A,n); /* A = (id<<16)+p^(-1) */ + + for (x = 0;x < n;++x) A[x] = (A[x]<<16)|(B[x]&0xffff); + /* A = p^(-1)<<16+c */ + + if (i < w-2) { + for (x = 0;x < n;++x) B[x] = (A[x]&~0xffff)|(B[x]>>16); + /* B = (p^(-1)<<16)+p */ + int32_sort(B,n); /* B = (id<<16)+p^(-2) */ + for (x = 0;x < n;++x) B[x] = (B[x]<<16)|(A[x]&0xffff); + /* B = (p^(-2)<<16)+c */ + } + + int32_sort(A,n); + /* A = id<<16+cp */ + for (x = 0;x < n;++x) { + int32 cpx = (B[x]&~0xffff)|(A[x]&0xffff); + B[x] = int32_min(B[x],cpx); + } + } + for (x = 0;x < n;++x) B[x] &= 0xffff; + } + + for (x = 0;x < n;++x) A[x] = (((int32)pi[x])<<16)+x; + int32_sort(A,n); /* A = (id<<16)+pi^(-1) */ + + for (j = 0;j < n/2;++j) { + long long x = 2*j; + int32 fj = B[x]&1; /* f[j] */ + int32 Fx = x+fj; /* F[x] */ + int32 Fx1 = Fx^1; /* F[x+1] */ + + out[pos>>3] ^= fj<<(pos&7); + pos += step; + + B[x] = (A[x]<<16)|Fx; + B[x+1] = (A[x+1]<<16)|Fx1; + } + /* B = (pi^(-1)<<16)+F */ + + int32_sort(B,n); /* B = (id<<16)+F(pi) */ + + pos += (2*w-3)*step*(n/2); + + for (k = 0;k < n/2;++k) { + long long y = 2*k; + int32 lk = B[y]&1; /* l[k] */ + int32 Ly = y+lk; /* L[y] */ + int32 Ly1 = Ly^1; /* L[y+1] */ + + out[pos>>3] ^= lk<<(pos&7); + pos += step; + + A[y] = (Ly<<16)|(B[y]&0xffff); + A[y+1] = (Ly1<<16)|(B[y+1]&0xffff); + } + /* A = (L<<16)+F(pi) */ + + int32_sort(A,n); /* A = (id<<16)+F(pi(L)) = (id<<16)+M */ + + pos -= (2*w-2)*step*(n/2); + + for (j = 0;j < n/2;++j) { + q[j] = (A[2*j]&0xffff)>>1; + q[j+n/2] = (A[2*j+1]&0xffff)>>1; + } + + cbrecursion(out,pos,step*2,q,w-1,n/2,temp); + cbrecursion(out,pos+step,step*2,q+n/2,w-1,n/2,temp); +} + +/* input: p, an array of int16 */ +/* input: n, length of p */ +/* input: s, meaning that stride-2^s cswaps are performed */ +/* input: cb, the control bits */ +/* output: the result of apply the control bits to p */ +static void layer(int16_t *p, const unsigned char *cb, int s, int n) +{ + int i, j; + int stride = 1 << s; + int index = 0; + int16_t d, m; + + for (i = 0; i < n; i += stride*2) + { + for (j = 0; j < stride; j++) + { + d = p[ i+j ] ^ p[ i+j+stride ]; + m = (cb[ index >> 3 ] >> (index & 7)) & 1; + m = -m; + d &= m; + p[ i+j ] ^= d; + p[ i+j+stride ] ^= d; + index++; + } + } +} + +/* parameters: 1 <= w <= 14; n = 2^w */ +/* input: permutation pi of {0,1,...,n-1} */ +/* output: (2m-1)n/2 control bits at positions 0,1,... */ +/* output position pos is by definition 1&(out[pos/8]>>(pos&7)) */ +void controlbitsfrompermutation(unsigned char *out,const int16 *pi,long long w,long long n) +{ + int32 temp[2*n]; + int16 pi_test[n], diff; + int i; + unsigned char *ptr; + + while (1) + { + memset(out,0,(((2*w-1)*n/2)+7)/8); + cbrecursion(out,0,1,pi,w,n,temp); + + // check for correctness + + for (i = 0; i < n; i++) + pi_test[i] = i; + + ptr = out; + for (i = 0; i < w; i++) + { + layer(pi_test, ptr, i, n); + ptr += n >> 4; + } + + for (i = w-2; i >= 0; i--) + { + layer(pi_test, ptr, i, n); + ptr += n >> 4; + } + + diff = 0; + for (i = 0; i < n; i++) + diff |= pi[i] ^ pi_test[i]; + + diff = crypto_int16_nonzero_mask(diff); + crypto_declassify(&diff,sizeof diff); + if (diff == 0) + break; + } +} + diff --git a/deps/mceliece/kem/mceliece6688128f/controlbits.h b/deps/mceliece/kem/mceliece6688128f/controlbits.h new file mode 100644 index 0000000..8ddd210 --- /dev/null +++ b/deps/mceliece/kem/mceliece6688128f/controlbits.h @@ -0,0 +1,14 @@ +/* This file is for implementing the Nassimi-Sahni algorithm */ +/* See David Nassimi, Sartaj Sahni "Parallel algorithms to set up the Benes permutationnetwork" */ +/* See also https://cr.yp.to/papers/controlbits-20200923.pdf */ + +#ifndef CONTROLBITS_H +#define CONTROLBITS_H + +#define controlbitsfrompermutation CRYPTO_NAMESPACE(controlbitsfrompermutation) + +#include + +extern void controlbitsfrompermutation(unsigned char *,const int16_t *,long long,long long); + +#endif diff --git a/deps/mceliece/kem/mceliece6688128f/crypto_hash.h b/deps/mceliece/kem/mceliece6688128f/crypto_hash.h new file mode 100644 index 0000000..b7c1086 --- /dev/null +++ b/deps/mceliece/kem/mceliece6688128f/crypto_hash.h @@ -0,0 +1,10 @@ +/* This file uses SHAKE256 implemented in the Keccak Code Package */ + +#include "../../mceliece_externals.h" + +#define crypto_hash_32b(out,in,inlen) \ + SHAKE256(out,32,in,inlen) + +#define shake(out,outlen,in,inlen) \ + SHAKE256(out,outlen,in,inlen) + diff --git a/deps/mceliece/kem/mceliece6688128f/crypto_kem.h b/deps/mceliece/kem/mceliece6688128f/crypto_kem.h new file mode 100644 index 0000000..308c62c --- /dev/null +++ b/deps/mceliece/kem/mceliece6688128f/crypto_kem.h @@ -0,0 +1,15 @@ +#ifndef crypto_kem_H +#define crypto_kem_H + +#include "crypto_kem_mceliece6688128f.h" + +#define crypto_kem_keypair crypto_kem_mceliece6688128f_keypair +#define crypto_kem_enc crypto_kem_mceliece6688128f_enc +#define crypto_kem_dec crypto_kem_mceliece6688128f_dec +#define crypto_kem_PUBLICKEYBYTES crypto_kem_mceliece6688128f_PUBLICKEYBYTES +#define crypto_kem_SECRETKEYBYTES crypto_kem_mceliece6688128f_SECRETKEYBYTES +#define crypto_kem_BYTES crypto_kem_mceliece6688128f_BYTES +#define crypto_kem_CIPHERTEXTBYTES crypto_kem_mceliece6688128f_CIPHERTEXTBYTES +#define crypto_kem_PRIMITIVE "mceliece6688128f" + +#endif diff --git a/deps/mceliece/kem/mceliece6688128f/crypto_kem_mceliece6688128f.h b/deps/mceliece/kem/mceliece6688128f/crypto_kem_mceliece6688128f.h new file mode 100644 index 0000000..c4e5234 --- /dev/null +++ b/deps/mceliece/kem/mceliece6688128f/crypto_kem_mceliece6688128f.h @@ -0,0 +1,28 @@ +#ifndef crypto_kem_mceliece6688128f_H +#define crypto_kem_mceliece6688128f_H + +#define crypto_kem_mceliece6688128f_ref_PUBLICKEYBYTES 1044992 +#define crypto_kem_mceliece6688128f_ref_SECRETKEYBYTES 13932 +#define crypto_kem_mceliece6688128f_ref_CIPHERTEXTBYTES 208 +#define crypto_kem_mceliece6688128f_ref_BYTES 32 + + +#ifdef __cplusplus +extern "C" { +#endif +extern int crypto_kem_mceliece6688128f_ref_keypair(unsigned char *,unsigned char *); +extern int crypto_kem_mceliece6688128f_ref_enc(unsigned char *,unsigned char *,const unsigned char *); +extern int crypto_kem_mceliece6688128f_ref_dec(unsigned char *,const unsigned char *,const unsigned char *); +#ifdef __cplusplus +} +#endif + +#define crypto_kem_mceliece6688128f_keypair crypto_kem_mceliece6688128f_ref_keypair +#define crypto_kem_mceliece6688128f_enc crypto_kem_mceliece6688128f_ref_enc +#define crypto_kem_mceliece6688128f_dec crypto_kem_mceliece6688128f_ref_dec +#define crypto_kem_mceliece6688128f_PUBLICKEYBYTES crypto_kem_mceliece6688128f_ref_PUBLICKEYBYTES +#define crypto_kem_mceliece6688128f_SECRETKEYBYTES crypto_kem_mceliece6688128f_ref_SECRETKEYBYTES +#define crypto_kem_mceliece6688128f_BYTES crypto_kem_mceliece6688128f_ref_BYTES +#define crypto_kem_mceliece6688128f_CIPHERTEXTBYTES crypto_kem_mceliece6688128f_ref_CIPHERTEXTBYTES + +#endif diff --git a/deps/mceliece/kem/mceliece6688128f/decrypt.c b/deps/mceliece/kem/mceliece6688128f/decrypt.c new file mode 100644 index 0000000..c4cc6de --- /dev/null +++ b/deps/mceliece/kem/mceliece6688128f/decrypt.c @@ -0,0 +1,93 @@ +/* + This file is for Niederreiter decryption +*/ + +#include +#include "decrypt.h" + +#include "params.h" +#include "benes.h" +#include "util.h" +#include "synd.h" +#include "root.h" +#include "gf.h" +#include "bm.h" + +/* Niederreiter decryption with the Berlekamp decoder */ +/* intput: sk, secret key */ +/* c, ciphertext */ +/* output: e, error vector */ +/* return: 0 for success; 1 for failure */ +int decrypt(unsigned char *e, const unsigned char *sk, const unsigned char *c) +{ + int i, w = 0; + uint16_t check; + + unsigned char r[ SYS_N/8 ]; + + gf g[ SYS_T+1 ]; + gf L[ SYS_N ]; + + gf s[ SYS_T*2 ]; + gf s_cmp[ SYS_T*2 ]; + gf locator[ SYS_T+1 ]; + gf images[ SYS_N ]; + + gf t; + + // + + for (i = 0; i < SYND_BYTES; i++) r[i] = c[i]; + for (i = SYND_BYTES; i < SYS_N/8; i++) r[i] = 0; + + for (i = 0; i < SYS_T; i++) { g[i] = load_gf(sk); sk += 2; } g[ SYS_T ] = 1; + + support_gen(L, sk); + + synd(s, g, L, r); + + bm(locator, s); + + root(images, locator, L); + + // + + for (i = 0; i < SYS_N/8; i++) + e[i] = 0; + + for (i = 0; i < SYS_N; i++) + { + t = gf_iszero(images[i]) & 1; + + e[ i/8 ] |= t << (i%8); + w += t; + + } + +#ifdef KAT + { + int k; + printf("decrypt e: positions"); + for (k = 0;k < SYS_N;++k) + if (e[k/8] & (1 << (k&7))) + printf(" %d",k); + printf("\n"); + } +#endif + + synd(s_cmp, g, L, e); + + // + + check = w; + check ^= SYS_T; + + for (i = 0; i < SYS_T*2; i++) + check |= s[i] ^ s_cmp[i]; + + check -= 1; + check >>= 15; + + return check ^ 1; +} + diff --git a/deps/mceliece/kem/mceliece6688128f/decrypt.h b/deps/mceliece/kem/mceliece6688128f/decrypt.h new file mode 100644 index 0000000..266a5cd --- /dev/null +++ b/deps/mceliece/kem/mceliece6688128f/decrypt.h @@ -0,0 +1,12 @@ +/* + This file is for Nieddereiter decryption +*/ + +#ifndef DECRYPT_H +#define DECRYPT_H +#define decrypt CRYPTO_NAMESPACE(decrypt) + +int decrypt(unsigned char *, const unsigned char *, const unsigned char *); + +#endif + diff --git a/deps/mceliece/kem/mceliece6688128f/encrypt.c b/deps/mceliece/kem/mceliece6688128f/encrypt.c new file mode 100644 index 0000000..4823d2f --- /dev/null +++ b/deps/mceliece/kem/mceliece6688128f/encrypt.c @@ -0,0 +1,161 @@ +/* + This file is for Niederreiter encryption +*/ + +#include "encrypt.h" + +#include "util.h" +#include "params.h" +#include "randombytes.h" + +#include +#include +#include +#include + +#include "gf.h" +#include "crypto_declassify.h" +#include "crypto_uint16.h" +#include "crypto_uint32.h" + +static inline crypto_uint16 uint16_is_smaller_declassify(uint16_t t,uint16_t u) +{ + crypto_uint16 mask = crypto_uint16_smaller_mask(t,u); + crypto_declassify(&mask,sizeof mask); + return mask; +} + +static inline crypto_uint32 uint32_is_equal_declassify(uint32_t t,uint32_t u) +{ + crypto_uint32 mask = crypto_uint32_equal_mask(t,u); + crypto_declassify(&mask,sizeof mask); + return mask; +} + +static inline unsigned char same_mask(uint16_t x, uint16_t y) +{ + uint32_t mask; + + mask = x ^ y; + mask -= 1; + mask >>= 31; + mask = -mask; + + return mask & 0xFF; +} + +/* output: e, an error vector of weight t */ +static void gen_e(unsigned char *e) +{ + int i, j, eq, count; + + union + { + uint16_t nums[ SYS_T*2 ]; + unsigned char bytes[ SYS_T*2 * sizeof(uint16_t) ]; + } buf; + + uint16_t ind[ SYS_T ]; + unsigned char mask; + unsigned char val[ SYS_T ]; + + while (1) + { + randombytes(buf.bytes, sizeof(buf)); + + for (i = 0; i < SYS_T*2; i++) + buf.nums[i] = load_gf(buf.bytes + i*2); + + // moving and counting indices in the correct range + + count = 0; + for (i = 0; i < SYS_T*2 && count < SYS_T; i++) + if (uint16_is_smaller_declassify(buf.nums[i],SYS_N)) + ind[ count++ ] = buf.nums[i]; + + if (count < SYS_T) continue; + + // check for repetition + + eq = 0; + + for (i = 1; i < SYS_T; i++) + for (j = 0; j < i; j++) + if (uint32_is_equal_declassify(ind[i],ind[j])) + eq = 1; + + if (eq == 0) + break; + } + + for (j = 0; j < SYS_T; j++) + val[j] = 1 << (ind[j] & 7); + + for (i = 0; i < SYS_N/8; i++) + { + e[i] = 0; + + for (j = 0; j < SYS_T; j++) + { + mask = same_mask(i, (ind[j] >> 3)); + + e[i] |= val[j] & mask; + } + } +} + +/* input: public key pk, error vector e */ +/* output: syndrome s */ +static void syndrome(unsigned char *s, const unsigned char *pk, unsigned char *e) +{ + unsigned char b, row[SYS_N/8]; + const unsigned char *pk_ptr = pk; + + int i, j; + + for (i = 0; i < SYND_BYTES; i++) + s[i] = 0; + + for (i = 0; i < PK_NROWS; i++) + { + for (j = 0; j < SYS_N/8; j++) + row[j] = 0; + + for (j = 0; j < PK_ROW_BYTES; j++) + row[ SYS_N/8 - PK_ROW_BYTES + j ] = pk_ptr[j]; + + row[i/8] |= 1 << (i%8); + + b = 0; + for (j = 0; j < SYS_N/8; j++) + b ^= row[j] & e[j]; + + b ^= b >> 4; + b ^= b >> 2; + b ^= b >> 1; + b &= 1; + + s[ i/8 ] |= (b << (i%8)); + + pk_ptr += PK_ROW_BYTES; + } +} + +void encrypt(unsigned char *s, const unsigned char *pk, unsigned char *e) +{ + gen_e(e); + +#ifdef KAT + { + int k; + printf("encrypt e: positions"); + for (k = 0;k < SYS_N;++k) + if (e[k/8] & (1 << (k&7))) + printf(" %d",k); + printf("\n"); + } +#endif + + syndrome(s, pk, e); +} + diff --git a/deps/mceliece/kem/mceliece6688128f/encrypt.h b/deps/mceliece/kem/mceliece6688128f/encrypt.h new file mode 100644 index 0000000..8edd7a6 --- /dev/null +++ b/deps/mceliece/kem/mceliece6688128f/encrypt.h @@ -0,0 +1,12 @@ +/* + This file is for Niederreiter encryption +*/ + +#ifndef ENCRYPT_H +#define ENCRYPT_H +#define encrypt CRYPTO_NAMESPACE(encrypt) + +void encrypt(unsigned char *, const unsigned char *, unsigned char *); + +#endif + diff --git a/deps/mceliece/kem/mceliece6688128f/gf.c b/deps/mceliece/kem/mceliece6688128f/gf.c new file mode 100644 index 0000000..159a286 --- /dev/null +++ b/deps/mceliece/kem/mceliece6688128f/gf.c @@ -0,0 +1,215 @@ +/* + This file is for functions for field arithmetic +*/ + +#include "gf.h" + +#include "params.h" + +gf gf_iszero(gf a) +{ + uint32_t t = a; + + t -= 1; + t >>= 19; + + return (gf) t; +} + +gf gf_add(gf in0, gf in1) +{ + return in0 ^ in1; +} + +gf gf_mul(gf in0, gf in1) +{ + int i; + + uint64_t tmp; + uint64_t t0; + uint64_t t1; + uint64_t t; + + t0 = in0; + t1 = in1; + + tmp = t0 * (t1 & 1); + + for (i = 1; i < GFBITS; i++) + tmp ^= (t0 * (t1 & (1 << i))); + + // + + t = tmp & 0x1FF0000; + tmp ^= (t >> 9) ^ (t >> 10) ^ (t >> 12) ^ (t >> 13); + + t = tmp & 0x000E000; + tmp ^= (t >> 9) ^ (t >> 10) ^ (t >> 12) ^ (t >> 13); + + return tmp & GFMASK; +} + +/* input: field element in */ +/* return: (in^2)^2 */ +static inline gf gf_sq2(gf in) +{ + int i; + + const uint64_t B[] = {0x1111111111111111, + 0x0303030303030303, + 0x000F000F000F000F, + 0x000000FF000000FF}; + + const uint64_t M[] = {0x0001FF0000000000, + 0x000000FF80000000, + 0x000000007FC00000, + 0x00000000003FE000}; + + uint64_t x = in; + uint64_t t; + + x = (x | (x << 24)) & B[3]; + x = (x | (x << 12)) & B[2]; + x = (x | (x << 6)) & B[1]; + x = (x | (x << 3)) & B[0]; + + for (i = 0; i < 4; i++) + { + t = x & M[i]; + x ^= (t >> 9) ^ (t >> 10) ^ (t >> 12) ^ (t >> 13); + } + + return x & GFMASK; +} + +/* input: field element in, m */ +/* return: (in^2)*m */ +static inline gf gf_sqmul(gf in, gf m) +{ + int i; + + uint64_t x; + uint64_t t0; + uint64_t t1; + uint64_t t; + + const uint64_t M[] = {0x0000001FF0000000, + 0x000000000FF80000, + 0x000000000007E000}; + + t0 = in; + t1 = m; + + x = (t1 << 6) * (t0 & (1 << 6)); + + t0 ^= (t0 << 7); + + x ^= (t1 * (t0 & (0x04001))); + x ^= (t1 * (t0 & (0x08002))) << 1; + x ^= (t1 * (t0 & (0x10004))) << 2; + x ^= (t1 * (t0 & (0x20008))) << 3; + x ^= (t1 * (t0 & (0x40010))) << 4; + x ^= (t1 * (t0 & (0x80020))) << 5; + + for (i = 0; i < 3; i++) + { + t = x & M[i]; + x ^= (t >> 9) ^ (t >> 10) ^ (t >> 12) ^ (t >> 13); + } + + return x & GFMASK; +} + +/* input: field element in, m */ +/* return: ((in^2)^2)*m */ +static inline gf gf_sq2mul(gf in, gf m) +{ + int i; + + uint64_t x; + uint64_t t0; + uint64_t t1; + uint64_t t; + + const uint64_t M[] = {0x1FF0000000000000, + 0x000FF80000000000, + 0x000007FC00000000, + 0x00000003FE000000, + 0x0000000001FE0000, + 0x000000000001E000}; + + t0 = in; + t1 = m; + + x = (t1 << 18) * (t0 & (1 << 6)); + + t0 ^= (t0 << 21); + + x ^= (t1 * (t0 & (0x010000001))); + x ^= (t1 * (t0 & (0x020000002))) << 3; + x ^= (t1 * (t0 & (0x040000004))) << 6; + x ^= (t1 * (t0 & (0x080000008))) << 9; + x ^= (t1 * (t0 & (0x100000010))) << 12; + x ^= (t1 * (t0 & (0x200000020))) << 15; + + for (i = 0; i < 6; i++) + { + t = x & M[i]; + x ^= (t >> 9) ^ (t >> 10) ^ (t >> 12) ^ (t >> 13); + } + + return x & GFMASK; +} + +/* input: field element den, num */ +/* return: (num/den) */ +gf gf_frac(gf den, gf num) +{ + gf tmp_11; + gf tmp_1111; + gf out; + + tmp_11 = gf_sqmul(den, den); // ^11 + tmp_1111 = gf_sq2mul(tmp_11, tmp_11); // ^1111 + out = gf_sq2(tmp_1111); + out = gf_sq2mul(out, tmp_1111); // ^11111111 + out = gf_sq2(out); + out = gf_sq2mul(out, tmp_1111); // ^111111111111 + + return gf_sqmul(out, num); // ^1111111111110 = ^-1 +} + +gf gf_inv(gf den) +{ + return gf_frac(den, ((gf) 1)); +} + +/* input: in0, in1 in GF((2^m)^t)*/ +/* output: out = in0*in1 */ +void GF_mul(gf *out, gf *in0, gf *in1) +{ + int i, j; + + gf prod[ SYS_T*2-1 ]; + + for (i = 0; i < SYS_T*2-1; i++) + prod[i] = 0; + + for (i = 0; i < SYS_T; i++) + for (j = 0; j < SYS_T; j++) + prod[i+j] ^= gf_mul(in0[i], in1[j]); + + // + + for (i = (SYS_T-1)*2; i >= SYS_T; i--) + { + prod[i - SYS_T + 7] ^= prod[i]; + prod[i - SYS_T + 2] ^= prod[i]; + prod[i - SYS_T + 1] ^= prod[i]; + prod[i - SYS_T + 0] ^= prod[i]; + } + + for (i = 0; i < SYS_T; i++) + out[i] = prod[i]; +} + diff --git a/deps/mceliece/kem/mceliece6688128f/gf.h b/deps/mceliece/kem/mceliece6688128f/gf.h new file mode 100644 index 0000000..f62209d --- /dev/null +++ b/deps/mceliece/kem/mceliece6688128f/gf.h @@ -0,0 +1,27 @@ +/* + This file is for functions for field arithmetic +*/ + +#ifndef GF_H +#define GF_H +#define gf_add CRYPTO_NAMESPACE(gf_add) +#define gf_frac CRYPTO_NAMESPACE(gf_frac) +#define gf_inv CRYPTO_NAMESPACE(gf_inv) +#define gf_iszero CRYPTO_NAMESPACE(gf_iszero) +#define gf_mul CRYPTO_NAMESPACE(gf_mul) +#define GF_mul CRYPTO_NAMESPACE(GF_mul) + +#include + +typedef uint16_t gf; + +gf gf_iszero(gf); +gf gf_add(gf, gf); +gf gf_mul(gf, gf); +gf gf_frac(gf, gf); +gf gf_inv(gf); + +void GF_mul(gf *, gf *, gf *); + +#endif + diff --git a/deps/mceliece/kem/mceliece6688128f/int32_sort.h b/deps/mceliece/kem/mceliece6688128f/int32_sort.h new file mode 100644 index 0000000..a431af2 --- /dev/null +++ b/deps/mceliece/kem/mceliece6688128f/int32_sort.h @@ -0,0 +1,46 @@ +#ifndef int32_sort_h +#define int32_sort_h + +#define int32_sort CRYPTO_NAMESPACE(int32_sort) + +#include + +#define int32_MINMAX(a,b) \ +do { \ + int32_t ab = b ^ a; \ + int32_t c = b - a; \ + c ^= ab & (c ^ b); \ + c >>= 31; \ + c &= ab; \ + a ^= c; \ + b ^= c; \ +} while(0) + +static void int32_sort(int32_t *x,long long n) +{ + long long top,p,q,r,i; + + if (n < 2) return; + top = 1; + while (top < n - top) top += top; + + for (p = top;p > 0;p >>= 1) { + for (i = 0;i < n - p;++i) + if (!(i & p)) + int32_MINMAX(x[i],x[i+p]); + i = 0; + for (q = top;q > p;q >>= 1) { + for (;i < n - q;++i) { + if (!(i & p)) { + int32_t a = x[i + p]; + for (r = q;r > p;r >>= 1) + int32_MINMAX(a,x[i+r]); + x[i + p] = a; + } + } + } + } +} + +#endif + diff --git a/deps/mceliece/kem/mceliece6688128f/operations.c b/deps/mceliece/kem/mceliece6688128f/operations.c new file mode 100644 index 0000000..bb605b1 --- /dev/null +++ b/deps/mceliece/kem/mceliece6688128f/operations.c @@ -0,0 +1,147 @@ +#include "operations.h" + +#include "controlbits.h" +#include "randombytes.h" +#include "crypto_hash.h" +#include "encrypt.h" +#include "decrypt.h" +#include "params.h" +#include "sk_gen.h" +#include "pk_gen.h" +#include "util.h" + +#include +#include + +int crypto_kem_enc( + unsigned char *c, + unsigned char *key, + const unsigned char *pk +) +{ + unsigned char e[ SYS_N/8 ]; + unsigned char one_ec[ 1 + SYS_N/8 + SYND_BYTES ] = {1}; + + // + + encrypt(c, pk, e); + + memcpy(one_ec + 1, e, SYS_N/8); + memcpy(one_ec + 1 + SYS_N/8, c, SYND_BYTES); + + crypto_hash_32b(key, one_ec, sizeof(one_ec)); + + return 0; +} + +int crypto_kem_dec( + unsigned char *key, + const unsigned char *c, + const unsigned char *sk +) +{ + int i; + + unsigned char ret_decrypt = 0; + + uint16_t m; + + unsigned char e[ SYS_N/8 ]; + unsigned char preimage[ 1 + SYS_N/8 + SYND_BYTES ]; + unsigned char *x = preimage; + const unsigned char *s = sk + 40 + IRR_BYTES + COND_BYTES; + + // + + ret_decrypt = decrypt(e, sk + 40, c); + + m = ret_decrypt; + m -= 1; + m >>= 8; + + *x++ = m & 1; + for (i = 0; i < SYS_N/8; i++) + *x++ = (~m & s[i]) | (m & e[i]); + + for (i = 0; i < SYND_BYTES; i++) + *x++ = c[i]; + + crypto_hash_32b(key, preimage, sizeof(preimage)); + + return 0; +} + +int crypto_kem_keypair +( + unsigned char *pk, + unsigned char *sk +) +{ + int i; + unsigned char seed[ 33 ] = {64}; + unsigned char r[ SYS_N/8 + (1 << GFBITS)*sizeof(uint32_t) + SYS_T*2 + 32 ]; + unsigned char *rp, *skp; + uint64_t pivots; + + gf f[ SYS_T ]; // element in GF(2^mt) + gf irr[ SYS_T ]; // Goppa polynomial + uint32_t perm[ 1 << GFBITS ]; // random permutation as 32-bit integers + int16_t pi[ 1 << GFBITS ]; // random permutation + + randombytes(seed+1, 32); + + while (1) + { + rp = &r[ sizeof(r)-32 ]; + skp = sk; + + // expanding and updating the seed + + shake(r, sizeof(r), seed, 33); + memcpy(skp, seed+1, 32); + skp += 32 + 8; + memcpy(seed+1, &r[ sizeof(r)-32 ], 32); + + // generating irreducible polynomial + + rp -= sizeof(f); + + for (i = 0; i < SYS_T; i++) + f[i] = load_gf(rp + i*2); + + if (genpoly_gen(irr, f)) + continue; + + for (i = 0; i < SYS_T; i++) + store_gf(skp + i*2, irr[i]); + + skp += IRR_BYTES; + + // generating permutation + + rp -= sizeof(perm); + + for (i = 0; i < (1 << GFBITS); i++) + perm[i] = load4(rp + i*4); + + if (pk_gen(pk, skp - IRR_BYTES, perm, pi, &pivots)) + continue; + + controlbitsfrompermutation(skp, pi, GFBITS, 1 << GFBITS); + skp += COND_BYTES; + + // storing the random string s + + rp -= SYS_N/8; + memcpy(skp, rp, SYS_N/8); + + // storing positions of the 32 pivots + + store8(sk + 32, pivots); + + break; + } + + return 0; +} + diff --git a/deps/mceliece/kem/mceliece6688128f/operations.h b/deps/mceliece/kem/mceliece6688128f/operations.h new file mode 100644 index 0000000..bf65502 --- /dev/null +++ b/deps/mceliece/kem/mceliece6688128f/operations.h @@ -0,0 +1,25 @@ +#ifndef OPERATIONS_H +#define OPERATIONS_H + +#include "crypto_kem.h" + +int crypto_kem_enc( + unsigned char *c, + unsigned char *key, + const unsigned char *pk +); + +int crypto_kem_dec( + unsigned char *key, + const unsigned char *c, + const unsigned char *sk +); + +int crypto_kem_keypair +( + unsigned char *pk, + unsigned char *sk +); + +#endif + diff --git a/deps/mceliece/kem/mceliece6688128f/params.h b/deps/mceliece/kem/mceliece6688128f/params.h new file mode 100644 index 0000000..147d579 --- /dev/null +++ b/deps/mceliece/kem/mceliece6688128f/params.h @@ -0,0 +1,20 @@ +#ifndef PARAMS_H +#define PARAMS_H + +#define GFBITS 13 +#define SYS_N 6688 +#define SYS_T 128 + +#define COND_BYTES ((1 << (GFBITS-4))*(2*GFBITS - 1)) +#define IRR_BYTES (SYS_T * 2) + +#define PK_NROWS (SYS_T*GFBITS) +#define PK_NCOLS (SYS_N - PK_NROWS) +#define PK_ROW_BYTES ((PK_NCOLS + 7)/8) + +#define SYND_BYTES ((PK_NROWS + 7)/8) + +#define GFMASK ((1 << GFBITS) - 1) + +#endif + diff --git a/deps/mceliece/kem/mceliece6688128f/pk_gen.c b/deps/mceliece/kem/mceliece6688128f/pk_gen.c new file mode 100644 index 0000000..5ae6c10 --- /dev/null +++ b/deps/mceliece/kem/mceliece6688128f/pk_gen.c @@ -0,0 +1,252 @@ +/* + This file is for public-key generation +*/ + +#include +#include +#include +#include + +#include "controlbits.h" +#include "uint64_sort.h" +#include "pk_gen.h" +#include "params.h" +#include "benes.h" +#include "root.h" +#include "util.h" +#include "crypto_declassify.h" +#include "crypto_uint64.h" + +static crypto_uint64 uint64_is_equal_declassify(uint64_t t,uint64_t u) +{ + crypto_uint64 mask = crypto_uint64_equal_mask(t,u); + crypto_declassify(&mask,sizeof mask); + return mask; +} + +static crypto_uint64 uint64_is_zero_declassify(uint64_t t) +{ + crypto_uint64 mask = crypto_uint64_zero_mask(t); + crypto_declassify(&mask,sizeof mask); + return mask; +} + +#define min(a, b) ((a < b) ? a : b) + +/* return number of trailing zeros of the non-zero input in */ +static inline int ctz(uint64_t in) +{ + int i, b, m = 0, r = 0; + + for (i = 0; i < 64; i++) + { + b = (in >> i) & 1; + m |= b; + r += (m^1) & (b^1); + } + + return r; +} + +static inline uint64_t same_mask(uint16_t x, uint16_t y) +{ + uint64_t mask; + + mask = x ^ y; + mask -= 1; + mask >>= 63; + mask = -mask; + + return mask; +} + +static int mov_columns(uint8_t mat[][ SYS_N/8 ], int16_t * pi, uint64_t * pivots) +{ + int i, j, k, s, block_idx, row; + uint64_t buf[64], ctz_list[32], t, d, mask, one = 1; + + row = PK_NROWS - 32; + block_idx = row/8; + + // extract the 32x64 matrix + + for (i = 0; i < 32; i++) + buf[i] = load8( &mat[ row + i ][ block_idx ] ); + + // compute the column indices of pivots by Gaussian elimination. + // the indices are stored in ctz_list + + *pivots = 0; + + for (i = 0; i < 32; i++) + { + t = buf[i]; + for (j = i+1; j < 32; j++) + t |= buf[j]; + + if (uint64_is_zero_declassify(t)) return -1; // return if buf is not full rank + + ctz_list[i] = s = ctz(t); + *pivots |= one << ctz_list[i]; + + for (j = i+1; j < 32; j++) { mask = (buf[i] >> s) & 1; mask -= 1; buf[i] ^= buf[j] & mask; } + for (j = i+1; j < 32; j++) { mask = (buf[j] >> s) & 1; mask = -mask; buf[j] ^= buf[i] & mask; } + } + + // updating permutation + + for (j = 0; j < 32; j++) + for (k = j+1; k < 64; k++) + { + d = pi[ row + j ] ^ pi[ row + k ]; + d &= same_mask(k, ctz_list[j]); + pi[ row + j ] ^= d; + pi[ row + k ] ^= d; + } + + // moving columns of mat according to the column indices of pivots + + for (i = 0; i < PK_NROWS; i++) + { + t = load8( &mat[ i ][ block_idx ] ); + + for (j = 0; j < 32; j++) + { + d = t >> j; + d ^= t >> ctz_list[j]; + d &= 1; + + t ^= d << ctz_list[j]; + t ^= d << j; + } + + store8( &mat[ i ][ block_idx ], t ); + } + + return 0; +} + +/* input: secret key sk */ +/* output: public key pk */ +int pk_gen(unsigned char * pk, unsigned char * sk, uint32_t * perm, int16_t * pi, uint64_t * pivots) +{ + int i, j, k; + int row, c; + + uint64_t buf[ 1 << GFBITS ]; + + unsigned char mat[ PK_NROWS ][ SYS_N/8 ]; + unsigned char mask; + unsigned char b; + + gf g[ SYS_T+1 ]; // Goppa polynomial + gf L[ SYS_N ]; // support + gf inv[ SYS_N ]; + + // + + g[ SYS_T ] = 1; + + for (i = 0; i < SYS_T; i++) { g[i] = load_gf(sk); sk += 2; } + + for (i = 0; i < (1 << GFBITS); i++) + { + buf[i] = perm[i]; + buf[i] <<= 31; + buf[i] |= i; + } + + uint64_sort(buf, 1 << GFBITS); + + for (i = 1; i < (1 << GFBITS); i++) + if (uint64_is_equal_declassify(buf[i-1] >> 31,buf[i] >> 31)) + return -1; + + for (i = 0; i < (1 << GFBITS); i++) pi[i] = buf[i] & GFMASK; + for (i = 0; i < SYS_N; i++) L[i] = bitrev(pi[i]); + + // filling the matrix + + root(inv, g, L); + + for (i = 0; i < SYS_N; i++) + inv[i] = gf_inv(inv[i]); + + for (i = 0; i < PK_NROWS; i++) + for (j = 0; j < SYS_N/8; j++) + mat[i][j] = 0; + + for (i = 0; i < SYS_T; i++) + { + for (j = 0; j < SYS_N; j+=8) + for (k = 0; k < GFBITS; k++) + { + b = (inv[j+7] >> k) & 1; b <<= 1; + b |= (inv[j+6] >> k) & 1; b <<= 1; + b |= (inv[j+5] >> k) & 1; b <<= 1; + b |= (inv[j+4] >> k) & 1; b <<= 1; + b |= (inv[j+3] >> k) & 1; b <<= 1; + b |= (inv[j+2] >> k) & 1; b <<= 1; + b |= (inv[j+1] >> k) & 1; b <<= 1; + b |= (inv[j+0] >> k) & 1; + + mat[ i*GFBITS + k ][ j/8 ] = b; + } + + for (j = 0; j < SYS_N; j++) + inv[j] = gf_mul(inv[j], L[j]); + + } + + // gaussian elimination + + for (i = 0; i < (PK_NROWS + 7) / 8; i++) + for (j = 0; j < 8; j++) + { + row = i*8 + j; + + if (row >= PK_NROWS) + break; + + if (row == PK_NROWS - 32) + { + if (mov_columns(mat, pi, pivots)) + return -1; + } + + for (k = row + 1; k < PK_NROWS; k++) + { + mask = mat[ row ][ i ] ^ mat[ k ][ i ]; + mask >>= j; + mask &= 1; + mask = -mask; + + for (c = 0; c < SYS_N/8; c++) + mat[ row ][ c ] ^= mat[ k ][ c ] & mask; + } + + if ( uint64_is_zero_declassify((mat[ row ][ i ] >> j) & 1) ) // return if not systematic + { + return -1; + } + + for (k = 0; k < PK_NROWS; k++) + { + if (k != row) + { + mask = mat[ k ][ i ] >> j; + mask &= 1; + mask = -mask; + + for (c = 0; c < SYS_N/8; c++) + mat[ k ][ c ] ^= mat[ row ][ c ] & mask; + } + } + } + + for (i = 0; i < PK_NROWS; i++) + memcpy(pk + i*PK_ROW_BYTES, mat[i] + PK_NROWS/8, PK_ROW_BYTES); + + return 0; +} + diff --git a/deps/mceliece/kem/mceliece6688128f/pk_gen.h b/deps/mceliece/kem/mceliece6688128f/pk_gen.h new file mode 100644 index 0000000..96b7e7b --- /dev/null +++ b/deps/mceliece/kem/mceliece6688128f/pk_gen.h @@ -0,0 +1,14 @@ +/* + This file is for public-key generation +*/ + +#ifndef PK_GEN_H +#define PK_GEN_H +#define pk_gen CRYPTO_NAMESPACE(pk_gen) + +#include "gf.h" + +int pk_gen(unsigned char *, unsigned char *, uint32_t *, int16_t *, uint64_t *); + +#endif + diff --git a/deps/mceliece/kem/mceliece6688128f/randombytes.h b/deps/mceliece/kem/mceliece6688128f/randombytes.h new file mode 100644 index 0000000..7e59351 --- /dev/null +++ b/deps/mceliece/kem/mceliece6688128f/randombytes.h @@ -0,0 +1 @@ +#include "../../mceliece_externals.h" diff --git a/deps/mceliece/kem/mceliece6688128f/root.c b/deps/mceliece/kem/mceliece6688128f/root.c new file mode 100644 index 0000000..1c1b634 --- /dev/null +++ b/deps/mceliece/kem/mceliece6688128f/root.c @@ -0,0 +1,38 @@ +/* + This file is for evaluating a polynomial at one or more field elements +*/ + +#include "root.h" +#include "params.h" +#include "gf.h" + +#include + +/* input: polynomial f and field element a */ +/* return f(a) */ +gf eval(gf *f, gf a) +{ + int i; + gf r; + + r = f[ SYS_T ]; + + for (i = SYS_T-1; i >= 0; i--) + { + r = gf_mul(r, a); + r = gf_add(r, f[i]); + } + + return r; +} + +/* input: polynomial f and list of field elements L */ +/* output: out = [ f(a) for a in L ] */ +void root(gf *out, gf *f, gf *L) +{ + int i; + + for (i = 0; i < SYS_N; i++) + out[i] = eval(f, L[i]); +} + diff --git a/deps/mceliece/kem/mceliece6688128f/root.h b/deps/mceliece/kem/mceliece6688128f/root.h new file mode 100644 index 0000000..42516e4 --- /dev/null +++ b/deps/mceliece/kem/mceliece6688128f/root.h @@ -0,0 +1,16 @@ +/* + This file is for evaluating a polynomial at one or more field elements +*/ + +#ifndef ROOT_H +#define ROOT_H +#define eval CRYPTO_NAMESPACE(eval) +#define root CRYPTO_NAMESPACE(root) + +#include "gf.h" + +gf eval(gf *, gf); +void root(gf *, gf *, gf *); + +#endif + diff --git a/deps/mceliece/kem/mceliece6688128f/sk_gen.c b/deps/mceliece/kem/mceliece6688128f/sk_gen.c new file mode 100644 index 0000000..340cc9a --- /dev/null +++ b/deps/mceliece/kem/mceliece6688128f/sk_gen.c @@ -0,0 +1,85 @@ +/* + This file is for secret-key generation +*/ + +#include "sk_gen.h" + +#include "randombytes.h" +#include "controlbits.h" +#include "params.h" +#include "util.h" +#include "gf.h" +#include "crypto_declassify.h" +#include "crypto_uint16.h" + +static inline crypto_uint16 gf_is_zero_declassify(gf t) +{ + crypto_uint16 mask = crypto_uint16_zero_mask(t); + crypto_declassify(&mask,sizeof mask); + return mask; +} + +/* input: f, element in GF((2^m)^t) */ +/* output: out, minimal polynomial of f */ +/* return: 0 for success and -1 for failure */ +int genpoly_gen(gf *out, gf *f) +{ + int i, j, k, c; + + gf mat[ SYS_T+1 ][ SYS_T ]; + gf mask, inv, t; + + // fill matrix + + mat[0][0] = 1; + + for (i = 1; i < SYS_T; i++) + mat[0][i] = 0; + + for (i = 0; i < SYS_T; i++) + mat[1][i] = f[i]; + + for (j = 2; j <= SYS_T; j++) + GF_mul(mat[j], mat[j-1], f); + + // gaussian + + for (j = 0; j < SYS_T; j++) + { + for (k = j + 1; k < SYS_T; k++) + { + mask = gf_iszero(mat[ j ][ j ]); + + for (c = j; c < SYS_T + 1; c++) + mat[ c ][ j ] ^= mat[ c ][ k ] & mask; + + } + + if ( gf_is_zero_declassify(mat[ j ][ j ]) ) // return if not systematic + { + return -1; + } + + inv = gf_inv(mat[j][j]); + + for (c = j; c < SYS_T + 1; c++) + mat[ c ][ j ] = gf_mul(mat[ c ][ j ], inv) ; + + for (k = 0; k < SYS_T; k++) + { + if (k != j) + { + t = mat[ j ][ k ]; + + for (c = j; c < SYS_T + 1; c++) + mat[ c ][ k ] ^= gf_mul(mat[ c ][ j ], t); + } + } + } + + for (i = 0; i < SYS_T; i++) + out[i] = mat[ SYS_T ][ i ]; + + return 0; +} + diff --git a/deps/mceliece/kem/mceliece6688128f/sk_gen.h b/deps/mceliece/kem/mceliece6688128f/sk_gen.h new file mode 100644 index 0000000..e319703 --- /dev/null +++ b/deps/mceliece/kem/mceliece6688128f/sk_gen.h @@ -0,0 +1,18 @@ +/* + This file is for secret-key generation +*/ + +#ifndef SK_GEN_H +#define SK_GEN_H +#define genpoly_gen CRYPTO_NAMESPACE(genpoly_gen) +#define perm_check CRYPTO_NAMESPACE(perm_check) + +#include "gf.h" + +#include + +int genpoly_gen(gf *, gf *); +int perm_check(uint32_t *); + +#endif + diff --git a/deps/mceliece/kem/mceliece6688128f/subroutines/crypto_declassify.h b/deps/mceliece/kem/mceliece6688128f/subroutines/crypto_declassify.h new file mode 100644 index 0000000..8d84209 --- /dev/null +++ b/deps/mceliece/kem/mceliece6688128f/subroutines/crypto_declassify.h @@ -0,0 +1,8 @@ +#ifndef crypto_declassify_h +#define crypto_declassify_h + +static void crypto_declassify(void *x,unsigned long long n) +{ +} + +#endif diff --git a/deps/mceliece/kem/mceliece6688128f/subroutines/crypto_int16.h b/deps/mceliece/kem/mceliece6688128f/subroutines/crypto_int16.h new file mode 100644 index 0000000..72bbf52 --- /dev/null +++ b/deps/mceliece/kem/mceliece6688128f/subroutines/crypto_int16.h @@ -0,0 +1,81 @@ +#ifndef crypto_int16_h +#define crypto_int16_h + +#include +typedef int16_t crypto_int16; + +static crypto_int16 crypto_int16_negative_mask(crypto_int16 crypto_int16_x) +{ + return crypto_int16_x >> 15; +} + +static crypto_int16 crypto_int16_nonzero_mask(crypto_int16 crypto_int16_x) +{ + return crypto_int16_negative_mask(crypto_int16_x) | crypto_int16_negative_mask(-crypto_int16_x); +} + +static crypto_int16 crypto_int16_zero_mask(crypto_int16 crypto_int16_x) +{ + return ~crypto_int16_nonzero_mask(crypto_int16_x); +} + +static crypto_int16 crypto_int16_positive_mask(crypto_int16 crypto_int16_x) +{ + crypto_int16 crypto_int16_z = -crypto_int16_x; + crypto_int16_z ^= crypto_int16_x & crypto_int16_z; + return crypto_int16_negative_mask(crypto_int16_z); +} + +static crypto_int16 crypto_int16_unequal_mask(crypto_int16 crypto_int16_x,crypto_int16 crypto_int16_y) +{ + crypto_int16 crypto_int16_xy = crypto_int16_x ^ crypto_int16_y; + return crypto_int16_nonzero_mask(crypto_int16_xy); +} + +static crypto_int16 crypto_int16_equal_mask(crypto_int16 crypto_int16_x,crypto_int16 crypto_int16_y) +{ + return ~crypto_int16_unequal_mask(crypto_int16_x,crypto_int16_y); +} + +static crypto_int16 crypto_int16_smaller_mask(crypto_int16 crypto_int16_x,crypto_int16 crypto_int16_y) +{ + crypto_int16 crypto_int16_xy = crypto_int16_x ^ crypto_int16_y; + crypto_int16 crypto_int16_z = crypto_int16_x - crypto_int16_y; + crypto_int16_z ^= crypto_int16_xy & (crypto_int16_z ^ crypto_int16_x); + return crypto_int16_negative_mask(crypto_int16_z); +} + +static crypto_int16 crypto_int16_min(crypto_int16 crypto_int16_x,crypto_int16 crypto_int16_y) +{ + crypto_int16 crypto_int16_xy = crypto_int16_y ^ crypto_int16_x; + crypto_int16 crypto_int16_z = crypto_int16_y - crypto_int16_x; + crypto_int16_z ^= crypto_int16_xy & (crypto_int16_z ^ crypto_int16_y); + crypto_int16_z = crypto_int16_negative_mask(crypto_int16_z); + crypto_int16_z &= crypto_int16_xy; + return crypto_int16_x ^ crypto_int16_z; +} + +static crypto_int16 crypto_int16_max(crypto_int16 crypto_int16_x,crypto_int16 crypto_int16_y) +{ + crypto_int16 crypto_int16_xy = crypto_int16_y ^ crypto_int16_x; + crypto_int16 crypto_int16_z = crypto_int16_y - crypto_int16_x; + crypto_int16_z ^= crypto_int16_xy & (crypto_int16_z ^ crypto_int16_y); + crypto_int16_z = crypto_int16_negative_mask(crypto_int16_z); + crypto_int16_z &= crypto_int16_xy; + return crypto_int16_y ^ crypto_int16_z; +} + +static void crypto_int16_minmax(crypto_int16 *crypto_int16_a,crypto_int16 *crypto_int16_b) +{ + crypto_int16 crypto_int16_x = *crypto_int16_a; + crypto_int16 crypto_int16_y = *crypto_int16_b; + crypto_int16 crypto_int16_xy = crypto_int16_y ^ crypto_int16_x; + crypto_int16 crypto_int16_z = crypto_int16_y - crypto_int16_x; + crypto_int16_z ^= crypto_int16_xy & (crypto_int16_z ^ crypto_int16_y); + crypto_int16_z = crypto_int16_negative_mask(crypto_int16_z); + crypto_int16_z &= crypto_int16_xy; + *crypto_int16_a = crypto_int16_x ^ crypto_int16_z; + *crypto_int16_b = crypto_int16_y ^ crypto_int16_z; +} + +#endif diff --git a/deps/mceliece/kem/mceliece6688128f/subroutines/crypto_int32.h b/deps/mceliece/kem/mceliece6688128f/subroutines/crypto_int32.h new file mode 100644 index 0000000..c22f735 --- /dev/null +++ b/deps/mceliece/kem/mceliece6688128f/subroutines/crypto_int32.h @@ -0,0 +1,81 @@ +#ifndef crypto_int32_h +#define crypto_int32_h + +#include +typedef int32_t crypto_int32; + +static crypto_int32 crypto_int32_negative_mask(crypto_int32 crypto_int32_x) +{ + return crypto_int32_x >> 31; +} + +static crypto_int32 crypto_int32_nonzero_mask(crypto_int32 crypto_int32_x) +{ + return crypto_int32_negative_mask(crypto_int32_x) | crypto_int32_negative_mask(-crypto_int32_x); +} + +static crypto_int32 crypto_int32_zero_mask(crypto_int32 crypto_int32_x) +{ + return ~crypto_int32_nonzero_mask(crypto_int32_x); +} + +static crypto_int32 crypto_int32_positive_mask(crypto_int32 crypto_int32_x) +{ + crypto_int32 crypto_int32_z = -crypto_int32_x; + crypto_int32_z ^= crypto_int32_x & crypto_int32_z; + return crypto_int32_negative_mask(crypto_int32_z); +} + +static crypto_int32 crypto_int32_unequal_mask(crypto_int32 crypto_int32_x,crypto_int32 crypto_int32_y) +{ + crypto_int32 crypto_int32_xy = crypto_int32_x ^ crypto_int32_y; + return crypto_int32_nonzero_mask(crypto_int32_xy); +} + +static crypto_int32 crypto_int32_equal_mask(crypto_int32 crypto_int32_x,crypto_int32 crypto_int32_y) +{ + return ~crypto_int32_unequal_mask(crypto_int32_x,crypto_int32_y); +} + +static crypto_int32 crypto_int32_smaller_mask(crypto_int32 crypto_int32_x,crypto_int32 crypto_int32_y) +{ + crypto_int32 crypto_int32_xy = crypto_int32_x ^ crypto_int32_y; + crypto_int32 crypto_int32_z = crypto_int32_x - crypto_int32_y; + crypto_int32_z ^= crypto_int32_xy & (crypto_int32_z ^ crypto_int32_x); + return crypto_int32_negative_mask(crypto_int32_z); +} + +static crypto_int32 crypto_int32_min(crypto_int32 crypto_int32_x,crypto_int32 crypto_int32_y) +{ + crypto_int32 crypto_int32_xy = crypto_int32_y ^ crypto_int32_x; + crypto_int32 crypto_int32_z = crypto_int32_y - crypto_int32_x; + crypto_int32_z ^= crypto_int32_xy & (crypto_int32_z ^ crypto_int32_y); + crypto_int32_z = crypto_int32_negative_mask(crypto_int32_z); + crypto_int32_z &= crypto_int32_xy; + return crypto_int32_x ^ crypto_int32_z; +} + +static crypto_int32 crypto_int32_max(crypto_int32 crypto_int32_x,crypto_int32 crypto_int32_y) +{ + crypto_int32 crypto_int32_xy = crypto_int32_y ^ crypto_int32_x; + crypto_int32 crypto_int32_z = crypto_int32_y - crypto_int32_x; + crypto_int32_z ^= crypto_int32_xy & (crypto_int32_z ^ crypto_int32_y); + crypto_int32_z = crypto_int32_negative_mask(crypto_int32_z); + crypto_int32_z &= crypto_int32_xy; + return crypto_int32_y ^ crypto_int32_z; +} + +static void crypto_int32_minmax(crypto_int32 *crypto_int32_a,crypto_int32 *crypto_int32_b) +{ + crypto_int32 crypto_int32_x = *crypto_int32_a; + crypto_int32 crypto_int32_y = *crypto_int32_b; + crypto_int32 crypto_int32_xy = crypto_int32_y ^ crypto_int32_x; + crypto_int32 crypto_int32_z = crypto_int32_y - crypto_int32_x; + crypto_int32_z ^= crypto_int32_xy & (crypto_int32_z ^ crypto_int32_y); + crypto_int32_z = crypto_int32_negative_mask(crypto_int32_z); + crypto_int32_z &= crypto_int32_xy; + *crypto_int32_a = crypto_int32_x ^ crypto_int32_z; + *crypto_int32_b = crypto_int32_y ^ crypto_int32_z; +} + +#endif diff --git a/deps/mceliece/kem/mceliece6688128f/subroutines/crypto_uint16.h b/deps/mceliece/kem/mceliece6688128f/subroutines/crypto_uint16.h new file mode 100644 index 0000000..f0ebbbf --- /dev/null +++ b/deps/mceliece/kem/mceliece6688128f/subroutines/crypto_uint16.h @@ -0,0 +1,76 @@ +#ifndef crypto_uint16_h +#define crypto_uint16_h + +#include +typedef uint16_t crypto_uint16; + +typedef int16_t crypto_uint16_signed; + +static crypto_uint16_signed crypto_uint16_signed_negative_mask(crypto_uint16_signed crypto_uint16_signed_x) +{ + return crypto_uint16_signed_x >> 15; +} + +static crypto_uint16 crypto_uint16_nonzero_mask(crypto_uint16 crypto_uint16_x) +{ + return crypto_uint16_signed_negative_mask(crypto_uint16_x) | crypto_uint16_signed_negative_mask(-crypto_uint16_x); +} + +static crypto_uint16 crypto_uint16_zero_mask(crypto_uint16 crypto_uint16_x) +{ + return ~crypto_uint16_nonzero_mask(crypto_uint16_x); +} + +static crypto_uint16 crypto_uint16_unequal_mask(crypto_uint16 crypto_uint16_x,crypto_uint16 crypto_uint16_y) +{ + crypto_uint16 crypto_uint16_xy = crypto_uint16_x ^ crypto_uint16_y; + return crypto_uint16_nonzero_mask(crypto_uint16_xy); +} + +static crypto_uint16 crypto_uint16_equal_mask(crypto_uint16 crypto_uint16_x,crypto_uint16 crypto_uint16_y) +{ + return ~crypto_uint16_unequal_mask(crypto_uint16_x,crypto_uint16_y); +} + +static crypto_uint16 crypto_uint16_smaller_mask(crypto_uint16 crypto_uint16_x,crypto_uint16 crypto_uint16_y) +{ + crypto_uint16 crypto_uint16_xy = crypto_uint16_x ^ crypto_uint16_y; + crypto_uint16 crypto_uint16_z = crypto_uint16_x - crypto_uint16_y; + crypto_uint16_z ^= crypto_uint16_xy & (crypto_uint16_z ^ crypto_uint16_x ^ (((crypto_uint16) 1) << 15)); + return crypto_uint16_signed_negative_mask(crypto_uint16_z); +} + +static crypto_uint16 crypto_uint16_min(crypto_uint16 crypto_uint16_x,crypto_uint16 crypto_uint16_y) +{ + crypto_uint16 crypto_uint16_xy = crypto_uint16_y ^ crypto_uint16_x; + crypto_uint16 crypto_uint16_z = crypto_uint16_y - crypto_uint16_x; + crypto_uint16_z ^= crypto_uint16_xy & (crypto_uint16_z ^ crypto_uint16_y ^ (((crypto_uint16) 1) << 15)); + crypto_uint16_z = crypto_uint16_signed_negative_mask(crypto_uint16_z); + crypto_uint16_z &= crypto_uint16_xy; + return crypto_uint16_x ^ crypto_uint16_z; +} + +static crypto_uint16 crypto_uint16_max(crypto_uint16 crypto_uint16_x,crypto_uint16 crypto_uint16_y) +{ + crypto_uint16 crypto_uint16_xy = crypto_uint16_y ^ crypto_uint16_x; + crypto_uint16 crypto_uint16_z = crypto_uint16_y - crypto_uint16_x; + crypto_uint16_z ^= crypto_uint16_xy & (crypto_uint16_z ^ crypto_uint16_y ^ (((crypto_uint16) 1) << 15)); + crypto_uint16_z = crypto_uint16_signed_negative_mask(crypto_uint16_z); + crypto_uint16_z &= crypto_uint16_xy; + return crypto_uint16_y ^ crypto_uint16_z; +} + +static void crypto_uint16_minmax(crypto_uint16 *crypto_uint16_a,crypto_uint16 *crypto_uint16_b) +{ + crypto_uint16 crypto_uint16_x = *crypto_uint16_a; + crypto_uint16 crypto_uint16_y = *crypto_uint16_b; + crypto_uint16 crypto_uint16_xy = crypto_uint16_y ^ crypto_uint16_x; + crypto_uint16 crypto_uint16_z = crypto_uint16_y - crypto_uint16_x; + crypto_uint16_z ^= crypto_uint16_xy & (crypto_uint16_z ^ crypto_uint16_y ^ (((crypto_uint16) 1) << 15)); + crypto_uint16_z = crypto_uint16_signed_negative_mask(crypto_uint16_z); + crypto_uint16_z &= crypto_uint16_xy; + *crypto_uint16_a = crypto_uint16_x ^ crypto_uint16_z; + *crypto_uint16_b = crypto_uint16_y ^ crypto_uint16_z; +} + +#endif diff --git a/deps/mceliece/kem/mceliece6688128f/subroutines/crypto_uint32.h b/deps/mceliece/kem/mceliece6688128f/subroutines/crypto_uint32.h new file mode 100644 index 0000000..3f39d62 --- /dev/null +++ b/deps/mceliece/kem/mceliece6688128f/subroutines/crypto_uint32.h @@ -0,0 +1,76 @@ +#ifndef crypto_uint32_h +#define crypto_uint32_h + +#include +typedef uint32_t crypto_uint32; + +typedef int32_t crypto_uint32_signed; + +static crypto_uint32_signed crypto_uint32_signed_negative_mask(crypto_uint32_signed crypto_uint32_signed_x) +{ + return crypto_uint32_signed_x >> 31; +} + +static crypto_uint32 crypto_uint32_nonzero_mask(crypto_uint32 crypto_uint32_x) +{ + return crypto_uint32_signed_negative_mask(crypto_uint32_x) | crypto_uint32_signed_negative_mask(-crypto_uint32_x); +} + +static crypto_uint32 crypto_uint32_zero_mask(crypto_uint32 crypto_uint32_x) +{ + return ~crypto_uint32_nonzero_mask(crypto_uint32_x); +} + +static crypto_uint32 crypto_uint32_unequal_mask(crypto_uint32 crypto_uint32_x,crypto_uint32 crypto_uint32_y) +{ + crypto_uint32 crypto_uint32_xy = crypto_uint32_x ^ crypto_uint32_y; + return crypto_uint32_nonzero_mask(crypto_uint32_xy); +} + +static crypto_uint32 crypto_uint32_equal_mask(crypto_uint32 crypto_uint32_x,crypto_uint32 crypto_uint32_y) +{ + return ~crypto_uint32_unequal_mask(crypto_uint32_x,crypto_uint32_y); +} + +static crypto_uint32 crypto_uint32_smaller_mask(crypto_uint32 crypto_uint32_x,crypto_uint32 crypto_uint32_y) +{ + crypto_uint32 crypto_uint32_xy = crypto_uint32_x ^ crypto_uint32_y; + crypto_uint32 crypto_uint32_z = crypto_uint32_x - crypto_uint32_y; + crypto_uint32_z ^= crypto_uint32_xy & (crypto_uint32_z ^ crypto_uint32_x ^ (((crypto_uint32) 1) << 31)); + return crypto_uint32_signed_negative_mask(crypto_uint32_z); +} + +static crypto_uint32 crypto_uint32_min(crypto_uint32 crypto_uint32_x,crypto_uint32 crypto_uint32_y) +{ + crypto_uint32 crypto_uint32_xy = crypto_uint32_y ^ crypto_uint32_x; + crypto_uint32 crypto_uint32_z = crypto_uint32_y - crypto_uint32_x; + crypto_uint32_z ^= crypto_uint32_xy & (crypto_uint32_z ^ crypto_uint32_y ^ (((crypto_uint32) 1) << 31)); + crypto_uint32_z = crypto_uint32_signed_negative_mask(crypto_uint32_z); + crypto_uint32_z &= crypto_uint32_xy; + return crypto_uint32_x ^ crypto_uint32_z; +} + +static crypto_uint32 crypto_uint32_max(crypto_uint32 crypto_uint32_x,crypto_uint32 crypto_uint32_y) +{ + crypto_uint32 crypto_uint32_xy = crypto_uint32_y ^ crypto_uint32_x; + crypto_uint32 crypto_uint32_z = crypto_uint32_y - crypto_uint32_x; + crypto_uint32_z ^= crypto_uint32_xy & (crypto_uint32_z ^ crypto_uint32_y ^ (((crypto_uint32) 1) << 31)); + crypto_uint32_z = crypto_uint32_signed_negative_mask(crypto_uint32_z); + crypto_uint32_z &= crypto_uint32_xy; + return crypto_uint32_y ^ crypto_uint32_z; +} + +static void crypto_uint32_minmax(crypto_uint32 *crypto_uint32_a,crypto_uint32 *crypto_uint32_b) +{ + crypto_uint32 crypto_uint32_x = *crypto_uint32_a; + crypto_uint32 crypto_uint32_y = *crypto_uint32_b; + crypto_uint32 crypto_uint32_xy = crypto_uint32_y ^ crypto_uint32_x; + crypto_uint32 crypto_uint32_z = crypto_uint32_y - crypto_uint32_x; + crypto_uint32_z ^= crypto_uint32_xy & (crypto_uint32_z ^ crypto_uint32_y ^ (((crypto_uint32) 1) << 31)); + crypto_uint32_z = crypto_uint32_signed_negative_mask(crypto_uint32_z); + crypto_uint32_z &= crypto_uint32_xy; + *crypto_uint32_a = crypto_uint32_x ^ crypto_uint32_z; + *crypto_uint32_b = crypto_uint32_y ^ crypto_uint32_z; +} + +#endif diff --git a/deps/mceliece/kem/mceliece6688128f/subroutines/crypto_uint64.h b/deps/mceliece/kem/mceliece6688128f/subroutines/crypto_uint64.h new file mode 100644 index 0000000..42e2be9 --- /dev/null +++ b/deps/mceliece/kem/mceliece6688128f/subroutines/crypto_uint64.h @@ -0,0 +1,76 @@ +#ifndef crypto_uint64_h +#define crypto_uint64_h + +#include +typedef uint64_t crypto_uint64; + +typedef int64_t crypto_uint64_signed; + +static crypto_uint64_signed crypto_uint64_signed_negative_mask(crypto_uint64_signed crypto_uint64_signed_x) +{ + return crypto_uint64_signed_x >> 63; +} + +static crypto_uint64 crypto_uint64_nonzero_mask(crypto_uint64 crypto_uint64_x) +{ + return crypto_uint64_signed_negative_mask(crypto_uint64_x) | crypto_uint64_signed_negative_mask(-crypto_uint64_x); +} + +static crypto_uint64 crypto_uint64_zero_mask(crypto_uint64 crypto_uint64_x) +{ + return ~crypto_uint64_nonzero_mask(crypto_uint64_x); +} + +static crypto_uint64 crypto_uint64_unequal_mask(crypto_uint64 crypto_uint64_x,crypto_uint64 crypto_uint64_y) +{ + crypto_uint64 crypto_uint64_xy = crypto_uint64_x ^ crypto_uint64_y; + return crypto_uint64_nonzero_mask(crypto_uint64_xy); +} + +static crypto_uint64 crypto_uint64_equal_mask(crypto_uint64 crypto_uint64_x,crypto_uint64 crypto_uint64_y) +{ + return ~crypto_uint64_unequal_mask(crypto_uint64_x,crypto_uint64_y); +} + +static crypto_uint64 crypto_uint64_smaller_mask(crypto_uint64 crypto_uint64_x,crypto_uint64 crypto_uint64_y) +{ + crypto_uint64 crypto_uint64_xy = crypto_uint64_x ^ crypto_uint64_y; + crypto_uint64 crypto_uint64_z = crypto_uint64_x - crypto_uint64_y; + crypto_uint64_z ^= crypto_uint64_xy & (crypto_uint64_z ^ crypto_uint64_x ^ (((crypto_uint64) 1) << 63)); + return crypto_uint64_signed_negative_mask(crypto_uint64_z); +} + +static crypto_uint64 crypto_uint64_min(crypto_uint64 crypto_uint64_x,crypto_uint64 crypto_uint64_y) +{ + crypto_uint64 crypto_uint64_xy = crypto_uint64_y ^ crypto_uint64_x; + crypto_uint64 crypto_uint64_z = crypto_uint64_y - crypto_uint64_x; + crypto_uint64_z ^= crypto_uint64_xy & (crypto_uint64_z ^ crypto_uint64_y ^ (((crypto_uint64) 1) << 63)); + crypto_uint64_z = crypto_uint64_signed_negative_mask(crypto_uint64_z); + crypto_uint64_z &= crypto_uint64_xy; + return crypto_uint64_x ^ crypto_uint64_z; +} + +static crypto_uint64 crypto_uint64_max(crypto_uint64 crypto_uint64_x,crypto_uint64 crypto_uint64_y) +{ + crypto_uint64 crypto_uint64_xy = crypto_uint64_y ^ crypto_uint64_x; + crypto_uint64 crypto_uint64_z = crypto_uint64_y - crypto_uint64_x; + crypto_uint64_z ^= crypto_uint64_xy & (crypto_uint64_z ^ crypto_uint64_y ^ (((crypto_uint64) 1) << 63)); + crypto_uint64_z = crypto_uint64_signed_negative_mask(crypto_uint64_z); + crypto_uint64_z &= crypto_uint64_xy; + return crypto_uint64_y ^ crypto_uint64_z; +} + +static void crypto_uint64_minmax(crypto_uint64 *crypto_uint64_a,crypto_uint64 *crypto_uint64_b) +{ + crypto_uint64 crypto_uint64_x = *crypto_uint64_a; + crypto_uint64 crypto_uint64_y = *crypto_uint64_b; + crypto_uint64 crypto_uint64_xy = crypto_uint64_y ^ crypto_uint64_x; + crypto_uint64 crypto_uint64_z = crypto_uint64_y - crypto_uint64_x; + crypto_uint64_z ^= crypto_uint64_xy & (crypto_uint64_z ^ crypto_uint64_y ^ (((crypto_uint64) 1) << 63)); + crypto_uint64_z = crypto_uint64_signed_negative_mask(crypto_uint64_z); + crypto_uint64_z &= crypto_uint64_xy; + *crypto_uint64_a = crypto_uint64_x ^ crypto_uint64_z; + *crypto_uint64_b = crypto_uint64_y ^ crypto_uint64_z; +} + +#endif diff --git a/deps/mceliece/kem/mceliece6688128f/synd.c b/deps/mceliece/kem/mceliece6688128f/synd.c new file mode 100644 index 0000000..c945647 --- /dev/null +++ b/deps/mceliece/kem/mceliece6688128f/synd.c @@ -0,0 +1,36 @@ +/* + This file is for syndrome computation +*/ + +#include "synd.h" + +#include "params.h" +#include "root.h" + +#include + +/* input: Goppa polynomial f, support L, received word r */ +/* output: out, the syndrome of length 2t */ +void synd(gf *out, gf *f, gf *L, unsigned char *r) +{ + int i, j; + gf e, e_inv, c; + + for (j = 0; j < 2*SYS_T; j++) + out[j] = 0; + + for (i = 0; i < SYS_N; i++) + { + c = (r[i/8] >> (i%8)) & 1; + + e = eval(f, L[i]); + e_inv = gf_inv(gf_mul(e,e)); + + for (j = 0; j < 2*SYS_T; j++) + { + out[j] = gf_add(out[j], gf_mul(e_inv, c)); + e_inv = gf_mul(e_inv, L[i]); + } + } +} + diff --git a/deps/mceliece/kem/mceliece6688128f/synd.h b/deps/mceliece/kem/mceliece6688128f/synd.h new file mode 100644 index 0000000..9331406 --- /dev/null +++ b/deps/mceliece/kem/mceliece6688128f/synd.h @@ -0,0 +1,14 @@ +/* + This file is for syndrome computation +*/ + +#ifndef SYND_H +#define SYND_H +#define synd CRYPTO_NAMESPACE(synd) + +#include "gf.h" + +void synd(gf *, gf *, gf *, unsigned char *); + +#endif + diff --git a/deps/mceliece/kem/mceliece6688128f/transpose.c b/deps/mceliece/kem/mceliece6688128f/transpose.c new file mode 100644 index 0000000..0da2bc5 --- /dev/null +++ b/deps/mceliece/kem/mceliece6688128f/transpose.c @@ -0,0 +1,43 @@ +/* + This file is for matrix transposition +*/ + +#include "transpose.h" + +#include + +/* input: in, a 64x64 matrix over GF(2) */ +/* output: out, transpose of in */ +void transpose_64x64(uint64_t * out, uint64_t * in) +{ + int i, j, s, d; + + uint64_t x, y; + uint64_t masks[6][2] = { + {0x5555555555555555, 0xAAAAAAAAAAAAAAAA}, + {0x3333333333333333, 0xCCCCCCCCCCCCCCCC}, + {0x0F0F0F0F0F0F0F0F, 0xF0F0F0F0F0F0F0F0}, + {0x00FF00FF00FF00FF, 0xFF00FF00FF00FF00}, + {0x0000FFFF0000FFFF, 0xFFFF0000FFFF0000}, + {0x00000000FFFFFFFF, 0xFFFFFFFF00000000} + }; + + for (i = 0; i < 64; i++) + out[i] = in[i]; + + for (d = 5; d >= 0; d--) + { + s = 1 << d; + + for (i = 0; i < 64; i += s*2) + for (j = i; j < i+s; j++) + { + x = (out[j] & masks[d][0]) | ((out[j+s] & masks[d][0]) << s); + y = ((out[j] & masks[d][1]) >> s) | (out[j+s] & masks[d][1]); + + out[j+0] = x; + out[j+s] = y; + } + } +} + diff --git a/deps/mceliece/kem/mceliece6688128f/transpose.h b/deps/mceliece/kem/mceliece6688128f/transpose.h new file mode 100644 index 0000000..31e5b96 --- /dev/null +++ b/deps/mceliece/kem/mceliece6688128f/transpose.h @@ -0,0 +1,14 @@ +/* + This file is for matrix transposition +*/ + +#ifndef TRANSPOSE_H +#define TRANSPOSE_H +#define transpose_64x64 CRYPTO_NAMESPACE(transpose_64x64) + +#include + +void transpose_64x64(uint64_t *, uint64_t *); + +#endif + diff --git a/deps/mceliece/kem/mceliece6688128f/uint64_sort.h b/deps/mceliece/kem/mceliece6688128f/uint64_sort.h new file mode 100644 index 0000000..2fb100c --- /dev/null +++ b/deps/mceliece/kem/mceliece6688128f/uint64_sort.h @@ -0,0 +1,45 @@ +#ifndef uint64_sort_h +#define uint64_sort_h + +#define int64_sort CRYPTO_NAMESPACE(int64_sort) + +#include + +#define uint64_MINMAX(a,b) \ +do { \ + uint64_t c = b - a; \ + c >>= 63; \ + c = -c; \ + c &= a ^ b; \ + a ^= c; \ + b ^= c; \ +} while(0) + +static void uint64_sort(uint64_t *x,long long n) +{ + long long top,p,q,r,i; + + if (n < 2) return; + top = 1; + while (top < n - top) top += top; + + for (p = top;p > 0;p >>= 1) { + for (i = 0;i < n - p;++i) + if (!(i & p)) + uint64_MINMAX(x[i],x[i+p]); + i = 0; + for (q = top;q > p;q >>= 1) { + for (;i < n - q;++i) { + if (!(i & p)) { + uint64_t a = x[i + p]; + for (r = q;r > p;r >>= 1) + uint64_MINMAX(a,x[i+r]); + x[i + p] = a; + } + } + } + } +} + +#endif + diff --git a/deps/mceliece/kem/mceliece6688128f/util.c b/deps/mceliece/kem/mceliece6688128f/util.c new file mode 100644 index 0000000..1679168 --- /dev/null +++ b/deps/mceliece/kem/mceliece6688128f/util.c @@ -0,0 +1,75 @@ +/* + This file is for loading/storing data in a little-endian fashion +*/ + +#include "util.h" + +#include "params.h" + +void store_gf(unsigned char *dest, gf a) +{ + dest[0] = a & 0xFF; + dest[1] = a >> 8; +} + +uint16_t load_gf(const unsigned char *src) +{ + uint16_t a; + + a = src[1]; + a <<= 8; + a |= src[0]; + + return a & GFMASK; +} + +uint32_t load4(const unsigned char * in) +{ + int i; + uint32_t ret = in[3]; + + for (i = 2; i >= 0; i--) + { + ret <<= 8; + ret |= in[i]; + } + + return ret; +} + +void store8(unsigned char *out, uint64_t in) +{ + out[0] = (in >> 0x00) & 0xFF; + out[1] = (in >> 0x08) & 0xFF; + out[2] = (in >> 0x10) & 0xFF; + out[3] = (in >> 0x18) & 0xFF; + out[4] = (in >> 0x20) & 0xFF; + out[5] = (in >> 0x28) & 0xFF; + out[6] = (in >> 0x30) & 0xFF; + out[7] = (in >> 0x38) & 0xFF; +} + +uint64_t load8(const unsigned char * in) +{ + int i; + uint64_t ret = in[7]; + + for (i = 6; i >= 0; i--) + { + ret <<= 8; + ret |= in[i]; + } + + return ret; +} + +gf bitrev(gf a) +{ + a = ((a & 0x00FF) << 8) | ((a & 0xFF00) >> 8); + a = ((a & 0x0F0F) << 4) | ((a & 0xF0F0) >> 4); + a = ((a & 0x3333) << 2) | ((a & 0xCCCC) >> 2); + a = ((a & 0x5555) << 1) | ((a & 0xAAAA) >> 1); + + return a >> 3; +} + diff --git a/deps/mceliece/kem/mceliece6688128f/util.h b/deps/mceliece/kem/mceliece6688128f/util.h new file mode 100644 index 0000000..d610bee --- /dev/null +++ b/deps/mceliece/kem/mceliece6688128f/util.h @@ -0,0 +1,27 @@ +/* + This file is for loading/storing data in a little-endian fashion +*/ + +#ifndef UTIL_H +#define UTIL_H +#define bitrev CRYPTO_NAMESPACE(bitrev) +#define load4 CRYPTO_NAMESPACE(load4) +#define load8 CRYPTO_NAMESPACE(load8) +#define load_gf CRYPTO_NAMESPACE(load_gf) +#define store8 CRYPTO_NAMESPACE(store8) +#define store_gf CRYPTO_NAMESPACE(store_gf) + +#include "gf.h" +#include + +void store_gf(unsigned char *, gf); +uint16_t load_gf(const unsigned char *); +uint32_t load4(const unsigned char *); + +void store8(unsigned char *, uint64_t ); +uint64_t load8(const unsigned char *); + +gf bitrev(gf); + +#endif + diff --git a/deps/mceliece/kem/mceliece6960119/benes.c b/deps/mceliece/kem/mceliece6960119/benes.c new file mode 100644 index 0000000..3b4e710 --- /dev/null +++ b/deps/mceliece/kem/mceliece6960119/benes.c @@ -0,0 +1,181 @@ +/* + This file is for Benes network related functions + + For the implementation strategy, see + https://eprint.iacr.org/2017/793.pdf +*/ + +#include "util.h" +#include "transpose.h" +#include "params.h" +#include "benes.h" + +/* middle layers of the benes network */ +static void layer_in(uint64_t data[2][64], uint64_t * bits, int lgs) +{ + int i, j, s; + + uint64_t d; + + s = 1 << lgs; + + for (i = 0; i < 64; i += s*2) + for (j = i; j < i+s; j++) + { + + d = (data[0][j+0] ^ data[0][j+s]); + d &= (*bits++); + data[0][j+0] ^= d; + data[0][j+s] ^= d; + + d = (data[1][j+0] ^ data[1][j+s]); + d &= (*bits++); + data[1][j+0] ^= d; + data[1][j+s] ^= d; + } +} + +/* first and last layers of the benes network */ +static void layer_ex(uint64_t * data, uint64_t * bits, int lgs) +{ + int i, j, s; + + uint64_t d; + + s = 1 << lgs; + + for (i = 0; i < 128; i += s*2) + for (j = i; j < i+s; j++) + { + + d = (data[j+0] ^ data[j+s]); + d &= (*bits++); + data[j+0] ^= d; + data[j+s] ^= d; + } +} + +/* input: r, sequence of bits to be permuted */ +/* bits, condition bits of the Benes network */ +/* rev, 0 for normal application; !0 for inverse */ +/* output: r, permuted bits */ +void apply_benes(unsigned char * r, const unsigned char * bits, int rev) +{ + int i, iter, inc; + + unsigned char *r_ptr = r; + const unsigned char *bits_ptr; + + uint64_t r_int_v[2][64]; + uint64_t r_int_h[2][64]; + uint64_t b_int_v[64]; + uint64_t b_int_h[64]; + + // + + if (rev) { bits_ptr = bits + 12288; inc = -1024; } + else { bits_ptr = bits; inc = 0; } + + for (i = 0; i < 64; i++) + { + r_int_v[0][i] = load8(r_ptr + i*16 + 0); + r_int_v[1][i] = load8(r_ptr + i*16 + 8); + } + + transpose_64x64(r_int_h[0], r_int_v[0]); + transpose_64x64(r_int_h[1], r_int_v[1]); + + for (iter = 0; iter <= 6; iter++) + { + for (i = 0; i < 64; i++) + { + b_int_v[i] = load8(bits_ptr); bits_ptr += 8; + } + + bits_ptr += inc; + + transpose_64x64(b_int_h, b_int_v); + + layer_ex(r_int_h[0], b_int_h, iter); + } + + transpose_64x64(r_int_v[0], r_int_h[0]); + transpose_64x64(r_int_v[1], r_int_h[1]); + + for (iter = 0; iter <= 5; iter++) + { + for (i = 0; i < 64; i++) { b_int_v[i] = load8(bits_ptr); bits_ptr += 8; } + bits_ptr += inc; + + layer_in(r_int_v, b_int_v, iter); + } + + for (iter = 4; iter >= 0; iter--) + { + for (i = 0; i < 64; i++) { b_int_v[i] = load8(bits_ptr); bits_ptr += 8; } + bits_ptr += inc; + + layer_in(r_int_v, b_int_v, iter); + } + + transpose_64x64(r_int_h[0], r_int_v[0]); + transpose_64x64(r_int_h[1], r_int_v[1]); + + for (iter = 6; iter >= 0; iter--) + { + for (i = 0; i < 64; i++) + { + b_int_v[i] = load8(bits_ptr); bits_ptr += 8; + } + + bits_ptr += inc; + + transpose_64x64(b_int_h, b_int_v); + + layer_ex(r_int_h[0], b_int_h, iter); + } + + transpose_64x64(r_int_v[0], r_int_h[0]); + transpose_64x64(r_int_v[1], r_int_h[1]); + + for (i = 0; i < 64; i++) + { + store8(r_ptr + i*16 + 0, r_int_v[0][i]); + store8(r_ptr + i*16 + 8, r_int_v[1][i]); + } +} + +/* input: condition bits c */ +/* output: support s */ +void support_gen(gf * s, const unsigned char *c) +{ + gf a; + int i, j; + unsigned char L[ GFBITS ][ (1 << GFBITS)/8 ]; + + for (i = 0; i < GFBITS; i++) + for (j = 0; j < (1 << GFBITS)/8; j++) + L[i][j] = 0; + + for (i = 0; i < (1 << GFBITS); i++) + { + a = bitrev((gf) i); + + for (j = 0; j < GFBITS; j++) + L[j][ i/8 ] |= ((a >> j) & 1) << (i%8); + } + + for (j = 0; j < GFBITS; j++) + apply_benes(L[j], c, 0); + + for (i = 0; i < SYS_N; i++) + { + s[i] = 0; + for (j = GFBITS-1; j >= 0; j--) + { + s[i] <<= 1; + s[i] |= (L[j][i/8] >> (i%8)) & 1; + } + } +} + diff --git a/deps/mceliece/kem/mceliece6960119/benes.h b/deps/mceliece/kem/mceliece6960119/benes.h new file mode 100644 index 0000000..c2ef35a --- /dev/null +++ b/deps/mceliece/kem/mceliece6960119/benes.h @@ -0,0 +1,16 @@ +/* + This file is for Benes network related functions +*/ + +#ifndef BENES_H +#define BENES_H +#define apply_benes CRYPTO_NAMESPACE(apply_benes) +#define support_gen CRYPTO_NAMESPACE(support_gen) + +#include "gf.h" + +void apply_benes(unsigned char *, const unsigned char *, int); +void support_gen(gf *, const unsigned char *); + +#endif + diff --git a/deps/mceliece/kem/mceliece6960119/bm.c b/deps/mceliece/kem/mceliece6960119/bm.c new file mode 100644 index 0000000..056a734 --- /dev/null +++ b/deps/mceliece/kem/mceliece6960119/bm.c @@ -0,0 +1,72 @@ +/* + This file is for the Berlekamp-Massey algorithm + see http://crypto.stanford.edu/~mironov/cs359/massey.pdf +*/ + +#include "params.h" +#include "gf.h" +#include "bm.h" + +#define min(a, b) ((a < b) ? a : b) + +/* the Berlekamp-Massey algorithm */ +/* input: s, sequence of field elements */ +/* output: out, minimal polynomial of s */ +void bm(gf *out, gf *s) +{ + int i; + + uint16_t N = 0; + uint16_t L = 0; + uint16_t mle; + uint16_t mne; + + gf T[ SYS_T+1 ]; + gf C[ SYS_T+1 ]; + gf B[ SYS_T+1 ]; + + gf b = 1, d, f; + + // + + for (i = 0; i < SYS_T+1; i++) + C[i] = B[i] = 0; + + B[1] = C[0] = 1; + + // + + for (N = 0; N < 2 * SYS_T; N++) + { + d = 0; + + for (i = 0; i <= min(N, SYS_T); i++) + d ^= gf_mul(C[i], s[ N-i]); + + mne = d; mne -= 1; mne >>= 15; mne -= 1; + mle = N; mle -= 2*L; mle >>= 15; mle -= 1; + mle &= mne; + + for (i = 0; i <= SYS_T; i++) + T[i] = C[i]; + + f = gf_frac(b, d); + + for (i = 0; i <= SYS_T; i++) + C[i] ^= gf_mul(f, B[i]) & mne; + + L = (L & ~mle) | ((N+1-L) & mle); + + for (i = 0; i <= SYS_T; i++) + B[i] = (B[i] & ~mle) | (T[i] & mle); + + b = (b & ~mle) | (d & mle); + + for (i = SYS_T; i >= 1; i--) B[i] = B[i-1]; + B[0] = 0; + } + + for (i = 0; i <= SYS_T; i++) + out[i] = C[ SYS_T-i ]; +} + diff --git a/deps/mceliece/kem/mceliece6960119/bm.h b/deps/mceliece/kem/mceliece6960119/bm.h new file mode 100644 index 0000000..73d5c6c --- /dev/null +++ b/deps/mceliece/kem/mceliece6960119/bm.h @@ -0,0 +1,13 @@ +/* + This file is for the Berlekamp-Massey algorithm + see http://crypto.stanford.edu/~mironov/cs359/massey.pdf +*/ + +#ifndef BM_H +#define BM_H +#define bm CRYPTO_NAMESPACE(bm) + +void bm(gf *, gf *); + +#endif + diff --git a/deps/mceliece/kem/mceliece6960119/controlbits.c b/deps/mceliece/kem/mceliece6960119/controlbits.c new file mode 100644 index 0000000..db9db9c --- /dev/null +++ b/deps/mceliece/kem/mceliece6960119/controlbits.c @@ -0,0 +1,220 @@ +/* This file is for implementing the Nassimi-Sahni algorithm */ +/* See David Nassimi, Sartaj Sahni "Parallel algorithms to set up the Benes permutationnetwork" */ +/* See also https://cr.yp.to/papers/controlbits-20200923.pdf */ + +#include +#include "crypto_declassify.h" +#include "controlbits.h" +#include "int32_sort.h" +typedef int16_t int16; +typedef int32_t int32; +#include "crypto_int32.h" +#define int32_min crypto_int32_min +#include "crypto_int16.h" + +/* parameters: 1 <= w <= 14; n = 2^w */ +/* input: permutation pi of {0,1,...,n-1} */ +/* output: (2m-1)n/2 control bits at positions pos,pos+step,... */ +/* output position pos is by definition 1&(out[pos/8]>>(pos&7)) */ +/* caller must 0-initialize positions first */ +/* temp must have space for int32[2*n] */ +static void cbrecursion(unsigned char *out,long long pos,long long step,const int16 *pi,long long w,long long n,int32 *temp) +{ +#define A temp +#define B (temp+n) +#define q ((int16 *) (temp+n+n/4)) +/* q can start anywhere between temp+n and temp+n/2 */ + + long long x,i,j,k; + + if (w == 1) { + out[pos>>3] ^= pi[0]<<(pos&7); + return; + } + + for (x = 0;x < n;++x) A[x] = ((pi[x]^1)<<16)|pi[x^1]; + int32_sort(A,n); /* A = (id<<16)+pibar */ + + for (x = 0;x < n;++x) { + int32 Ax = A[x]; + int32 px = Ax&0xffff; + int32 cx = int32_min(px,x); + B[x] = (px<<16)|cx; + } + /* B = (p<<16)+c */ + + for (x = 0;x < n;++x) A[x] = (A[x]<<16)|x; /* A = (pibar<<16)+id */ + int32_sort(A,n); /* A = (id<<16)+pibar^-1 */ + + for (x = 0;x < n;++x) A[x] = (A[x]<<16)+(B[x]>>16); /* A = (pibar^(-1)<<16)+pibar */ + int32_sort(A,n); /* A = (id<<16)+pibar^2 */ + + if (w <= 10) { + for (x = 0;x < n;++x) B[x] = ((A[x]&0xffff)<<10)|(B[x]&0x3ff); + + for (i = 1;i < w-1;++i) { + /* B = (p<<10)+c */ + + for (x = 0;x < n;++x) A[x] = ((B[x]&~0x3ff)<<6)|x; /* A = (p<<16)+id */ + int32_sort(A,n); /* A = (id<<16)+p^{-1} */ + + for (x = 0;x < n;++x) A[x] = (A[x]<<20)|B[x]; /* A = (p^{-1}<<20)+(p<<10)+c */ + int32_sort(A,n); /* A = (id<<20)+(pp<<10)+cp */ + + for (x = 0;x < n;++x) { + int32 ppcpx = A[x]&0xfffff; + int32 ppcx = (A[x]&0xffc00)|(B[x]&0x3ff); + B[x] = int32_min(ppcx,ppcpx); + } + } + for (x = 0;x < n;++x) B[x] &= 0x3ff; + } else { + for (x = 0;x < n;++x) B[x] = (A[x]<<16)|(B[x]&0xffff); + + for (i = 1;i < w-1;++i) { + /* B = (p<<16)+c */ + + for (x = 0;x < n;++x) A[x] = (B[x]&~0xffff)|x; + int32_sort(A,n); /* A = (id<<16)+p^(-1) */ + + for (x = 0;x < n;++x) A[x] = (A[x]<<16)|(B[x]&0xffff); + /* A = p^(-1)<<16+c */ + + if (i < w-2) { + for (x = 0;x < n;++x) B[x] = (A[x]&~0xffff)|(B[x]>>16); + /* B = (p^(-1)<<16)+p */ + int32_sort(B,n); /* B = (id<<16)+p^(-2) */ + for (x = 0;x < n;++x) B[x] = (B[x]<<16)|(A[x]&0xffff); + /* B = (p^(-2)<<16)+c */ + } + + int32_sort(A,n); + /* A = id<<16+cp */ + for (x = 0;x < n;++x) { + int32 cpx = (B[x]&~0xffff)|(A[x]&0xffff); + B[x] = int32_min(B[x],cpx); + } + } + for (x = 0;x < n;++x) B[x] &= 0xffff; + } + + for (x = 0;x < n;++x) A[x] = (((int32)pi[x])<<16)+x; + int32_sort(A,n); /* A = (id<<16)+pi^(-1) */ + + for (j = 0;j < n/2;++j) { + long long x = 2*j; + int32 fj = B[x]&1; /* f[j] */ + int32 Fx = x+fj; /* F[x] */ + int32 Fx1 = Fx^1; /* F[x+1] */ + + out[pos>>3] ^= fj<<(pos&7); + pos += step; + + B[x] = (A[x]<<16)|Fx; + B[x+1] = (A[x+1]<<16)|Fx1; + } + /* B = (pi^(-1)<<16)+F */ + + int32_sort(B,n); /* B = (id<<16)+F(pi) */ + + pos += (2*w-3)*step*(n/2); + + for (k = 0;k < n/2;++k) { + long long y = 2*k; + int32 lk = B[y]&1; /* l[k] */ + int32 Ly = y+lk; /* L[y] */ + int32 Ly1 = Ly^1; /* L[y+1] */ + + out[pos>>3] ^= lk<<(pos&7); + pos += step; + + A[y] = (Ly<<16)|(B[y]&0xffff); + A[y+1] = (Ly1<<16)|(B[y+1]&0xffff); + } + /* A = (L<<16)+F(pi) */ + + int32_sort(A,n); /* A = (id<<16)+F(pi(L)) = (id<<16)+M */ + + pos -= (2*w-2)*step*(n/2); + + for (j = 0;j < n/2;++j) { + q[j] = (A[2*j]&0xffff)>>1; + q[j+n/2] = (A[2*j+1]&0xffff)>>1; + } + + cbrecursion(out,pos,step*2,q,w-1,n/2,temp); + cbrecursion(out,pos+step,step*2,q+n/2,w-1,n/2,temp); +} + +/* input: p, an array of int16 */ +/* input: n, length of p */ +/* input: s, meaning that stride-2^s cswaps are performed */ +/* input: cb, the control bits */ +/* output: the result of apply the control bits to p */ +static void layer(int16_t *p, const unsigned char *cb, int s, int n) +{ + int i, j; + int stride = 1 << s; + int index = 0; + int16_t d, m; + + for (i = 0; i < n; i += stride*2) + { + for (j = 0; j < stride; j++) + { + d = p[ i+j ] ^ p[ i+j+stride ]; + m = (cb[ index >> 3 ] >> (index & 7)) & 1; + m = -m; + d &= m; + p[ i+j ] ^= d; + p[ i+j+stride ] ^= d; + index++; + } + } +} + +/* parameters: 1 <= w <= 14; n = 2^w */ +/* input: permutation pi of {0,1,...,n-1} */ +/* output: (2m-1)n/2 control bits at positions 0,1,... */ +/* output position pos is by definition 1&(out[pos/8]>>(pos&7)) */ +void controlbitsfrompermutation(unsigned char *out,const int16 *pi,long long w,long long n) +{ + int32 temp[2*n]; + int16 pi_test[n], diff; + int i; + unsigned char *ptr; + + while (1) + { + memset(out,0,(((2*w-1)*n/2)+7)/8); + cbrecursion(out,0,1,pi,w,n,temp); + + // check for correctness + + for (i = 0; i < n; i++) + pi_test[i] = i; + + ptr = out; + for (i = 0; i < w; i++) + { + layer(pi_test, ptr, i, n); + ptr += n >> 4; + } + + for (i = w-2; i >= 0; i--) + { + layer(pi_test, ptr, i, n); + ptr += n >> 4; + } + + diff = 0; + for (i = 0; i < n; i++) + diff |= pi[i] ^ pi_test[i]; + + diff = crypto_int16_nonzero_mask(diff); + crypto_declassify(&diff,sizeof diff); + if (diff == 0) + break; + } +} + diff --git a/deps/mceliece/kem/mceliece6960119/controlbits.h b/deps/mceliece/kem/mceliece6960119/controlbits.h new file mode 100644 index 0000000..8ddd210 --- /dev/null +++ b/deps/mceliece/kem/mceliece6960119/controlbits.h @@ -0,0 +1,14 @@ +/* This file is for implementing the Nassimi-Sahni algorithm */ +/* See David Nassimi, Sartaj Sahni "Parallel algorithms to set up the Benes permutationnetwork" */ +/* See also https://cr.yp.to/papers/controlbits-20200923.pdf */ + +#ifndef CONTROLBITS_H +#define CONTROLBITS_H + +#define controlbitsfrompermutation CRYPTO_NAMESPACE(controlbitsfrompermutation) + +#include + +extern void controlbitsfrompermutation(unsigned char *,const int16_t *,long long,long long); + +#endif diff --git a/deps/mceliece/kem/mceliece6960119/crypto_hash.h b/deps/mceliece/kem/mceliece6960119/crypto_hash.h new file mode 100644 index 0000000..b7c1086 --- /dev/null +++ b/deps/mceliece/kem/mceliece6960119/crypto_hash.h @@ -0,0 +1,10 @@ +/* This file uses SHAKE256 implemented in the Keccak Code Package */ + +#include "../../mceliece_externals.h" + +#define crypto_hash_32b(out,in,inlen) \ + SHAKE256(out,32,in,inlen) + +#define shake(out,outlen,in,inlen) \ + SHAKE256(out,outlen,in,inlen) + diff --git a/deps/mceliece/kem/mceliece6960119/crypto_kem.h b/deps/mceliece/kem/mceliece6960119/crypto_kem.h new file mode 100644 index 0000000..13c2e07 --- /dev/null +++ b/deps/mceliece/kem/mceliece6960119/crypto_kem.h @@ -0,0 +1,15 @@ +#ifndef crypto_kem_H +#define crypto_kem_H + +#include "crypto_kem_mceliece6960119.h" + +#define crypto_kem_keypair crypto_kem_mceliece6960119_keypair +#define crypto_kem_enc crypto_kem_mceliece6960119_enc +#define crypto_kem_dec crypto_kem_mceliece6960119_dec +#define crypto_kem_PUBLICKEYBYTES crypto_kem_mceliece6960119_PUBLICKEYBYTES +#define crypto_kem_SECRETKEYBYTES crypto_kem_mceliece6960119_SECRETKEYBYTES +#define crypto_kem_BYTES crypto_kem_mceliece6960119_BYTES +#define crypto_kem_CIPHERTEXTBYTES crypto_kem_mceliece6960119_CIPHERTEXTBYTES +#define crypto_kem_PRIMITIVE "mceliece6960119" + +#endif diff --git a/deps/mceliece/kem/mceliece6960119/crypto_kem_mceliece6960119.h b/deps/mceliece/kem/mceliece6960119/crypto_kem_mceliece6960119.h new file mode 100644 index 0000000..c6cae37 --- /dev/null +++ b/deps/mceliece/kem/mceliece6960119/crypto_kem_mceliece6960119.h @@ -0,0 +1,27 @@ +#ifndef crypto_kem_mceliece6960119_H +#define crypto_kem_mceliece6960119_H + +#define crypto_kem_mceliece6960119_ref_PUBLICKEYBYTES 1047319 +#define crypto_kem_mceliece6960119_ref_SECRETKEYBYTES 13948 +#define crypto_kem_mceliece6960119_ref_CIPHERTEXTBYTES 194 +#define crypto_kem_mceliece6960119_ref_BYTES 32 + +#ifdef __cplusplus +extern "C" { +#endif +extern int crypto_kem_mceliece6960119_ref_keypair(unsigned char *,unsigned char *); +extern int crypto_kem_mceliece6960119_ref_enc(unsigned char *,unsigned char *,const unsigned char *); +extern int crypto_kem_mceliece6960119_ref_dec(unsigned char *,const unsigned char *,const unsigned char *); +#ifdef __cplusplus +} +#endif + +#define crypto_kem_mceliece6960119_keypair crypto_kem_mceliece6960119_ref_keypair +#define crypto_kem_mceliece6960119_enc crypto_kem_mceliece6960119_ref_enc +#define crypto_kem_mceliece6960119_dec crypto_kem_mceliece6960119_ref_dec +#define crypto_kem_mceliece6960119_PUBLICKEYBYTES crypto_kem_mceliece6960119_ref_PUBLICKEYBYTES +#define crypto_kem_mceliece6960119_SECRETKEYBYTES crypto_kem_mceliece6960119_ref_SECRETKEYBYTES +#define crypto_kem_mceliece6960119_BYTES crypto_kem_mceliece6960119_ref_BYTES +#define crypto_kem_mceliece6960119_CIPHERTEXTBYTES crypto_kem_mceliece6960119_ref_CIPHERTEXTBYTES + +#endif diff --git a/deps/mceliece/kem/mceliece6960119/decrypt.c b/deps/mceliece/kem/mceliece6960119/decrypt.c new file mode 100644 index 0000000..c4cc6de --- /dev/null +++ b/deps/mceliece/kem/mceliece6960119/decrypt.c @@ -0,0 +1,93 @@ +/* + This file is for Niederreiter decryption +*/ + +#include +#include "decrypt.h" + +#include "params.h" +#include "benes.h" +#include "util.h" +#include "synd.h" +#include "root.h" +#include "gf.h" +#include "bm.h" + +/* Niederreiter decryption with the Berlekamp decoder */ +/* intput: sk, secret key */ +/* c, ciphertext */ +/* output: e, error vector */ +/* return: 0 for success; 1 for failure */ +int decrypt(unsigned char *e, const unsigned char *sk, const unsigned char *c) +{ + int i, w = 0; + uint16_t check; + + unsigned char r[ SYS_N/8 ]; + + gf g[ SYS_T+1 ]; + gf L[ SYS_N ]; + + gf s[ SYS_T*2 ]; + gf s_cmp[ SYS_T*2 ]; + gf locator[ SYS_T+1 ]; + gf images[ SYS_N ]; + + gf t; + + // + + for (i = 0; i < SYND_BYTES; i++) r[i] = c[i]; + for (i = SYND_BYTES; i < SYS_N/8; i++) r[i] = 0; + + for (i = 0; i < SYS_T; i++) { g[i] = load_gf(sk); sk += 2; } g[ SYS_T ] = 1; + + support_gen(L, sk); + + synd(s, g, L, r); + + bm(locator, s); + + root(images, locator, L); + + // + + for (i = 0; i < SYS_N/8; i++) + e[i] = 0; + + for (i = 0; i < SYS_N; i++) + { + t = gf_iszero(images[i]) & 1; + + e[ i/8 ] |= t << (i%8); + w += t; + + } + +#ifdef KAT + { + int k; + printf("decrypt e: positions"); + for (k = 0;k < SYS_N;++k) + if (e[k/8] & (1 << (k&7))) + printf(" %d",k); + printf("\n"); + } +#endif + + synd(s_cmp, g, L, e); + + // + + check = w; + check ^= SYS_T; + + for (i = 0; i < SYS_T*2; i++) + check |= s[i] ^ s_cmp[i]; + + check -= 1; + check >>= 15; + + return check ^ 1; +} + diff --git a/deps/mceliece/kem/mceliece6960119/decrypt.h b/deps/mceliece/kem/mceliece6960119/decrypt.h new file mode 100644 index 0000000..266a5cd --- /dev/null +++ b/deps/mceliece/kem/mceliece6960119/decrypt.h @@ -0,0 +1,12 @@ +/* + This file is for Nieddereiter decryption +*/ + +#ifndef DECRYPT_H +#define DECRYPT_H +#define decrypt CRYPTO_NAMESPACE(decrypt) + +int decrypt(unsigned char *, const unsigned char *, const unsigned char *); + +#endif + diff --git a/deps/mceliece/kem/mceliece6960119/encrypt.c b/deps/mceliece/kem/mceliece6960119/encrypt.c new file mode 100644 index 0000000..662458d --- /dev/null +++ b/deps/mceliece/kem/mceliece6960119/encrypt.c @@ -0,0 +1,164 @@ +/* + This file is for Niederreiter encryption +*/ + +#include "encrypt.h" + +#include "util.h" +#include "params.h" +#include "randombytes.h" + +#include +#include +#include +#include + +#include "gf.h" +#include "crypto_declassify.h" +#include "crypto_uint16.h" +#include "crypto_uint32.h" + +static inline crypto_uint16 uint16_is_smaller_declassify(uint16_t t,uint16_t u) +{ + crypto_uint16 mask = crypto_uint16_smaller_mask(t,u); + crypto_declassify(&mask,sizeof mask); + return mask; +} + +static inline crypto_uint32 uint32_is_equal_declassify(uint32_t t,uint32_t u) +{ + crypto_uint32 mask = crypto_uint32_equal_mask(t,u); + crypto_declassify(&mask,sizeof mask); + return mask; +} + +static inline unsigned char same_mask(uint16_t x, uint16_t y) +{ + uint32_t mask; + + mask = x ^ y; + mask -= 1; + mask >>= 31; + mask = -mask; + + return mask & 0xFF; +} + +/* output: e, an error vector of weight t */ +static void gen_e(unsigned char *e) +{ + int i, j, eq, count; + + union + { + uint16_t nums[ SYS_T*2 ]; + unsigned char bytes[ SYS_T*2 * sizeof(uint16_t) ]; + } buf; + + uint16_t ind[ SYS_T ]; + unsigned char mask; + unsigned char val[ SYS_T ]; + + while (1) + { + randombytes(buf.bytes, sizeof(buf)); + + for (i = 0; i < SYS_T*2; i++) + buf.nums[i] = load_gf(buf.bytes + i*2); + + // moving and counting indices in the correct range + + count = 0; + for (i = 0; i < SYS_T*2 && count < SYS_T; i++) + if (uint16_is_smaller_declassify(buf.nums[i],SYS_N)) + ind[ count++ ] = buf.nums[i]; + + if (count < SYS_T) continue; + + // check for repetition + + eq = 0; + + for (i = 1; i < SYS_T; i++) + for (j = 0; j < i; j++) + if (uint32_is_equal_declassify(ind[i],ind[j])) + eq = 1; + + if (eq == 0) + break; + } + + for (j = 0; j < SYS_T; j++) + val[j] = 1 << (ind[j] & 7); + + for (i = 0; i < SYS_N/8; i++) + { + e[i] = 0; + + for (j = 0; j < SYS_T; j++) + { + mask = same_mask(i, (ind[j] >> 3)); + + e[i] |= val[j] & mask; + } + } +} + +/* input: public key pk, error vector e */ +/* output: syndrome s */ +static void syndrome(unsigned char *s, const unsigned char *pk, unsigned char *e) +{ + unsigned char b, row[SYS_N/8]; + const unsigned char *pk_ptr = pk; + + int i, j, tail = PK_NROWS % 8; + + for (i = 0; i < SYND_BYTES; i++) + s[i] = 0; + + for (i = 0; i < PK_NROWS; i++) + { + for (j = 0; j < SYS_N/8; j++) + row[j] = 0; + + for (j = 0; j < PK_ROW_BYTES; j++) + row[ SYS_N/8 - PK_ROW_BYTES + j ] = pk_ptr[j]; + + for (j = SYS_N/8-1; j >= SYS_N/8 - PK_ROW_BYTES; j--) + row[ j ] = (row[ j ] << tail) | (row[j-1] >> (8-tail)); + + row[i/8] |= 1 << (i%8); + + b = 0; + for (j = 0; j < SYS_N/8; j++) + b ^= row[j] & e[j]; + + b ^= b >> 4; + b ^= b >> 2; + b ^= b >> 1; + b &= 1; + + s[ i/8 ] |= (b << (i%8)); + + pk_ptr += PK_ROW_BYTES; + } +} + +void encrypt(unsigned char *s, const unsigned char *pk, unsigned char *e) +{ + gen_e(e); + +#ifdef KAT + { + int k; + printf("encrypt e: positions"); + for (k = 0;k < SYS_N;++k) + if (e[k/8] & (1 << (k&7))) + printf(" %d",k); + printf("\n"); + } +#endif + + syndrome(s, pk, e); +} + diff --git a/deps/mceliece/kem/mceliece6960119/encrypt.h b/deps/mceliece/kem/mceliece6960119/encrypt.h new file mode 100644 index 0000000..8edd7a6 --- /dev/null +++ b/deps/mceliece/kem/mceliece6960119/encrypt.h @@ -0,0 +1,12 @@ +/* + This file is for Niederreiter encryption +*/ + +#ifndef ENCRYPT_H +#define ENCRYPT_H +#define encrypt CRYPTO_NAMESPACE(encrypt) + +void encrypt(unsigned char *, const unsigned char *, unsigned char *); + +#endif + diff --git a/deps/mceliece/kem/mceliece6960119/gf.c b/deps/mceliece/kem/mceliece6960119/gf.c new file mode 100644 index 0000000..6a0c2e9 --- /dev/null +++ b/deps/mceliece/kem/mceliece6960119/gf.c @@ -0,0 +1,213 @@ +/* + This file is for functions for field arithmetic +*/ + +#include "gf.h" + +#include "params.h" + +gf gf_iszero(gf a) +{ + uint32_t t = a; + + t -= 1; + t >>= 19; + + return (gf) t; +} + +gf gf_add(gf in0, gf in1) +{ + return in0 ^ in1; +} + +gf gf_mul(gf in0, gf in1) +{ + int i; + + uint64_t tmp; + uint64_t t0; + uint64_t t1; + uint64_t t; + + t0 = in0; + t1 = in1; + + tmp = t0 * (t1 & 1); + + for (i = 1; i < GFBITS; i++) + tmp ^= (t0 * (t1 & (1 << i))); + + // + + t = tmp & 0x1FF0000; + tmp ^= (t >> 9) ^ (t >> 10) ^ (t >> 12) ^ (t >> 13); + + t = tmp & 0x000E000; + tmp ^= (t >> 9) ^ (t >> 10) ^ (t >> 12) ^ (t >> 13); + + return tmp & GFMASK; +} + +/* input: field element in */ +/* return: (in^2)^2 */ +static inline gf gf_sq2(gf in) +{ + int i; + + const uint64_t B[] = {0x1111111111111111, + 0x0303030303030303, + 0x000F000F000F000F, + 0x000000FF000000FF}; + + const uint64_t M[] = {0x0001FF0000000000, + 0x000000FF80000000, + 0x000000007FC00000, + 0x00000000003FE000}; + + uint64_t x = in; + uint64_t t; + + x = (x | (x << 24)) & B[3]; + x = (x | (x << 12)) & B[2]; + x = (x | (x << 6)) & B[1]; + x = (x | (x << 3)) & B[0]; + + for (i = 0; i < 4; i++) + { + t = x & M[i]; + x ^= (t >> 9) ^ (t >> 10) ^ (t >> 12) ^ (t >> 13); + } + + return x & GFMASK; +} + +/* input: field element in, m */ +/* return: (in^2)*m */ +static inline gf gf_sqmul(gf in, gf m) +{ + int i; + + uint64_t x; + uint64_t t0; + uint64_t t1; + uint64_t t; + + const uint64_t M[] = {0x0000001FF0000000, + 0x000000000FF80000, + 0x000000000007E000}; + + t0 = in; + t1 = m; + + x = (t1 << 6) * (t0 & (1 << 6)); + + t0 ^= (t0 << 7); + + x ^= (t1 * (t0 & (0x04001))); + x ^= (t1 * (t0 & (0x08002))) << 1; + x ^= (t1 * (t0 & (0x10004))) << 2; + x ^= (t1 * (t0 & (0x20008))) << 3; + x ^= (t1 * (t0 & (0x40010))) << 4; + x ^= (t1 * (t0 & (0x80020))) << 5; + + for (i = 0; i < 3; i++) + { + t = x & M[i]; + x ^= (t >> 9) ^ (t >> 10) ^ (t >> 12) ^ (t >> 13); + } + + return x & GFMASK; +} + +/* input: field element in, m */ +/* return: ((in^2)^2)*m */ +static inline gf gf_sq2mul(gf in, gf m) +{ + int i; + + uint64_t x; + uint64_t t0; + uint64_t t1; + uint64_t t; + + const uint64_t M[] = {0x1FF0000000000000, + 0x000FF80000000000, + 0x000007FC00000000, + 0x00000003FE000000, + 0x0000000001FE0000, + 0x000000000001E000}; + + t0 = in; + t1 = m; + + x = (t1 << 18) * (t0 & (1 << 6)); + + t0 ^= (t0 << 21); + + x ^= (t1 * (t0 & (0x010000001))); + x ^= (t1 * (t0 & (0x020000002))) << 3; + x ^= (t1 * (t0 & (0x040000004))) << 6; + x ^= (t1 * (t0 & (0x080000008))) << 9; + x ^= (t1 * (t0 & (0x100000010))) << 12; + x ^= (t1 * (t0 & (0x200000020))) << 15; + + for (i = 0; i < 6; i++) + { + t = x & M[i]; + x ^= (t >> 9) ^ (t >> 10) ^ (t >> 12) ^ (t >> 13); + } + + return x & GFMASK; +} + +/* input: field element den, num */ +/* return: (num/den) */ +gf gf_frac(gf den, gf num) +{ + gf tmp_11; + gf tmp_1111; + gf out; + + tmp_11 = gf_sqmul(den, den); // ^11 + tmp_1111 = gf_sq2mul(tmp_11, tmp_11); // ^1111 + out = gf_sq2(tmp_1111); + out = gf_sq2mul(out, tmp_1111); // ^11111111 + out = gf_sq2(out); + out = gf_sq2mul(out, tmp_1111); // ^111111111111 + + return gf_sqmul(out, num); // ^1111111111110 = ^-1 +} + +gf gf_inv(gf den) +{ + return gf_frac(den, ((gf) 1)); +} + +/* input: in0, in1 in GF((2^m)^t)*/ +/* output: out = in0*in1 */ +void GF_mul(gf *out, gf *in0, gf *in1) +{ + int i, j; + + gf prod[ SYS_T*2-1 ]; + + for (i = 0; i < SYS_T*2-1; i++) + prod[i] = 0; + + for (i = 0; i < SYS_T; i++) + for (j = 0; j < SYS_T; j++) + prod[i+j] ^= gf_mul(in0[i], in1[j]); + + // + + for (i = (SYS_T-1)*2; i >= SYS_T; i--) + { + prod[i - SYS_T + 8] ^= prod[i]; + prod[i - SYS_T + 0] ^= prod[i]; + } + + for (i = 0; i < SYS_T; i++) + out[i] = prod[i]; +} + diff --git a/deps/mceliece/kem/mceliece6960119/gf.h b/deps/mceliece/kem/mceliece6960119/gf.h new file mode 100644 index 0000000..f62209d --- /dev/null +++ b/deps/mceliece/kem/mceliece6960119/gf.h @@ -0,0 +1,27 @@ +/* + This file is for functions for field arithmetic +*/ + +#ifndef GF_H +#define GF_H +#define gf_add CRYPTO_NAMESPACE(gf_add) +#define gf_frac CRYPTO_NAMESPACE(gf_frac) +#define gf_inv CRYPTO_NAMESPACE(gf_inv) +#define gf_iszero CRYPTO_NAMESPACE(gf_iszero) +#define gf_mul CRYPTO_NAMESPACE(gf_mul) +#define GF_mul CRYPTO_NAMESPACE(GF_mul) + +#include + +typedef uint16_t gf; + +gf gf_iszero(gf); +gf gf_add(gf, gf); +gf gf_mul(gf, gf); +gf gf_frac(gf, gf); +gf gf_inv(gf); + +void GF_mul(gf *, gf *, gf *); + +#endif + diff --git a/deps/mceliece/kem/mceliece6960119/int32_sort.h b/deps/mceliece/kem/mceliece6960119/int32_sort.h new file mode 100644 index 0000000..a431af2 --- /dev/null +++ b/deps/mceliece/kem/mceliece6960119/int32_sort.h @@ -0,0 +1,46 @@ +#ifndef int32_sort_h +#define int32_sort_h + +#define int32_sort CRYPTO_NAMESPACE(int32_sort) + +#include + +#define int32_MINMAX(a,b) \ +do { \ + int32_t ab = b ^ a; \ + int32_t c = b - a; \ + c ^= ab & (c ^ b); \ + c >>= 31; \ + c &= ab; \ + a ^= c; \ + b ^= c; \ +} while(0) + +static void int32_sort(int32_t *x,long long n) +{ + long long top,p,q,r,i; + + if (n < 2) return; + top = 1; + while (top < n - top) top += top; + + for (p = top;p > 0;p >>= 1) { + for (i = 0;i < n - p;++i) + if (!(i & p)) + int32_MINMAX(x[i],x[i+p]); + i = 0; + for (q = top;q > p;q >>= 1) { + for (;i < n - q;++i) { + if (!(i & p)) { + int32_t a = x[i + p]; + for (r = q;r > p;r >>= 1) + int32_MINMAX(a,x[i+r]); + x[i + p] = a; + } + } + } + } +} + +#endif + diff --git a/deps/mceliece/kem/mceliece6960119/operations.c b/deps/mceliece/kem/mceliece6960119/operations.c new file mode 100644 index 0000000..3b408ac --- /dev/null +++ b/deps/mceliece/kem/mceliece6960119/operations.c @@ -0,0 +1,203 @@ +#include "operations.h" + +#include "controlbits.h" +#include "randombytes.h" +#include "crypto_hash.h" +#include "encrypt.h" +#include "decrypt.h" +#include "params.h" +#include "sk_gen.h" +#include "pk_gen.h" +#include "util.h" + +#include +#include + +/* check if the padding bits of pk are all zero */ +static int check_pk_padding(const unsigned char * pk) +{ + unsigned char b; + int i, ret; + + b = 0; + for (i = 0; i < PK_NROWS; i++) + b |= pk[i*PK_ROW_BYTES + PK_ROW_BYTES-1]; + + b >>= (PK_NCOLS % 8); + b -= 1; + b >>= 7; + ret = b; + + return ret-1; +} + +int crypto_kem_enc( + unsigned char *c, + unsigned char *key, + const unsigned char *pk +) +{ + unsigned char e[ SYS_N/8 ]; + unsigned char one_ec[ 1 + SYS_N/8 + SYND_BYTES ] = {1}; + unsigned char mask; + int i, padding_ok; + + // + + padding_ok = check_pk_padding(pk); + + encrypt(c, pk, e); + + memcpy(one_ec + 1, e, SYS_N/8); + memcpy(one_ec + 1 + SYS_N/8, c, SYND_BYTES); + + crypto_hash_32b(key, one_ec, sizeof(one_ec)); + + // clear outputs (set to all 0's) if padding bits are not all zero + + mask = padding_ok; + mask ^= 0xFF; + + for (i = 0; i < SYND_BYTES; i++) + c[i] &= mask; + + for (i = 0; i < 32; i++) + key[i] &= mask; + + return padding_ok; +} + +/* check if the padding bits of c are all zero */ +static int check_c_padding(const unsigned char * c) +{ + unsigned char b; + int ret; + + b = c[ SYND_BYTES-1 ] >> (PK_NROWS % 8); + b -= 1; + b >>= 7; + ret = b; + + return ret-1; +} + +int crypto_kem_dec( + unsigned char *key, + const unsigned char *c, + const unsigned char *sk +) +{ + int i, padding_ok; + + unsigned char mask; + unsigned char ret_decrypt = 0; + + uint16_t m; + + unsigned char e[ SYS_N/8 ]; + unsigned char preimage[ 1 + SYS_N/8 + SYND_BYTES ]; + unsigned char *x = preimage; + const unsigned char *s = sk + 40 + IRR_BYTES + COND_BYTES; + + // + + padding_ok = check_c_padding(c); + + ret_decrypt = decrypt(e, sk + 40, c); + + m = ret_decrypt; + m -= 1; + m >>= 8; + + *x++ = m & 1; + for (i = 0; i < SYS_N/8; i++) + *x++ = (~m & s[i]) | (m & e[i]); + + for (i = 0; i < SYND_BYTES; i++) + *x++ = c[i]; + + crypto_hash_32b(key, preimage, sizeof(preimage)); + + // clear outputs (set to all 1's) if padding bits are not all zero + + mask = padding_ok; + + for (i = 0; i < 32; i++) + key[i] |= mask; + + return padding_ok; +} + +int crypto_kem_keypair +( + unsigned char *pk, + unsigned char *sk +) +{ + int i; + unsigned char seed[ 33 ] = {64}; + unsigned char r[ SYS_N/8 + (1 << GFBITS)*sizeof(uint32_t) + SYS_T*2 + 32 ]; + unsigned char *rp, *skp; + + gf f[ SYS_T ]; // element in GF(2^mt) + gf irr[ SYS_T ]; // Goppa polynomial + uint32_t perm[ 1 << GFBITS ]; // random permutation as 32-bit integers + int16_t pi[ 1 << GFBITS ]; // random permutation + + randombytes(seed+1, 32); + + while (1) + { + rp = &r[ sizeof(r)-32 ]; + skp = sk; + + // expanding and updating the seed + + shake(r, sizeof(r), seed, 33); + memcpy(skp, seed+1, 32); + skp += 32 + 8; + memcpy(seed+1, &r[ sizeof(r)-32 ], 32); + + // generating irreducible polynomial + + rp -= sizeof(f); + + for (i = 0; i < SYS_T; i++) + f[i] = load_gf(rp + i*2); + + if (genpoly_gen(irr, f)) + continue; + + for (i = 0; i < SYS_T; i++) + store_gf(skp + i*2, irr[i]); + + skp += IRR_BYTES; + + // generating permutation + + rp -= sizeof(perm); + + for (i = 0; i < (1 << GFBITS); i++) + perm[i] = load4(rp + i*4); + + if (pk_gen(pk, skp - IRR_BYTES, perm, pi)) + continue; + + controlbitsfrompermutation(skp, pi, GFBITS, 1 << GFBITS); + skp += COND_BYTES; + + // storing the random string s + + rp -= SYS_N/8; + memcpy(skp, rp, SYS_N/8); + + // storing positions of the 32 pivots + + store8(sk + 32, 0xFFFFFFFF); + + break; + } + + return 0; +} + diff --git a/deps/mceliece/kem/mceliece6960119/operations.h b/deps/mceliece/kem/mceliece6960119/operations.h new file mode 100644 index 0000000..bf65502 --- /dev/null +++ b/deps/mceliece/kem/mceliece6960119/operations.h @@ -0,0 +1,25 @@ +#ifndef OPERATIONS_H +#define OPERATIONS_H + +#include "crypto_kem.h" + +int crypto_kem_enc( + unsigned char *c, + unsigned char *key, + const unsigned char *pk +); + +int crypto_kem_dec( + unsigned char *key, + const unsigned char *c, + const unsigned char *sk +); + +int crypto_kem_keypair +( + unsigned char *pk, + unsigned char *sk +); + +#endif + diff --git a/deps/mceliece/kem/mceliece6960119/params.h b/deps/mceliece/kem/mceliece6960119/params.h new file mode 100644 index 0000000..6457fa6 --- /dev/null +++ b/deps/mceliece/kem/mceliece6960119/params.h @@ -0,0 +1,20 @@ +#ifndef PARAMS_H +#define PARAMS_H + +#define GFBITS 13 +#define SYS_N 6960 +#define SYS_T 119 + +#define COND_BYTES ((1 << (GFBITS-4))*(2*GFBITS - 1)) +#define IRR_BYTES (SYS_T * 2) + +#define PK_NROWS (SYS_T*GFBITS) +#define PK_NCOLS (SYS_N - PK_NROWS) +#define PK_ROW_BYTES ((PK_NCOLS + 7)/8) + +#define SYND_BYTES ((PK_NROWS + 7)/8) + +#define GFMASK ((1 << GFBITS) - 1) + +#endif + diff --git a/deps/mceliece/kem/mceliece6960119/pk_gen.c b/deps/mceliece/kem/mceliece6960119/pk_gen.c new file mode 100644 index 0000000..3772706 --- /dev/null +++ b/deps/mceliece/kem/mceliece6960119/pk_gen.c @@ -0,0 +1,160 @@ +/* + This file is for public-key generation +*/ + +#include +#include +#include +#include + +#include "controlbits.h" +#include "uint64_sort.h" +#include "pk_gen.h" +#include "params.h" +#include "benes.h" +#include "root.h" +#include "util.h" +#include "crypto_declassify.h" +#include "crypto_uint64.h" + +static crypto_uint64 uint64_is_equal_declassify(uint64_t t,uint64_t u) +{ + crypto_uint64 mask = crypto_uint64_equal_mask(t,u); + crypto_declassify(&mask,sizeof mask); + return mask; +} + +static crypto_uint64 uint64_is_zero_declassify(uint64_t t) +{ + crypto_uint64 mask = crypto_uint64_zero_mask(t); + crypto_declassify(&mask,sizeof mask); + return mask; +} + +/* input: secret key sk */ +/* output: public key pk */ +int pk_gen(unsigned char * pk, unsigned char * sk, uint32_t * perm, int16_t * pi) +{ + unsigned char *pk_ptr = pk; + + int i, j, k; + int row, c, tail; + + uint64_t buf[ 1 << GFBITS ]; + + unsigned char mat[ PK_NROWS ][ SYS_N/8 ]; + unsigned char mask; + unsigned char b; + + gf g[ SYS_T+1 ]; // Goppa polynomial + gf L[ SYS_N ]; // support + gf inv[ SYS_N ]; + + // + + g[ SYS_T ] = 1; + + for (i = 0; i < SYS_T; i++) { g[i] = load_gf(sk); sk += 2; } + + for (i = 0; i < (1 << GFBITS); i++) + { + buf[i] = perm[i]; + buf[i] <<= 31; + buf[i] |= i; + } + + uint64_sort(buf, 1 << GFBITS); + + for (i = 1; i < (1 << GFBITS); i++) + if (uint64_is_equal_declassify(buf[i-1] >> 31,buf[i] >> 31)) + return -1; + + for (i = 0; i < (1 << GFBITS); i++) pi[i] = buf[i] & GFMASK; + for (i = 0; i < SYS_N; i++) L[i] = bitrev(pi[i]); + + // filling the matrix + + root(inv, g, L); + + for (i = 0; i < SYS_N; i++) + inv[i] = gf_inv(inv[i]); + + for (i = 0; i < PK_NROWS; i++) + for (j = 0; j < SYS_N/8; j++) + mat[i][j] = 0; + + for (i = 0; i < SYS_T; i++) + { + for (j = 0; j < SYS_N; j+=8) + for (k = 0; k < GFBITS; k++) + { + b = (inv[j+7] >> k) & 1; b <<= 1; + b |= (inv[j+6] >> k) & 1; b <<= 1; + b |= (inv[j+5] >> k) & 1; b <<= 1; + b |= (inv[j+4] >> k) & 1; b <<= 1; + b |= (inv[j+3] >> k) & 1; b <<= 1; + b |= (inv[j+2] >> k) & 1; b <<= 1; + b |= (inv[j+1] >> k) & 1; b <<= 1; + b |= (inv[j+0] >> k) & 1; + + mat[ i*GFBITS + k ][ j/8 ] = b; + } + + for (j = 0; j < SYS_N; j++) + inv[j] = gf_mul(inv[j], L[j]); + + } + + // gaussian elimination + + for (i = 0; i < (PK_NROWS + 7) / 8; i++) + for (j = 0; j < 8; j++) + { + row = i*8 + j; + + if (row >= PK_NROWS) + break; + + for (k = row + 1; k < PK_NROWS; k++) + { + mask = mat[ row ][ i ] ^ mat[ k ][ i ]; + mask >>= j; + mask &= 1; + mask = -mask; + + for (c = 0; c < SYS_N/8; c++) + mat[ row ][ c ] ^= mat[ k ][ c ] & mask; + } + + if ( uint64_is_zero_declassify((mat[ row ][ i ] >> j) & 1) ) // return if not systematic + { + return -1; + } + + for (k = 0; k < PK_NROWS; k++) + { + if (k != row) + { + mask = mat[ k ][ i ] >> j; + mask &= 1; + mask = -mask; + + for (c = 0; c < SYS_N/8; c++) + mat[ k ][ c ] ^= mat[ row ][ c ] & mask; + } + } + } + + tail = PK_NROWS % 8; + + for (i = 0; i < PK_NROWS; i++) + { + for (j = (PK_NROWS - 1)/8; j < SYS_N/8 - 1; j++) + *pk_ptr++ = (mat[i][j] >> tail) | (mat[i][j+1] << (8-tail)); + + *pk_ptr++ = (mat[i][j] >> tail); + } + + return 0; +} + diff --git a/deps/mceliece/kem/mceliece6960119/pk_gen.h b/deps/mceliece/kem/mceliece6960119/pk_gen.h new file mode 100644 index 0000000..eec43a7 --- /dev/null +++ b/deps/mceliece/kem/mceliece6960119/pk_gen.h @@ -0,0 +1,14 @@ +/* + This file is for public-key generation +*/ + +#ifndef PK_GEN_H +#define PK_GEN_H +#define pk_gen CRYPTO_NAMESPACE(pk_gen) + +#include "gf.h" + +int pk_gen(unsigned char *, unsigned char *, uint32_t *, int16_t *); + +#endif + diff --git a/deps/mceliece/kem/mceliece6960119/randombytes.h b/deps/mceliece/kem/mceliece6960119/randombytes.h new file mode 100644 index 0000000..7e59351 --- /dev/null +++ b/deps/mceliece/kem/mceliece6960119/randombytes.h @@ -0,0 +1 @@ +#include "../../mceliece_externals.h" diff --git a/deps/mceliece/kem/mceliece6960119/root.c b/deps/mceliece/kem/mceliece6960119/root.c new file mode 100644 index 0000000..1c1b634 --- /dev/null +++ b/deps/mceliece/kem/mceliece6960119/root.c @@ -0,0 +1,38 @@ +/* + This file is for evaluating a polynomial at one or more field elements +*/ + +#include "root.h" +#include "params.h" +#include "gf.h" + +#include + +/* input: polynomial f and field element a */ +/* return f(a) */ +gf eval(gf *f, gf a) +{ + int i; + gf r; + + r = f[ SYS_T ]; + + for (i = SYS_T-1; i >= 0; i--) + { + r = gf_mul(r, a); + r = gf_add(r, f[i]); + } + + return r; +} + +/* input: polynomial f and list of field elements L */ +/* output: out = [ f(a) for a in L ] */ +void root(gf *out, gf *f, gf *L) +{ + int i; + + for (i = 0; i < SYS_N; i++) + out[i] = eval(f, L[i]); +} + diff --git a/deps/mceliece/kem/mceliece6960119/root.h b/deps/mceliece/kem/mceliece6960119/root.h new file mode 100644 index 0000000..42516e4 --- /dev/null +++ b/deps/mceliece/kem/mceliece6960119/root.h @@ -0,0 +1,16 @@ +/* + This file is for evaluating a polynomial at one or more field elements +*/ + +#ifndef ROOT_H +#define ROOT_H +#define eval CRYPTO_NAMESPACE(eval) +#define root CRYPTO_NAMESPACE(root) + +#include "gf.h" + +gf eval(gf *, gf); +void root(gf *, gf *, gf *); + +#endif + diff --git a/deps/mceliece/kem/mceliece6960119/sk_gen.c b/deps/mceliece/kem/mceliece6960119/sk_gen.c new file mode 100644 index 0000000..340cc9a --- /dev/null +++ b/deps/mceliece/kem/mceliece6960119/sk_gen.c @@ -0,0 +1,85 @@ +/* + This file is for secret-key generation +*/ + +#include "sk_gen.h" + +#include "randombytes.h" +#include "controlbits.h" +#include "params.h" +#include "util.h" +#include "gf.h" +#include "crypto_declassify.h" +#include "crypto_uint16.h" + +static inline crypto_uint16 gf_is_zero_declassify(gf t) +{ + crypto_uint16 mask = crypto_uint16_zero_mask(t); + crypto_declassify(&mask,sizeof mask); + return mask; +} + +/* input: f, element in GF((2^m)^t) */ +/* output: out, minimal polynomial of f */ +/* return: 0 for success and -1 for failure */ +int genpoly_gen(gf *out, gf *f) +{ + int i, j, k, c; + + gf mat[ SYS_T+1 ][ SYS_T ]; + gf mask, inv, t; + + // fill matrix + + mat[0][0] = 1; + + for (i = 1; i < SYS_T; i++) + mat[0][i] = 0; + + for (i = 0; i < SYS_T; i++) + mat[1][i] = f[i]; + + for (j = 2; j <= SYS_T; j++) + GF_mul(mat[j], mat[j-1], f); + + // gaussian + + for (j = 0; j < SYS_T; j++) + { + for (k = j + 1; k < SYS_T; k++) + { + mask = gf_iszero(mat[ j ][ j ]); + + for (c = j; c < SYS_T + 1; c++) + mat[ c ][ j ] ^= mat[ c ][ k ] & mask; + + } + + if ( gf_is_zero_declassify(mat[ j ][ j ]) ) // return if not systematic + { + return -1; + } + + inv = gf_inv(mat[j][j]); + + for (c = j; c < SYS_T + 1; c++) + mat[ c ][ j ] = gf_mul(mat[ c ][ j ], inv) ; + + for (k = 0; k < SYS_T; k++) + { + if (k != j) + { + t = mat[ j ][ k ]; + + for (c = j; c < SYS_T + 1; c++) + mat[ c ][ k ] ^= gf_mul(mat[ c ][ j ], t); + } + } + } + + for (i = 0; i < SYS_T; i++) + out[i] = mat[ SYS_T ][ i ]; + + return 0; +} + diff --git a/deps/mceliece/kem/mceliece6960119/sk_gen.h b/deps/mceliece/kem/mceliece6960119/sk_gen.h new file mode 100644 index 0000000..e319703 --- /dev/null +++ b/deps/mceliece/kem/mceliece6960119/sk_gen.h @@ -0,0 +1,18 @@ +/* + This file is for secret-key generation +*/ + +#ifndef SK_GEN_H +#define SK_GEN_H +#define genpoly_gen CRYPTO_NAMESPACE(genpoly_gen) +#define perm_check CRYPTO_NAMESPACE(perm_check) + +#include "gf.h" + +#include + +int genpoly_gen(gf *, gf *); +int perm_check(uint32_t *); + +#endif + diff --git a/deps/mceliece/kem/mceliece6960119/subroutines/crypto_declassify.h b/deps/mceliece/kem/mceliece6960119/subroutines/crypto_declassify.h new file mode 100644 index 0000000..8d84209 --- /dev/null +++ b/deps/mceliece/kem/mceliece6960119/subroutines/crypto_declassify.h @@ -0,0 +1,8 @@ +#ifndef crypto_declassify_h +#define crypto_declassify_h + +static void crypto_declassify(void *x,unsigned long long n) +{ +} + +#endif diff --git a/deps/mceliece/kem/mceliece6960119/subroutines/crypto_int16.h b/deps/mceliece/kem/mceliece6960119/subroutines/crypto_int16.h new file mode 100644 index 0000000..72bbf52 --- /dev/null +++ b/deps/mceliece/kem/mceliece6960119/subroutines/crypto_int16.h @@ -0,0 +1,81 @@ +#ifndef crypto_int16_h +#define crypto_int16_h + +#include +typedef int16_t crypto_int16; + +static crypto_int16 crypto_int16_negative_mask(crypto_int16 crypto_int16_x) +{ + return crypto_int16_x >> 15; +} + +static crypto_int16 crypto_int16_nonzero_mask(crypto_int16 crypto_int16_x) +{ + return crypto_int16_negative_mask(crypto_int16_x) | crypto_int16_negative_mask(-crypto_int16_x); +} + +static crypto_int16 crypto_int16_zero_mask(crypto_int16 crypto_int16_x) +{ + return ~crypto_int16_nonzero_mask(crypto_int16_x); +} + +static crypto_int16 crypto_int16_positive_mask(crypto_int16 crypto_int16_x) +{ + crypto_int16 crypto_int16_z = -crypto_int16_x; + crypto_int16_z ^= crypto_int16_x & crypto_int16_z; + return crypto_int16_negative_mask(crypto_int16_z); +} + +static crypto_int16 crypto_int16_unequal_mask(crypto_int16 crypto_int16_x,crypto_int16 crypto_int16_y) +{ + crypto_int16 crypto_int16_xy = crypto_int16_x ^ crypto_int16_y; + return crypto_int16_nonzero_mask(crypto_int16_xy); +} + +static crypto_int16 crypto_int16_equal_mask(crypto_int16 crypto_int16_x,crypto_int16 crypto_int16_y) +{ + return ~crypto_int16_unequal_mask(crypto_int16_x,crypto_int16_y); +} + +static crypto_int16 crypto_int16_smaller_mask(crypto_int16 crypto_int16_x,crypto_int16 crypto_int16_y) +{ + crypto_int16 crypto_int16_xy = crypto_int16_x ^ crypto_int16_y; + crypto_int16 crypto_int16_z = crypto_int16_x - crypto_int16_y; + crypto_int16_z ^= crypto_int16_xy & (crypto_int16_z ^ crypto_int16_x); + return crypto_int16_negative_mask(crypto_int16_z); +} + +static crypto_int16 crypto_int16_min(crypto_int16 crypto_int16_x,crypto_int16 crypto_int16_y) +{ + crypto_int16 crypto_int16_xy = crypto_int16_y ^ crypto_int16_x; + crypto_int16 crypto_int16_z = crypto_int16_y - crypto_int16_x; + crypto_int16_z ^= crypto_int16_xy & (crypto_int16_z ^ crypto_int16_y); + crypto_int16_z = crypto_int16_negative_mask(crypto_int16_z); + crypto_int16_z &= crypto_int16_xy; + return crypto_int16_x ^ crypto_int16_z; +} + +static crypto_int16 crypto_int16_max(crypto_int16 crypto_int16_x,crypto_int16 crypto_int16_y) +{ + crypto_int16 crypto_int16_xy = crypto_int16_y ^ crypto_int16_x; + crypto_int16 crypto_int16_z = crypto_int16_y - crypto_int16_x; + crypto_int16_z ^= crypto_int16_xy & (crypto_int16_z ^ crypto_int16_y); + crypto_int16_z = crypto_int16_negative_mask(crypto_int16_z); + crypto_int16_z &= crypto_int16_xy; + return crypto_int16_y ^ crypto_int16_z; +} + +static void crypto_int16_minmax(crypto_int16 *crypto_int16_a,crypto_int16 *crypto_int16_b) +{ + crypto_int16 crypto_int16_x = *crypto_int16_a; + crypto_int16 crypto_int16_y = *crypto_int16_b; + crypto_int16 crypto_int16_xy = crypto_int16_y ^ crypto_int16_x; + crypto_int16 crypto_int16_z = crypto_int16_y - crypto_int16_x; + crypto_int16_z ^= crypto_int16_xy & (crypto_int16_z ^ crypto_int16_y); + crypto_int16_z = crypto_int16_negative_mask(crypto_int16_z); + crypto_int16_z &= crypto_int16_xy; + *crypto_int16_a = crypto_int16_x ^ crypto_int16_z; + *crypto_int16_b = crypto_int16_y ^ crypto_int16_z; +} + +#endif diff --git a/deps/mceliece/kem/mceliece6960119/subroutines/crypto_int32.h b/deps/mceliece/kem/mceliece6960119/subroutines/crypto_int32.h new file mode 100644 index 0000000..c22f735 --- /dev/null +++ b/deps/mceliece/kem/mceliece6960119/subroutines/crypto_int32.h @@ -0,0 +1,81 @@ +#ifndef crypto_int32_h +#define crypto_int32_h + +#include +typedef int32_t crypto_int32; + +static crypto_int32 crypto_int32_negative_mask(crypto_int32 crypto_int32_x) +{ + return crypto_int32_x >> 31; +} + +static crypto_int32 crypto_int32_nonzero_mask(crypto_int32 crypto_int32_x) +{ + return crypto_int32_negative_mask(crypto_int32_x) | crypto_int32_negative_mask(-crypto_int32_x); +} + +static crypto_int32 crypto_int32_zero_mask(crypto_int32 crypto_int32_x) +{ + return ~crypto_int32_nonzero_mask(crypto_int32_x); +} + +static crypto_int32 crypto_int32_positive_mask(crypto_int32 crypto_int32_x) +{ + crypto_int32 crypto_int32_z = -crypto_int32_x; + crypto_int32_z ^= crypto_int32_x & crypto_int32_z; + return crypto_int32_negative_mask(crypto_int32_z); +} + +static crypto_int32 crypto_int32_unequal_mask(crypto_int32 crypto_int32_x,crypto_int32 crypto_int32_y) +{ + crypto_int32 crypto_int32_xy = crypto_int32_x ^ crypto_int32_y; + return crypto_int32_nonzero_mask(crypto_int32_xy); +} + +static crypto_int32 crypto_int32_equal_mask(crypto_int32 crypto_int32_x,crypto_int32 crypto_int32_y) +{ + return ~crypto_int32_unequal_mask(crypto_int32_x,crypto_int32_y); +} + +static crypto_int32 crypto_int32_smaller_mask(crypto_int32 crypto_int32_x,crypto_int32 crypto_int32_y) +{ + crypto_int32 crypto_int32_xy = crypto_int32_x ^ crypto_int32_y; + crypto_int32 crypto_int32_z = crypto_int32_x - crypto_int32_y; + crypto_int32_z ^= crypto_int32_xy & (crypto_int32_z ^ crypto_int32_x); + return crypto_int32_negative_mask(crypto_int32_z); +} + +static crypto_int32 crypto_int32_min(crypto_int32 crypto_int32_x,crypto_int32 crypto_int32_y) +{ + crypto_int32 crypto_int32_xy = crypto_int32_y ^ crypto_int32_x; + crypto_int32 crypto_int32_z = crypto_int32_y - crypto_int32_x; + crypto_int32_z ^= crypto_int32_xy & (crypto_int32_z ^ crypto_int32_y); + crypto_int32_z = crypto_int32_negative_mask(crypto_int32_z); + crypto_int32_z &= crypto_int32_xy; + return crypto_int32_x ^ crypto_int32_z; +} + +static crypto_int32 crypto_int32_max(crypto_int32 crypto_int32_x,crypto_int32 crypto_int32_y) +{ + crypto_int32 crypto_int32_xy = crypto_int32_y ^ crypto_int32_x; + crypto_int32 crypto_int32_z = crypto_int32_y - crypto_int32_x; + crypto_int32_z ^= crypto_int32_xy & (crypto_int32_z ^ crypto_int32_y); + crypto_int32_z = crypto_int32_negative_mask(crypto_int32_z); + crypto_int32_z &= crypto_int32_xy; + return crypto_int32_y ^ crypto_int32_z; +} + +static void crypto_int32_minmax(crypto_int32 *crypto_int32_a,crypto_int32 *crypto_int32_b) +{ + crypto_int32 crypto_int32_x = *crypto_int32_a; + crypto_int32 crypto_int32_y = *crypto_int32_b; + crypto_int32 crypto_int32_xy = crypto_int32_y ^ crypto_int32_x; + crypto_int32 crypto_int32_z = crypto_int32_y - crypto_int32_x; + crypto_int32_z ^= crypto_int32_xy & (crypto_int32_z ^ crypto_int32_y); + crypto_int32_z = crypto_int32_negative_mask(crypto_int32_z); + crypto_int32_z &= crypto_int32_xy; + *crypto_int32_a = crypto_int32_x ^ crypto_int32_z; + *crypto_int32_b = crypto_int32_y ^ crypto_int32_z; +} + +#endif diff --git a/deps/mceliece/kem/mceliece6960119/subroutines/crypto_uint16.h b/deps/mceliece/kem/mceliece6960119/subroutines/crypto_uint16.h new file mode 100644 index 0000000..f0ebbbf --- /dev/null +++ b/deps/mceliece/kem/mceliece6960119/subroutines/crypto_uint16.h @@ -0,0 +1,76 @@ +#ifndef crypto_uint16_h +#define crypto_uint16_h + +#include +typedef uint16_t crypto_uint16; + +typedef int16_t crypto_uint16_signed; + +static crypto_uint16_signed crypto_uint16_signed_negative_mask(crypto_uint16_signed crypto_uint16_signed_x) +{ + return crypto_uint16_signed_x >> 15; +} + +static crypto_uint16 crypto_uint16_nonzero_mask(crypto_uint16 crypto_uint16_x) +{ + return crypto_uint16_signed_negative_mask(crypto_uint16_x) | crypto_uint16_signed_negative_mask(-crypto_uint16_x); +} + +static crypto_uint16 crypto_uint16_zero_mask(crypto_uint16 crypto_uint16_x) +{ + return ~crypto_uint16_nonzero_mask(crypto_uint16_x); +} + +static crypto_uint16 crypto_uint16_unequal_mask(crypto_uint16 crypto_uint16_x,crypto_uint16 crypto_uint16_y) +{ + crypto_uint16 crypto_uint16_xy = crypto_uint16_x ^ crypto_uint16_y; + return crypto_uint16_nonzero_mask(crypto_uint16_xy); +} + +static crypto_uint16 crypto_uint16_equal_mask(crypto_uint16 crypto_uint16_x,crypto_uint16 crypto_uint16_y) +{ + return ~crypto_uint16_unequal_mask(crypto_uint16_x,crypto_uint16_y); +} + +static crypto_uint16 crypto_uint16_smaller_mask(crypto_uint16 crypto_uint16_x,crypto_uint16 crypto_uint16_y) +{ + crypto_uint16 crypto_uint16_xy = crypto_uint16_x ^ crypto_uint16_y; + crypto_uint16 crypto_uint16_z = crypto_uint16_x - crypto_uint16_y; + crypto_uint16_z ^= crypto_uint16_xy & (crypto_uint16_z ^ crypto_uint16_x ^ (((crypto_uint16) 1) << 15)); + return crypto_uint16_signed_negative_mask(crypto_uint16_z); +} + +static crypto_uint16 crypto_uint16_min(crypto_uint16 crypto_uint16_x,crypto_uint16 crypto_uint16_y) +{ + crypto_uint16 crypto_uint16_xy = crypto_uint16_y ^ crypto_uint16_x; + crypto_uint16 crypto_uint16_z = crypto_uint16_y - crypto_uint16_x; + crypto_uint16_z ^= crypto_uint16_xy & (crypto_uint16_z ^ crypto_uint16_y ^ (((crypto_uint16) 1) << 15)); + crypto_uint16_z = crypto_uint16_signed_negative_mask(crypto_uint16_z); + crypto_uint16_z &= crypto_uint16_xy; + return crypto_uint16_x ^ crypto_uint16_z; +} + +static crypto_uint16 crypto_uint16_max(crypto_uint16 crypto_uint16_x,crypto_uint16 crypto_uint16_y) +{ + crypto_uint16 crypto_uint16_xy = crypto_uint16_y ^ crypto_uint16_x; + crypto_uint16 crypto_uint16_z = crypto_uint16_y - crypto_uint16_x; + crypto_uint16_z ^= crypto_uint16_xy & (crypto_uint16_z ^ crypto_uint16_y ^ (((crypto_uint16) 1) << 15)); + crypto_uint16_z = crypto_uint16_signed_negative_mask(crypto_uint16_z); + crypto_uint16_z &= crypto_uint16_xy; + return crypto_uint16_y ^ crypto_uint16_z; +} + +static void crypto_uint16_minmax(crypto_uint16 *crypto_uint16_a,crypto_uint16 *crypto_uint16_b) +{ + crypto_uint16 crypto_uint16_x = *crypto_uint16_a; + crypto_uint16 crypto_uint16_y = *crypto_uint16_b; + crypto_uint16 crypto_uint16_xy = crypto_uint16_y ^ crypto_uint16_x; + crypto_uint16 crypto_uint16_z = crypto_uint16_y - crypto_uint16_x; + crypto_uint16_z ^= crypto_uint16_xy & (crypto_uint16_z ^ crypto_uint16_y ^ (((crypto_uint16) 1) << 15)); + crypto_uint16_z = crypto_uint16_signed_negative_mask(crypto_uint16_z); + crypto_uint16_z &= crypto_uint16_xy; + *crypto_uint16_a = crypto_uint16_x ^ crypto_uint16_z; + *crypto_uint16_b = crypto_uint16_y ^ crypto_uint16_z; +} + +#endif diff --git a/deps/mceliece/kem/mceliece6960119/subroutines/crypto_uint32.h b/deps/mceliece/kem/mceliece6960119/subroutines/crypto_uint32.h new file mode 100644 index 0000000..3f39d62 --- /dev/null +++ b/deps/mceliece/kem/mceliece6960119/subroutines/crypto_uint32.h @@ -0,0 +1,76 @@ +#ifndef crypto_uint32_h +#define crypto_uint32_h + +#include +typedef uint32_t crypto_uint32; + +typedef int32_t crypto_uint32_signed; + +static crypto_uint32_signed crypto_uint32_signed_negative_mask(crypto_uint32_signed crypto_uint32_signed_x) +{ + return crypto_uint32_signed_x >> 31; +} + +static crypto_uint32 crypto_uint32_nonzero_mask(crypto_uint32 crypto_uint32_x) +{ + return crypto_uint32_signed_negative_mask(crypto_uint32_x) | crypto_uint32_signed_negative_mask(-crypto_uint32_x); +} + +static crypto_uint32 crypto_uint32_zero_mask(crypto_uint32 crypto_uint32_x) +{ + return ~crypto_uint32_nonzero_mask(crypto_uint32_x); +} + +static crypto_uint32 crypto_uint32_unequal_mask(crypto_uint32 crypto_uint32_x,crypto_uint32 crypto_uint32_y) +{ + crypto_uint32 crypto_uint32_xy = crypto_uint32_x ^ crypto_uint32_y; + return crypto_uint32_nonzero_mask(crypto_uint32_xy); +} + +static crypto_uint32 crypto_uint32_equal_mask(crypto_uint32 crypto_uint32_x,crypto_uint32 crypto_uint32_y) +{ + return ~crypto_uint32_unequal_mask(crypto_uint32_x,crypto_uint32_y); +} + +static crypto_uint32 crypto_uint32_smaller_mask(crypto_uint32 crypto_uint32_x,crypto_uint32 crypto_uint32_y) +{ + crypto_uint32 crypto_uint32_xy = crypto_uint32_x ^ crypto_uint32_y; + crypto_uint32 crypto_uint32_z = crypto_uint32_x - crypto_uint32_y; + crypto_uint32_z ^= crypto_uint32_xy & (crypto_uint32_z ^ crypto_uint32_x ^ (((crypto_uint32) 1) << 31)); + return crypto_uint32_signed_negative_mask(crypto_uint32_z); +} + +static crypto_uint32 crypto_uint32_min(crypto_uint32 crypto_uint32_x,crypto_uint32 crypto_uint32_y) +{ + crypto_uint32 crypto_uint32_xy = crypto_uint32_y ^ crypto_uint32_x; + crypto_uint32 crypto_uint32_z = crypto_uint32_y - crypto_uint32_x; + crypto_uint32_z ^= crypto_uint32_xy & (crypto_uint32_z ^ crypto_uint32_y ^ (((crypto_uint32) 1) << 31)); + crypto_uint32_z = crypto_uint32_signed_negative_mask(crypto_uint32_z); + crypto_uint32_z &= crypto_uint32_xy; + return crypto_uint32_x ^ crypto_uint32_z; +} + +static crypto_uint32 crypto_uint32_max(crypto_uint32 crypto_uint32_x,crypto_uint32 crypto_uint32_y) +{ + crypto_uint32 crypto_uint32_xy = crypto_uint32_y ^ crypto_uint32_x; + crypto_uint32 crypto_uint32_z = crypto_uint32_y - crypto_uint32_x; + crypto_uint32_z ^= crypto_uint32_xy & (crypto_uint32_z ^ crypto_uint32_y ^ (((crypto_uint32) 1) << 31)); + crypto_uint32_z = crypto_uint32_signed_negative_mask(crypto_uint32_z); + crypto_uint32_z &= crypto_uint32_xy; + return crypto_uint32_y ^ crypto_uint32_z; +} + +static void crypto_uint32_minmax(crypto_uint32 *crypto_uint32_a,crypto_uint32 *crypto_uint32_b) +{ + crypto_uint32 crypto_uint32_x = *crypto_uint32_a; + crypto_uint32 crypto_uint32_y = *crypto_uint32_b; + crypto_uint32 crypto_uint32_xy = crypto_uint32_y ^ crypto_uint32_x; + crypto_uint32 crypto_uint32_z = crypto_uint32_y - crypto_uint32_x; + crypto_uint32_z ^= crypto_uint32_xy & (crypto_uint32_z ^ crypto_uint32_y ^ (((crypto_uint32) 1) << 31)); + crypto_uint32_z = crypto_uint32_signed_negative_mask(crypto_uint32_z); + crypto_uint32_z &= crypto_uint32_xy; + *crypto_uint32_a = crypto_uint32_x ^ crypto_uint32_z; + *crypto_uint32_b = crypto_uint32_y ^ crypto_uint32_z; +} + +#endif diff --git a/deps/mceliece/kem/mceliece6960119/subroutines/crypto_uint64.h b/deps/mceliece/kem/mceliece6960119/subroutines/crypto_uint64.h new file mode 100644 index 0000000..42e2be9 --- /dev/null +++ b/deps/mceliece/kem/mceliece6960119/subroutines/crypto_uint64.h @@ -0,0 +1,76 @@ +#ifndef crypto_uint64_h +#define crypto_uint64_h + +#include +typedef uint64_t crypto_uint64; + +typedef int64_t crypto_uint64_signed; + +static crypto_uint64_signed crypto_uint64_signed_negative_mask(crypto_uint64_signed crypto_uint64_signed_x) +{ + return crypto_uint64_signed_x >> 63; +} + +static crypto_uint64 crypto_uint64_nonzero_mask(crypto_uint64 crypto_uint64_x) +{ + return crypto_uint64_signed_negative_mask(crypto_uint64_x) | crypto_uint64_signed_negative_mask(-crypto_uint64_x); +} + +static crypto_uint64 crypto_uint64_zero_mask(crypto_uint64 crypto_uint64_x) +{ + return ~crypto_uint64_nonzero_mask(crypto_uint64_x); +} + +static crypto_uint64 crypto_uint64_unequal_mask(crypto_uint64 crypto_uint64_x,crypto_uint64 crypto_uint64_y) +{ + crypto_uint64 crypto_uint64_xy = crypto_uint64_x ^ crypto_uint64_y; + return crypto_uint64_nonzero_mask(crypto_uint64_xy); +} + +static crypto_uint64 crypto_uint64_equal_mask(crypto_uint64 crypto_uint64_x,crypto_uint64 crypto_uint64_y) +{ + return ~crypto_uint64_unequal_mask(crypto_uint64_x,crypto_uint64_y); +} + +static crypto_uint64 crypto_uint64_smaller_mask(crypto_uint64 crypto_uint64_x,crypto_uint64 crypto_uint64_y) +{ + crypto_uint64 crypto_uint64_xy = crypto_uint64_x ^ crypto_uint64_y; + crypto_uint64 crypto_uint64_z = crypto_uint64_x - crypto_uint64_y; + crypto_uint64_z ^= crypto_uint64_xy & (crypto_uint64_z ^ crypto_uint64_x ^ (((crypto_uint64) 1) << 63)); + return crypto_uint64_signed_negative_mask(crypto_uint64_z); +} + +static crypto_uint64 crypto_uint64_min(crypto_uint64 crypto_uint64_x,crypto_uint64 crypto_uint64_y) +{ + crypto_uint64 crypto_uint64_xy = crypto_uint64_y ^ crypto_uint64_x; + crypto_uint64 crypto_uint64_z = crypto_uint64_y - crypto_uint64_x; + crypto_uint64_z ^= crypto_uint64_xy & (crypto_uint64_z ^ crypto_uint64_y ^ (((crypto_uint64) 1) << 63)); + crypto_uint64_z = crypto_uint64_signed_negative_mask(crypto_uint64_z); + crypto_uint64_z &= crypto_uint64_xy; + return crypto_uint64_x ^ crypto_uint64_z; +} + +static crypto_uint64 crypto_uint64_max(crypto_uint64 crypto_uint64_x,crypto_uint64 crypto_uint64_y) +{ + crypto_uint64 crypto_uint64_xy = crypto_uint64_y ^ crypto_uint64_x; + crypto_uint64 crypto_uint64_z = crypto_uint64_y - crypto_uint64_x; + crypto_uint64_z ^= crypto_uint64_xy & (crypto_uint64_z ^ crypto_uint64_y ^ (((crypto_uint64) 1) << 63)); + crypto_uint64_z = crypto_uint64_signed_negative_mask(crypto_uint64_z); + crypto_uint64_z &= crypto_uint64_xy; + return crypto_uint64_y ^ crypto_uint64_z; +} + +static void crypto_uint64_minmax(crypto_uint64 *crypto_uint64_a,crypto_uint64 *crypto_uint64_b) +{ + crypto_uint64 crypto_uint64_x = *crypto_uint64_a; + crypto_uint64 crypto_uint64_y = *crypto_uint64_b; + crypto_uint64 crypto_uint64_xy = crypto_uint64_y ^ crypto_uint64_x; + crypto_uint64 crypto_uint64_z = crypto_uint64_y - crypto_uint64_x; + crypto_uint64_z ^= crypto_uint64_xy & (crypto_uint64_z ^ crypto_uint64_y ^ (((crypto_uint64) 1) << 63)); + crypto_uint64_z = crypto_uint64_signed_negative_mask(crypto_uint64_z); + crypto_uint64_z &= crypto_uint64_xy; + *crypto_uint64_a = crypto_uint64_x ^ crypto_uint64_z; + *crypto_uint64_b = crypto_uint64_y ^ crypto_uint64_z; +} + +#endif diff --git a/deps/mceliece/kem/mceliece6960119/synd.c b/deps/mceliece/kem/mceliece6960119/synd.c new file mode 100644 index 0000000..c945647 --- /dev/null +++ b/deps/mceliece/kem/mceliece6960119/synd.c @@ -0,0 +1,36 @@ +/* + This file is for syndrome computation +*/ + +#include "synd.h" + +#include "params.h" +#include "root.h" + +#include + +/* input: Goppa polynomial f, support L, received word r */ +/* output: out, the syndrome of length 2t */ +void synd(gf *out, gf *f, gf *L, unsigned char *r) +{ + int i, j; + gf e, e_inv, c; + + for (j = 0; j < 2*SYS_T; j++) + out[j] = 0; + + for (i = 0; i < SYS_N; i++) + { + c = (r[i/8] >> (i%8)) & 1; + + e = eval(f, L[i]); + e_inv = gf_inv(gf_mul(e,e)); + + for (j = 0; j < 2*SYS_T; j++) + { + out[j] = gf_add(out[j], gf_mul(e_inv, c)); + e_inv = gf_mul(e_inv, L[i]); + } + } +} + diff --git a/deps/mceliece/kem/mceliece6960119/synd.h b/deps/mceliece/kem/mceliece6960119/synd.h new file mode 100644 index 0000000..9331406 --- /dev/null +++ b/deps/mceliece/kem/mceliece6960119/synd.h @@ -0,0 +1,14 @@ +/* + This file is for syndrome computation +*/ + +#ifndef SYND_H +#define SYND_H +#define synd CRYPTO_NAMESPACE(synd) + +#include "gf.h" + +void synd(gf *, gf *, gf *, unsigned char *); + +#endif + diff --git a/deps/mceliece/kem/mceliece6960119/transpose.c b/deps/mceliece/kem/mceliece6960119/transpose.c new file mode 100644 index 0000000..0da2bc5 --- /dev/null +++ b/deps/mceliece/kem/mceliece6960119/transpose.c @@ -0,0 +1,43 @@ +/* + This file is for matrix transposition +*/ + +#include "transpose.h" + +#include + +/* input: in, a 64x64 matrix over GF(2) */ +/* output: out, transpose of in */ +void transpose_64x64(uint64_t * out, uint64_t * in) +{ + int i, j, s, d; + + uint64_t x, y; + uint64_t masks[6][2] = { + {0x5555555555555555, 0xAAAAAAAAAAAAAAAA}, + {0x3333333333333333, 0xCCCCCCCCCCCCCCCC}, + {0x0F0F0F0F0F0F0F0F, 0xF0F0F0F0F0F0F0F0}, + {0x00FF00FF00FF00FF, 0xFF00FF00FF00FF00}, + {0x0000FFFF0000FFFF, 0xFFFF0000FFFF0000}, + {0x00000000FFFFFFFF, 0xFFFFFFFF00000000} + }; + + for (i = 0; i < 64; i++) + out[i] = in[i]; + + for (d = 5; d >= 0; d--) + { + s = 1 << d; + + for (i = 0; i < 64; i += s*2) + for (j = i; j < i+s; j++) + { + x = (out[j] & masks[d][0]) | ((out[j+s] & masks[d][0]) << s); + y = ((out[j] & masks[d][1]) >> s) | (out[j+s] & masks[d][1]); + + out[j+0] = x; + out[j+s] = y; + } + } +} + diff --git a/deps/mceliece/kem/mceliece6960119/transpose.h b/deps/mceliece/kem/mceliece6960119/transpose.h new file mode 100644 index 0000000..31e5b96 --- /dev/null +++ b/deps/mceliece/kem/mceliece6960119/transpose.h @@ -0,0 +1,14 @@ +/* + This file is for matrix transposition +*/ + +#ifndef TRANSPOSE_H +#define TRANSPOSE_H +#define transpose_64x64 CRYPTO_NAMESPACE(transpose_64x64) + +#include + +void transpose_64x64(uint64_t *, uint64_t *); + +#endif + diff --git a/deps/mceliece/kem/mceliece6960119/uint64_sort.h b/deps/mceliece/kem/mceliece6960119/uint64_sort.h new file mode 100644 index 0000000..2fb100c --- /dev/null +++ b/deps/mceliece/kem/mceliece6960119/uint64_sort.h @@ -0,0 +1,45 @@ +#ifndef uint64_sort_h +#define uint64_sort_h + +#define int64_sort CRYPTO_NAMESPACE(int64_sort) + +#include + +#define uint64_MINMAX(a,b) \ +do { \ + uint64_t c = b - a; \ + c >>= 63; \ + c = -c; \ + c &= a ^ b; \ + a ^= c; \ + b ^= c; \ +} while(0) + +static void uint64_sort(uint64_t *x,long long n) +{ + long long top,p,q,r,i; + + if (n < 2) return; + top = 1; + while (top < n - top) top += top; + + for (p = top;p > 0;p >>= 1) { + for (i = 0;i < n - p;++i) + if (!(i & p)) + uint64_MINMAX(x[i],x[i+p]); + i = 0; + for (q = top;q > p;q >>= 1) { + for (;i < n - q;++i) { + if (!(i & p)) { + uint64_t a = x[i + p]; + for (r = q;r > p;r >>= 1) + uint64_MINMAX(a,x[i+r]); + x[i + p] = a; + } + } + } + } +} + +#endif + diff --git a/deps/mceliece/kem/mceliece6960119/util.c b/deps/mceliece/kem/mceliece6960119/util.c new file mode 100644 index 0000000..1679168 --- /dev/null +++ b/deps/mceliece/kem/mceliece6960119/util.c @@ -0,0 +1,75 @@ +/* + This file is for loading/storing data in a little-endian fashion +*/ + +#include "util.h" + +#include "params.h" + +void store_gf(unsigned char *dest, gf a) +{ + dest[0] = a & 0xFF; + dest[1] = a >> 8; +} + +uint16_t load_gf(const unsigned char *src) +{ + uint16_t a; + + a = src[1]; + a <<= 8; + a |= src[0]; + + return a & GFMASK; +} + +uint32_t load4(const unsigned char * in) +{ + int i; + uint32_t ret = in[3]; + + for (i = 2; i >= 0; i--) + { + ret <<= 8; + ret |= in[i]; + } + + return ret; +} + +void store8(unsigned char *out, uint64_t in) +{ + out[0] = (in >> 0x00) & 0xFF; + out[1] = (in >> 0x08) & 0xFF; + out[2] = (in >> 0x10) & 0xFF; + out[3] = (in >> 0x18) & 0xFF; + out[4] = (in >> 0x20) & 0xFF; + out[5] = (in >> 0x28) & 0xFF; + out[6] = (in >> 0x30) & 0xFF; + out[7] = (in >> 0x38) & 0xFF; +} + +uint64_t load8(const unsigned char * in) +{ + int i; + uint64_t ret = in[7]; + + for (i = 6; i >= 0; i--) + { + ret <<= 8; + ret |= in[i]; + } + + return ret; +} + +gf bitrev(gf a) +{ + a = ((a & 0x00FF) << 8) | ((a & 0xFF00) >> 8); + a = ((a & 0x0F0F) << 4) | ((a & 0xF0F0) >> 4); + a = ((a & 0x3333) << 2) | ((a & 0xCCCC) >> 2); + a = ((a & 0x5555) << 1) | ((a & 0xAAAA) >> 1); + + return a >> 3; +} + diff --git a/deps/mceliece/kem/mceliece6960119/util.h b/deps/mceliece/kem/mceliece6960119/util.h new file mode 100644 index 0000000..d610bee --- /dev/null +++ b/deps/mceliece/kem/mceliece6960119/util.h @@ -0,0 +1,27 @@ +/* + This file is for loading/storing data in a little-endian fashion +*/ + +#ifndef UTIL_H +#define UTIL_H +#define bitrev CRYPTO_NAMESPACE(bitrev) +#define load4 CRYPTO_NAMESPACE(load4) +#define load8 CRYPTO_NAMESPACE(load8) +#define load_gf CRYPTO_NAMESPACE(load_gf) +#define store8 CRYPTO_NAMESPACE(store8) +#define store_gf CRYPTO_NAMESPACE(store_gf) + +#include "gf.h" +#include + +void store_gf(unsigned char *, gf); +uint16_t load_gf(const unsigned char *); +uint32_t load4(const unsigned char *); + +void store8(unsigned char *, uint64_t ); +uint64_t load8(const unsigned char *); + +gf bitrev(gf); + +#endif + diff --git a/deps/mceliece/kem/mceliece6960119f/benes.c b/deps/mceliece/kem/mceliece6960119f/benes.c new file mode 100644 index 0000000..3b4e710 --- /dev/null +++ b/deps/mceliece/kem/mceliece6960119f/benes.c @@ -0,0 +1,181 @@ +/* + This file is for Benes network related functions + + For the implementation strategy, see + https://eprint.iacr.org/2017/793.pdf +*/ + +#include "util.h" +#include "transpose.h" +#include "params.h" +#include "benes.h" + +/* middle layers of the benes network */ +static void layer_in(uint64_t data[2][64], uint64_t * bits, int lgs) +{ + int i, j, s; + + uint64_t d; + + s = 1 << lgs; + + for (i = 0; i < 64; i += s*2) + for (j = i; j < i+s; j++) + { + + d = (data[0][j+0] ^ data[0][j+s]); + d &= (*bits++); + data[0][j+0] ^= d; + data[0][j+s] ^= d; + + d = (data[1][j+0] ^ data[1][j+s]); + d &= (*bits++); + data[1][j+0] ^= d; + data[1][j+s] ^= d; + } +} + +/* first and last layers of the benes network */ +static void layer_ex(uint64_t * data, uint64_t * bits, int lgs) +{ + int i, j, s; + + uint64_t d; + + s = 1 << lgs; + + for (i = 0; i < 128; i += s*2) + for (j = i; j < i+s; j++) + { + + d = (data[j+0] ^ data[j+s]); + d &= (*bits++); + data[j+0] ^= d; + data[j+s] ^= d; + } +} + +/* input: r, sequence of bits to be permuted */ +/* bits, condition bits of the Benes network */ +/* rev, 0 for normal application; !0 for inverse */ +/* output: r, permuted bits */ +void apply_benes(unsigned char * r, const unsigned char * bits, int rev) +{ + int i, iter, inc; + + unsigned char *r_ptr = r; + const unsigned char *bits_ptr; + + uint64_t r_int_v[2][64]; + uint64_t r_int_h[2][64]; + uint64_t b_int_v[64]; + uint64_t b_int_h[64]; + + // + + if (rev) { bits_ptr = bits + 12288; inc = -1024; } + else { bits_ptr = bits; inc = 0; } + + for (i = 0; i < 64; i++) + { + r_int_v[0][i] = load8(r_ptr + i*16 + 0); + r_int_v[1][i] = load8(r_ptr + i*16 + 8); + } + + transpose_64x64(r_int_h[0], r_int_v[0]); + transpose_64x64(r_int_h[1], r_int_v[1]); + + for (iter = 0; iter <= 6; iter++) + { + for (i = 0; i < 64; i++) + { + b_int_v[i] = load8(bits_ptr); bits_ptr += 8; + } + + bits_ptr += inc; + + transpose_64x64(b_int_h, b_int_v); + + layer_ex(r_int_h[0], b_int_h, iter); + } + + transpose_64x64(r_int_v[0], r_int_h[0]); + transpose_64x64(r_int_v[1], r_int_h[1]); + + for (iter = 0; iter <= 5; iter++) + { + for (i = 0; i < 64; i++) { b_int_v[i] = load8(bits_ptr); bits_ptr += 8; } + bits_ptr += inc; + + layer_in(r_int_v, b_int_v, iter); + } + + for (iter = 4; iter >= 0; iter--) + { + for (i = 0; i < 64; i++) { b_int_v[i] = load8(bits_ptr); bits_ptr += 8; } + bits_ptr += inc; + + layer_in(r_int_v, b_int_v, iter); + } + + transpose_64x64(r_int_h[0], r_int_v[0]); + transpose_64x64(r_int_h[1], r_int_v[1]); + + for (iter = 6; iter >= 0; iter--) + { + for (i = 0; i < 64; i++) + { + b_int_v[i] = load8(bits_ptr); bits_ptr += 8; + } + + bits_ptr += inc; + + transpose_64x64(b_int_h, b_int_v); + + layer_ex(r_int_h[0], b_int_h, iter); + } + + transpose_64x64(r_int_v[0], r_int_h[0]); + transpose_64x64(r_int_v[1], r_int_h[1]); + + for (i = 0; i < 64; i++) + { + store8(r_ptr + i*16 + 0, r_int_v[0][i]); + store8(r_ptr + i*16 + 8, r_int_v[1][i]); + } +} + +/* input: condition bits c */ +/* output: support s */ +void support_gen(gf * s, const unsigned char *c) +{ + gf a; + int i, j; + unsigned char L[ GFBITS ][ (1 << GFBITS)/8 ]; + + for (i = 0; i < GFBITS; i++) + for (j = 0; j < (1 << GFBITS)/8; j++) + L[i][j] = 0; + + for (i = 0; i < (1 << GFBITS); i++) + { + a = bitrev((gf) i); + + for (j = 0; j < GFBITS; j++) + L[j][ i/8 ] |= ((a >> j) & 1) << (i%8); + } + + for (j = 0; j < GFBITS; j++) + apply_benes(L[j], c, 0); + + for (i = 0; i < SYS_N; i++) + { + s[i] = 0; + for (j = GFBITS-1; j >= 0; j--) + { + s[i] <<= 1; + s[i] |= (L[j][i/8] >> (i%8)) & 1; + } + } +} + diff --git a/deps/mceliece/kem/mceliece6960119f/benes.h b/deps/mceliece/kem/mceliece6960119f/benes.h new file mode 100644 index 0000000..c2ef35a --- /dev/null +++ b/deps/mceliece/kem/mceliece6960119f/benes.h @@ -0,0 +1,16 @@ +/* + This file is for Benes network related functions +*/ + +#ifndef BENES_H +#define BENES_H +#define apply_benes CRYPTO_NAMESPACE(apply_benes) +#define support_gen CRYPTO_NAMESPACE(support_gen) + +#include "gf.h" + +void apply_benes(unsigned char *, const unsigned char *, int); +void support_gen(gf *, const unsigned char *); + +#endif + diff --git a/deps/mceliece/kem/mceliece6960119f/bm.c b/deps/mceliece/kem/mceliece6960119f/bm.c new file mode 100644 index 0000000..056a734 --- /dev/null +++ b/deps/mceliece/kem/mceliece6960119f/bm.c @@ -0,0 +1,72 @@ +/* + This file is for the Berlekamp-Massey algorithm + see http://crypto.stanford.edu/~mironov/cs359/massey.pdf +*/ + +#include "params.h" +#include "gf.h" +#include "bm.h" + +#define min(a, b) ((a < b) ? a : b) + +/* the Berlekamp-Massey algorithm */ +/* input: s, sequence of field elements */ +/* output: out, minimal polynomial of s */ +void bm(gf *out, gf *s) +{ + int i; + + uint16_t N = 0; + uint16_t L = 0; + uint16_t mle; + uint16_t mne; + + gf T[ SYS_T+1 ]; + gf C[ SYS_T+1 ]; + gf B[ SYS_T+1 ]; + + gf b = 1, d, f; + + // + + for (i = 0; i < SYS_T+1; i++) + C[i] = B[i] = 0; + + B[1] = C[0] = 1; + + // + + for (N = 0; N < 2 * SYS_T; N++) + { + d = 0; + + for (i = 0; i <= min(N, SYS_T); i++) + d ^= gf_mul(C[i], s[ N-i]); + + mne = d; mne -= 1; mne >>= 15; mne -= 1; + mle = N; mle -= 2*L; mle >>= 15; mle -= 1; + mle &= mne; + + for (i = 0; i <= SYS_T; i++) + T[i] = C[i]; + + f = gf_frac(b, d); + + for (i = 0; i <= SYS_T; i++) + C[i] ^= gf_mul(f, B[i]) & mne; + + L = (L & ~mle) | ((N+1-L) & mle); + + for (i = 0; i <= SYS_T; i++) + B[i] = (B[i] & ~mle) | (T[i] & mle); + + b = (b & ~mle) | (d & mle); + + for (i = SYS_T; i >= 1; i--) B[i] = B[i-1]; + B[0] = 0; + } + + for (i = 0; i <= SYS_T; i++) + out[i] = C[ SYS_T-i ]; +} + diff --git a/deps/mceliece/kem/mceliece6960119f/bm.h b/deps/mceliece/kem/mceliece6960119f/bm.h new file mode 100644 index 0000000..73d5c6c --- /dev/null +++ b/deps/mceliece/kem/mceliece6960119f/bm.h @@ -0,0 +1,13 @@ +/* + This file is for the Berlekamp-Massey algorithm + see http://crypto.stanford.edu/~mironov/cs359/massey.pdf +*/ + +#ifndef BM_H +#define BM_H +#define bm CRYPTO_NAMESPACE(bm) + +void bm(gf *, gf *); + +#endif + diff --git a/deps/mceliece/kem/mceliece6960119f/controlbits.c b/deps/mceliece/kem/mceliece6960119f/controlbits.c new file mode 100644 index 0000000..db9db9c --- /dev/null +++ b/deps/mceliece/kem/mceliece6960119f/controlbits.c @@ -0,0 +1,220 @@ +/* This file is for implementing the Nassimi-Sahni algorithm */ +/* See David Nassimi, Sartaj Sahni "Parallel algorithms to set up the Benes permutationnetwork" */ +/* See also https://cr.yp.to/papers/controlbits-20200923.pdf */ + +#include +#include "crypto_declassify.h" +#include "controlbits.h" +#include "int32_sort.h" +typedef int16_t int16; +typedef int32_t int32; +#include "crypto_int32.h" +#define int32_min crypto_int32_min +#include "crypto_int16.h" + +/* parameters: 1 <= w <= 14; n = 2^w */ +/* input: permutation pi of {0,1,...,n-1} */ +/* output: (2m-1)n/2 control bits at positions pos,pos+step,... */ +/* output position pos is by definition 1&(out[pos/8]>>(pos&7)) */ +/* caller must 0-initialize positions first */ +/* temp must have space for int32[2*n] */ +static void cbrecursion(unsigned char *out,long long pos,long long step,const int16 *pi,long long w,long long n,int32 *temp) +{ +#define A temp +#define B (temp+n) +#define q ((int16 *) (temp+n+n/4)) +/* q can start anywhere between temp+n and temp+n/2 */ + + long long x,i,j,k; + + if (w == 1) { + out[pos>>3] ^= pi[0]<<(pos&7); + return; + } + + for (x = 0;x < n;++x) A[x] = ((pi[x]^1)<<16)|pi[x^1]; + int32_sort(A,n); /* A = (id<<16)+pibar */ + + for (x = 0;x < n;++x) { + int32 Ax = A[x]; + int32 px = Ax&0xffff; + int32 cx = int32_min(px,x); + B[x] = (px<<16)|cx; + } + /* B = (p<<16)+c */ + + for (x = 0;x < n;++x) A[x] = (A[x]<<16)|x; /* A = (pibar<<16)+id */ + int32_sort(A,n); /* A = (id<<16)+pibar^-1 */ + + for (x = 0;x < n;++x) A[x] = (A[x]<<16)+(B[x]>>16); /* A = (pibar^(-1)<<16)+pibar */ + int32_sort(A,n); /* A = (id<<16)+pibar^2 */ + + if (w <= 10) { + for (x = 0;x < n;++x) B[x] = ((A[x]&0xffff)<<10)|(B[x]&0x3ff); + + for (i = 1;i < w-1;++i) { + /* B = (p<<10)+c */ + + for (x = 0;x < n;++x) A[x] = ((B[x]&~0x3ff)<<6)|x; /* A = (p<<16)+id */ + int32_sort(A,n); /* A = (id<<16)+p^{-1} */ + + for (x = 0;x < n;++x) A[x] = (A[x]<<20)|B[x]; /* A = (p^{-1}<<20)+(p<<10)+c */ + int32_sort(A,n); /* A = (id<<20)+(pp<<10)+cp */ + + for (x = 0;x < n;++x) { + int32 ppcpx = A[x]&0xfffff; + int32 ppcx = (A[x]&0xffc00)|(B[x]&0x3ff); + B[x] = int32_min(ppcx,ppcpx); + } + } + for (x = 0;x < n;++x) B[x] &= 0x3ff; + } else { + for (x = 0;x < n;++x) B[x] = (A[x]<<16)|(B[x]&0xffff); + + for (i = 1;i < w-1;++i) { + /* B = (p<<16)+c */ + + for (x = 0;x < n;++x) A[x] = (B[x]&~0xffff)|x; + int32_sort(A,n); /* A = (id<<16)+p^(-1) */ + + for (x = 0;x < n;++x) A[x] = (A[x]<<16)|(B[x]&0xffff); + /* A = p^(-1)<<16+c */ + + if (i < w-2) { + for (x = 0;x < n;++x) B[x] = (A[x]&~0xffff)|(B[x]>>16); + /* B = (p^(-1)<<16)+p */ + int32_sort(B,n); /* B = (id<<16)+p^(-2) */ + for (x = 0;x < n;++x) B[x] = (B[x]<<16)|(A[x]&0xffff); + /* B = (p^(-2)<<16)+c */ + } + + int32_sort(A,n); + /* A = id<<16+cp */ + for (x = 0;x < n;++x) { + int32 cpx = (B[x]&~0xffff)|(A[x]&0xffff); + B[x] = int32_min(B[x],cpx); + } + } + for (x = 0;x < n;++x) B[x] &= 0xffff; + } + + for (x = 0;x < n;++x) A[x] = (((int32)pi[x])<<16)+x; + int32_sort(A,n); /* A = (id<<16)+pi^(-1) */ + + for (j = 0;j < n/2;++j) { + long long x = 2*j; + int32 fj = B[x]&1; /* f[j] */ + int32 Fx = x+fj; /* F[x] */ + int32 Fx1 = Fx^1; /* F[x+1] */ + + out[pos>>3] ^= fj<<(pos&7); + pos += step; + + B[x] = (A[x]<<16)|Fx; + B[x+1] = (A[x+1]<<16)|Fx1; + } + /* B = (pi^(-1)<<16)+F */ + + int32_sort(B,n); /* B = (id<<16)+F(pi) */ + + pos += (2*w-3)*step*(n/2); + + for (k = 0;k < n/2;++k) { + long long y = 2*k; + int32 lk = B[y]&1; /* l[k] */ + int32 Ly = y+lk; /* L[y] */ + int32 Ly1 = Ly^1; /* L[y+1] */ + + out[pos>>3] ^= lk<<(pos&7); + pos += step; + + A[y] = (Ly<<16)|(B[y]&0xffff); + A[y+1] = (Ly1<<16)|(B[y+1]&0xffff); + } + /* A = (L<<16)+F(pi) */ + + int32_sort(A,n); /* A = (id<<16)+F(pi(L)) = (id<<16)+M */ + + pos -= (2*w-2)*step*(n/2); + + for (j = 0;j < n/2;++j) { + q[j] = (A[2*j]&0xffff)>>1; + q[j+n/2] = (A[2*j+1]&0xffff)>>1; + } + + cbrecursion(out,pos,step*2,q,w-1,n/2,temp); + cbrecursion(out,pos+step,step*2,q+n/2,w-1,n/2,temp); +} + +/* input: p, an array of int16 */ +/* input: n, length of p */ +/* input: s, meaning that stride-2^s cswaps are performed */ +/* input: cb, the control bits */ +/* output: the result of apply the control bits to p */ +static void layer(int16_t *p, const unsigned char *cb, int s, int n) +{ + int i, j; + int stride = 1 << s; + int index = 0; + int16_t d, m; + + for (i = 0; i < n; i += stride*2) + { + for (j = 0; j < stride; j++) + { + d = p[ i+j ] ^ p[ i+j+stride ]; + m = (cb[ index >> 3 ] >> (index & 7)) & 1; + m = -m; + d &= m; + p[ i+j ] ^= d; + p[ i+j+stride ] ^= d; + index++; + } + } +} + +/* parameters: 1 <= w <= 14; n = 2^w */ +/* input: permutation pi of {0,1,...,n-1} */ +/* output: (2m-1)n/2 control bits at positions 0,1,... */ +/* output position pos is by definition 1&(out[pos/8]>>(pos&7)) */ +void controlbitsfrompermutation(unsigned char *out,const int16 *pi,long long w,long long n) +{ + int32 temp[2*n]; + int16 pi_test[n], diff; + int i; + unsigned char *ptr; + + while (1) + { + memset(out,0,(((2*w-1)*n/2)+7)/8); + cbrecursion(out,0,1,pi,w,n,temp); + + // check for correctness + + for (i = 0; i < n; i++) + pi_test[i] = i; + + ptr = out; + for (i = 0; i < w; i++) + { + layer(pi_test, ptr, i, n); + ptr += n >> 4; + } + + for (i = w-2; i >= 0; i--) + { + layer(pi_test, ptr, i, n); + ptr += n >> 4; + } + + diff = 0; + for (i = 0; i < n; i++) + diff |= pi[i] ^ pi_test[i]; + + diff = crypto_int16_nonzero_mask(diff); + crypto_declassify(&diff,sizeof diff); + if (diff == 0) + break; + } +} + diff --git a/deps/mceliece/kem/mceliece6960119f/controlbits.h b/deps/mceliece/kem/mceliece6960119f/controlbits.h new file mode 100644 index 0000000..8ddd210 --- /dev/null +++ b/deps/mceliece/kem/mceliece6960119f/controlbits.h @@ -0,0 +1,14 @@ +/* This file is for implementing the Nassimi-Sahni algorithm */ +/* See David Nassimi, Sartaj Sahni "Parallel algorithms to set up the Benes permutationnetwork" */ +/* See also https://cr.yp.to/papers/controlbits-20200923.pdf */ + +#ifndef CONTROLBITS_H +#define CONTROLBITS_H + +#define controlbitsfrompermutation CRYPTO_NAMESPACE(controlbitsfrompermutation) + +#include + +extern void controlbitsfrompermutation(unsigned char *,const int16_t *,long long,long long); + +#endif diff --git a/deps/mceliece/kem/mceliece6960119f/crypto_hash.h b/deps/mceliece/kem/mceliece6960119f/crypto_hash.h new file mode 100644 index 0000000..b7c1086 --- /dev/null +++ b/deps/mceliece/kem/mceliece6960119f/crypto_hash.h @@ -0,0 +1,10 @@ +/* This file uses SHAKE256 implemented in the Keccak Code Package */ + +#include "../../mceliece_externals.h" + +#define crypto_hash_32b(out,in,inlen) \ + SHAKE256(out,32,in,inlen) + +#define shake(out,outlen,in,inlen) \ + SHAKE256(out,outlen,in,inlen) + diff --git a/deps/mceliece/kem/mceliece6960119f/crypto_kem.h b/deps/mceliece/kem/mceliece6960119f/crypto_kem.h new file mode 100644 index 0000000..4163978 --- /dev/null +++ b/deps/mceliece/kem/mceliece6960119f/crypto_kem.h @@ -0,0 +1,15 @@ +#ifndef crypto_kem_H +#define crypto_kem_H + +#include "crypto_kem_mceliece6960119f.h" + +#define crypto_kem_keypair crypto_kem_mceliece6960119f_keypair +#define crypto_kem_enc crypto_kem_mceliece6960119f_enc +#define crypto_kem_dec crypto_kem_mceliece6960119f_dec +#define crypto_kem_PUBLICKEYBYTES crypto_kem_mceliece6960119f_PUBLICKEYBYTES +#define crypto_kem_SECRETKEYBYTES crypto_kem_mceliece6960119f_SECRETKEYBYTES +#define crypto_kem_BYTES crypto_kem_mceliece6960119f_BYTES +#define crypto_kem_CIPHERTEXTBYTES crypto_kem_mceliece6960119f_CIPHERTEXTBYTES +#define crypto_kem_PRIMITIVE "mceliece6960119f" + +#endif diff --git a/deps/mceliece/kem/mceliece6960119f/crypto_kem_mceliece6960119f.h b/deps/mceliece/kem/mceliece6960119f/crypto_kem_mceliece6960119f.h new file mode 100644 index 0000000..a054a44 --- /dev/null +++ b/deps/mceliece/kem/mceliece6960119f/crypto_kem_mceliece6960119f.h @@ -0,0 +1,27 @@ +#ifndef crypto_kem_mceliece6960119f_H +#define crypto_kem_mceliece6960119f_H + +#define crypto_kem_mceliece6960119f_ref_PUBLICKEYBYTES 1047319 +#define crypto_kem_mceliece6960119f_ref_SECRETKEYBYTES 13948 +#define crypto_kem_mceliece6960119f_ref_CIPHERTEXTBYTES 194 +#define crypto_kem_mceliece6960119f_ref_BYTES 32 + +#ifdef __cplusplus +extern "C" { +#endif +extern int crypto_kem_mceliece6960119f_ref_keypair(unsigned char *,unsigned char *); +extern int crypto_kem_mceliece6960119f_ref_enc(unsigned char *,unsigned char *,const unsigned char *); +extern int crypto_kem_mceliece6960119f_ref_dec(unsigned char *,const unsigned char *,const unsigned char *); +#ifdef __cplusplus +} +#endif + +#define crypto_kem_mceliece6960119f_keypair crypto_kem_mceliece6960119f_ref_keypair +#define crypto_kem_mceliece6960119f_enc crypto_kem_mceliece6960119f_ref_enc +#define crypto_kem_mceliece6960119f_dec crypto_kem_mceliece6960119f_ref_dec +#define crypto_kem_mceliece6960119f_PUBLICKEYBYTES crypto_kem_mceliece6960119f_ref_PUBLICKEYBYTES +#define crypto_kem_mceliece6960119f_SECRETKEYBYTES crypto_kem_mceliece6960119f_ref_SECRETKEYBYTES +#define crypto_kem_mceliece6960119f_BYTES crypto_kem_mceliece6960119f_ref_BYTES +#define crypto_kem_mceliece6960119f_CIPHERTEXTBYTES crypto_kem_mceliece6960119f_ref_CIPHERTEXTBYTES + +#endif diff --git a/deps/mceliece/kem/mceliece6960119f/decrypt.c b/deps/mceliece/kem/mceliece6960119f/decrypt.c new file mode 100644 index 0000000..c4cc6de --- /dev/null +++ b/deps/mceliece/kem/mceliece6960119f/decrypt.c @@ -0,0 +1,93 @@ +/* + This file is for Niederreiter decryption +*/ + +#include +#include "decrypt.h" + +#include "params.h" +#include "benes.h" +#include "util.h" +#include "synd.h" +#include "root.h" +#include "gf.h" +#include "bm.h" + +/* Niederreiter decryption with the Berlekamp decoder */ +/* intput: sk, secret key */ +/* c, ciphertext */ +/* output: e, error vector */ +/* return: 0 for success; 1 for failure */ +int decrypt(unsigned char *e, const unsigned char *sk, const unsigned char *c) +{ + int i, w = 0; + uint16_t check; + + unsigned char r[ SYS_N/8 ]; + + gf g[ SYS_T+1 ]; + gf L[ SYS_N ]; + + gf s[ SYS_T*2 ]; + gf s_cmp[ SYS_T*2 ]; + gf locator[ SYS_T+1 ]; + gf images[ SYS_N ]; + + gf t; + + // + + for (i = 0; i < SYND_BYTES; i++) r[i] = c[i]; + for (i = SYND_BYTES; i < SYS_N/8; i++) r[i] = 0; + + for (i = 0; i < SYS_T; i++) { g[i] = load_gf(sk); sk += 2; } g[ SYS_T ] = 1; + + support_gen(L, sk); + + synd(s, g, L, r); + + bm(locator, s); + + root(images, locator, L); + + // + + for (i = 0; i < SYS_N/8; i++) + e[i] = 0; + + for (i = 0; i < SYS_N; i++) + { + t = gf_iszero(images[i]) & 1; + + e[ i/8 ] |= t << (i%8); + w += t; + + } + +#ifdef KAT + { + int k; + printf("decrypt e: positions"); + for (k = 0;k < SYS_N;++k) + if (e[k/8] & (1 << (k&7))) + printf(" %d",k); + printf("\n"); + } +#endif + + synd(s_cmp, g, L, e); + + // + + check = w; + check ^= SYS_T; + + for (i = 0; i < SYS_T*2; i++) + check |= s[i] ^ s_cmp[i]; + + check -= 1; + check >>= 15; + + return check ^ 1; +} + diff --git a/deps/mceliece/kem/mceliece6960119f/decrypt.h b/deps/mceliece/kem/mceliece6960119f/decrypt.h new file mode 100644 index 0000000..266a5cd --- /dev/null +++ b/deps/mceliece/kem/mceliece6960119f/decrypt.h @@ -0,0 +1,12 @@ +/* + This file is for Nieddereiter decryption +*/ + +#ifndef DECRYPT_H +#define DECRYPT_H +#define decrypt CRYPTO_NAMESPACE(decrypt) + +int decrypt(unsigned char *, const unsigned char *, const unsigned char *); + +#endif + diff --git a/deps/mceliece/kem/mceliece6960119f/encrypt.c b/deps/mceliece/kem/mceliece6960119f/encrypt.c new file mode 100644 index 0000000..662458d --- /dev/null +++ b/deps/mceliece/kem/mceliece6960119f/encrypt.c @@ -0,0 +1,164 @@ +/* + This file is for Niederreiter encryption +*/ + +#include "encrypt.h" + +#include "util.h" +#include "params.h" +#include "randombytes.h" + +#include +#include +#include +#include + +#include "gf.h" +#include "crypto_declassify.h" +#include "crypto_uint16.h" +#include "crypto_uint32.h" + +static inline crypto_uint16 uint16_is_smaller_declassify(uint16_t t,uint16_t u) +{ + crypto_uint16 mask = crypto_uint16_smaller_mask(t,u); + crypto_declassify(&mask,sizeof mask); + return mask; +} + +static inline crypto_uint32 uint32_is_equal_declassify(uint32_t t,uint32_t u) +{ + crypto_uint32 mask = crypto_uint32_equal_mask(t,u); + crypto_declassify(&mask,sizeof mask); + return mask; +} + +static inline unsigned char same_mask(uint16_t x, uint16_t y) +{ + uint32_t mask; + + mask = x ^ y; + mask -= 1; + mask >>= 31; + mask = -mask; + + return mask & 0xFF; +} + +/* output: e, an error vector of weight t */ +static void gen_e(unsigned char *e) +{ + int i, j, eq, count; + + union + { + uint16_t nums[ SYS_T*2 ]; + unsigned char bytes[ SYS_T*2 * sizeof(uint16_t) ]; + } buf; + + uint16_t ind[ SYS_T ]; + unsigned char mask; + unsigned char val[ SYS_T ]; + + while (1) + { + randombytes(buf.bytes, sizeof(buf)); + + for (i = 0; i < SYS_T*2; i++) + buf.nums[i] = load_gf(buf.bytes + i*2); + + // moving and counting indices in the correct range + + count = 0; + for (i = 0; i < SYS_T*2 && count < SYS_T; i++) + if (uint16_is_smaller_declassify(buf.nums[i],SYS_N)) + ind[ count++ ] = buf.nums[i]; + + if (count < SYS_T) continue; + + // check for repetition + + eq = 0; + + for (i = 1; i < SYS_T; i++) + for (j = 0; j < i; j++) + if (uint32_is_equal_declassify(ind[i],ind[j])) + eq = 1; + + if (eq == 0) + break; + } + + for (j = 0; j < SYS_T; j++) + val[j] = 1 << (ind[j] & 7); + + for (i = 0; i < SYS_N/8; i++) + { + e[i] = 0; + + for (j = 0; j < SYS_T; j++) + { + mask = same_mask(i, (ind[j] >> 3)); + + e[i] |= val[j] & mask; + } + } +} + +/* input: public key pk, error vector e */ +/* output: syndrome s */ +static void syndrome(unsigned char *s, const unsigned char *pk, unsigned char *e) +{ + unsigned char b, row[SYS_N/8]; + const unsigned char *pk_ptr = pk; + + int i, j, tail = PK_NROWS % 8; + + for (i = 0; i < SYND_BYTES; i++) + s[i] = 0; + + for (i = 0; i < PK_NROWS; i++) + { + for (j = 0; j < SYS_N/8; j++) + row[j] = 0; + + for (j = 0; j < PK_ROW_BYTES; j++) + row[ SYS_N/8 - PK_ROW_BYTES + j ] = pk_ptr[j]; + + for (j = SYS_N/8-1; j >= SYS_N/8 - PK_ROW_BYTES; j--) + row[ j ] = (row[ j ] << tail) | (row[j-1] >> (8-tail)); + + row[i/8] |= 1 << (i%8); + + b = 0; + for (j = 0; j < SYS_N/8; j++) + b ^= row[j] & e[j]; + + b ^= b >> 4; + b ^= b >> 2; + b ^= b >> 1; + b &= 1; + + s[ i/8 ] |= (b << (i%8)); + + pk_ptr += PK_ROW_BYTES; + } +} + +void encrypt(unsigned char *s, const unsigned char *pk, unsigned char *e) +{ + gen_e(e); + +#ifdef KAT + { + int k; + printf("encrypt e: positions"); + for (k = 0;k < SYS_N;++k) + if (e[k/8] & (1 << (k&7))) + printf(" %d",k); + printf("\n"); + } +#endif + + syndrome(s, pk, e); +} + diff --git a/deps/mceliece/kem/mceliece6960119f/encrypt.h b/deps/mceliece/kem/mceliece6960119f/encrypt.h new file mode 100644 index 0000000..8edd7a6 --- /dev/null +++ b/deps/mceliece/kem/mceliece6960119f/encrypt.h @@ -0,0 +1,12 @@ +/* + This file is for Niederreiter encryption +*/ + +#ifndef ENCRYPT_H +#define ENCRYPT_H +#define encrypt CRYPTO_NAMESPACE(encrypt) + +void encrypt(unsigned char *, const unsigned char *, unsigned char *); + +#endif + diff --git a/deps/mceliece/kem/mceliece6960119f/gf.c b/deps/mceliece/kem/mceliece6960119f/gf.c new file mode 100644 index 0000000..6a0c2e9 --- /dev/null +++ b/deps/mceliece/kem/mceliece6960119f/gf.c @@ -0,0 +1,213 @@ +/* + This file is for functions for field arithmetic +*/ + +#include "gf.h" + +#include "params.h" + +gf gf_iszero(gf a) +{ + uint32_t t = a; + + t -= 1; + t >>= 19; + + return (gf) t; +} + +gf gf_add(gf in0, gf in1) +{ + return in0 ^ in1; +} + +gf gf_mul(gf in0, gf in1) +{ + int i; + + uint64_t tmp; + uint64_t t0; + uint64_t t1; + uint64_t t; + + t0 = in0; + t1 = in1; + + tmp = t0 * (t1 & 1); + + for (i = 1; i < GFBITS; i++) + tmp ^= (t0 * (t1 & (1 << i))); + + // + + t = tmp & 0x1FF0000; + tmp ^= (t >> 9) ^ (t >> 10) ^ (t >> 12) ^ (t >> 13); + + t = tmp & 0x000E000; + tmp ^= (t >> 9) ^ (t >> 10) ^ (t >> 12) ^ (t >> 13); + + return tmp & GFMASK; +} + +/* input: field element in */ +/* return: (in^2)^2 */ +static inline gf gf_sq2(gf in) +{ + int i; + + const uint64_t B[] = {0x1111111111111111, + 0x0303030303030303, + 0x000F000F000F000F, + 0x000000FF000000FF}; + + const uint64_t M[] = {0x0001FF0000000000, + 0x000000FF80000000, + 0x000000007FC00000, + 0x00000000003FE000}; + + uint64_t x = in; + uint64_t t; + + x = (x | (x << 24)) & B[3]; + x = (x | (x << 12)) & B[2]; + x = (x | (x << 6)) & B[1]; + x = (x | (x << 3)) & B[0]; + + for (i = 0; i < 4; i++) + { + t = x & M[i]; + x ^= (t >> 9) ^ (t >> 10) ^ (t >> 12) ^ (t >> 13); + } + + return x & GFMASK; +} + +/* input: field element in, m */ +/* return: (in^2)*m */ +static inline gf gf_sqmul(gf in, gf m) +{ + int i; + + uint64_t x; + uint64_t t0; + uint64_t t1; + uint64_t t; + + const uint64_t M[] = {0x0000001FF0000000, + 0x000000000FF80000, + 0x000000000007E000}; + + t0 = in; + t1 = m; + + x = (t1 << 6) * (t0 & (1 << 6)); + + t0 ^= (t0 << 7); + + x ^= (t1 * (t0 & (0x04001))); + x ^= (t1 * (t0 & (0x08002))) << 1; + x ^= (t1 * (t0 & (0x10004))) << 2; + x ^= (t1 * (t0 & (0x20008))) << 3; + x ^= (t1 * (t0 & (0x40010))) << 4; + x ^= (t1 * (t0 & (0x80020))) << 5; + + for (i = 0; i < 3; i++) + { + t = x & M[i]; + x ^= (t >> 9) ^ (t >> 10) ^ (t >> 12) ^ (t >> 13); + } + + return x & GFMASK; +} + +/* input: field element in, m */ +/* return: ((in^2)^2)*m */ +static inline gf gf_sq2mul(gf in, gf m) +{ + int i; + + uint64_t x; + uint64_t t0; + uint64_t t1; + uint64_t t; + + const uint64_t M[] = {0x1FF0000000000000, + 0x000FF80000000000, + 0x000007FC00000000, + 0x00000003FE000000, + 0x0000000001FE0000, + 0x000000000001E000}; + + t0 = in; + t1 = m; + + x = (t1 << 18) * (t0 & (1 << 6)); + + t0 ^= (t0 << 21); + + x ^= (t1 * (t0 & (0x010000001))); + x ^= (t1 * (t0 & (0x020000002))) << 3; + x ^= (t1 * (t0 & (0x040000004))) << 6; + x ^= (t1 * (t0 & (0x080000008))) << 9; + x ^= (t1 * (t0 & (0x100000010))) << 12; + x ^= (t1 * (t0 & (0x200000020))) << 15; + + for (i = 0; i < 6; i++) + { + t = x & M[i]; + x ^= (t >> 9) ^ (t >> 10) ^ (t >> 12) ^ (t >> 13); + } + + return x & GFMASK; +} + +/* input: field element den, num */ +/* return: (num/den) */ +gf gf_frac(gf den, gf num) +{ + gf tmp_11; + gf tmp_1111; + gf out; + + tmp_11 = gf_sqmul(den, den); // ^11 + tmp_1111 = gf_sq2mul(tmp_11, tmp_11); // ^1111 + out = gf_sq2(tmp_1111); + out = gf_sq2mul(out, tmp_1111); // ^11111111 + out = gf_sq2(out); + out = gf_sq2mul(out, tmp_1111); // ^111111111111 + + return gf_sqmul(out, num); // ^1111111111110 = ^-1 +} + +gf gf_inv(gf den) +{ + return gf_frac(den, ((gf) 1)); +} + +/* input: in0, in1 in GF((2^m)^t)*/ +/* output: out = in0*in1 */ +void GF_mul(gf *out, gf *in0, gf *in1) +{ + int i, j; + + gf prod[ SYS_T*2-1 ]; + + for (i = 0; i < SYS_T*2-1; i++) + prod[i] = 0; + + for (i = 0; i < SYS_T; i++) + for (j = 0; j < SYS_T; j++) + prod[i+j] ^= gf_mul(in0[i], in1[j]); + + // + + for (i = (SYS_T-1)*2; i >= SYS_T; i--) + { + prod[i - SYS_T + 8] ^= prod[i]; + prod[i - SYS_T + 0] ^= prod[i]; + } + + for (i = 0; i < SYS_T; i++) + out[i] = prod[i]; +} + diff --git a/deps/mceliece/kem/mceliece6960119f/gf.h b/deps/mceliece/kem/mceliece6960119f/gf.h new file mode 100644 index 0000000..f62209d --- /dev/null +++ b/deps/mceliece/kem/mceliece6960119f/gf.h @@ -0,0 +1,27 @@ +/* + This file is for functions for field arithmetic +*/ + +#ifndef GF_H +#define GF_H +#define gf_add CRYPTO_NAMESPACE(gf_add) +#define gf_frac CRYPTO_NAMESPACE(gf_frac) +#define gf_inv CRYPTO_NAMESPACE(gf_inv) +#define gf_iszero CRYPTO_NAMESPACE(gf_iszero) +#define gf_mul CRYPTO_NAMESPACE(gf_mul) +#define GF_mul CRYPTO_NAMESPACE(GF_mul) + +#include + +typedef uint16_t gf; + +gf gf_iszero(gf); +gf gf_add(gf, gf); +gf gf_mul(gf, gf); +gf gf_frac(gf, gf); +gf gf_inv(gf); + +void GF_mul(gf *, gf *, gf *); + +#endif + diff --git a/deps/mceliece/kem/mceliece6960119f/int32_sort.h b/deps/mceliece/kem/mceliece6960119f/int32_sort.h new file mode 100644 index 0000000..a431af2 --- /dev/null +++ b/deps/mceliece/kem/mceliece6960119f/int32_sort.h @@ -0,0 +1,46 @@ +#ifndef int32_sort_h +#define int32_sort_h + +#define int32_sort CRYPTO_NAMESPACE(int32_sort) + +#include + +#define int32_MINMAX(a,b) \ +do { \ + int32_t ab = b ^ a; \ + int32_t c = b - a; \ + c ^= ab & (c ^ b); \ + c >>= 31; \ + c &= ab; \ + a ^= c; \ + b ^= c; \ +} while(0) + +static void int32_sort(int32_t *x,long long n) +{ + long long top,p,q,r,i; + + if (n < 2) return; + top = 1; + while (top < n - top) top += top; + + for (p = top;p > 0;p >>= 1) { + for (i = 0;i < n - p;++i) + if (!(i & p)) + int32_MINMAX(x[i],x[i+p]); + i = 0; + for (q = top;q > p;q >>= 1) { + for (;i < n - q;++i) { + if (!(i & p)) { + int32_t a = x[i + p]; + for (r = q;r > p;r >>= 1) + int32_MINMAX(a,x[i+r]); + x[i + p] = a; + } + } + } + } +} + +#endif + diff --git a/deps/mceliece/kem/mceliece6960119f/operations.c b/deps/mceliece/kem/mceliece6960119f/operations.c new file mode 100644 index 0000000..132ce8b --- /dev/null +++ b/deps/mceliece/kem/mceliece6960119f/operations.c @@ -0,0 +1,204 @@ +#include "operations.h" + +#include "controlbits.h" +#include "randombytes.h" +#include "crypto_hash.h" +#include "encrypt.h" +#include "decrypt.h" +#include "params.h" +#include "sk_gen.h" +#include "pk_gen.h" +#include "util.h" + +#include +#include + +/* check if the padding bits of pk are all zero */ +static int check_pk_padding(const unsigned char * pk) +{ + unsigned char b; + int i, ret; + + b = 0; + for (i = 0; i < PK_NROWS; i++) + b |= pk[i*PK_ROW_BYTES + PK_ROW_BYTES-1]; + + b >>= (PK_NCOLS % 8); + b -= 1; + b >>= 7; + ret = b; + + return ret-1; +} + +int crypto_kem_enc( + unsigned char *c, + unsigned char *key, + const unsigned char *pk +) +{ + unsigned char e[ SYS_N/8 ]; + unsigned char one_ec[ 1 + SYS_N/8 + SYND_BYTES ] = {1}; + unsigned char mask; + int i, padding_ok; + + // + + padding_ok = check_pk_padding(pk); + + encrypt(c, pk, e); + + memcpy(one_ec + 1, e, SYS_N/8); + memcpy(one_ec + 1 + SYS_N/8, c, SYND_BYTES); + + crypto_hash_32b(key, one_ec, sizeof(one_ec)); + + // clear outputs (set to all 0's) if padding bits are not all zero + + mask = padding_ok; + mask ^= 0xFF; + + for (i = 0; i < SYND_BYTES; i++) + c[i] &= mask; + + for (i = 0; i < 32; i++) + key[i] &= mask; + + return padding_ok; +} + +/* check if the padding bits of c are all zero */ +static int check_c_padding(const unsigned char * c) +{ + unsigned char b; + int ret; + + b = c[ SYND_BYTES-1 ] >> (PK_NROWS % 8); + b -= 1; + b >>= 7; + ret = b; + + return ret-1; +} + +int crypto_kem_dec( + unsigned char *key, + const unsigned char *c, + const unsigned char *sk +) +{ + int i, padding_ok; + + unsigned char mask; + unsigned char ret_decrypt = 0; + + uint16_t m; + + unsigned char e[ SYS_N/8 ]; + unsigned char preimage[ 1 + SYS_N/8 + SYND_BYTES ]; + unsigned char *x = preimage; + const unsigned char *s = sk + 40 + IRR_BYTES + COND_BYTES; + + // + + padding_ok = check_c_padding(c); + + ret_decrypt = decrypt(e, sk + 40, c); + + m = ret_decrypt; + m -= 1; + m >>= 8; + + *x++ = m & 1; + for (i = 0; i < SYS_N/8; i++) + *x++ = (~m & s[i]) | (m & e[i]); + + for (i = 0; i < SYND_BYTES; i++) + *x++ = c[i]; + + crypto_hash_32b(key, preimage, sizeof(preimage)); + + // clear outputs (set to all 1's) if padding bits are not all zero + + mask = padding_ok; + + for (i = 0; i < 32; i++) + key[i] |= mask; + + return padding_ok; +} + +int crypto_kem_keypair +( + unsigned char *pk, + unsigned char *sk +) +{ + int i; + unsigned char seed[ 33 ] = {64}; + unsigned char r[ SYS_N/8 + (1 << GFBITS)*sizeof(uint32_t) + SYS_T*2 + 32 ]; + unsigned char *rp, *skp; + uint64_t pivots; + + gf f[ SYS_T ]; // element in GF(2^mt) + gf irr[ SYS_T ]; // Goppa polynomial + uint32_t perm[ 1 << GFBITS ]; // random permutation as 32-bit integers + int16_t pi[ 1 << GFBITS ]; // random permutation + + randombytes(seed+1, 32); + + while (1) + { + rp = &r[ sizeof(r)-32 ]; + skp = sk; + + // expanding and updating the seed + + shake(r, sizeof(r), seed, 33); + memcpy(skp, seed+1, 32); + skp += 32 + 8; + memcpy(seed+1, &r[ sizeof(r)-32 ], 32); + + // generating irreducible polynomial + + rp -= sizeof(f); + + for (i = 0; i < SYS_T; i++) + f[i] = load_gf(rp + i*2); + + if (genpoly_gen(irr, f)) + continue; + + for (i = 0; i < SYS_T; i++) + store_gf(skp + i*2, irr[i]); + + skp += IRR_BYTES; + + // generating permutation + + rp -= sizeof(perm); + + for (i = 0; i < (1 << GFBITS); i++) + perm[i] = load4(rp + i*4); + + if (pk_gen(pk, skp - IRR_BYTES, perm, pi, &pivots)) + continue; + + controlbitsfrompermutation(skp, pi, GFBITS, 1 << GFBITS); + skp += COND_BYTES; + + // storing the random string s + + rp -= SYS_N/8; + memcpy(skp, rp, SYS_N/8); + + // storing positions of the 32 pivots + + store8(sk + 32, pivots); + + break; + } + + return 0; +} + diff --git a/deps/mceliece/kem/mceliece6960119f/operations.h b/deps/mceliece/kem/mceliece6960119f/operations.h new file mode 100644 index 0000000..bf65502 --- /dev/null +++ b/deps/mceliece/kem/mceliece6960119f/operations.h @@ -0,0 +1,25 @@ +#ifndef OPERATIONS_H +#define OPERATIONS_H + +#include "crypto_kem.h" + +int crypto_kem_enc( + unsigned char *c, + unsigned char *key, + const unsigned char *pk +); + +int crypto_kem_dec( + unsigned char *key, + const unsigned char *c, + const unsigned char *sk +); + +int crypto_kem_keypair +( + unsigned char *pk, + unsigned char *sk +); + +#endif + diff --git a/deps/mceliece/kem/mceliece6960119f/params.h b/deps/mceliece/kem/mceliece6960119f/params.h new file mode 100644 index 0000000..6457fa6 --- /dev/null +++ b/deps/mceliece/kem/mceliece6960119f/params.h @@ -0,0 +1,20 @@ +#ifndef PARAMS_H +#define PARAMS_H + +#define GFBITS 13 +#define SYS_N 6960 +#define SYS_T 119 + +#define COND_BYTES ((1 << (GFBITS-4))*(2*GFBITS - 1)) +#define IRR_BYTES (SYS_T * 2) + +#define PK_NROWS (SYS_T*GFBITS) +#define PK_NCOLS (SYS_N - PK_NROWS) +#define PK_ROW_BYTES ((PK_NCOLS + 7)/8) + +#define SYND_BYTES ((PK_NROWS + 7)/8) + +#define GFMASK ((1 << GFBITS) - 1) + +#endif + diff --git a/deps/mceliece/kem/mceliece6960119f/pk_gen.c b/deps/mceliece/kem/mceliece6960119f/pk_gen.c new file mode 100644 index 0000000..a1e7a8c --- /dev/null +++ b/deps/mceliece/kem/mceliece6960119f/pk_gen.c @@ -0,0 +1,278 @@ +/* + This file is for public-key generation +*/ + +#include +#include +#include +#include + +#include "controlbits.h" +#include "uint64_sort.h" +#include "pk_gen.h" +#include "params.h" +#include "benes.h" +#include "root.h" +#include "util.h" +#include "crypto_declassify.h" +#include "crypto_uint64.h" + +static crypto_uint64 uint64_is_equal_declassify(uint64_t t,uint64_t u) +{ + crypto_uint64 mask = crypto_uint64_equal_mask(t,u); + crypto_declassify(&mask,sizeof mask); + return mask; +} + +static crypto_uint64 uint64_is_zero_declassify(uint64_t t) +{ + crypto_uint64 mask = crypto_uint64_zero_mask(t); + crypto_declassify(&mask,sizeof mask); + return mask; +} + +#define min(a, b) ((a < b) ? a : b) + +/* return number of trailing zeros of the non-zero input in */ +static inline int ctz(uint64_t in) +{ + int i, b, m = 0, r = 0; + + for (i = 0; i < 64; i++) + { + b = (in >> i) & 1; + m |= b; + r += (m^1) & (b^1); + } + + return r; +} + +static inline uint64_t same_mask(uint16_t x, uint16_t y) +{ + uint64_t mask; + + mask = x ^ y; + mask -= 1; + mask >>= 63; + mask = -mask; + + return mask; +} + +static int mov_columns(uint8_t mat[][ SYS_N/8 ], int16_t * pi, uint64_t * pivots) +{ + int i, j, k, s, block_idx, row, tail; + uint64_t buf[64], ctz_list[32], t, d, mask, one = 1; + unsigned char tmp[9]; + + row = PK_NROWS - 32; + block_idx = row/8; + tail = row % 8; + + // extract the 32x64 matrix + + for (i = 0; i < 32; i++) + { + for (j = 0; j < 9; j++) tmp[j] = mat[ row + i ][ block_idx + j ]; + for (j = 0; j < 8; j++) tmp[j] = (tmp[j] >> tail) | (tmp[j+1] << (8-tail)); + + buf[i] = load8( tmp ); + } + + // compute the column indices of pivots by Gaussian elimination. + // the indices are stored in ctz_list + + *pivots = 0; + + for (i = 0; i < 32; i++) + { + t = buf[i]; + for (j = i+1; j < 32; j++) + t |= buf[j]; + + if (uint64_is_zero_declassify(t)) return -1; // return if buf is not full rank + + ctz_list[i] = s = ctz(t); + *pivots |= one << ctz_list[i]; + + for (j = i+1; j < 32; j++) { mask = (buf[i] >> s) & 1; mask -= 1; buf[i] ^= buf[j] & mask; } + for (j = i+1; j < 32; j++) { mask = (buf[j] >> s) & 1; mask = -mask; buf[j] ^= buf[i] & mask; } + } + + // updating permutation + + for (j = 0; j < 32; j++) + for (k = j+1; k < 64; k++) + { + d = pi[ row + j ] ^ pi[ row + k ]; + d &= same_mask(k, ctz_list[j]); + pi[ row + j ] ^= d; + pi[ row + k ] ^= d; + } + + // moving columns of mat according to the column indices of pivots + + for (i = 0; i < PK_NROWS; i++) + { + + for (k = 0; k < 9; k++) tmp[k] = mat[ i ][ block_idx + k ]; + for (k = 0; k < 8; k++) tmp[k] = (tmp[k] >> tail) | (tmp[k+1] << (8-tail)); + + t = load8( tmp ); + + for (j = 0; j < 32; j++) + { + d = t >> j; + d ^= t >> ctz_list[j]; + d &= 1; + + t ^= d << ctz_list[j]; + t ^= d << j; + } + + store8( tmp, t ); + + mat[ i ][ block_idx + 8 ] = (mat[ i ][ block_idx + 8 ] >> tail << tail) | (tmp[7] >> (8-tail)); + mat[ i ][ block_idx + 0 ] = (tmp[0] << tail) | (mat[ i ][ block_idx ] << (8-tail) >> (8-tail)); + + for (k = 7; k >= 1; k--) + mat[ i ][ block_idx + k ] = (tmp[k] << tail) | (tmp[k-1] >> (8-tail)); + } + + return 0; +} + +/* input: secret key sk */ +/* output: public key pk */ +int pk_gen(unsigned char * pk, unsigned char * sk, uint32_t * perm, int16_t * pi, uint64_t * pivots) +{ + unsigned char *pk_ptr = pk; + + int i, j, k; + int row, c, tail; + + uint64_t buf[ 1 << GFBITS ]; + + unsigned char mat[ PK_NROWS ][ SYS_N/8 ]; + unsigned char mask; + unsigned char b; + + gf g[ SYS_T+1 ]; // Goppa polynomial + gf L[ SYS_N ]; // support + gf inv[ SYS_N ]; + + // + + g[ SYS_T ] = 1; + + for (i = 0; i < SYS_T; i++) { g[i] = load_gf(sk); sk += 2; } + + for (i = 0; i < (1 << GFBITS); i++) + { + buf[i] = perm[i]; + buf[i] <<= 31; + buf[i] |= i; + } + + uint64_sort(buf, 1 << GFBITS); + + for (i = 1; i < (1 << GFBITS); i++) + if (uint64_is_equal_declassify(buf[i-1] >> 31,buf[i] >> 31)) + return -1; + + for (i = 0; i < (1 << GFBITS); i++) pi[i] = buf[i] & GFMASK; + for (i = 0; i < SYS_N; i++) L[i] = bitrev(pi[i]); + + // filling the matrix + + root(inv, g, L); + + for (i = 0; i < SYS_N; i++) + inv[i] = gf_inv(inv[i]); + + for (i = 0; i < PK_NROWS; i++) + for (j = 0; j < SYS_N/8; j++) + mat[i][j] = 0; + + for (i = 0; i < SYS_T; i++) + { + for (j = 0; j < SYS_N; j+=8) + for (k = 0; k < GFBITS; k++) + { + b = (inv[j+7] >> k) & 1; b <<= 1; + b |= (inv[j+6] >> k) & 1; b <<= 1; + b |= (inv[j+5] >> k) & 1; b <<= 1; + b |= (inv[j+4] >> k) & 1; b <<= 1; + b |= (inv[j+3] >> k) & 1; b <<= 1; + b |= (inv[j+2] >> k) & 1; b <<= 1; + b |= (inv[j+1] >> k) & 1; b <<= 1; + b |= (inv[j+0] >> k) & 1; + + mat[ i*GFBITS + k ][ j/8 ] = b; + } + + for (j = 0; j < SYS_N; j++) + inv[j] = gf_mul(inv[j], L[j]); + + } + + // gaussian elimination + + for (i = 0; i < (PK_NROWS + 7) / 8; i++) + for (j = 0; j < 8; j++) + { + row = i*8 + j; + + if (row >= PK_NROWS) + break; + + if (row == PK_NROWS - 32) + { + if (mov_columns(mat, pi, pivots)) + return -1; + } + + for (k = row + 1; k < PK_NROWS; k++) + { + mask = mat[ row ][ i ] ^ mat[ k ][ i ]; + mask >>= j; + mask &= 1; + mask = -mask; + + for (c = 0; c < SYS_N/8; c++) + mat[ row ][ c ] ^= mat[ k ][ c ] & mask; + } + + if ( uint64_is_zero_declassify((mat[ row ][ i ] >> j) & 1) ) // return if not systematic + { + return -1; + } + + for (k = 0; k < PK_NROWS; k++) + { + if (k != row) + { + mask = mat[ k ][ i ] >> j; + mask &= 1; + mask = -mask; + + for (c = 0; c < SYS_N/8; c++) + mat[ k ][ c ] ^= mat[ row ][ c ] & mask; + } + } + } + + tail = PK_NROWS % 8; + + for (i = 0; i < PK_NROWS; i++) + { + for (j = (PK_NROWS - 1)/8; j < SYS_N/8 - 1; j++) + *pk_ptr++ = (mat[i][j] >> tail) | (mat[i][j+1] << (8-tail)); + + *pk_ptr++ = (mat[i][j] >> tail); + } + + return 0; +} + diff --git a/deps/mceliece/kem/mceliece6960119f/pk_gen.h b/deps/mceliece/kem/mceliece6960119f/pk_gen.h new file mode 100644 index 0000000..96b7e7b --- /dev/null +++ b/deps/mceliece/kem/mceliece6960119f/pk_gen.h @@ -0,0 +1,14 @@ +/* + This file is for public-key generation +*/ + +#ifndef PK_GEN_H +#define PK_GEN_H +#define pk_gen CRYPTO_NAMESPACE(pk_gen) + +#include "gf.h" + +int pk_gen(unsigned char *, unsigned char *, uint32_t *, int16_t *, uint64_t *); + +#endif + diff --git a/deps/mceliece/kem/mceliece6960119f/randombytes.h b/deps/mceliece/kem/mceliece6960119f/randombytes.h new file mode 100644 index 0000000..7e59351 --- /dev/null +++ b/deps/mceliece/kem/mceliece6960119f/randombytes.h @@ -0,0 +1 @@ +#include "../../mceliece_externals.h" diff --git a/deps/mceliece/kem/mceliece6960119f/root.c b/deps/mceliece/kem/mceliece6960119f/root.c new file mode 100644 index 0000000..1c1b634 --- /dev/null +++ b/deps/mceliece/kem/mceliece6960119f/root.c @@ -0,0 +1,38 @@ +/* + This file is for evaluating a polynomial at one or more field elements +*/ + +#include "root.h" +#include "params.h" +#include "gf.h" + +#include + +/* input: polynomial f and field element a */ +/* return f(a) */ +gf eval(gf *f, gf a) +{ + int i; + gf r; + + r = f[ SYS_T ]; + + for (i = SYS_T-1; i >= 0; i--) + { + r = gf_mul(r, a); + r = gf_add(r, f[i]); + } + + return r; +} + +/* input: polynomial f and list of field elements L */ +/* output: out = [ f(a) for a in L ] */ +void root(gf *out, gf *f, gf *L) +{ + int i; + + for (i = 0; i < SYS_N; i++) + out[i] = eval(f, L[i]); +} + diff --git a/deps/mceliece/kem/mceliece6960119f/root.h b/deps/mceliece/kem/mceliece6960119f/root.h new file mode 100644 index 0000000..42516e4 --- /dev/null +++ b/deps/mceliece/kem/mceliece6960119f/root.h @@ -0,0 +1,16 @@ +/* + This file is for evaluating a polynomial at one or more field elements +*/ + +#ifndef ROOT_H +#define ROOT_H +#define eval CRYPTO_NAMESPACE(eval) +#define root CRYPTO_NAMESPACE(root) + +#include "gf.h" + +gf eval(gf *, gf); +void root(gf *, gf *, gf *); + +#endif + diff --git a/deps/mceliece/kem/mceliece6960119f/sk_gen.c b/deps/mceliece/kem/mceliece6960119f/sk_gen.c new file mode 100644 index 0000000..340cc9a --- /dev/null +++ b/deps/mceliece/kem/mceliece6960119f/sk_gen.c @@ -0,0 +1,85 @@ +/* + This file is for secret-key generation +*/ + +#include "sk_gen.h" + +#include "randombytes.h" +#include "controlbits.h" +#include "params.h" +#include "util.h" +#include "gf.h" +#include "crypto_declassify.h" +#include "crypto_uint16.h" + +static inline crypto_uint16 gf_is_zero_declassify(gf t) +{ + crypto_uint16 mask = crypto_uint16_zero_mask(t); + crypto_declassify(&mask,sizeof mask); + return mask; +} + +/* input: f, element in GF((2^m)^t) */ +/* output: out, minimal polynomial of f */ +/* return: 0 for success and -1 for failure */ +int genpoly_gen(gf *out, gf *f) +{ + int i, j, k, c; + + gf mat[ SYS_T+1 ][ SYS_T ]; + gf mask, inv, t; + + // fill matrix + + mat[0][0] = 1; + + for (i = 1; i < SYS_T; i++) + mat[0][i] = 0; + + for (i = 0; i < SYS_T; i++) + mat[1][i] = f[i]; + + for (j = 2; j <= SYS_T; j++) + GF_mul(mat[j], mat[j-1], f); + + // gaussian + + for (j = 0; j < SYS_T; j++) + { + for (k = j + 1; k < SYS_T; k++) + { + mask = gf_iszero(mat[ j ][ j ]); + + for (c = j; c < SYS_T + 1; c++) + mat[ c ][ j ] ^= mat[ c ][ k ] & mask; + + } + + if ( gf_is_zero_declassify(mat[ j ][ j ]) ) // return if not systematic + { + return -1; + } + + inv = gf_inv(mat[j][j]); + + for (c = j; c < SYS_T + 1; c++) + mat[ c ][ j ] = gf_mul(mat[ c ][ j ], inv) ; + + for (k = 0; k < SYS_T; k++) + { + if (k != j) + { + t = mat[ j ][ k ]; + + for (c = j; c < SYS_T + 1; c++) + mat[ c ][ k ] ^= gf_mul(mat[ c ][ j ], t); + } + } + } + + for (i = 0; i < SYS_T; i++) + out[i] = mat[ SYS_T ][ i ]; + + return 0; +} + diff --git a/deps/mceliece/kem/mceliece6960119f/sk_gen.h b/deps/mceliece/kem/mceliece6960119f/sk_gen.h new file mode 100644 index 0000000..e319703 --- /dev/null +++ b/deps/mceliece/kem/mceliece6960119f/sk_gen.h @@ -0,0 +1,18 @@ +/* + This file is for secret-key generation +*/ + +#ifndef SK_GEN_H +#define SK_GEN_H +#define genpoly_gen CRYPTO_NAMESPACE(genpoly_gen) +#define perm_check CRYPTO_NAMESPACE(perm_check) + +#include "gf.h" + +#include + +int genpoly_gen(gf *, gf *); +int perm_check(uint32_t *); + +#endif + diff --git a/deps/mceliece/kem/mceliece6960119f/subroutines/crypto_declassify.h b/deps/mceliece/kem/mceliece6960119f/subroutines/crypto_declassify.h new file mode 100644 index 0000000..8d84209 --- /dev/null +++ b/deps/mceliece/kem/mceliece6960119f/subroutines/crypto_declassify.h @@ -0,0 +1,8 @@ +#ifndef crypto_declassify_h +#define crypto_declassify_h + +static void crypto_declassify(void *x,unsigned long long n) +{ +} + +#endif diff --git a/deps/mceliece/kem/mceliece6960119f/subroutines/crypto_int16.h b/deps/mceliece/kem/mceliece6960119f/subroutines/crypto_int16.h new file mode 100644 index 0000000..72bbf52 --- /dev/null +++ b/deps/mceliece/kem/mceliece6960119f/subroutines/crypto_int16.h @@ -0,0 +1,81 @@ +#ifndef crypto_int16_h +#define crypto_int16_h + +#include +typedef int16_t crypto_int16; + +static crypto_int16 crypto_int16_negative_mask(crypto_int16 crypto_int16_x) +{ + return crypto_int16_x >> 15; +} + +static crypto_int16 crypto_int16_nonzero_mask(crypto_int16 crypto_int16_x) +{ + return crypto_int16_negative_mask(crypto_int16_x) | crypto_int16_negative_mask(-crypto_int16_x); +} + +static crypto_int16 crypto_int16_zero_mask(crypto_int16 crypto_int16_x) +{ + return ~crypto_int16_nonzero_mask(crypto_int16_x); +} + +static crypto_int16 crypto_int16_positive_mask(crypto_int16 crypto_int16_x) +{ + crypto_int16 crypto_int16_z = -crypto_int16_x; + crypto_int16_z ^= crypto_int16_x & crypto_int16_z; + return crypto_int16_negative_mask(crypto_int16_z); +} + +static crypto_int16 crypto_int16_unequal_mask(crypto_int16 crypto_int16_x,crypto_int16 crypto_int16_y) +{ + crypto_int16 crypto_int16_xy = crypto_int16_x ^ crypto_int16_y; + return crypto_int16_nonzero_mask(crypto_int16_xy); +} + +static crypto_int16 crypto_int16_equal_mask(crypto_int16 crypto_int16_x,crypto_int16 crypto_int16_y) +{ + return ~crypto_int16_unequal_mask(crypto_int16_x,crypto_int16_y); +} + +static crypto_int16 crypto_int16_smaller_mask(crypto_int16 crypto_int16_x,crypto_int16 crypto_int16_y) +{ + crypto_int16 crypto_int16_xy = crypto_int16_x ^ crypto_int16_y; + crypto_int16 crypto_int16_z = crypto_int16_x - crypto_int16_y; + crypto_int16_z ^= crypto_int16_xy & (crypto_int16_z ^ crypto_int16_x); + return crypto_int16_negative_mask(crypto_int16_z); +} + +static crypto_int16 crypto_int16_min(crypto_int16 crypto_int16_x,crypto_int16 crypto_int16_y) +{ + crypto_int16 crypto_int16_xy = crypto_int16_y ^ crypto_int16_x; + crypto_int16 crypto_int16_z = crypto_int16_y - crypto_int16_x; + crypto_int16_z ^= crypto_int16_xy & (crypto_int16_z ^ crypto_int16_y); + crypto_int16_z = crypto_int16_negative_mask(crypto_int16_z); + crypto_int16_z &= crypto_int16_xy; + return crypto_int16_x ^ crypto_int16_z; +} + +static crypto_int16 crypto_int16_max(crypto_int16 crypto_int16_x,crypto_int16 crypto_int16_y) +{ + crypto_int16 crypto_int16_xy = crypto_int16_y ^ crypto_int16_x; + crypto_int16 crypto_int16_z = crypto_int16_y - crypto_int16_x; + crypto_int16_z ^= crypto_int16_xy & (crypto_int16_z ^ crypto_int16_y); + crypto_int16_z = crypto_int16_negative_mask(crypto_int16_z); + crypto_int16_z &= crypto_int16_xy; + return crypto_int16_y ^ crypto_int16_z; +} + +static void crypto_int16_minmax(crypto_int16 *crypto_int16_a,crypto_int16 *crypto_int16_b) +{ + crypto_int16 crypto_int16_x = *crypto_int16_a; + crypto_int16 crypto_int16_y = *crypto_int16_b; + crypto_int16 crypto_int16_xy = crypto_int16_y ^ crypto_int16_x; + crypto_int16 crypto_int16_z = crypto_int16_y - crypto_int16_x; + crypto_int16_z ^= crypto_int16_xy & (crypto_int16_z ^ crypto_int16_y); + crypto_int16_z = crypto_int16_negative_mask(crypto_int16_z); + crypto_int16_z &= crypto_int16_xy; + *crypto_int16_a = crypto_int16_x ^ crypto_int16_z; + *crypto_int16_b = crypto_int16_y ^ crypto_int16_z; +} + +#endif diff --git a/deps/mceliece/kem/mceliece6960119f/subroutines/crypto_int32.h b/deps/mceliece/kem/mceliece6960119f/subroutines/crypto_int32.h new file mode 100644 index 0000000..c22f735 --- /dev/null +++ b/deps/mceliece/kem/mceliece6960119f/subroutines/crypto_int32.h @@ -0,0 +1,81 @@ +#ifndef crypto_int32_h +#define crypto_int32_h + +#include +typedef int32_t crypto_int32; + +static crypto_int32 crypto_int32_negative_mask(crypto_int32 crypto_int32_x) +{ + return crypto_int32_x >> 31; +} + +static crypto_int32 crypto_int32_nonzero_mask(crypto_int32 crypto_int32_x) +{ + return crypto_int32_negative_mask(crypto_int32_x) | crypto_int32_negative_mask(-crypto_int32_x); +} + +static crypto_int32 crypto_int32_zero_mask(crypto_int32 crypto_int32_x) +{ + return ~crypto_int32_nonzero_mask(crypto_int32_x); +} + +static crypto_int32 crypto_int32_positive_mask(crypto_int32 crypto_int32_x) +{ + crypto_int32 crypto_int32_z = -crypto_int32_x; + crypto_int32_z ^= crypto_int32_x & crypto_int32_z; + return crypto_int32_negative_mask(crypto_int32_z); +} + +static crypto_int32 crypto_int32_unequal_mask(crypto_int32 crypto_int32_x,crypto_int32 crypto_int32_y) +{ + crypto_int32 crypto_int32_xy = crypto_int32_x ^ crypto_int32_y; + return crypto_int32_nonzero_mask(crypto_int32_xy); +} + +static crypto_int32 crypto_int32_equal_mask(crypto_int32 crypto_int32_x,crypto_int32 crypto_int32_y) +{ + return ~crypto_int32_unequal_mask(crypto_int32_x,crypto_int32_y); +} + +static crypto_int32 crypto_int32_smaller_mask(crypto_int32 crypto_int32_x,crypto_int32 crypto_int32_y) +{ + crypto_int32 crypto_int32_xy = crypto_int32_x ^ crypto_int32_y; + crypto_int32 crypto_int32_z = crypto_int32_x - crypto_int32_y; + crypto_int32_z ^= crypto_int32_xy & (crypto_int32_z ^ crypto_int32_x); + return crypto_int32_negative_mask(crypto_int32_z); +} + +static crypto_int32 crypto_int32_min(crypto_int32 crypto_int32_x,crypto_int32 crypto_int32_y) +{ + crypto_int32 crypto_int32_xy = crypto_int32_y ^ crypto_int32_x; + crypto_int32 crypto_int32_z = crypto_int32_y - crypto_int32_x; + crypto_int32_z ^= crypto_int32_xy & (crypto_int32_z ^ crypto_int32_y); + crypto_int32_z = crypto_int32_negative_mask(crypto_int32_z); + crypto_int32_z &= crypto_int32_xy; + return crypto_int32_x ^ crypto_int32_z; +} + +static crypto_int32 crypto_int32_max(crypto_int32 crypto_int32_x,crypto_int32 crypto_int32_y) +{ + crypto_int32 crypto_int32_xy = crypto_int32_y ^ crypto_int32_x; + crypto_int32 crypto_int32_z = crypto_int32_y - crypto_int32_x; + crypto_int32_z ^= crypto_int32_xy & (crypto_int32_z ^ crypto_int32_y); + crypto_int32_z = crypto_int32_negative_mask(crypto_int32_z); + crypto_int32_z &= crypto_int32_xy; + return crypto_int32_y ^ crypto_int32_z; +} + +static void crypto_int32_minmax(crypto_int32 *crypto_int32_a,crypto_int32 *crypto_int32_b) +{ + crypto_int32 crypto_int32_x = *crypto_int32_a; + crypto_int32 crypto_int32_y = *crypto_int32_b; + crypto_int32 crypto_int32_xy = crypto_int32_y ^ crypto_int32_x; + crypto_int32 crypto_int32_z = crypto_int32_y - crypto_int32_x; + crypto_int32_z ^= crypto_int32_xy & (crypto_int32_z ^ crypto_int32_y); + crypto_int32_z = crypto_int32_negative_mask(crypto_int32_z); + crypto_int32_z &= crypto_int32_xy; + *crypto_int32_a = crypto_int32_x ^ crypto_int32_z; + *crypto_int32_b = crypto_int32_y ^ crypto_int32_z; +} + +#endif diff --git a/deps/mceliece/kem/mceliece6960119f/subroutines/crypto_uint16.h b/deps/mceliece/kem/mceliece6960119f/subroutines/crypto_uint16.h new file mode 100644 index 0000000..f0ebbbf --- /dev/null +++ b/deps/mceliece/kem/mceliece6960119f/subroutines/crypto_uint16.h @@ -0,0 +1,76 @@ +#ifndef crypto_uint16_h +#define crypto_uint16_h + +#include +typedef uint16_t crypto_uint16; + +typedef int16_t crypto_uint16_signed; + +static crypto_uint16_signed crypto_uint16_signed_negative_mask(crypto_uint16_signed crypto_uint16_signed_x) +{ + return crypto_uint16_signed_x >> 15; +} + +static crypto_uint16 crypto_uint16_nonzero_mask(crypto_uint16 crypto_uint16_x) +{ + return crypto_uint16_signed_negative_mask(crypto_uint16_x) | crypto_uint16_signed_negative_mask(-crypto_uint16_x); +} + +static crypto_uint16 crypto_uint16_zero_mask(crypto_uint16 crypto_uint16_x) +{ + return ~crypto_uint16_nonzero_mask(crypto_uint16_x); +} + +static crypto_uint16 crypto_uint16_unequal_mask(crypto_uint16 crypto_uint16_x,crypto_uint16 crypto_uint16_y) +{ + crypto_uint16 crypto_uint16_xy = crypto_uint16_x ^ crypto_uint16_y; + return crypto_uint16_nonzero_mask(crypto_uint16_xy); +} + +static crypto_uint16 crypto_uint16_equal_mask(crypto_uint16 crypto_uint16_x,crypto_uint16 crypto_uint16_y) +{ + return ~crypto_uint16_unequal_mask(crypto_uint16_x,crypto_uint16_y); +} + +static crypto_uint16 crypto_uint16_smaller_mask(crypto_uint16 crypto_uint16_x,crypto_uint16 crypto_uint16_y) +{ + crypto_uint16 crypto_uint16_xy = crypto_uint16_x ^ crypto_uint16_y; + crypto_uint16 crypto_uint16_z = crypto_uint16_x - crypto_uint16_y; + crypto_uint16_z ^= crypto_uint16_xy & (crypto_uint16_z ^ crypto_uint16_x ^ (((crypto_uint16) 1) << 15)); + return crypto_uint16_signed_negative_mask(crypto_uint16_z); +} + +static crypto_uint16 crypto_uint16_min(crypto_uint16 crypto_uint16_x,crypto_uint16 crypto_uint16_y) +{ + crypto_uint16 crypto_uint16_xy = crypto_uint16_y ^ crypto_uint16_x; + crypto_uint16 crypto_uint16_z = crypto_uint16_y - crypto_uint16_x; + crypto_uint16_z ^= crypto_uint16_xy & (crypto_uint16_z ^ crypto_uint16_y ^ (((crypto_uint16) 1) << 15)); + crypto_uint16_z = crypto_uint16_signed_negative_mask(crypto_uint16_z); + crypto_uint16_z &= crypto_uint16_xy; + return crypto_uint16_x ^ crypto_uint16_z; +} + +static crypto_uint16 crypto_uint16_max(crypto_uint16 crypto_uint16_x,crypto_uint16 crypto_uint16_y) +{ + crypto_uint16 crypto_uint16_xy = crypto_uint16_y ^ crypto_uint16_x; + crypto_uint16 crypto_uint16_z = crypto_uint16_y - crypto_uint16_x; + crypto_uint16_z ^= crypto_uint16_xy & (crypto_uint16_z ^ crypto_uint16_y ^ (((crypto_uint16) 1) << 15)); + crypto_uint16_z = crypto_uint16_signed_negative_mask(crypto_uint16_z); + crypto_uint16_z &= crypto_uint16_xy; + return crypto_uint16_y ^ crypto_uint16_z; +} + +static void crypto_uint16_minmax(crypto_uint16 *crypto_uint16_a,crypto_uint16 *crypto_uint16_b) +{ + crypto_uint16 crypto_uint16_x = *crypto_uint16_a; + crypto_uint16 crypto_uint16_y = *crypto_uint16_b; + crypto_uint16 crypto_uint16_xy = crypto_uint16_y ^ crypto_uint16_x; + crypto_uint16 crypto_uint16_z = crypto_uint16_y - crypto_uint16_x; + crypto_uint16_z ^= crypto_uint16_xy & (crypto_uint16_z ^ crypto_uint16_y ^ (((crypto_uint16) 1) << 15)); + crypto_uint16_z = crypto_uint16_signed_negative_mask(crypto_uint16_z); + crypto_uint16_z &= crypto_uint16_xy; + *crypto_uint16_a = crypto_uint16_x ^ crypto_uint16_z; + *crypto_uint16_b = crypto_uint16_y ^ crypto_uint16_z; +} + +#endif diff --git a/deps/mceliece/kem/mceliece6960119f/subroutines/crypto_uint32.h b/deps/mceliece/kem/mceliece6960119f/subroutines/crypto_uint32.h new file mode 100644 index 0000000..3f39d62 --- /dev/null +++ b/deps/mceliece/kem/mceliece6960119f/subroutines/crypto_uint32.h @@ -0,0 +1,76 @@ +#ifndef crypto_uint32_h +#define crypto_uint32_h + +#include +typedef uint32_t crypto_uint32; + +typedef int32_t crypto_uint32_signed; + +static crypto_uint32_signed crypto_uint32_signed_negative_mask(crypto_uint32_signed crypto_uint32_signed_x) +{ + return crypto_uint32_signed_x >> 31; +} + +static crypto_uint32 crypto_uint32_nonzero_mask(crypto_uint32 crypto_uint32_x) +{ + return crypto_uint32_signed_negative_mask(crypto_uint32_x) | crypto_uint32_signed_negative_mask(-crypto_uint32_x); +} + +static crypto_uint32 crypto_uint32_zero_mask(crypto_uint32 crypto_uint32_x) +{ + return ~crypto_uint32_nonzero_mask(crypto_uint32_x); +} + +static crypto_uint32 crypto_uint32_unequal_mask(crypto_uint32 crypto_uint32_x,crypto_uint32 crypto_uint32_y) +{ + crypto_uint32 crypto_uint32_xy = crypto_uint32_x ^ crypto_uint32_y; + return crypto_uint32_nonzero_mask(crypto_uint32_xy); +} + +static crypto_uint32 crypto_uint32_equal_mask(crypto_uint32 crypto_uint32_x,crypto_uint32 crypto_uint32_y) +{ + return ~crypto_uint32_unequal_mask(crypto_uint32_x,crypto_uint32_y); +} + +static crypto_uint32 crypto_uint32_smaller_mask(crypto_uint32 crypto_uint32_x,crypto_uint32 crypto_uint32_y) +{ + crypto_uint32 crypto_uint32_xy = crypto_uint32_x ^ crypto_uint32_y; + crypto_uint32 crypto_uint32_z = crypto_uint32_x - crypto_uint32_y; + crypto_uint32_z ^= crypto_uint32_xy & (crypto_uint32_z ^ crypto_uint32_x ^ (((crypto_uint32) 1) << 31)); + return crypto_uint32_signed_negative_mask(crypto_uint32_z); +} + +static crypto_uint32 crypto_uint32_min(crypto_uint32 crypto_uint32_x,crypto_uint32 crypto_uint32_y) +{ + crypto_uint32 crypto_uint32_xy = crypto_uint32_y ^ crypto_uint32_x; + crypto_uint32 crypto_uint32_z = crypto_uint32_y - crypto_uint32_x; + crypto_uint32_z ^= crypto_uint32_xy & (crypto_uint32_z ^ crypto_uint32_y ^ (((crypto_uint32) 1) << 31)); + crypto_uint32_z = crypto_uint32_signed_negative_mask(crypto_uint32_z); + crypto_uint32_z &= crypto_uint32_xy; + return crypto_uint32_x ^ crypto_uint32_z; +} + +static crypto_uint32 crypto_uint32_max(crypto_uint32 crypto_uint32_x,crypto_uint32 crypto_uint32_y) +{ + crypto_uint32 crypto_uint32_xy = crypto_uint32_y ^ crypto_uint32_x; + crypto_uint32 crypto_uint32_z = crypto_uint32_y - crypto_uint32_x; + crypto_uint32_z ^= crypto_uint32_xy & (crypto_uint32_z ^ crypto_uint32_y ^ (((crypto_uint32) 1) << 31)); + crypto_uint32_z = crypto_uint32_signed_negative_mask(crypto_uint32_z); + crypto_uint32_z &= crypto_uint32_xy; + return crypto_uint32_y ^ crypto_uint32_z; +} + +static void crypto_uint32_minmax(crypto_uint32 *crypto_uint32_a,crypto_uint32 *crypto_uint32_b) +{ + crypto_uint32 crypto_uint32_x = *crypto_uint32_a; + crypto_uint32 crypto_uint32_y = *crypto_uint32_b; + crypto_uint32 crypto_uint32_xy = crypto_uint32_y ^ crypto_uint32_x; + crypto_uint32 crypto_uint32_z = crypto_uint32_y - crypto_uint32_x; + crypto_uint32_z ^= crypto_uint32_xy & (crypto_uint32_z ^ crypto_uint32_y ^ (((crypto_uint32) 1) << 31)); + crypto_uint32_z = crypto_uint32_signed_negative_mask(crypto_uint32_z); + crypto_uint32_z &= crypto_uint32_xy; + *crypto_uint32_a = crypto_uint32_x ^ crypto_uint32_z; + *crypto_uint32_b = crypto_uint32_y ^ crypto_uint32_z; +} + +#endif diff --git a/deps/mceliece/kem/mceliece6960119f/subroutines/crypto_uint64.h b/deps/mceliece/kem/mceliece6960119f/subroutines/crypto_uint64.h new file mode 100644 index 0000000..42e2be9 --- /dev/null +++ b/deps/mceliece/kem/mceliece6960119f/subroutines/crypto_uint64.h @@ -0,0 +1,76 @@ +#ifndef crypto_uint64_h +#define crypto_uint64_h + +#include +typedef uint64_t crypto_uint64; + +typedef int64_t crypto_uint64_signed; + +static crypto_uint64_signed crypto_uint64_signed_negative_mask(crypto_uint64_signed crypto_uint64_signed_x) +{ + return crypto_uint64_signed_x >> 63; +} + +static crypto_uint64 crypto_uint64_nonzero_mask(crypto_uint64 crypto_uint64_x) +{ + return crypto_uint64_signed_negative_mask(crypto_uint64_x) | crypto_uint64_signed_negative_mask(-crypto_uint64_x); +} + +static crypto_uint64 crypto_uint64_zero_mask(crypto_uint64 crypto_uint64_x) +{ + return ~crypto_uint64_nonzero_mask(crypto_uint64_x); +} + +static crypto_uint64 crypto_uint64_unequal_mask(crypto_uint64 crypto_uint64_x,crypto_uint64 crypto_uint64_y) +{ + crypto_uint64 crypto_uint64_xy = crypto_uint64_x ^ crypto_uint64_y; + return crypto_uint64_nonzero_mask(crypto_uint64_xy); +} + +static crypto_uint64 crypto_uint64_equal_mask(crypto_uint64 crypto_uint64_x,crypto_uint64 crypto_uint64_y) +{ + return ~crypto_uint64_unequal_mask(crypto_uint64_x,crypto_uint64_y); +} + +static crypto_uint64 crypto_uint64_smaller_mask(crypto_uint64 crypto_uint64_x,crypto_uint64 crypto_uint64_y) +{ + crypto_uint64 crypto_uint64_xy = crypto_uint64_x ^ crypto_uint64_y; + crypto_uint64 crypto_uint64_z = crypto_uint64_x - crypto_uint64_y; + crypto_uint64_z ^= crypto_uint64_xy & (crypto_uint64_z ^ crypto_uint64_x ^ (((crypto_uint64) 1) << 63)); + return crypto_uint64_signed_negative_mask(crypto_uint64_z); +} + +static crypto_uint64 crypto_uint64_min(crypto_uint64 crypto_uint64_x,crypto_uint64 crypto_uint64_y) +{ + crypto_uint64 crypto_uint64_xy = crypto_uint64_y ^ crypto_uint64_x; + crypto_uint64 crypto_uint64_z = crypto_uint64_y - crypto_uint64_x; + crypto_uint64_z ^= crypto_uint64_xy & (crypto_uint64_z ^ crypto_uint64_y ^ (((crypto_uint64) 1) << 63)); + crypto_uint64_z = crypto_uint64_signed_negative_mask(crypto_uint64_z); + crypto_uint64_z &= crypto_uint64_xy; + return crypto_uint64_x ^ crypto_uint64_z; +} + +static crypto_uint64 crypto_uint64_max(crypto_uint64 crypto_uint64_x,crypto_uint64 crypto_uint64_y) +{ + crypto_uint64 crypto_uint64_xy = crypto_uint64_y ^ crypto_uint64_x; + crypto_uint64 crypto_uint64_z = crypto_uint64_y - crypto_uint64_x; + crypto_uint64_z ^= crypto_uint64_xy & (crypto_uint64_z ^ crypto_uint64_y ^ (((crypto_uint64) 1) << 63)); + crypto_uint64_z = crypto_uint64_signed_negative_mask(crypto_uint64_z); + crypto_uint64_z &= crypto_uint64_xy; + return crypto_uint64_y ^ crypto_uint64_z; +} + +static void crypto_uint64_minmax(crypto_uint64 *crypto_uint64_a,crypto_uint64 *crypto_uint64_b) +{ + crypto_uint64 crypto_uint64_x = *crypto_uint64_a; + crypto_uint64 crypto_uint64_y = *crypto_uint64_b; + crypto_uint64 crypto_uint64_xy = crypto_uint64_y ^ crypto_uint64_x; + crypto_uint64 crypto_uint64_z = crypto_uint64_y - crypto_uint64_x; + crypto_uint64_z ^= crypto_uint64_xy & (crypto_uint64_z ^ crypto_uint64_y ^ (((crypto_uint64) 1) << 63)); + crypto_uint64_z = crypto_uint64_signed_negative_mask(crypto_uint64_z); + crypto_uint64_z &= crypto_uint64_xy; + *crypto_uint64_a = crypto_uint64_x ^ crypto_uint64_z; + *crypto_uint64_b = crypto_uint64_y ^ crypto_uint64_z; +} + +#endif diff --git a/deps/mceliece/kem/mceliece6960119f/synd.c b/deps/mceliece/kem/mceliece6960119f/synd.c new file mode 100644 index 0000000..c945647 --- /dev/null +++ b/deps/mceliece/kem/mceliece6960119f/synd.c @@ -0,0 +1,36 @@ +/* + This file is for syndrome computation +*/ + +#include "synd.h" + +#include "params.h" +#include "root.h" + +#include + +/* input: Goppa polynomial f, support L, received word r */ +/* output: out, the syndrome of length 2t */ +void synd(gf *out, gf *f, gf *L, unsigned char *r) +{ + int i, j; + gf e, e_inv, c; + + for (j = 0; j < 2*SYS_T; j++) + out[j] = 0; + + for (i = 0; i < SYS_N; i++) + { + c = (r[i/8] >> (i%8)) & 1; + + e = eval(f, L[i]); + e_inv = gf_inv(gf_mul(e,e)); + + for (j = 0; j < 2*SYS_T; j++) + { + out[j] = gf_add(out[j], gf_mul(e_inv, c)); + e_inv = gf_mul(e_inv, L[i]); + } + } +} + diff --git a/deps/mceliece/kem/mceliece6960119f/synd.h b/deps/mceliece/kem/mceliece6960119f/synd.h new file mode 100644 index 0000000..9331406 --- /dev/null +++ b/deps/mceliece/kem/mceliece6960119f/synd.h @@ -0,0 +1,14 @@ +/* + This file is for syndrome computation +*/ + +#ifndef SYND_H +#define SYND_H +#define synd CRYPTO_NAMESPACE(synd) + +#include "gf.h" + +void synd(gf *, gf *, gf *, unsigned char *); + +#endif + diff --git a/deps/mceliece/kem/mceliece6960119f/transpose.c b/deps/mceliece/kem/mceliece6960119f/transpose.c new file mode 100644 index 0000000..0da2bc5 --- /dev/null +++ b/deps/mceliece/kem/mceliece6960119f/transpose.c @@ -0,0 +1,43 @@ +/* + This file is for matrix transposition +*/ + +#include "transpose.h" + +#include + +/* input: in, a 64x64 matrix over GF(2) */ +/* output: out, transpose of in */ +void transpose_64x64(uint64_t * out, uint64_t * in) +{ + int i, j, s, d; + + uint64_t x, y; + uint64_t masks[6][2] = { + {0x5555555555555555, 0xAAAAAAAAAAAAAAAA}, + {0x3333333333333333, 0xCCCCCCCCCCCCCCCC}, + {0x0F0F0F0F0F0F0F0F, 0xF0F0F0F0F0F0F0F0}, + {0x00FF00FF00FF00FF, 0xFF00FF00FF00FF00}, + {0x0000FFFF0000FFFF, 0xFFFF0000FFFF0000}, + {0x00000000FFFFFFFF, 0xFFFFFFFF00000000} + }; + + for (i = 0; i < 64; i++) + out[i] = in[i]; + + for (d = 5; d >= 0; d--) + { + s = 1 << d; + + for (i = 0; i < 64; i += s*2) + for (j = i; j < i+s; j++) + { + x = (out[j] & masks[d][0]) | ((out[j+s] & masks[d][0]) << s); + y = ((out[j] & masks[d][1]) >> s) | (out[j+s] & masks[d][1]); + + out[j+0] = x; + out[j+s] = y; + } + } +} + diff --git a/deps/mceliece/kem/mceliece6960119f/transpose.h b/deps/mceliece/kem/mceliece6960119f/transpose.h new file mode 100644 index 0000000..31e5b96 --- /dev/null +++ b/deps/mceliece/kem/mceliece6960119f/transpose.h @@ -0,0 +1,14 @@ +/* + This file is for matrix transposition +*/ + +#ifndef TRANSPOSE_H +#define TRANSPOSE_H +#define transpose_64x64 CRYPTO_NAMESPACE(transpose_64x64) + +#include + +void transpose_64x64(uint64_t *, uint64_t *); + +#endif + diff --git a/deps/mceliece/kem/mceliece6960119f/uint64_sort.h b/deps/mceliece/kem/mceliece6960119f/uint64_sort.h new file mode 100644 index 0000000..2fb100c --- /dev/null +++ b/deps/mceliece/kem/mceliece6960119f/uint64_sort.h @@ -0,0 +1,45 @@ +#ifndef uint64_sort_h +#define uint64_sort_h + +#define int64_sort CRYPTO_NAMESPACE(int64_sort) + +#include + +#define uint64_MINMAX(a,b) \ +do { \ + uint64_t c = b - a; \ + c >>= 63; \ + c = -c; \ + c &= a ^ b; \ + a ^= c; \ + b ^= c; \ +} while(0) + +static void uint64_sort(uint64_t *x,long long n) +{ + long long top,p,q,r,i; + + if (n < 2) return; + top = 1; + while (top < n - top) top += top; + + for (p = top;p > 0;p >>= 1) { + for (i = 0;i < n - p;++i) + if (!(i & p)) + uint64_MINMAX(x[i],x[i+p]); + i = 0; + for (q = top;q > p;q >>= 1) { + for (;i < n - q;++i) { + if (!(i & p)) { + uint64_t a = x[i + p]; + for (r = q;r > p;r >>= 1) + uint64_MINMAX(a,x[i+r]); + x[i + p] = a; + } + } + } + } +} + +#endif + diff --git a/deps/mceliece/kem/mceliece6960119f/util.c b/deps/mceliece/kem/mceliece6960119f/util.c new file mode 100644 index 0000000..1679168 --- /dev/null +++ b/deps/mceliece/kem/mceliece6960119f/util.c @@ -0,0 +1,75 @@ +/* + This file is for loading/storing data in a little-endian fashion +*/ + +#include "util.h" + +#include "params.h" + +void store_gf(unsigned char *dest, gf a) +{ + dest[0] = a & 0xFF; + dest[1] = a >> 8; +} + +uint16_t load_gf(const unsigned char *src) +{ + uint16_t a; + + a = src[1]; + a <<= 8; + a |= src[0]; + + return a & GFMASK; +} + +uint32_t load4(const unsigned char * in) +{ + int i; + uint32_t ret = in[3]; + + for (i = 2; i >= 0; i--) + { + ret <<= 8; + ret |= in[i]; + } + + return ret; +} + +void store8(unsigned char *out, uint64_t in) +{ + out[0] = (in >> 0x00) & 0xFF; + out[1] = (in >> 0x08) & 0xFF; + out[2] = (in >> 0x10) & 0xFF; + out[3] = (in >> 0x18) & 0xFF; + out[4] = (in >> 0x20) & 0xFF; + out[5] = (in >> 0x28) & 0xFF; + out[6] = (in >> 0x30) & 0xFF; + out[7] = (in >> 0x38) & 0xFF; +} + +uint64_t load8(const unsigned char * in) +{ + int i; + uint64_t ret = in[7]; + + for (i = 6; i >= 0; i--) + { + ret <<= 8; + ret |= in[i]; + } + + return ret; +} + +gf bitrev(gf a) +{ + a = ((a & 0x00FF) << 8) | ((a & 0xFF00) >> 8); + a = ((a & 0x0F0F) << 4) | ((a & 0xF0F0) >> 4); + a = ((a & 0x3333) << 2) | ((a & 0xCCCC) >> 2); + a = ((a & 0x5555) << 1) | ((a & 0xAAAA) >> 1); + + return a >> 3; +} + diff --git a/deps/mceliece/kem/mceliece6960119f/util.h b/deps/mceliece/kem/mceliece6960119f/util.h new file mode 100644 index 0000000..d610bee --- /dev/null +++ b/deps/mceliece/kem/mceliece6960119f/util.h @@ -0,0 +1,27 @@ +/* + This file is for loading/storing data in a little-endian fashion +*/ + +#ifndef UTIL_H +#define UTIL_H +#define bitrev CRYPTO_NAMESPACE(bitrev) +#define load4 CRYPTO_NAMESPACE(load4) +#define load8 CRYPTO_NAMESPACE(load8) +#define load_gf CRYPTO_NAMESPACE(load_gf) +#define store8 CRYPTO_NAMESPACE(store8) +#define store_gf CRYPTO_NAMESPACE(store_gf) + +#include "gf.h" +#include + +void store_gf(unsigned char *, gf); +uint16_t load_gf(const unsigned char *); +uint32_t load4(const unsigned char *); + +void store8(unsigned char *, uint64_t ); +uint64_t load8(const unsigned char *); + +gf bitrev(gf); + +#endif + diff --git a/deps/mceliece/kem/mceliece8192128/benes.c b/deps/mceliece/kem/mceliece8192128/benes.c new file mode 100644 index 0000000..3b4e710 --- /dev/null +++ b/deps/mceliece/kem/mceliece8192128/benes.c @@ -0,0 +1,181 @@ +/* + This file is for Benes network related functions + + For the implementation strategy, see + https://eprint.iacr.org/2017/793.pdf +*/ + +#include "util.h" +#include "transpose.h" +#include "params.h" +#include "benes.h" + +/* middle layers of the benes network */ +static void layer_in(uint64_t data[2][64], uint64_t * bits, int lgs) +{ + int i, j, s; + + uint64_t d; + + s = 1 << lgs; + + for (i = 0; i < 64; i += s*2) + for (j = i; j < i+s; j++) + { + + d = (data[0][j+0] ^ data[0][j+s]); + d &= (*bits++); + data[0][j+0] ^= d; + data[0][j+s] ^= d; + + d = (data[1][j+0] ^ data[1][j+s]); + d &= (*bits++); + data[1][j+0] ^= d; + data[1][j+s] ^= d; + } +} + +/* first and last layers of the benes network */ +static void layer_ex(uint64_t * data, uint64_t * bits, int lgs) +{ + int i, j, s; + + uint64_t d; + + s = 1 << lgs; + + for (i = 0; i < 128; i += s*2) + for (j = i; j < i+s; j++) + { + + d = (data[j+0] ^ data[j+s]); + d &= (*bits++); + data[j+0] ^= d; + data[j+s] ^= d; + } +} + +/* input: r, sequence of bits to be permuted */ +/* bits, condition bits of the Benes network */ +/* rev, 0 for normal application; !0 for inverse */ +/* output: r, permuted bits */ +void apply_benes(unsigned char * r, const unsigned char * bits, int rev) +{ + int i, iter, inc; + + unsigned char *r_ptr = r; + const unsigned char *bits_ptr; + + uint64_t r_int_v[2][64]; + uint64_t r_int_h[2][64]; + uint64_t b_int_v[64]; + uint64_t b_int_h[64]; + + // + + if (rev) { bits_ptr = bits + 12288; inc = -1024; } + else { bits_ptr = bits; inc = 0; } + + for (i = 0; i < 64; i++) + { + r_int_v[0][i] = load8(r_ptr + i*16 + 0); + r_int_v[1][i] = load8(r_ptr + i*16 + 8); + } + + transpose_64x64(r_int_h[0], r_int_v[0]); + transpose_64x64(r_int_h[1], r_int_v[1]); + + for (iter = 0; iter <= 6; iter++) + { + for (i = 0; i < 64; i++) + { + b_int_v[i] = load8(bits_ptr); bits_ptr += 8; + } + + bits_ptr += inc; + + transpose_64x64(b_int_h, b_int_v); + + layer_ex(r_int_h[0], b_int_h, iter); + } + + transpose_64x64(r_int_v[0], r_int_h[0]); + transpose_64x64(r_int_v[1], r_int_h[1]); + + for (iter = 0; iter <= 5; iter++) + { + for (i = 0; i < 64; i++) { b_int_v[i] = load8(bits_ptr); bits_ptr += 8; } + bits_ptr += inc; + + layer_in(r_int_v, b_int_v, iter); + } + + for (iter = 4; iter >= 0; iter--) + { + for (i = 0; i < 64; i++) { b_int_v[i] = load8(bits_ptr); bits_ptr += 8; } + bits_ptr += inc; + + layer_in(r_int_v, b_int_v, iter); + } + + transpose_64x64(r_int_h[0], r_int_v[0]); + transpose_64x64(r_int_h[1], r_int_v[1]); + + for (iter = 6; iter >= 0; iter--) + { + for (i = 0; i < 64; i++) + { + b_int_v[i] = load8(bits_ptr); bits_ptr += 8; + } + + bits_ptr += inc; + + transpose_64x64(b_int_h, b_int_v); + + layer_ex(r_int_h[0], b_int_h, iter); + } + + transpose_64x64(r_int_v[0], r_int_h[0]); + transpose_64x64(r_int_v[1], r_int_h[1]); + + for (i = 0; i < 64; i++) + { + store8(r_ptr + i*16 + 0, r_int_v[0][i]); + store8(r_ptr + i*16 + 8, r_int_v[1][i]); + } +} + +/* input: condition bits c */ +/* output: support s */ +void support_gen(gf * s, const unsigned char *c) +{ + gf a; + int i, j; + unsigned char L[ GFBITS ][ (1 << GFBITS)/8 ]; + + for (i = 0; i < GFBITS; i++) + for (j = 0; j < (1 << GFBITS)/8; j++) + L[i][j] = 0; + + for (i = 0; i < (1 << GFBITS); i++) + { + a = bitrev((gf) i); + + for (j = 0; j < GFBITS; j++) + L[j][ i/8 ] |= ((a >> j) & 1) << (i%8); + } + + for (j = 0; j < GFBITS; j++) + apply_benes(L[j], c, 0); + + for (i = 0; i < SYS_N; i++) + { + s[i] = 0; + for (j = GFBITS-1; j >= 0; j--) + { + s[i] <<= 1; + s[i] |= (L[j][i/8] >> (i%8)) & 1; + } + } +} + diff --git a/deps/mceliece/kem/mceliece8192128/benes.h b/deps/mceliece/kem/mceliece8192128/benes.h new file mode 100644 index 0000000..c2ef35a --- /dev/null +++ b/deps/mceliece/kem/mceliece8192128/benes.h @@ -0,0 +1,16 @@ +/* + This file is for Benes network related functions +*/ + +#ifndef BENES_H +#define BENES_H +#define apply_benes CRYPTO_NAMESPACE(apply_benes) +#define support_gen CRYPTO_NAMESPACE(support_gen) + +#include "gf.h" + +void apply_benes(unsigned char *, const unsigned char *, int); +void support_gen(gf *, const unsigned char *); + +#endif + diff --git a/deps/mceliece/kem/mceliece8192128/bm.c b/deps/mceliece/kem/mceliece8192128/bm.c new file mode 100644 index 0000000..056a734 --- /dev/null +++ b/deps/mceliece/kem/mceliece8192128/bm.c @@ -0,0 +1,72 @@ +/* + This file is for the Berlekamp-Massey algorithm + see http://crypto.stanford.edu/~mironov/cs359/massey.pdf +*/ + +#include "params.h" +#include "gf.h" +#include "bm.h" + +#define min(a, b) ((a < b) ? a : b) + +/* the Berlekamp-Massey algorithm */ +/* input: s, sequence of field elements */ +/* output: out, minimal polynomial of s */ +void bm(gf *out, gf *s) +{ + int i; + + uint16_t N = 0; + uint16_t L = 0; + uint16_t mle; + uint16_t mne; + + gf T[ SYS_T+1 ]; + gf C[ SYS_T+1 ]; + gf B[ SYS_T+1 ]; + + gf b = 1, d, f; + + // + + for (i = 0; i < SYS_T+1; i++) + C[i] = B[i] = 0; + + B[1] = C[0] = 1; + + // + + for (N = 0; N < 2 * SYS_T; N++) + { + d = 0; + + for (i = 0; i <= min(N, SYS_T); i++) + d ^= gf_mul(C[i], s[ N-i]); + + mne = d; mne -= 1; mne >>= 15; mne -= 1; + mle = N; mle -= 2*L; mle >>= 15; mle -= 1; + mle &= mne; + + for (i = 0; i <= SYS_T; i++) + T[i] = C[i]; + + f = gf_frac(b, d); + + for (i = 0; i <= SYS_T; i++) + C[i] ^= gf_mul(f, B[i]) & mne; + + L = (L & ~mle) | ((N+1-L) & mle); + + for (i = 0; i <= SYS_T; i++) + B[i] = (B[i] & ~mle) | (T[i] & mle); + + b = (b & ~mle) | (d & mle); + + for (i = SYS_T; i >= 1; i--) B[i] = B[i-1]; + B[0] = 0; + } + + for (i = 0; i <= SYS_T; i++) + out[i] = C[ SYS_T-i ]; +} + diff --git a/deps/mceliece/kem/mceliece8192128/bm.h b/deps/mceliece/kem/mceliece8192128/bm.h new file mode 100644 index 0000000..73d5c6c --- /dev/null +++ b/deps/mceliece/kem/mceliece8192128/bm.h @@ -0,0 +1,13 @@ +/* + This file is for the Berlekamp-Massey algorithm + see http://crypto.stanford.edu/~mironov/cs359/massey.pdf +*/ + +#ifndef BM_H +#define BM_H +#define bm CRYPTO_NAMESPACE(bm) + +void bm(gf *, gf *); + +#endif + diff --git a/deps/mceliece/kem/mceliece8192128/controlbits.c b/deps/mceliece/kem/mceliece8192128/controlbits.c new file mode 100644 index 0000000..db9db9c --- /dev/null +++ b/deps/mceliece/kem/mceliece8192128/controlbits.c @@ -0,0 +1,220 @@ +/* This file is for implementing the Nassimi-Sahni algorithm */ +/* See David Nassimi, Sartaj Sahni "Parallel algorithms to set up the Benes permutationnetwork" */ +/* See also https://cr.yp.to/papers/controlbits-20200923.pdf */ + +#include +#include "crypto_declassify.h" +#include "controlbits.h" +#include "int32_sort.h" +typedef int16_t int16; +typedef int32_t int32; +#include "crypto_int32.h" +#define int32_min crypto_int32_min +#include "crypto_int16.h" + +/* parameters: 1 <= w <= 14; n = 2^w */ +/* input: permutation pi of {0,1,...,n-1} */ +/* output: (2m-1)n/2 control bits at positions pos,pos+step,... */ +/* output position pos is by definition 1&(out[pos/8]>>(pos&7)) */ +/* caller must 0-initialize positions first */ +/* temp must have space for int32[2*n] */ +static void cbrecursion(unsigned char *out,long long pos,long long step,const int16 *pi,long long w,long long n,int32 *temp) +{ +#define A temp +#define B (temp+n) +#define q ((int16 *) (temp+n+n/4)) +/* q can start anywhere between temp+n and temp+n/2 */ + + long long x,i,j,k; + + if (w == 1) { + out[pos>>3] ^= pi[0]<<(pos&7); + return; + } + + for (x = 0;x < n;++x) A[x] = ((pi[x]^1)<<16)|pi[x^1]; + int32_sort(A,n); /* A = (id<<16)+pibar */ + + for (x = 0;x < n;++x) { + int32 Ax = A[x]; + int32 px = Ax&0xffff; + int32 cx = int32_min(px,x); + B[x] = (px<<16)|cx; + } + /* B = (p<<16)+c */ + + for (x = 0;x < n;++x) A[x] = (A[x]<<16)|x; /* A = (pibar<<16)+id */ + int32_sort(A,n); /* A = (id<<16)+pibar^-1 */ + + for (x = 0;x < n;++x) A[x] = (A[x]<<16)+(B[x]>>16); /* A = (pibar^(-1)<<16)+pibar */ + int32_sort(A,n); /* A = (id<<16)+pibar^2 */ + + if (w <= 10) { + for (x = 0;x < n;++x) B[x] = ((A[x]&0xffff)<<10)|(B[x]&0x3ff); + + for (i = 1;i < w-1;++i) { + /* B = (p<<10)+c */ + + for (x = 0;x < n;++x) A[x] = ((B[x]&~0x3ff)<<6)|x; /* A = (p<<16)+id */ + int32_sort(A,n); /* A = (id<<16)+p^{-1} */ + + for (x = 0;x < n;++x) A[x] = (A[x]<<20)|B[x]; /* A = (p^{-1}<<20)+(p<<10)+c */ + int32_sort(A,n); /* A = (id<<20)+(pp<<10)+cp */ + + for (x = 0;x < n;++x) { + int32 ppcpx = A[x]&0xfffff; + int32 ppcx = (A[x]&0xffc00)|(B[x]&0x3ff); + B[x] = int32_min(ppcx,ppcpx); + } + } + for (x = 0;x < n;++x) B[x] &= 0x3ff; + } else { + for (x = 0;x < n;++x) B[x] = (A[x]<<16)|(B[x]&0xffff); + + for (i = 1;i < w-1;++i) { + /* B = (p<<16)+c */ + + for (x = 0;x < n;++x) A[x] = (B[x]&~0xffff)|x; + int32_sort(A,n); /* A = (id<<16)+p^(-1) */ + + for (x = 0;x < n;++x) A[x] = (A[x]<<16)|(B[x]&0xffff); + /* A = p^(-1)<<16+c */ + + if (i < w-2) { + for (x = 0;x < n;++x) B[x] = (A[x]&~0xffff)|(B[x]>>16); + /* B = (p^(-1)<<16)+p */ + int32_sort(B,n); /* B = (id<<16)+p^(-2) */ + for (x = 0;x < n;++x) B[x] = (B[x]<<16)|(A[x]&0xffff); + /* B = (p^(-2)<<16)+c */ + } + + int32_sort(A,n); + /* A = id<<16+cp */ + for (x = 0;x < n;++x) { + int32 cpx = (B[x]&~0xffff)|(A[x]&0xffff); + B[x] = int32_min(B[x],cpx); + } + } + for (x = 0;x < n;++x) B[x] &= 0xffff; + } + + for (x = 0;x < n;++x) A[x] = (((int32)pi[x])<<16)+x; + int32_sort(A,n); /* A = (id<<16)+pi^(-1) */ + + for (j = 0;j < n/2;++j) { + long long x = 2*j; + int32 fj = B[x]&1; /* f[j] */ + int32 Fx = x+fj; /* F[x] */ + int32 Fx1 = Fx^1; /* F[x+1] */ + + out[pos>>3] ^= fj<<(pos&7); + pos += step; + + B[x] = (A[x]<<16)|Fx; + B[x+1] = (A[x+1]<<16)|Fx1; + } + /* B = (pi^(-1)<<16)+F */ + + int32_sort(B,n); /* B = (id<<16)+F(pi) */ + + pos += (2*w-3)*step*(n/2); + + for (k = 0;k < n/2;++k) { + long long y = 2*k; + int32 lk = B[y]&1; /* l[k] */ + int32 Ly = y+lk; /* L[y] */ + int32 Ly1 = Ly^1; /* L[y+1] */ + + out[pos>>3] ^= lk<<(pos&7); + pos += step; + + A[y] = (Ly<<16)|(B[y]&0xffff); + A[y+1] = (Ly1<<16)|(B[y+1]&0xffff); + } + /* A = (L<<16)+F(pi) */ + + int32_sort(A,n); /* A = (id<<16)+F(pi(L)) = (id<<16)+M */ + + pos -= (2*w-2)*step*(n/2); + + for (j = 0;j < n/2;++j) { + q[j] = (A[2*j]&0xffff)>>1; + q[j+n/2] = (A[2*j+1]&0xffff)>>1; + } + + cbrecursion(out,pos,step*2,q,w-1,n/2,temp); + cbrecursion(out,pos+step,step*2,q+n/2,w-1,n/2,temp); +} + +/* input: p, an array of int16 */ +/* input: n, length of p */ +/* input: s, meaning that stride-2^s cswaps are performed */ +/* input: cb, the control bits */ +/* output: the result of apply the control bits to p */ +static void layer(int16_t *p, const unsigned char *cb, int s, int n) +{ + int i, j; + int stride = 1 << s; + int index = 0; + int16_t d, m; + + for (i = 0; i < n; i += stride*2) + { + for (j = 0; j < stride; j++) + { + d = p[ i+j ] ^ p[ i+j+stride ]; + m = (cb[ index >> 3 ] >> (index & 7)) & 1; + m = -m; + d &= m; + p[ i+j ] ^= d; + p[ i+j+stride ] ^= d; + index++; + } + } +} + +/* parameters: 1 <= w <= 14; n = 2^w */ +/* input: permutation pi of {0,1,...,n-1} */ +/* output: (2m-1)n/2 control bits at positions 0,1,... */ +/* output position pos is by definition 1&(out[pos/8]>>(pos&7)) */ +void controlbitsfrompermutation(unsigned char *out,const int16 *pi,long long w,long long n) +{ + int32 temp[2*n]; + int16 pi_test[n], diff; + int i; + unsigned char *ptr; + + while (1) + { + memset(out,0,(((2*w-1)*n/2)+7)/8); + cbrecursion(out,0,1,pi,w,n,temp); + + // check for correctness + + for (i = 0; i < n; i++) + pi_test[i] = i; + + ptr = out; + for (i = 0; i < w; i++) + { + layer(pi_test, ptr, i, n); + ptr += n >> 4; + } + + for (i = w-2; i >= 0; i--) + { + layer(pi_test, ptr, i, n); + ptr += n >> 4; + } + + diff = 0; + for (i = 0; i < n; i++) + diff |= pi[i] ^ pi_test[i]; + + diff = crypto_int16_nonzero_mask(diff); + crypto_declassify(&diff,sizeof diff); + if (diff == 0) + break; + } +} + diff --git a/deps/mceliece/kem/mceliece8192128/controlbits.h b/deps/mceliece/kem/mceliece8192128/controlbits.h new file mode 100644 index 0000000..8ddd210 --- /dev/null +++ b/deps/mceliece/kem/mceliece8192128/controlbits.h @@ -0,0 +1,14 @@ +/* This file is for implementing the Nassimi-Sahni algorithm */ +/* See David Nassimi, Sartaj Sahni "Parallel algorithms to set up the Benes permutationnetwork" */ +/* See also https://cr.yp.to/papers/controlbits-20200923.pdf */ + +#ifndef CONTROLBITS_H +#define CONTROLBITS_H + +#define controlbitsfrompermutation CRYPTO_NAMESPACE(controlbitsfrompermutation) + +#include + +extern void controlbitsfrompermutation(unsigned char *,const int16_t *,long long,long long); + +#endif diff --git a/deps/mceliece/kem/mceliece8192128/crypto_hash.h b/deps/mceliece/kem/mceliece8192128/crypto_hash.h new file mode 100644 index 0000000..b7c1086 --- /dev/null +++ b/deps/mceliece/kem/mceliece8192128/crypto_hash.h @@ -0,0 +1,10 @@ +/* This file uses SHAKE256 implemented in the Keccak Code Package */ + +#include "../../mceliece_externals.h" + +#define crypto_hash_32b(out,in,inlen) \ + SHAKE256(out,32,in,inlen) + +#define shake(out,outlen,in,inlen) \ + SHAKE256(out,outlen,in,inlen) + diff --git a/deps/mceliece/kem/mceliece8192128/crypto_kem.h b/deps/mceliece/kem/mceliece8192128/crypto_kem.h new file mode 100644 index 0000000..a213837 --- /dev/null +++ b/deps/mceliece/kem/mceliece8192128/crypto_kem.h @@ -0,0 +1,15 @@ +#ifndef crypto_kem_H +#define crypto_kem_H + +#include "crypto_kem_mceliece8192128.h" + +#define crypto_kem_keypair crypto_kem_mceliece8192128_keypair +#define crypto_kem_enc crypto_kem_mceliece8192128_enc +#define crypto_kem_dec crypto_kem_mceliece8192128_dec +#define crypto_kem_PUBLICKEYBYTES crypto_kem_mceliece8192128_PUBLICKEYBYTES +#define crypto_kem_SECRETKEYBYTES crypto_kem_mceliece8192128_SECRETKEYBYTES +#define crypto_kem_BYTES crypto_kem_mceliece8192128_BYTES +#define crypto_kem_CIPHERTEXTBYTES crypto_kem_mceliece8192128_CIPHERTEXTBYTES +#define crypto_kem_PRIMITIVE "mceliece8192128" + +#endif diff --git a/deps/mceliece/kem/mceliece8192128/crypto_kem_mceliece8192128.h b/deps/mceliece/kem/mceliece8192128/crypto_kem_mceliece8192128.h new file mode 100644 index 0000000..9b6f90a --- /dev/null +++ b/deps/mceliece/kem/mceliece8192128/crypto_kem_mceliece8192128.h @@ -0,0 +1,27 @@ +#ifndef crypto_kem_mceliece8192128_H +#define crypto_kem_mceliece8192128_H + +#define crypto_kem_mceliece8192128_ref_PUBLICKEYBYTES 1357824 +#define crypto_kem_mceliece8192128_ref_SECRETKEYBYTES 14120 +#define crypto_kem_mceliece8192128_ref_CIPHERTEXTBYTES 208 +#define crypto_kem_mceliece8192128_ref_BYTES 32 + +#ifdef __cplusplus +extern "C" { +#endif +extern int crypto_kem_mceliece8192128_ref_keypair(unsigned char *,unsigned char *); +extern int crypto_kem_mceliece8192128_ref_enc(unsigned char *,unsigned char *,const unsigned char *); +extern int crypto_kem_mceliece8192128_ref_dec(unsigned char *,const unsigned char *,const unsigned char *); +#ifdef __cplusplus +} +#endif + +#define crypto_kem_mceliece8192128_keypair crypto_kem_mceliece8192128_ref_keypair +#define crypto_kem_mceliece8192128_enc crypto_kem_mceliece8192128_ref_enc +#define crypto_kem_mceliece8192128_dec crypto_kem_mceliece8192128_ref_dec +#define crypto_kem_mceliece8192128_PUBLICKEYBYTES crypto_kem_mceliece8192128_ref_PUBLICKEYBYTES +#define crypto_kem_mceliece8192128_SECRETKEYBYTES crypto_kem_mceliece8192128_ref_SECRETKEYBYTES +#define crypto_kem_mceliece8192128_BYTES crypto_kem_mceliece8192128_ref_BYTES +#define crypto_kem_mceliece8192128_CIPHERTEXTBYTES crypto_kem_mceliece8192128_ref_CIPHERTEXTBYTES + +#endif diff --git a/deps/mceliece/kem/mceliece8192128/decrypt.c b/deps/mceliece/kem/mceliece8192128/decrypt.c new file mode 100644 index 0000000..c4cc6de --- /dev/null +++ b/deps/mceliece/kem/mceliece8192128/decrypt.c @@ -0,0 +1,93 @@ +/* + This file is for Niederreiter decryption +*/ + +#include +#include "decrypt.h" + +#include "params.h" +#include "benes.h" +#include "util.h" +#include "synd.h" +#include "root.h" +#include "gf.h" +#include "bm.h" + +/* Niederreiter decryption with the Berlekamp decoder */ +/* intput: sk, secret key */ +/* c, ciphertext */ +/* output: e, error vector */ +/* return: 0 for success; 1 for failure */ +int decrypt(unsigned char *e, const unsigned char *sk, const unsigned char *c) +{ + int i, w = 0; + uint16_t check; + + unsigned char r[ SYS_N/8 ]; + + gf g[ SYS_T+1 ]; + gf L[ SYS_N ]; + + gf s[ SYS_T*2 ]; + gf s_cmp[ SYS_T*2 ]; + gf locator[ SYS_T+1 ]; + gf images[ SYS_N ]; + + gf t; + + // + + for (i = 0; i < SYND_BYTES; i++) r[i] = c[i]; + for (i = SYND_BYTES; i < SYS_N/8; i++) r[i] = 0; + + for (i = 0; i < SYS_T; i++) { g[i] = load_gf(sk); sk += 2; } g[ SYS_T ] = 1; + + support_gen(L, sk); + + synd(s, g, L, r); + + bm(locator, s); + + root(images, locator, L); + + // + + for (i = 0; i < SYS_N/8; i++) + e[i] = 0; + + for (i = 0; i < SYS_N; i++) + { + t = gf_iszero(images[i]) & 1; + + e[ i/8 ] |= t << (i%8); + w += t; + + } + +#ifdef KAT + { + int k; + printf("decrypt e: positions"); + for (k = 0;k < SYS_N;++k) + if (e[k/8] & (1 << (k&7))) + printf(" %d",k); + printf("\n"); + } +#endif + + synd(s_cmp, g, L, e); + + // + + check = w; + check ^= SYS_T; + + for (i = 0; i < SYS_T*2; i++) + check |= s[i] ^ s_cmp[i]; + + check -= 1; + check >>= 15; + + return check ^ 1; +} + diff --git a/deps/mceliece/kem/mceliece8192128/decrypt.h b/deps/mceliece/kem/mceliece8192128/decrypt.h new file mode 100644 index 0000000..266a5cd --- /dev/null +++ b/deps/mceliece/kem/mceliece8192128/decrypt.h @@ -0,0 +1,12 @@ +/* + This file is for Nieddereiter decryption +*/ + +#ifndef DECRYPT_H +#define DECRYPT_H +#define decrypt CRYPTO_NAMESPACE(decrypt) + +int decrypt(unsigned char *, const unsigned char *, const unsigned char *); + +#endif + diff --git a/deps/mceliece/kem/mceliece8192128/encrypt.c b/deps/mceliece/kem/mceliece8192128/encrypt.c new file mode 100644 index 0000000..997854f --- /dev/null +++ b/deps/mceliece/kem/mceliece8192128/encrypt.c @@ -0,0 +1,139 @@ +/* + This file is for Niederreiter encryption +*/ + +#include "encrypt.h" + +#include "util.h" +#include "params.h" +#include "randombytes.h" + +#include +#include +#include +#include + +#include "gf.h" +#include "crypto_declassify.h" +#include "crypto_uint32.h" + +static inline crypto_uint32 uint32_is_equal_declassify(uint32_t t,uint32_t u) +{ + crypto_uint32 mask = crypto_uint32_equal_mask(t,u); + crypto_declassify(&mask,sizeof mask); + return mask; +} + +static inline unsigned char same_mask(uint16_t x, uint16_t y) +{ + uint32_t mask; + + mask = x ^ y; + mask -= 1; + mask >>= 31; + mask = -mask; + + return mask & 0xFF; +} + +/* output: e, an error vector of weight t */ +static void gen_e(unsigned char *e) +{ + int i, j, eq; + + uint16_t ind[ SYS_T ]; + unsigned char bytes[ sizeof(ind) ]; + unsigned char mask; + unsigned char val[ SYS_T ]; + + while (1) + { + randombytes(bytes, sizeof(bytes)); + + for (i = 0; i < SYS_T; i++) + ind[i] = load_gf(bytes + i*2); + + // check for repetition + + eq = 0; + + for (i = 1; i < SYS_T; i++) + for (j = 0; j < i; j++) + if (uint32_is_equal_declassify(ind[i],ind[j])) + eq = 1; + + if (eq == 0) + break; + } + + for (j = 0; j < SYS_T; j++) + val[j] = 1 << (ind[j] & 7); + + for (i = 0; i < SYS_N/8; i++) + { + e[i] = 0; + + for (j = 0; j < SYS_T; j++) + { + mask = same_mask(i, (ind[j] >> 3)); + + e[i] |= val[j] & mask; + } + } +} + +/* input: public key pk, error vector e */ +/* output: syndrome s */ +static void syndrome(unsigned char *s, const unsigned char *pk, unsigned char *e) +{ + unsigned char b, row[SYS_N/8]; + const unsigned char *pk_ptr = pk; + + int i, j; + + for (i = 0; i < SYND_BYTES; i++) + s[i] = 0; + + for (i = 0; i < PK_NROWS; i++) + { + for (j = 0; j < SYS_N/8; j++) + row[j] = 0; + + for (j = 0; j < PK_ROW_BYTES; j++) + row[ SYS_N/8 - PK_ROW_BYTES + j ] = pk_ptr[j]; + + row[i/8] |= 1 << (i%8); + + b = 0; + for (j = 0; j < SYS_N/8; j++) + b ^= row[j] & e[j]; + + b ^= b >> 4; + b ^= b >> 2; + b ^= b >> 1; + b &= 1; + + s[ i/8 ] |= (b << (i%8)); + + pk_ptr += PK_ROW_BYTES; + } +} + +void encrypt(unsigned char *s, const unsigned char *pk, unsigned char *e) +{ + gen_e(e); + +#ifdef KAT + { + int k; + printf("encrypt e: positions"); + for (k = 0;k < SYS_N;++k) + if (e[k/8] & (1 << (k&7))) + printf(" %d",k); + printf("\n"); + } +#endif + + syndrome(s, pk, e); +} + diff --git a/deps/mceliece/kem/mceliece8192128/encrypt.h b/deps/mceliece/kem/mceliece8192128/encrypt.h new file mode 100644 index 0000000..8edd7a6 --- /dev/null +++ b/deps/mceliece/kem/mceliece8192128/encrypt.h @@ -0,0 +1,12 @@ +/* + This file is for Niederreiter encryption +*/ + +#ifndef ENCRYPT_H +#define ENCRYPT_H +#define encrypt CRYPTO_NAMESPACE(encrypt) + +void encrypt(unsigned char *, const unsigned char *, unsigned char *); + +#endif + diff --git a/deps/mceliece/kem/mceliece8192128/gf.c b/deps/mceliece/kem/mceliece8192128/gf.c new file mode 100644 index 0000000..159a286 --- /dev/null +++ b/deps/mceliece/kem/mceliece8192128/gf.c @@ -0,0 +1,215 @@ +/* + This file is for functions for field arithmetic +*/ + +#include "gf.h" + +#include "params.h" + +gf gf_iszero(gf a) +{ + uint32_t t = a; + + t -= 1; + t >>= 19; + + return (gf) t; +} + +gf gf_add(gf in0, gf in1) +{ + return in0 ^ in1; +} + +gf gf_mul(gf in0, gf in1) +{ + int i; + + uint64_t tmp; + uint64_t t0; + uint64_t t1; + uint64_t t; + + t0 = in0; + t1 = in1; + + tmp = t0 * (t1 & 1); + + for (i = 1; i < GFBITS; i++) + tmp ^= (t0 * (t1 & (1 << i))); + + // + + t = tmp & 0x1FF0000; + tmp ^= (t >> 9) ^ (t >> 10) ^ (t >> 12) ^ (t >> 13); + + t = tmp & 0x000E000; + tmp ^= (t >> 9) ^ (t >> 10) ^ (t >> 12) ^ (t >> 13); + + return tmp & GFMASK; +} + +/* input: field element in */ +/* return: (in^2)^2 */ +static inline gf gf_sq2(gf in) +{ + int i; + + const uint64_t B[] = {0x1111111111111111, + 0x0303030303030303, + 0x000F000F000F000F, + 0x000000FF000000FF}; + + const uint64_t M[] = {0x0001FF0000000000, + 0x000000FF80000000, + 0x000000007FC00000, + 0x00000000003FE000}; + + uint64_t x = in; + uint64_t t; + + x = (x | (x << 24)) & B[3]; + x = (x | (x << 12)) & B[2]; + x = (x | (x << 6)) & B[1]; + x = (x | (x << 3)) & B[0]; + + for (i = 0; i < 4; i++) + { + t = x & M[i]; + x ^= (t >> 9) ^ (t >> 10) ^ (t >> 12) ^ (t >> 13); + } + + return x & GFMASK; +} + +/* input: field element in, m */ +/* return: (in^2)*m */ +static inline gf gf_sqmul(gf in, gf m) +{ + int i; + + uint64_t x; + uint64_t t0; + uint64_t t1; + uint64_t t; + + const uint64_t M[] = {0x0000001FF0000000, + 0x000000000FF80000, + 0x000000000007E000}; + + t0 = in; + t1 = m; + + x = (t1 << 6) * (t0 & (1 << 6)); + + t0 ^= (t0 << 7); + + x ^= (t1 * (t0 & (0x04001))); + x ^= (t1 * (t0 & (0x08002))) << 1; + x ^= (t1 * (t0 & (0x10004))) << 2; + x ^= (t1 * (t0 & (0x20008))) << 3; + x ^= (t1 * (t0 & (0x40010))) << 4; + x ^= (t1 * (t0 & (0x80020))) << 5; + + for (i = 0; i < 3; i++) + { + t = x & M[i]; + x ^= (t >> 9) ^ (t >> 10) ^ (t >> 12) ^ (t >> 13); + } + + return x & GFMASK; +} + +/* input: field element in, m */ +/* return: ((in^2)^2)*m */ +static inline gf gf_sq2mul(gf in, gf m) +{ + int i; + + uint64_t x; + uint64_t t0; + uint64_t t1; + uint64_t t; + + const uint64_t M[] = {0x1FF0000000000000, + 0x000FF80000000000, + 0x000007FC00000000, + 0x00000003FE000000, + 0x0000000001FE0000, + 0x000000000001E000}; + + t0 = in; + t1 = m; + + x = (t1 << 18) * (t0 & (1 << 6)); + + t0 ^= (t0 << 21); + + x ^= (t1 * (t0 & (0x010000001))); + x ^= (t1 * (t0 & (0x020000002))) << 3; + x ^= (t1 * (t0 & (0x040000004))) << 6; + x ^= (t1 * (t0 & (0x080000008))) << 9; + x ^= (t1 * (t0 & (0x100000010))) << 12; + x ^= (t1 * (t0 & (0x200000020))) << 15; + + for (i = 0; i < 6; i++) + { + t = x & M[i]; + x ^= (t >> 9) ^ (t >> 10) ^ (t >> 12) ^ (t >> 13); + } + + return x & GFMASK; +} + +/* input: field element den, num */ +/* return: (num/den) */ +gf gf_frac(gf den, gf num) +{ + gf tmp_11; + gf tmp_1111; + gf out; + + tmp_11 = gf_sqmul(den, den); // ^11 + tmp_1111 = gf_sq2mul(tmp_11, tmp_11); // ^1111 + out = gf_sq2(tmp_1111); + out = gf_sq2mul(out, tmp_1111); // ^11111111 + out = gf_sq2(out); + out = gf_sq2mul(out, tmp_1111); // ^111111111111 + + return gf_sqmul(out, num); // ^1111111111110 = ^-1 +} + +gf gf_inv(gf den) +{ + return gf_frac(den, ((gf) 1)); +} + +/* input: in0, in1 in GF((2^m)^t)*/ +/* output: out = in0*in1 */ +void GF_mul(gf *out, gf *in0, gf *in1) +{ + int i, j; + + gf prod[ SYS_T*2-1 ]; + + for (i = 0; i < SYS_T*2-1; i++) + prod[i] = 0; + + for (i = 0; i < SYS_T; i++) + for (j = 0; j < SYS_T; j++) + prod[i+j] ^= gf_mul(in0[i], in1[j]); + + // + + for (i = (SYS_T-1)*2; i >= SYS_T; i--) + { + prod[i - SYS_T + 7] ^= prod[i]; + prod[i - SYS_T + 2] ^= prod[i]; + prod[i - SYS_T + 1] ^= prod[i]; + prod[i - SYS_T + 0] ^= prod[i]; + } + + for (i = 0; i < SYS_T; i++) + out[i] = prod[i]; +} + diff --git a/deps/mceliece/kem/mceliece8192128/gf.h b/deps/mceliece/kem/mceliece8192128/gf.h new file mode 100644 index 0000000..f62209d --- /dev/null +++ b/deps/mceliece/kem/mceliece8192128/gf.h @@ -0,0 +1,27 @@ +/* + This file is for functions for field arithmetic +*/ + +#ifndef GF_H +#define GF_H +#define gf_add CRYPTO_NAMESPACE(gf_add) +#define gf_frac CRYPTO_NAMESPACE(gf_frac) +#define gf_inv CRYPTO_NAMESPACE(gf_inv) +#define gf_iszero CRYPTO_NAMESPACE(gf_iszero) +#define gf_mul CRYPTO_NAMESPACE(gf_mul) +#define GF_mul CRYPTO_NAMESPACE(GF_mul) + +#include + +typedef uint16_t gf; + +gf gf_iszero(gf); +gf gf_add(gf, gf); +gf gf_mul(gf, gf); +gf gf_frac(gf, gf); +gf gf_inv(gf); + +void GF_mul(gf *, gf *, gf *); + +#endif + diff --git a/deps/mceliece/kem/mceliece8192128/int32_sort.h b/deps/mceliece/kem/mceliece8192128/int32_sort.h new file mode 100644 index 0000000..a431af2 --- /dev/null +++ b/deps/mceliece/kem/mceliece8192128/int32_sort.h @@ -0,0 +1,46 @@ +#ifndef int32_sort_h +#define int32_sort_h + +#define int32_sort CRYPTO_NAMESPACE(int32_sort) + +#include + +#define int32_MINMAX(a,b) \ +do { \ + int32_t ab = b ^ a; \ + int32_t c = b - a; \ + c ^= ab & (c ^ b); \ + c >>= 31; \ + c &= ab; \ + a ^= c; \ + b ^= c; \ +} while(0) + +static void int32_sort(int32_t *x,long long n) +{ + long long top,p,q,r,i; + + if (n < 2) return; + top = 1; + while (top < n - top) top += top; + + for (p = top;p > 0;p >>= 1) { + for (i = 0;i < n - p;++i) + if (!(i & p)) + int32_MINMAX(x[i],x[i+p]); + i = 0; + for (q = top;q > p;q >>= 1) { + for (;i < n - q;++i) { + if (!(i & p)) { + int32_t a = x[i + p]; + for (r = q;r > p;r >>= 1) + int32_MINMAX(a,x[i+r]); + x[i + p] = a; + } + } + } + } +} + +#endif + diff --git a/deps/mceliece/kem/mceliece8192128/operations.c b/deps/mceliece/kem/mceliece8192128/operations.c new file mode 100644 index 0000000..d05e774 --- /dev/null +++ b/deps/mceliece/kem/mceliece8192128/operations.c @@ -0,0 +1,146 @@ +#include "operations.h" + +#include "controlbits.h" +#include "randombytes.h" +#include "crypto_hash.h" +#include "encrypt.h" +#include "decrypt.h" +#include "params.h" +#include "sk_gen.h" +#include "pk_gen.h" +#include "util.h" + +#include +#include + +int crypto_kem_enc( + unsigned char *c, + unsigned char *key, + const unsigned char *pk +) +{ + unsigned char e[ SYS_N/8 ]; + unsigned char one_ec[ 1 + SYS_N/8 + SYND_BYTES ] = {1}; + + // + + encrypt(c, pk, e); + + memcpy(one_ec + 1, e, SYS_N/8); + memcpy(one_ec + 1 + SYS_N/8, c, SYND_BYTES); + + crypto_hash_32b(key, one_ec, sizeof(one_ec)); + + return 0; +} + +int crypto_kem_dec( + unsigned char *key, + const unsigned char *c, + const unsigned char *sk +) +{ + int i; + + unsigned char ret_decrypt = 0; + + uint16_t m; + + unsigned char e[ SYS_N/8 ]; + unsigned char preimage[ 1 + SYS_N/8 + SYND_BYTES ]; + unsigned char *x = preimage; + const unsigned char *s = sk + 40 + IRR_BYTES + COND_BYTES; + + // + + ret_decrypt = decrypt(e, sk + 40, c); + + m = ret_decrypt; + m -= 1; + m >>= 8; + + *x++ = m & 1; + for (i = 0; i < SYS_N/8; i++) + *x++ = (~m & s[i]) | (m & e[i]); + + for (i = 0; i < SYND_BYTES; i++) + *x++ = c[i]; + + crypto_hash_32b(key, preimage, sizeof(preimage)); + + return 0; +} + +int crypto_kem_keypair +( + unsigned char *pk, + unsigned char *sk +) +{ + int i; + unsigned char seed[ 33 ] = {64}; + unsigned char r[ SYS_N/8 + (1 << GFBITS)*sizeof(uint32_t) + SYS_T*2 + 32 ]; + unsigned char *rp, *skp; + + gf f[ SYS_T ]; // element in GF(2^mt) + gf irr[ SYS_T ]; // Goppa polynomial + uint32_t perm[ 1 << GFBITS ]; // random permutation as 32-bit integers + int16_t pi[ 1 << GFBITS ]; // random permutation + + randombytes(seed+1, 32); + + while (1) + { + rp = &r[ sizeof(r)-32 ]; + skp = sk; + + // expanding and updating the seed + + shake(r, sizeof(r), seed, 33); + memcpy(skp, seed+1, 32); + skp += 32 + 8; + memcpy(seed+1, &r[ sizeof(r)-32 ], 32); + + // generating irreducible polynomial + + rp -= sizeof(f); + + for (i = 0; i < SYS_T; i++) + f[i] = load_gf(rp + i*2); + + if (genpoly_gen(irr, f)) + continue; + + for (i = 0; i < SYS_T; i++) + store_gf(skp + i*2, irr[i]); + + skp += IRR_BYTES; + + // generating permutation + + rp -= sizeof(perm); + + for (i = 0; i < (1 << GFBITS); i++) + perm[i] = load4(rp + i*4); + + if (pk_gen(pk, skp - IRR_BYTES, perm, pi)) + continue; + + controlbitsfrompermutation(skp, pi, GFBITS, 1 << GFBITS); + skp += COND_BYTES; + + // storing the random string s + + rp -= SYS_N/8; + memcpy(skp, rp, SYS_N/8); + + // storing positions of the 32 pivots + + store8(sk + 32, 0xFFFFFFFF); + + break; + } + + return 0; +} + diff --git a/deps/mceliece/kem/mceliece8192128/operations.h b/deps/mceliece/kem/mceliece8192128/operations.h new file mode 100644 index 0000000..bf65502 --- /dev/null +++ b/deps/mceliece/kem/mceliece8192128/operations.h @@ -0,0 +1,25 @@ +#ifndef OPERATIONS_H +#define OPERATIONS_H + +#include "crypto_kem.h" + +int crypto_kem_enc( + unsigned char *c, + unsigned char *key, + const unsigned char *pk +); + +int crypto_kem_dec( + unsigned char *key, + const unsigned char *c, + const unsigned char *sk +); + +int crypto_kem_keypair +( + unsigned char *pk, + unsigned char *sk +); + +#endif + diff --git a/deps/mceliece/kem/mceliece8192128/params.h b/deps/mceliece/kem/mceliece8192128/params.h new file mode 100644 index 0000000..85d379d --- /dev/null +++ b/deps/mceliece/kem/mceliece8192128/params.h @@ -0,0 +1,20 @@ +#ifndef PARAMS_H +#define PARAMS_H + +#define GFBITS 13 +#define SYS_N 8192 +#define SYS_T 128 + +#define COND_BYTES ((1 << (GFBITS-4))*(2*GFBITS - 1)) +#define IRR_BYTES (SYS_T * 2) + +#define PK_NROWS (SYS_T*GFBITS) +#define PK_NCOLS (SYS_N - PK_NROWS) +#define PK_ROW_BYTES ((PK_NCOLS + 7)/8) + +#define SYND_BYTES ((PK_NROWS + 7)/8) + +#define GFMASK ((1 << GFBITS) - 1) + +#endif + diff --git a/deps/mceliece/kem/mceliece8192128/pk_gen.c b/deps/mceliece/kem/mceliece8192128/pk_gen.c new file mode 100644 index 0000000..d42ab25 --- /dev/null +++ b/deps/mceliece/kem/mceliece8192128/pk_gen.c @@ -0,0 +1,151 @@ +/* + This file is for public-key generation +*/ + +#include +#include +#include +#include + +#include "controlbits.h" +#include "uint64_sort.h" +#include "pk_gen.h" +#include "params.h" +#include "benes.h" +#include "root.h" +#include "util.h" +#include "crypto_declassify.h" +#include "crypto_uint64.h" + +static crypto_uint64 uint64_is_equal_declassify(uint64_t t,uint64_t u) +{ + crypto_uint64 mask = crypto_uint64_equal_mask(t,u); + crypto_declassify(&mask,sizeof mask); + return mask; +} + +static crypto_uint64 uint64_is_zero_declassify(uint64_t t) +{ + crypto_uint64 mask = crypto_uint64_zero_mask(t); + crypto_declassify(&mask,sizeof mask); + return mask; +} + +/* input: secret key sk */ +/* output: public key pk */ +int pk_gen(unsigned char * pk, unsigned char * sk, uint32_t * perm, int16_t * pi) +{ + int i, j, k; + int row, c; + + uint64_t buf[ 1 << GFBITS ]; + + unsigned char mat[ PK_NROWS ][ SYS_N/8 ]; + unsigned char mask; + unsigned char b; + + gf g[ SYS_T+1 ]; // Goppa polynomial + gf L[ SYS_N ]; // support + gf inv[ SYS_N ]; + + // + + g[ SYS_T ] = 1; + + for (i = 0; i < SYS_T; i++) { g[i] = load_gf(sk); sk += 2; } + + for (i = 0; i < (1 << GFBITS); i++) + { + buf[i] = perm[i]; + buf[i] <<= 31; + buf[i] |= i; + } + + uint64_sort(buf, 1 << GFBITS); + + for (i = 1; i < (1 << GFBITS); i++) + if (uint64_is_equal_declassify(buf[i-1] >> 31,buf[i] >> 31)) + return -1; + + for (i = 0; i < (1 << GFBITS); i++) pi[i] = buf[i] & GFMASK; + for (i = 0; i < SYS_N; i++) L[i] = bitrev(pi[i]); + + // filling the matrix + + root(inv, g, L); + + for (i = 0; i < SYS_N; i++) + inv[i] = gf_inv(inv[i]); + + for (i = 0; i < PK_NROWS; i++) + for (j = 0; j < SYS_N/8; j++) + mat[i][j] = 0; + + for (i = 0; i < SYS_T; i++) + { + for (j = 0; j < SYS_N; j+=8) + for (k = 0; k < GFBITS; k++) + { + b = (inv[j+7] >> k) & 1; b <<= 1; + b |= (inv[j+6] >> k) & 1; b <<= 1; + b |= (inv[j+5] >> k) & 1; b <<= 1; + b |= (inv[j+4] >> k) & 1; b <<= 1; + b |= (inv[j+3] >> k) & 1; b <<= 1; + b |= (inv[j+2] >> k) & 1; b <<= 1; + b |= (inv[j+1] >> k) & 1; b <<= 1; + b |= (inv[j+0] >> k) & 1; + + mat[ i*GFBITS + k ][ j/8 ] = b; + } + + for (j = 0; j < SYS_N; j++) + inv[j] = gf_mul(inv[j], L[j]); + + } + + // gaussian elimination + + for (i = 0; i < (PK_NROWS + 7) / 8; i++) + for (j = 0; j < 8; j++) + { + row = i*8 + j; + + if (row >= PK_NROWS) + break; + + for (k = row + 1; k < PK_NROWS; k++) + { + mask = mat[ row ][ i ] ^ mat[ k ][ i ]; + mask >>= j; + mask &= 1; + mask = -mask; + + for (c = 0; c < SYS_N/8; c++) + mat[ row ][ c ] ^= mat[ k ][ c ] & mask; + } + + if ( uint64_is_zero_declassify((mat[ row ][ i ] >> j) & 1) ) // return if not systematic + { + return -1; + } + + for (k = 0; k < PK_NROWS; k++) + { + if (k != row) + { + mask = mat[ k ][ i ] >> j; + mask &= 1; + mask = -mask; + + for (c = 0; c < SYS_N/8; c++) + mat[ k ][ c ] ^= mat[ row ][ c ] & mask; + } + } + } + + for (i = 0; i < PK_NROWS; i++) + memcpy(pk + i*PK_ROW_BYTES, mat[i] + PK_NROWS/8, PK_ROW_BYTES); + + return 0; +} + diff --git a/deps/mceliece/kem/mceliece8192128/pk_gen.h b/deps/mceliece/kem/mceliece8192128/pk_gen.h new file mode 100644 index 0000000..eec43a7 --- /dev/null +++ b/deps/mceliece/kem/mceliece8192128/pk_gen.h @@ -0,0 +1,14 @@ +/* + This file is for public-key generation +*/ + +#ifndef PK_GEN_H +#define PK_GEN_H +#define pk_gen CRYPTO_NAMESPACE(pk_gen) + +#include "gf.h" + +int pk_gen(unsigned char *, unsigned char *, uint32_t *, int16_t *); + +#endif + diff --git a/deps/mceliece/kem/mceliece8192128/randombytes.h b/deps/mceliece/kem/mceliece8192128/randombytes.h new file mode 100644 index 0000000..7e59351 --- /dev/null +++ b/deps/mceliece/kem/mceliece8192128/randombytes.h @@ -0,0 +1 @@ +#include "../../mceliece_externals.h" diff --git a/deps/mceliece/kem/mceliece8192128/root.c b/deps/mceliece/kem/mceliece8192128/root.c new file mode 100644 index 0000000..1c1b634 --- /dev/null +++ b/deps/mceliece/kem/mceliece8192128/root.c @@ -0,0 +1,38 @@ +/* + This file is for evaluating a polynomial at one or more field elements +*/ + +#include "root.h" +#include "params.h" +#include "gf.h" + +#include + +/* input: polynomial f and field element a */ +/* return f(a) */ +gf eval(gf *f, gf a) +{ + int i; + gf r; + + r = f[ SYS_T ]; + + for (i = SYS_T-1; i >= 0; i--) + { + r = gf_mul(r, a); + r = gf_add(r, f[i]); + } + + return r; +} + +/* input: polynomial f and list of field elements L */ +/* output: out = [ f(a) for a in L ] */ +void root(gf *out, gf *f, gf *L) +{ + int i; + + for (i = 0; i < SYS_N; i++) + out[i] = eval(f, L[i]); +} + diff --git a/deps/mceliece/kem/mceliece8192128/root.h b/deps/mceliece/kem/mceliece8192128/root.h new file mode 100644 index 0000000..42516e4 --- /dev/null +++ b/deps/mceliece/kem/mceliece8192128/root.h @@ -0,0 +1,16 @@ +/* + This file is for evaluating a polynomial at one or more field elements +*/ + +#ifndef ROOT_H +#define ROOT_H +#define eval CRYPTO_NAMESPACE(eval) +#define root CRYPTO_NAMESPACE(root) + +#include "gf.h" + +gf eval(gf *, gf); +void root(gf *, gf *, gf *); + +#endif + diff --git a/deps/mceliece/kem/mceliece8192128/sk_gen.c b/deps/mceliece/kem/mceliece8192128/sk_gen.c new file mode 100644 index 0000000..340cc9a --- /dev/null +++ b/deps/mceliece/kem/mceliece8192128/sk_gen.c @@ -0,0 +1,85 @@ +/* + This file is for secret-key generation +*/ + +#include "sk_gen.h" + +#include "randombytes.h" +#include "controlbits.h" +#include "params.h" +#include "util.h" +#include "gf.h" +#include "crypto_declassify.h" +#include "crypto_uint16.h" + +static inline crypto_uint16 gf_is_zero_declassify(gf t) +{ + crypto_uint16 mask = crypto_uint16_zero_mask(t); + crypto_declassify(&mask,sizeof mask); + return mask; +} + +/* input: f, element in GF((2^m)^t) */ +/* output: out, minimal polynomial of f */ +/* return: 0 for success and -1 for failure */ +int genpoly_gen(gf *out, gf *f) +{ + int i, j, k, c; + + gf mat[ SYS_T+1 ][ SYS_T ]; + gf mask, inv, t; + + // fill matrix + + mat[0][0] = 1; + + for (i = 1; i < SYS_T; i++) + mat[0][i] = 0; + + for (i = 0; i < SYS_T; i++) + mat[1][i] = f[i]; + + for (j = 2; j <= SYS_T; j++) + GF_mul(mat[j], mat[j-1], f); + + // gaussian + + for (j = 0; j < SYS_T; j++) + { + for (k = j + 1; k < SYS_T; k++) + { + mask = gf_iszero(mat[ j ][ j ]); + + for (c = j; c < SYS_T + 1; c++) + mat[ c ][ j ] ^= mat[ c ][ k ] & mask; + + } + + if ( gf_is_zero_declassify(mat[ j ][ j ]) ) // return if not systematic + { + return -1; + } + + inv = gf_inv(mat[j][j]); + + for (c = j; c < SYS_T + 1; c++) + mat[ c ][ j ] = gf_mul(mat[ c ][ j ], inv) ; + + for (k = 0; k < SYS_T; k++) + { + if (k != j) + { + t = mat[ j ][ k ]; + + for (c = j; c < SYS_T + 1; c++) + mat[ c ][ k ] ^= gf_mul(mat[ c ][ j ], t); + } + } + } + + for (i = 0; i < SYS_T; i++) + out[i] = mat[ SYS_T ][ i ]; + + return 0; +} + diff --git a/deps/mceliece/kem/mceliece8192128/sk_gen.h b/deps/mceliece/kem/mceliece8192128/sk_gen.h new file mode 100644 index 0000000..e319703 --- /dev/null +++ b/deps/mceliece/kem/mceliece8192128/sk_gen.h @@ -0,0 +1,18 @@ +/* + This file is for secret-key generation +*/ + +#ifndef SK_GEN_H +#define SK_GEN_H +#define genpoly_gen CRYPTO_NAMESPACE(genpoly_gen) +#define perm_check CRYPTO_NAMESPACE(perm_check) + +#include "gf.h" + +#include + +int genpoly_gen(gf *, gf *); +int perm_check(uint32_t *); + +#endif + diff --git a/deps/mceliece/kem/mceliece8192128/subroutines/crypto_declassify.h b/deps/mceliece/kem/mceliece8192128/subroutines/crypto_declassify.h new file mode 100644 index 0000000..8d84209 --- /dev/null +++ b/deps/mceliece/kem/mceliece8192128/subroutines/crypto_declassify.h @@ -0,0 +1,8 @@ +#ifndef crypto_declassify_h +#define crypto_declassify_h + +static void crypto_declassify(void *x,unsigned long long n) +{ +} + +#endif diff --git a/deps/mceliece/kem/mceliece8192128/subroutines/crypto_int16.h b/deps/mceliece/kem/mceliece8192128/subroutines/crypto_int16.h new file mode 100644 index 0000000..72bbf52 --- /dev/null +++ b/deps/mceliece/kem/mceliece8192128/subroutines/crypto_int16.h @@ -0,0 +1,81 @@ +#ifndef crypto_int16_h +#define crypto_int16_h + +#include +typedef int16_t crypto_int16; + +static crypto_int16 crypto_int16_negative_mask(crypto_int16 crypto_int16_x) +{ + return crypto_int16_x >> 15; +} + +static crypto_int16 crypto_int16_nonzero_mask(crypto_int16 crypto_int16_x) +{ + return crypto_int16_negative_mask(crypto_int16_x) | crypto_int16_negative_mask(-crypto_int16_x); +} + +static crypto_int16 crypto_int16_zero_mask(crypto_int16 crypto_int16_x) +{ + return ~crypto_int16_nonzero_mask(crypto_int16_x); +} + +static crypto_int16 crypto_int16_positive_mask(crypto_int16 crypto_int16_x) +{ + crypto_int16 crypto_int16_z = -crypto_int16_x; + crypto_int16_z ^= crypto_int16_x & crypto_int16_z; + return crypto_int16_negative_mask(crypto_int16_z); +} + +static crypto_int16 crypto_int16_unequal_mask(crypto_int16 crypto_int16_x,crypto_int16 crypto_int16_y) +{ + crypto_int16 crypto_int16_xy = crypto_int16_x ^ crypto_int16_y; + return crypto_int16_nonzero_mask(crypto_int16_xy); +} + +static crypto_int16 crypto_int16_equal_mask(crypto_int16 crypto_int16_x,crypto_int16 crypto_int16_y) +{ + return ~crypto_int16_unequal_mask(crypto_int16_x,crypto_int16_y); +} + +static crypto_int16 crypto_int16_smaller_mask(crypto_int16 crypto_int16_x,crypto_int16 crypto_int16_y) +{ + crypto_int16 crypto_int16_xy = crypto_int16_x ^ crypto_int16_y; + crypto_int16 crypto_int16_z = crypto_int16_x - crypto_int16_y; + crypto_int16_z ^= crypto_int16_xy & (crypto_int16_z ^ crypto_int16_x); + return crypto_int16_negative_mask(crypto_int16_z); +} + +static crypto_int16 crypto_int16_min(crypto_int16 crypto_int16_x,crypto_int16 crypto_int16_y) +{ + crypto_int16 crypto_int16_xy = crypto_int16_y ^ crypto_int16_x; + crypto_int16 crypto_int16_z = crypto_int16_y - crypto_int16_x; + crypto_int16_z ^= crypto_int16_xy & (crypto_int16_z ^ crypto_int16_y); + crypto_int16_z = crypto_int16_negative_mask(crypto_int16_z); + crypto_int16_z &= crypto_int16_xy; + return crypto_int16_x ^ crypto_int16_z; +} + +static crypto_int16 crypto_int16_max(crypto_int16 crypto_int16_x,crypto_int16 crypto_int16_y) +{ + crypto_int16 crypto_int16_xy = crypto_int16_y ^ crypto_int16_x; + crypto_int16 crypto_int16_z = crypto_int16_y - crypto_int16_x; + crypto_int16_z ^= crypto_int16_xy & (crypto_int16_z ^ crypto_int16_y); + crypto_int16_z = crypto_int16_negative_mask(crypto_int16_z); + crypto_int16_z &= crypto_int16_xy; + return crypto_int16_y ^ crypto_int16_z; +} + +static void crypto_int16_minmax(crypto_int16 *crypto_int16_a,crypto_int16 *crypto_int16_b) +{ + crypto_int16 crypto_int16_x = *crypto_int16_a; + crypto_int16 crypto_int16_y = *crypto_int16_b; + crypto_int16 crypto_int16_xy = crypto_int16_y ^ crypto_int16_x; + crypto_int16 crypto_int16_z = crypto_int16_y - crypto_int16_x; + crypto_int16_z ^= crypto_int16_xy & (crypto_int16_z ^ crypto_int16_y); + crypto_int16_z = crypto_int16_negative_mask(crypto_int16_z); + crypto_int16_z &= crypto_int16_xy; + *crypto_int16_a = crypto_int16_x ^ crypto_int16_z; + *crypto_int16_b = crypto_int16_y ^ crypto_int16_z; +} + +#endif diff --git a/deps/mceliece/kem/mceliece8192128/subroutines/crypto_int32.h b/deps/mceliece/kem/mceliece8192128/subroutines/crypto_int32.h new file mode 100644 index 0000000..c22f735 --- /dev/null +++ b/deps/mceliece/kem/mceliece8192128/subroutines/crypto_int32.h @@ -0,0 +1,81 @@ +#ifndef crypto_int32_h +#define crypto_int32_h + +#include +typedef int32_t crypto_int32; + +static crypto_int32 crypto_int32_negative_mask(crypto_int32 crypto_int32_x) +{ + return crypto_int32_x >> 31; +} + +static crypto_int32 crypto_int32_nonzero_mask(crypto_int32 crypto_int32_x) +{ + return crypto_int32_negative_mask(crypto_int32_x) | crypto_int32_negative_mask(-crypto_int32_x); +} + +static crypto_int32 crypto_int32_zero_mask(crypto_int32 crypto_int32_x) +{ + return ~crypto_int32_nonzero_mask(crypto_int32_x); +} + +static crypto_int32 crypto_int32_positive_mask(crypto_int32 crypto_int32_x) +{ + crypto_int32 crypto_int32_z = -crypto_int32_x; + crypto_int32_z ^= crypto_int32_x & crypto_int32_z; + return crypto_int32_negative_mask(crypto_int32_z); +} + +static crypto_int32 crypto_int32_unequal_mask(crypto_int32 crypto_int32_x,crypto_int32 crypto_int32_y) +{ + crypto_int32 crypto_int32_xy = crypto_int32_x ^ crypto_int32_y; + return crypto_int32_nonzero_mask(crypto_int32_xy); +} + +static crypto_int32 crypto_int32_equal_mask(crypto_int32 crypto_int32_x,crypto_int32 crypto_int32_y) +{ + return ~crypto_int32_unequal_mask(crypto_int32_x,crypto_int32_y); +} + +static crypto_int32 crypto_int32_smaller_mask(crypto_int32 crypto_int32_x,crypto_int32 crypto_int32_y) +{ + crypto_int32 crypto_int32_xy = crypto_int32_x ^ crypto_int32_y; + crypto_int32 crypto_int32_z = crypto_int32_x - crypto_int32_y; + crypto_int32_z ^= crypto_int32_xy & (crypto_int32_z ^ crypto_int32_x); + return crypto_int32_negative_mask(crypto_int32_z); +} + +static crypto_int32 crypto_int32_min(crypto_int32 crypto_int32_x,crypto_int32 crypto_int32_y) +{ + crypto_int32 crypto_int32_xy = crypto_int32_y ^ crypto_int32_x; + crypto_int32 crypto_int32_z = crypto_int32_y - crypto_int32_x; + crypto_int32_z ^= crypto_int32_xy & (crypto_int32_z ^ crypto_int32_y); + crypto_int32_z = crypto_int32_negative_mask(crypto_int32_z); + crypto_int32_z &= crypto_int32_xy; + return crypto_int32_x ^ crypto_int32_z; +} + +static crypto_int32 crypto_int32_max(crypto_int32 crypto_int32_x,crypto_int32 crypto_int32_y) +{ + crypto_int32 crypto_int32_xy = crypto_int32_y ^ crypto_int32_x; + crypto_int32 crypto_int32_z = crypto_int32_y - crypto_int32_x; + crypto_int32_z ^= crypto_int32_xy & (crypto_int32_z ^ crypto_int32_y); + crypto_int32_z = crypto_int32_negative_mask(crypto_int32_z); + crypto_int32_z &= crypto_int32_xy; + return crypto_int32_y ^ crypto_int32_z; +} + +static void crypto_int32_minmax(crypto_int32 *crypto_int32_a,crypto_int32 *crypto_int32_b) +{ + crypto_int32 crypto_int32_x = *crypto_int32_a; + crypto_int32 crypto_int32_y = *crypto_int32_b; + crypto_int32 crypto_int32_xy = crypto_int32_y ^ crypto_int32_x; + crypto_int32 crypto_int32_z = crypto_int32_y - crypto_int32_x; + crypto_int32_z ^= crypto_int32_xy & (crypto_int32_z ^ crypto_int32_y); + crypto_int32_z = crypto_int32_negative_mask(crypto_int32_z); + crypto_int32_z &= crypto_int32_xy; + *crypto_int32_a = crypto_int32_x ^ crypto_int32_z; + *crypto_int32_b = crypto_int32_y ^ crypto_int32_z; +} + +#endif diff --git a/deps/mceliece/kem/mceliece8192128/subroutines/crypto_uint16.h b/deps/mceliece/kem/mceliece8192128/subroutines/crypto_uint16.h new file mode 100644 index 0000000..f0ebbbf --- /dev/null +++ b/deps/mceliece/kem/mceliece8192128/subroutines/crypto_uint16.h @@ -0,0 +1,76 @@ +#ifndef crypto_uint16_h +#define crypto_uint16_h + +#include +typedef uint16_t crypto_uint16; + +typedef int16_t crypto_uint16_signed; + +static crypto_uint16_signed crypto_uint16_signed_negative_mask(crypto_uint16_signed crypto_uint16_signed_x) +{ + return crypto_uint16_signed_x >> 15; +} + +static crypto_uint16 crypto_uint16_nonzero_mask(crypto_uint16 crypto_uint16_x) +{ + return crypto_uint16_signed_negative_mask(crypto_uint16_x) | crypto_uint16_signed_negative_mask(-crypto_uint16_x); +} + +static crypto_uint16 crypto_uint16_zero_mask(crypto_uint16 crypto_uint16_x) +{ + return ~crypto_uint16_nonzero_mask(crypto_uint16_x); +} + +static crypto_uint16 crypto_uint16_unequal_mask(crypto_uint16 crypto_uint16_x,crypto_uint16 crypto_uint16_y) +{ + crypto_uint16 crypto_uint16_xy = crypto_uint16_x ^ crypto_uint16_y; + return crypto_uint16_nonzero_mask(crypto_uint16_xy); +} + +static crypto_uint16 crypto_uint16_equal_mask(crypto_uint16 crypto_uint16_x,crypto_uint16 crypto_uint16_y) +{ + return ~crypto_uint16_unequal_mask(crypto_uint16_x,crypto_uint16_y); +} + +static crypto_uint16 crypto_uint16_smaller_mask(crypto_uint16 crypto_uint16_x,crypto_uint16 crypto_uint16_y) +{ + crypto_uint16 crypto_uint16_xy = crypto_uint16_x ^ crypto_uint16_y; + crypto_uint16 crypto_uint16_z = crypto_uint16_x - crypto_uint16_y; + crypto_uint16_z ^= crypto_uint16_xy & (crypto_uint16_z ^ crypto_uint16_x ^ (((crypto_uint16) 1) << 15)); + return crypto_uint16_signed_negative_mask(crypto_uint16_z); +} + +static crypto_uint16 crypto_uint16_min(crypto_uint16 crypto_uint16_x,crypto_uint16 crypto_uint16_y) +{ + crypto_uint16 crypto_uint16_xy = crypto_uint16_y ^ crypto_uint16_x; + crypto_uint16 crypto_uint16_z = crypto_uint16_y - crypto_uint16_x; + crypto_uint16_z ^= crypto_uint16_xy & (crypto_uint16_z ^ crypto_uint16_y ^ (((crypto_uint16) 1) << 15)); + crypto_uint16_z = crypto_uint16_signed_negative_mask(crypto_uint16_z); + crypto_uint16_z &= crypto_uint16_xy; + return crypto_uint16_x ^ crypto_uint16_z; +} + +static crypto_uint16 crypto_uint16_max(crypto_uint16 crypto_uint16_x,crypto_uint16 crypto_uint16_y) +{ + crypto_uint16 crypto_uint16_xy = crypto_uint16_y ^ crypto_uint16_x; + crypto_uint16 crypto_uint16_z = crypto_uint16_y - crypto_uint16_x; + crypto_uint16_z ^= crypto_uint16_xy & (crypto_uint16_z ^ crypto_uint16_y ^ (((crypto_uint16) 1) << 15)); + crypto_uint16_z = crypto_uint16_signed_negative_mask(crypto_uint16_z); + crypto_uint16_z &= crypto_uint16_xy; + return crypto_uint16_y ^ crypto_uint16_z; +} + +static void crypto_uint16_minmax(crypto_uint16 *crypto_uint16_a,crypto_uint16 *crypto_uint16_b) +{ + crypto_uint16 crypto_uint16_x = *crypto_uint16_a; + crypto_uint16 crypto_uint16_y = *crypto_uint16_b; + crypto_uint16 crypto_uint16_xy = crypto_uint16_y ^ crypto_uint16_x; + crypto_uint16 crypto_uint16_z = crypto_uint16_y - crypto_uint16_x; + crypto_uint16_z ^= crypto_uint16_xy & (crypto_uint16_z ^ crypto_uint16_y ^ (((crypto_uint16) 1) << 15)); + crypto_uint16_z = crypto_uint16_signed_negative_mask(crypto_uint16_z); + crypto_uint16_z &= crypto_uint16_xy; + *crypto_uint16_a = crypto_uint16_x ^ crypto_uint16_z; + *crypto_uint16_b = crypto_uint16_y ^ crypto_uint16_z; +} + +#endif diff --git a/deps/mceliece/kem/mceliece8192128/subroutines/crypto_uint32.h b/deps/mceliece/kem/mceliece8192128/subroutines/crypto_uint32.h new file mode 100644 index 0000000..3f39d62 --- /dev/null +++ b/deps/mceliece/kem/mceliece8192128/subroutines/crypto_uint32.h @@ -0,0 +1,76 @@ +#ifndef crypto_uint32_h +#define crypto_uint32_h + +#include +typedef uint32_t crypto_uint32; + +typedef int32_t crypto_uint32_signed; + +static crypto_uint32_signed crypto_uint32_signed_negative_mask(crypto_uint32_signed crypto_uint32_signed_x) +{ + return crypto_uint32_signed_x >> 31; +} + +static crypto_uint32 crypto_uint32_nonzero_mask(crypto_uint32 crypto_uint32_x) +{ + return crypto_uint32_signed_negative_mask(crypto_uint32_x) | crypto_uint32_signed_negative_mask(-crypto_uint32_x); +} + +static crypto_uint32 crypto_uint32_zero_mask(crypto_uint32 crypto_uint32_x) +{ + return ~crypto_uint32_nonzero_mask(crypto_uint32_x); +} + +static crypto_uint32 crypto_uint32_unequal_mask(crypto_uint32 crypto_uint32_x,crypto_uint32 crypto_uint32_y) +{ + crypto_uint32 crypto_uint32_xy = crypto_uint32_x ^ crypto_uint32_y; + return crypto_uint32_nonzero_mask(crypto_uint32_xy); +} + +static crypto_uint32 crypto_uint32_equal_mask(crypto_uint32 crypto_uint32_x,crypto_uint32 crypto_uint32_y) +{ + return ~crypto_uint32_unequal_mask(crypto_uint32_x,crypto_uint32_y); +} + +static crypto_uint32 crypto_uint32_smaller_mask(crypto_uint32 crypto_uint32_x,crypto_uint32 crypto_uint32_y) +{ + crypto_uint32 crypto_uint32_xy = crypto_uint32_x ^ crypto_uint32_y; + crypto_uint32 crypto_uint32_z = crypto_uint32_x - crypto_uint32_y; + crypto_uint32_z ^= crypto_uint32_xy & (crypto_uint32_z ^ crypto_uint32_x ^ (((crypto_uint32) 1) << 31)); + return crypto_uint32_signed_negative_mask(crypto_uint32_z); +} + +static crypto_uint32 crypto_uint32_min(crypto_uint32 crypto_uint32_x,crypto_uint32 crypto_uint32_y) +{ + crypto_uint32 crypto_uint32_xy = crypto_uint32_y ^ crypto_uint32_x; + crypto_uint32 crypto_uint32_z = crypto_uint32_y - crypto_uint32_x; + crypto_uint32_z ^= crypto_uint32_xy & (crypto_uint32_z ^ crypto_uint32_y ^ (((crypto_uint32) 1) << 31)); + crypto_uint32_z = crypto_uint32_signed_negative_mask(crypto_uint32_z); + crypto_uint32_z &= crypto_uint32_xy; + return crypto_uint32_x ^ crypto_uint32_z; +} + +static crypto_uint32 crypto_uint32_max(crypto_uint32 crypto_uint32_x,crypto_uint32 crypto_uint32_y) +{ + crypto_uint32 crypto_uint32_xy = crypto_uint32_y ^ crypto_uint32_x; + crypto_uint32 crypto_uint32_z = crypto_uint32_y - crypto_uint32_x; + crypto_uint32_z ^= crypto_uint32_xy & (crypto_uint32_z ^ crypto_uint32_y ^ (((crypto_uint32) 1) << 31)); + crypto_uint32_z = crypto_uint32_signed_negative_mask(crypto_uint32_z); + crypto_uint32_z &= crypto_uint32_xy; + return crypto_uint32_y ^ crypto_uint32_z; +} + +static void crypto_uint32_minmax(crypto_uint32 *crypto_uint32_a,crypto_uint32 *crypto_uint32_b) +{ + crypto_uint32 crypto_uint32_x = *crypto_uint32_a; + crypto_uint32 crypto_uint32_y = *crypto_uint32_b; + crypto_uint32 crypto_uint32_xy = crypto_uint32_y ^ crypto_uint32_x; + crypto_uint32 crypto_uint32_z = crypto_uint32_y - crypto_uint32_x; + crypto_uint32_z ^= crypto_uint32_xy & (crypto_uint32_z ^ crypto_uint32_y ^ (((crypto_uint32) 1) << 31)); + crypto_uint32_z = crypto_uint32_signed_negative_mask(crypto_uint32_z); + crypto_uint32_z &= crypto_uint32_xy; + *crypto_uint32_a = crypto_uint32_x ^ crypto_uint32_z; + *crypto_uint32_b = crypto_uint32_y ^ crypto_uint32_z; +} + +#endif diff --git a/deps/mceliece/kem/mceliece8192128/subroutines/crypto_uint64.h b/deps/mceliece/kem/mceliece8192128/subroutines/crypto_uint64.h new file mode 100644 index 0000000..42e2be9 --- /dev/null +++ b/deps/mceliece/kem/mceliece8192128/subroutines/crypto_uint64.h @@ -0,0 +1,76 @@ +#ifndef crypto_uint64_h +#define crypto_uint64_h + +#include +typedef uint64_t crypto_uint64; + +typedef int64_t crypto_uint64_signed; + +static crypto_uint64_signed crypto_uint64_signed_negative_mask(crypto_uint64_signed crypto_uint64_signed_x) +{ + return crypto_uint64_signed_x >> 63; +} + +static crypto_uint64 crypto_uint64_nonzero_mask(crypto_uint64 crypto_uint64_x) +{ + return crypto_uint64_signed_negative_mask(crypto_uint64_x) | crypto_uint64_signed_negative_mask(-crypto_uint64_x); +} + +static crypto_uint64 crypto_uint64_zero_mask(crypto_uint64 crypto_uint64_x) +{ + return ~crypto_uint64_nonzero_mask(crypto_uint64_x); +} + +static crypto_uint64 crypto_uint64_unequal_mask(crypto_uint64 crypto_uint64_x,crypto_uint64 crypto_uint64_y) +{ + crypto_uint64 crypto_uint64_xy = crypto_uint64_x ^ crypto_uint64_y; + return crypto_uint64_nonzero_mask(crypto_uint64_xy); +} + +static crypto_uint64 crypto_uint64_equal_mask(crypto_uint64 crypto_uint64_x,crypto_uint64 crypto_uint64_y) +{ + return ~crypto_uint64_unequal_mask(crypto_uint64_x,crypto_uint64_y); +} + +static crypto_uint64 crypto_uint64_smaller_mask(crypto_uint64 crypto_uint64_x,crypto_uint64 crypto_uint64_y) +{ + crypto_uint64 crypto_uint64_xy = crypto_uint64_x ^ crypto_uint64_y; + crypto_uint64 crypto_uint64_z = crypto_uint64_x - crypto_uint64_y; + crypto_uint64_z ^= crypto_uint64_xy & (crypto_uint64_z ^ crypto_uint64_x ^ (((crypto_uint64) 1) << 63)); + return crypto_uint64_signed_negative_mask(crypto_uint64_z); +} + +static crypto_uint64 crypto_uint64_min(crypto_uint64 crypto_uint64_x,crypto_uint64 crypto_uint64_y) +{ + crypto_uint64 crypto_uint64_xy = crypto_uint64_y ^ crypto_uint64_x; + crypto_uint64 crypto_uint64_z = crypto_uint64_y - crypto_uint64_x; + crypto_uint64_z ^= crypto_uint64_xy & (crypto_uint64_z ^ crypto_uint64_y ^ (((crypto_uint64) 1) << 63)); + crypto_uint64_z = crypto_uint64_signed_negative_mask(crypto_uint64_z); + crypto_uint64_z &= crypto_uint64_xy; + return crypto_uint64_x ^ crypto_uint64_z; +} + +static crypto_uint64 crypto_uint64_max(crypto_uint64 crypto_uint64_x,crypto_uint64 crypto_uint64_y) +{ + crypto_uint64 crypto_uint64_xy = crypto_uint64_y ^ crypto_uint64_x; + crypto_uint64 crypto_uint64_z = crypto_uint64_y - crypto_uint64_x; + crypto_uint64_z ^= crypto_uint64_xy & (crypto_uint64_z ^ crypto_uint64_y ^ (((crypto_uint64) 1) << 63)); + crypto_uint64_z = crypto_uint64_signed_negative_mask(crypto_uint64_z); + crypto_uint64_z &= crypto_uint64_xy; + return crypto_uint64_y ^ crypto_uint64_z; +} + +static void crypto_uint64_minmax(crypto_uint64 *crypto_uint64_a,crypto_uint64 *crypto_uint64_b) +{ + crypto_uint64 crypto_uint64_x = *crypto_uint64_a; + crypto_uint64 crypto_uint64_y = *crypto_uint64_b; + crypto_uint64 crypto_uint64_xy = crypto_uint64_y ^ crypto_uint64_x; + crypto_uint64 crypto_uint64_z = crypto_uint64_y - crypto_uint64_x; + crypto_uint64_z ^= crypto_uint64_xy & (crypto_uint64_z ^ crypto_uint64_y ^ (((crypto_uint64) 1) << 63)); + crypto_uint64_z = crypto_uint64_signed_negative_mask(crypto_uint64_z); + crypto_uint64_z &= crypto_uint64_xy; + *crypto_uint64_a = crypto_uint64_x ^ crypto_uint64_z; + *crypto_uint64_b = crypto_uint64_y ^ crypto_uint64_z; +} + +#endif diff --git a/deps/mceliece/kem/mceliece8192128/synd.c b/deps/mceliece/kem/mceliece8192128/synd.c new file mode 100644 index 0000000..c945647 --- /dev/null +++ b/deps/mceliece/kem/mceliece8192128/synd.c @@ -0,0 +1,36 @@ +/* + This file is for syndrome computation +*/ + +#include "synd.h" + +#include "params.h" +#include "root.h" + +#include + +/* input: Goppa polynomial f, support L, received word r */ +/* output: out, the syndrome of length 2t */ +void synd(gf *out, gf *f, gf *L, unsigned char *r) +{ + int i, j; + gf e, e_inv, c; + + for (j = 0; j < 2*SYS_T; j++) + out[j] = 0; + + for (i = 0; i < SYS_N; i++) + { + c = (r[i/8] >> (i%8)) & 1; + + e = eval(f, L[i]); + e_inv = gf_inv(gf_mul(e,e)); + + for (j = 0; j < 2*SYS_T; j++) + { + out[j] = gf_add(out[j], gf_mul(e_inv, c)); + e_inv = gf_mul(e_inv, L[i]); + } + } +} + diff --git a/deps/mceliece/kem/mceliece8192128/synd.h b/deps/mceliece/kem/mceliece8192128/synd.h new file mode 100644 index 0000000..9331406 --- /dev/null +++ b/deps/mceliece/kem/mceliece8192128/synd.h @@ -0,0 +1,14 @@ +/* + This file is for syndrome computation +*/ + +#ifndef SYND_H +#define SYND_H +#define synd CRYPTO_NAMESPACE(synd) + +#include "gf.h" + +void synd(gf *, gf *, gf *, unsigned char *); + +#endif + diff --git a/deps/mceliece/kem/mceliece8192128/transpose.c b/deps/mceliece/kem/mceliece8192128/transpose.c new file mode 100644 index 0000000..0da2bc5 --- /dev/null +++ b/deps/mceliece/kem/mceliece8192128/transpose.c @@ -0,0 +1,43 @@ +/* + This file is for matrix transposition +*/ + +#include "transpose.h" + +#include + +/* input: in, a 64x64 matrix over GF(2) */ +/* output: out, transpose of in */ +void transpose_64x64(uint64_t * out, uint64_t * in) +{ + int i, j, s, d; + + uint64_t x, y; + uint64_t masks[6][2] = { + {0x5555555555555555, 0xAAAAAAAAAAAAAAAA}, + {0x3333333333333333, 0xCCCCCCCCCCCCCCCC}, + {0x0F0F0F0F0F0F0F0F, 0xF0F0F0F0F0F0F0F0}, + {0x00FF00FF00FF00FF, 0xFF00FF00FF00FF00}, + {0x0000FFFF0000FFFF, 0xFFFF0000FFFF0000}, + {0x00000000FFFFFFFF, 0xFFFFFFFF00000000} + }; + + for (i = 0; i < 64; i++) + out[i] = in[i]; + + for (d = 5; d >= 0; d--) + { + s = 1 << d; + + for (i = 0; i < 64; i += s*2) + for (j = i; j < i+s; j++) + { + x = (out[j] & masks[d][0]) | ((out[j+s] & masks[d][0]) << s); + y = ((out[j] & masks[d][1]) >> s) | (out[j+s] & masks[d][1]); + + out[j+0] = x; + out[j+s] = y; + } + } +} + diff --git a/deps/mceliece/kem/mceliece8192128/transpose.h b/deps/mceliece/kem/mceliece8192128/transpose.h new file mode 100644 index 0000000..31e5b96 --- /dev/null +++ b/deps/mceliece/kem/mceliece8192128/transpose.h @@ -0,0 +1,14 @@ +/* + This file is for matrix transposition +*/ + +#ifndef TRANSPOSE_H +#define TRANSPOSE_H +#define transpose_64x64 CRYPTO_NAMESPACE(transpose_64x64) + +#include + +void transpose_64x64(uint64_t *, uint64_t *); + +#endif + diff --git a/deps/mceliece/kem/mceliece8192128/uint64_sort.h b/deps/mceliece/kem/mceliece8192128/uint64_sort.h new file mode 100644 index 0000000..2fb100c --- /dev/null +++ b/deps/mceliece/kem/mceliece8192128/uint64_sort.h @@ -0,0 +1,45 @@ +#ifndef uint64_sort_h +#define uint64_sort_h + +#define int64_sort CRYPTO_NAMESPACE(int64_sort) + +#include + +#define uint64_MINMAX(a,b) \ +do { \ + uint64_t c = b - a; \ + c >>= 63; \ + c = -c; \ + c &= a ^ b; \ + a ^= c; \ + b ^= c; \ +} while(0) + +static void uint64_sort(uint64_t *x,long long n) +{ + long long top,p,q,r,i; + + if (n < 2) return; + top = 1; + while (top < n - top) top += top; + + for (p = top;p > 0;p >>= 1) { + for (i = 0;i < n - p;++i) + if (!(i & p)) + uint64_MINMAX(x[i],x[i+p]); + i = 0; + for (q = top;q > p;q >>= 1) { + for (;i < n - q;++i) { + if (!(i & p)) { + uint64_t a = x[i + p]; + for (r = q;r > p;r >>= 1) + uint64_MINMAX(a,x[i+r]); + x[i + p] = a; + } + } + } + } +} + +#endif + diff --git a/deps/mceliece/kem/mceliece8192128/util.c b/deps/mceliece/kem/mceliece8192128/util.c new file mode 100644 index 0000000..1679168 --- /dev/null +++ b/deps/mceliece/kem/mceliece8192128/util.c @@ -0,0 +1,75 @@ +/* + This file is for loading/storing data in a little-endian fashion +*/ + +#include "util.h" + +#include "params.h" + +void store_gf(unsigned char *dest, gf a) +{ + dest[0] = a & 0xFF; + dest[1] = a >> 8; +} + +uint16_t load_gf(const unsigned char *src) +{ + uint16_t a; + + a = src[1]; + a <<= 8; + a |= src[0]; + + return a & GFMASK; +} + +uint32_t load4(const unsigned char * in) +{ + int i; + uint32_t ret = in[3]; + + for (i = 2; i >= 0; i--) + { + ret <<= 8; + ret |= in[i]; + } + + return ret; +} + +void store8(unsigned char *out, uint64_t in) +{ + out[0] = (in >> 0x00) & 0xFF; + out[1] = (in >> 0x08) & 0xFF; + out[2] = (in >> 0x10) & 0xFF; + out[3] = (in >> 0x18) & 0xFF; + out[4] = (in >> 0x20) & 0xFF; + out[5] = (in >> 0x28) & 0xFF; + out[6] = (in >> 0x30) & 0xFF; + out[7] = (in >> 0x38) & 0xFF; +} + +uint64_t load8(const unsigned char * in) +{ + int i; + uint64_t ret = in[7]; + + for (i = 6; i >= 0; i--) + { + ret <<= 8; + ret |= in[i]; + } + + return ret; +} + +gf bitrev(gf a) +{ + a = ((a & 0x00FF) << 8) | ((a & 0xFF00) >> 8); + a = ((a & 0x0F0F) << 4) | ((a & 0xF0F0) >> 4); + a = ((a & 0x3333) << 2) | ((a & 0xCCCC) >> 2); + a = ((a & 0x5555) << 1) | ((a & 0xAAAA) >> 1); + + return a >> 3; +} + diff --git a/deps/mceliece/kem/mceliece8192128/util.h b/deps/mceliece/kem/mceliece8192128/util.h new file mode 100644 index 0000000..d610bee --- /dev/null +++ b/deps/mceliece/kem/mceliece8192128/util.h @@ -0,0 +1,27 @@ +/* + This file is for loading/storing data in a little-endian fashion +*/ + +#ifndef UTIL_H +#define UTIL_H +#define bitrev CRYPTO_NAMESPACE(bitrev) +#define load4 CRYPTO_NAMESPACE(load4) +#define load8 CRYPTO_NAMESPACE(load8) +#define load_gf CRYPTO_NAMESPACE(load_gf) +#define store8 CRYPTO_NAMESPACE(store8) +#define store_gf CRYPTO_NAMESPACE(store_gf) + +#include "gf.h" +#include + +void store_gf(unsigned char *, gf); +uint16_t load_gf(const unsigned char *); +uint32_t load4(const unsigned char *); + +void store8(unsigned char *, uint64_t ); +uint64_t load8(const unsigned char *); + +gf bitrev(gf); + +#endif + diff --git a/deps/mceliece/kem/mceliece8192128f/benes.c b/deps/mceliece/kem/mceliece8192128f/benes.c new file mode 100644 index 0000000..3b4e710 --- /dev/null +++ b/deps/mceliece/kem/mceliece8192128f/benes.c @@ -0,0 +1,181 @@ +/* + This file is for Benes network related functions + + For the implementation strategy, see + https://eprint.iacr.org/2017/793.pdf +*/ + +#include "util.h" +#include "transpose.h" +#include "params.h" +#include "benes.h" + +/* middle layers of the benes network */ +static void layer_in(uint64_t data[2][64], uint64_t * bits, int lgs) +{ + int i, j, s; + + uint64_t d; + + s = 1 << lgs; + + for (i = 0; i < 64; i += s*2) + for (j = i; j < i+s; j++) + { + + d = (data[0][j+0] ^ data[0][j+s]); + d &= (*bits++); + data[0][j+0] ^= d; + data[0][j+s] ^= d; + + d = (data[1][j+0] ^ data[1][j+s]); + d &= (*bits++); + data[1][j+0] ^= d; + data[1][j+s] ^= d; + } +} + +/* first and last layers of the benes network */ +static void layer_ex(uint64_t * data, uint64_t * bits, int lgs) +{ + int i, j, s; + + uint64_t d; + + s = 1 << lgs; + + for (i = 0; i < 128; i += s*2) + for (j = i; j < i+s; j++) + { + + d = (data[j+0] ^ data[j+s]); + d &= (*bits++); + data[j+0] ^= d; + data[j+s] ^= d; + } +} + +/* input: r, sequence of bits to be permuted */ +/* bits, condition bits of the Benes network */ +/* rev, 0 for normal application; !0 for inverse */ +/* output: r, permuted bits */ +void apply_benes(unsigned char * r, const unsigned char * bits, int rev) +{ + int i, iter, inc; + + unsigned char *r_ptr = r; + const unsigned char *bits_ptr; + + uint64_t r_int_v[2][64]; + uint64_t r_int_h[2][64]; + uint64_t b_int_v[64]; + uint64_t b_int_h[64]; + + // + + if (rev) { bits_ptr = bits + 12288; inc = -1024; } + else { bits_ptr = bits; inc = 0; } + + for (i = 0; i < 64; i++) + { + r_int_v[0][i] = load8(r_ptr + i*16 + 0); + r_int_v[1][i] = load8(r_ptr + i*16 + 8); + } + + transpose_64x64(r_int_h[0], r_int_v[0]); + transpose_64x64(r_int_h[1], r_int_v[1]); + + for (iter = 0; iter <= 6; iter++) + { + for (i = 0; i < 64; i++) + { + b_int_v[i] = load8(bits_ptr); bits_ptr += 8; + } + + bits_ptr += inc; + + transpose_64x64(b_int_h, b_int_v); + + layer_ex(r_int_h[0], b_int_h, iter); + } + + transpose_64x64(r_int_v[0], r_int_h[0]); + transpose_64x64(r_int_v[1], r_int_h[1]); + + for (iter = 0; iter <= 5; iter++) + { + for (i = 0; i < 64; i++) { b_int_v[i] = load8(bits_ptr); bits_ptr += 8; } + bits_ptr += inc; + + layer_in(r_int_v, b_int_v, iter); + } + + for (iter = 4; iter >= 0; iter--) + { + for (i = 0; i < 64; i++) { b_int_v[i] = load8(bits_ptr); bits_ptr += 8; } + bits_ptr += inc; + + layer_in(r_int_v, b_int_v, iter); + } + + transpose_64x64(r_int_h[0], r_int_v[0]); + transpose_64x64(r_int_h[1], r_int_v[1]); + + for (iter = 6; iter >= 0; iter--) + { + for (i = 0; i < 64; i++) + { + b_int_v[i] = load8(bits_ptr); bits_ptr += 8; + } + + bits_ptr += inc; + + transpose_64x64(b_int_h, b_int_v); + + layer_ex(r_int_h[0], b_int_h, iter); + } + + transpose_64x64(r_int_v[0], r_int_h[0]); + transpose_64x64(r_int_v[1], r_int_h[1]); + + for (i = 0; i < 64; i++) + { + store8(r_ptr + i*16 + 0, r_int_v[0][i]); + store8(r_ptr + i*16 + 8, r_int_v[1][i]); + } +} + +/* input: condition bits c */ +/* output: support s */ +void support_gen(gf * s, const unsigned char *c) +{ + gf a; + int i, j; + unsigned char L[ GFBITS ][ (1 << GFBITS)/8 ]; + + for (i = 0; i < GFBITS; i++) + for (j = 0; j < (1 << GFBITS)/8; j++) + L[i][j] = 0; + + for (i = 0; i < (1 << GFBITS); i++) + { + a = bitrev((gf) i); + + for (j = 0; j < GFBITS; j++) + L[j][ i/8 ] |= ((a >> j) & 1) << (i%8); + } + + for (j = 0; j < GFBITS; j++) + apply_benes(L[j], c, 0); + + for (i = 0; i < SYS_N; i++) + { + s[i] = 0; + for (j = GFBITS-1; j >= 0; j--) + { + s[i] <<= 1; + s[i] |= (L[j][i/8] >> (i%8)) & 1; + } + } +} + diff --git a/deps/mceliece/kem/mceliece8192128f/benes.h b/deps/mceliece/kem/mceliece8192128f/benes.h new file mode 100644 index 0000000..c2ef35a --- /dev/null +++ b/deps/mceliece/kem/mceliece8192128f/benes.h @@ -0,0 +1,16 @@ +/* + This file is for Benes network related functions +*/ + +#ifndef BENES_H +#define BENES_H +#define apply_benes CRYPTO_NAMESPACE(apply_benes) +#define support_gen CRYPTO_NAMESPACE(support_gen) + +#include "gf.h" + +void apply_benes(unsigned char *, const unsigned char *, int); +void support_gen(gf *, const unsigned char *); + +#endif + diff --git a/deps/mceliece/kem/mceliece8192128f/bm.c b/deps/mceliece/kem/mceliece8192128f/bm.c new file mode 100644 index 0000000..056a734 --- /dev/null +++ b/deps/mceliece/kem/mceliece8192128f/bm.c @@ -0,0 +1,72 @@ +/* + This file is for the Berlekamp-Massey algorithm + see http://crypto.stanford.edu/~mironov/cs359/massey.pdf +*/ + +#include "params.h" +#include "gf.h" +#include "bm.h" + +#define min(a, b) ((a < b) ? a : b) + +/* the Berlekamp-Massey algorithm */ +/* input: s, sequence of field elements */ +/* output: out, minimal polynomial of s */ +void bm(gf *out, gf *s) +{ + int i; + + uint16_t N = 0; + uint16_t L = 0; + uint16_t mle; + uint16_t mne; + + gf T[ SYS_T+1 ]; + gf C[ SYS_T+1 ]; + gf B[ SYS_T+1 ]; + + gf b = 1, d, f; + + // + + for (i = 0; i < SYS_T+1; i++) + C[i] = B[i] = 0; + + B[1] = C[0] = 1; + + // + + for (N = 0; N < 2 * SYS_T; N++) + { + d = 0; + + for (i = 0; i <= min(N, SYS_T); i++) + d ^= gf_mul(C[i], s[ N-i]); + + mne = d; mne -= 1; mne >>= 15; mne -= 1; + mle = N; mle -= 2*L; mle >>= 15; mle -= 1; + mle &= mne; + + for (i = 0; i <= SYS_T; i++) + T[i] = C[i]; + + f = gf_frac(b, d); + + for (i = 0; i <= SYS_T; i++) + C[i] ^= gf_mul(f, B[i]) & mne; + + L = (L & ~mle) | ((N+1-L) & mle); + + for (i = 0; i <= SYS_T; i++) + B[i] = (B[i] & ~mle) | (T[i] & mle); + + b = (b & ~mle) | (d & mle); + + for (i = SYS_T; i >= 1; i--) B[i] = B[i-1]; + B[0] = 0; + } + + for (i = 0; i <= SYS_T; i++) + out[i] = C[ SYS_T-i ]; +} + diff --git a/deps/mceliece/kem/mceliece8192128f/bm.h b/deps/mceliece/kem/mceliece8192128f/bm.h new file mode 100644 index 0000000..73d5c6c --- /dev/null +++ b/deps/mceliece/kem/mceliece8192128f/bm.h @@ -0,0 +1,13 @@ +/* + This file is for the Berlekamp-Massey algorithm + see http://crypto.stanford.edu/~mironov/cs359/massey.pdf +*/ + +#ifndef BM_H +#define BM_H +#define bm CRYPTO_NAMESPACE(bm) + +void bm(gf *, gf *); + +#endif + diff --git a/deps/mceliece/kem/mceliece8192128f/controlbits.c b/deps/mceliece/kem/mceliece8192128f/controlbits.c new file mode 100644 index 0000000..db9db9c --- /dev/null +++ b/deps/mceliece/kem/mceliece8192128f/controlbits.c @@ -0,0 +1,220 @@ +/* This file is for implementing the Nassimi-Sahni algorithm */ +/* See David Nassimi, Sartaj Sahni "Parallel algorithms to set up the Benes permutationnetwork" */ +/* See also https://cr.yp.to/papers/controlbits-20200923.pdf */ + +#include +#include "crypto_declassify.h" +#include "controlbits.h" +#include "int32_sort.h" +typedef int16_t int16; +typedef int32_t int32; +#include "crypto_int32.h" +#define int32_min crypto_int32_min +#include "crypto_int16.h" + +/* parameters: 1 <= w <= 14; n = 2^w */ +/* input: permutation pi of {0,1,...,n-1} */ +/* output: (2m-1)n/2 control bits at positions pos,pos+step,... */ +/* output position pos is by definition 1&(out[pos/8]>>(pos&7)) */ +/* caller must 0-initialize positions first */ +/* temp must have space for int32[2*n] */ +static void cbrecursion(unsigned char *out,long long pos,long long step,const int16 *pi,long long w,long long n,int32 *temp) +{ +#define A temp +#define B (temp+n) +#define q ((int16 *) (temp+n+n/4)) +/* q can start anywhere between temp+n and temp+n/2 */ + + long long x,i,j,k; + + if (w == 1) { + out[pos>>3] ^= pi[0]<<(pos&7); + return; + } + + for (x = 0;x < n;++x) A[x] = ((pi[x]^1)<<16)|pi[x^1]; + int32_sort(A,n); /* A = (id<<16)+pibar */ + + for (x = 0;x < n;++x) { + int32 Ax = A[x]; + int32 px = Ax&0xffff; + int32 cx = int32_min(px,x); + B[x] = (px<<16)|cx; + } + /* B = (p<<16)+c */ + + for (x = 0;x < n;++x) A[x] = (A[x]<<16)|x; /* A = (pibar<<16)+id */ + int32_sort(A,n); /* A = (id<<16)+pibar^-1 */ + + for (x = 0;x < n;++x) A[x] = (A[x]<<16)+(B[x]>>16); /* A = (pibar^(-1)<<16)+pibar */ + int32_sort(A,n); /* A = (id<<16)+pibar^2 */ + + if (w <= 10) { + for (x = 0;x < n;++x) B[x] = ((A[x]&0xffff)<<10)|(B[x]&0x3ff); + + for (i = 1;i < w-1;++i) { + /* B = (p<<10)+c */ + + for (x = 0;x < n;++x) A[x] = ((B[x]&~0x3ff)<<6)|x; /* A = (p<<16)+id */ + int32_sort(A,n); /* A = (id<<16)+p^{-1} */ + + for (x = 0;x < n;++x) A[x] = (A[x]<<20)|B[x]; /* A = (p^{-1}<<20)+(p<<10)+c */ + int32_sort(A,n); /* A = (id<<20)+(pp<<10)+cp */ + + for (x = 0;x < n;++x) { + int32 ppcpx = A[x]&0xfffff; + int32 ppcx = (A[x]&0xffc00)|(B[x]&0x3ff); + B[x] = int32_min(ppcx,ppcpx); + } + } + for (x = 0;x < n;++x) B[x] &= 0x3ff; + } else { + for (x = 0;x < n;++x) B[x] = (A[x]<<16)|(B[x]&0xffff); + + for (i = 1;i < w-1;++i) { + /* B = (p<<16)+c */ + + for (x = 0;x < n;++x) A[x] = (B[x]&~0xffff)|x; + int32_sort(A,n); /* A = (id<<16)+p^(-1) */ + + for (x = 0;x < n;++x) A[x] = (A[x]<<16)|(B[x]&0xffff); + /* A = p^(-1)<<16+c */ + + if (i < w-2) { + for (x = 0;x < n;++x) B[x] = (A[x]&~0xffff)|(B[x]>>16); + /* B = (p^(-1)<<16)+p */ + int32_sort(B,n); /* B = (id<<16)+p^(-2) */ + for (x = 0;x < n;++x) B[x] = (B[x]<<16)|(A[x]&0xffff); + /* B = (p^(-2)<<16)+c */ + } + + int32_sort(A,n); + /* A = id<<16+cp */ + for (x = 0;x < n;++x) { + int32 cpx = (B[x]&~0xffff)|(A[x]&0xffff); + B[x] = int32_min(B[x],cpx); + } + } + for (x = 0;x < n;++x) B[x] &= 0xffff; + } + + for (x = 0;x < n;++x) A[x] = (((int32)pi[x])<<16)+x; + int32_sort(A,n); /* A = (id<<16)+pi^(-1) */ + + for (j = 0;j < n/2;++j) { + long long x = 2*j; + int32 fj = B[x]&1; /* f[j] */ + int32 Fx = x+fj; /* F[x] */ + int32 Fx1 = Fx^1; /* F[x+1] */ + + out[pos>>3] ^= fj<<(pos&7); + pos += step; + + B[x] = (A[x]<<16)|Fx; + B[x+1] = (A[x+1]<<16)|Fx1; + } + /* B = (pi^(-1)<<16)+F */ + + int32_sort(B,n); /* B = (id<<16)+F(pi) */ + + pos += (2*w-3)*step*(n/2); + + for (k = 0;k < n/2;++k) { + long long y = 2*k; + int32 lk = B[y]&1; /* l[k] */ + int32 Ly = y+lk; /* L[y] */ + int32 Ly1 = Ly^1; /* L[y+1] */ + + out[pos>>3] ^= lk<<(pos&7); + pos += step; + + A[y] = (Ly<<16)|(B[y]&0xffff); + A[y+1] = (Ly1<<16)|(B[y+1]&0xffff); + } + /* A = (L<<16)+F(pi) */ + + int32_sort(A,n); /* A = (id<<16)+F(pi(L)) = (id<<16)+M */ + + pos -= (2*w-2)*step*(n/2); + + for (j = 0;j < n/2;++j) { + q[j] = (A[2*j]&0xffff)>>1; + q[j+n/2] = (A[2*j+1]&0xffff)>>1; + } + + cbrecursion(out,pos,step*2,q,w-1,n/2,temp); + cbrecursion(out,pos+step,step*2,q+n/2,w-1,n/2,temp); +} + +/* input: p, an array of int16 */ +/* input: n, length of p */ +/* input: s, meaning that stride-2^s cswaps are performed */ +/* input: cb, the control bits */ +/* output: the result of apply the control bits to p */ +static void layer(int16_t *p, const unsigned char *cb, int s, int n) +{ + int i, j; + int stride = 1 << s; + int index = 0; + int16_t d, m; + + for (i = 0; i < n; i += stride*2) + { + for (j = 0; j < stride; j++) + { + d = p[ i+j ] ^ p[ i+j+stride ]; + m = (cb[ index >> 3 ] >> (index & 7)) & 1; + m = -m; + d &= m; + p[ i+j ] ^= d; + p[ i+j+stride ] ^= d; + index++; + } + } +} + +/* parameters: 1 <= w <= 14; n = 2^w */ +/* input: permutation pi of {0,1,...,n-1} */ +/* output: (2m-1)n/2 control bits at positions 0,1,... */ +/* output position pos is by definition 1&(out[pos/8]>>(pos&7)) */ +void controlbitsfrompermutation(unsigned char *out,const int16 *pi,long long w,long long n) +{ + int32 temp[2*n]; + int16 pi_test[n], diff; + int i; + unsigned char *ptr; + + while (1) + { + memset(out,0,(((2*w-1)*n/2)+7)/8); + cbrecursion(out,0,1,pi,w,n,temp); + + // check for correctness + + for (i = 0; i < n; i++) + pi_test[i] = i; + + ptr = out; + for (i = 0; i < w; i++) + { + layer(pi_test, ptr, i, n); + ptr += n >> 4; + } + + for (i = w-2; i >= 0; i--) + { + layer(pi_test, ptr, i, n); + ptr += n >> 4; + } + + diff = 0; + for (i = 0; i < n; i++) + diff |= pi[i] ^ pi_test[i]; + + diff = crypto_int16_nonzero_mask(diff); + crypto_declassify(&diff,sizeof diff); + if (diff == 0) + break; + } +} + diff --git a/deps/mceliece/kem/mceliece8192128f/controlbits.h b/deps/mceliece/kem/mceliece8192128f/controlbits.h new file mode 100644 index 0000000..8ddd210 --- /dev/null +++ b/deps/mceliece/kem/mceliece8192128f/controlbits.h @@ -0,0 +1,14 @@ +/* This file is for implementing the Nassimi-Sahni algorithm */ +/* See David Nassimi, Sartaj Sahni "Parallel algorithms to set up the Benes permutationnetwork" */ +/* See also https://cr.yp.to/papers/controlbits-20200923.pdf */ + +#ifndef CONTROLBITS_H +#define CONTROLBITS_H + +#define controlbitsfrompermutation CRYPTO_NAMESPACE(controlbitsfrompermutation) + +#include + +extern void controlbitsfrompermutation(unsigned char *,const int16_t *,long long,long long); + +#endif diff --git a/deps/mceliece/kem/mceliece8192128f/crypto_hash.h b/deps/mceliece/kem/mceliece8192128f/crypto_hash.h new file mode 100644 index 0000000..b7c1086 --- /dev/null +++ b/deps/mceliece/kem/mceliece8192128f/crypto_hash.h @@ -0,0 +1,10 @@ +/* This file uses SHAKE256 implemented in the Keccak Code Package */ + +#include "../../mceliece_externals.h" + +#define crypto_hash_32b(out,in,inlen) \ + SHAKE256(out,32,in,inlen) + +#define shake(out,outlen,in,inlen) \ + SHAKE256(out,outlen,in,inlen) + diff --git a/deps/mceliece/kem/mceliece8192128f/crypto_kem.h b/deps/mceliece/kem/mceliece8192128f/crypto_kem.h new file mode 100644 index 0000000..cc778fa --- /dev/null +++ b/deps/mceliece/kem/mceliece8192128f/crypto_kem.h @@ -0,0 +1,15 @@ +#ifndef crypto_kem_H +#define crypto_kem_H + +#include "crypto_kem_mceliece8192128f.h" + +#define crypto_kem_keypair crypto_kem_mceliece8192128f_keypair +#define crypto_kem_enc crypto_kem_mceliece8192128f_enc +#define crypto_kem_dec crypto_kem_mceliece8192128f_dec +#define crypto_kem_PUBLICKEYBYTES crypto_kem_mceliece8192128f_PUBLICKEYBYTES +#define crypto_kem_SECRETKEYBYTES crypto_kem_mceliece8192128f_SECRETKEYBYTES +#define crypto_kem_BYTES crypto_kem_mceliece8192128f_BYTES +#define crypto_kem_CIPHERTEXTBYTES crypto_kem_mceliece8192128f_CIPHERTEXTBYTES +#define crypto_kem_PRIMITIVE "mceliece8192128f" + +#endif diff --git a/deps/mceliece/kem/mceliece8192128f/crypto_kem_mceliece8192128f.h b/deps/mceliece/kem/mceliece8192128f/crypto_kem_mceliece8192128f.h new file mode 100644 index 0000000..0f3d4f2 --- /dev/null +++ b/deps/mceliece/kem/mceliece8192128f/crypto_kem_mceliece8192128f.h @@ -0,0 +1,27 @@ +#ifndef crypto_kem_mceliece8192128f_H +#define crypto_kem_mceliece8192128f_H + +#define crypto_kem_mceliece8192128f_ref_PUBLICKEYBYTES 1357824 +#define crypto_kem_mceliece8192128f_ref_SECRETKEYBYTES 14120 +#define crypto_kem_mceliece8192128f_ref_CIPHERTEXTBYTES 208 +#define crypto_kem_mceliece8192128f_ref_BYTES 32 + +#ifdef __cplusplus +extern "C" { +#endif +extern int crypto_kem_mceliece8192128f_ref_keypair(unsigned char *,unsigned char *); +extern int crypto_kem_mceliece8192128f_ref_enc(unsigned char *,unsigned char *,const unsigned char *); +extern int crypto_kem_mceliece8192128f_ref_dec(unsigned char *,const unsigned char *,const unsigned char *); +#ifdef __cplusplus +} +#endif + +#define crypto_kem_mceliece8192128f_keypair crypto_kem_mceliece8192128f_ref_keypair +#define crypto_kem_mceliece8192128f_enc crypto_kem_mceliece8192128f_ref_enc +#define crypto_kem_mceliece8192128f_dec crypto_kem_mceliece8192128f_ref_dec +#define crypto_kem_mceliece8192128f_PUBLICKEYBYTES crypto_kem_mceliece8192128f_ref_PUBLICKEYBYTES +#define crypto_kem_mceliece8192128f_SECRETKEYBYTES crypto_kem_mceliece8192128f_ref_SECRETKEYBYTES +#define crypto_kem_mceliece8192128f_BYTES crypto_kem_mceliece8192128f_ref_BYTES +#define crypto_kem_mceliece8192128f_CIPHERTEXTBYTES crypto_kem_mceliece8192128f_ref_CIPHERTEXTBYTES + +#endif diff --git a/deps/mceliece/kem/mceliece8192128f/decrypt.c b/deps/mceliece/kem/mceliece8192128f/decrypt.c new file mode 100644 index 0000000..c4cc6de --- /dev/null +++ b/deps/mceliece/kem/mceliece8192128f/decrypt.c @@ -0,0 +1,93 @@ +/* + This file is for Niederreiter decryption +*/ + +#include +#include "decrypt.h" + +#include "params.h" +#include "benes.h" +#include "util.h" +#include "synd.h" +#include "root.h" +#include "gf.h" +#include "bm.h" + +/* Niederreiter decryption with the Berlekamp decoder */ +/* intput: sk, secret key */ +/* c, ciphertext */ +/* output: e, error vector */ +/* return: 0 for success; 1 for failure */ +int decrypt(unsigned char *e, const unsigned char *sk, const unsigned char *c) +{ + int i, w = 0; + uint16_t check; + + unsigned char r[ SYS_N/8 ]; + + gf g[ SYS_T+1 ]; + gf L[ SYS_N ]; + + gf s[ SYS_T*2 ]; + gf s_cmp[ SYS_T*2 ]; + gf locator[ SYS_T+1 ]; + gf images[ SYS_N ]; + + gf t; + + // + + for (i = 0; i < SYND_BYTES; i++) r[i] = c[i]; + for (i = SYND_BYTES; i < SYS_N/8; i++) r[i] = 0; + + for (i = 0; i < SYS_T; i++) { g[i] = load_gf(sk); sk += 2; } g[ SYS_T ] = 1; + + support_gen(L, sk); + + synd(s, g, L, r); + + bm(locator, s); + + root(images, locator, L); + + // + + for (i = 0; i < SYS_N/8; i++) + e[i] = 0; + + for (i = 0; i < SYS_N; i++) + { + t = gf_iszero(images[i]) & 1; + + e[ i/8 ] |= t << (i%8); + w += t; + + } + +#ifdef KAT + { + int k; + printf("decrypt e: positions"); + for (k = 0;k < SYS_N;++k) + if (e[k/8] & (1 << (k&7))) + printf(" %d",k); + printf("\n"); + } +#endif + + synd(s_cmp, g, L, e); + + // + + check = w; + check ^= SYS_T; + + for (i = 0; i < SYS_T*2; i++) + check |= s[i] ^ s_cmp[i]; + + check -= 1; + check >>= 15; + + return check ^ 1; +} + diff --git a/deps/mceliece/kem/mceliece8192128f/decrypt.h b/deps/mceliece/kem/mceliece8192128f/decrypt.h new file mode 100644 index 0000000..266a5cd --- /dev/null +++ b/deps/mceliece/kem/mceliece8192128f/decrypt.h @@ -0,0 +1,12 @@ +/* + This file is for Nieddereiter decryption +*/ + +#ifndef DECRYPT_H +#define DECRYPT_H +#define decrypt CRYPTO_NAMESPACE(decrypt) + +int decrypt(unsigned char *, const unsigned char *, const unsigned char *); + +#endif + diff --git a/deps/mceliece/kem/mceliece8192128f/encrypt.c b/deps/mceliece/kem/mceliece8192128f/encrypt.c new file mode 100644 index 0000000..997854f --- /dev/null +++ b/deps/mceliece/kem/mceliece8192128f/encrypt.c @@ -0,0 +1,139 @@ +/* + This file is for Niederreiter encryption +*/ + +#include "encrypt.h" + +#include "util.h" +#include "params.h" +#include "randombytes.h" + +#include +#include +#include +#include + +#include "gf.h" +#include "crypto_declassify.h" +#include "crypto_uint32.h" + +static inline crypto_uint32 uint32_is_equal_declassify(uint32_t t,uint32_t u) +{ + crypto_uint32 mask = crypto_uint32_equal_mask(t,u); + crypto_declassify(&mask,sizeof mask); + return mask; +} + +static inline unsigned char same_mask(uint16_t x, uint16_t y) +{ + uint32_t mask; + + mask = x ^ y; + mask -= 1; + mask >>= 31; + mask = -mask; + + return mask & 0xFF; +} + +/* output: e, an error vector of weight t */ +static void gen_e(unsigned char *e) +{ + int i, j, eq; + + uint16_t ind[ SYS_T ]; + unsigned char bytes[ sizeof(ind) ]; + unsigned char mask; + unsigned char val[ SYS_T ]; + + while (1) + { + randombytes(bytes, sizeof(bytes)); + + for (i = 0; i < SYS_T; i++) + ind[i] = load_gf(bytes + i*2); + + // check for repetition + + eq = 0; + + for (i = 1; i < SYS_T; i++) + for (j = 0; j < i; j++) + if (uint32_is_equal_declassify(ind[i],ind[j])) + eq = 1; + + if (eq == 0) + break; + } + + for (j = 0; j < SYS_T; j++) + val[j] = 1 << (ind[j] & 7); + + for (i = 0; i < SYS_N/8; i++) + { + e[i] = 0; + + for (j = 0; j < SYS_T; j++) + { + mask = same_mask(i, (ind[j] >> 3)); + + e[i] |= val[j] & mask; + } + } +} + +/* input: public key pk, error vector e */ +/* output: syndrome s */ +static void syndrome(unsigned char *s, const unsigned char *pk, unsigned char *e) +{ + unsigned char b, row[SYS_N/8]; + const unsigned char *pk_ptr = pk; + + int i, j; + + for (i = 0; i < SYND_BYTES; i++) + s[i] = 0; + + for (i = 0; i < PK_NROWS; i++) + { + for (j = 0; j < SYS_N/8; j++) + row[j] = 0; + + for (j = 0; j < PK_ROW_BYTES; j++) + row[ SYS_N/8 - PK_ROW_BYTES + j ] = pk_ptr[j]; + + row[i/8] |= 1 << (i%8); + + b = 0; + for (j = 0; j < SYS_N/8; j++) + b ^= row[j] & e[j]; + + b ^= b >> 4; + b ^= b >> 2; + b ^= b >> 1; + b &= 1; + + s[ i/8 ] |= (b << (i%8)); + + pk_ptr += PK_ROW_BYTES; + } +} + +void encrypt(unsigned char *s, const unsigned char *pk, unsigned char *e) +{ + gen_e(e); + +#ifdef KAT + { + int k; + printf("encrypt e: positions"); + for (k = 0;k < SYS_N;++k) + if (e[k/8] & (1 << (k&7))) + printf(" %d",k); + printf("\n"); + } +#endif + + syndrome(s, pk, e); +} + diff --git a/deps/mceliece/kem/mceliece8192128f/encrypt.h b/deps/mceliece/kem/mceliece8192128f/encrypt.h new file mode 100644 index 0000000..8edd7a6 --- /dev/null +++ b/deps/mceliece/kem/mceliece8192128f/encrypt.h @@ -0,0 +1,12 @@ +/* + This file is for Niederreiter encryption +*/ + +#ifndef ENCRYPT_H +#define ENCRYPT_H +#define encrypt CRYPTO_NAMESPACE(encrypt) + +void encrypt(unsigned char *, const unsigned char *, unsigned char *); + +#endif + diff --git a/deps/mceliece/kem/mceliece8192128f/gf.c b/deps/mceliece/kem/mceliece8192128f/gf.c new file mode 100644 index 0000000..159a286 --- /dev/null +++ b/deps/mceliece/kem/mceliece8192128f/gf.c @@ -0,0 +1,215 @@ +/* + This file is for functions for field arithmetic +*/ + +#include "gf.h" + +#include "params.h" + +gf gf_iszero(gf a) +{ + uint32_t t = a; + + t -= 1; + t >>= 19; + + return (gf) t; +} + +gf gf_add(gf in0, gf in1) +{ + return in0 ^ in1; +} + +gf gf_mul(gf in0, gf in1) +{ + int i; + + uint64_t tmp; + uint64_t t0; + uint64_t t1; + uint64_t t; + + t0 = in0; + t1 = in1; + + tmp = t0 * (t1 & 1); + + for (i = 1; i < GFBITS; i++) + tmp ^= (t0 * (t1 & (1 << i))); + + // + + t = tmp & 0x1FF0000; + tmp ^= (t >> 9) ^ (t >> 10) ^ (t >> 12) ^ (t >> 13); + + t = tmp & 0x000E000; + tmp ^= (t >> 9) ^ (t >> 10) ^ (t >> 12) ^ (t >> 13); + + return tmp & GFMASK; +} + +/* input: field element in */ +/* return: (in^2)^2 */ +static inline gf gf_sq2(gf in) +{ + int i; + + const uint64_t B[] = {0x1111111111111111, + 0x0303030303030303, + 0x000F000F000F000F, + 0x000000FF000000FF}; + + const uint64_t M[] = {0x0001FF0000000000, + 0x000000FF80000000, + 0x000000007FC00000, + 0x00000000003FE000}; + + uint64_t x = in; + uint64_t t; + + x = (x | (x << 24)) & B[3]; + x = (x | (x << 12)) & B[2]; + x = (x | (x << 6)) & B[1]; + x = (x | (x << 3)) & B[0]; + + for (i = 0; i < 4; i++) + { + t = x & M[i]; + x ^= (t >> 9) ^ (t >> 10) ^ (t >> 12) ^ (t >> 13); + } + + return x & GFMASK; +} + +/* input: field element in, m */ +/* return: (in^2)*m */ +static inline gf gf_sqmul(gf in, gf m) +{ + int i; + + uint64_t x; + uint64_t t0; + uint64_t t1; + uint64_t t; + + const uint64_t M[] = {0x0000001FF0000000, + 0x000000000FF80000, + 0x000000000007E000}; + + t0 = in; + t1 = m; + + x = (t1 << 6) * (t0 & (1 << 6)); + + t0 ^= (t0 << 7); + + x ^= (t1 * (t0 & (0x04001))); + x ^= (t1 * (t0 & (0x08002))) << 1; + x ^= (t1 * (t0 & (0x10004))) << 2; + x ^= (t1 * (t0 & (0x20008))) << 3; + x ^= (t1 * (t0 & (0x40010))) << 4; + x ^= (t1 * (t0 & (0x80020))) << 5; + + for (i = 0; i < 3; i++) + { + t = x & M[i]; + x ^= (t >> 9) ^ (t >> 10) ^ (t >> 12) ^ (t >> 13); + } + + return x & GFMASK; +} + +/* input: field element in, m */ +/* return: ((in^2)^2)*m */ +static inline gf gf_sq2mul(gf in, gf m) +{ + int i; + + uint64_t x; + uint64_t t0; + uint64_t t1; + uint64_t t; + + const uint64_t M[] = {0x1FF0000000000000, + 0x000FF80000000000, + 0x000007FC00000000, + 0x00000003FE000000, + 0x0000000001FE0000, + 0x000000000001E000}; + + t0 = in; + t1 = m; + + x = (t1 << 18) * (t0 & (1 << 6)); + + t0 ^= (t0 << 21); + + x ^= (t1 * (t0 & (0x010000001))); + x ^= (t1 * (t0 & (0x020000002))) << 3; + x ^= (t1 * (t0 & (0x040000004))) << 6; + x ^= (t1 * (t0 & (0x080000008))) << 9; + x ^= (t1 * (t0 & (0x100000010))) << 12; + x ^= (t1 * (t0 & (0x200000020))) << 15; + + for (i = 0; i < 6; i++) + { + t = x & M[i]; + x ^= (t >> 9) ^ (t >> 10) ^ (t >> 12) ^ (t >> 13); + } + + return x & GFMASK; +} + +/* input: field element den, num */ +/* return: (num/den) */ +gf gf_frac(gf den, gf num) +{ + gf tmp_11; + gf tmp_1111; + gf out; + + tmp_11 = gf_sqmul(den, den); // ^11 + tmp_1111 = gf_sq2mul(tmp_11, tmp_11); // ^1111 + out = gf_sq2(tmp_1111); + out = gf_sq2mul(out, tmp_1111); // ^11111111 + out = gf_sq2(out); + out = gf_sq2mul(out, tmp_1111); // ^111111111111 + + return gf_sqmul(out, num); // ^1111111111110 = ^-1 +} + +gf gf_inv(gf den) +{ + return gf_frac(den, ((gf) 1)); +} + +/* input: in0, in1 in GF((2^m)^t)*/ +/* output: out = in0*in1 */ +void GF_mul(gf *out, gf *in0, gf *in1) +{ + int i, j; + + gf prod[ SYS_T*2-1 ]; + + for (i = 0; i < SYS_T*2-1; i++) + prod[i] = 0; + + for (i = 0; i < SYS_T; i++) + for (j = 0; j < SYS_T; j++) + prod[i+j] ^= gf_mul(in0[i], in1[j]); + + // + + for (i = (SYS_T-1)*2; i >= SYS_T; i--) + { + prod[i - SYS_T + 7] ^= prod[i]; + prod[i - SYS_T + 2] ^= prod[i]; + prod[i - SYS_T + 1] ^= prod[i]; + prod[i - SYS_T + 0] ^= prod[i]; + } + + for (i = 0; i < SYS_T; i++) + out[i] = prod[i]; +} + diff --git a/deps/mceliece/kem/mceliece8192128f/gf.h b/deps/mceliece/kem/mceliece8192128f/gf.h new file mode 100644 index 0000000..f62209d --- /dev/null +++ b/deps/mceliece/kem/mceliece8192128f/gf.h @@ -0,0 +1,27 @@ +/* + This file is for functions for field arithmetic +*/ + +#ifndef GF_H +#define GF_H +#define gf_add CRYPTO_NAMESPACE(gf_add) +#define gf_frac CRYPTO_NAMESPACE(gf_frac) +#define gf_inv CRYPTO_NAMESPACE(gf_inv) +#define gf_iszero CRYPTO_NAMESPACE(gf_iszero) +#define gf_mul CRYPTO_NAMESPACE(gf_mul) +#define GF_mul CRYPTO_NAMESPACE(GF_mul) + +#include + +typedef uint16_t gf; + +gf gf_iszero(gf); +gf gf_add(gf, gf); +gf gf_mul(gf, gf); +gf gf_frac(gf, gf); +gf gf_inv(gf); + +void GF_mul(gf *, gf *, gf *); + +#endif + diff --git a/deps/mceliece/kem/mceliece8192128f/int32_sort.h b/deps/mceliece/kem/mceliece8192128f/int32_sort.h new file mode 100644 index 0000000..a431af2 --- /dev/null +++ b/deps/mceliece/kem/mceliece8192128f/int32_sort.h @@ -0,0 +1,46 @@ +#ifndef int32_sort_h +#define int32_sort_h + +#define int32_sort CRYPTO_NAMESPACE(int32_sort) + +#include + +#define int32_MINMAX(a,b) \ +do { \ + int32_t ab = b ^ a; \ + int32_t c = b - a; \ + c ^= ab & (c ^ b); \ + c >>= 31; \ + c &= ab; \ + a ^= c; \ + b ^= c; \ +} while(0) + +static void int32_sort(int32_t *x,long long n) +{ + long long top,p,q,r,i; + + if (n < 2) return; + top = 1; + while (top < n - top) top += top; + + for (p = top;p > 0;p >>= 1) { + for (i = 0;i < n - p;++i) + if (!(i & p)) + int32_MINMAX(x[i],x[i+p]); + i = 0; + for (q = top;q > p;q >>= 1) { + for (;i < n - q;++i) { + if (!(i & p)) { + int32_t a = x[i + p]; + for (r = q;r > p;r >>= 1) + int32_MINMAX(a,x[i+r]); + x[i + p] = a; + } + } + } + } +} + +#endif + diff --git a/deps/mceliece/kem/mceliece8192128f/operations.c b/deps/mceliece/kem/mceliece8192128f/operations.c new file mode 100644 index 0000000..bb605b1 --- /dev/null +++ b/deps/mceliece/kem/mceliece8192128f/operations.c @@ -0,0 +1,147 @@ +#include "operations.h" + +#include "controlbits.h" +#include "randombytes.h" +#include "crypto_hash.h" +#include "encrypt.h" +#include "decrypt.h" +#include "params.h" +#include "sk_gen.h" +#include "pk_gen.h" +#include "util.h" + +#include +#include + +int crypto_kem_enc( + unsigned char *c, + unsigned char *key, + const unsigned char *pk +) +{ + unsigned char e[ SYS_N/8 ]; + unsigned char one_ec[ 1 + SYS_N/8 + SYND_BYTES ] = {1}; + + // + + encrypt(c, pk, e); + + memcpy(one_ec + 1, e, SYS_N/8); + memcpy(one_ec + 1 + SYS_N/8, c, SYND_BYTES); + + crypto_hash_32b(key, one_ec, sizeof(one_ec)); + + return 0; +} + +int crypto_kem_dec( + unsigned char *key, + const unsigned char *c, + const unsigned char *sk +) +{ + int i; + + unsigned char ret_decrypt = 0; + + uint16_t m; + + unsigned char e[ SYS_N/8 ]; + unsigned char preimage[ 1 + SYS_N/8 + SYND_BYTES ]; + unsigned char *x = preimage; + const unsigned char *s = sk + 40 + IRR_BYTES + COND_BYTES; + + // + + ret_decrypt = decrypt(e, sk + 40, c); + + m = ret_decrypt; + m -= 1; + m >>= 8; + + *x++ = m & 1; + for (i = 0; i < SYS_N/8; i++) + *x++ = (~m & s[i]) | (m & e[i]); + + for (i = 0; i < SYND_BYTES; i++) + *x++ = c[i]; + + crypto_hash_32b(key, preimage, sizeof(preimage)); + + return 0; +} + +int crypto_kem_keypair +( + unsigned char *pk, + unsigned char *sk +) +{ + int i; + unsigned char seed[ 33 ] = {64}; + unsigned char r[ SYS_N/8 + (1 << GFBITS)*sizeof(uint32_t) + SYS_T*2 + 32 ]; + unsigned char *rp, *skp; + uint64_t pivots; + + gf f[ SYS_T ]; // element in GF(2^mt) + gf irr[ SYS_T ]; // Goppa polynomial + uint32_t perm[ 1 << GFBITS ]; // random permutation as 32-bit integers + int16_t pi[ 1 << GFBITS ]; // random permutation + + randombytes(seed+1, 32); + + while (1) + { + rp = &r[ sizeof(r)-32 ]; + skp = sk; + + // expanding and updating the seed + + shake(r, sizeof(r), seed, 33); + memcpy(skp, seed+1, 32); + skp += 32 + 8; + memcpy(seed+1, &r[ sizeof(r)-32 ], 32); + + // generating irreducible polynomial + + rp -= sizeof(f); + + for (i = 0; i < SYS_T; i++) + f[i] = load_gf(rp + i*2); + + if (genpoly_gen(irr, f)) + continue; + + for (i = 0; i < SYS_T; i++) + store_gf(skp + i*2, irr[i]); + + skp += IRR_BYTES; + + // generating permutation + + rp -= sizeof(perm); + + for (i = 0; i < (1 << GFBITS); i++) + perm[i] = load4(rp + i*4); + + if (pk_gen(pk, skp - IRR_BYTES, perm, pi, &pivots)) + continue; + + controlbitsfrompermutation(skp, pi, GFBITS, 1 << GFBITS); + skp += COND_BYTES; + + // storing the random string s + + rp -= SYS_N/8; + memcpy(skp, rp, SYS_N/8); + + // storing positions of the 32 pivots + + store8(sk + 32, pivots); + + break; + } + + return 0; +} + diff --git a/deps/mceliece/kem/mceliece8192128f/operations.h b/deps/mceliece/kem/mceliece8192128f/operations.h new file mode 100644 index 0000000..bf65502 --- /dev/null +++ b/deps/mceliece/kem/mceliece8192128f/operations.h @@ -0,0 +1,25 @@ +#ifndef OPERATIONS_H +#define OPERATIONS_H + +#include "crypto_kem.h" + +int crypto_kem_enc( + unsigned char *c, + unsigned char *key, + const unsigned char *pk +); + +int crypto_kem_dec( + unsigned char *key, + const unsigned char *c, + const unsigned char *sk +); + +int crypto_kem_keypair +( + unsigned char *pk, + unsigned char *sk +); + +#endif + diff --git a/deps/mceliece/kem/mceliece8192128f/params.h b/deps/mceliece/kem/mceliece8192128f/params.h new file mode 100644 index 0000000..85d379d --- /dev/null +++ b/deps/mceliece/kem/mceliece8192128f/params.h @@ -0,0 +1,20 @@ +#ifndef PARAMS_H +#define PARAMS_H + +#define GFBITS 13 +#define SYS_N 8192 +#define SYS_T 128 + +#define COND_BYTES ((1 << (GFBITS-4))*(2*GFBITS - 1)) +#define IRR_BYTES (SYS_T * 2) + +#define PK_NROWS (SYS_T*GFBITS) +#define PK_NCOLS (SYS_N - PK_NROWS) +#define PK_ROW_BYTES ((PK_NCOLS + 7)/8) + +#define SYND_BYTES ((PK_NROWS + 7)/8) + +#define GFMASK ((1 << GFBITS) - 1) + +#endif + diff --git a/deps/mceliece/kem/mceliece8192128f/pk_gen.c b/deps/mceliece/kem/mceliece8192128f/pk_gen.c new file mode 100644 index 0000000..82039a5 --- /dev/null +++ b/deps/mceliece/kem/mceliece8192128f/pk_gen.c @@ -0,0 +1,252 @@ +/* + This file is for public-key generation +*/ + +#include +#include +#include +#include + +#include "controlbits.h" +#include "uint64_sort.h" +#include "pk_gen.h" +#include "params.h" +#include "benes.h" +#include "root.h" +#include "util.h" +#include "crypto_declassify.h" +#include "crypto_uint64.h" + +static crypto_uint64 uint64_is_equal_declassify(uint64_t t,uint64_t u) +{ + crypto_uint64 mask = crypto_uint64_equal_mask(t,u); + crypto_declassify(&mask,sizeof mask); + return mask; +} + +static crypto_uint64 uint64_is_zero_declassify(uint64_t t) +{ + crypto_uint64 mask = crypto_uint64_zero_mask(t); + crypto_declassify(&mask,sizeof mask); + return mask; +} + +#define min(a, b) ((a < b) ? a : b) + +/* return number of trailing zeros of the non-zero input in */ +static inline int ctz(uint64_t in) +{ + int i, b, m = 0, r = 0; + + for (i = 0; i < 64; i++) + { + b = (in >> i) & 1; + m |= b; + r += (m^1) & (b^1); + } + + return r; +} + +static inline uint64_t same_mask(uint16_t x, uint16_t y) +{ + uint64_t mask; + + mask = x ^ y; + mask -= 1; + mask >>= 63; + mask = -mask; + + return mask; +} + +static int mov_columns(uint8_t mat[][ SYS_N/8 ], int16_t * pi, uint64_t * pivots) +{ + int i, j, k, s, block_idx, row; + uint64_t buf[64], ctz_list[32], t, d, mask, one = 1; + + row = PK_NROWS - 32; + block_idx = row/8; + + // extract the 32x64 matrix + + for (i = 0; i < 32; i++) + buf[i] = load8( &mat[ row + i ][ block_idx ] ); + + // compute the column indices of pivots by Gaussian elimination. + // the indices are stored in ctz_list + + *pivots = 0; + + for (i = 0; i < 32; i++) + { + t = buf[i]; + for (j = i+1; j < 32; j++) + t |= buf[j]; + + if (uint64_is_zero_declassify(t)) return -1; // return if buf is not full rank + + ctz_list[i] = s = ctz(t); + *pivots |= one << s; + + for (j = i+1; j < 32; j++) { mask = (buf[i] >> s) & 1; mask -= 1; buf[i] ^= buf[j] & mask; } + for (j = i+1; j < 32; j++) { mask = (buf[j] >> s) & 1; mask = -mask; buf[j] ^= buf[i] & mask; } + } + + // updating permutation + + for (j = 0; j < 32; j++) + for (k = j+1; k < 64; k++) + { + d = pi[ row + j ] ^ pi[ row + k ]; + d &= same_mask(k, ctz_list[j]); + pi[ row + j ] ^= d; + pi[ row + k ] ^= d; + } + + // moving columns of mat according to the column indices of pivots + + for (i = 0; i < PK_NROWS; i++) + { + t = load8( &mat[ i ][ block_idx ] ); + + for (j = 0; j < 32; j++) + { + d = t >> j; + d ^= t >> ctz_list[j]; + d &= 1; + + t ^= d << ctz_list[j]; + t ^= d << j; + } + + store8( &mat[ i ][ block_idx ], t ); + } + + return 0; +} + +/* input: secret key sk */ +/* output: public key pk */ +int pk_gen(unsigned char * pk, unsigned char * sk, uint32_t * perm, int16_t * pi, uint64_t * pivots) +{ + int i, j, k; + int row, c; + + uint64_t buf[ 1 << GFBITS ]; + + unsigned char mat[ PK_NROWS ][ SYS_N/8 ]; + unsigned char mask; + unsigned char b; + + gf g[ SYS_T+1 ]; // Goppa polynomial + gf L[ SYS_N ]; // support + gf inv[ SYS_N ]; + + // + + g[ SYS_T ] = 1; + + for (i = 0; i < SYS_T; i++) { g[i] = load_gf(sk); sk += 2; } + + for (i = 0; i < (1 << GFBITS); i++) + { + buf[i] = perm[i]; + buf[i] <<= 31; + buf[i] |= i; + } + + uint64_sort(buf, 1 << GFBITS); + + for (i = 1; i < (1 << GFBITS); i++) + if (uint64_is_equal_declassify(buf[i-1] >> 31,buf[i] >> 31)) + return -1; + + for (i = 0; i < (1 << GFBITS); i++) pi[i] = buf[i] & GFMASK; + for (i = 0; i < SYS_N; i++) L[i] = bitrev(pi[i]); + + // filling the matrix + + root(inv, g, L); + + for (i = 0; i < SYS_N; i++) + inv[i] = gf_inv(inv[i]); + + for (i = 0; i < PK_NROWS; i++) + for (j = 0; j < SYS_N/8; j++) + mat[i][j] = 0; + + for (i = 0; i < SYS_T; i++) + { + for (j = 0; j < SYS_N; j+=8) + for (k = 0; k < GFBITS; k++) + { + b = (inv[j+7] >> k) & 1; b <<= 1; + b |= (inv[j+6] >> k) & 1; b <<= 1; + b |= (inv[j+5] >> k) & 1; b <<= 1; + b |= (inv[j+4] >> k) & 1; b <<= 1; + b |= (inv[j+3] >> k) & 1; b <<= 1; + b |= (inv[j+2] >> k) & 1; b <<= 1; + b |= (inv[j+1] >> k) & 1; b <<= 1; + b |= (inv[j+0] >> k) & 1; + + mat[ i*GFBITS + k ][ j/8 ] = b; + } + + for (j = 0; j < SYS_N; j++) + inv[j] = gf_mul(inv[j], L[j]); + + } + + // gaussian elimination + + for (i = 0; i < (PK_NROWS + 7) / 8; i++) + for (j = 0; j < 8; j++) + { + row = i*8 + j; + + if (row >= PK_NROWS) + break; + + if (row == PK_NROWS - 32) + { + if (mov_columns(mat, pi, pivots)) + return -1; + } + + for (k = row + 1; k < PK_NROWS; k++) + { + mask = mat[ row ][ i ] ^ mat[ k ][ i ]; + mask >>= j; + mask &= 1; + mask = -mask; + + for (c = 0; c < SYS_N/8; c++) + mat[ row ][ c ] ^= mat[ k ][ c ] & mask; + } + + if ( uint64_is_zero_declassify((mat[ row ][ i ] >> j) & 1) ) // return if not systematic + { + return -1; + } + + for (k = 0; k < PK_NROWS; k++) + { + if (k != row) + { + mask = mat[ k ][ i ] >> j; + mask &= 1; + mask = -mask; + + for (c = 0; c < SYS_N/8; c++) + mat[ k ][ c ] ^= mat[ row ][ c ] & mask; + } + } + } + + for (i = 0; i < PK_NROWS; i++) + memcpy(pk + i*PK_ROW_BYTES, mat[i] + PK_NROWS/8, PK_ROW_BYTES); + + return 0; +} + diff --git a/deps/mceliece/kem/mceliece8192128f/pk_gen.h b/deps/mceliece/kem/mceliece8192128f/pk_gen.h new file mode 100644 index 0000000..96b7e7b --- /dev/null +++ b/deps/mceliece/kem/mceliece8192128f/pk_gen.h @@ -0,0 +1,14 @@ +/* + This file is for public-key generation +*/ + +#ifndef PK_GEN_H +#define PK_GEN_H +#define pk_gen CRYPTO_NAMESPACE(pk_gen) + +#include "gf.h" + +int pk_gen(unsigned char *, unsigned char *, uint32_t *, int16_t *, uint64_t *); + +#endif + diff --git a/deps/mceliece/kem/mceliece8192128f/randombytes.h b/deps/mceliece/kem/mceliece8192128f/randombytes.h new file mode 100644 index 0000000..7e59351 --- /dev/null +++ b/deps/mceliece/kem/mceliece8192128f/randombytes.h @@ -0,0 +1 @@ +#include "../../mceliece_externals.h" diff --git a/deps/mceliece/kem/mceliece8192128f/root.c b/deps/mceliece/kem/mceliece8192128f/root.c new file mode 100644 index 0000000..1c1b634 --- /dev/null +++ b/deps/mceliece/kem/mceliece8192128f/root.c @@ -0,0 +1,38 @@ +/* + This file is for evaluating a polynomial at one or more field elements +*/ + +#include "root.h" +#include "params.h" +#include "gf.h" + +#include + +/* input: polynomial f and field element a */ +/* return f(a) */ +gf eval(gf *f, gf a) +{ + int i; + gf r; + + r = f[ SYS_T ]; + + for (i = SYS_T-1; i >= 0; i--) + { + r = gf_mul(r, a); + r = gf_add(r, f[i]); + } + + return r; +} + +/* input: polynomial f and list of field elements L */ +/* output: out = [ f(a) for a in L ] */ +void root(gf *out, gf *f, gf *L) +{ + int i; + + for (i = 0; i < SYS_N; i++) + out[i] = eval(f, L[i]); +} + diff --git a/deps/mceliece/kem/mceliece8192128f/root.h b/deps/mceliece/kem/mceliece8192128f/root.h new file mode 100644 index 0000000..42516e4 --- /dev/null +++ b/deps/mceliece/kem/mceliece8192128f/root.h @@ -0,0 +1,16 @@ +/* + This file is for evaluating a polynomial at one or more field elements +*/ + +#ifndef ROOT_H +#define ROOT_H +#define eval CRYPTO_NAMESPACE(eval) +#define root CRYPTO_NAMESPACE(root) + +#include "gf.h" + +gf eval(gf *, gf); +void root(gf *, gf *, gf *); + +#endif + diff --git a/deps/mceliece/kem/mceliece8192128f/sk_gen.c b/deps/mceliece/kem/mceliece8192128f/sk_gen.c new file mode 100644 index 0000000..340cc9a --- /dev/null +++ b/deps/mceliece/kem/mceliece8192128f/sk_gen.c @@ -0,0 +1,85 @@ +/* + This file is for secret-key generation +*/ + +#include "sk_gen.h" + +#include "randombytes.h" +#include "controlbits.h" +#include "params.h" +#include "util.h" +#include "gf.h" +#include "crypto_declassify.h" +#include "crypto_uint16.h" + +static inline crypto_uint16 gf_is_zero_declassify(gf t) +{ + crypto_uint16 mask = crypto_uint16_zero_mask(t); + crypto_declassify(&mask,sizeof mask); + return mask; +} + +/* input: f, element in GF((2^m)^t) */ +/* output: out, minimal polynomial of f */ +/* return: 0 for success and -1 for failure */ +int genpoly_gen(gf *out, gf *f) +{ + int i, j, k, c; + + gf mat[ SYS_T+1 ][ SYS_T ]; + gf mask, inv, t; + + // fill matrix + + mat[0][0] = 1; + + for (i = 1; i < SYS_T; i++) + mat[0][i] = 0; + + for (i = 0; i < SYS_T; i++) + mat[1][i] = f[i]; + + for (j = 2; j <= SYS_T; j++) + GF_mul(mat[j], mat[j-1], f); + + // gaussian + + for (j = 0; j < SYS_T; j++) + { + for (k = j + 1; k < SYS_T; k++) + { + mask = gf_iszero(mat[ j ][ j ]); + + for (c = j; c < SYS_T + 1; c++) + mat[ c ][ j ] ^= mat[ c ][ k ] & mask; + + } + + if ( gf_is_zero_declassify(mat[ j ][ j ]) ) // return if not systematic + { + return -1; + } + + inv = gf_inv(mat[j][j]); + + for (c = j; c < SYS_T + 1; c++) + mat[ c ][ j ] = gf_mul(mat[ c ][ j ], inv) ; + + for (k = 0; k < SYS_T; k++) + { + if (k != j) + { + t = mat[ j ][ k ]; + + for (c = j; c < SYS_T + 1; c++) + mat[ c ][ k ] ^= gf_mul(mat[ c ][ j ], t); + } + } + } + + for (i = 0; i < SYS_T; i++) + out[i] = mat[ SYS_T ][ i ]; + + return 0; +} + diff --git a/deps/mceliece/kem/mceliece8192128f/sk_gen.h b/deps/mceliece/kem/mceliece8192128f/sk_gen.h new file mode 100644 index 0000000..e319703 --- /dev/null +++ b/deps/mceliece/kem/mceliece8192128f/sk_gen.h @@ -0,0 +1,18 @@ +/* + This file is for secret-key generation +*/ + +#ifndef SK_GEN_H +#define SK_GEN_H +#define genpoly_gen CRYPTO_NAMESPACE(genpoly_gen) +#define perm_check CRYPTO_NAMESPACE(perm_check) + +#include "gf.h" + +#include + +int genpoly_gen(gf *, gf *); +int perm_check(uint32_t *); + +#endif + diff --git a/deps/mceliece/kem/mceliece8192128f/subroutines/crypto_declassify.h b/deps/mceliece/kem/mceliece8192128f/subroutines/crypto_declassify.h new file mode 100644 index 0000000..8d84209 --- /dev/null +++ b/deps/mceliece/kem/mceliece8192128f/subroutines/crypto_declassify.h @@ -0,0 +1,8 @@ +#ifndef crypto_declassify_h +#define crypto_declassify_h + +static void crypto_declassify(void *x,unsigned long long n) +{ +} + +#endif diff --git a/deps/mceliece/kem/mceliece8192128f/subroutines/crypto_int16.h b/deps/mceliece/kem/mceliece8192128f/subroutines/crypto_int16.h new file mode 100644 index 0000000..72bbf52 --- /dev/null +++ b/deps/mceliece/kem/mceliece8192128f/subroutines/crypto_int16.h @@ -0,0 +1,81 @@ +#ifndef crypto_int16_h +#define crypto_int16_h + +#include +typedef int16_t crypto_int16; + +static crypto_int16 crypto_int16_negative_mask(crypto_int16 crypto_int16_x) +{ + return crypto_int16_x >> 15; +} + +static crypto_int16 crypto_int16_nonzero_mask(crypto_int16 crypto_int16_x) +{ + return crypto_int16_negative_mask(crypto_int16_x) | crypto_int16_negative_mask(-crypto_int16_x); +} + +static crypto_int16 crypto_int16_zero_mask(crypto_int16 crypto_int16_x) +{ + return ~crypto_int16_nonzero_mask(crypto_int16_x); +} + +static crypto_int16 crypto_int16_positive_mask(crypto_int16 crypto_int16_x) +{ + crypto_int16 crypto_int16_z = -crypto_int16_x; + crypto_int16_z ^= crypto_int16_x & crypto_int16_z; + return crypto_int16_negative_mask(crypto_int16_z); +} + +static crypto_int16 crypto_int16_unequal_mask(crypto_int16 crypto_int16_x,crypto_int16 crypto_int16_y) +{ + crypto_int16 crypto_int16_xy = crypto_int16_x ^ crypto_int16_y; + return crypto_int16_nonzero_mask(crypto_int16_xy); +} + +static crypto_int16 crypto_int16_equal_mask(crypto_int16 crypto_int16_x,crypto_int16 crypto_int16_y) +{ + return ~crypto_int16_unequal_mask(crypto_int16_x,crypto_int16_y); +} + +static crypto_int16 crypto_int16_smaller_mask(crypto_int16 crypto_int16_x,crypto_int16 crypto_int16_y) +{ + crypto_int16 crypto_int16_xy = crypto_int16_x ^ crypto_int16_y; + crypto_int16 crypto_int16_z = crypto_int16_x - crypto_int16_y; + crypto_int16_z ^= crypto_int16_xy & (crypto_int16_z ^ crypto_int16_x); + return crypto_int16_negative_mask(crypto_int16_z); +} + +static crypto_int16 crypto_int16_min(crypto_int16 crypto_int16_x,crypto_int16 crypto_int16_y) +{ + crypto_int16 crypto_int16_xy = crypto_int16_y ^ crypto_int16_x; + crypto_int16 crypto_int16_z = crypto_int16_y - crypto_int16_x; + crypto_int16_z ^= crypto_int16_xy & (crypto_int16_z ^ crypto_int16_y); + crypto_int16_z = crypto_int16_negative_mask(crypto_int16_z); + crypto_int16_z &= crypto_int16_xy; + return crypto_int16_x ^ crypto_int16_z; +} + +static crypto_int16 crypto_int16_max(crypto_int16 crypto_int16_x,crypto_int16 crypto_int16_y) +{ + crypto_int16 crypto_int16_xy = crypto_int16_y ^ crypto_int16_x; + crypto_int16 crypto_int16_z = crypto_int16_y - crypto_int16_x; + crypto_int16_z ^= crypto_int16_xy & (crypto_int16_z ^ crypto_int16_y); + crypto_int16_z = crypto_int16_negative_mask(crypto_int16_z); + crypto_int16_z &= crypto_int16_xy; + return crypto_int16_y ^ crypto_int16_z; +} + +static void crypto_int16_minmax(crypto_int16 *crypto_int16_a,crypto_int16 *crypto_int16_b) +{ + crypto_int16 crypto_int16_x = *crypto_int16_a; + crypto_int16 crypto_int16_y = *crypto_int16_b; + crypto_int16 crypto_int16_xy = crypto_int16_y ^ crypto_int16_x; + crypto_int16 crypto_int16_z = crypto_int16_y - crypto_int16_x; + crypto_int16_z ^= crypto_int16_xy & (crypto_int16_z ^ crypto_int16_y); + crypto_int16_z = crypto_int16_negative_mask(crypto_int16_z); + crypto_int16_z &= crypto_int16_xy; + *crypto_int16_a = crypto_int16_x ^ crypto_int16_z; + *crypto_int16_b = crypto_int16_y ^ crypto_int16_z; +} + +#endif diff --git a/deps/mceliece/kem/mceliece8192128f/subroutines/crypto_int32.h b/deps/mceliece/kem/mceliece8192128f/subroutines/crypto_int32.h new file mode 100644 index 0000000..c22f735 --- /dev/null +++ b/deps/mceliece/kem/mceliece8192128f/subroutines/crypto_int32.h @@ -0,0 +1,81 @@ +#ifndef crypto_int32_h +#define crypto_int32_h + +#include +typedef int32_t crypto_int32; + +static crypto_int32 crypto_int32_negative_mask(crypto_int32 crypto_int32_x) +{ + return crypto_int32_x >> 31; +} + +static crypto_int32 crypto_int32_nonzero_mask(crypto_int32 crypto_int32_x) +{ + return crypto_int32_negative_mask(crypto_int32_x) | crypto_int32_negative_mask(-crypto_int32_x); +} + +static crypto_int32 crypto_int32_zero_mask(crypto_int32 crypto_int32_x) +{ + return ~crypto_int32_nonzero_mask(crypto_int32_x); +} + +static crypto_int32 crypto_int32_positive_mask(crypto_int32 crypto_int32_x) +{ + crypto_int32 crypto_int32_z = -crypto_int32_x; + crypto_int32_z ^= crypto_int32_x & crypto_int32_z; + return crypto_int32_negative_mask(crypto_int32_z); +} + +static crypto_int32 crypto_int32_unequal_mask(crypto_int32 crypto_int32_x,crypto_int32 crypto_int32_y) +{ + crypto_int32 crypto_int32_xy = crypto_int32_x ^ crypto_int32_y; + return crypto_int32_nonzero_mask(crypto_int32_xy); +} + +static crypto_int32 crypto_int32_equal_mask(crypto_int32 crypto_int32_x,crypto_int32 crypto_int32_y) +{ + return ~crypto_int32_unequal_mask(crypto_int32_x,crypto_int32_y); +} + +static crypto_int32 crypto_int32_smaller_mask(crypto_int32 crypto_int32_x,crypto_int32 crypto_int32_y) +{ + crypto_int32 crypto_int32_xy = crypto_int32_x ^ crypto_int32_y; + crypto_int32 crypto_int32_z = crypto_int32_x - crypto_int32_y; + crypto_int32_z ^= crypto_int32_xy & (crypto_int32_z ^ crypto_int32_x); + return crypto_int32_negative_mask(crypto_int32_z); +} + +static crypto_int32 crypto_int32_min(crypto_int32 crypto_int32_x,crypto_int32 crypto_int32_y) +{ + crypto_int32 crypto_int32_xy = crypto_int32_y ^ crypto_int32_x; + crypto_int32 crypto_int32_z = crypto_int32_y - crypto_int32_x; + crypto_int32_z ^= crypto_int32_xy & (crypto_int32_z ^ crypto_int32_y); + crypto_int32_z = crypto_int32_negative_mask(crypto_int32_z); + crypto_int32_z &= crypto_int32_xy; + return crypto_int32_x ^ crypto_int32_z; +} + +static crypto_int32 crypto_int32_max(crypto_int32 crypto_int32_x,crypto_int32 crypto_int32_y) +{ + crypto_int32 crypto_int32_xy = crypto_int32_y ^ crypto_int32_x; + crypto_int32 crypto_int32_z = crypto_int32_y - crypto_int32_x; + crypto_int32_z ^= crypto_int32_xy & (crypto_int32_z ^ crypto_int32_y); + crypto_int32_z = crypto_int32_negative_mask(crypto_int32_z); + crypto_int32_z &= crypto_int32_xy; + return crypto_int32_y ^ crypto_int32_z; +} + +static void crypto_int32_minmax(crypto_int32 *crypto_int32_a,crypto_int32 *crypto_int32_b) +{ + crypto_int32 crypto_int32_x = *crypto_int32_a; + crypto_int32 crypto_int32_y = *crypto_int32_b; + crypto_int32 crypto_int32_xy = crypto_int32_y ^ crypto_int32_x; + crypto_int32 crypto_int32_z = crypto_int32_y - crypto_int32_x; + crypto_int32_z ^= crypto_int32_xy & (crypto_int32_z ^ crypto_int32_y); + crypto_int32_z = crypto_int32_negative_mask(crypto_int32_z); + crypto_int32_z &= crypto_int32_xy; + *crypto_int32_a = crypto_int32_x ^ crypto_int32_z; + *crypto_int32_b = crypto_int32_y ^ crypto_int32_z; +} + +#endif diff --git a/deps/mceliece/kem/mceliece8192128f/subroutines/crypto_uint16.h b/deps/mceliece/kem/mceliece8192128f/subroutines/crypto_uint16.h new file mode 100644 index 0000000..f0ebbbf --- /dev/null +++ b/deps/mceliece/kem/mceliece8192128f/subroutines/crypto_uint16.h @@ -0,0 +1,76 @@ +#ifndef crypto_uint16_h +#define crypto_uint16_h + +#include +typedef uint16_t crypto_uint16; + +typedef int16_t crypto_uint16_signed; + +static crypto_uint16_signed crypto_uint16_signed_negative_mask(crypto_uint16_signed crypto_uint16_signed_x) +{ + return crypto_uint16_signed_x >> 15; +} + +static crypto_uint16 crypto_uint16_nonzero_mask(crypto_uint16 crypto_uint16_x) +{ + return crypto_uint16_signed_negative_mask(crypto_uint16_x) | crypto_uint16_signed_negative_mask(-crypto_uint16_x); +} + +static crypto_uint16 crypto_uint16_zero_mask(crypto_uint16 crypto_uint16_x) +{ + return ~crypto_uint16_nonzero_mask(crypto_uint16_x); +} + +static crypto_uint16 crypto_uint16_unequal_mask(crypto_uint16 crypto_uint16_x,crypto_uint16 crypto_uint16_y) +{ + crypto_uint16 crypto_uint16_xy = crypto_uint16_x ^ crypto_uint16_y; + return crypto_uint16_nonzero_mask(crypto_uint16_xy); +} + +static crypto_uint16 crypto_uint16_equal_mask(crypto_uint16 crypto_uint16_x,crypto_uint16 crypto_uint16_y) +{ + return ~crypto_uint16_unequal_mask(crypto_uint16_x,crypto_uint16_y); +} + +static crypto_uint16 crypto_uint16_smaller_mask(crypto_uint16 crypto_uint16_x,crypto_uint16 crypto_uint16_y) +{ + crypto_uint16 crypto_uint16_xy = crypto_uint16_x ^ crypto_uint16_y; + crypto_uint16 crypto_uint16_z = crypto_uint16_x - crypto_uint16_y; + crypto_uint16_z ^= crypto_uint16_xy & (crypto_uint16_z ^ crypto_uint16_x ^ (((crypto_uint16) 1) << 15)); + return crypto_uint16_signed_negative_mask(crypto_uint16_z); +} + +static crypto_uint16 crypto_uint16_min(crypto_uint16 crypto_uint16_x,crypto_uint16 crypto_uint16_y) +{ + crypto_uint16 crypto_uint16_xy = crypto_uint16_y ^ crypto_uint16_x; + crypto_uint16 crypto_uint16_z = crypto_uint16_y - crypto_uint16_x; + crypto_uint16_z ^= crypto_uint16_xy & (crypto_uint16_z ^ crypto_uint16_y ^ (((crypto_uint16) 1) << 15)); + crypto_uint16_z = crypto_uint16_signed_negative_mask(crypto_uint16_z); + crypto_uint16_z &= crypto_uint16_xy; + return crypto_uint16_x ^ crypto_uint16_z; +} + +static crypto_uint16 crypto_uint16_max(crypto_uint16 crypto_uint16_x,crypto_uint16 crypto_uint16_y) +{ + crypto_uint16 crypto_uint16_xy = crypto_uint16_y ^ crypto_uint16_x; + crypto_uint16 crypto_uint16_z = crypto_uint16_y - crypto_uint16_x; + crypto_uint16_z ^= crypto_uint16_xy & (crypto_uint16_z ^ crypto_uint16_y ^ (((crypto_uint16) 1) << 15)); + crypto_uint16_z = crypto_uint16_signed_negative_mask(crypto_uint16_z); + crypto_uint16_z &= crypto_uint16_xy; + return crypto_uint16_y ^ crypto_uint16_z; +} + +static void crypto_uint16_minmax(crypto_uint16 *crypto_uint16_a,crypto_uint16 *crypto_uint16_b) +{ + crypto_uint16 crypto_uint16_x = *crypto_uint16_a; + crypto_uint16 crypto_uint16_y = *crypto_uint16_b; + crypto_uint16 crypto_uint16_xy = crypto_uint16_y ^ crypto_uint16_x; + crypto_uint16 crypto_uint16_z = crypto_uint16_y - crypto_uint16_x; + crypto_uint16_z ^= crypto_uint16_xy & (crypto_uint16_z ^ crypto_uint16_y ^ (((crypto_uint16) 1) << 15)); + crypto_uint16_z = crypto_uint16_signed_negative_mask(crypto_uint16_z); + crypto_uint16_z &= crypto_uint16_xy; + *crypto_uint16_a = crypto_uint16_x ^ crypto_uint16_z; + *crypto_uint16_b = crypto_uint16_y ^ crypto_uint16_z; +} + +#endif diff --git a/deps/mceliece/kem/mceliece8192128f/subroutines/crypto_uint32.h b/deps/mceliece/kem/mceliece8192128f/subroutines/crypto_uint32.h new file mode 100644 index 0000000..3f39d62 --- /dev/null +++ b/deps/mceliece/kem/mceliece8192128f/subroutines/crypto_uint32.h @@ -0,0 +1,76 @@ +#ifndef crypto_uint32_h +#define crypto_uint32_h + +#include +typedef uint32_t crypto_uint32; + +typedef int32_t crypto_uint32_signed; + +static crypto_uint32_signed crypto_uint32_signed_negative_mask(crypto_uint32_signed crypto_uint32_signed_x) +{ + return crypto_uint32_signed_x >> 31; +} + +static crypto_uint32 crypto_uint32_nonzero_mask(crypto_uint32 crypto_uint32_x) +{ + return crypto_uint32_signed_negative_mask(crypto_uint32_x) | crypto_uint32_signed_negative_mask(-crypto_uint32_x); +} + +static crypto_uint32 crypto_uint32_zero_mask(crypto_uint32 crypto_uint32_x) +{ + return ~crypto_uint32_nonzero_mask(crypto_uint32_x); +} + +static crypto_uint32 crypto_uint32_unequal_mask(crypto_uint32 crypto_uint32_x,crypto_uint32 crypto_uint32_y) +{ + crypto_uint32 crypto_uint32_xy = crypto_uint32_x ^ crypto_uint32_y; + return crypto_uint32_nonzero_mask(crypto_uint32_xy); +} + +static crypto_uint32 crypto_uint32_equal_mask(crypto_uint32 crypto_uint32_x,crypto_uint32 crypto_uint32_y) +{ + return ~crypto_uint32_unequal_mask(crypto_uint32_x,crypto_uint32_y); +} + +static crypto_uint32 crypto_uint32_smaller_mask(crypto_uint32 crypto_uint32_x,crypto_uint32 crypto_uint32_y) +{ + crypto_uint32 crypto_uint32_xy = crypto_uint32_x ^ crypto_uint32_y; + crypto_uint32 crypto_uint32_z = crypto_uint32_x - crypto_uint32_y; + crypto_uint32_z ^= crypto_uint32_xy & (crypto_uint32_z ^ crypto_uint32_x ^ (((crypto_uint32) 1) << 31)); + return crypto_uint32_signed_negative_mask(crypto_uint32_z); +} + +static crypto_uint32 crypto_uint32_min(crypto_uint32 crypto_uint32_x,crypto_uint32 crypto_uint32_y) +{ + crypto_uint32 crypto_uint32_xy = crypto_uint32_y ^ crypto_uint32_x; + crypto_uint32 crypto_uint32_z = crypto_uint32_y - crypto_uint32_x; + crypto_uint32_z ^= crypto_uint32_xy & (crypto_uint32_z ^ crypto_uint32_y ^ (((crypto_uint32) 1) << 31)); + crypto_uint32_z = crypto_uint32_signed_negative_mask(crypto_uint32_z); + crypto_uint32_z &= crypto_uint32_xy; + return crypto_uint32_x ^ crypto_uint32_z; +} + +static crypto_uint32 crypto_uint32_max(crypto_uint32 crypto_uint32_x,crypto_uint32 crypto_uint32_y) +{ + crypto_uint32 crypto_uint32_xy = crypto_uint32_y ^ crypto_uint32_x; + crypto_uint32 crypto_uint32_z = crypto_uint32_y - crypto_uint32_x; + crypto_uint32_z ^= crypto_uint32_xy & (crypto_uint32_z ^ crypto_uint32_y ^ (((crypto_uint32) 1) << 31)); + crypto_uint32_z = crypto_uint32_signed_negative_mask(crypto_uint32_z); + crypto_uint32_z &= crypto_uint32_xy; + return crypto_uint32_y ^ crypto_uint32_z; +} + +static void crypto_uint32_minmax(crypto_uint32 *crypto_uint32_a,crypto_uint32 *crypto_uint32_b) +{ + crypto_uint32 crypto_uint32_x = *crypto_uint32_a; + crypto_uint32 crypto_uint32_y = *crypto_uint32_b; + crypto_uint32 crypto_uint32_xy = crypto_uint32_y ^ crypto_uint32_x; + crypto_uint32 crypto_uint32_z = crypto_uint32_y - crypto_uint32_x; + crypto_uint32_z ^= crypto_uint32_xy & (crypto_uint32_z ^ crypto_uint32_y ^ (((crypto_uint32) 1) << 31)); + crypto_uint32_z = crypto_uint32_signed_negative_mask(crypto_uint32_z); + crypto_uint32_z &= crypto_uint32_xy; + *crypto_uint32_a = crypto_uint32_x ^ crypto_uint32_z; + *crypto_uint32_b = crypto_uint32_y ^ crypto_uint32_z; +} + +#endif diff --git a/deps/mceliece/kem/mceliece8192128f/subroutines/crypto_uint64.h b/deps/mceliece/kem/mceliece8192128f/subroutines/crypto_uint64.h new file mode 100644 index 0000000..42e2be9 --- /dev/null +++ b/deps/mceliece/kem/mceliece8192128f/subroutines/crypto_uint64.h @@ -0,0 +1,76 @@ +#ifndef crypto_uint64_h +#define crypto_uint64_h + +#include +typedef uint64_t crypto_uint64; + +typedef int64_t crypto_uint64_signed; + +static crypto_uint64_signed crypto_uint64_signed_negative_mask(crypto_uint64_signed crypto_uint64_signed_x) +{ + return crypto_uint64_signed_x >> 63; +} + +static crypto_uint64 crypto_uint64_nonzero_mask(crypto_uint64 crypto_uint64_x) +{ + return crypto_uint64_signed_negative_mask(crypto_uint64_x) | crypto_uint64_signed_negative_mask(-crypto_uint64_x); +} + +static crypto_uint64 crypto_uint64_zero_mask(crypto_uint64 crypto_uint64_x) +{ + return ~crypto_uint64_nonzero_mask(crypto_uint64_x); +} + +static crypto_uint64 crypto_uint64_unequal_mask(crypto_uint64 crypto_uint64_x,crypto_uint64 crypto_uint64_y) +{ + crypto_uint64 crypto_uint64_xy = crypto_uint64_x ^ crypto_uint64_y; + return crypto_uint64_nonzero_mask(crypto_uint64_xy); +} + +static crypto_uint64 crypto_uint64_equal_mask(crypto_uint64 crypto_uint64_x,crypto_uint64 crypto_uint64_y) +{ + return ~crypto_uint64_unequal_mask(crypto_uint64_x,crypto_uint64_y); +} + +static crypto_uint64 crypto_uint64_smaller_mask(crypto_uint64 crypto_uint64_x,crypto_uint64 crypto_uint64_y) +{ + crypto_uint64 crypto_uint64_xy = crypto_uint64_x ^ crypto_uint64_y; + crypto_uint64 crypto_uint64_z = crypto_uint64_x - crypto_uint64_y; + crypto_uint64_z ^= crypto_uint64_xy & (crypto_uint64_z ^ crypto_uint64_x ^ (((crypto_uint64) 1) << 63)); + return crypto_uint64_signed_negative_mask(crypto_uint64_z); +} + +static crypto_uint64 crypto_uint64_min(crypto_uint64 crypto_uint64_x,crypto_uint64 crypto_uint64_y) +{ + crypto_uint64 crypto_uint64_xy = crypto_uint64_y ^ crypto_uint64_x; + crypto_uint64 crypto_uint64_z = crypto_uint64_y - crypto_uint64_x; + crypto_uint64_z ^= crypto_uint64_xy & (crypto_uint64_z ^ crypto_uint64_y ^ (((crypto_uint64) 1) << 63)); + crypto_uint64_z = crypto_uint64_signed_negative_mask(crypto_uint64_z); + crypto_uint64_z &= crypto_uint64_xy; + return crypto_uint64_x ^ crypto_uint64_z; +} + +static crypto_uint64 crypto_uint64_max(crypto_uint64 crypto_uint64_x,crypto_uint64 crypto_uint64_y) +{ + crypto_uint64 crypto_uint64_xy = crypto_uint64_y ^ crypto_uint64_x; + crypto_uint64 crypto_uint64_z = crypto_uint64_y - crypto_uint64_x; + crypto_uint64_z ^= crypto_uint64_xy & (crypto_uint64_z ^ crypto_uint64_y ^ (((crypto_uint64) 1) << 63)); + crypto_uint64_z = crypto_uint64_signed_negative_mask(crypto_uint64_z); + crypto_uint64_z &= crypto_uint64_xy; + return crypto_uint64_y ^ crypto_uint64_z; +} + +static void crypto_uint64_minmax(crypto_uint64 *crypto_uint64_a,crypto_uint64 *crypto_uint64_b) +{ + crypto_uint64 crypto_uint64_x = *crypto_uint64_a; + crypto_uint64 crypto_uint64_y = *crypto_uint64_b; + crypto_uint64 crypto_uint64_xy = crypto_uint64_y ^ crypto_uint64_x; + crypto_uint64 crypto_uint64_z = crypto_uint64_y - crypto_uint64_x; + crypto_uint64_z ^= crypto_uint64_xy & (crypto_uint64_z ^ crypto_uint64_y ^ (((crypto_uint64) 1) << 63)); + crypto_uint64_z = crypto_uint64_signed_negative_mask(crypto_uint64_z); + crypto_uint64_z &= crypto_uint64_xy; + *crypto_uint64_a = crypto_uint64_x ^ crypto_uint64_z; + *crypto_uint64_b = crypto_uint64_y ^ crypto_uint64_z; +} + +#endif diff --git a/deps/mceliece/kem/mceliece8192128f/synd.c b/deps/mceliece/kem/mceliece8192128f/synd.c new file mode 100644 index 0000000..c945647 --- /dev/null +++ b/deps/mceliece/kem/mceliece8192128f/synd.c @@ -0,0 +1,36 @@ +/* + This file is for syndrome computation +*/ + +#include "synd.h" + +#include "params.h" +#include "root.h" + +#include + +/* input: Goppa polynomial f, support L, received word r */ +/* output: out, the syndrome of length 2t */ +void synd(gf *out, gf *f, gf *L, unsigned char *r) +{ + int i, j; + gf e, e_inv, c; + + for (j = 0; j < 2*SYS_T; j++) + out[j] = 0; + + for (i = 0; i < SYS_N; i++) + { + c = (r[i/8] >> (i%8)) & 1; + + e = eval(f, L[i]); + e_inv = gf_inv(gf_mul(e,e)); + + for (j = 0; j < 2*SYS_T; j++) + { + out[j] = gf_add(out[j], gf_mul(e_inv, c)); + e_inv = gf_mul(e_inv, L[i]); + } + } +} + diff --git a/deps/mceliece/kem/mceliece8192128f/synd.h b/deps/mceliece/kem/mceliece8192128f/synd.h new file mode 100644 index 0000000..9331406 --- /dev/null +++ b/deps/mceliece/kem/mceliece8192128f/synd.h @@ -0,0 +1,14 @@ +/* + This file is for syndrome computation +*/ + +#ifndef SYND_H +#define SYND_H +#define synd CRYPTO_NAMESPACE(synd) + +#include "gf.h" + +void synd(gf *, gf *, gf *, unsigned char *); + +#endif + diff --git a/deps/mceliece/kem/mceliece8192128f/transpose.c b/deps/mceliece/kem/mceliece8192128f/transpose.c new file mode 100644 index 0000000..0da2bc5 --- /dev/null +++ b/deps/mceliece/kem/mceliece8192128f/transpose.c @@ -0,0 +1,43 @@ +/* + This file is for matrix transposition +*/ + +#include "transpose.h" + +#include + +/* input: in, a 64x64 matrix over GF(2) */ +/* output: out, transpose of in */ +void transpose_64x64(uint64_t * out, uint64_t * in) +{ + int i, j, s, d; + + uint64_t x, y; + uint64_t masks[6][2] = { + {0x5555555555555555, 0xAAAAAAAAAAAAAAAA}, + {0x3333333333333333, 0xCCCCCCCCCCCCCCCC}, + {0x0F0F0F0F0F0F0F0F, 0xF0F0F0F0F0F0F0F0}, + {0x00FF00FF00FF00FF, 0xFF00FF00FF00FF00}, + {0x0000FFFF0000FFFF, 0xFFFF0000FFFF0000}, + {0x00000000FFFFFFFF, 0xFFFFFFFF00000000} + }; + + for (i = 0; i < 64; i++) + out[i] = in[i]; + + for (d = 5; d >= 0; d--) + { + s = 1 << d; + + for (i = 0; i < 64; i += s*2) + for (j = i; j < i+s; j++) + { + x = (out[j] & masks[d][0]) | ((out[j+s] & masks[d][0]) << s); + y = ((out[j] & masks[d][1]) >> s) | (out[j+s] & masks[d][1]); + + out[j+0] = x; + out[j+s] = y; + } + } +} + diff --git a/deps/mceliece/kem/mceliece8192128f/transpose.h b/deps/mceliece/kem/mceliece8192128f/transpose.h new file mode 100644 index 0000000..31e5b96 --- /dev/null +++ b/deps/mceliece/kem/mceliece8192128f/transpose.h @@ -0,0 +1,14 @@ +/* + This file is for matrix transposition +*/ + +#ifndef TRANSPOSE_H +#define TRANSPOSE_H +#define transpose_64x64 CRYPTO_NAMESPACE(transpose_64x64) + +#include + +void transpose_64x64(uint64_t *, uint64_t *); + +#endif + diff --git a/deps/mceliece/kem/mceliece8192128f/uint64_sort.h b/deps/mceliece/kem/mceliece8192128f/uint64_sort.h new file mode 100644 index 0000000..2fb100c --- /dev/null +++ b/deps/mceliece/kem/mceliece8192128f/uint64_sort.h @@ -0,0 +1,45 @@ +#ifndef uint64_sort_h +#define uint64_sort_h + +#define int64_sort CRYPTO_NAMESPACE(int64_sort) + +#include + +#define uint64_MINMAX(a,b) \ +do { \ + uint64_t c = b - a; \ + c >>= 63; \ + c = -c; \ + c &= a ^ b; \ + a ^= c; \ + b ^= c; \ +} while(0) + +static void uint64_sort(uint64_t *x,long long n) +{ + long long top,p,q,r,i; + + if (n < 2) return; + top = 1; + while (top < n - top) top += top; + + for (p = top;p > 0;p >>= 1) { + for (i = 0;i < n - p;++i) + if (!(i & p)) + uint64_MINMAX(x[i],x[i+p]); + i = 0; + for (q = top;q > p;q >>= 1) { + for (;i < n - q;++i) { + if (!(i & p)) { + uint64_t a = x[i + p]; + for (r = q;r > p;r >>= 1) + uint64_MINMAX(a,x[i+r]); + x[i + p] = a; + } + } + } + } +} + +#endif + diff --git a/deps/mceliece/kem/mceliece8192128f/util.c b/deps/mceliece/kem/mceliece8192128f/util.c new file mode 100644 index 0000000..1679168 --- /dev/null +++ b/deps/mceliece/kem/mceliece8192128f/util.c @@ -0,0 +1,75 @@ +/* + This file is for loading/storing data in a little-endian fashion +*/ + +#include "util.h" + +#include "params.h" + +void store_gf(unsigned char *dest, gf a) +{ + dest[0] = a & 0xFF; + dest[1] = a >> 8; +} + +uint16_t load_gf(const unsigned char *src) +{ + uint16_t a; + + a = src[1]; + a <<= 8; + a |= src[0]; + + return a & GFMASK; +} + +uint32_t load4(const unsigned char * in) +{ + int i; + uint32_t ret = in[3]; + + for (i = 2; i >= 0; i--) + { + ret <<= 8; + ret |= in[i]; + } + + return ret; +} + +void store8(unsigned char *out, uint64_t in) +{ + out[0] = (in >> 0x00) & 0xFF; + out[1] = (in >> 0x08) & 0xFF; + out[2] = (in >> 0x10) & 0xFF; + out[3] = (in >> 0x18) & 0xFF; + out[4] = (in >> 0x20) & 0xFF; + out[5] = (in >> 0x28) & 0xFF; + out[6] = (in >> 0x30) & 0xFF; + out[7] = (in >> 0x38) & 0xFF; +} + +uint64_t load8(const unsigned char * in) +{ + int i; + uint64_t ret = in[7]; + + for (i = 6; i >= 0; i--) + { + ret <<= 8; + ret |= in[i]; + } + + return ret; +} + +gf bitrev(gf a) +{ + a = ((a & 0x00FF) << 8) | ((a & 0xFF00) >> 8); + a = ((a & 0x0F0F) << 4) | ((a & 0xF0F0) >> 4); + a = ((a & 0x3333) << 2) | ((a & 0xCCCC) >> 2); + a = ((a & 0x5555) << 1) | ((a & 0xAAAA) >> 1); + + return a >> 3; +} + diff --git a/deps/mceliece/kem/mceliece8192128f/util.h b/deps/mceliece/kem/mceliece8192128f/util.h new file mode 100644 index 0000000..d610bee --- /dev/null +++ b/deps/mceliece/kem/mceliece8192128f/util.h @@ -0,0 +1,27 @@ +/* + This file is for loading/storing data in a little-endian fashion +*/ + +#ifndef UTIL_H +#define UTIL_H +#define bitrev CRYPTO_NAMESPACE(bitrev) +#define load4 CRYPTO_NAMESPACE(load4) +#define load8 CRYPTO_NAMESPACE(load8) +#define load_gf CRYPTO_NAMESPACE(load_gf) +#define store8 CRYPTO_NAMESPACE(store8) +#define store_gf CRYPTO_NAMESPACE(store_gf) + +#include "gf.h" +#include + +void store_gf(unsigned char *, gf); +uint16_t load_gf(const unsigned char *); +uint32_t load4(const unsigned char *); + +void store8(unsigned char *, uint64_t ); +uint64_t load8(const unsigned char *); + +gf bitrev(gf); + +#endif + diff --git a/deps/mceliece/mceliece.h b/deps/mceliece/mceliece.h new file mode 100644 index 0000000..68fa865 --- /dev/null +++ b/deps/mceliece/mceliece.h @@ -0,0 +1,10 @@ +#include "kem/mceliece348864/crypto_kem_mceliece348864.h" +#include "kem/mceliece348864f/crypto_kem_mceliece348864f.h" +#include "kem/mceliece460896/crypto_kem_mceliece460896.h" +#include "kem/mceliece460896f/crypto_kem_mceliece460896f.h" +#include "kem/mceliece6688128/crypto_kem_mceliece6688128.h" +#include "kem/mceliece6688128f/crypto_kem_mceliece6688128f.h" +#include "kem/mceliece6960119/crypto_kem_mceliece6960119.h" +#include "kem/mceliece6960119f/crypto_kem_mceliece6960119f.h" +#include "kem/mceliece8192128/crypto_kem_mceliece8192128.h" +#include "kem/mceliece8192128f/crypto_kem_mceliece8192128f.h" diff --git a/deps/mceliece/mceliece_externals.h b/deps/mceliece/mceliece_externals.h new file mode 100644 index 0000000..28ee00e --- /dev/null +++ b/deps/mceliece/mceliece_externals.h @@ -0,0 +1,24 @@ +#ifndef _EXTERNALS_H +#define _EXTERNALS_H + +#include + +#ifndef NO_SHORT_NAMES_FOR_EXTERNALS +# define randombytes pqcrypto_mceliece_randombytes +# define SHAKE256 pqcrypto_mceliece_SHAKE256 +#endif + +#ifdef __EMSCRIPTEN__ +# define WASM_EXTERN extern +#else +# define WASM_EXTERN +#endif + +WASM_EXTERN +int pqcrypto_mceliece_randombytes(unsigned char*, size_t); + +WASM_EXTERN +int pqcrypto_mceliece_SHAKE256(unsigned char*, size_t, + const unsigned char*, size_t); + +#endif diff --git a/deps/mceliece/test-vectors-from-kat b/deps/mceliece/test-vectors-from-kat new file mode 100755 index 0000000..f8308cf --- /dev/null +++ b/deps/mceliece/test-vectors-from-kat @@ -0,0 +1,33 @@ +#!/bin/bash +set -e + +if [ -z "$1" ]; then + echo "Usage: $0 [FILE.tar.gz]" >&2 + exit 1 +fi + +echo -n '[' +comma='' +tar tf "$1" | grep '\.rsp$' | while read -r name; do + dir=$(dirname "$name") + id=$(basename "$dir") + + echo $comma + comma=',' + + tar -xOf "$1" "$name" | tail -n +6 | cut -c 6- | ( + echo ' {' + echo ' "algorithm": "'"$id"'",' + read -r sk_hex + read -r ct_hex + read -r ss_hex + sk=$(echo "$sk_hex" | xxd -r -p | base64 -w 0) + ct=$(echo "$ct_hex" | xxd -r -p | base64 -w 0) + ss=$(echo "$ss_hex" | xxd -r -p | base64 -w 0) + echo ' "privateKey": "'"$sk"'",' + echo ' "key": "'"$ss"'",' + echo ' "encryptedKey": "'"$ct"'"' + echo -n ' }' + ) +done +echo -e '\n]' diff --git a/index.js b/index.js new file mode 100644 index 0000000..45b57cf --- /dev/null +++ b/index.js @@ -0,0 +1,15 @@ +'use strict'; + +let McEliece; +try { + // Try to load native bindings first. + ({ McEliece } = require('bindings')('node_mceliece')); +} catch (err) { + // If native bindings are not available, use WebAssembly instead. + ({ McEliece } = require('./wasm/main_thread')); + process.emitWarning(`Using WebAssembly backend: ${err.message}`); +} + +Object.freeze(McEliece.supportedAlgorithms); + +Object.defineProperty(module.exports, 'McEliece', { value: McEliece }); diff --git a/node_mceliece.cc b/node_mceliece.cc new file mode 100644 index 0000000..36ec642 --- /dev/null +++ b/node_mceliece.cc @@ -0,0 +1,453 @@ +#include +#include +#include +#include + +#include +#include + +extern "C" { + +#define NO_SHORT_NAMES_FOR_EXTERNALS +#include +#include + +#define CHECK(a, message) do { \ + if ((a) != 1) { \ + napi_fatal_error(__FILE__, NAPI_AUTO_LENGTH, \ + message, NAPI_AUTO_LENGTH); \ + } \ + } while (0) \ + +int pqcrypto_mceliece_randombytes(unsigned char* x, size_t xlen) { + CHECK(RAND_bytes(x, xlen), "RAND_bytes failed"); + return 0; +} + +int pqcrypto_mceliece_SHAKE256(unsigned char *output, size_t outputByteLen, + const unsigned char *input, size_t inputByteLen) { + EVP_MD_CTX* ctx; + + CHECK((ctx = EVP_MD_CTX_create()) != NULL, + "EVP_MD_CTX_create failed"); + CHECK(EVP_DigestInit_ex(ctx, EVP_shake256(), NULL), + "EVP_DigestInit_ex failed"); + CHECK(EVP_DigestUpdate(ctx, input, inputByteLen), + "EVP_DigestUpdate failed"); + CHECK(EVP_DigestFinalXOF(ctx, output, outputByteLen), + "EVP_DigestFinalXOF failed"); + + EVP_MD_CTX_free(ctx); + return 0; +} + +} + +namespace { + +typedef int (*keypair_fn_t)(unsigned char* public_key, unsigned char* private_key); +typedef int (*encrypt_fn_t)(unsigned char* ciphertext, unsigned char* key, const unsigned char* public_key); +typedef int (*decrypt_fn_t)(unsigned char* key, const unsigned char* ciphertext, const unsigned char* public_key); + +typedef struct { + const char* name; + size_t public_key_size; + size_t private_key_size; + size_t key_size; + size_t ciphertext_size; + keypair_fn_t keypair; + encrypt_fn_t encrypt; + decrypt_fn_t decrypt; +} mceliece_t; + +const mceliece_t kems[] = { + { + "mceliece348864", + crypto_kem_mceliece348864_ref_PUBLICKEYBYTES, + crypto_kem_mceliece348864_ref_SECRETKEYBYTES, + crypto_kem_mceliece348864_ref_BYTES, + crypto_kem_mceliece348864_ref_CIPHERTEXTBYTES, + crypto_kem_mceliece348864_ref_keypair, + crypto_kem_mceliece348864_ref_enc, + crypto_kem_mceliece348864_ref_dec + }, + { + "mceliece348864f", + crypto_kem_mceliece348864f_ref_PUBLICKEYBYTES, + crypto_kem_mceliece348864f_ref_SECRETKEYBYTES, + crypto_kem_mceliece348864f_ref_BYTES, + crypto_kem_mceliece348864f_ref_CIPHERTEXTBYTES, + crypto_kem_mceliece348864f_ref_keypair, + crypto_kem_mceliece348864f_ref_enc, + crypto_kem_mceliece348864f_ref_dec + }, + { + "mceliece460896", + crypto_kem_mceliece460896_ref_PUBLICKEYBYTES, + crypto_kem_mceliece460896_ref_SECRETKEYBYTES, + crypto_kem_mceliece460896_ref_BYTES, + crypto_kem_mceliece460896_ref_CIPHERTEXTBYTES, + crypto_kem_mceliece460896_ref_keypair, + crypto_kem_mceliece460896_ref_enc, + crypto_kem_mceliece460896_ref_dec + }, + { + "mceliece460896f", + crypto_kem_mceliece460896f_ref_PUBLICKEYBYTES, + crypto_kem_mceliece460896f_ref_SECRETKEYBYTES, + crypto_kem_mceliece460896f_ref_BYTES, + crypto_kem_mceliece460896f_ref_CIPHERTEXTBYTES, + crypto_kem_mceliece460896f_ref_keypair, + crypto_kem_mceliece460896f_ref_enc, + crypto_kem_mceliece460896f_ref_dec + }, + { + "mceliece6688128", + crypto_kem_mceliece6688128_ref_PUBLICKEYBYTES, + crypto_kem_mceliece6688128_ref_SECRETKEYBYTES, + crypto_kem_mceliece6688128_ref_BYTES, + crypto_kem_mceliece6688128_ref_CIPHERTEXTBYTES, + crypto_kem_mceliece6688128_ref_keypair, + crypto_kem_mceliece6688128_ref_enc, + crypto_kem_mceliece6688128_ref_dec + }, + { + "mceliece6688128f", + crypto_kem_mceliece6688128f_ref_PUBLICKEYBYTES, + crypto_kem_mceliece6688128f_ref_SECRETKEYBYTES, + crypto_kem_mceliece6688128f_ref_BYTES, + crypto_kem_mceliece6688128f_ref_CIPHERTEXTBYTES, + crypto_kem_mceliece6688128f_ref_keypair, + crypto_kem_mceliece6688128f_ref_enc, + crypto_kem_mceliece6688128f_ref_dec + }, + { + "mceliece6960119", + crypto_kem_mceliece6960119_ref_PUBLICKEYBYTES, + crypto_kem_mceliece6960119_ref_SECRETKEYBYTES, + crypto_kem_mceliece6960119_ref_BYTES, + crypto_kem_mceliece6960119_ref_CIPHERTEXTBYTES, + crypto_kem_mceliece6960119_ref_keypair, + crypto_kem_mceliece6960119_ref_enc, + crypto_kem_mceliece6960119_ref_dec + }, + { + "mceliece6960119f", + crypto_kem_mceliece6960119f_ref_PUBLICKEYBYTES, + crypto_kem_mceliece6960119f_ref_SECRETKEYBYTES, + crypto_kem_mceliece6960119f_ref_BYTES, + crypto_kem_mceliece6960119f_ref_CIPHERTEXTBYTES, + crypto_kem_mceliece6960119f_ref_keypair, + crypto_kem_mceliece6960119f_ref_enc, + crypto_kem_mceliece6960119f_ref_dec + }, + { + "mceliece8192128", + crypto_kem_mceliece8192128_ref_PUBLICKEYBYTES, + crypto_kem_mceliece8192128_ref_SECRETKEYBYTES, + crypto_kem_mceliece8192128_ref_BYTES, + crypto_kem_mceliece8192128_ref_CIPHERTEXTBYTES, + crypto_kem_mceliece8192128_ref_keypair, + crypto_kem_mceliece8192128_ref_enc, + crypto_kem_mceliece8192128_ref_dec + }, + { + "mceliece8192128f", + crypto_kem_mceliece8192128f_ref_PUBLICKEYBYTES, + crypto_kem_mceliece8192128f_ref_SECRETKEYBYTES, + crypto_kem_mceliece8192128f_ref_BYTES, + crypto_kem_mceliece8192128f_ref_CIPHERTEXTBYTES, + crypto_kem_mceliece8192128f_ref_keypair, + crypto_kem_mceliece8192128f_ref_enc, + crypto_kem_mceliece8192128f_ref_dec + } +}; + +const mceliece_t* get_kem(const char* name) { + for (unsigned int i = 0; i < sizeof(kems) / sizeof(mceliece_t); i++) { + if (strcmp(kems[i].name, name) == 0) + return &kems[i]; + } + return NULL; +} + +template +inline T* Malloc(size_t size) { + return reinterpret_cast(malloc(size)); +} + +void Free(Napi::Env env, void* p) { + free(p); +} + +template +inline T* Duplicate(const void* mem, size_t size) { + T* copy = Malloc(size); + if (copy != nullptr) + memcpy(copy, mem, size); + return copy; +} + +class KeygenWorker : public Napi::AsyncWorker { + public: + KeygenWorker(Napi::Function& callback, const mceliece_t* impl) : AsyncWorker(callback), impl(impl) {} + + ~KeygenWorker() {} + + void Execute() override { + public_key = Malloc(impl->public_key_size); + private_key = Malloc(impl->private_key_size); + + if (public_key == nullptr || private_key == nullptr) { + free(public_key); + free(private_key); + return SetError("Failed to allocate memory"); + } + + if (impl->keypair(public_key, private_key) != 0) { + free(public_key); + free(private_key); + return SetError("failed to generate keypair"); + } + } + + std::vector GetResult(Napi::Env env) override { + const auto public_key_buf = Napi::Buffer::New(env, public_key, impl->public_key_size, Free); + const auto private_key_buf = Napi::Buffer::New(env, private_key, impl->private_key_size, Free); + + Napi::Object obj = Napi::Object::New(env); + obj.Set("publicKey", public_key_buf); + obj.Set("privateKey", private_key_buf); + return { env.Undefined(), obj }; + } + + private: + const mceliece_t* impl; + unsigned char* public_key; + unsigned char* private_key; +}; + +class DecryptWorker : public Napi::AsyncWorker { + public: + DecryptWorker(Napi::Function& callback, const mceliece_t* impl, const void* private_key, const void* ciphertext) : AsyncWorker(callback), impl(impl) { + this->private_key = Duplicate(private_key, impl->private_key_size); + this->ciphertext = Duplicate(ciphertext, impl->ciphertext_size); + } + + void Execute() override { + if (private_key == nullptr || ciphertext == nullptr) + return SetError("Failed to allocate memory"); + + actual_key = Malloc(impl->key_size); + if (actual_key == nullptr) + return SetError("Failed to allocate memory"); + + if (impl->decrypt(actual_key, ciphertext, private_key) != 0) { + free(actual_key); + return SetError("decryption failed"); + } + } + + std::vector GetResult(Napi::Env env) override { + const auto key = Napi::Buffer::New(env, actual_key, impl->key_size, Free); + return { env.Undefined(), key }; + } + + ~DecryptWorker() { + free(private_key); + free(ciphertext); + } + + private: + const mceliece_t* impl; + unsigned char* private_key; + unsigned char* ciphertext; + unsigned char* actual_key; +}; + +class McEliece : public Napi::ObjectWrap { + public: + McEliece(const Napi::CallbackInfo& info) : Napi::ObjectWrap(info) { + Napi::Env env = info.Env(); + + if (info.Length() != 1) { + Napi::TypeError::New(env, "Wrong number of arguments") + .ThrowAsJavaScriptException(); + return; + } + + if (!info[0].IsString()) { + Napi::TypeError::New(env, "First argument must be a string") + .ThrowAsJavaScriptException(); + return; + } + + std::string name = info[0].As(); + this->impl = get_kem(name.c_str()); + + if (this->impl == nullptr) { + Napi::Error::New(env, "No such implementation") + .ThrowAsJavaScriptException(); + } + } + + Napi::Value Keypair(const Napi::CallbackInfo& info) { + Napi::Env env = info.Env(); + + if (info[0].IsFunction()) { + Napi::Function cb = info[0].As(); + KeygenWorker* worker = new KeygenWorker(cb, impl); + worker->Queue(); + return env.Undefined(); + } + + Napi::Buffer public_key = Napi::Buffer::New(env, impl->public_key_size); + Napi::Buffer private_key = Napi::Buffer::New(env, impl->private_key_size); + int r = impl->keypair(public_key.Data(), private_key.Data()); + if (r != 0) { + Napi::Error::New(env, "failed to generate keypair").ThrowAsJavaScriptException(); + return env.Undefined(); + } + + Napi::Object obj = Napi::Object::New(env); + obj.Set("publicKey", public_key); + obj.Set("privateKey", private_key); + return obj; + } + + Napi::Value GenerateKey(const Napi::CallbackInfo& info) { + Napi::Env env = info.Env(); + + if (info.Length() != 1) { + Napi::TypeError::New(env, "Wrong number of arguments") + .ThrowAsJavaScriptException(); + return env.Undefined(); + } + + if (!info[0].IsTypedArray()) { + Napi::TypeError::New(env, "First argument must be a TypedArray") + .ThrowAsJavaScriptException(); + return env.Undefined(); + } + + Napi::Buffer public_key = info[0].As>(); + if (public_key.Length() != impl->public_key_size) { + Napi::TypeError::New(env, "Invalid public key size") + .ThrowAsJavaScriptException(); + return env.Undefined(); + } + + Napi::Buffer encrypted_key = Napi::Buffer::New(env, impl->ciphertext_size); + Napi::Buffer actual_key = Napi::Buffer::New(env, impl->key_size); + + int r = impl->encrypt(encrypted_key.Data(), actual_key.Data(), public_key.Data()); + if (r != 0) { + Napi::Error::New(env, "encryption failed").ThrowAsJavaScriptException(); + return env.Undefined(); + } + + Napi::Object obj = Napi::Object::New(env); + obj.Set("key", actual_key); + obj.Set("encryptedKey", encrypted_key); + return obj; + } + + Napi::Value DecryptKey(const Napi::CallbackInfo& info) { + Napi::Env env = info.Env(); + + if (info.Length() != 2 && info.Length() != 3) { + Napi::TypeError::New(env, "Wrong number of arguments") + .ThrowAsJavaScriptException(); + return env.Undefined(); + } + + if (!info[0].IsTypedArray()) { + Napi::TypeError::New(env, "First argument must be a TypedArray") + .ThrowAsJavaScriptException(); + return env.Undefined(); + } + + if (!info[1].IsTypedArray()) { + Napi::TypeError::New(env, "Second argument must be a TypedArray") + .ThrowAsJavaScriptException(); + return env.Undefined(); + } + + Napi::Buffer private_key = info[0].As>(); + if (private_key.Length() != impl->private_key_size) { + Napi::TypeError::New(env, "Invalid private key size") + .ThrowAsJavaScriptException(); + return env.Undefined(); + } + + Napi::Buffer encrypted_key = info[1].As>(); + if (encrypted_key.Length() != impl->ciphertext_size) { + Napi::TypeError::New(env, "Invalid ciphertext size") + .ThrowAsJavaScriptException(); + return env.Undefined(); + } + + if (info.Length() == 3 && info[2].IsFunction()) { + Napi::Function cb = info[2].As(); + DecryptWorker* worker = new DecryptWorker(cb, impl, private_key.Data(), encrypted_key.Data()); + worker->Queue(); + return env.Undefined(); + } + + Napi::Buffer actual_key = Napi::Buffer::New(env, impl->key_size); + + int r = impl->decrypt(actual_key.Data(), encrypted_key.Data(), private_key.Data()); + if (r != 0) { + Napi::Error::New(env, "decryption failed").ThrowAsJavaScriptException(); + return env.Undefined(); + } + + return actual_key; + } + + Napi::Value GetKeySize(const Napi::CallbackInfo& info) { + return Napi::Value::From(info.Env(), impl->key_size); + } + + Napi::Value GetEncryptedKeySize(const Napi::CallbackInfo& info) { + return Napi::Value::From(info.Env(), impl->ciphertext_size); + } + + Napi::Value GetPublicKeySize(const Napi::CallbackInfo& info) { + return Napi::Value::From(info.Env(), impl->public_key_size); + } + + Napi::Value GetPrivateKeySize(const Napi::CallbackInfo& info) { + return Napi::Value::From(info.Env(), impl->private_key_size); + } + + private: + const mceliece_t* impl; +}; + +Napi::Object Init(Napi::Env env, Napi::Object exports) { + Napi::HandleScope scope(env); + + Napi::Function func = McEliece::DefineClass(env, "McEliece", { + Napi::ObjectWrap::InstanceMethod("keypair", &McEliece::Keypair), + Napi::ObjectWrap::InstanceMethod("generateKey", &McEliece::GenerateKey), + Napi::ObjectWrap::InstanceMethod("decryptKey", &McEliece::DecryptKey), + Napi::ObjectWrap::InstanceAccessor("keySize", &McEliece::GetKeySize, nullptr), + Napi::ObjectWrap::InstanceAccessor("encryptedKeySize", &McEliece::GetEncryptedKeySize, nullptr), + Napi::ObjectWrap::InstanceAccessor("publicKeySize", &McEliece::GetPublicKeySize, nullptr), + Napi::ObjectWrap::InstanceAccessor("privateKeySize", &McEliece::GetPrivateKeySize, nullptr) + }); + + Napi::Array supported_algorithms = Napi::Array::New(env, sizeof(kems) / sizeof(*kems)); + for (unsigned int i = 0; i < sizeof(kems) / sizeof(*kems); i++) { + supported_algorithms[i] = Napi::String::New(env, kems[i].name); + } + func.DefineProperty(Napi::PropertyDescriptor::Value("supportedAlgorithms", supported_algorithms)); + + exports.Set("McEliece", func); + return exports; +} + +NODE_API_MODULE(NODE_GYP_MODULE_NAME, Init); + +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..f0e948f --- /dev/null +++ b/package.json @@ -0,0 +1,51 @@ +{ + "name": "mceliece-nist", + "version": "4.0.1", + "description": "Node.js bindings for the reference implementation of the McEliece KEM.", + "main": "index.js", + "dependencies": { + "bindings": "^1.5.0", + "node-addon-api": "^6.1.0" + }, + "devDependencies": { + "tape": "^5.5.3" + }, + "scripts": { + "test": "node test", + "build-native": "node-gyp rebuild", + "install": "npm run build-native || echo Compilation failed. You can use the module, but native bindings will not be available.", + "build-wasm": "cd deps/mceliece && ./build-wasm", + "prepack": "npm run build-wasm" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/tniessen/node-mceliece-nist.git" + }, + "keywords": [ + "mceliece", + "pqc", + "quantum", + "crypto", + "cryptography", + "asymmetric", + "kem", + "key", + "exchange" + ], + "author": "Tobias Nießen ", + "license": "ISC", + "gypfile": true, + "bugs": { + "url": "https://github.com/tniessen/node-mceliece-nist/issues" + }, + "homepage": "https://github.com/tniessen/node-mceliece-nist#readme", + "files": [ + "README.md", + "binding.gyp", + "index.js", + "node_mceliece.cc", + "package.json", + "deps/mceliece", + "wasm/" + ] +} diff --git a/test.js b/test.js new file mode 100644 index 0000000..e749fa2 --- /dev/null +++ b/test.js @@ -0,0 +1,184 @@ +'use strict'; + +const test = require('tape'); + +const { McEliece } = require('./'); + +test('McEliece constructor', (t) => { + t.plan(1); + + t.throws(() => new McEliece('foo'), + /No such implementation/, + 'should throw if the algorithm does not exist'); +}); + +test('McEliece.supportedAlgorithms', (t) => { + t.plan(4); + + t.ok(Array.isArray(McEliece.supportedAlgorithms), + 'supportedAlgorithms should be an array'); + + t.ok(McEliece.supportedAlgorithms.length >= 2, + 'supportedAlgorithms should contain multiple algorithms'); + + t.throws(() => McEliece.supportedAlgorithms = [], + 'supportedAlgorithms should not be writable'); + + t.throws(() => McEliece.supportedAlgorithms.shift(), + 'supportedAlgorithms should not be modifiable'); +}); + +for (const algorithm of McEliece.supportedAlgorithms) { + test(`properties of ${algorithm}`, (st) => { + const [, n, t] = /^mceliece(\d{4})(\d{2,3})f?$/.exec(algorithm); + const m = Math.ceil(Math.log2(n)); + const k = n - m * t; + st.ok(k > 0 && Number.isSafeInteger(k), 'n, k, t should be valid'); + + const kem = new McEliece(algorithm); + st.equal(kem.keySize, 32, 'keySize should be 32 bytes'); + st.equal(kem.encryptedKeySize, Math.ceil(m * t / 8), + 'encryptedKeySize should be ceil(m * t / 8) bytes'); + st.equal(kem.publicKeySize, m * t * Math.ceil(k / 8), + 'publicKeySize should be m * t * ceil(k / 8) bytes'); + st.equal(kem.privateKeySize, + 32 + // delta + 8 + // c + t * Math.ceil(m / 8) + // g + Math.ceil((2 * m - 1) * 2**(m - 4)) + // alpha_1, ..., alpha_n + Math.ceil(n / 8), // s + 'privateKeySize should consist of delta, c, g, alpha, s'); + + st.end(); + }); + + test(`synchronous ${algorithm}`, (t) => { + const kem = new McEliece(algorithm); + const { keySize, encryptedKeySize, publicKeySize, privateKeySize } = kem; + + // Generate a key pair. + const { publicKey, privateKey } = kem.keypair(); + + t.ok(Buffer.isBuffer(publicKey), + 'publicKey should be a Buffer'); + t.equal(publicKey.length, publicKeySize, + `publicKey.length should be ${publicKeySize}`); + t.ok(Buffer.isBuffer(privateKey), + 'privateKey should be a Buffer'); + t.equal(privateKey.length, privateKeySize, + `privateKey.length should be ${privateKeySize}`); + + // Encrypt and decrypt. + const { key, encryptedKey } = kem.generateKey(publicKey); + t.equal(key.length, keySize, + `key.length should be ${keySize}`); + t.equal(encryptedKey.length, encryptedKeySize, + `encryptedKey.length should be ${encryptedKeySize}`); + + const receivedKey = kem.decryptKey(privateKey, encryptedKey); + t.deepEqual(receivedKey, key, 'decrypted key should match generated key'); + + t.end(); + }); + + test(`asynchronous ${algorithm}`, (t) => { + const kem = new McEliece(algorithm); + const { keySize, encryptedKeySize, publicKeySize, privateKeySize } = kem; + + // This variable will be set to true synchronously in order to detect whether + // the main thread was blocked. + let wasAsync = false; + + kem.keypair((err, result) => { + t.ok(wasAsync, 'keypair with callback should be async'); + t.error(err, 'keypair should not fail'); + + const { publicKey, privateKey } = result; + + t.ok(Buffer.isBuffer(publicKey), + 'publicKey should be a Buffer'); + t.equal(publicKey.length, publicKeySize, + `publicKey.length should be ${publicKeySize}`); + t.ok(Buffer.isBuffer(privateKey), + 'privateKey should be a Buffer'); + t.equal(privateKey.length, privateKeySize, + `privateKey.length should be ${privateKeySize}`); + + const { key, encryptedKey } = kem.generateKey(publicKey); + t.equal(key.length, keySize, + `key.length should be ${keySize}`); + t.equal(encryptedKey.length, encryptedKeySize, + `encryptedKey.length should be ${encryptedKeySize}`); + + wasAsync = false; + kem.decryptKey(privateKey, encryptedKey, (err, receivedKey) => { + t.ok(wasAsync, 'decryptKey with callback should be async'); + t.error(err, 'decryptKey should not fail'); + + t.deepEqual(receivedKey, key, + 'decrypted key should match generated key'); + t.end(); + }); + + wasAsync = true; + }); + + wasAsync = true; + }); +} + +// Use static test vectors to make sure that the output is correct. +test('KAT test vectors', (t) => { + const vectors = require('./test_vectors'); + t.plan(vectors.length); + + for (const { algorithm, privateKey, encryptedKey, key } of vectors) { + const kem = new McEliece(algorithm); + const receivedKey = kem.decryptKey(Buffer.from(privateKey, 'base64'), + Buffer.from(encryptedKey, 'base64')); + t.equal(receivedKey.toString('base64'), key, + `KAT vector for ${algorithm} should produce ${key}`); + } +}); + +test('Argument validation', (t) => { + t.throws(() => new McEliece(), /number of arguments/, + 'Constructor throws with no arguments'); + for (const v of [undefined, {}, true, 123, 123n]) { + t.throws(() => new McEliece(v), /First argument must be a string/, + `Constructor throws if first argument of type ${typeof v}`); + } + t.throws(() => new McEliece('foo', 'bar'), /number of arguments/, + 'Constructor throws if more than one argument'); + + const kem = new McEliece(McEliece.supportedAlgorithms[0]); + + t.throws(() => kem.generateKey(), /number of arguments/, + 'generateKey throws with no arguments'); + for (const v of [undefined, {}, true, 123, 123n, 'foo']) { + t.throws(() => kem.generateKey(v), /First argument must be a TypedArray/, + `generateKey throws if first argument of type ${typeof v}`); + } + t.throws(() => kem.generateKey('foo', 'bar'), /number of arguments/, + 'generateKey throws if more than one argument'); + + const fakePrivateKey = new Uint8Array(kem.privateKeySize); + const fakeEncryptedKey = new Uint8Array(kem.encryptedKeySize); + t.throws(() => kem.decryptKey(), /number of arguments/, + 'decryptKey throws with no arguments'); + t.throws(() => kem.decryptKey(fakePrivateKey), /number of arguments/, + 'decryptKey throws with only one argument'); + t.throws(() => kem.decryptKey(fakePrivateKey, fakeEncryptedKey, () => {}, 1), + /number of arguments/, + 'decryptKey throws if more than three arguments'); + for (const v of [undefined, {}, true, 123, 123n, 'foo']) { + t.throws(() => kem.decryptKey(v, fakeEncryptedKey), + /First argument must be a TypedArray/, + `decryptKey throws if first argument of type ${typeof v}`); + t.throws(() => kem.decryptKey(fakePrivateKey, v), + /Second argument must be a TypedArray/, + `decryptKey throws if second argument of type ${typeof v}`); + } + + t.end(); +}); diff --git a/test_vectors.json b/test_vectors.json new file mode 100644 index 0000000..aae7b99 --- /dev/null +++ b/test_vectors.json @@ -0,0 +1,62 @@ +[ + { + "algorithm": "mceliece348864", + "privateKey": "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", + "key": "tPn/HkOQ474LvOv/mlJa6DsZEhGJaqh4bOi8URyfeMM=", + "encryptedKey": "3vYZCKcKMJnkW01dkZV63nD1cdIQ1SXWVdtylFFfkdl3lfI1NhW8fN8TUCGB5bzIyav+8xgZ1m3SdgNjaU94lgImSj4kRFaBoBg840OiJk/f+WyCqzGK6IjRBdUtWbwb" + }, + { + "algorithm": "mceliece348864f", + "privateKey": "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", + "key": "S16nXdUb5WvnOfbsa6vCy+U4aDMDsFk00z2TJW0atu8=", + "encryptedKey": "4gW7KBTe0VgoZPKx0qJjl0Ee5OYfaZj/Yc1V5MT7NauZeI0A9C0tO3mwggA1dJd2yqgnMLHr4rgSMEJPy8uLWoBLD6MCWxCBdUVvgPSr0XhsXbAsZWQzPen+Z+1Kktb+" + }, + { + "algorithm": "mceliece460896", + "privateKey": "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", + "key": "Ey1HfQwkMGGBxq0BWQ05vpskBO0yzL4OsfFpaAISzBw=", + "encryptedKey": "z3jEKjh5Xg9da6w4rN7mxMlTb5O8wy4IuM4LiG5zeqWtUcwOLluRdrZ/AyfqEXM03NVmStz/s58ZMsSYshClbrXJ6cfF2wPcRsXSRQ0fBcFSUzvjCqVE8g/xHKwf/ruRnWmwM2QqwKvBwXSvy+nyJDOl0+IEhiGnmCzAjV2eN7xlq+lt+KZRdYiUtuWKNOQsuCeYvj/Xs9lt4n5l" + }, + { + "algorithm": "mceliece460896f", + "privateKey": "fJk1oLB2lKoMbRDk22sa3S/YGiXMsUgDLc1zmTZzfy3///9/AQAAACgbkQf2H6ITHgPSCAwHtggJHMYfrRkkGv4M0BZNAkgQSweZHCUfwwpcBLwWphHNC9EW/gdGEtMQlBikFscSgA9dA5Mefx9HGXIYYxoEEtsSoQplGssXrANJH5EYYQa7FN8P9ADOFjwB5ReqDQ0InhD/AXwT0BT6GmoM0BhdFTYWlgUyGn8Hah+2FekeKQVqHVcJpwcWEQ8KOgybHasHrgjABsAEyBVIDI4JwR8qHEwe7RCXGUoTJR7HHL8A0QYTGhjFN6Sucs/auLBFzGwg9fKkcQj/b6S3e3iTXzgk2kQXHJ92jcaMqgsdDDA+Ud1S9SOWI20w9+M2qv0Ax+RLAGU4ZWPDn5/hjuOr2J6u3yt5LBqwZ8KbPAU3DfWElbY124riiM/maexxiuz5LDutX9pXdTPhY5GzonFSSsmRkUzd1ZD3GBeVkFKTBceqnk1Ax7Tv6f5q/ELxl2QO+KEtxhD70jeM5AjqDUX9I2a5b7fkW7i9z4ACky1Es+cq3jemFwAleGLQqcRjhsI4zOsIYGx0byw3f5qukCQzyBHvTtFeDtQq03TLLae9KQSI/ZsL6+wQE4wXNL83INlm5sob0kGRlPwoAs4chqxZywOJBY1MAFQuH7p256QXe6x/RzS/0N6f4jxdXitTVs0FyvneCEETqVMCsUb2Vb/Yn6wuJmiHrJu9KvweqUYEjCJRLWOqeJBc4WaVPxn0/Qy+HsQ9rvF/G5LKdCKSr2tH2CFY6mdUzzj+jy6o7ygrQi1lDwpRWnpf+PAO1koqWHpxBWmw+l2CrHEnaukWYzwbe+zByhst80exQ27z/gY4aFdjwwa4BkGX+F0rVQoYhcdFU0Dar0jZ10FrWY22DUkNggdAi1M5v1bMQGDHDcI+7DQp8+naBQjRkCjiAhTOWCZUzxT2+9gtEomyNZFHDb+r6YAVZI4msPnNQqiIGsnW3zUoNy0ofQ4pHJ3x+5YIAfwYxbikeDqhDqRAEwxii3rTWzKAYafkLaDcisYzgMTGKw/PRBe1NKoGmzDPzu5ATMSQgLHQVxf/fDfoWqljfpYidK2JeOaPVWfpj4HA4fi5E/FZztGKF8lKavUU+yvZB5yyL3Bjj3QjcWTZCHxnXIosXQ3OA0Ek8qobKsDPD5mOVMLMVxS5xC77U7WDEBf8CtkF3yxrvkwHo0OT07CZo7xUuJp5JLLWijnTKg9A7jgGyuHnQbtX6Zut/ZIubHmN1hloBzzecdN9U7Nr8t8YwR1872OYQSkuHSaKdm0yB+agj4b7qjjjyTbwmL1gsbeq5mme0MdfIOsYtPeQDrmDyESVsxFcTCxWU/QuLdKJPPnCWCWT2Ek7W/1PvHFDd+b7AGXFmymonhRRRws46T8kK4QrLpSQR5AL7Emo76VKHpvSwV/FBTCWqz9mNV9SQAbfwk1ZodbWhmWzqehJ6PsmdfuYBnFmp0875uxOrjlAT5HT/oaGBgtuM5aprMBifqejwOC/F6lKicX9BFhiXeARxRRdrfKqgDV3jbRe3vAV2ncHSpPia1pRELZj9zJo6IG21l6P7/vufRxMVTx4RhKhfLUDXIRCloY8wc1KTVQyq2idYK+XXdxwKnTYTLsXuHoFzufqYkIejK4gyWDuiIJxQ6eohJE0Wiksld1/SaGVsg+YCYZqZeAfvyfMj1yx6Vmhiey7r65G/9xBjURp8XqTsARKuVNSCw/9GgbWO8g2CQGDlGd9eIMXcuYjLwp/UovSV7VJ1VRsIosaNsrRZ7Gvmrm3O6W6AZo3ci9WHVmhCvTrGINApLeWQOL1yXDP/0cDpgcTceyLc/1Gylpv3wTGOellbUH2t5oVq/yx1PFzix1Db3wC9U3myi2gXBVcO/DehTSgzJgUmzCuNoxqbeLXLgAqEiTJRYZYlXJCKt70vzhgqAr6NpU9jcnlLIyEhrmWT4nukgzq3qbmZJc2Yg1TOlZEdXcYNma0Wk6MiGR/ijMW0MGlGKQG1GQ0eJFoaBllQ1EXE89SHuI5ByPUimjK2ACRkZW3yXMPHlMO0gqvk7om4I8bSE1Hrzp5Zl+J2r35oUPHip68WRRrRU4JPbZSiv2nSOv6OADePHJQ7tpEm0kvp3Dl6r2siVjxE2ymhiwuLnrcwr8HhFbkox+FCkIEZMW6Rls1+i3zgaCPQu2wLOkuIEi0vGQm0qzB8g5YEoTfD5VDlsY9OrYyf9pkjNacKXfNjsuysEktA7eR7cgcfSKZslPnPyApRxNGLKGc10M1qVXpy7LBEwDytUu5Wf+bcE6lGvSNO3EZODtj6KpmMcw+QXd1T7RtjgBtKl2LjEyopYz1J9jM3hD5ydbdHNoP9CCNafcs5169SuHpJEZbzdNNVtdBlhTheSHqGjUx+d5P66ueIDWjGyI9baJxPiPYqc9PbP7xVZBmqc9tkBbmiNDCBeuwib5PspbS4C+p/KeUaXR4Epix900rnaa1Sl4PrTZNlCef0Hi/76ej4XedbkXqObVhAhf70CVl0EZ/dqCa5c51RigUOZ949B0q5KCoI77d02OTttMbaP94tYr9xSSjyJ1oJgd9b3Ox7GHHMGbLZVdMt7nk6wPcis+L1s6HyL+8Auxz5qMWpGHU+2oznlJA2Go9yJs7FwmOBbFtwagzSBO6qYIYKz5e8jGoIq0OZcpqtIZX6gQYkX94me36K4bYkf4UmUsUbN0Ak0byjWowBuzRsp+EciNvAWWty932Of29On0Kxa9QmhPFWgqtPHJRP5TJKEJ/I0ktszJ5gufDXyNuXk8uPV/atKaV/CdipOEr8Mn7EOpz22+71ppkMpu4Simmhw4/p/wXH+Kkfx2mO8wfOMtkE6QjPCGWNfz1rD+jF6CWgln2a7/NNy60vX1jnhQjPUTBEl/JNJglXjiIUlcAMNRtLu6RpWhuRKZsXy5lUFAy7kpd/uyfA33iawUjEpC2fU6Hmi/31ilBO8wcOlFpTZl3rB5ppJKzbHKx5xLQBZrBEgMDAAAExK2DCPWvYw7XBiJmUgaBXpskpNb3qw6V5+ylkiIhCFD0HBcEzYDCVJ6AbHOUAmS9POy5tMQjyh2AEPIFN87loBAZJR3wy+Fh+EfMZeQaIv7E3b0xmJjwjnpPdID1p1CUqwor1ilEqaIqEwMy45LQDg69yNiREA4u7yGi69NVhtXv0pmrqaLU7BE9lEwkuHIXc5C2XMcsS43sUv7bLRiryZIm0kvjPKWGXWk3RfXxPAg1DUGFPDVolqKj7Lv9UY+z2diAmBPaXaNv8Vn7w68pAL62HyqCWF79OAElwn6jA9qlMZxGF/WhSyW+airWG962IoXfX+vuCU79w8W9nW74xDExaiG5/2lW09YXoCRtSRCAuSusWbOHUu7sU3V1pPaLe7rrEssVOG0fFVk1iAkzQTSePP9/eHuZPpa+lOT/wsf+FJLs9K/YqKfJlaYvEloGGKjiHdLq+cltbHRQxOd214dHCY2g6vdA5sfCtwJ4SzZgJpbpM1Pr+BMnb3dqOy+wKIPsWTBhCAT5nXWm7Dg0YWgkr+TDN2HKZiLKOGL77/nLv3UxxI88ZfqSLsENK82svLWXj3SiAqoqTFBp6y/7eGHhobHZIZ5Dslx8TM9ymHMOZU/T/R7SxgZcTDicQ2nmS4yxLnQA5/ckn5nBtGrA3XMNaUUe+bnzeVOe12kAAAAA94RzAKLvROO7G6T5GMDhDNRHNopW5hJJ0mf9/xBPAEB113YYi+gjCppFgLoIHgzDMviWH4aAiucx+abDQ3QRTIiQLFqcpo3eVqMdYM28njgmCF1Eb+q/oqSw1T4og+a9T8Om4hYTOqfdWbWxHLuPgDjyl3Tsvje+alTCkznZcOzuBvdrU6kVjPJG2bQkH2nrYODqTcSFJb+xsUdkijhzb3QaRR7c7ZYNpJ1Qk0sQQ/qnUm25UWNZTWX/6Q9OPBgJs3uvCJrCxM6fzaePycSDFia6K6FI5DNForf0llrxAjpdnK+Q+tSEXB9s7wC177zSJbt53u6cSDc2oeT995U+D8a2ZtGCwqvALC3Dl7r+dkVTluvr7yvMvQKte6uGNnHQN6b4CWJmPONI17LJeZvy7Y0kz8H1new26/QcvId7ZV/IPjs/XW8G6VuTVY0EMQ+rHKNKfDBz/ToplfG0UTIk7SOLMfxpOW5HqgzGkhyL1+CWY+E+zienxJ6XLWdztgRUo/V+7SXVgQpOPS9DL78Ich5QfSxsfg73EffmpMfVKt2OA8LimuaqwovCK7J2hzjtqaW5UDzms9jfjMA/SSOXU8WSJTWXZkj2yIChTvL6uwI7dhE+r/CFwH7bNYKT7ZEeEGknPfHdzqHpCJEyFPTdoOuAfc2qvQoJOf+1zAAAAAAAAAAASpAhbAgdHiBTRLwgAhIJMQCXzk4edPgNFbUiYOKdjDlIocGSLSTJSuMu/RalXxiKF9dfWsMb5GpTENxOfbFEDYvwbjZHaZZ3Xhovjk1HkgdE4RnKNGdHHiUwvDhZ8+9OtoykSFfTGmE1PsSsdDJqN2XcuXdKulGzshZjix1I3JcUSeW2MeaH7BHlUqeo5deWkn2qzKXQZTmcqgdJEeogOx6bXPPNfLfFMIyIgFNycGajvL2prvk1m/OPIOVBVCJgkVZUS0RNJhJ7aCSWqJE1peHU9ZE639fEHghQzI8FtW7etWmyUG80KiNBneedcvObfcBxJECyXMUF82YZuhbvOzAXW2vZpv5TByQn0Ib+MuqoOyrK58wWCtdA/8m8IHUTQKRMFTIPcwtPOMCNDXtdwczm9FrXiVVxxuXFCcsAvRS1WYkX0Yx+YBvyDXEhaZmFaW2ltdb6A4VVkiQ+mzjP8jp3s2R9G9MsRCMtD4sQrq2vsn2rON36dcsoUzhM0826rzKJLwA8dMv9ZQB8BSHcosa/zHhIQLOqoGc0qkbHlnGsQWvbE3dkbf224u/Ax10cL1mGSI0TyEQlfyjdTbUjTgvZGb6cxab0K4oRMvT7Idw2f5xyBmooskG2fH67iGvoxP4DCDfnKvQMDP1lDQGSRmMEIYX9V4FdAAAAAAAAAAAAAAAAAAAAABYcIiCxwAhwhAsY4AagHCNIAtAIicnRnasRjYA9rSi2xeBJDAIJbCFMGgVM1nshOzEMBy4zQb4DpFa5z6VAigD0T8M//16mvFOQHBMhlACfYcv6qZVkEmEhbFdwSKwiqLsDv0WYpMB9ioBejQas6M/fWcVvfkb06flDjQYvwNg56qNUDdHeaMRNryj7yagBzGAiEgs1AVcMEhMG244AenIuoYw3gpEK25BEu2wsLeeN7AaTQNhfVw/3UcxzDX66QkQDw7Z+rbwMBLtD6i13URPLLRJmFbjKxSI3UEM6BtdJt26TV6kCBZGhpQVnogKerPwgL80oZlr4cNd9Ml8tAzcRYkzP2sCw/jE8CYn9UHDBFTs61ZI8xhyH0jjd3BR+i8itRVHviu2AzljvaVc79LBDJndjp5hhdjNEnPOhQPUQ9RrtlhuKFLreJ4EFJjnFClzF1dkFdgc1ATk6EzahHlbD1HPY/CEYfI7XuDxWqkuyCF/Xy2c9giXVlMTe3D7Zl6naWrrAtnnwhUwmvB/WQTAsIMvd2USTMeFBwBqo+v2Zu4YBHGX8jZ4woO7JGKny/WZXrc2FdEBPubV5fGrIrmbETIBEZ4k5KHLFFG5qSLmze3QD96NUpEYDy6C1ixiLGSZjdiEM7Or32hXmJ0zfZngAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABECIlgYIWIGA5yBYDHsHRRJC4IqWjwwF9InIdvoJzAHUSJQiyAtOEIsbKWo9gh1DNZbwbUDVhnYGhAAbyyng+QSAco8cGQrYvrxYMvcM/CGZ+ZPtYKIfWNYEiHFunDFUYJhHRKytOAHymIJMgEAJIJ5Z05xSC9GPesFmvYiMZCL0XDQnaLv26QxQIkR+rRlAa1Mqx2ITMO0Dy1FICwg12tVxc5z4DXgQ4q+loqO71Pss8EM8B9exc+hulCEOIsy1pbSaqIAlyFFYjNYW3TRF6upLIJ8wsjOEaRo9XLqd99Qturib0Hbnm8oGZUduR1MoLJyKZDAJSiHYAyWYXwb6D/DDzm9n3bNLiJMZDMFYlymvgCGba34sPiUs2bWw6Egp6VW1SCgaVk16BKzPgTjh6lz2DQT8hOFWHWA8QFlCiCIEyCSE1BkjWjKD7Ngw+keOEDIpwDqk/uxlU+GQXYaCt+uWxGobcJlPh5lMDRZnKsYEVbuSEUIZkCyb1SeRhuK8tfeQ4jwur/oXyDDQhs5UzR6av1KDRXfe2CAz+nBz+CzhyeDwjDeLrYtNRPTwkc/eckNoB8+EWAcMUAQlFClEMrH5aPZo3v7sQzsGFvprNX/De3PDELxwL9l/AjZOqsS0gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACoL2LlFcJRBIAEFbKBAwMxCPkGySCVGTA0AAoj8ihgs1AhSNMKzCmdOmEIsgQRYsAAHRAyDkBeAg4EOaBhYSYAwMRcZFPRsWn9ZTIXdpG6rKEkwgJwFeZpfKUkuF2jgVgKRzSSaKEj1KspBG6FUfgOCpJDP0JQDCiJHizByyfpC9dnxEK0WYvAhMyyEIQkZ0isbgCCGDlcSEoBMV9lMq57vU2Q8AiuyBLaozR9Ga5NphOiKBBUAqktACJCWtHQvVHjlx24vTSTCMH2QExC1VfaKRAEYvu2faGQg9ChR49hH0VKdBjNsZVa0LIAwPyQuDkp99OjVkb1CAZs9KDMl1wUzdroHEgYNnhMn6RS9pMMpVVG+MFVDeLEB0hIKAMEdReyO3a8+Aj33j9saxNEzq0m6sRIFJ0gzR3HqQUL/QpMRKdBdAeDo8QiX1AhzOMSEoCAlZO0+OPJFYvfWergGOIqTwjZV7INtXqlg7ZKGF1FRXg173BBkBGt41nesUiCOah19UXgLE0RQuXbglp/N3vgFfHJXu1V/xcPj4wsd0PW842WdUkBuBr46GBo0JZ/wlAuX1wliEnrtF80hVuSq0L6AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADEgGVlhNAvCJgIATwGEUVOCoBJRCNoxMwMYC7ABgGE4IEkFEQUmFZACSKCCRcC21GUXsNtpoAYACcADREDzNEFBgkoiRlKKakQQAFQBxtoARFqmCBCBq4vWhBEgIKg8mRayIwwFGZqZQYABTIlglQBgDABFHpIEYsNwsAHBQQhUKOYTFEHKegiBFpCAEcZJGyJRuJHUkqEJBOBaqSBhnIQooeioQ+mggb+QlDnpiWoQkJDiUHkoAYBFkH2jZkDIkAgF+FBQmaUSwLQqw0EejUBEn4AstiIIvqsYJMBlKQYQKutVGdGQPEygFFwZlyYLcao7B4gEbkCSAKcKi1gRrXCGwMz8ANtHyvQkD5kzp04ZMwy+jjBNCtuWFj28PAI/9QJLMShA2QefB29U0AE2cUFDGGxvD5pOVRGwEEragLJtsJ6gNzpkpF6E00TbfwMmoEvGTLNTA1JOv1LRvCY8jvQNRlKREwBUKoyKENUwWLxQCABUcOaq6hWfShDMHAO2QwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACWbAQODEAUhB1FHWQYEIEX8I/IWlEAIPYNilS0SpIMAhDNEEM44ClFieBYACIIVACKKABMAgAgAIBZJdwhFh5h4iIhkcYEObAgAjkECKnsII6CJACtOyJcSFDpMg4gksgDDCxA1YAAbSjyNJQsHCpwYwCcHwBiq8MwyAs4YhBG4AoAUwUIolIhFXwTQAIZWEMoMAkkxbksACEA0pRCeBhDCUmQBqTRYkCAVCsIFCwMUFcYaKgYkDKQa5ACBORAIpIm4BQCFC8xCAAB4J4sAhQB3C6AzIc+1HkpmkEwToawywVVGADGU1EgsYE4UIIBhn/ZB0IGOBAEM0AwQUAFVzwCt+YiKLB1s8eRuvmz4fadGi+CTJwI/164olYqmscAIJ+I5OQ482GbqY98mlScXp6ouwaEefQxiuhVvmW9aP9tDKY1zsEGWSKLwJPkb5b9cJzwF9HWUbQnF6v58ihlMulzEMgZTkyKTHe5X/zlY3sFFbwKpcDSJhL0SSh/O+tljuyECHKoG7ADR6EOSOmU4djsSODxvLfVsl9+kuQsEt1rFGM/TerdtGLDW0fgLMC3SbbFzXPhtXHg72lQO8JYWp5hUEntBMDv2crFGdE+KVexZTUdejO0Dn7EjWyxk6pBHgvtAnA+IGW8z1iyDsaYGHXLb2a8DzWLm0OzZrzOgvk7uiGJ1RaeCE9yjt/G3LosQo3WbZNi/2ZgR+/5/y2d8k1oVgu280uYMMY0meTh/7Fi0zUpKDWfiqq2s8WAQAOoEmlUEqs40TabcPKxmcEbUp36f/zke/yLxcpHgg1bGkI6vLuXNQu5XkuY0qBJWx3FfunDGxj/9ETtC3fjwEOV0PgCSsClr2cb/ODcc5+TJpwHF3HY/glgbAyUH6we0nglMd8scPQEI2uMPNYSWzY8CkfkEpcOGurFXzGCxDRHrRWtvzepMld/gORRe0wgoMUlb27Jo7zPG/CqObLy0qXln+/g0Hcq5PY2xaqvfTQxRyOLNLChyshLW9e4UB79NMcOR6wjH0l7bPapaLkNCFdsm440s1f+REkZ8i8olQZJqepkx82MqJLzH2oyj83/cbjcRpG6Q5rt/uonXQZqZemZp4qMZPDIIAXvXhQqO105BYT8uDKTabkusVuygAWEvvJNYwi/94YGTECmD3R1fA4CKCVCylKxZDzzv2Wtv7IOBVj/88mBj6IShd0FJs7fIwFScEpKi8CD4t5tGTiibzZcE1sNHWiLFSG6rwM+IXeM12u3PPkmjjIhdyywzBeuUcXs2XVPPrPUMLa647z7uGX2BOD33TMz+YlLhs9YGT1tWPI9ralLcavXZcH4llWPLHQsFmjX69IQeVvLXDCASNgR/jGA0gjn1kInDuB1QeMqx7kwQ7zgUsDArMCVyk2PCPBM70qRetGzI0uaPifE9oPxoe6OD3ao3LlWTULAHSqvRVP6v0FkrYSool6CARUbCjW0he5tCsVNGyv9BFPYaKIPeWspwvM9SQ21dn7exsynpYgjQ8bHXHX5BxuiKP7aG5qaBvd681iOlRjXj4pLiOu05yL3guDhVWgoGhcdR/Je+UAH9zbbLnP+83j6XIXRAcjt8ncs2xOKlhmCHR6JH4s8jdwL+FExsJAvoBf9hRzjfuCqPL7zFSQx3geKzqyrqzqHWUYrjv9g4Wv5PKL8xeC8O8xWPRTVkz6uKubX1Cq3qOGnJYS8UnRRFXuwsj2B5g9E69zDFcut80qi0/up2GujLk2GG+MI0RLCjiFpKNF08C1cHYjfQwah8EfhBq8QgziCxk6xvD0LBA6DxGNBYqyqD9C5k8ecHU2/8z2X/vEG+ZM526JpiSnijgjSJ8VhvzyOdeSnK+uwcqOSwb2OwG4DYrDcbZTpeJLFBuWe6TrGg1Y0AZRxf6UqdBsJtVgtePNHBjHomzopJNVaFPxsbk1Trwfe6qzGDEqpxJ7yyoun3ztW8zbmucrWQ9YHyp5Nqm8w3XNKJc2BRxXF+vaczUQX3bTN3Ntlbkt6t6Zo+3+msVU1ZoF/XjN8wGf/haAQORoLOZUOi4qKIUbCy7yvA4dBZZ4rbCX/qMjDCBw4mwf2fu9cxFyMuWGHs+fRyp282zPMbtWTLDc4wPOHcuzwUZpT2i8c3a8RY3K7b6Aj3ET0Oler0QfQoHa3uP77fl7P+LjsRfbiQp7kQGrz6A1pBSkmW9Eg5u5mygtMIX6GOGwv/eamlY7TwDJiSIAdBzFIXqo0SE8S7nS/aIU9njsTzNV45vLbnzZ4jn+5TdKW1W5sQesNWA20Ydx7SODz/ovavCh1BLZCVaCSWeEI8cmyJbszgPdbcuea0xSv6k0zmyX0VIkOGTQqFeWKUSOInBzfrdQ+UcZaQMzQ59W8IomAxrfToU50MtnqN5wVtmcSovpaWlr0nLeQ9YSHZPobO3PU+hPEZ5JJkkcfOM5hGoBBj8ZR4HG/aa5Z+xwYCvfSi0kjVOt84ElT726zdcQoKtN1NwaWAqbyY/jXu39g+q6gNktwAvo2/IU7ryCYJpmUHZLw7Y98mNlQh9b4SE6NLraFL+hZs2fZDrOnEnghPxAdYo1wY6IFAqPoIExJOlBz5tFd/PL9ifnCiRVhMovxqSJc6Ht3UFgW4Hgx+WZVRmUlbHDcBmfMofCxCww4DRtpCNKIuUihJyT/oZWXSvW/6GXUPOQSL9oHmiIV9PcE9sojOfkFOldIu0CORCEa6hmCSw4o7f8FsRZ1RFks5DqehNPSlyZpIcP6yV3C0zllosYembysai6yARU/yErwU2uKhq2A557Zzsf2wqjIUQFl9rE946JyhBjaLjYBflbFXImewU/YpjBQp2v5XZ6UbHuAxX/WqrBGTCiQhHwvbV/lgiNJsjLtSNxd/ib7PXG5qsR9GyjBOoo6gnpyBdrgq9R7vNP/5PWxrUvfnEGgCztQwbO4MxCgIIs8lEztv6T3YimqhxcCvP3FaxN1HeHU1q5xmb9Ye5Kr/ES+I2t07MZrXIldXdBg1V5xFoYY3im2agx9M2nKrjhJOcwwOMYZBkr5P7KId9zraB/WE+F+Cm/N88ixINjkwumeH+2hf9xfaMjY8rkN69N8Z1a1sXJzP8WEilIpchJkGpFu9tr9BNtWFfeBFGSi83W7HzZKVzYxoBn4NNLaMJ0nVpDrtkGJHeNtblyYr1CwZg6iCbKoawrrlgW6cmbdmG4rWSVyVKC+DaxToTtCyaTv0Xdp/iX1GkXi3K27IjSoDusaj6Kx6yzCLnoqnjWSPXofgAtI/o9YJTXz6ae5gvk+N0D+JTw+nBpvBcF3Jsb61+Gp5OLzkaxt8PVILUpuvRJhd38NWwz4ccuzXhoOAeTrUyOxAInSXveynicaU9lyhR1hbKyMfzW1huonaDufMfnAs72TBqy8dJrS0qltwn1+TxML4Sg9SUYvwiErmUkiUSpl3L9lGCNjoj1fKPOiREgG/tBCv9FGs54Y1POOfsf50LjaxGMY3TtXGg4Ct//DjZh8NOdWkdFxiTE3GLfNQyC9aWjPeKg9tWlTiHfo7XjcwhzxcdDZpdipMjEpe3GWRGovrOFqgDPD6szHYJ/5FkGa/jp64sMASNdnSmtj6Ol2g9D4dXStFOe+BcZEatifqxCzoQfTENV0hYoz+5njZ/hmk+E+6dfcsqj8Y4VvUKK41BbuRMEoyTvQ5U6i6f9t73zsjFbbVbGOfq15UtSPhWr1aK0Wg5Zgw5SBawnllE8317UoVq7C/wc+ZhxWJwUXVP61M4/xJIjaV9xYa3QHY1/o1NIybKS6NxZMJOCpeyzCmFRFiAiadvBJ7OoMOfZj139i+DWZzc+Xw26Y8dMOfFkN0JCHFKj2Y2Ltc93K8+EZ289UfcYA6fU71kFDvR0cD0Rj2HKEPCCNc7cf/baEo6oyUUfXoD+mIa97Vir9De06TTN+3hnngDOwx8w7U47XUJ6qnHKu0UG2kq9PrZeHfa0fxR2sNaGx1yhcrqL/rZGgdRVZF74E3IV222vo/U/tAgvUS5OYlhP0eFGe3HJOEudgjc/8jeLVh0m7qbEb4g2HR6zYHDPhrgfqvoKUDTrMKNgPoTZzd66moGXcWGSLwe18x0pajWeSed8nCbozPmuy9uPKaeZPo+IDsts4reRQ4U+VWV0A6eAI7tmMHgcEFJ4BTeKk+KI4CZwBUr3+lxiS2IWwL1ZgqCIWqobF1+EHNhkJuMHtcwQUz0GqTSrbVDFc0MVkCN669Tn4tN+8PWRs7eL2KaTaUulFKcIVn8fowW7p5+UgNUxZY/fcFC6SvwFufxuyb5EJH789roUxwl2Nus3HCbRGw7P5zZvSeXVy3tgwgqLIAQpGoUb2Y5vCRjCPZXgmKMQI3PuPgSV6ygFVj2ER3Ms13tWFddFgCQsVIyV0/EQIAUdYuRiIlD5ZlTCbuzud7OT3Rqqev4f71sBw2dflP79UOL2Kh9k1ASMMjVN9f7crMBYEp3PyBLBH69GBf+VYjCFZUvSuu7jKoxSDUgwJNTO6cgGpfloNMHT/dmPSFtMSRFpVD9QlpFIYu7nmQzAMXTn1XmYx+Cm6r/tcOtqvxRKUUEZTbSEIBWpEuQFGE2MJjHfKynNM9+wlUFezRtM7OHg//1mjcPCOfQCl4Crf5nOc2M0P/KBJkAHmZDUA2RIKyH5mdLqEf/+tQH6JBcmD21DDpgY/egET1O01h71KI3EqqCZOs4CAQdiTgmu5gNRF5NheE91zdGV+tReqCm8RloLAkaba67jP91rYTkCY0YgetwZHnzrDlqLYxzytqf2OBgmmLEuRWCZtSBM4I1aCK4YHzDxmGFIM/PCZPTVi4+fkfiB30q/6I6GlAFIYqMTxnf0tj4nJSB9+Xu2WkfTFqkkLArIGJDYa7J6mzyCwAJym5sRoA365XxbY/q7f8mze5Qds3aSI81Ber7U1OE32U+K5xzOKIhhZ3J2QVMpdEkF2jdeIGi3UIn41th9ZCjBAvUOehJ1T7C+cUCvV8u3wSZLXPQGBSUNA57dGPdGvAlGLnk5QQnjjiy0rf66G8ByGUMODpMujf+5foadVCs+7aMpnAMyXS8hINs9fZucsli87TkI/oKDc9Rwj9QbkizUzPbUHCODrcWl9lMtnDSHuX7+r0Rc/v/9ObGveSoWDt5wN+g6yVo/RH9Xf1fWRlRndNsssoljNbO9YSz4We2xsKq0C07SmYdweUFwYV5GB7XocNY0C50rKWL5pXWgTi0L8nHfQ1Lvisntj5RP3qywLp/YlKEMFKMIToccm7ZarD3Ceap8v44rVtmK8kIaoCMwNY04SG+A2t3u3FXk4i7eP8N6oog/ztcPeRoBwzz1ySqSiWJKEubSUu/2ts6KlRDdKagcEmS5Y1k1FXqniWSLB0bnIIdCTD86YaGWkwPqoRXBHexfv4VtqZ6T/v3HzA6L0H3LlG/iiGY9eM5Kak4KAossz+ljFrhOCk55Ragocqw/fWgq+azNofmYSY+/RelBoFWNKzfpMcCcWyU5BKX/kdmunjwFDR6Wx7vqT99IJbCqBimlloVYYohV94EJoiiRHNHd8DSiwWuz83bAj3ZU0OkOFFEiTUPwrsSnPi1Bb92nNGKD8AXzGMQRZQFYXDof8Bm0CbL+6wxepPp3U2q2uMyrTDNiWPuD5AAJ+7qp7ZMqH0TnFIc7d8dD+hG3BMK1NB5BpAnQpK1pYNNT/OLxT36+q63XIMhzqtZsuzGD/bANmG8J3wynSp7WAZ500XZA1WmFUucWj0wOpNW3j/bcRO7l1uyrP/soTve3NvxGGtaCfUh/D8qBNrtkkgS2VDiKLzT5OD4EAAQXizlJjwzDNXZ+p7P262xdIDSdBbrbP8qSGqLpvm0mihP9UzXsIl1NK9msSaRWU/iq5PQXtbs1SbwZ6cDfet+vIblYqiWFjo8g2y8hLCFPm+UEoz3+JT8IzvzZTaxntaxFNJ/jbU9clJHHhXIeVDK1rhZLGU4HJKDiwiS9nMPDdGT8FDyImbftj4vfwF95l0ShEEZLTVFIft0wsvKVb8rHpLWnLERkS5vcDu1aTeRkCMC32dgGB9/ySj7bM/Z9M6hgKyczID0+4f0WwlN80mR+xWkvSaRgGT2ohDaR1AgtgbBg3cxIU2c3ZbRJ3nAEHENJhql1ILptI94kFIMYjd600i4tuRAg96lH8jw502MhBWmYCbgJZmlzDoRp02u7T9sgE9DiGn2VpJZqlYe3IkdsMCrUhquWqPyCV+qR+Dw2FDh/h4wir9J9nT7rW1AUQ5Aqp7b90ZLGy55+lVqCk/1GsfYdirIjWzc/qYJe9sqUlyKtPCmnau9w4nwxXQUuFOSOhliGXoCSyF3efLg/7de7edt2Vtou4AjE8lDsYYGyDL/QPi4DEw18qTSZXE6UjCoe/Ah6P2327LNd6hbn6A8l1zrQSlCnJYpVU/mLb5n6fJhn/mkWcFFoviHdZM08nOPDY6CBQizYNWLLZb2jTIPDbMNZxXeB46vXmas1nHHSeE15Kcjcc3Hz2nzuq01XzVEw6bLP1yCQmKbsiDS4PbtBtqaYNxHYxoWvaGP3jk5cYOANoi3tExEanQRvCFKEgnBVOjKgtNu1HurHKUmbkA3q8N1c9Vv69Y1EfaMTuFhipkQFDm46vo+Ly+7tcvh6uXUomyy/WsZo0/HujsGmJDJV2YyRfj1iNmjVl0b8UwAsOnSegWfFPU29j73PKxlJXMyqiAoJ8dqHji24QNUiFRp/nxwcZyLClRP0LbRa8BkXL5uFNphdqN9jklDSwbIzkXksVCifLRRWqZ3L/HroMSJxmpuN9S58bNK1TF3kMJ+F4DYqclLLh91m0/vjjMiT93c1nU8OHSWqFgYRYAo3a5YkgAz1xMV2/mMiNck1fjnckAFprRuPe2KDptl/wYwBy9djlwDziKgIkiBeWD+oAQZBNW5xtffQNzCb9l6WyKrj4ZroklXiTR/l5tXnZmdYnAkhajzmB9tHVlmEFl6b+TWxHpHsKOUeg3kewZGjkf2W6x1MQhwog+ub5T8GolwffYI6+fguHcr+PT/sQpTWNPZiPMJR14op+RIm7mjRYEOaJsuGIixFN9/9RWirQzfeBC9XMByk377p8sAYVzqvdQcd6seqGgfZsuHoPJ7QI6R5G1cWfc63PWkgaDWD04njAcKv+vxmmNOJbcSfNf7Wd/4LHDwo775txZzYUAD7TGCu4YV9t8HIRxifc1HrvKRGJ7mAC5XiBlVTpDhDwodF4ygtrkHtxpI9fkSjCioSZJsQr6HBM+G7W/v+tqid1R0x8SNNp4sL/wjqnYvirRgyk+64opF6g0sdBwhKilsVTlWBoWH5eUbO59EHXDvfEkiGIO0wfe/RcCPhro3JGyybN8xrIu+HpBuR4q10NbZNvxfSYAhI4U722EWZVUjTHiufBMDT8yXEA54p7x8oBhlSI5lr66rZHa+tls9yIL/5j7lM99BICx7wqnMjNnb19jga62QWYI/UvN8bECCNxoirKRfj7CUGFXoi2p4X7qlvcCJ1HsBWHOfg54wBA82gs/bgwRIdL9P/7N7GCUkojhT82x8McDv1+d9lZUlR6/8Xu/5vPfc20rQtGDQBAphaq2yczr+6QkqCv024Xuk5QJMpL/dA2CRo+6DrbFiIQGQlBiFTrkSxyctsnBlg4ALgpZ7LW4o6VrKQMDMLWY3J6EO6fjLQqrt3RMj7OZCSZdUZZOiFR2VIikn3ZrQsFJNsXBzAnP59bvOr6/ocEHZuGwQCmFUcnrPBwwhEJjUiVPOEec7CvHGDvr+jRXvzSD9Bcl0UMD6AsQkceC87kSe6AjOfsZZoA0FcCYtH/p9iDx9DLO2wNWN6/X+/W6Uy6D5fi0UBuY3osCXw60190W9UQ1snp+gYW1lyp9yTuJHYyaIbph24qMWWrfDVha/cX6xga/MO/58Ww+mBMrvMH2r8mZjdlbukiGweMrnQiwrdbvVOO6exNwPc95eG6V7F0rpUdbKvcPWuRN3HHoyPCs9HMYWfucxOS/l8rCzwsPnCpZvmcE2+U5b85qfMRiAieGb5BtLXNDWVIdaM/7upFtATYNp0o0wsfQoALVxBXJ0DjMta5uVjZYt4xxO+KKWmitjOhZsxgj6aID1wm3XJQpW5iL2w7v+i6ngfNXyisdcjdlBO2DcMgXHH2vbGQgpp4XMAxF3EDGw4e6RqFGLupQRLvkjurXkMRuHe/6y7Wt3Nf8a/I+Fxw675ijB/DIHnSPu02ui72n3KUp5t1WOGslQcZtx17ZC3j7S1GFKLwLxoUEqFKWiYjT+un7lznaObzDygiGPsPvmX99M2qgoe+UaExsZuyxw4ELZL7kUEuU29Foa5EqUIxfsCNk1NQugpEwR12HxBxKy3D8QDQE5UfhsxgmYjTXVzyR1brDuTYdWYgzDWGJotHCFZtSMhyIT5umJ1S+tPfTKg/QbNnUfdWr+pdU84KI1ccCGBEYPmhZMPuwdjiQBXhaa5q2Q5XMp6Y3ynlVhseBvTnH0oNk8A2CRI4zKg+xIZTJVBNEG1vs+WTIvoo8BVEKhZJRzKIG2edcUrzFpCwK5UWlevr0Dz2bTYBqv02HTDx27PHEMAIB3OE1UxQorabS5UY8K9kR9ynEAjIIgLab63yz6H7QWRJWoMWbsd9RdJLVRg9UgP4ffCwyZ3ewXcNymNK6zp9yMSftpr4uYxfIraINXpH4liUsWTV9tyCK9g59F1lWWGdWXwUQPcLWcmkdE2XMSK1n9qfgO25wqUzj7Ug32x9FXqklGTNBq9FGFg6IrD3iVD27SNAUFV8dGrbM5REM2msFZG5U30/xrXvCzRhhvYWB18OTaKLr12VScu0LVMkEP/FmM/j1CBWlHJj9MKZwPXh+d3877Sm8nG3Z85JRGQRZLXbPQZr93TW91oECjCFkmHCKyu5jn1bfvcHWFMoXkpjtqfeoPBMevQI4LV9yz0ZMeEQr0dlpV/PKFOwFQC/+CIBaXs4UtFn3xZQzLFbT2oy/omOpGqrx+rpLusf8ntR9hQks7auEnGesvQYUhC8JS9U9+nnywbTAkJ/8bx6+IFTdQ+gofyIKinMn/8je2LheW7qbOuY6M0Z94W4CINsIk8Tp/IBUfhFhEUqcp5/I4BSX12ggjE7y90k/QvKuD2OoqlsIfWg6evcbUPqZuV1Sp7rMX5H4eZsYpsBCGqJKQk/NWG4qI9xFBi70Zj+Bgc+S1jxzlGgpk4R0Z+TtagAUdOxwxaQEo0pyvhGdWb7qHeVumBGSo8eWIyz39rS34Rwj7/RH/x8F6SNULAFO3du48y/sYveM3iMQ0JBUyaTCeoSEgZ9qbrZWaHzPo2IAZlu4fmrhxkAA72i4CzDnEgZV3xPbKrABsg9swQjnYSfyTBL0/uLSPiZnADLk4t06uNrz3rPGoVVOs4ufwim456HZZD7EUGvaudOFu6pqVEm0KxUXaCuGSFGxr2ozs4knwfreeh1BGglvqWdDUCAy7AiEhWMwgDwrcNSAayzTg8cSIVhoWub0u/7KHlhTcSzjVToO6DBZhyMffmgCUF2nyZHrARgigwSRXjDjwnneZTCb5ie4NRkOFu+MUKiE0tvkz+LFmyu4bjMd+fjUtOMj9dze6bxk1ten3PXLmGIgVVmbDK4WflOUjAMrZTW/qeI9/6cLFOcJlcXqpNQHm08AK5qJX4Jq4T3ShKEyFvcQAwLYQ6vM5VbP8j+f9A1hk1/q8yib22aPCTkSZMpVG7EAGiv/G1xfxizmPiRC+nlFmj8AeFv7EstyNscDGzeH7+Y/3quzaIjxFGiNV93cOa3WaGNlxRepTBrz4My2wcAcn+URZieNEa/DpgDu2pFpdesnUAj2KSjeFYTNEvY0dMgIYFFdpfe9IwSWOkXD1Keq/HApGOMAdnNuyrDmPzgQfY/0T/5eYOWzjZxPkvkGMOHXS5Dkvrdez4XLCxdYfXlbmM+59E+pYNb1M+1K/I/Yze2ED", + "key": "ifa9tTmkbg3w2L477avPEaHQyPaOcH+XCBgmtaeKfqU=", + "encryptedKey": "vPPJji7JbxJ1QLhE9N8LF24kYMl9brgkI7ODOu/waA/Es/dY46b6A6I9hBnKC0ZBkaskXKXH4RLfJPznKMQLQU2i9rBYeWd02kY5Zqxf0hR2NQ5Gw8zQejF6M9wpEygJuqJVpB1kVtATAawIyUstVxSM6kHnr+A28X085i9G7DHH/rB97Rdn+GE4nsiRgOEHaYr6+gl2OB8EoMoG" + }, + { + "algorithm": "mceliece6688128", + "privateKey": "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", + "key": "ezUgCoOHors3Y5SmhHPnq+XOOSSE2r5sHvDuLNn2gCI=", + "encryptedKey": "ASePdACXL9BapjaKT4ZiSXpaMaPpaL+BtJ69+4Mxdp6hu1J1rUbTP41mJMLzBflh3IgShQsgwv48fo+wOTu7//wEWKAXZexRmrMy2pUgR7iofGGNO/KARrlPgocqddHAkNvnaBaN9tfWdV+vta4FCuUgv37WQckBYd+3Dkpe+ajWSFbKyCHZiwDoFF00YqTbbPLgwALboRJX13FuIvGPjigRPN9f51gcyChUFlq5PjbUCA+Oe4EWZn6cEtUVpEPqAC5gnG9e6Dn/KC2Oqva7jA==" + }, + { + "algorithm": "mceliece6688128f", + "privateKey": "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", + "key": "KfRWdM+1Lilc0x5TA7c4dRVpmnZHd3QrWkh3mNQSGMg=", + "encryptedKey": "ZAtNqBwxmNRwfgLK1xPo62vkMQduPufWqlMjqcVR/v6L3JeAUqVSRNk0fC20pe92xv/07j8+lzrL1YwOA2ZdrxhXsph89GOZTMMelWRfgc8uGPfV67wSEmibb4dlaS3dD3hS+s7YRxvaVXN+1OMSmt6E4kbCDQJ4DVkNR9bZC7Km+nFBtyKQ207hR44JsbSLfYzOTzfjKaHtj5u6xNrGBANYzti0uWKJq1viepX7NaDWA9zH6U2Mmpcoo4ltHuVW9eGF3FQtocsHp0gNVhjWRw==" + }, + { + "algorithm": "mceliece6960119", + "privateKey": "QECtqHmZz2mOa/FUYLSUo5Y+4TCaPbEafdJCmlqktdP/////AAAAAEwe4g6WA3EOhRiRD8oVbgJZBzEIkAXrBWgD0R4FCQAMLxUvDy4cmB3FAD8OtQzSDE0DhRYdBsUDdxUeH4cOxAiUG2gBqh8ACFAdagm5CE8GZxEzHIEVixZuHPsQCB15GUwKvBHNBMsNyxNvDhYbTg8VFp0UqgPhArcMEhxdF20AWgMPBEUBBRbjCkINGBnRFWoAbB2FGNgHmxRJHJwO9A4nBIwW1RyTGuoUYh7ME5YDTAy/FI8R8x5BFb8XXQQHG/4Wlh3UCm8P6gWWCJkYwhQiB2ERDxo2CMwHPR2QA5MCJA9EDk4VFBPbHw8H1hgKS04AUkVwMiZq8cHJBKhtdmbL1eME0jxMfjMc5ZrEUWo+usRgkFyXHO0RYLYZ5drb24qqbaUc5UZqEmEkA9C0Yd9jw6XOyLugJFUb0IwQzY0HRerqFEDSAR6mZv5/FEcMRTr4ixoQzLd4zQu170E3CFPMXkW5jDFV4kPIEm+thj3Buxk+bkxRnkINRv2hjSyYh+0ByW95am2X7mif1VUHo/HxXtuu7WpwIevoEshUtsMyv4XqZeBTIAY+GrO8LwMssVzlzd4SA04GMYZXqdv7TQ/QOWHUS2zdq0NnKFSQd0NYhYj54wDVXmGL4ZBueYPnBeac0rL9L+EE8W2qu8fdEmET8x9ErcHWsULn5IYLdNtE5ZheclP/8Ig6SP8Pa9YSKIi5sAZMKpIBFaOX27PxGbrkXgUH/z+C2skDsTyop1E8BQ2sJDHxKegcoqnNoVr+LpUPQs4xVUWMp/m8h/Ww4wH+SuRJvq/86f+tpHjIXn4nHloez9p5dx22V2WxSs6H8t6w9xb22JcUJ5BBQTBECqNApOGHWQ/Y1rgzawhDD9/lmsWGS56krHnqVKZ4W3dGHGD1soag2+/mRECuEsl9Js8YvbYxrZtjFisWv3CPe2OQpu960/5xh1Huqy1UqzRRShTHk4Pwl0Ti35pFYrnKt/eRZf8qLGt9gzGMJA6fSaQlGVNgYcZewpwqisvhcPA2sLcJwtX7zgFpwufan93q4GAa3GDA+zTJzfSdPhkIa4Y3HiTbs6n56Q6K0X94y6ZlHRx0gIoCH9Mz7WlGUvbF0/sENKJjLC79HWAshojKdD8zjQKWg2TNWq/Qb2vcbxi9JMB46n4d2WZfhWH1PnZjPs5qIPz92OXUcXnL0/WDv/wjTdUhBN7xwwHMWWDRD6BoSR1LorEfQ35EbvnmlIDUSm3GjyP2clO4smvIgJIqnKufV1Mzw/1SNpErZ0RMS9RQm3kdC4AJ8sFftqGnOJOWm5UikCnkfba3wdL+gjc4aymoCe82MXQkji3nTP9bhsVBXYpMeuN7EsjeaR9JvAEmdIxoXc1ZNMC2PRPSExMR0h1g5gLK0iRAckpjXzCucxyTJEeC4Zdcz+xX2Rs55fK1aP+RubBTq3Lwq8qu4MWD+ECOLWFNxnKBQfkWzseacetlS1clYoGBTUa+7z7r0+Ql5P/6IXVKsDeYyUuLPHop3z5q4ENuxzffq8vFHYJXV/IuGGbBCEWHToREVc3D9qgiGv2G/m1qLoo64f4pz7WluaBOmtQuqGe5Vi3d45bxtk+2zeK7NzHGOMoenw2+fkPgXzd9PFuaoOmAYCuIWgpf4nXuuutB3ElHt8HeV2SgoxInGLjTCg/Xu0ANI6a4SVtlMND8DRqqCEbIPzIDz2dLYAtlIJMgVxgVWjXljgZLdkXZ+CkAiB/NUeY47Y7PzrP4dZwhkndHqptyb0vUWcH9+0gtUnUgGP7v4XaKdZGppmUBbQ9/TVRlRNrcKVWfsid7yranhm0n3ZyHPzl+Wie0LlVB7P2XMT57KBk0SH2dikfFGZ53JGjJCDMSFYJn7qGyACKdR1yJk6TblPyEvmbx7Qz6Ylz0cVr76z8X+AIxf3b3WPn02bLbq/ZffCRtnQwYPhzZnkzzrpDCyyeu9HBX2+BVnsL7YNuACfAA1Vsaf6w8oyjeAS+0pi5l2wjTBUFm+8XPcbmvateBFK1GMc2ViP8it2FHlr3gvtfZDR/gTKJgzIsfcLkUEdHdwA/kaVXqJwjy/1O6cS1dWcWYP8Ds6bUqZcIbXvIixZ1tHyym/SRLid0aAU2+rdyCrsgKAMcemn7DELaCX84qwwciDkQranXJBiKQu+DRl1GMYcbjAFavGea0C3n7HMg1CFJIEI8URJZQkDa/qh65onHCgJUeerjOAF1dNjaBIvdn21308EuKX6/2R9rf/pG8eXdNcSAWrBMlQkA92SLpfhNlDLCONLLSAzNpQU82K3izD76n+hIeb5MyPdUqB8BuGODOpggPikOj/xyesMK2BBpg+85a55Rx5J2qfTXKYc87mKWKxG4AdClAJDFVRd0+6ilAK0HIhQwrcispalUiPh+XjwCGl49gh5tq2weQFh3EcQcveLbLi7yrhVknWFEeAZych5w+UooL5AcmdS8XXjNh8qrmSpoD/js6HvQnG6ZI6Iz7qaCojHW5aVyWLpuXyWINUaW9jWH+q8VilBHHbV2RcnQy9XrzvKWp9t5KV0d5OhOCy9bzyjvlWR9DO6okBkdKsClUCMZJSTMwd9ZsNw+GxYogq09bWKKl81NGaC0h34KxGfJEOykkwrClme67MAN2WiT0/KefbjvuPS2veAlgpN8c5zVGlabIPLaOzDBUlwxclVU4DIri5+6x/UjVQcgqj6tSJXb01vhvXCH8AnU7VHtzKV2kDDxa5RpYTOIaOYp5Ij4hEjaFOhT+7vaN32fNU4jxJfS9SKNFhkGkHbt5kZg50OBbN/H77rQiPPfMSHRG4kKissH8ufvZ5BNu/GGCNrbwmSlSRUq/B2siWUEWtJfEorJp5StvBq3Q4AoB8L4YH19zWEnaM0dI867Et7jmzauBvEp/4mzIBLEB3LVi6Ma6filRNY1PoRnpadfj9+QlKJDEHvBDXnI4ztRAUAvmPKVZMWY1MyAZjpsvzZkZg704IW82dj9beDXOzDc+Q7juAp5xG6U32rsYrOouUQ9mchEqo5CIUuCx55Rw28Fgr/Yk4QAAZdQsN+lk7FInNj7jan8mgxk5pOL22zk9OaeyBYcVdpALNsNanu7kZsjwWGHecZZfSqoOZxGW+83xn4QQ2a3x2hmwjTElNCj/DaGX6PpKaU4IgK6n3GxM4/yKW7r6FVsV5hCFyfOwhlETuM30OwhqXDLIw8R8aa+UfQrTv/fNRV7QN2ZIZGZmWbBSVn3Xcny7bJRxAPJdIal/rGHnL9QZ3VlBQhusfZTEdFkmix2q4zKIfl/fQ443/xRS4pWbWvu137r9Sbjz0U+pvz3sZ/pz1rSopuQtZjfUxpxch47EUSDE5eLxwlA9axy9L9DZsYpkJk2KKkxBbr5hMUqwZvftnBD5bvg5f3CtIt7mYkBOOzyPaRxwGWpWvgLA3WnHjI4/mCS9p3GS2KBbZpdzCpKNGpoGgAMW8iOJUnh0M2YlE/UFF8c9cqUrIkNN48AjT2O8Gg3t5aK6vNHJKhdIsjkLRAkf4odJP9NwlrZmnChRhi2YARQKHKkE6/aO8RNXSdatKbXwgpKyyrFcHaQ+t76nPWMIH2Soquv5Xiuo1HB2Tg5krQayUuXsRn8dub6VFr1uZXZTBljkShqcvUovrxRb593bXYtER1E+EmlFMTuKYuKZxHKzrfzSnbM1obWaaZ94GjQBr5Jn5EqctYMyc8FEiTk2OgobkRarfufkgz9YAAAAACB4CiYqaxAsAqYKUQe5eow8RpAQV4bpLCWORuwR/e1vhZYtED2EbzGGE8+5i9gphkkNOQBw7QOqNkzVkRPJe2pR0TUdN7RATJ/nElqlAUgI+Y/aWUIW9wpC+30a0bq6GzZHnkeo2JMZgOx/KQLzAqcATGFAi2hUpKgZ6Rx2CCvyzta7R7Ct6kFqzR+bppI5UnKaq+gEdbki+jP4Vnfj/NIWL2gpluZ0GZ+oa5nggHXiWVOpBMj3uBRr0BoxK2oCpcsurHGWBHKqoB/dIP6oVEJht4k6GKxv5wO6gLYCxj4RJEwLnP2vz9duMzHgSZ/aCvVkPLFB+ig7/TLpO2xcGC6LRn7pTr14O5I7Cnnk+8qqfEWvonBveQ5+/6RNMmDX+FkkCumw/AR/HMxGZMcu7W1SiFh4MVDl/3hvTZQ+ywZ35xrBAAOHz+y+507/to8Z2tPmpF72E+MlO4DL6rdG1A8h+8I49iKKIqUe+4H4Y1Dnkmwp3dKpdg6iFRXLiImoyO05asgumKk86mgtm1MGaLKX8vriwwblE/Fx/P1mGzpSEiLzqYq2XR/r17zLXeRHbcmjfmb42da4Qk7KDa18p6CU6ClPVq8a9yP45hqgytT5I8X4AIm+mGoPbZFjn9yJmYGuLckrlbpHGtZBaq62HI83utM8YxHM49PS3LwAAAAAAAAAAKEQwOBJABGZFyp444PoTEGq07ERaQApECQ5AmJQ/mbR9HtXHMwTCkYUJwjU9hXhZXBMTi/RtROn5YNgoWyKrTw7IVT5nqMtqDmQs0oTQVuKcLKXwHfXvqhwhTCJDLLTcIs1s1hiM+uqv+Q3N+95i3CswRe5Pyi4RhyPF+rvZUlap0WUvYCbF494YlEKwMt5LQb+VogYCXiclaSSmZjUg11pqewbypgR0LIslwPcKPQThIRtLlWJzC5zRJzSI6KPf9gDaeoNNxqYREPItjybY3DPh7cICqOfiCwM0kleaiZgANIYHT0b/FbtWNyMxFll70RAW2wWS3YtG8r0tviLVs5aeuehmDNnJuK0rNEp94/XjBhfNNyjFr8aAQxmXWPQ+h5A960EYiCyGIQ3vpb7KWLKkkzuk/CYBVGQNM3A9IVSPEZBv/pNc2Ig/ovrv61YUNIoJ0f6e+0yG1XEX1yxz2LkedtWAC0jEkjWkp0piqH1VZQSkIjUavwwZ3pjP01S4Cm613MnQVqYKJGcuTC/vTIsvcA4rCz9idirzwWi5O5v5s0MPVBV+R3vYNiPlNDP6zcVrgtKVqrWNvyEURnS+twXRxDqut7czr/geaulmDN+7taxA2UUWO29EgvdYt6khOrZP7wdlXoX6MMaeNh8q8nLewXEeiJdzwAAAAAAAAAAAAAAAAAAAAAcXUpQqMrgw5AIRHAAiyD8I6vHwMTWVoO4Qhg4iAOzYAtTBAlBKQMrIJNtt0mghEYOJJgWlPpJsBIiBrKYB8GqnWcRpalqidP4iZZ4T1T2qZLoVfJiayQMP8+xAIjeZ5wojFFPSnfuirdNmaBobNJRYMUkKy65GLlmChjllwyNNYnbZcxM1JBl/zL7HzQgRhfppawl4z6a7m2iZRScPyGCNf3sO+987zI21757cFbY021psAWPi5hLot3XnBC0gtVcY7iTvZlEwQNHWt75kwsOJgAvn6UXsCLztr7BCDl5fL2/2ujDDn0g9We8TkWf336cThRpeFm84gRUZfuh0wckJo5RlVy6fJuOSso3YKgvB3S9uFaOmqSBmgd+4oYm4SpLRHIrg1xSr1lTSRzwWBB1QoSljW5wU2U7DBRV8ote3ttrPRdUNkssznNL/UEO0r34WVrSStAKp3xXt+NIxMA7NrB/m/4ncVNFDV5ORoEudbDaLXVLy6KN0f/mejuiyERadyi/n4+2T/Zzfom9mtL7RD15NCXgCnBCG2dt55jA/QWB58kMoDjH/hO4zjEeYEiq3B/uqdwgwurs7KIT5NnwNK4HENxp4GaBw3alfuncSFjIQS/9mZrg+BgETy6hKbhF8kWvwaadiN4sMgOhF2RxAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIDxsI0BhHtEIoD0AoDCRRXsrBIizhLAA5TWhKIBK2EMIHzqTAQwm85Q3mEdPAnviSpNECKGUClXIdpgI0GJILxiY1Ke3BHOo9mZZMNnhCEPWRPANIDlXf+Jc9BOXGcN7WrACSAg+qxkSEyT1TQfDFTF8foHwKIITO4SA2U1nF8UmytRdrSLsAqxPFyFH9lA1PcLaiw6YIZsKYVgPWhYkDta9j8X06J1YkRXl5XBcxxuxgo9SobkWI+CwsOvXXoBulz7AkphRYiTmwjdToNgsfG1dB5OhxUMAUAkJG50RJwMXEpBKMHzTKSGC1MW6RwACZ0hVUA4p01yZlhvWK878S2QD5CRdog7XOTG2IkOeMcHKqgp6VdDxHeIQFZpil1esrt+tNVY1Veb4nCYqJl8ygCp+ly8lh1Eg30hylLjk1L02YLbuJLxSSXlDkz7Z8H1nLDpCtOXQBJJTQlo/DRT1jAd6HKhngawNm6MxSLOl0e90kJEcIskZBpt7KfDKlHlJ+Nq4qgjBitxZnTz7uYBfPPCZiqGQBtrHWk0Q8LkhX4yB7iBbXiqRF4lUyw9ZNpdbi2XzdCdC6W6TZEdoI73CoiW4YFyH6AEGLa9OlYURmGX4SDJPGbRXCsfTHUcRIbD0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAhFk0qRBwYAU8ou8JICZOshmcBBDNuQIHNxOQNEKlTByQsBUEfrBLOMWAB6ARSwSEhohJusgQAbc2xAUIMgRT4Jd0naoBgJ6AFQAOOCiAKJdEMLECbImqzroBR6R9tBcDoB2QWlhJyaDQqgQ6RBIUTtigFAOtowrIho0UvNGAMMJvGPjCoRbCHmoNwknjT9RyQjJthWFuXtALKg8OBw0YDyZgqYc/VYy6C1gCnDFPOhxRqHD7WRZho3+QEFZn9DPwusTSbBQCrE3G3kgxlcBGtGFtputyzONljxkjq6SyJMXdJdLHA3kk9F2IEEfllTnwgotKH4lUHk9lzYC7zjI/7IMKGYmk9TyZ9dp0MpSIzkqUFLOgP648fI09Cjk+kC1cgGzUgijyRhxGbmQQQJJXJ6CV8oGLsVXcDLa8CuVwuGgM4jlAbT4EpCU3BZiWjXWIlCCZYBigdMf6twWP2i+nlQGunb+VYJTpSEyF6Vkt9o53IOes/LvtkUwRz8WqgFSOqGFX83Cmgjw61dMilSLJxnEIomucFGsHsoxu5fgCDdche1MjOigJEysBMgC1DPoAyeZ+wwKC4tEGiIM38SKwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAxsgo0AqQFZ1CEAY3oVgQC8UIEEhYggqeHoUcykTUIFOCkIX91QQ6KuKGRbYBFAzAgNmhRhUCIRC4AQSgNZDvFkKnpBCRqUDIwOigOHECg8BmGtFFwXRDafhSS6DQChNetUJISNAoWCKQBMMU0oP2DEIQIFOWMhMAkqQoOkGgCBsY8Vxg8MRDnCxNCnMHIYIaqVRfkFAigW+R77NaC77oeVzkxBuaU+rN1QIFVKGgxRxjDaeHBAECDwEkpVuoeSA1bTD8bALasApSIEJDNvm7xAgDCLCLLPhKWmqs5X8F/mEqyFFQpMh2k80sNB4DqOgbCZrTIaEaLxD9PiiMWmboCE7gR/xbGRY7qJQgo3NDCEHVfa0YQSzowhJ6navBB0FGK9ONeBtgEbpcwm0bOsZh66gVO0LcgsNAU0gi11LLYsVGAslQrtXZlVW0hSlPyAFNryILmcs4jQSqLpVWDZmBGleIR22JGbaT1lUyXSDQtSDsINROC0mpdgDSYIGkjHuAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAdKoIFeAburAlFOWqOAkCt4MqZDiMnSAA4KBVAFSCSWkAAcMQvRGGYhFBnVBSMnYKCCBAJQJRHlMcyITSRCHBOAABhjSkSBCEWySUgjRhJCACFiCARRgoAEMEEADOCRQTldZIRMYWdCi7YRIAAVhtkMGSfQ00YEKszgC2zxBT1FA1kEyRFCALUCbEjIECiNCCeAq46rEqhBkAwPJKAHJqGWcAQR8KhCkoAVQANAVh0bJgCKJNRBg87xMAiFnJFBkIoPSuWSCqkEgN4ECwrCWAZoQAXRGIASTanDFUIBZgwgqZQAAPUY7DRicSZzU1gBVkREKxykMxSXEAYgWhUAowR1UNHG7JScsAKMi6yiNibOgp3xAlSe98RB3acw9DFlFeuDjg21CyDgBjws/nkYazhngXNElH3QIXn4gehKXwpCueCGeZUyKE1RmhigMVx4NTt1iP4v5356647YWz3ON8ex/zaA7HwXr1iqD1OP8AWmLVpI1ScT22YAqU2Mt+Oo7w4+oD+UAvbmG1Bsx+WnzuOrHEaVo+bekC0mEwtgR7qdGABAfhCfIzu5jaC1As62nbQtTN1F1S31Aiizf55z65TyE93Ks275vO283tShqXa+QCazCL3w/UGrmIHirpAdfI8I6K0aN/EVkrYYF/SqU3se05s229k3hzfj2CVsGUwQwipxKRM1Y1+JdeRTVYeTJX7rD2nuQyTVT8aIxJlb0sNYEPF+GtQ+Bm2LdSkU91zLnxsVJ+0Io84CNDuF7jzXPVl6HY5/1Ml3NGjR2JaSasa4AvvXUB6UsD3xAbMyI8yOTILRJQGdeMnHHNxw6wWTXwIh7wPQfA5d/EG28Epe1bIpY57GbUmWUXytlBs4yFF4HMz5CkjxIfeZmdysxBidbqb+pmPnJ93gVfDvRs+w6+bTIvajsB6+CvfQLMoBpj5ATAyGJ2ChFpBjYnPPOmKOST9mFPGneWcMQmv2oG3mIUsglQpc784NY+1DP+QDVSol2bzkiD+iqlBmnPhbM+n/DRcxnWxVCVUp6QOryqG0W8dsINWYyXdNUNq8VNoM9ZhqMcoiNkfzjwQKztiiCUDgRFMPYKAODLkN9awk1zjJNbFabyB3zcmMAAnT6FjxFTWUPv/79jcRotCw19NEnFMwR0qfeymnH+Sc13Y2StiFzzwOEqgv0rIitmZ7RbgZZJweDETw+9A3CsyGRwqcOxkwEyl3k00Y0+bra8iaAWcGqlheZPiOiJXZC8jkq1i09mmW81xx+TF1kxU+PIjmfwhlD6tQvScqBnkSNyCRMqgriXXvZAZxvOiehRa6avtq4FOlvfU8AULrH9nCFVviQ4tTgCc9CVRQivROZdW2N5KY7Yntoss3J363StXgXiNfWet2gp71AECQfjxrGuz6OnjCqTwaYJeGiwnG8yLXVuFfnYHARjTavikHvnoq5zLwr9LKvWWcLnSsM4rsx5EApTBq1+PzejVtFMWLD5MeTXRecB36OIfLqinFX395u+zTFou0gBvpbcqJfPWTn9sK9wBEUIK8Dwne33gYpYeAvYHOXwh8KUY4MkatDQYFV3wUIT9qpMsdeJUFVfds3bLDx6fd2jd12DX138VqbFEoLIHwzPZByhBCq9sJLc+8N8pQX4T5PUhpXDh5uMOkbjXq+C1j07KsLpqhmMAWmNEFUfSgZMT977nbwFHEqeYnRGPXRsM8eyy7wOlKo55vrY+/X43+GbaUoXrro1eoicokIumc+yyKqjavJFJtUylZu5iCx6w86HANvwgS27gwe0Dy+G6w6nChsbL62JV0EulB2f80b5R8Wkj6k9CQkDvpXqG2sfq4l4+1EH1kiD3M6STz+PHxvEtbsW1DrEizDSE1KmSaZbjpJTM5krigDgc4jF+qhJJ9UHH+OxIwJUiC5cdGPvYzQ1rjLgvS06vGLAflciXXi0aqVm3NLAPzVSi/sT2BuiLCm6SX1lbDvP/XtTU0x5iG/bFwHs+bkVOFlM2qoexv4mAAhjaoCboym+TQcggdkqW2cphEnJ+KJPtzCMzPhR9GRyqzKQMMUjUSxES7jUMONoZ5GS59T4EpANY+eRLEBKW03XEdWZZ6adVTGNzgeYW+Zd2spO9wtXhDYe6Ug8EGontuSaRLYOogHfaW9v5gO4E7N2digi4e68OAUlKUt5YwAWrKKfMjfdE9gjnJtdUDxhKy72FWTsuyrhG56ZqmhbN4BEHUrFDYjJU6pAMp0ioLaKoo/qW1FeQk0v6ZlfDx3Dm4PCgOBIjXEyUXtv36LT54R86EGgtaUfE45wNh3Kx4r0bcJqr5i2OPpO4aoW7RvfU5jEIDbpApc6z0brHmgE26j58zuayi+4d2uvYqy0VllztlyRa8fitA4thwWUaVh18PqYIR4mLpG9vMI18FjVfNmfaCbOT5wrqiRyU2pdX8NGQ8rM+zTLGhoMmzDS7yUqBfls3n/5rKJ6wnLf7CI4U7hjC3GIhP6ewSnBwjz3tIsBUygJ9Y62R+N1SmGv32+NERotWrGbNJmoG4KnEE4GSsw21g7h6GZl9hq6KhMzAEtuGb5kpXOzhgbYhyLA/oATaX8PxLMJGXQc0Dsdya0YfQUXTuXycCCkl6MUtsT6vUavabXpDzDSoHGoO/4Bw2D2WXCrmE3M1EUAZwyQuolSK5JSv7D5V5Krxh9vAoMCCnieSwxGnr/2QF8oCnNxVHQLWlzewLFMCZ4rg5U81Jib5H0VWZgqSUUVWgpv1N6KKRdCuWdkKwbZ4Q6peaFumINW5t8o/lM4ALPeQwPND+RbnmYm1sEJHDyHHeN30pjrT4uSEe8HKMPnFQGwuMGnNWbc6xiUpcvArZI1Zem5MycPnR/NV0vRGSYBq6ldKWaTLoJw+KiyPP9/GlPxozXjpgG/qsVk91iGUzWAu12fR7/5dUEyWPY6JiuLr9UDE5IN0IrD0272k3S+8tFw1L6UHvqz3qFiSahpIQwFghzgwuRFJf27oDqfHgqUfoHouSwkhIghIEBgpk0BoXPMVybfPYyKywAIG2V4Cy3qCf/hrjggujREXdCZSyZJROe+0eL/i89w9A31DJ3dCrNTArq2qhqBumZLhjGa1wJFLe/E8mntmNmyzMoa1jRtuRHtmMTMSCyroUqjD41LbazsEg9Bx3I41N6y402skZeoQJ1mPnYkxRKY4+R1WPi/R0DYYq20/K1AeQp8l046KZwo/Pw2oyQqM+6j8rttqP96z8OHit1h6azPcadfMD+n1b11nzG0X0uAMAbR2e8Huu04jhj0FhEs9MYC/81EhhC8rfRKlMSrZMk6WpUfooZ2mWSAYb2g8GCjcXMOyhROeOiNs7UkLdWGb3lz0HNgcbIyeo5APfjWua8Nk3RNVEkCmvi8N4T5V1cbTOYuRyc2cQgyN15DZ3K/CKg9CF9qLwF9FIC4/+UcFmZVSDipNETsCWkSzljinj+qiCvR0FNXugoRh3D9mtZvM/aI+72ysYtFDCHUUdbssn4zpNoSsi2OjzQAeHDTfBCssBM7W6IDWaHWdvEHPFLZ65JIDaak1yRyNJDI1n9aNRHsJpeTmZzzbebd8BimjUclxpE69LlsSfzR0d0wZcISLzs1sIfHKcrYkG5YmLaROByq66Fbz7tETg8R8GUhM3Kdtok1qxU0caHaPKNNk9kpeQP41mg+6Nzb2+onn4Z9EYNrl+2Mmnx6GpPsXPoM6HRinXUQxhzY93wiHwxqyj8JppB1gf17biutgmF44fDRyGmEAIDHOwzD2YD9O18ll2KqUONvxCCUGYbz1Xfy3y4U89gXGEC5nZygcmQsv5vIDxaX7WoQYvTYDopb/yzxwopZJ5woZehZD+AwRp0/7ZazIw2QKoeGkf4fNA0eQyF5C+AS23MJ6yujk6Vik5IAAJ4qGA+gG5RzZkWqrhEST5Hd8zVRnrYoh6zzJcE6cuckV54D0cBgP4TxarQZit7BG2wqx80rj0VR7tI4OWGgG1CjUPKnR62BCP+GlxEHk3k7PJlSI/rfIpeZoCI2mr/ZT0g7qYYjvNGUoyw+ImUMYSX28bkPfJy53CaINXIS3gkItzPj+ewkXkc0ls443r8XLQDR/+NjTbpKFz/u0cIYXlgAtWxUMHkIM8sYL7HoqCFjpCVyiXCsqhp9yzheV6QoxY4CHCRAkTFHFViC9CXe+30cIpFhODZQbuH/C9TfbLsEjIt1j0eNN2L6P8nKB+EfPmn3ZMrToqiBBi9VPNRrhH4nSqwfOn6dDWV0s+MQnk55JqPUASIjLs9/UvsaXcIHNCa8m0ICTcftZ/dbO/rYlsQqsCTTtmCv4AcMHCdP8rHm+BoTKr95MpL2ZsIblHZncbZv/WpJ6J+lv09aM3lm33ehzRpJPTpLtRqPM0qQjdQCGbgId9G74NJmwU/sHqPEay9iob9MhqWUQKijFTDEUYSSRnrC9gNS8X8DB0EjyJDvBS9zJbpvOUcytBrZV+68xCUrED3Dja+bJcaQ8rkQKPyjImnZEmmdVfXa8iS89UmUGGuG64xWtRxDY96ny7HhznauJ5boO8XPsC8ab6nrWS40hw+GuE213m4hzxPbagESur9fQaq0UFhyIMsDS+lEfedpk07qdJ3SS5WvbzGdzgkd8ZA7dAkHAxP1kU4aPfH4RMn/kP8jcwFvKN2dFcJmlFcELjv3lQ3k6yUNe98w5b7F4t01lnT9PiU/OdVryJEUw/lbrO1mcMIxou5fu8QjYdlWWFYCKDLoMyhhxpfUqaKCPwm4ghDaOig2Ax9ZpS6aIhwLNE9ovgQmIKHsgaXVTKHVJAK7s/0ZA7czEbtL02j+3rL6W81c5LcOdt00CGBeLtP6UrLO5OP4N+Jqt70Pg8lnJL3VT8EcbVKPxVO16ys/CyNEbVIlWQo0IB6JN+n8nazjzHwKp4nVnAYA9YnRMLGV7KxkJJuHjaH4UXuHpPMawIVC5iVtmd2UAEeqACxmJwqzkDCONCx1pXMZq4om6mKotaAfTqrGxKqgUpdy4b0QZz7p6T3xLs8cl34bATQgebZ32XZ9o+OFsOXgpum1VT4nmLjj0IqCyTIc/wZwFRb3tm1062G6kjPoK/kg3+3n4k7cR5CZlyRdBaht9qsk3+YDeNRYL9Czwl+3viQ2oWPyxeCwOL5837dVNIOOWQAsDHOPsmA/nCFuJRCl/mfILmpB4QdDJFUBISwR0fYTarusWSdMIm2LEXuFONVkqkkGL2vpYLsR9au0FINc9UQXc+Li9c/sxZhRhSyKL6aMNIJKetyB/Dk+uaWsiS7gaCT1uQofN9pCjWBFBj1ZA6RMXWGYfoP1qKezoiQQtGFhEhnhq3uOiMttfIbAkSWxnQc0Df/tVDd8WhgiiUzMnzcDOxQfTRDK+5vceF1C/+BoKkA8FpFo8ZGKc4gkZL78eeRj8qxuDYE51ZPt4wcOnM4ouQA3FmVCE8bQNZvf4Teg5Sbw4fknYUOaw4Em+0ZGRWH35nooYbPF4qa/A4YGbkHQwjrkYAqvMjnosZXKb/gflNuKztDfJMm7mJnOcHP8v3tiJuJcnePDZ1d49LobnyQC0JqEMccTLYrgyrNFb9E8uaxB3+bCqYjo9bHWCUtls8x9tiEp46GlW5S+rLPnabv1yCfdXdchLIJLicmC52tXXcn2m3iWvtRYpTxUgy0xSWir29FZPB/yjWL8jDglCDmayVZq/u86XWZLeSWsl8dsgPyxonI40LaaY0b70WdA/2crmxG7egIC4IIDSWjdfJka4Lll+5BcoqGIOU5zk0L1evI3UpeVBKAO8/RBT5L/VsP75ZINA81NP9MNaNyo2NPaT/dtRLesxf0f5mA1iA36sGHTV6gdehxjiU1wt7dbQka3URskqGKgBwLPiqATk6XmDx4QxUPhl/vWxrTZGNs3UHK+qTY0p0hZbpTWHxe2LRfcmTFExIr7KgLov2YSli2B7A+8TSf+4F4eO+1vNLastr1P96r8shzWWIn/HPN+4QUCgGW2jzWC7jyOcs2QoCYdgQmbVWHnJSrSYzguTKxawhiM+s/SK3THPSIjZW1nCja7T6reAm3UMoLYUA6VVrQcJHdxGQaBR7jHwfwIKi/Y2yFyijD/8qYX+oz+eUCwbWtQ5DeD6a4QvOBSkDOlbtNjnuvb80kTKMRNzDkxh+q15f60arBDQfw1aAh3FKJIZdtqgErLnOED+yvcUepvpr2SbkcThsGaz08PdWeaMkCfUWeLhTgaMtw+c5Cq5ndQ75r9ZiNia9K1PCM2vViaF6/32Zf71nZrmQGII+b9I6QXzHsSM2+a5cHsMraSKFtt0j61nyRtU2ly1KPgNQXV2iawfQbd9jv2HUTw7TBNMxG/lVYG+ZoFBpoiMxe6gIymCeEJXYOUWE5zzhyQQqQcS2Ajyqk4ar2Eg5+3G5Yob004VvEPp803jXpCitaj+leJ8T8uUrw1Td0ZD2nw7GzxGI6TdcZ8F4A4Z5KO8V4ihJF8PhjSMq+4eAcb2+Nx1RAO6hX72LMAWbLld/zTCStF2x8k4LWjSHCBz9AobgOA21ifmaxXXJaOKL66kYf9rWZeD7mo6zvm8xwiUy8UM8/OPSXe8FpInJHMDSKClu7dr5yDb0A86m+xg76hkEfiT4WQGXIOzeMjnAmlUNcUuNXzza7D4qUbnRr1AG6n39MxIzLlvw5/WEvJt1y7umYN0ww+wJPFjU1amd64kyzJR93rfN9hkdXldb7Y+LMaFsCD1tXTjb0+0H10pn/lJ5pD6MrhbXDFEiVB1E2td9+w2atr89LCNVUj/GaaBwS++fXr2y9cMHbPiyFVAQg60960nNsbXSItslGwjaedHR/GfiD3iVlu//frr7uGptQGuzP/M5UG/XgSAP9+q5qyh/sJwbI/PGqEWIgZguR/WYeCsV7ix90O0ubLgOvBOUgpsSkzuehXaTpR/0MMsLNXUa6A97cJXdKCsRsi6dVckOBUkD/rbRBdSF+k5xEUlA7iusCuDcx5br+s16R5OK3Zl9DLRmU9vwBP/Dpym7eFs7xTgQPBCC43OWlFOVdA3YH6EzSr2OB99si4BS2LulMOxuTwZH62Bm4OeW4hZF02W5UQ+SDMENWWXbIRdgPsSwL89+jtnxG8vdrQgFXYhC5w2OuRKVSDSIBiZeqrFE88XcHrTJqZeVm4p0b7g2mWqnlDyLwTffDwuyoI94nPILyHeDKUG+TYNys2wuo5nVFE8cK7tfV/QPOeXdzVNMCChc5quk3gSC6HNEd7BwYnbA5jcr13A6a88qzWfpQKS5h63UBfeWeF0qEO7mbcNEkcfD30RYXqvB5r/k+QvTLpdEFu2HWVbEiqyHMPgcYEY0O/+uENLxK9mE4lfYMjEFOzDioICpzV/QLVSeZYH9lPeP7hOYjtLbfrohktyKT+oEjJSe9JpEV/C6XMqFBbCpOjiAuwaD50iYoLyS5Ib78PQgUj1fmz4QoVQp71yLJKrIg+nR6mWkS8yXuz+TvDv/fzrtRSKu92au5nB+c/YrJRpdKRhq0pKuCLLe+m9KSgWFCoxpxupoU4XDbDp8cvbGQvDowH7hLQWZW7mvWyTU1IO6pwbOtRVVZxbpfgItaBdz7GwUqJ3cgJKqCMYB99GZjsYfd7hd6Bja157osSLTfmFJa3/2G1KMLZjBssszcQblTmvG0bsdbtJQ4yhLbLcSGApcHNv/j73dzNkGqt+VQ7m5aRQzIZDB4TfYURKlndjk7jXCn3zxNh6jIlrUgmhawHJLXkZKk/ui2qi9dj8DQ3EiCUvUwykknXZhQ8nuBGFOTagZ1VDH5dP4U5DD7T0ZVBrXgTM4n2EAkww1MBMBLXKFxl0SSKkauZBf2sWbbBZAUf87zwnxAe9UZoHVrQu8XgL3oveTHV7Yx5ajre+5GtcUIWaR7Tgt9Ou0ky25iJtem61IMUTRwrBt/1q6v72nZawX4eiskOsUPCSYhKPoIo4zLhwPVX/DowrxCkKDxA0YqWzbm8aNPBiQ4FKCYRXly1FsaXnCoBV9vUaTlwP3DiyQr+HQ06vTOC7e/bWMk2q2Ds7K5sAOEblTbGasv//BjxGV9JU9hY9i1Jb3Ob+kEe+HNndAzJAcbUkTRqZPvZ5PptkGysvENDpOi3nwrnjMRcsMxpXEizkRAESfSl5lT1QywwH1vZ4Cu1h8hsaegtzrtLHC8lA6jqiGQV+h/P7Df8i42bwTX/7rkjKVQwCZ0tz9lvemzqVSMdTAZ20R0YmIKwFNXxnVMsDNJfdniycG5s/GVNAQx9MAsA9CYfhvWq/QQoqa7yMueiWmcmxBw73qzxnuUfYqr05pu8SQOpYC4dxj2TVV6hV9qupYRdZ8nNt+HzfHFJg8Limr3S03sy7qqSpuKWly1ankDjsOraS1VzIUNQy8SwqcLljzHRGI17DrppTBbomR2ngPDy6I+vRYAeWNkNRwOv2L6/PMFx7OSjDC8tjOMUR1P/DNHXgo9dlSlbSIJWDbV92+4HPPUzltb2UcwmT4p7+YW2BOEDXuTdm3ab/4yVzY18ARvKDB1emN3bJ9L5dnTbHRH8hs9P3eOuaiFvJNKrMcaZV4dyR12X589ZV3zcPbUXpfEBhN2dSlU1e8Jj+2eXu1pJle+FdQYAVemEp/r/4UWEsMaYxCOJmjK/gnuQeUNwvuU6eMtfqiZILAH2x63TRFdOWILpvizFozMt6fNOw6bXuBpjXTcc5kWxCSU55W7LariROPaDAx8uASvcSdey+Pdp+Oouye45TXy/NUwsQ4Fh2JMy+6usOXcpxiolX48GdCmIc8D4ofJinlSbACz4C0jvQ4oSXpRXo0OCP82rP67iNFtf2eNRNVzbAYisWw9dViCG46uv17tSmn7V0+DgEAlM9kzbj38hd7OHpaVySzrixOM+SBZmTYlyeT0j18NIwpf8cWmde5iQ3iaGajGTv++Y46hog8/FRZ1RukCHbkTdnvo6EQgU8R0xrBggNCTlPL7SsPw06l1YQhPCLNwA0/VF/fF0phkByTeQYqvtL8cWm0j+64/1NvHqIYATKiOpnk759LH4Uv1IzH3EnOLs/0ydgZPnOR6DMSTaWraP6DnNIm93WM39j4UNMgxN84I0fINPPKaNmtAHhgvpXaf0ZFV7+lK+GH+UFRJ/6Usoc2o28pdfkTCoOKAdb1nHMkr6q6ArMeZnsvOwKyOTqC4JtYdhKFt9F3OyFVc21dXWm/QOojq4V7e9BT38iGoOOxd7CVoSQWiixyjwUN9XAkDBNiLp5JIZ9vXEoEjH2C4kU00Lvp/tZCboRGV8Ei9YNtJihAuvxUWbMYWYsxc3kUwGnos2wrB4dKTIHP5RTcaJU6HmMSP0uZbizBDiJTl/KU9jVorfmlslzyuTAQ3vm0mPgq/QHBd/l2jeaaYOMnniN3+eJJYQUL7Lqc8SuULJcw7LIlPP4udZDSIFge81sg5bVXEA1qmt6w2bYD3iBd5HPYpCB3H1xAF9N717CQ08p3P37JQjlamzexHwLuDelGDHRhPHwIycjQxpwsyAQ536v3QtA6z5aYBWZXp4ekgKKrhp+staWsYkfwf4Z9Jx/VeqrL5x0gTwdJ14ubxg9c7RP4U4MBDK5AkTBHDSaXdug4oF9E8c7eGRSwY3Lid8qytf3U+QXDj/T2fcP0RhTLqz+9JmsVw+wC79YlwtXb+oUhJXI8ni3tVZOTAWnIDp6bNJ8hSStmscNnglBEuQ/MS8pBONPXWfDpmNyJzuSBFyrVNtq9XgKDBLuJYwnlYaafkqZBEaVktAqpgVCYBrk0Dqfpstu9cPI2waShUg/mwh0fApyj2xxrEE1xQ9T7sOCvV/ownlPIgPttprTNK2qrigqO3hZbtxcEcCTT9Rm4jtgFWKu45iLL5OWKflPuch74xuUVC9UnMkat3wpN6ZEoMRRN/QJeJacIDzCdha6uFYqtbvykwz0RTSl+0E5/oe6tMSk6JUiXvP3kugwaeXyMMJgCmcXgNnnXS/WH7iVELyLBLyccWpSqyRut0rCRUW2Z4Xk7ETBTrmawLXLEpbjETCTh+1ALZKIY2P9wq4MgvG5KzRHIpo8MBZyxObGDVBibuZngmZEH1FY94Jd2ZTAu6gTNIdc4NNj/qI8g6nyQ4DCTPi8KCsMdZQq5E+z9JEsSTd3JBSzNkXVJm8clBsEraLqk0378kjfH5ewbmmwouApQY3jBerTuOC9a9kXVQ3sg2P4LDj20Ie1zTS0TMZPR34gVfoiNJNopi9bT67NPrLKkcHBIpGzK8Z63RZ1tHc2k6PqlQ4kLM3LVV2m17psYqj+rA02T7ZW8O7w2m38nWTwYdMRuRdzo0GIVSPAjDJuwA2ASWa4NLRrC7pWpZGp4ijoJME4WE+yDOCXSjg==", + "key": "rOFrnUN+VkARKO3k7jocRc/hPY6CiKN1TbTZt4xaPd8=", + "encryptedKey": "Y8OdKTFIZqD+Uos9XeN9XG9yJ57nEQNhmLDCyh8pPTVB4NFGfWPS5ckrgGAAHPACAX9guVTF3EV7pjxZu+Mwu2a8hybmBazQ6QzXFnN29ozAcdT5MTSVZO8o1+qz0f9hVj7h3v2VpUgASXlzarGzm+CNV6SfOZiPI1dKWgb8TDF/CMG4Qu+ER3O+dHAeV+yREH3kDG7rIiYwYhpvvypMuMy5w5Wr2F/cA8D74OVuyfcFK5BgjiFlP6LeGtYsaMJlbAY=" + }, + { + "algorithm": "mceliece6960119f", + "privateKey": "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", + "key": "L9ylG3JDGpU05nDZ7WyMCF1XqkCcQeIWaOA+0MVpukM=", + "encryptedKey": "OURAVrlWh88iLvxWxP69mdDvbvcYN2iJhA3LNXIbBJYP70dHO1OMUS08+y54o3jKp7IJhu1PDRNnAoLdZBEOBscezhsF4NDN+gOJ7twUVPjRRDDLPDM5x1T9s2uOvmEdEqYRd1H9KoNERLCw7RrYRkwyhCSVi/i3Wiq459U35Aq7M/x3X0vujqkshDlpjJkQXXtSDWOYaEwdubBCGomrUUx1kUtdjDxRHgtVu6byteJ8ZNjC4q+loStm31lGuuvSiAQ=" + }, + { + "algorithm": "mceliece8192128", + "privateKey": "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", + "key": "gjUXAqLDlzZEy3NfybbOqP5SbX1ynuE0/BLAIBaQ6FQ=", + "encryptedKey": "rZco51GcX4Uf2hFIz2Uok8iIQoiTCZVBb5V5jE8uAVH/YXgoy8vHS6OHDQTkH7h1vmUagHDiO4nUc2KDPYmau1fSWIb9m3HCAnw/MvtdaZkiBTuk5yl+nuh4ONvAZnfgtOtNnt6glFptCgECC7MMM88EmDc7mvNRfdIDMf+x+Bd5RiUe+oC+R36W2KyvXyq5PeZ4aN5Qa0TgofoFgXZFCjgJAaWqDgM2QqfszVDHeRYmitIlr7O3oVYPr0z0dqz/u/ow0e/xf71zsQnPn/LswA==" + }, + { + "algorithm": "mceliece8192128f", + "privateKey": "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", + "key": "vB6S+9NLeQfA+iVoxeX6k2r3pvDC7mQr38dg2JRoP5I=", + "encryptedKey": "8iDwc9WOd8OvXDZslM7f8lnkFEyPuo7L+DNYLCkiQpQx17zKFdWHQFz2RkEc4ROVDeexXpKs/4vbmThb4ZF/fuaMuljDJQUoLFaNZ+4pyEsHmIydTQLNWiFUSjBQ0ktwAbMjL7xTTyAzq3oQq05cgWoM57H720bS27X6yTS8+lfGdSZVZK80AOpNztfmi+2wr0xSolv7pr4hYqp62472he+8EZQHppOK+QRjC351Wp0vdJbwYSnudTjQkUQQe9UbxyXW1ac/QZ2Cd7vBlf9Mfw==" + } +] diff --git a/wasm/impl.js b/wasm/impl.js new file mode 100644 index 0000000..8618281 --- /dev/null +++ b/wasm/impl.js @@ -0,0 +1,231 @@ +'use strict'; + +const assert = require('assert'); +const { Worker } = require('worker_threads'); +const { createHash, randomFillSync } = require('crypto'); + +const constants = require('./mceliece_constants.js'); + +function buffer(u8array) { + return Buffer.from(u8array.buffer, u8array.byteOffset, u8array.byteLength); +} + +module.exports.createClass = (mod) => { + function bytes(offset, length) { + return Buffer.from(instance.exports.memory.buffer, offset, length); + } + + function doAsync(algorithm, op, args, callback) { + new Worker(__dirname + '/worker.js', { + workerData: { mod, algorithm, op, args } + }).on('message', ({ err, result }) => { + return callback(err, result); + }); + } + + const instance = new WebAssembly.Instance(mod, { + env: { + pqcrypto_mceliece_randombytes(ptr, count) { + randomFillSync(bytes(ptr, count)); + }, + pqcrypto_mceliece_SHAKE256(outputPtr, outputByteLen, inputPtr, inputByteLen) { + const input = bytes(inputPtr, inputByteLen); + const out = bytes(outputPtr, outputByteLen); + + createHash('shake256', { outputLength: outputByteLen }) + .update(input) + .digest() + .copy(out); + } + } + }); + + function alg(name) { + const ns = `crypto_kem_${name}_ref`; + return { + name, + publicKeySize: constants[`${ns}_PUBLICKEYBYTES`], + privateKeySize: constants[`${ns}_SECRETKEYBYTES`], + keySize: constants[`${ns}_BYTES`], + ciphertextSize: constants[`${ns}_CIPHERTEXTBYTES`], + keypair: instance.exports[`${ns}_keypair`], + encrypt: instance.exports[`${ns}_enc`], + decrypt: instance.exports[`${ns}_dec`] + }; + } + + const kems = Object.fromEntries([ + 'mceliece348864', + 'mceliece348864f', + 'mceliece460896', + 'mceliece460896f', + 'mceliece6688128', + 'mceliece6688128f', + 'mceliece6960119', + 'mceliece6960119f', + 'mceliece8192128', + 'mceliece8192128f' + ].map(name => [name, alg(name)])); + + const kImpl = Symbol(); + + class McEliece { + constructor(name) { + if (arguments.length !== 1) { + throw new TypeError('Wrong number of arguments'); + } + + if (typeof name !== 'string') { + throw new TypeError('First argument must be a string'); + } + + if ((this[kImpl] = kems[name]) === undefined) + throw new Error('No such implementation'); + } + + get keySize() { + return this[kImpl].keySize; + } + + get encryptedKeySize() { + return this[kImpl].ciphertextSize; + } + + get publicKeySize() { + return this[kImpl].publicKeySize; + } + + get privateKeySize() { + return this[kImpl].privateKeySize; + } + + keypair(callback) { + if (typeof callback === 'function') { + return doAsync(this[kImpl].name, 'keypair', [], (err, result) => { + if (err) + return callback(err); + + const { publicKey, privateKey } = result; + callback(undefined, { + publicKey: buffer(publicKey), + privateKey: buffer(privateKey) + }); + }); + } + + const { publicKeySize, privateKeySize, keypair } = this[kImpl]; + + const publicKeyPtr = instance.exports.malloc(publicKeySize); + const privateKeyPtr = instance.exports.malloc(privateKeySize); + + const ret = keypair(publicKeyPtr, privateKeyPtr); + try { + if (ret !== 0) + throw new Error('failed to generate keypair'); + + const publicKey = Buffer.from(bytes(publicKeyPtr, publicKeySize)); + const privateKey = Buffer.from(bytes(privateKeyPtr, privateKeySize)); + return { publicKey, privateKey }; + } finally { + instance.exports.free(publicKeyPtr); + instance.exports.free(privateKeyPtr); + } + } + + generateKey(publicKey) { + if (arguments.length !== 1) { + throw new TypeError('Wrong number of arguments'); + } + + if (!ArrayBuffer.isView(publicKey)) { + throw new TypeError('First argument must be a TypedArray'); + } + + const { publicKeySize, keySize, ciphertextSize, encrypt } = this[kImpl]; + + if (publicKey.length !== publicKeySize) + throw new TypeError('Invalid public key size'); + + const publicKeyPtr = instance.exports.malloc(publicKeySize); + const encryptedKeyPtr = instance.exports.malloc(ciphertextSize); + const keyPtr = instance.exports.malloc(keySize); + + publicKey.copy(bytes(publicKeyPtr, publicKeySize)); + + const ret = encrypt(encryptedKeyPtr, keyPtr, publicKeyPtr); + try { + if (ret !== 0) + throw new Error('encryption failed'); + + return { + key: Buffer.from(bytes(keyPtr, keySize)), + encryptedKey: Buffer.from(bytes(encryptedKeyPtr, ciphertextSize)) + }; + } finally { + instance.exports.free(publicKeyPtr); + instance.exports.free(encryptedKeyPtr); + instance.exports.free(keyPtr); + } + } + + decryptKey(privateKey, encryptedKey, callback) { + if (arguments.length < 2 || arguments.length > 3) { + throw new TypeError('Wrong number of arguments'); + } + + if (!ArrayBuffer.isView(privateKey)) { + throw new TypeError('First argument must be a TypedArray'); + } + + if (!ArrayBuffer.isView(encryptedKey)) { + throw new TypeError('Second argument must be a TypedArray'); + } + + if (typeof callback === 'function') { + return doAsync(this[kImpl].name, 'decryptKey', [privateKey, encryptedKey], (err, result) => { + if (err) + return callback(err); + callback(undefined, buffer(result)); + }); + } + + if (!Buffer.isBuffer(privateKey)) + privateKey = buffer(privateKey); + if (!Buffer.isBuffer(encryptedKey)) + encryptedKey = buffer(encryptedKey); + + const { privateKeySize, ciphertextSize, keySize, decrypt } = this[kImpl]; + + if (privateKey.length !== privateKeySize) + throw new TypeError('Invalid private key size'); + + if (encryptedKey.length !== ciphertextSize) + throw new TypeError('Invalid ciphertext size'); + + const privateKeyPtr = instance.exports.malloc(privateKeySize); + const encryptedKeyPtr = instance.exports.malloc(ciphertextSize); + const keyPtr = instance.exports.malloc(keySize); + + privateKey.copy(bytes(privateKeyPtr, privateKeySize)); + encryptedKey.copy(bytes(encryptedKeyPtr, ciphertextSize)); + + const ret = decrypt(keyPtr, encryptedKeyPtr, privateKeyPtr); + try { + if (ret !== 0) + throw new Error('decryption failed'); + + return Buffer.from(bytes(keyPtr, keySize)); + } finally { + instance.exports.free(privateKeyPtr); + instance.exports.free(encryptedKeyPtr); + instance.exports.free(keyPtr); + } + } + } + + Object.defineProperty(McEliece, 'supportedAlgorithms', { + value: Object.keys(kems) + }); + + return McEliece; +} diff --git a/wasm/main_thread.js b/wasm/main_thread.js new file mode 100644 index 0000000..f6a0112 --- /dev/null +++ b/wasm/main_thread.js @@ -0,0 +1,9 @@ +'use strict'; + +const { readFileSync } = require('fs'); +const { join } = require('path'); + +const { createClass } = require('./impl'); + +const mod = new WebAssembly.Module(readFileSync(join(__dirname, 'mceliece.wasm'))); +module.exports.McEliece = createClass(mod); diff --git a/wasm/worker.js b/wasm/worker.js new file mode 100644 index 0000000..9c80709 --- /dev/null +++ b/wasm/worker.js @@ -0,0 +1,18 @@ +'use strict'; + +const { parentPort, workerData } = require('worker_threads'); + +const { createClass } = require('./impl'); + +const { mod, algorithm, op, args } = workerData; +const me = new (createClass(mod))(algorithm); + +let response; +try { + response = { + result: me[op](...args) + }; +} catch (err) { + response = { err }; +} +parentPort.postMessage(response);