GithubHelp home page GithubHelp logo

argyle-software / kyber Goto Github PK

View Code? Open in Web Editor NEW
157.0 10.0 34.0 3.2 MB

A rust implementation of the Kyber post-quantum KEM

Home Page: https://docs.rs/pqc_kyber/

License: Apache License 2.0

Rust 82.27% Assembly 8.64% C 2.17% Shell 0.63% Makefile 0.05% C++ 0.16% JavaScript 5.45% HTML 0.55% CSS 0.09%
cryptography key-exchange-algorithm post-quantum post-quantum-kem wasm

kyber's Introduction

Kyber

Build Status Crates NPM License dependency status

A rust implementation of the Kyber algorithm, a KEM standardised by the NIST Post-Quantum Standardization Project.

This library:

  • Is no_std compatible and needs no allocator, suitable for embedded devices.
  • Reference files contain no unsafe code and are written in pure rust.
  • On x86_64 platforms offers an avx2 optimized version, which includes assembly from the C reference repo.
  • Compiles to WASM using wasm-bindgen and has a ready-to-use binary published on NPM.

See the features section for different options regarding security levels and modes of operation. The default security setting is kyber768.

It is recommended to use Kyber in a hybrid system alongside a traditional key exchange algorithm such as X25519.

Please also read the security considerations before use.

Minimum Supported Rust Version: 1.56.0


Installation

cargo add pqc_kyber

Usage

use pqc_kyber::*;

For optimisations on x86 platforms enable the avx2 feature and the following RUSTFLAGS:

export RUSTFLAGS="-C target-feature=+aes,+avx2,+sse2,+sse4.1,+bmi2,+popcnt"

Key Encapsulation

// Generate Keypair
let keys_bob = keypair(&mut rng)?;

// Alice encapsulates a shared secret using Bob's public key
let (ciphertext, shared_secret_alice) = encapsulate(&keys_bob.public, &mut rng)?;

// Bob decapsulates a shared secret using the ciphertext sent by Alice 
let shared_secret_bob = decapsulate(&ciphertext, &keys_bob.secret)?;

assert_eq!(shared_secret_alice, shared_secret_bob);

Unilaterally Authenticated Key Exchange

let mut rng = rand::thread_rng();

// Initialize the key exchange structs
let mut alice = Uake::new();
let mut bob = Uake::new();

// Generate Bob's Keypair
let bob_keys = keypair(&mut rng)?;

// Alice initiates key exchange
let client_init = alice.client_init(&bob_keys.public, &mut rng)?;

// Bob authenticates and responds
let server_response = bob.server_receive(
  client_init, &bob_keys.secret, &mut rng
)?;

// Alice decapsulates the shared secret
alice.client_confirm(server_response)?;

// Both key exchange structs now have the same shared secret
assert_eq!(alice.shared_secret, bob.shared_secret);

Mutually Authenticated Key Exchange

Follows the same workflow except Bob requires Alice's public keys:

let mut alice = Ake::new();
let mut bob = Ake::new();

let alice_keys = keypair(&mut rng)?;
let bob_keys = keypair(&mut rng)?;

let client_init = alice.client_init(&bob_keys.public, &mut rng)?;

let server_response = bob.server_receive(
  client_init, &alice_keys.public, &bob_keys.secret, &mut rng
)?;

alice.client_confirm(server_response, &alice_keys.secret)?;

assert_eq!(alice.shared_secret, bob.shared_secret);

Errors

The KyberError enum has two variants:

  • InvalidInput - One or more inputs to a function are incorrectly sized. A possible cause of this is two parties using different security levels while trying to negotiate a key exchange.

  • Decapsulation - The ciphertext was unable to be authenticated. The shared secret was not decapsulated.

  • RandomBytesGeneration - Error trying to fill random bytes (i.e external (hardware) RNG modules can fail).


Features

If no security level is specified then kyber768 is used by default as recommended by the authors. It is roughly equivalent to AES-192. Apart from the two security levels, all other features can be combined as needed. For example:

[dependencies]
pqc_kyber = {version = "0.7.1", features = ["kyber512", "90s", "avx2"]}
Feature Description
std Enable the standard library
kyber512 Enables kyber512 mode, with a security level roughly equivalent to AES-128.
kyber1024 Enables kyber1024 mode, with a security level roughly equivalent to AES-256. A compile-time error is raised if more than one security level is specified.
90s Uses AES256 in counter mode and SHA2 as a replacement for SHAKE. This can provide hardware speedups in some cases.
90s-fixslice Uses a fixslice implementation of AES256 by RustCrypto, this provides greater side-channel attack resistance, especially on embedded platforms
avx2 On x86_64 platforms enable the optimized version. This flag is will cause a compile error on other architectures.
wasm For compiling to WASM targets
nasm Uses Netwide Assembler avx2 code instead of GAS for portability. Requires a nasm compiler: https://www.nasm.us/
zeroize This will zero out the key exchange structs on drop using the zeroize crate
benchmarking Enables the criterion benchmarking suite

Testing

The run_all_tests script will traverse all possible codepaths by running a matrix of the security levels, variants and crate features.

Known Answer Tests require deterministic rng seeds, enable kyber_kat in RUSTFLAGSto use them. Using this outside of cargo test will result in a compile-time error. The test vector files are quite large, you will need to build them yourself from the C reference code. There's a helper script to do this here.

# This example runs the basic tests for kyber768
cargo test

# This runs the KATs for kyber512 in 90's mode
RUSTFLAGS='--cfg kyber_kat' cargo test --features "kyber512 90s"

See the testing readme for more comprehensive info.


Benchmarking

Uses criterion for benchmarking. If you have GNUPlot installed it will generate statistical graphs in ./target/criterion/.

You will need to enable the benchmarking feature.

See the benchmarking readme for information on correct usage.


Fuzzing

The fuzzing suite uses honggfuzz, installation and instructions are on the fuzzing page.


WebAssembly

This library has been compiled into web assembly and published as a npm package. Usage instructions are here:

https://www.npmjs.com/package/pqc-kyber

Which is also located here in the wasm readme

To install:

npm i pqc-kyber

To compile the wasm files yourself you need to enable the wasm feature.

For example, using wasm-pack:

wasm-pack build -- --features wasm

Which will export the wasm, javascript and typescript files into ./pkg/.

To compile a different variant into a separate folder:

wasm-pack build --out-dir pkg_kyber512/ -- --features "wasm kyber512" 

There is also a basic html demo in the www folder.

From the www folder run:

npm run start

Security Considerations

While much care has been taken porting from the C reference codebase, this library has not undergone any third-party security auditing nor can any guarantees be made about the potential for underlying vulnerabilities in LWE cryptography or potential side-channel attacks arising from this implementation.

Kyber is relatively new, it is advised to use it in a hybrid key exchange system alongside a traditional algorithm like X25519 rather than by itself.

For further reading the IETF have a draft construction for hybrid key exchange in TLS 1.3:

https://www.ietf.org/archive/id/draft-ietf-tls-hybrid-design-04.html

You can also see how such a system is implemented here in C by OpenSSH

Please use at your own risk.


About

Kyber is an IND-CCA2-secure key encapsulation mechanism (KEM), whose security is based on the hardness of solving the learning-with-errors (LWE) problem over module lattices. It is the final standardised algorithm resulting from the NIST post-quantum cryptography project.

The official website: https://pq-crystals.org/kyber/

Authors of the Kyber Algorithm:

  • Roberto Avanzi, ARM Limited (DE)
  • Joppe Bos, NXP Semiconductors (BE)
  • Léo Ducas, CWI Amsterdam (NL)
  • Eike Kiltz, Ruhr University Bochum (DE)
  • Tancrède Lepoint, SRI International (US)
  • Vadim Lyubashevsky, IBM Research Zurich (CH)
  • John M. Schanck, University of Waterloo (CA)
  • Peter Schwabe, Radboud University (NL)
  • Gregor Seiler, IBM Research Zurich (CH)
  • Damien Stehle, ENS Lyon (FR)

Contributing

Contributions welcome. For pull requests create a feature fork and submit it to the development branch. More information is available on the contributing page


Alternatives

The PQClean project has rust bindings for their Kyber C codebase:

https://github.com/rustpq/pqcrypto

kyber's People

Contributors

bwesterb avatar ektehtris avatar faern avatar francescomedina avatar mberry avatar tbrezot avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

kyber's Issues

CI runners

Currently tests are only run on Linux.

Add Windows and MacOS, the latter will need to be reference only until #2 is fixed.

Include 32 bit runners to make sure the usage of usize isn't causing trouble anywhere.

Also investigate using QEMU to do a sanity check for the load/store functions and integer conversions on a big-endian system.

gen_matrix is incorrect

The current implementation of gen_matrix, given below, is incorrect. The problem is in the case that the initial BUFLEN=504 bytes squeezed from the XOF are not enough. Then only a single extra block is squeezed from the XOF, but the whole buffer is used for rejection sampling.

Compare your Rust implementation:

fn gen_matrix(a: &mut [Polyvec], seed: &[u8], transposed: bool)
{ 
  let mut ctr;
  // 530 is expected number of required bytes
  const GEN_MATRIX_NBLOCKS: usize = 
    (12*KYBER_N/8*(1 << 12)/KYBER_Q + XOF_BLOCKBYTES)/XOF_BLOCKBYTES;
  const BUFLEN: usize = GEN_MATRIX_NBLOCKS*XOF_BLOCKBYTES;
  let mut buf = [0u8; BUFLEN+2];
  let mut off: usize;
  let mut state = XofState::new();

  for i in 0..KYBER_K {
    for j in 0..KYBER_K {
      if transposed {
        xof_absorb(&mut state, seed, i as u8, j as u8);
      }
      else {
        xof_absorb(&mut state, seed, j as u8, i as u8);
      }
      xof_squeezeblocks(&mut buf, GEN_MATRIX_NBLOCKS, &mut state);
      ctr = rej_uniform(&mut a[i].vec[j].coeffs, KYBER_N, &buf, BUFLEN);

      while ctr < KYBER_N
      {
        off = BUFLEN % 3;
        for k in 0..off {
          buf[k] = buf[BUFLEN - off + k];
        }
        xof_squeezeblocks(&mut buf[off..], 1, &mut state);
        ctr += rej_uniform(&mut a[i].vec[j].coeffs[ctr..], KYBER_N - ctr, &buf, BUFLEN);
      }
    }
  }
}

To the reference implementation where buflen is correctly adjusted:

void gen_matrix(polyvec *a, const uint8_t seed[KYBER_SYMBYTES], int transposed)
{
  unsigned int ctr, i, j, k;
  unsigned int buflen, off;
  uint8_t buf[GEN_MATRIX_NBLOCKS*XOF_BLOCKBYTES+2];
  xof_state state;

  for(i=0;i<KYBER_K;i++) {
    for(j=0;j<KYBER_K;j++) {
      if(transposed)
        xof_absorb(&state, seed, i, j);
      else
        xof_absorb(&state, seed, j, i);

      xof_squeezeblocks(buf, GEN_MATRIX_NBLOCKS, &state);
      buflen = GEN_MATRIX_NBLOCKS*XOF_BLOCKBYTES;
      ctr = rej_uniform(a[i].vec[j].coeffs, KYBER_N, buf, buflen);

      while(ctr < KYBER_N) {
        off = buflen % 3;
        for(k = 0; k < off; k++)
          buf[k] = buf[buflen - off + k];
        xof_squeezeblocks(buf + off, 1, &state);
        buflen = off + XOF_BLOCKBYTES;
        ctr += rej_uniform(a[i].vec[j].coeffs + ctr, KYBER_N - ctr, buf, buflen);
      }
    }
  }
}

The issue for regular Kyber occurs with probability approximately 2^-105.

Benchmarking

Two-part issue:

  1. Key generation benchmarking uses a cryptographic rng, this leads to wildly fluctuating benches due to the bottleneck of entropy generation and is basically worthless. Temporarily should probably be removed.
    It needs to be replaced with a non-cryptographic rng to get accurate readings, this should probably be something like fastrand or perhaps XXHash with deterministic output.

  2. Setup a github action using the current Criterion benchmark harness that can report any regressions on PR's.

Add an option to use RustCrypto AES

Use rustcrypto for the 90's mode AES functions.

Kyber uses some intermediate functions not exposed by the rustcrypto crate, namely aes256ctr_init and aes256ctr_squeezeblocks

The PRF is already implemented yet not in use.

kyber/src/symmetric.rs

Lines 117 to 129 in 6e274dc

// TODO: Add feature to use RustCrypto AES_CTR
// implementation with no lookup tables
// Perhaps add an option for ring also.
// Working RustCrypto code:
// if cfg!(feature = "rustcrypto-aes") {
// let mut expnonce = [0u8; 16];
// expnonce[0] = nonce;
// let key = GenericArray::from_slice(key);
// let iv = GenericArray::from_slice(&expnonce);
// let mut cipher = Aes256Ctr::new(&key, &iv);
// cipher.apply_keystream(out);
// }

Error compiling pqc_kyber library in rust program`(panic_handler)`

Hi,

I am trying to play with pqc_library in order to test some crypto latencies. At the moment of building cargo ( cargo build --release), pqc_library throws the following errors:

$ cargo build --release`
   Compiling pqc_kyber v0.7.1
error: #[panic_handler] function required, but not found

error: language item required, but not found: eh_personality
  |
  = note: this can occur when a binary crate with #![no_std] is compiled for a target where eh_personality is defined in the standard library
  = help: you may be able to compile for a target that doesn't need eh_personality, specify a target with --target or in .cargo/config

error: could not compile pqc_kyber (lib) due to 2 previous errors

I've tried several things such as adding a #[panic_handler] function with panic warnings in main.rs, or adding

[profile.dev]
panic = "abort"

[profile.release]
panic = "abort"

to the cargo.toml file, nothing changes for me. I am running the program in ubuntu20.04.

Any help is welcome,
R.

v0.5.0 not on master

$ git log --format=oneline origin/master | head -n3       
1b1637ce63197fb15fbccd9b03080e0714cc2656 v0.5.0 (#70)
1e9e7c95a568b8698d2f35f6637af76c70288b66 Merge pull request #66 from francescomedina/more-kem-tests
06f58d5ee98fd4529afcf0ab1399cde89e7bfbbf Rustcrypto aes256ctr (#64)
$ git log --format=oneline v0.5.0 | head -n3
22fedf357b4603a820f7689c883f19687d0a1403 v0.5.0 Update: changelog Update: wasm binary and files Bump: deps Add: release on version tag github action Add: release checklist
1e9e7c95a568b8698d2f35f6637af76c70288b66 Merge pull request #66 from francescomedina/more-kem-tests
06f58d5ee98fd4529afcf0ab1399cde89e7bfbbf Rustcrypto aes256ctr (#64)
$ git diff origin/master v0.5.0
diff --git a/.github/workflows/cross.yml b/.github/workflows/cross.yml
index 48ab046..6d97df9 100644
--- a/.github/workflows/cross.yml
+++ b/.github/workflows/cross.yml
@@ -9,6 +9,7 @@ jobs:
     strategy:
       matrix:
         target: [
+          aarch64-linux-android, 
           aarch64-unknown-linux-gnu,
           aarch64-unknown-linux-musl,
           arm-unknown-linux-gnueabi,

Could you provide PKE API?

Could you provide application programming interface for PKE (public key encryption scheme)? Which is lower level and more customizable.

Kyber not compiling with React

Issue: When using the npm package pqc-kyber within a react framework, the application will not complie.

Discussion: My current assumption is there is an issue with WASM dependencies when getting the react's webpack to compile the WASM.

Alternatively, WASM pack is not compiling from rust to WASM with the correct dependencies.
Some steps I have already tried:

  1. Compile the package myself.
  2. Modify the webpack for WASM
  3. Install wasm-loader for react

Recommendation: I think if the collective group could look at this problem we could find a solution. React is one of the most popular front end frameworks, so if we could get this package work with react we could increase adoption.

This is the exact error I see:

Uncaught TypeError: wasm.keypair is not a function
    keypair pqc_kyber_bg.js:189
    App App.js:7
    React 11
    workLoop scheduler.development.js:266
    flushWork scheduler.development.js:239
    performWorkUntilDeadline scheduler.development.js:533
    js scheduler.development.js:571
    js scheduler.development.js:633
    factory react refresh:6
    Webpack 24
pqc_kyber_bg.js:189

Add a changelog

As far as I can tell, this repository does not have any changelog. The absence of a changelog together with the absence of tags (#24) makes it quite hard to figure out what changed between 0.2 and 0.3.

MacOS: fails benchmarks

Apple Silicon M2 running MacOS Ventura 13.3.1, Xcode-14.3, Rust-1.69.0.

$ cargo bench --features "benchmarking kyber1024"        
  Downloaded tinytemplate v1.2.1
  Downloaded ciborium-io v0.2.0
.  .  .
   Compiling pqc_kyber v0.6.0 (/Users/ur20980/src/kyber-pure)
   Compiling clap v3.2.24
   Compiling lazy_static v1.4.0
   Compiling ppv-lite86 v0.2.17
   Compiling crossbeam-deque v0.8.3
   Compiling rand_chacha v0.3.1
   Compiling rand v0.8.5
   Compiling rayon v1.7.0
   Compiling plotters v0.3.4
   Compiling ciborium v0.2.0
   Compiling tinytemplate v1.2.1
   Compiling criterion v0.4.0
    Finished bench [optimized] target(s) in 12.63s
     Running unittests src/lib.rs (target/release/deps/pqc_kyber-795659d6ce51cfa5)

running 0 tests

test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s

     Running benches/api.rs (target/release/deps/api-52af575b14e196b1)
Gnuplot not found, using plotters backend
Keypair Generation      time:   [30.546 µs 30.712 µs 30.904 µs]
Found 2 outliers among 100 measurements (2.00%)
  2 (2.00%) high mild

Benchmarking Encapsulate: Warming up for 3.0000 sthread 'main' panicked at 'index out of bounds: the len is 0 but the index is 0', src/reference/fips202.rs:27:11
stack backtrace:
   0: rust_begin_unwind
             at /rustc/84c898d65adf2f39a5a98507f1fe0ce10a2b8dbc/library/std/src/panicking.rs:579:5
   1: core::panicking::panic_fmt
             at /rustc/84c898d65adf2f39a5a98507f1fe0ce10a2b8dbc/library/core/src/panicking.rs:64:14
   2: core::panicking::panic_bounds_check
             at /rustc/84c898d65adf2f39a5a98507f1fe0ce10a2b8dbc/library/core/src/panicking.rs:159:5
   3: pqc_kyber::reference::fips202::keccak_absorb_once
   4: pqc_kyber::reference::fips202::sha3_256
   5: pqc_kyber::kem::crypto_kem_enc
   6: criterion::bencher::Bencher<M>::iter
   7: <criterion::routine::Function<M,F,T> as criterion::routine::Routine<M,T>>::warm_up
   8: criterion::routine::Routine::sample
   9: criterion::analysis::common
  10: criterion::benchmark_group::BenchmarkGroup<M>::bench_function
  11: api::main
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.

error: bench failed, to rerun pass `--bench api`

and

$ cargo bench --features "benchmarking kyber1024" --bench api 
    Finished bench [optimized] target(s) in 0.04s
     Running benches/api.rs (target/release/deps/api-52af575b14e196b1)
Keypair Generation      time:   [31.035 µs 31.092 µs 31.146 µs]
                        change: [-0.9414% -0.3577% +0.2071%] (p = 0.23 > 0.05)
                        No change in performance detected.
Found 1 outliers among 100 measurements (1.00%)
  1 (1.00%) high mild

Benchmarking Encapsulate: Warming up for 3.0000 sthread 'main' panicked at 'index out of bounds: the len is 0 but the index is 0', src/reference/fips202.rs:27:11
stack backtrace:
   0: rust_begin_unwind
             at /rustc/84c898d65adf2f39a5a98507f1fe0ce10a2b8dbc/library/std/src/panicking.rs:579:5
   1: core::panicking::panic_fmt
             at /rustc/84c898d65adf2f39a5a98507f1fe0ce10a2b8dbc/library/core/src/panicking.rs:64:14
   2: core::panicking::panic_bounds_check
             at /rustc/84c898d65adf2f39a5a98507f1fe0ce10a2b8dbc/library/core/src/panicking.rs:159:5
   3: pqc_kyber::reference::fips202::keccak_absorb_once
   4: pqc_kyber::reference::fips202::sha3_256
   5: pqc_kyber::kem::crypto_kem_enc
   6: criterion::bencher::Bencher<M>::iter
   7: <criterion::routine::Function<M,F,T> as criterion::routine::Routine<M,T>>::warm_up
   8: criterion::routine::Routine::sample
   9: criterion::analysis::common
  10: criterion::benchmark_group::BenchmarkGroup<M>::bench_function
  11: api::main
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.

error: bench failed, to rerun pass `--bench api`

Fails to compile on MacOS

The assembly files included for the AVX2 code don't export underscore-prefixed names, which is what the ABI on MacOS expects. Thus this crate fails to compile on Mac. (without specifying reference)

Pass keypairs only to the functions

Keypairs components should not be individual inputs for the API.

The entire keypair should be passed to the functions. Perhaps add something like a strict mode also that confirms correctness for any end users faced with adversarial input.

Add git tags for releases

A common and very good practice is to add git tags to the commits where a crate was published from. This makes it so much easier to find the relevant code and see code diffs between releases. I would appreciate this a lot.

Implement PKE

Performing key-exchange with Kyber is only half the story. Using the resulting keys to perform encryption/decryption of chosen plaintexts should also be a feature of this crate.

compile time error for no_std

use pqc_kyber::*;
fn main(){
let mut rng = rand::thread_rng();
let pair = keypair(&mut rng);
let (ct, ss) = encapsulate(&pair.public, &mut rng)?;
}
#[panic_handler]
fn my_panic(_info: &core::panic::PanicInfo) -> ! {
loop {}
}

#[lang = "eh_personality"]
extern "C" fn eh_personality() {}

Still get compile time error:
error: #[panic_handler] function required, but not found

error: language item required, but not found: eh_personality
|
= note: this can occur when a binary crate with #![no_std] is compiled for a target where eh_personality is defined in the standard library
= help: you may be able to compile for a target that doesn't need eh_personality, specify a target with --target or in .cargo/config

Kyber does not allow explicit rejection

In this implementation, when re-encryption fails, explicit rejection is used. That is not allowed by the Kyber specification: decapsulation always has to succeed.

Don't store shared secret on stack, and allow it to be zeroized

The current signature of both encapsulate and decapsulate (fn encapsulate(...) -> Result<... [u8; 32] ...>, fn decapsulate(...) -> Result<[u8; 32], ...> stores the secret on the stack. This means it will potentially be copied around many times in memory, depending on how optimizations happen to generate the final code.

It is recommended to zero out cryptographic secrets when done with them/before other software has a chance to read that memory. This is currently not really possible with pqc_kyber and the current function signatures.

I recommend, and would be very interested in improving this. I implemented something very similar for classic-mceliece-rust recently. All secrets were bundled up in dedicated containers that allowed both borrowed and owned versions of the data, but that was never copied around in the memory, and that automatically cleared themselves on drop. See here for one example: https://github.com/Colfenor/classic-mceliece-rust/blob/bb57cd4f97ae2d092b8b1bfbc88c49507eca2892/src/lib.rs#L283-L333

The same goes for the SecretKey type really. It should implement Zeroize + ZeroizeOnDrop.

fips202 keccak_absorb does not absorb properly

The current implementation is flawed:

pub(crate) fn keccak_absorb(
  s: &mut[u64], 
  mut pos: usize, 
  r: usize, 
  input: &[u8], 
  mut inlen: usize
) -> usize
{
  let mut idx = 0usize;
  while pos+inlen >= r {
    for i in pos..r {
      s[i/8] ^= (input[idx] as u64) << 8 * (i%8);
      idx += 1;
    }
    inlen -= r-pos;
    keccakf1600_statepermute(s);
    pos = 0;
  }
  let new_pos = pos+inlen;
  for i in pos..new_pos {
    s[i/8] ^= (input[idx] as u64) << 8 * (i%8);
  }
  new_pos
}

Note that idx is not incremented in the final loop.

Inconsistent between C and Rust implementations

Hello,

Sorry if I'm doing something wrong but I have some inconsistent. And if I was indeed doing wrong, I'm wondering why it would not give an error...

Let's say Bob and Alice uses Kyber in Rust and C respectively because they are purist.
Bob uses this code after the first part of Alice one (it was for convenient) :

/* Deterministic randombytes by Daniel J. Bernstein */
/* taken from SUPERCOP (https://bench.cr.yp.to)     */

#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include "kem.h"
#include <fcntl.h>
#include <sys/stat.h>
#include "randombytes.h"
#include <string.h>
#include <errno.h>
static uint8_t* datafromhex(char *string)
{
  //From https://stackoverflow.com/a/35452093
  //Needs the char* and returns an already allocated array
  if (string == NULL)
    return NULL;
  size_t slength = strlen(string);
  if ((slength % 2) != 0) // must be even
    return NULL;

  size_t dlength = slength / 2;

  uint8_t *data = malloc(dlength);
  memset(data, 0, dlength);

  size_t index = 0;
  while (index < slength)
  {
    char c = string[index];
    int value = 0;
    if (c >= '0' && c <= '9')
      value = (c - '0');
    else if (c >= 'A' && c <= 'F')
      value = (10 + (c - 'A'));
    else if (c >= 'a' && c <= 'f')
      value = (10 + (c - 'a'));
    else
    {
      free(data);
      return NULL;
    }

    data[(index / 2)] += value << (((index + 1) % 2) * 4);

    index++;
  }

  return data;
}

int main(void)
{
  unsigned int j;
  uint8_t pk[CRYPTO_PUBLICKEYBYTES]={0};
  uint8_t sk[CRYPTO_SECRETKEYBYTES]={0};
  char pkhex[CRYPTO_PUBLICKEYBYTES*2+1]={0};
  char skhex[CRYPTO_SECRETKEYBYTES*2+1]={0};
  FILE *file;
  FILE *skey;
  FILE *pkey;
  mode_t umode;
  uint8_t ct[CRYPTO_CIPHERTEXTBYTES];
  uint8_t key_a[CRYPTO_BYTES];
  uint8_t key_b[CRYPTO_BYTES];
  pkey = fopen("bobpublickey.pem", "r");
  if (fread(pkhex, sizeof(pkhex[0]), CRYPTO_PUBLICKEYBYTES*2, pkey) != CRYPTO_PUBLICKEYBYTES*2)
  {
    fprintf(stderr, "Cannot extract public key.\n");
    exit(EXIT_FAILURE);
  }
  uint8_t *result;
  printf("Pkhex is %s\n",pkhex);
  result=datafromhex(pkhex);
  if (result==NULL) {
    fprintf(stderr, "Cannot extract public key.\n");
    exit(EXIT_FAILURE);
  }
  *pk=*result;
  free(result);
  fclose(pkey);
    skey = fopen("bobsecretkey.pem", "r");
//  if (fread(skhex, sizeof(skhex[0]), CRYPTO_SECRETKEYBYTES*2, skey) != CRYPTO_SECRETKEYBYTES*2)
  if (fread(skhex, sizeof(skhex[0]), 6336, skey) != 6336)
  {
    fprintf(stderr, "Cannot extract secret key\n");
    exit(EXIT_FAILURE);
  }
  printf("SKhex is : %s\n",skhex);
  result=datafromhex(skhex);
  if (result==NULL) {
    fprintf(stderr, "Cannot decode secret key.\n");
    exit(EXIT_FAILURE);
  }
  *sk=*result;
  free(result);
  fclose(skey);
    // Encapsulation
  crypto_kem_enc(ct, key_b, pk);
  crypto_kem_dec(key_a, ct, sk);
  file = fopen("sharedsecret.pem", "w");
  if (file == NULL)
  {
    fprintf(stderr, "Cannot create file for shared secret.\n");
    exit(EXIT_FAILURE);
  }
  for (j = 0; j < CRYPTO_BYTES; j++)
    fprintf(file, "%02x", key_a[j]);
  fclose(file);
  file = fopen("cipher.pem", "w");
  if (file == NULL)
  {
    fprintf(stderr, "Cannot create file for shared secret.\n");
    exit(EXIT_FAILURE);
  }
  for (j = 0; j < CRYPTO_CIPHERTEXTBYTES; j++)
    fprintf(file,"%02x", ct[j]);
  fclose(file);
  return 0;
}

Bob shares its key to Alice (just to test, we don't do that in real life) so she can try her Rust code :

use hex::{self, FromHexError, decode};
use pqc_kyber::*;
use rand;
use std::fs::{self, File};
use std::io::{Error, Write};
#[cfg(target_family = "unix")]
use std::os::unix::fs::PermissionsExt;
fn encodehex(data: &[u8]) -> String {
    hex::encode(data)
}
fn decodehex(hex: &str) -> Result<Vec<u8>, FromHexError> {
    hex::decode(hex)
}

fn main() -> Result<(), KyberError> {
    let mut rng = rand::thread_rng();
    let mut alice = Ake::new();
    let mut bob = Ake::new();

    let alice_keys = keypair(&mut rng)?;
    let bob_keys = keypair(&mut rng)?;
    fs::write("bobpublickey.pem",hex::encode(bob_keys.public));
    fs::write("bobsecretkey.pem",hex::encode(bob_keys.secret));
    fs::write("alicepublickey.pem",hex::encode(alice_keys.public));
    fs::write("alicesecretkey.pem",hex::encode(alice_keys.secret));
    let bobpkey = fs::read("bobpublickey.pem").unwrap();
    let bobskey = fs::read("bobsecretkey.pem").unwrap();
    let bobpkey: [u8;KYBER_PUBLICKEYBYTES] = bobpkey[..KYBER_PUBLICKEYBYTES].try_into().unwrap();
    let bobskey: [u8;KYBER_SECRETKEYBYTES] = bobskey[..KYBER_SECRETKEYBYTES].try_into().unwrap();
    //let keys_bob = keypair(&mut rng)?;
    let keys_bob=Keypair {
        public: bobpkey,
        secret: bobskey
    };
    //Go to C to get the cipher to verify here.
    let ciphertext=fs::read_to_string("cipher.pem").unwrap();
    println!("Keys would be {}",ciphertext);
    let ciphertext = decodehex(&ciphertext.trim()).unwrap();
    // Alice encapsulates a shared secret using Bob's public key
    //let (ciphertext, shared_secret_alice) = encapsulate(&publickey, &mut rng)?;
    // Bob decapsulates a shared secret using the ciphertext sent by Alice
    let shared_secret_bob = decapsulate(&ciphertext, &keys_bob.secret)?;
    println!("Shared secret is {}",hex::encode(shared_secret_bob));
    Ok(())
}

However at the end, the shared secret is different :

Rust : 12d6dc3e341bb2afd57d7266d898771e6c25db3d28b3d321784dffec5b6f2401
C : fe3f00af8029fdfc22c84eb4f5ece5819ca9e373c94d72430623cc9fe21728fe

I don't know if I'm doing something wrong or if the implementation has some issues but the shared secret should be the same using same keys and same cipher.

Fails to build on M1 macOS (latest stable Rust) due to no_std

You get this, which after a dive into a rabbit hole seems caused by no_std. Commenting out the no_std directive in lib.rs gets rid of this. Note that I am using reference so no AVX2 errors are involved.

no_std should maybe be a feature flag?

   Compiling pqc_kyber v0.2.1
error: `#[panic_handler]` function required, but not found

error: language item required, but not found: `eh_personality`
  |
  = note: this can occur when a binary crate with `#![no_std]` is compiled for a target where `eh_personality` is defined in the standard library
  = help: you may be able to compile for a target that doesn't need `eh_personality`, specify a target with `--target` or in `.cargo/config`

error: could not compile `pqc_kyber` due to 2 previous errors

`std` as a default feature

Would be a breaking change for embedded devices but this should probably be done, most people want the error handling and the standard library.

Add a Misuse Resistant Hybrid API

Kyber should not be used by itself currently[1][2] in most cases. There's notes in the readme about this but always a chance of misuse with shiny new thing. We should have an easy to use/ hard to fuckup hybrid[3] mechanism.

The IETF TLS 1.3 draft proposal uses a simple concatenation[4]. OpenSSH currently uses concatenation then hashing for its sntrup761x25519 kem[5]. The other alternative here is xor'ing the shared secrets assuming they are the same size (a fair assumption).

I'd suggest Kyber768x25519 as an opinionated default, though it should be pluggable with other kem's as curve25519 isn't accepted by some companies/clouds/governments/standards bodies today and probably never will be.

[1] https://www.ietf.org/archive/id/draft-campagna-tls-bike-sike-hybrid-07.html

BIKE, Kyber and SIKE are post-quantum candidates which were submitted to the NIST Call for Proposals for Post-Quantum Cryptographic Schemes. While these schemes are still being analyzed as part of that process, there is already a need to protect the confidentiality of today's TLS connections against a future adversary with a quantum computer. Hybrid key exchanges are designed to provide two parallel key exchanges: one which is classical (e.g., ECDHE) and the other which is quantum-safe (e.g., SIKE). The hybrid schemes we propose are at least as secure as ECDH against a classical adversary, and at least as secure as the PQ KEM against a quantum adversary. This strategy is emerging as a method to speculatively provide additional security to existing protocols.

[2] https://eprint.iacr.org/2022/975.pdf

Our Magma implementation breaks the instantiation SIKEp434, which aims at security level 1
of the Post-Quantum Cryptography standardization process currently ran by
NIST, in about one hour on a single core.

[3] https://www.ietf.org/archive/id/draft-ietf-tls-hybrid-design-04.html#section-1.2

"Hybrid" key exchange, in this context, means the use of two (or more) key exchange algorithms based on different cryptographic assumptions, e.g., one traditional algorithm and one next-gen algorithm, with the purpose of the final session key being secure as long as at least one of the component key exchange algorithms remains unbroken.

[4] https://www.ietf.org/archive/id/draft-ietf-tls-hybrid-design-04.html#section-3

[5] https://github.com/openssh/openssh-portable/blob/master/kexsntrup761x25519.c#L103

Massive amounts of `clippy` warnings

After running:

git clone https://github.com/Argyle-Software/kyber kyber-clippy-test && cd kyber-clippy-test && cargo clippy --features=90s-fixslice -- -W clippy::pedantic -W clippy::correctness -W clippy::perf -W clippy::style -W clippy::suspicious -W clippy::complexity -A clippy::missing_errors_doc -W clippy::nursery -A clippy::module-name-repetitions -D warnings

I get a total of 547 errors, many of which could be pretty bad (I use even harsher lints in my lib.rs, there's a lot of warnings). Even with just cargo clippy --features=90s-fixslice I get 45 warnings.

I do also understand that these are some pretty harsh lints, and the lints I personally use in my work are even harsher, but I can't begin to imagine the amount of subtle bugs/performance issues they've solved - and my code is a lot more idiomatic.

The majority of the issues stem from needless borrowing or redundant slicing, but as_conversions are probably something to keep an eye on, as well as possible truncations.

I've forked the repo and started cleaning it up and making things more safe, but sadly I removed a lot of the functionality present here as it's not requried for our needs, otherwise I would've contributed my changes. I spent a few hours and got down to 140~ errors, most of which are now just as_conversions, which I'll still be fixing and making safe as I've had an issue with an as x conversion before that took far too long to debug, so now I use From/Into or their fallible counterparts.

This evidently isn't a major issue, so feel free to close it, I just wanted to bring attention to it as clippy is great at catching subtle mistakes. It could be good to add into CI too.

API Redesign & Ergonomics

The current API emulates the NIST code to follow along with the standardisation process. Now that is all done we can do a proper cleanup to make it more idiomatic along with general quality of life improvements. A non-comprehensive list of to-do's:

  • Keypair with no visible fields
  • Remove redundant public key field from Keypair
  • Runtime public key function to extract from secret key
  • Generate new Keypair struct from existing private key
  • Generate new Keypair struct from 64 byte seed
  • Encapsulation/Decapsulation function arguments accepting impl AsRef<PublicKey> / impl AsRef<SecretKey>
  • Keypair - impl Hash - For public key only, non-cryptographic hashes often used
  • Keypair - impl Debug - For public key only, elide secret key from any possible logging
  • Keypair - impl PartialEq - For public key only, make note in docs that it is not constant time
  • Keypair - impl Eq
  • Keypair - impl Zeroize - will require an alternative api using Pin/ Box along with documentation. Needs a locally instantiated SecretBuffer by the end user to prevent return value optimisations copying everything willynilly.
  • Replace type alias for SharedSecret with a concrete type, implement the same traits as for Keypair above.

Related to #59, it's preferable to get this all wrapped up into one release.

memfd support

So this is an investigative issue looking into a feature that implements memfd support for Linux and Android platforms. This can offer additional side-channel protection, though it isn't immune to kernel exploits.

Essentially returning a file descriptor instead of a keypair and then running the encapsulation/encapsulation on that is the preliminary starting point here.

Additional reading:

https://lwn.net/Articles/812325/

https://lwn.net/Articles/918106/

How to send encrypted public key to the server in Mutually Authenticated Key Exchange?

In examples/ake.rs we have this

  // Alice initiates key exchange with bob
  let client_send = alice.client_init(&bob_keys.public, &mut rng);
  
  // Bob receives the request and authenticates Alice, sends 
  // encapsulated shared secret back
  let server_send = bob.server_receive(
    client_send, &alice_keys.public, &bob_keys.secret, &mut rng
  )?;

To me, this assumes Alice sends an encrypted blob (client_send) and her public key (clear text) to Bob in order for Bob to do server_receive. But what if Alice is privacy-conscious and only wants to send her public key if its encrypted? Is this possible using the current tools in this crate?

encrypt custom messages

Can it encrypt custom messages to replace GPG? GPG is a program made by GNU project, it can encrypt user-inputted messages.

Use `aes` crate?

I noticed this crate vendors a portable bitsliced implementation of AES along with an AES-NI implementation which have been translated from the Kyber reference implementation.

Instead of that, I'd like to suggest using the aes crate from @RustCrypto. It includes a portable "fixsliced" implementation of AES, AES-NI support, and also support for the ARMv8 Cryptography Extensions. Additionally it implements runtime CPU feature detection on both x86 and ARM to determine if the hardware implementations are available, falling back to the portable implementations if not.

New release

In order to publish a version of our software on crates.io, we need all our dependencies to have a release version. Could you release a version after 8c7927e (we need the IND-CPA primitives)?

Using pqc-kyber NPM

I would really like to try and use the NPM package with the WASM implementation but am having issues
This relative module was not found:

This relative module was not found:
* ./pqc_kyber_bg.js in ./node_modules/pqc-kyber/pqc_kyber_bg.wasm  

Is there an example implementation around anywhere with the wasm exports being used?

I've also tried building it myself from this repo but am met with the "js" feature issue below. Unfortunately this was my first interaction with rust and I am unable to solve.

wasm-pack build -- --features wasm
[INFO]: Checking for the Wasm target...
[INFO]: Compiling to Wasm...
   Compiling proc-macro2 v1.0.27
   Compiling unicode-xid v0.2.2
   Compiling syn v1.0.72
   Compiling wasm-bindgen-shared v0.2.74
   Compiling log v0.4.14
   Compiling cfg-if v1.0.0
   Compiling bumpalo v3.7.0
   Compiling lazy_static v1.4.0
   Compiling cc v1.0.68
   Compiling wasm-bindgen v0.2.74
   Compiling getrandom v0.2.3
error: the wasm32-unknown-unknown target is not supported by default, you may need to enable the "js" feature. For more information see: https://docs.rs/getrandom/#webassembly-support
   --> /home/altfreq/.cargo/registry/src/github.com-1ecc6299db9ec823/getrandom-0.2.3/src/lib.rs:219:9
    |
219 | /         compile_error!("the wasm32-unknown-unknown target is not supported by \
220 | |                         default, you may need to enable the \"js\" feature. \
221 | |                         For more information see: \
222 | |                         https://docs.rs/getrandom/#webassembly-support");
    | |_________________________________________________________________________^

error[E0433]: failed to resolve: use of undeclared crate or module `imp`
   --> /home/altfreq/.cargo/registry/src/github.com-1ecc6299db9ec823/getrandom-0.2.3/src/lib.rs:246:5
    |
246 |     imp::getrandom_inner(dest)
    |     ^^^ use of undeclared crate or module `imp`

error: aborting due to 2 previous errors

For more information about this error, try `rustc --explain E0433`.
error: could not compile `getrandom`

To learn more, run the command again with --verbose.
warning: build failed, waiting for other jobs to finish...
error: build failed
Error: Compiling your crate to WebAssembly failed
Caused by: failed to execute `cargo build`: exited with exit code: 101
  full command: "cargo" "build" "--lib" "--release" "--target" "wasm32-unknown-unknown" "--features" "wasm"

Removing "90s"?

It might make sense to remove "90s" mode at some point since from what I can see on the mailing list it's not going to be standardized and therefore also will not fall under the carte blanche patent grant that only covers the standardized form.

Get criterion v0.5 working

As with the 0.4 release, things are now broken. Not urgent but would be nice to update the benchmarking suite.

References to kyber 764 which is not a standard

./Cargo.toml:# Defaults to "kyber764" if none selected
./readme.md:See the [**features**](#features) section for different options regarding security levels and modes of operation. The default security setting is kyber764.
./readme.md:If no security level is specified then kyber764 is used by default as recommended by the authors. It is roughly equivalent to AES-196.  Apart from the two security levels, all other features can be combined as needed. For example:
./src/avx2/indcpa.rs:  #[cfg(not(any(feature="kyber1024", feature="kyber512", feature="90s")))] // kyber764 
./src/avx2/indcpa.rs:    #[cfg(not(any(feature="kyber1024", feature="kyber512", feature="90s")))] // kyber764)
./src/lib.rs://! If no security level is set then Kyber764 is used, this is roughly equivalent to AES-196. See below for setting other levels. 
./tests/run_all_tests.sh:announce "Kyber764"
./tests/run_all_tests.sh:announce "Kyber764-90s"
./tests/run_all_tests.sh:announce "Reference Kyber764"
./tests/run_all_tests.sh:announce "Reference Kyber764-90s"
./tests/run_all_tests.sh:announce "Kyber764 KATs"
./tests/run_all_tests.sh:announce "Kyber764-90s KATs"
./tests/run_all_tests.sh:announce "Reference Kyber764 KATs"
./tests/run_all_tests.sh:announce "Reference Kyber764-90s KATs"

Please change those strings to 768 which is the actual standard (and which you actually implemented

Add rustfmt.toml file

tab_spaces = 2 
brace_style = "AlwaysNextLine"

brace_style requires nightly but you can alias it: cargo +nightly fmt

Fix readme

Incorrectly says avx2 is used by default.

Maybe a few other errors with recent changes .

Expose CPA primitives

Hello,

We are working on the hybridization of our scheme. We are using your library because it allows compiling to WASM. However, we would like to be able to use the CPA-Kyber primitives.

Could you consider making the reference module public?

Regards,

NSA suggestions

https://media.defense.gov/2022/Sep/07/2003071836/-1/-1/0/CSI_CNSA_2.0_FAQ_.PDF
Let's ses these 2 parts:
First: NSA suggests using Leighton-Micali Signature (LMS) or Xtended Merkle Signature Scheme (XMSS) to sign firmware or software. You should implement them in pure Rust.
Second:

Q: What is NSA’s position on the use of hybrid solutions?
A: NSA has confidence in CNSA 2.0 algorithms and will not require NSS developers to 
use hybrid certified products for security purposes. Product availability 
and interoperability requirements may lead to adopting hybrid solutions. NSA recognizes 
that some standards may require using hybrid-like constructions to accommodate the 
larger sizes of CRQC algorithms and will work with industry on the best options for 
implementation.

In my opinion, "product availability and interoperability" means compatibility for old browsers in WinXP and even Win10. So only when you're still using WinXP or even Win10, you use hybrid mode for your old browser. In my opinion, it's only for old browsers, Kyber is strong enough and works well without legacy cryptographies.

Fails to compile on Windows (x86_64-pc-windows-msvc)

Probably very related to #2. I just clone the master branch and run cargo build and I get the following:

log
$ cargo build
   Compiling pqc_kyber v0.2.1 (C:\Users\faern\src\kyber-master)
   Compiling synstructure v0.12.6
The following warnings were emitted during compilation:
warning: cl : Command line warning D9024 : unrecognized source file type 'src/avx2/basemul.S', object file assumed
warning: cl : Command line warning D9027 : source file 'src/avx2/basemul.S' ignored
warning: cl : Command line warning D9024 : unrecognized source file type 'src/avx2/fq.S', object file assumed
warning: cl : Command line warning D9027 : source file 'src/avx2/fq.S' ignored
warning: cl : Command line warning D9024 : unrecognized source file type 'src/avx2/invntt.S', object file assumed
warning: cl : Command line warning D9027 : source file 'src/avx2/invntt.S' ignored
warning: cl : Command line warning D9024 : unrecognized source file type 'src/avx2/ntt.S', object file assumed
warning: cl : Command line warning D9027 : source file 'src/avx2/ntt.S' ignored
warning: cl : Command line warning D9024 : unrecognized source file type 'src/avx2/shuffle.S', object file assumed
warning: cl : Command line warning D9027 : source file 'src/avx2/shuffle.S' ignored
error: failed to run custom build command for `pqc_kyber v0.2.1 (C:\Users\faern\src\kyber-master)`
Caused by:
  process didn't exit successfully: `C:\Users\faern\src\kyber-master\target\debug\build\pqc_kyber-de0e4d6bdeecf67b\build-script-build` (exit code: 1)
  --- stdout
  TARGET = Some("x86_64-pc-windows-msvc")
  OPT_LEVEL = Some("0")
  HOST = Some("x86_64-pc-windows-msvc")
  CC_x86_64-pc-windows-msvc = None
  CC_x86_64_pc_windows_msvc = None
  HOST_CC = None
  CC = None
  CFLAGS_x86_64-pc-windows-msvc = None
  CFLAGS_x86_64_pc_windows_msvc = None
  HOST_CFLAGS = None
  CFLAGS = None
  CRATE_CC_NO_DEFAULTS = None
  CARGO_CFG_TARGET_FEATURE = Some("fxsr,sse,sse2")
  DEBUG = Some("true")
  running: "C:\\Program Files (x86)\\Microsoft Visual Studio\\2019\\BuildTools\\VC\\Tools\\MSVC\\14.29.30133\\bin\\HostX64\\x64\\cl.exe" "-nologo" "-MD" "-Z7" "-Brepro" "-I" "src/avx2/" "-W4" "-FoC:\\Users\\faern\\src\\kyber-master\\target\\debug\\build\\pqc_kyber-4e4cd6b4fd1f06c6\\out\\src/avx2/basemul.o" "-c" "src/avx2/basemul.S"
  cargo:warning=cl : Command line warning D9024 : unrecognized source file type 'src/avx2/basemul.S', object file assumed
  cargo:warning=cl : Command line warning D9027 : source file 'src/avx2/basemul.S' ignored
  cl : Command line warning D9021 : no action performed
  exit code: 0
  running: "C:\\Program Files (x86)\\Microsoft Visual Studio\\2019\\BuildTools\\VC\\Tools\\MSVC\\14.29.30133\\bin\\HostX64\\x64\\cl.exe" "-nologo" "-MD" "-Z7" "-Brepro" "-I" "src/avx2/" "-W4" "-FoC:\\Users\\faern\\src\\kyber-master\\target\\debug\\build\\pqc_kyber-4e4cd6b4fd1f06c6\\out\\src/avx2/fq.o" "-c" "src/avx2/fq.S"
  cargo:warning=cl : Command line warning D9024 : unrecognized source file type 'src/avx2/fq.S', object file assumed
  cargo:warning=cl : Command line warning D9027 : source file 'src/avx2/fq.S' ignored
  cl : Command line warning D9021 : no action performed
  exit code: 0
  running: "C:\\Program Files (x86)\\Microsoft Visual Studio\\2019\\BuildTools\\VC\\Tools\\MSVC\\14.29.30133\\bin\\HostX64\\x64\\cl.exe" "-nologo" "-MD" "-Z7" "-Brepro" "-I" "src/avx2/" "-W4" "-FoC:\\Users\\faern\\src\\kyber-master\\target\\debug\\build\\pqc_kyber-4e4cd6b4fd1f06c6\\out\\src/avx2/invntt.o" "-c" "src/avx2/invntt.S"
  cargo:warning=cl : Command line warning D9024 : unrecognized source file type 'src/avx2/invntt.S', object file assumed
  cargo:warning=cl : Command line warning D9027 : source file 'src/avx2/invntt.S' ignored
  cl : Command line warning D9021 : no action performed
  exit code: 0
  running: "C:\\Program Files (x86)\\Microsoft Visual Studio\\2019\\BuildTools\\VC\\Tools\\MSVC\\14.29.30133\\bin\\HostX64\\x64\\cl.exe" "-nologo" "-MD" "-Z7" "-Brepro" "-I" "src/avx2/" "-W4" "-FoC:\\Users\\faern\\src\\kyber-master\\target\\debug\\build\\pqc_kyber-4e4cd6b4fd1f06c6\\out\\src/avx2/ntt.o" "-c" "src/avx2/ntt.S"
  cargo:warning=cl : Command line warning D9024 : unrecognized source file type 'src/avx2/ntt.S', object file assumed
  cargo:warning=cl : Command line warning D9027 : source file 'src/avx2/ntt.S' ignored
  cl : Command line warning D9021 : no action performed
  exit code: 0
  running: "C:\\Program Files (x86)\\Microsoft Visual Studio\\2019\\BuildTools\\VC\\Tools\\MSVC\\14.29.30133\\bin\\HostX64\\x64\\cl.exe" "-nologo" "-MD" "-Z7" "-Brepro" "-I" "src/avx2/" "-W4" "-FoC:\\Users\\faern\\src\\kyber-master\\target\\debug\\build\\pqc_kyber-4e4cd6b4fd1f06c6\\out\\src/avx2/shuffle.o" "-c" "src/avx2/shuffle.S"
  cargo:warning=cl : Command line warning D9024 : unrecognized source file type 'src/avx2/shuffle.S', object file assumed
  cargo:warning=cl : Command line warning D9027 : source file 'src/avx2/shuffle.S' ignored
  cl : Command line warning D9021 : no action performed
  exit code: 0
  AR_x86_64-pc-windows-msvc = None
  AR_x86_64_pc_windows_msvc = None
  HOST_AR = None
  AR = None
  running: "C:\\Program Files (x86)\\Microsoft Visual Studio\\2019\\BuildTools\\VC\\Tools\\MSVC\\14.29.30133\\bin\\HostX64\\x64\\lib.exe" "-out:C:\\Users\\faern\\src\\kyber-master\\target\\debug\\build\\pqc_kyber-4e4cd6b4fd1f06c6\\out\\libpqc_kyber.a" "-nologo" "C:\\Users\\faern\\src\\kyber-master\\target\\debug\\build\\pqc_kyber-4e4cd6b4fd1f06c6\\out\\src/avx2/basemul.o" "C:\\Users\\faern\\src\\kyber-master\\target\\debug\\build\\pqc_kyber-4e4cd6b4fd1f06c6\\out\\src/avx2/fq.o" "C:\\Users\\faern\\src\\kyber-master\\target\\debug\\build\\pqc_kyber-4e4cd6b4fd1f06c6\\out\\src/avx2/invntt.o" "C:\\Users\\faern\\src\\kyber-master\\target\\debug\\build\\pqc_kyber-4e4cd6b4fd1f06c6\\out\\src/avx2/ntt.o" "C:\\Users\\faern\\src\\kyber-master\\target\\debug\\build\\pqc_kyber-4e4cd6b4fd1f06c6\\out\\src/avx2/shuffle.o"
  LINK : fatal error LNK1181: cannot open input file 'C:\Users\faern\src\kyber-master\target\debug\build\pqc_kyber-4e4cd6b4fd1f06c6\out\src\avx2\basemul.o'
  exit code: 1181
  --- stderr
  error occurred: Command "C:\\Program Files (x86)\\Microsoft Visual Studio\\2019\\BuildTools\\VC\\Tools\\MSVC\\14.29.30133\\bin\\HostX64\\x64\\lib.exe" "-out:C:\\Users\\faern\\src\\kyber-master\\target\\debug\\build\\pqc_kyber-4e4cd6b4fd1f06c6\\out\\libpqc_kyber.a" "-nologo" "C:\\Users\\faern\\src\\kyber-master\\target\\debug\\build\\pqc_kyber-4e4cd6b4fd1f06c6\\out\\src/avx2/basemul.o" "C:\\Users\\faern\\src\\kyber-master\\target\\debug\\build\\pqc_kyber-4e4cd6b4fd1f06c6\\out\\src/avx2/fq.o" "C:\\Users\\faern\\src\\kyber-master\\target\\debug\\build\\pqc_kyber-4e4cd6b4fd1f06c6\\out\\src/avx2/invntt.o" "C:\\Users\\faern\\src\\kyber-master\\target\\debug\\build\\pqc_kyber-4e4cd6b4fd1f06c6\\out\\src/avx2/ntt.o" "C:\\Users\\faern\\src\\kyber-master\\target\\debug\\build\\pqc_kyber-4e4cd6b4fd1f06c6\\out\\src/avx2/shuffle.o" with args "lib.exe" did not execute successfully (status code exit code: 1181).
warning: build failed, waiting for other jobs to finish...

It works if I build for the gnu target (x86_64-pc-windows-gnu), but that's not the target I build my program for. It of course also works if activating the reference feature.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.