Add KyberFacade, add X25519 curve implementation

tutadb#1610
tutadb#1609
This commit is contained in:
paw 2023-09-25 16:25:43 +02:00 committed by vaf
parent fb75467806
commit 24a129a94d
154 changed files with 18845 additions and 6009 deletions

View file

@ -6,9 +6,7 @@ import androidx.test.platform.app.InstrumentationRegistry
import com.fasterxml.jackson.databind.ObjectMapper
import de.tutao.tutanota.AndroidNativeCryptoFacade.Companion.AES256_KEY_LENGTH_BYTES
import de.tutao.tutanota.AndroidNativeCryptoFacade.Companion.bytesToKey
import de.tutao.tutanota.ipc.RsaPrivateKey
import de.tutao.tutanota.ipc.RsaPublicKey
import de.tutao.tutanota.ipc.wrap
import de.tutao.tutanota.ipc.*
import de.tutao.tutanota.testdata.TestData
import kotlinx.coroutines.runBlocking
import org.apache.commons.io.output.ByteArrayOutputStream
@ -149,6 +147,31 @@ class CompatibilityTest {
}
}
@Test
@Throws(CryptoError::class)
fun kyber() = runBlocking {
for (td in testData.kyberEncryptionTests) {
// we need to use the same seed so that we always obtain the same encapsulation
val privateKey: KyberPrivateKey = hexToKyberPrivateKey(td.privateKey)
val publicKey: KyberPublicKey = hexToKyberPublicKey(td.publicKey)
val encapsulation = crypto.kyberEncapsulate(publicKey, hexToBytes(td.seed).wrap())
assertEquals(td.cipherText, bytesToHex(encapsulation.ciphertext.data))
assertEquals(td.sharedSecret, bytesToHex(encapsulation.sharedSecret.data))
val sharedSecret = crypto.kyberDecapsulate(privateKey, hexToBytes(td.cipherText).wrap())
assertEquals(td.sharedSecret, bytesToHex(sharedSecret.data))
}
}
private fun hexToKyberPrivateKey(privateKey: String): KyberPrivateKey {
val keyComponents = parseEncodedBytes(privateKey, 5)
return KyberPrivateKey(DataWrapper(keyComponents[0] + keyComponents[3] + keyComponents[4] + keyComponents[1] + keyComponents[2]))
}
private fun hexToKyberPublicKey(publicKey: String): KyberPublicKey {
val keyComponents = parseEncodedBytes(publicKey, 2)
return KyberPublicKey(DataWrapper(keyComponents[0] + keyComponents[1]))
}
companion object {
private const val TEST_DATA = "CompatibilityTestData.json"
private val om = ObjectMapper()
@ -229,6 +252,24 @@ class CompatibilityTest {
return String(hexChars)
}
fun parseEncodedBytes(hexKey: String, expectedParameters: Int): ArrayList<ByteArray> {
val paramBuffer = ArrayList<ByteArray>()
var pos = 0
while (pos < hexKey.length) {
val len = hexKey.substring(pos, pos + 4).toInt(16)
pos += 4
paramBuffer.add(hexToBytes(hexKey.substring(pos, pos + len)))
pos += len
}
if (hexKey.length != pos) {
throw CryptoError("invalid private key hex length")
}
if (paramBuffer.size != expectedParameters) {
throw CryptoError("invalid amount of key parameters. Expected: " + expectedParameters + " actual:" + paramBuffer.size)
}
return paramBuffer
}
private fun stubRandom(seed: String): SecureRandom {
return object : SecureRandom() {
@Synchronized

View file

@ -0,0 +1,58 @@
package de.tutao.tutanota.testdata;
/**
* Only convert to records after upgrading android to target API level 34 as this is copied to app-android!
*/
public class KyberTestData {
String publicKey;
String privateKey;
String cipherText;
String seed;
String sharedSecret;
public String getPublicKey() {
return publicKey;
}
public String getPrivateKey() {
return privateKey;
}
public String getCipherText() {
return cipherText;
}
public String getSeed() {
return seed;
}
public String getSharedSecret() {
return sharedSecret;
}
public KyberTestData setPublicKey(String publicKey) {
this.publicKey = publicKey;
return this;
}
public KyberTestData setPrivateKey(String privateKey) {
this.privateKey = privateKey;
return this;
}
public KyberTestData setCipherText(String cipherText) {
this.cipherText = cipherText;
return this;
}
public KyberTestData setSeed(String seed) {
this.seed = seed;
return this;
}
public KyberTestData setSharedSecret(String sharedSecret) {
this.sharedSecret = sharedSecret;
return this;
}
}

View file

@ -3,11 +3,13 @@ package de.tutao.tutanota.testdata;
import java.util.LinkedList;
import java.util.List;
/**
* Don't convert to records as this is copied to app-android!
*/
public class TestData {
List<EncryptionTestData> rsaEncryptionTests = new LinkedList<>();
List<KyberTestData> kyberEncryptionTests = new LinkedList<>();
List<SignatureTestData> rsaSignatureTests = new LinkedList<>();
List<AesTestData> aes256Tests = new LinkedList<>();
List<AesTestData> aes128Tests = new LinkedList<>();
@ -73,6 +75,10 @@ public class TestData {
return rsaEncryptionTests;
}
public List<KyberTestData> getKyberEncryptionTests() {
return kyberEncryptionTests;
}
public List<SignatureTestData> getRsaSignatureTests() {
return rsaSignatureTests;
}
@ -104,6 +110,7 @@ public class TestData {
public List<KdfTestData> getArgon2idTests() {
return argon2idTests;
}
public List<CompressionTestData> getCompressionTests() {
return compressionTests;
}

View file

@ -4,18 +4,67 @@ project("tutanota"
)
set(ARGON2_DIR "../../../../../libs/phc-winner-argon2")
set(LIBOQS_DIR "../../../../../libs/liboqs")
file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/include/oqs")
file(COPY
"${LIBOQS_DIR}/src/oqs.h"
"${LIBOQS_DIR}/src/common/common.h"
"${LIBOQS_DIR}/src/common/rand/rand.h"
"${LIBOQS_DIR}/src/common/aes/aes.h"
"${LIBOQS_DIR}/src/common/sha2/sha2.h"
"${LIBOQS_DIR}/src/common/sha3/sha3.h"
"${LIBOQS_DIR}/src/common/sha3/sha3x4.h"
"${LIBOQS_DIR}/src/kem/kyber/kem_kyber.h"
"${LIBOQS_DIR}/src/kem/kem.h"
"${LIBOQS_DIR}/src/sig/sig.h"
DESTINATION "${CMAKE_CURRENT_BINARY_DIR}/include/oqs"
)
file(TOUCH "${CMAKE_CURRENT_BINARY_DIR}/include/oqs/oqsconfig.h")
add_library(tutanota SHARED
tutanota.cpp
argon2.cpp
liboqs.cpp
helpers/byte_array_accessor.cpp
"${ARGON2_DIR}/src/argon2.c"
"${ARGON2_DIR}/src/core.c"
"${ARGON2_DIR}/src/encoding.c"
"${ARGON2_DIR}/src/ref.c"
"${ARGON2_DIR}/src/thread.c"
"${ARGON2_DIR}/src/blake2/blake2b.c"
"${LIBOQS_DIR}/src/kem/kem.c"
"${LIBOQS_DIR}/src/kem/kyber/pqcrystals-kyber_kyber1024_ref/kem.c"
"${LIBOQS_DIR}/src/kem/kyber/pqcrystals-kyber_kyber1024_ref/verify.c"
"${LIBOQS_DIR}/src/kem/kyber/pqcrystals-kyber_kyber1024_ref/indcpa.c"
"${LIBOQS_DIR}/src/kem/kyber/pqcrystals-kyber_kyber1024_ref/symmetric-shake.c"
"${LIBOQS_DIR}/src/kem/kyber/pqcrystals-kyber_kyber1024_ref/poly.c"
"${LIBOQS_DIR}/src/kem/kyber/pqcrystals-kyber_kyber1024_ref/polyvec.c"
"${LIBOQS_DIR}/src/kem/kyber/pqcrystals-kyber_kyber1024_ref/cbd.c"
"${LIBOQS_DIR}/src/kem/kyber/pqcrystals-kyber_kyber1024_ref/ntt.c"
"${LIBOQS_DIR}/src/kem/kyber/pqcrystals-kyber_kyber1024_ref/reduce.c"
"${LIBOQS_DIR}/src/kem/kyber/kem_kyber_1024.c"
"${LIBOQS_DIR}/src/common/pqclean_shims/fips202.c"
"${LIBOQS_DIR}/src/common/sha3/xkcp_sha3.c"
"${LIBOQS_DIR}/src/common/sha3/xkcp_low/KeccakP-1600/plain-64bits/KeccakP-1600-opt64.c"
"${LIBOQS_DIR}/src/common/common.c"
"../../../../../packages/tutanota-crypto/lib/encryption/Liboqs/rand.c"
)
target_include_directories(tutanota PRIVATE "${ARGON2_DIR}/include")
target_compile_definitions(tutanota
PRIVATE OQS_ENABLE_KEM_kyber_1024=1
PRIVATE OQS_VERSION_TEXT=\"tutakyber\"
PRIVATE OQS_ENABLE_KEM_kyber_1024=1
PRIVATE OQS_ENABLE_KEM_KYBER=1
PRIVATE KYBER_K=4
)
target_include_directories(tutanota
PRIVATE "${ARGON2_DIR}/include"
PRIVATE "${LIBOQS_DIR}/src/kem/kyber/pqcrystals-kyber_kyber1024_ref"
PRIVATE "${LIBOQS_DIR}/src/common/pqclean_shims"
PRIVATE "${CMAKE_CURRENT_BINARY_DIR}/include"
)
target_compile_options(tutanota PRIVATE "-O3")
set_property(TARGET tutanota PROPERTY CXX_STANDARD 17)

View file

@ -0,0 +1,44 @@
#include <jni.h>
#include "argon2.h"
#include <memory>
#include <string>
#include "helpers/byte_array_accessor.hpp"
#include "helpers/java_exception.hpp"
extern "C" JNIEXPORT jbyteArray JNICALL Java_de_tutao_tutanota_AndroidNativeCryptoFacade_argon2idHashRawImpl(
JNIEnv *env,
jobject pThis,
jbyteArray password,
jbyteArray salt,
jint timeCost,
jint memoryCost,
jint parallelism,
jint hashLength
) {
auto outBytes = ByteArrayAccessor(env, hashLength);
auto inPassword = ByteArrayAccessor(env, password);
auto inSalt = ByteArrayAccessor(env, salt);
auto retval = argon2id_hash_raw(timeCost,
memoryCost,
parallelism,
inPassword.getBytes(),
inPassword.getLength(),
inSalt.getBytes(),
inSalt.getLength(),
outBytes.getBytes(),
hashLength);
// zero out the password buffer (note: we can't do anything about the hash)
std::memset(inPassword.getBytes(), 0, inPassword.getLength());
if (retval != ARGON2_OK) {
JAVA_THROW_EXCEPTION("de/tutao/tutanota/CryptoError",
"argon2id_hash_raw returned %d: %s",
retval,
argon2_error_message(retval)
);
}
return outBytes.getByteArray();
}

View file

@ -0,0 +1,31 @@
#include "byte_array_accessor.hpp"
ByteArrayAccessor::ByteArrayAccessor(JNIEnv *env, jbyteArray byteArray) noexcept: env(env), byteArray(byteArray) {
this->bytes = env->GetByteArrayElements(byteArray, nullptr);
}
ByteArrayAccessor::ByteArrayAccessor(JNIEnv *env, jsize length) noexcept
: ByteArrayAccessor(env, env->NewByteArray(length)) {}
ByteArrayAccessor::~ByteArrayAccessor() noexcept {
this->env->ReleaseByteArrayElements(this->byteArray, this->bytes, 0);
}
jint ByteArrayAccessor::getLength() const noexcept {
return this->env->GetArrayLength(this->byteArray);
}
jbyte *ByteArrayAccessor::getBytes() const noexcept {
return this->bytes;
}
jbyteArray ByteArrayAccessor::getByteArray() const noexcept {
return this->byteArray;
}
jobject ByteArrayAccessor::createDataWrapper() const noexcept {
auto dataWrapperClass = this->env->FindClass("de/tutao/tutanota/ipc/DataWrapper");
return env->NewObject(dataWrapperClass,
env->GetMethodID(dataWrapperClass, "<init>", "([B)V"),
this->getByteArray());
}

View file

@ -0,0 +1,56 @@
#ifndef APP_ANDROID_BYTE_ARRAY_ACCESSOR_HPP
#define APP_ANDROID_BYTE_ARRAY_ACCESSOR_HPP
#include <memory>
#include <jni.h>
#include "non_copyable.hpp"
/**
* Container for holding byte arrays. Automatically releases the bytes pointer when out of scope.
*/
class ByteArrayAccessor {
NON_COPYABLE
public:
/**
* Instantiate with an existing byte array
* @param env java environment
* @param byteArray byte array
*/
ByteArrayAccessor(JNIEnv *env, jbyteArray byteArray) noexcept;
/**
* Instantiate a new byte array
* @param env java environment
* @param length length of new byte array
*/
ByteArrayAccessor(JNIEnv *env, jsize length) noexcept;
/**
* @return length of byte array
*/
jint getLength() const noexcept;
/**
* @return bytes pointer
*/
jbyte *getBytes() const noexcept;
/**
* @return byte array object
*/
jbyteArray getByteArray() const noexcept;
/**
* @return new IPC data wrapper
*/
jobject createDataWrapper() const noexcept;
~ByteArrayAccessor() noexcept;
private:
JNIEnv *env;
jbyte *bytes;
jbyteArray byteArray;
};
#endif

View file

@ -0,0 +1,19 @@
#ifndef APP_ANDROID_JAVA_EXCEPTION_HPP
#define APP_ANDROID_JAVA_EXCEPTION_HPP
/**
* Convenience function for queueing up an exception in the Java environment.
*
* Note that the JNI function will continue executing even with a pending exception (unlike throwing an exception in
* Java/Kotlin), but the return value will be ignored, and the exception will finally be thrown in the Java runtime upon
* completion.
*
* @param classPath path to the class, with path components separated with forward slashes (e.g. "java/lang/Exception")
*/
#define JAVA_THROW_EXCEPTION(classPath, ...) { \
char error[512]; \
std::snprintf(error, sizeof(error), __VA_ARGS__); \
env->ThrowNew(env->FindClass(classPath), error); \
}
#endif

View file

@ -0,0 +1,50 @@
#ifndef APP_ANDROID_KEM_HPP
#define APP_ANDROID_KEM_HPP
#include <oqs/kem.h>
#include <exception>
#include <string>
/**
* Container for instantiating and managing a KEM pointer.
*
* The pointer is automatically freed when it goes out of scope.
*/
class KEM {
NON_COPYABLE
public:
/**
* Instantiate a KEM pointer.
* @param methodName method name to use
* @throws KEMInitializeException if OQS_KEM_new failed for some reason (usually due to a bad method name)
*/
KEM(const char *methodName) : kem(OQS_KEM_new(methodName)) {
if (this->kem == nullptr) {
throw KEMInitializeException();
}
}
OQS_KEM *getKem() {
return this->kem;
}
~KEM() {
OQS_KEM_free(this->kem);
}
class KEMInitializeException : public std::exception {
public:
const char *what() const noexcept override {
return "KEM initialize failure";
}
};
operator OQS_KEM *() noexcept {
return this->getKem();
}
private:
OQS_KEM *kem;
};
#endif

View file

@ -0,0 +1,24 @@
#ifndef APP_ANDROID_NON_COPYABLE_HPP
#define APP_ANDROID_NON_COPYABLE_HPP
/**
* Used for making it impossible to copy an object. Useful if a class contains a pointer that must be unique but can't
* be freed trivally.
*/
class NonCopyable {
public:
NonCopyable() = default;
~NonCopyable() = default;
NonCopyable(const NonCopyable &) = delete;
NonCopyable &operator=(NonCopyable &) = delete;
};
/**
* Place in a class definition to make it non-copyable.
*/
#define NON_COPYABLE [[maybe_unused]] NonCopyable _nonCopyable;
#endif

View file

@ -0,0 +1,24 @@
#ifndef TUTA_RAND_H
#define TUTA_RAND_H
#include <cstdint>
#include <cstddef>
#ifdef __cplusplus
extern "C" {
#endif
/**
* Overwrite entropy with the contents of the buffer. Up to AMOUNT_OF_ENTROPY can be loaded at once.
*
* @param bytes random bytes to be generated by the caller (NOTE: take care to clear this buffer afterward!)
* @param amount number of bytes in the buffer
* @return how much entropy is left (negative value if the amount is greater than the size of the entropy pool)
*/
long TUTA_inject_entropy(const void *bytes, size_t amount);
#ifdef __cplusplus
}
#endif
#endif

View file

@ -0,0 +1,129 @@
#include <jni.h>
#include <memory>
#include <string>
#include <cstdio>
#include <oqs/kem.h>
#include "helpers/rand.h"
#include "helpers/java_exception.hpp"
#include "helpers/byte_array_accessor.hpp"
#include "helpers/kem.hpp"
static void fillEntropy(JNIEnv *env, jbyteArray seed);
// Guard to prevent UB
#define ASSERT_INPUT_LENGTH_EQUALS(name, expectedLength, actualLength) \
if((expectedLength) != (actualLength)) { \
JAVA_THROW_EXCEPTION("de/tutao/tutanota/CryptoError", "Bad input length for %s; expected %d, got %d instead", name, expectedLength, actualLength) \
return nullptr; \
}
extern "C" JNIEXPORT jobject JNICALL Java_de_tutao_tutanota_AndroidNativeCryptoFacade_generateKyberKeypairImpl(
JNIEnv *env,
jobject pThis,
jbyteArray seed
) {
fillEntropy(env, seed);
auto kyberKeyPairClass = env->FindClass("de/tutao/tutanota/ipc/KyberKeyPair");
auto kyberPrivateKeyClass = env->FindClass("de/tutao/tutanota/ipc/KyberPrivateKey");
auto kyberPublicKeyClass = env->FindClass("de/tutao/tutanota/ipc/KyberPublicKey");
auto publicKeyBytes = ByteArrayAccessor(env, OQS_KEM_kyber_1024_length_public_key);
auto privateKeyBytes = ByteArrayAccessor(env, OQS_KEM_kyber_1024_length_secret_key);
auto kyberPrivateKey = env->NewObject(kyberPrivateKeyClass,
env->GetMethodID(kyberPrivateKeyClass, "<init>",
"(Lde/tutao/tutanota/ipc/DataWrapper;)V"),
privateKeyBytes.createDataWrapper());
auto kyberPublicKey = env->NewObject(kyberPublicKeyClass,
env->GetMethodID(kyberPublicKeyClass, "<init>",
"(Lde/tutao/tutanota/ipc/DataWrapper;)V"),
publicKeyBytes.createDataWrapper());
auto kyberKeyPair = env->NewObject(kyberKeyPairClass,
env->GetMethodID(kyberKeyPairClass, "<init>",
"(Lde/tutao/tutanota/ipc/KyberPublicKey;Lde/tutao/tutanota/ipc/KyberPrivateKey;)V"),
kyberPublicKey, kyberPrivateKey);
OQS_STATUS result = OQS_KEM_keypair(KEM(OQS_KEM_alg_kyber_1024),
reinterpret_cast<std::uint8_t *>(publicKeyBytes.getBytes()),
reinterpret_cast<std::uint8_t *>(privateKeyBytes.getBytes()));
if (result != OQS_SUCCESS) {
JAVA_THROW_EXCEPTION("de/tutao/tutanota/CryptoError", "OQS_KEM_keypair returned %d", result);
}
return kyberKeyPair;
}
extern "C" JNIEXPORT jobject JNICALL Java_de_tutao_tutanota_AndroidNativeCryptoFacade_kyberEncapsulateImpl(
JNIEnv *env,
jobject pThis,
jbyteArray publicKey,
jbyteArray seed
) {
auto kyberEncapsulationClass = env->FindClass("de/tutao/tutanota/ipc/KyberEncapsulation");
auto publicKeyBytes = ByteArrayAccessor(env, publicKey);
auto cipherTextBytes = ByteArrayAccessor(env, OQS_KEM_kyber_1024_length_ciphertext);
auto sharedSecretBytes = ByteArrayAccessor(env, OQS_KEM_kyber_1024_length_shared_secret);
ASSERT_INPUT_LENGTH_EQUALS("public key", OQS_KEM_kyber_1024_length_public_key, publicKeyBytes.getLength())
fillEntropy(env, seed);
auto kyberEncapsulation = env->NewObject(kyberEncapsulationClass,
env->GetMethodID(kyberEncapsulationClass, "<init>",
"(Lde/tutao/tutanota/ipc/DataWrapper;Lde/tutao/tutanota/ipc/DataWrapper;)V"),
cipherTextBytes.createDataWrapper(),
sharedSecretBytes.createDataWrapper());
OQS_STATUS result = OQS_KEM_encaps(KEM(OQS_KEM_alg_kyber_1024),
reinterpret_cast<std::uint8_t *>(cipherTextBytes.getBytes()),
reinterpret_cast<std::uint8_t *>(sharedSecretBytes.getBytes()),
reinterpret_cast<std::uint8_t *>(publicKeyBytes.getBytes()));
if (result != OQS_SUCCESS) {
JAVA_THROW_EXCEPTION("de/tutao/tutanota/CryptoError", "OQS_KEM_encaps returned %d", result);
}
return kyberEncapsulation;
}
extern "C" JNIEXPORT jbyteArray JNICALL Java_de_tutao_tutanota_AndroidNativeCryptoFacade_kyberDecapsulateImpl(
JNIEnv *env,
jobject pThis,
jbyteArray ciphertext,
jbyteArray privateKey
) {
auto ciphertextBytes = ByteArrayAccessor(env, ciphertext);
auto privateKeyBytes = ByteArrayAccessor(env, privateKey);
auto sharedSecretBytes = ByteArrayAccessor(env, OQS_KEM_kyber_1024_length_shared_secret);
ASSERT_INPUT_LENGTH_EQUALS("private key", OQS_KEM_kyber_1024_length_secret_key, privateKeyBytes.getLength())
ASSERT_INPUT_LENGTH_EQUALS("cipher text", OQS_KEM_kyber_1024_length_ciphertext, ciphertextBytes.getLength())
OQS_STATUS result = OQS_KEM_decaps(KEM(OQS_KEM_alg_kyber_1024),
reinterpret_cast<std::uint8_t *>(sharedSecretBytes.getBytes()),
reinterpret_cast<std::uint8_t *>(ciphertextBytes.getBytes()),
reinterpret_cast<std::uint8_t *>(privateKeyBytes.getBytes()));
if (result != OQS_SUCCESS) {
JAVA_THROW_EXCEPTION("de/tutao/tutanota/CryptoError", "OQS_KEM_decaps returned %d", result);
}
return sharedSecretBytes.getByteArray();
}
static void fillEntropy(JNIEnv *env, jbyteArray seed) {
auto bytes = ByteArrayAccessor(env, seed);
// If amountWritten is negative, we passed too much entropy - programming error.
//
// We do not catch this, however, so be careful!
int amountWritten = TUTA_inject_entropy(bytes.getBytes(), bytes.getLength());
if (amountWritten < 0) {
std::fprintf(stderr, "Tried to inject too much entropy! Got %d bytes leftover\n", amountWritten);
}
}

View file

@ -1,51 +0,0 @@
#include <jni.h>
#include "argon2.h"
#include <memory>
#include <string>
static_assert(sizeof(jbyte) == sizeof(std::byte));
extern "C" JNIEXPORT jbyteArray JNICALL Java_de_tutao_tutanota_AndroidNativeCryptoFacade_argon2idHashRawImpl(
JNIEnv *env,
jobject pThis,
jbyteArray password,
jbyteArray salt,
jint timeCost,
jint memoryCost,
jint parallelism,
jint hashLength
) {
jbyteArray ret = env->NewByteArray(hashLength);
auto *outBytes = env->GetByteArrayElements(ret, nullptr);
auto *inPassword = env->GetByteArrayElements(password, nullptr);
auto *inSalt = env->GetByteArrayElements(salt, nullptr);
auto passwordLength = env->GetArrayLength(password);
auto saltLength = env->GetArrayLength(salt);
auto retval = argon2id_hash_raw(timeCost,
memoryCost,
parallelism,
inPassword,
passwordLength,
inSalt,
saltLength,
outBytes,
hashLength);
// zero out the password buffer (note: we can't do anything about the hash)
std::memset(inPassword, 0, passwordLength);
env->ReleaseByteArrayElements(ret, outBytes, 0);
env->ReleaseByteArrayElements(password, inPassword, 0);
env->ReleaseByteArrayElements(salt, inSalt, 0);
if (retval != ARGON2_OK) {
char error[256];
std::snprintf(error, sizeof(error), "argon2id_hash_raw returned %d: %s", retval, argon2_error_message(retval));
env->ThrowNew(env->FindClass("de/tutao/tutanota/CryptoError"), error);
}
return ret;
}

View file

@ -118,6 +118,30 @@ constructor(
)
}
@Throws(CryptoError::class)
override suspend fun generateKyberKeypair(seed: DataWrapper): KyberKeyPair {
return generateKyberKeypairImpl(seed.data)
}
@Throws(CryptoError::class)
private external fun generateKyberKeypairImpl(seed: ByteArray): KyberKeyPair
@Throws(CryptoError::class)
override suspend fun kyberEncapsulate(publicKey: KyberPublicKey, seed: DataWrapper): KyberEncapsulation {
return this.kyberEncapsulateImpl(publicKey.raw.data, seed.data)
}
@Throws(CryptoError::class)
private external fun kyberEncapsulateImpl(publicKey: ByteArray, seed: ByteArray): KyberEncapsulation
@Throws(CryptoError::class)
override suspend fun kyberDecapsulate(privateKey: KyberPrivateKey, ciphertext: DataWrapper): DataWrapper {
return DataWrapper(this.kyberDecapsulateImpl(ciphertext.data, privateKey.raw.data))
}
@Throws(CryptoError::class)
private external fun kyberDecapsulateImpl(ciphertext: ByteArray, privateKey: ByteArray): ByteArray
@Throws(CryptoError::class)
override suspend fun argon2idHashRaw(password: DataWrapper, salt: DataWrapper, timeCost: Int, memoryCost: Int, parallelism: Int, hashLength: Int): DataWrapper {
return DataWrapper(this.argon2idHashRawImpl(password.data, salt.data, timeCost, memoryCost, parallelism, hashLength))

View file

@ -11,7 +11,7 @@ class FileFacadeReceiveDispatcher(
private val json: Json,
private val facade: FileFacade,
) {
suspend fun dispatch(method: String, arg: List<String>): String {
when (method) {
"open" -> {
@ -58,7 +58,7 @@ class FileFacadeReceiveDispatcher(
)
return json.encodeToString(result)
}
"getSize" -> {
"getLength" -> {
val file: String = json.decodeFromString(arg[0])
val result: Int = this.facade.getSize(
file,

View file

@ -0,0 +1,14 @@
/* generated file, don't edit. */
package de.tutao.tutanota.ipc
import kotlinx.serialization.*
import kotlinx.serialization.json.*
@Serializable
data class KyberEncapsulation(
val ciphertext: DataWrapper,
val sharedSecret: DataWrapper,
)

View file

@ -0,0 +1,14 @@
/* generated file, don't edit. */
package de.tutao.tutanota.ipc
import kotlinx.serialization.*
import kotlinx.serialization.json.*
@Serializable
data class KyberKeyPair(
val publicKey: KyberPublicKey,
val privateKey: KyberPrivateKey,
)

View file

@ -0,0 +1,13 @@
/* generated file, don't edit. */
package de.tutao.tutanota.ipc
import kotlinx.serialization.*
import kotlinx.serialization.json.*
@Serializable
data class KyberPrivateKey(
val raw: DataWrapper,
)

View file

@ -0,0 +1,13 @@
/* generated file, don't edit. */
package de.tutao.tutanota.ipc
import kotlinx.serialization.*
import kotlinx.serialization.json.*
@Serializable
data class KyberPublicKey(
val raw: DataWrapper,
)

View file

@ -42,4 +42,15 @@ interface NativeCryptoFacade {
parallelism: Int,
hashLength: Int,
): DataWrapper
suspend fun generateKyberKeypair(
seed: DataWrapper,
): KyberKeyPair
suspend fun kyberEncapsulate(
publicKey: KyberPublicKey,
seed: DataWrapper,
): KyberEncapsulation
suspend fun kyberDecapsulate(
privateKey: KyberPrivateKey,
ciphertext: DataWrapper,
): DataWrapper
}

View file

@ -78,6 +78,31 @@ class NativeCryptoFacadeReceiveDispatcher(
)
return json.encodeToString(result)
}
"generateKyberKeypair" -> {
val seed: DataWrapper = json.decodeFromString(arg[0])
val result: KyberKeyPair = this.facade.generateKyberKeypair(
seed,
)
return json.encodeToString(result)
}
"kyberEncapsulate" -> {
val publicKey: KyberPublicKey = json.decodeFromString(arg[0])
val seed: DataWrapper = json.decodeFromString(arg[1])
val result: KyberEncapsulation = this.facade.kyberEncapsulate(
publicKey,
seed,
)
return json.encodeToString(result)
}
"kyberDecapsulate" -> {
val privateKey: KyberPrivateKey = json.decodeFromString(arg[0])
val ciphertext: DataWrapper = json.decodeFromString(arg[1])
val result: DataWrapper = this.facade.kyberDecapsulate(
privateKey,
ciphertext,
)
return json.encodeToString(result)
}
else -> throw Error("unknown method for NativeCryptoFacade: $method")
}
}

View file

@ -78,6 +78,71 @@
3D648B2C2AB98BEA00893C8D /* argon2.c in Sources */ = {isa = PBXBuildFile; fileRef = 3D648B1D2AB98BEA00893C8D /* argon2.c */; };
3D648B2D2AB98BEA00893C8D /* encoding.c in Sources */ = {isa = PBXBuildFile; fileRef = 3D648B1E2AB98BEA00893C8D /* encoding.c */; };
3D652B5820F8DC1600DF9962 /* build in Resources */ = {isa = PBXBuildFile; fileRef = 3D652B5720F8DC1500DF9962 /* build */; };
3D69DDF82AD441C000C6C900 /* KyberKeyPair.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3D69DDF72AD441C000C6C900 /* KyberKeyPair.swift */; };
3D69DDFB2AD441D100C6C900 /* KyberPublicKey.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3D69DDF92AD441D100C6C900 /* KyberPublicKey.swift */; };
3D69DDFC2AD441D100C6C900 /* KyberPrivateKey.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3D69DDFA2AD441D100C6C900 /* KyberPrivateKey.swift */; };
3D69DDFE2AD441F000C6C900 /* KyberEncapsulation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3D69DDFD2AD441F000C6C900 /* KyberEncapsulation.swift */; };
3D69DE002AD4427E00C6C900 /* Kyber.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3D69DDFF2AD4427E00C6C900 /* Kyber.swift */; };
3D69DEDE2AD445F700C6C900 /* LICENSE.txt in Resources */ = {isa = PBXBuildFile; fileRef = 3D69DE962AD445F600C6C900 /* LICENSE.txt */; };
3D69DEDF2AD445F700C6C900 /* sig.h in Headers */ = {isa = PBXBuildFile; fileRef = 3D69DE992AD445F600C6C900 /* sig.h */; };
3D69DEE02AD445F700C6C900 /* kem.c in Sources */ = {isa = PBXBuildFile; fileRef = 3D69DE9B2AD445F600C6C900 /* kem.c */; };
3D69DEE12AD445F700C6C900 /* symmetric-shake.c in Sources */ = {isa = PBXBuildFile; fileRef = 3D69DE9E2AD445F600C6C900 /* symmetric-shake.c */; };
3D69DEE22AD445F700C6C900 /* cbd.c in Sources */ = {isa = PBXBuildFile; fileRef = 3D69DE9F2AD445F600C6C900 /* cbd.c */; };
3D69DEE32AD445F700C6C900 /* ntt.c in Sources */ = {isa = PBXBuildFile; fileRef = 3D69DEA02AD445F600C6C900 /* ntt.c */; };
3D69DEE42AD445F700C6C900 /* poly.c in Sources */ = {isa = PBXBuildFile; fileRef = 3D69DEA12AD445F600C6C900 /* poly.c */; };
3D69DEE52AD445F700C6C900 /* params.h in Headers */ = {isa = PBXBuildFile; fileRef = 3D69DEA22AD445F700C6C900 /* params.h */; };
3D69DEE62AD445F700C6C900 /* polyvec.h in Headers */ = {isa = PBXBuildFile; fileRef = 3D69DEA32AD445F700C6C900 /* polyvec.h */; };
3D69DEE72AD445F700C6C900 /* LICENSE in Resources */ = {isa = PBXBuildFile; fileRef = 3D69DEA42AD445F700C6C900 /* LICENSE */; };
3D69DEE82AD445F700C6C900 /* reduce.c in Sources */ = {isa = PBXBuildFile; fileRef = 3D69DEA52AD445F700C6C900 /* reduce.c */; };
3D69DEE92AD445F700C6C900 /* verify.c in Sources */ = {isa = PBXBuildFile; fileRef = 3D69DEA62AD445F700C6C900 /* verify.c */; };
3D69DEEA2AD445F700C6C900 /* kem.c in Sources */ = {isa = PBXBuildFile; fileRef = 3D69DEA72AD445F700C6C900 /* kem.c */; };
3D69DEEB2AD445F700C6C900 /* indcpa.c in Sources */ = {isa = PBXBuildFile; fileRef = 3D69DEA82AD445F700C6C900 /* indcpa.c */; };
3D69DEEC2AD445F700C6C900 /* symmetric.h in Headers */ = {isa = PBXBuildFile; fileRef = 3D69DEA92AD445F700C6C900 /* symmetric.h */; };
3D69DEED2AD445F700C6C900 /* ntt.h in Headers */ = {isa = PBXBuildFile; fileRef = 3D69DEAA2AD445F700C6C900 /* ntt.h */; };
3D69DEEE2AD445F700C6C900 /* cbd.h in Headers */ = {isa = PBXBuildFile; fileRef = 3D69DEAB2AD445F700C6C900 /* cbd.h */; };
3D69DEEF2AD445F700C6C900 /* api.h in Headers */ = {isa = PBXBuildFile; fileRef = 3D69DEAC2AD445F700C6C900 /* api.h */; };
3D69DEF02AD445F700C6C900 /* reduce.h in Headers */ = {isa = PBXBuildFile; fileRef = 3D69DEAD2AD445F700C6C900 /* reduce.h */; };
3D69DEF12AD445F700C6C900 /* polyvec.c in Sources */ = {isa = PBXBuildFile; fileRef = 3D69DEAE2AD445F700C6C900 /* polyvec.c */; };
3D69DEF22AD445F700C6C900 /* poly.h in Headers */ = {isa = PBXBuildFile; fileRef = 3D69DEAF2AD445F700C6C900 /* poly.h */; };
3D69DEF32AD445F700C6C900 /* indcpa.h in Headers */ = {isa = PBXBuildFile; fileRef = 3D69DEB02AD445F700C6C900 /* indcpa.h */; };
3D69DEF42AD445F700C6C900 /* kem.h in Headers */ = {isa = PBXBuildFile; fileRef = 3D69DEB12AD445F700C6C900 /* kem.h */; };
3D69DEF52AD445F700C6C900 /* verify.h in Headers */ = {isa = PBXBuildFile; fileRef = 3D69DEB22AD445F700C6C900 /* verify.h */; };
3D69DEF62AD445F700C6C900 /* kem_kyber.h in Headers */ = {isa = PBXBuildFile; fileRef = 3D69DEB32AD445F700C6C900 /* kem_kyber.h */; };
3D69DEF72AD445F700C6C900 /* kem_kyber_1024.c in Sources */ = {isa = PBXBuildFile; fileRef = 3D69DEB42AD445F700C6C900 /* kem_kyber_1024.c */; };
3D69DEF82AD445F700C6C900 /* kem.h in Headers */ = {isa = PBXBuildFile; fileRef = 3D69DEB52AD445F700C6C900 /* kem.h */; };
3D69DEF92AD445F700C6C900 /* x86_64_helpers.h in Headers */ = {isa = PBXBuildFile; fileRef = 3D69DEB72AD445F700C6C900 /* x86_64_helpers.h */; };
3D69DEFA2AD445F700C6C900 /* common.c in Sources */ = {isa = PBXBuildFile; fileRef = 3D69DEB82AD445F700C6C900 /* common.c */; };
3D69DEFB2AD445F700C6C900 /* sha2.h in Headers */ = {isa = PBXBuildFile; fileRef = 3D69DEBA2AD445F700C6C900 /* sha2.h */; };
3D69DEFC2AD445F700C6C900 /* sha2_local.h in Headers */ = {isa = PBXBuildFile; fileRef = 3D69DEBB2AD445F700C6C900 /* sha2_local.h */; };
3D69DEFD2AD445F700C6C900 /* sha3x4.h in Headers */ = {isa = PBXBuildFile; fileRef = 3D69DEBD2AD445F700C6C900 /* sha3x4.h */; };
3D69DEFE2AD445F700C6C900 /* xkcp_dispatch.h in Headers */ = {isa = PBXBuildFile; fileRef = 3D69DEBE2AD445F700C6C900 /* xkcp_dispatch.h */; };
3D69DEFF2AD445F700C6C900 /* sha3.h in Headers */ = {isa = PBXBuildFile; fileRef = 3D69DEBF2AD445F700C6C900 /* sha3.h */; };
3D69DF002AD445F700C6C900 /* KeccakP-1600-unrolling.macros in Resources */ = {isa = PBXBuildFile; fileRef = 3D69DEC32AD445F700C6C900 /* KeccakP-1600-unrolling.macros */; };
3D69DF012AD445F700C6C900 /* KeccakP-1600-64.macros in Resources */ = {isa = PBXBuildFile; fileRef = 3D69DEC42AD445F700C6C900 /* KeccakP-1600-64.macros */; };
3D69DF022AD445F700C6C900 /* brg_endian.h in Headers */ = {isa = PBXBuildFile; fileRef = 3D69DEC52AD445F700C6C900 /* brg_endian.h */; };
3D69DF032AD445F700C6C900 /* KeccakP-1600-SnP.h in Headers */ = {isa = PBXBuildFile; fileRef = 3D69DEC62AD445F700C6C900 /* KeccakP-1600-SnP.h */; };
3D69DF042AD445F700C6C900 /* KeccakP-1600-opt64-config.h in Headers */ = {isa = PBXBuildFile; fileRef = 3D69DEC72AD445F700C6C900 /* KeccakP-1600-opt64-config.h */; };
3D69DF052AD445F700C6C900 /* KeccakP-1600-opt64.c in Sources */ = {isa = PBXBuildFile; fileRef = 3D69DEC82AD445F700C6C900 /* KeccakP-1600-opt64.c */; };
3D69DF062AD445F700C6C900 /* SnP-Relaned.h in Headers */ = {isa = PBXBuildFile; fileRef = 3D69DEC92AD445F700C6C900 /* SnP-Relaned.h */; };
3D69DF072AD445F700C6C900 /* xkcp_sha3.c in Sources */ = {isa = PBXBuildFile; fileRef = 3D69DECA2AD445F700C6C900 /* xkcp_sha3.c */; };
3D69DF082AD445F700C6C900 /* fips202.h in Headers */ = {isa = PBXBuildFile; fileRef = 3D69DECC2AD445F700C6C900 /* fips202.h */; };
3D69DF092AD445F700C6C900 /* randombytes.h in Headers */ = {isa = PBXBuildFile; fileRef = 3D69DECD2AD445F700C6C900 /* randombytes.h */; };
3D69DF0A2AD445F700C6C900 /* crypto_declassify.h in Headers */ = {isa = PBXBuildFile; fileRef = 3D69DECE2AD445F700C6C900 /* crypto_declassify.h */; };
3D69DF0B2AD445F700C6C900 /* nistseedexpander.h in Headers */ = {isa = PBXBuildFile; fileRef = 3D69DECF2AD445F700C6C900 /* nistseedexpander.h */; };
3D69DF0C2AD445F700C6C900 /* sha2.h in Headers */ = {isa = PBXBuildFile; fileRef = 3D69DED02AD445F700C6C900 /* sha2.h */; };
3D69DF0D2AD445F700C6C900 /* fips202.c in Sources */ = {isa = PBXBuildFile; fileRef = 3D69DED12AD445F700C6C900 /* fips202.c */; };
3D69DF0E2AD445F700C6C900 /* aes.h in Headers */ = {isa = PBXBuildFile; fileRef = 3D69DED22AD445F700C6C900 /* aes.h */; };
3D69DF0F2AD445F700C6C900 /* aes256ctr.h in Headers */ = {isa = PBXBuildFile; fileRef = 3D69DED32AD445F700C6C900 /* aes256ctr.h */; };
3D69DF102AD445F700C6C900 /* compat.h in Headers */ = {isa = PBXBuildFile; fileRef = 3D69DED42AD445F700C6C900 /* compat.h */; };
3D69DF112AD445F700C6C900 /* fips202x4.h in Headers */ = {isa = PBXBuildFile; fileRef = 3D69DED52AD445F700C6C900 /* fips202x4.h */; };
3D69DF122AD445F700C6C900 /* common.h in Headers */ = {isa = PBXBuildFile; fileRef = 3D69DED62AD445F700C6C900 /* common.h */; };
3D69DF132AD445F700C6C900 /* ossl_helpers.h in Headers */ = {isa = PBXBuildFile; fileRef = 3D69DED72AD445F700C6C900 /* ossl_helpers.h */; };
3D69DF142AD445F700C6C900 /* rand.h in Headers */ = {isa = PBXBuildFile; fileRef = 3D69DED92AD445F700C6C900 /* rand.h */; };
3D69DF152AD445F700C6C900 /* aes.h in Headers */ = {isa = PBXBuildFile; fileRef = 3D69DEDB2AD445F700C6C900 /* aes.h */; };
3D69DF162AD445F700C6C900 /* aes_local.h in Headers */ = {isa = PBXBuildFile; fileRef = 3D69DEDC2AD445F700C6C900 /* aes_local.h */; };
3D69DF172AD445F700C6C900 /* oqs.h in Headers */ = {isa = PBXBuildFile; fileRef = 3D69DEDD2AD445F700C6C900 /* oqs.h */; };
3D69DF352AD44D1E00C6C900 /* rand.c in Sources */ = {isa = PBXBuildFile; fileRef = 3D69DF332AD44D1E00C6C900 /* rand.c */; };
3D69DF362AD44D1E00C6C900 /* rand.h in Headers */ = {isa = PBXBuildFile; fileRef = 3D69DF342AD44D1E00C6C900 /* rand.h */; };
3D6A0AEA212C1701001CD791 /* CompatibilityTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 3D6A0AE9212C1701001CD791 /* CompatibilityTest.m */; settings = {COMPILER_FLAGS = "-Itutanota/include"; }; };
3D73DA312731953E008E7A8A /* RemoteProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3D73DA302731953E008E7A8A /* RemoteProtocol.swift */; };
3D73DA3427319A91008E7A8A /* Operation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3D73DA3327319A91008E7A8A /* Operation.swift */; };
@ -173,6 +238,7 @@
3D9B12AF2721966C002B46A1 /* IdTuple.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3D9B12AE2721966C002B46A1 /* IdTuple.swift */; };
3D9B12B32721A1E2002B46A1 /* TUTErrorFactory.h in Headers */ = {isa = PBXBuildFile; fileRef = 3D9B12B12721A1E2002B46A1 /* TUTErrorFactory.h */; };
3D9B12B42721A1E2002B46A1 /* TUTErrorFactory.m in Sources */ = {isa = PBXBuildFile; fileRef = 3D9B12B22721A1E2002B46A1 /* TUTErrorFactory.m */; };
3D9CDA4F2AD58266000B9267 /* KyberTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3D9CDA4E2AD58266000B9267 /* KyberTest.swift */; };
3DA047BF212C1BBE0062C36C /* CompatibilityTestData.json in Resources */ = {isa = PBXBuildFile; fileRef = 3DA047BE212C1BBD0062C36C /* CompatibilityTestData.json */; };
3DAA23A9267A208200219051 /* UIColorExtensionsTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3DAA23A8267A208200219051 /* UIColorExtensionsTest.swift */; };
3DAED2AF29A6267D00806DEA /* NotificationsHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3DAED2AE29A6267D00806DEA /* NotificationsHandler.swift */; };
@ -340,6 +406,71 @@
3D648B1D2AB98BEA00893C8D /* argon2.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = argon2.c; sourceTree = "<group>"; };
3D648B1E2AB98BEA00893C8D /* encoding.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = encoding.c; sourceTree = "<group>"; };
3D652B5720F8DC1500DF9962 /* build */ = {isa = PBXFileReference; lastKnownFileType = folder; name = build; path = ../../build; sourceTree = "<group>"; };
3D69DDF72AD441C000C6C900 /* KyberKeyPair.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = KyberKeyPair.swift; sourceTree = "<group>"; };
3D69DDF92AD441D100C6C900 /* KyberPublicKey.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = KyberPublicKey.swift; sourceTree = "<group>"; };
3D69DDFA2AD441D100C6C900 /* KyberPrivateKey.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = KyberPrivateKey.swift; sourceTree = "<group>"; };
3D69DDFD2AD441F000C6C900 /* KyberEncapsulation.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = KyberEncapsulation.swift; sourceTree = "<group>"; };
3D69DDFF2AD4427E00C6C900 /* Kyber.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Kyber.swift; sourceTree = "<group>"; };
3D69DE962AD445F600C6C900 /* LICENSE.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = LICENSE.txt; sourceTree = "<group>"; };
3D69DE992AD445F600C6C900 /* sig.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = sig.h; sourceTree = "<group>"; };
3D69DE9B2AD445F600C6C900 /* kem.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = kem.c; sourceTree = "<group>"; };
3D69DE9E2AD445F600C6C900 /* symmetric-shake.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "symmetric-shake.c"; sourceTree = "<group>"; };
3D69DE9F2AD445F600C6C900 /* cbd.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = cbd.c; sourceTree = "<group>"; };
3D69DEA02AD445F600C6C900 /* ntt.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ntt.c; sourceTree = "<group>"; };
3D69DEA12AD445F600C6C900 /* poly.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = poly.c; sourceTree = "<group>"; };
3D69DEA22AD445F700C6C900 /* params.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = params.h; sourceTree = "<group>"; };
3D69DEA32AD445F700C6C900 /* polyvec.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = polyvec.h; sourceTree = "<group>"; };
3D69DEA42AD445F700C6C900 /* LICENSE */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = LICENSE; sourceTree = "<group>"; };
3D69DEA52AD445F700C6C900 /* reduce.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = reduce.c; sourceTree = "<group>"; };
3D69DEA62AD445F700C6C900 /* verify.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = verify.c; sourceTree = "<group>"; };
3D69DEA72AD445F700C6C900 /* kem.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = kem.c; sourceTree = "<group>"; };
3D69DEA82AD445F700C6C900 /* indcpa.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = indcpa.c; sourceTree = "<group>"; };
3D69DEA92AD445F700C6C900 /* symmetric.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = symmetric.h; sourceTree = "<group>"; };
3D69DEAA2AD445F700C6C900 /* ntt.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ntt.h; sourceTree = "<group>"; };
3D69DEAB2AD445F700C6C900 /* cbd.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = cbd.h; sourceTree = "<group>"; };
3D69DEAC2AD445F700C6C900 /* api.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = api.h; sourceTree = "<group>"; };
3D69DEAD2AD445F700C6C900 /* reduce.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = reduce.h; sourceTree = "<group>"; };
3D69DEAE2AD445F700C6C900 /* polyvec.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = polyvec.c; sourceTree = "<group>"; };
3D69DEAF2AD445F700C6C900 /* poly.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = poly.h; sourceTree = "<group>"; };
3D69DEB02AD445F700C6C900 /* indcpa.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = indcpa.h; sourceTree = "<group>"; };
3D69DEB12AD445F700C6C900 /* kem.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = kem.h; sourceTree = "<group>"; };
3D69DEB22AD445F700C6C900 /* verify.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = verify.h; sourceTree = "<group>"; };
3D69DEB32AD445F700C6C900 /* kem_kyber.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = kem_kyber.h; sourceTree = "<group>"; };
3D69DEB42AD445F700C6C900 /* kem_kyber_1024.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = kem_kyber_1024.c; sourceTree = "<group>"; };
3D69DEB52AD445F700C6C900 /* kem.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = kem.h; sourceTree = "<group>"; };
3D69DEB72AD445F700C6C900 /* x86_64_helpers.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = x86_64_helpers.h; sourceTree = "<group>"; };
3D69DEB82AD445F700C6C900 /* common.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = common.c; sourceTree = "<group>"; };
3D69DEBA2AD445F700C6C900 /* sha2.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = sha2.h; sourceTree = "<group>"; };
3D69DEBB2AD445F700C6C900 /* sha2_local.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = sha2_local.h; sourceTree = "<group>"; };
3D69DEBD2AD445F700C6C900 /* sha3x4.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = sha3x4.h; sourceTree = "<group>"; };
3D69DEBE2AD445F700C6C900 /* xkcp_dispatch.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = xkcp_dispatch.h; sourceTree = "<group>"; };
3D69DEBF2AD445F700C6C900 /* sha3.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = sha3.h; sourceTree = "<group>"; };
3D69DEC32AD445F700C6C900 /* KeccakP-1600-unrolling.macros */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = "KeccakP-1600-unrolling.macros"; sourceTree = "<group>"; };
3D69DEC42AD445F700C6C900 /* KeccakP-1600-64.macros */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = "KeccakP-1600-64.macros"; sourceTree = "<group>"; };
3D69DEC52AD445F700C6C900 /* brg_endian.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = brg_endian.h; sourceTree = "<group>"; };
3D69DEC62AD445F700C6C900 /* KeccakP-1600-SnP.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "KeccakP-1600-SnP.h"; sourceTree = "<group>"; };
3D69DEC72AD445F700C6C900 /* KeccakP-1600-opt64-config.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "KeccakP-1600-opt64-config.h"; sourceTree = "<group>"; };
3D69DEC82AD445F700C6C900 /* KeccakP-1600-opt64.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = "KeccakP-1600-opt64.c"; sourceTree = "<group>"; };
3D69DEC92AD445F700C6C900 /* SnP-Relaned.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "SnP-Relaned.h"; sourceTree = "<group>"; };
3D69DECA2AD445F700C6C900 /* xkcp_sha3.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = xkcp_sha3.c; sourceTree = "<group>"; };
3D69DECC2AD445F700C6C900 /* fips202.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = fips202.h; sourceTree = "<group>"; };
3D69DECD2AD445F700C6C900 /* randombytes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = randombytes.h; sourceTree = "<group>"; };
3D69DECE2AD445F700C6C900 /* crypto_declassify.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = crypto_declassify.h; sourceTree = "<group>"; };
3D69DECF2AD445F700C6C900 /* nistseedexpander.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = nistseedexpander.h; sourceTree = "<group>"; };
3D69DED02AD445F700C6C900 /* sha2.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = sha2.h; sourceTree = "<group>"; };
3D69DED12AD445F700C6C900 /* fips202.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = fips202.c; sourceTree = "<group>"; };
3D69DED22AD445F700C6C900 /* aes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = aes.h; sourceTree = "<group>"; };
3D69DED32AD445F700C6C900 /* aes256ctr.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = aes256ctr.h; sourceTree = "<group>"; };
3D69DED42AD445F700C6C900 /* compat.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = compat.h; sourceTree = "<group>"; };
3D69DED52AD445F700C6C900 /* fips202x4.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = fips202x4.h; sourceTree = "<group>"; };
3D69DED62AD445F700C6C900 /* common.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = common.h; sourceTree = "<group>"; };
3D69DED72AD445F700C6C900 /* ossl_helpers.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ossl_helpers.h; sourceTree = "<group>"; };
3D69DED92AD445F700C6C900 /* rand.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = rand.h; sourceTree = "<group>"; };
3D69DEDB2AD445F700C6C900 /* aes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = aes.h; sourceTree = "<group>"; };
3D69DEDC2AD445F700C6C900 /* aes_local.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = aes_local.h; sourceTree = "<group>"; };
3D69DEDD2AD445F700C6C900 /* oqs.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = oqs.h; sourceTree = "<group>"; };
3D69DF332AD44D1E00C6C900 /* rand.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = rand.c; sourceTree = "<group>"; };
3D69DF342AD44D1E00C6C900 /* rand.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = rand.h; sourceTree = "<group>"; };
3D6A0AE9212C1701001CD791 /* CompatibilityTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CompatibilityTest.m; sourceTree = "<group>"; };
3D73DA302731953E008E7A8A /* RemoteProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RemoteProtocol.swift; sourceTree = "<group>"; };
3D73DA3327319A91008E7A8A /* Operation.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Operation.swift; sourceTree = "<group>"; };
@ -439,6 +570,7 @@
3D9B12AE2721966C002B46A1 /* IdTuple.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IdTuple.swift; sourceTree = "<group>"; };
3D9B12B12721A1E2002B46A1 /* TUTErrorFactory.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TUTErrorFactory.h; sourceTree = "<group>"; };
3D9B12B22721A1E2002B46A1 /* TUTErrorFactory.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TUTErrorFactory.m; sourceTree = "<group>"; };
3D9CDA4E2AD58266000B9267 /* KyberTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KyberTest.swift; sourceTree = "<group>"; };
3DA047BE212C1BBD0062C36C /* CompatibilityTestData.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = CompatibilityTestData.json; sourceTree = "<group>"; };
3DAA23A5267A202000219051 /* tutanotaTests-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "tutanotaTests-Bridging-Header.h"; sourceTree = "<group>"; };
3DAA23A8267A208200219051 /* UIColorExtensionsTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UIColorExtensionsTest.swift; sourceTree = "<group>"; };
@ -616,6 +748,193 @@
path = blake2;
sourceTree = "<group>";
};
3D69DE952AD445F600C6C900 /* liboqs */ = {
isa = PBXGroup;
children = (
3D69DE962AD445F600C6C900 /* LICENSE.txt */,
3D69DF322AD44D1E00C6C900 /* rand */,
3D69DE972AD445F600C6C900 /* src */,
);
path = liboqs;
sourceTree = "<group>";
};
3D69DE972AD445F600C6C900 /* src */ = {
isa = PBXGroup;
children = (
3D69DE982AD445F600C6C900 /* sig */,
3D69DE9A2AD445F600C6C900 /* kem */,
3D69DEB62AD445F700C6C900 /* common */,
3D69DEDD2AD445F700C6C900 /* oqs.h */,
);
path = src;
sourceTree = "<group>";
};
3D69DE982AD445F600C6C900 /* sig */ = {
isa = PBXGroup;
children = (
3D69DE992AD445F600C6C900 /* sig.h */,
);
path = sig;
sourceTree = "<group>";
};
3D69DE9A2AD445F600C6C900 /* kem */ = {
isa = PBXGroup;
children = (
3D69DE9B2AD445F600C6C900 /* kem.c */,
3D69DE9C2AD445F600C6C900 /* kyber */,
3D69DEB52AD445F700C6C900 /* kem.h */,
);
path = kem;
sourceTree = "<group>";
};
3D69DE9C2AD445F600C6C900 /* kyber */ = {
isa = PBXGroup;
children = (
3D69DE9D2AD445F600C6C900 /* pqcrystals-kyber_kyber1024_ref */,
3D69DEB32AD445F700C6C900 /* kem_kyber.h */,
3D69DEB42AD445F700C6C900 /* kem_kyber_1024.c */,
);
path = kyber;
sourceTree = "<group>";
};
3D69DE9D2AD445F600C6C900 /* pqcrystals-kyber_kyber1024_ref */ = {
isa = PBXGroup;
children = (
3D69DE9E2AD445F600C6C900 /* symmetric-shake.c */,
3D69DE9F2AD445F600C6C900 /* cbd.c */,
3D69DEA02AD445F600C6C900 /* ntt.c */,
3D69DEA12AD445F600C6C900 /* poly.c */,
3D69DEA22AD445F700C6C900 /* params.h */,
3D69DEA32AD445F700C6C900 /* polyvec.h */,
3D69DEA42AD445F700C6C900 /* LICENSE */,
3D69DEA52AD445F700C6C900 /* reduce.c */,
3D69DEA62AD445F700C6C900 /* verify.c */,
3D69DEA72AD445F700C6C900 /* kem.c */,
3D69DEA82AD445F700C6C900 /* indcpa.c */,
3D69DEA92AD445F700C6C900 /* symmetric.h */,
3D69DEAA2AD445F700C6C900 /* ntt.h */,
3D69DEAB2AD445F700C6C900 /* cbd.h */,
3D69DEAC2AD445F700C6C900 /* api.h */,
3D69DEAD2AD445F700C6C900 /* reduce.h */,
3D69DEAE2AD445F700C6C900 /* polyvec.c */,
3D69DEAF2AD445F700C6C900 /* poly.h */,
3D69DEB02AD445F700C6C900 /* indcpa.h */,
3D69DEB12AD445F700C6C900 /* kem.h */,
3D69DEB22AD445F700C6C900 /* verify.h */,
);
path = "pqcrystals-kyber_kyber1024_ref";
sourceTree = "<group>";
};
3D69DEB62AD445F700C6C900 /* common */ = {
isa = PBXGroup;
children = (
3D69DEB72AD445F700C6C900 /* x86_64_helpers.h */,
3D69DEB82AD445F700C6C900 /* common.c */,
3D69DEB92AD445F700C6C900 /* sha2 */,
3D69DEBC2AD445F700C6C900 /* sha3 */,
3D69DECB2AD445F700C6C900 /* pqclean_shims */,
3D69DED62AD445F700C6C900 /* common.h */,
3D69DED72AD445F700C6C900 /* ossl_helpers.h */,
3D69DED82AD445F700C6C900 /* rand */,
3D69DEDA2AD445F700C6C900 /* aes */,
);
path = common;
sourceTree = "<group>";
};
3D69DEB92AD445F700C6C900 /* sha2 */ = {
isa = PBXGroup;
children = (
3D69DEBA2AD445F700C6C900 /* sha2.h */,
3D69DEBB2AD445F700C6C900 /* sha2_local.h */,
);
path = sha2;
sourceTree = "<group>";
};
3D69DEBC2AD445F700C6C900 /* sha3 */ = {
isa = PBXGroup;
children = (
3D69DEBD2AD445F700C6C900 /* sha3x4.h */,
3D69DEBE2AD445F700C6C900 /* xkcp_dispatch.h */,
3D69DEBF2AD445F700C6C900 /* sha3.h */,
3D69DEC02AD445F700C6C900 /* xkcp_low */,
3D69DECA2AD445F700C6C900 /* xkcp_sha3.c */,
);
path = sha3;
sourceTree = "<group>";
};
3D69DEC02AD445F700C6C900 /* xkcp_low */ = {
isa = PBXGroup;
children = (
3D69DEC12AD445F700C6C900 /* KeccakP-1600 */,
);
path = xkcp_low;
sourceTree = "<group>";
};
3D69DEC12AD445F700C6C900 /* KeccakP-1600 */ = {
isa = PBXGroup;
children = (
3D69DEC22AD445F700C6C900 /* plain-64bits */,
);
path = "KeccakP-1600";
sourceTree = "<group>";
};
3D69DEC22AD445F700C6C900 /* plain-64bits */ = {
isa = PBXGroup;
children = (
3D69DEC32AD445F700C6C900 /* KeccakP-1600-unrolling.macros */,
3D69DEC42AD445F700C6C900 /* KeccakP-1600-64.macros */,
3D69DEC52AD445F700C6C900 /* brg_endian.h */,
3D69DEC62AD445F700C6C900 /* KeccakP-1600-SnP.h */,
3D69DEC72AD445F700C6C900 /* KeccakP-1600-opt64-config.h */,
3D69DEC82AD445F700C6C900 /* KeccakP-1600-opt64.c */,
3D69DEC92AD445F700C6C900 /* SnP-Relaned.h */,
);
path = "plain-64bits";
sourceTree = "<group>";
};
3D69DECB2AD445F700C6C900 /* pqclean_shims */ = {
isa = PBXGroup;
children = (
3D69DECC2AD445F700C6C900 /* fips202.h */,
3D69DECD2AD445F700C6C900 /* randombytes.h */,
3D69DECE2AD445F700C6C900 /* crypto_declassify.h */,
3D69DECF2AD445F700C6C900 /* nistseedexpander.h */,
3D69DED02AD445F700C6C900 /* sha2.h */,
3D69DED12AD445F700C6C900 /* fips202.c */,
3D69DED22AD445F700C6C900 /* aes.h */,
3D69DED32AD445F700C6C900 /* aes256ctr.h */,
3D69DED42AD445F700C6C900 /* compat.h */,
3D69DED52AD445F700C6C900 /* fips202x4.h */,
);
path = pqclean_shims;
sourceTree = "<group>";
};
3D69DED82AD445F700C6C900 /* rand */ = {
isa = PBXGroup;
children = (
3D69DED92AD445F700C6C900 /* rand.h */,
);
path = rand;
sourceTree = "<group>";
};
3D69DEDA2AD445F700C6C900 /* aes */ = {
isa = PBXGroup;
children = (
3D69DEDB2AD445F700C6C900 /* aes.h */,
3D69DEDC2AD445F700C6C900 /* aes_local.h */,
);
path = aes;
sourceTree = "<group>";
};
3D69DF322AD44D1E00C6C900 /* rand */ = {
isa = PBXGroup;
children = (
3D69DF332AD44D1E00C6C900 /* rand.c */,
3D69DF342AD44D1E00C6C900 /* rand.h */,
);
path = rand;
sourceTree = "<group>";
};
3D6C6D0522B7707B00289576 /* Keychain */ = {
isa = PBXGroup;
children = (
@ -672,12 +991,14 @@
3D891F002105B12E0031E528 /* TUTCrypto.m */,
3D891F1D2105BB200031E528 /* rsa_oaep_sha256.h */,
3D891EFD2105B12E0031E528 /* rsa_oaep_sha256.c */,
3D69DE952AD445F600C6C900 /* liboqs */,
3D648B0C2AB98BEA00893C8D /* phc-winner-argon2 */,
3DDE55232AB88D8300A77D14 /* AES.swift */,
3DF7FA592AB2EE3B00DB08D1 /* Argon2.swift */,
3D9B12A22721926E002B46A1 /* ValueEncryption.swift */,
3D84F5722722F35600858A58 /* IosNativeCryptoFacade.swift */,
3DB07C7A27303F0600BFBB4D /* Keys.swift */,
3D69DDFF2AD4427E00C6C900 /* Kyber.swift */,
3D9B12A22721926E002B46A1 /* ValueEncryption.swift */,
);
path = Crypto;
sourceTree = "<group>";
@ -1297,6 +1618,10 @@
3DBA56C42850AAA6004416BE /* UploadTaskResponse.swift */,
3DBA56C52850AAA6004416BE /* NativeKey.swift */,
3DBA56C62850AAA6004416BE /* CommonNativeFacade.swift */,
3D69DDF72AD441C000C6C900 /* KyberKeyPair.swift */,
3D69DDFA2AD441D100C6C900 /* KyberPrivateKey.swift */,
3D69DDF92AD441D100C6C900 /* KyberPublicKey.swift */,
3D69DDFD2AD441F000C6C900 /* KyberEncapsulation.swift */,
);
path = GeneratedIpc;
sourceTree = "<group>";
@ -1412,6 +1737,7 @@
3D4A426029B638D700B10451 /* AlarmManagerTest.swift */,
3DF7FA5D2AB2FBE700DB08D1 /* CompatibilityTestSwift.swift */,
3D1801532AB0B85100C72613 /* AlarmEntitiesTest.swift */,
3D9CDA4E2AD58266000B9267 /* KyberTest.swift */,
);
path = tutanotaTests;
sourceTree = "<group>";
@ -1446,17 +1772,57 @@
isa = PBXHeadersBuildPhase;
buildActionMask = 2147483647;
files = (
3D69DEF42AD445F700C6C900 /* kem.h in Headers */,
3D69DF122AD445F700C6C900 /* common.h in Headers */,
3D69DEF22AD445F700C6C900 /* poly.h in Headers */,
3D69DEF62AD445F700C6C900 /* kem_kyber.h in Headers */,
3D69DF062AD445F700C6C900 /* SnP-Relaned.h in Headers */,
3D648B222AB98BEA00893C8D /* core.h in Headers */,
3D69DEFF2AD445F700C6C900 /* sha3.h in Headers */,
3D69DEED2AD445F700C6C900 /* ntt.h in Headers */,
3D69DF112AD445F700C6C900 /* fips202x4.h in Headers */,
3D69DEF02AD445F700C6C900 /* reduce.h in Headers */,
3D69DF162AD445F700C6C900 /* aes_local.h in Headers */,
3D69DF092AD445F700C6C900 /* randombytes.h in Headers */,
3D69DEFC2AD445F700C6C900 /* sha2_local.h in Headers */,
3D69DF0C2AD445F700C6C900 /* sha2.h in Headers */,
3D648B292AB98BEA00893C8D /* encoding.h in Headers */,
3D69DEF52AD445F700C6C900 /* verify.h in Headers */,
3D69DF132AD445F700C6C900 /* ossl_helpers.h in Headers */,
3D648B242AB98BEA00893C8D /* blamka-round-opt.h in Headers */,
3D69DF022AD445F700C6C900 /* brg_endian.h in Headers */,
3D69DF142AD445F700C6C900 /* rand.h in Headers */,
3D4E3CAA28EC6787001FA9D1 /* sqlite3.h in Headers */,
3D69DEEC2AD445F700C6C900 /* symmetric.h in Headers */,
3D69DF042AD445F700C6C900 /* KeccakP-1600-opt64-config.h in Headers */,
3D69DF362AD44D1E00C6C900 /* rand.h in Headers */,
3D69DF0F2AD445F700C6C900 /* aes256ctr.h in Headers */,
3D69DEFD2AD445F700C6C900 /* sha3x4.h in Headers */,
3D69DEF82AD445F700C6C900 /* kem.h in Headers */,
3D9B12B32721A1E2002B46A1 /* TUTErrorFactory.h in Headers */,
3DCE7AAB27200E0A0085E40D /* WebviewHacks.h in Headers */,
3D69DEFE2AD445F700C6C900 /* xkcp_dispatch.h in Headers */,
3D69DF0B2AD445F700C6C900 /* nistseedexpander.h in Headers */,
3D69DF082AD445F700C6C900 /* fips202.h in Headers */,
3D69DEDF2AD445F700C6C900 /* sig.h in Headers */,
3D648B202AB98BEA00893C8D /* argon2.h in Headers */,
3D69DEF32AD445F700C6C900 /* indcpa.h in Headers */,
3D69DF102AD445F700C6C900 /* compat.h in Headers */,
3D648B232AB98BEA00893C8D /* blamka-round-ref.h in Headers */,
3D69DEFB2AD445F700C6C900 /* sha2.h in Headers */,
3D69DF152AD445F700C6C900 /* aes.h in Headers */,
3D69DEE52AD445F700C6C900 /* params.h in Headers */,
3D69DEF92AD445F700C6C900 /* x86_64_helpers.h in Headers */,
3D69DF0A2AD445F700C6C900 /* crypto_declassify.h in Headers */,
3D648B2B2AB98BEA00893C8D /* thread.h in Headers */,
3D648B252AB98BEA00893C8D /* blake2.h in Headers */,
3D69DF0E2AD445F700C6C900 /* aes.h in Headers */,
3D69DEEE2AD445F700C6C900 /* cbd.h in Headers */,
3D69DEEF2AD445F700C6C900 /* api.h in Headers */,
3D69DF032AD445F700C6C900 /* KeccakP-1600-SnP.h in Headers */,
3D648B272AB98BEA00893C8D /* blake2-impl.h in Headers */,
3D69DF172AD445F700C6C900 /* oqs.h in Headers */,
3D69DEE62AD445F700C6C900 /* polyvec.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@ -1667,6 +2033,7 @@
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
3D69DEDE2AD445F700C6C900 /* LICENSE.txt in Resources */,
3D652B5820F8DC1600DF9962 /* build in Resources */,
3D9A1F4222031B99002C2455 /* InfoPlist.strings in Resources */,
3D9A1F3C22031B99002C2455 /* InfoPlist.strings in Resources */,
@ -1692,9 +2059,11 @@
3D9A1F2C22031B99002C2455 /* InfoPlist.strings in Resources */,
3D9A1F1422031B99002C2455 /* InfoPlist.strings in Resources */,
3D9A1F4122031B99002C2455 /* InfoPlist.strings in Resources */,
3D69DF012AD445F700C6C900 /* KeccakP-1600-64.macros in Resources */,
3D9A1F1222031B99002C2455 /* InfoPlist.strings in Resources */,
3D9A1F1022031B99002C2455 /* InfoPlist.strings in Resources */,
3D9A1F0C22031B99002C2455 /* InfoPlist.strings in Resources */,
3D69DF002AD445F700C6C900 /* KeccakP-1600-unrolling.macros in Resources */,
3D9A1F3622031B99002C2455 /* InfoPlist.strings in Resources */,
3D9A1F1522031B99002C2455 /* InfoPlist.strings in Resources */,
3D9A1F1322031B99002C2455 /* InfoPlist.strings in Resources */,
@ -1702,6 +2071,7 @@
3D9A1F3722031B99002C2455 /* InfoPlist.strings in Resources */,
3D9A1F4622031B99002C2455 /* InfoPlist.strings in Resources */,
3D9A1F1622031B99002C2455 /* InfoPlist.strings in Resources */,
3D69DEE72AD445F700C6C900 /* LICENSE in Resources */,
3D9A1F2B22031B99002C2455 /* InfoPlist.strings in Resources */,
3D9A1F4422031B99002C2455 /* InfoPlist.strings in Resources */,
3D9A1F2122031B99002C2455 /* InfoPlist.strings in Resources */,
@ -1773,6 +2143,7 @@
3D3B516229376C2200C1B7DA /* SharingUtils.swift in Sources */,
3D220200293F752D00366FD2 /* WebAuthnSignResult.swift in Sources */,
3DBA56D32850AAA6004416BE /* ElectronResult.swift in Sources */,
3D69DDFE2AD441F000C6C900 /* KyberEncapsulation.swift in Sources */,
3DBA56C92850AAA6004416BE /* DownloadTaskResponse.swift in Sources */,
3DBA56CE2850AAA6004416BE /* IosGlobalDispatcher.swift in Sources */,
3DBA56CD2850AAA6004416BE /* NativeShortcut.swift in Sources */,
@ -1793,12 +2164,12 @@
3DC5DEC728576621007364FF /* NativeInterface.swift in Sources */,
3D220202293F752D00366FD2 /* WebauthnKeyDescriptor.swift in Sources */,
3DCE7AAC27200E0A0085E40D /* WebviewHacks.m in Sources */,
3D648B282AB98BEA00893C8D /* ref.c in Sources */,
3DCE7AA22719D04B0085E40D /* UserPreferenceFacade.swift in Sources */,
3D0EB1F626F489AD002E5102 /* KeychainManager.swift in Sources */,
3DBA56D22850AAA6004416BE /* ErrorInfo.swift in Sources */,
3D4A426929B6513900B10451 /* DateProvider.swift in Sources */,
3D92867C273A7D19006B8FB2 /* TutanotaError.swift in Sources */,
3D69DE002AD4427E00C6C900 /* Kyber.swift in Sources */,
3D3AFAE2285B0C350077F302 /* NativeContact.swift in Sources */,
3D891F082105B12F0031E528 /* rsa_oaep_sha256.c in Sources */,
3D2201F7293F750D00366FD2 /* WebAuthnFacadeReceiveDispatcher.swift in Sources */,
@ -1812,6 +2183,7 @@
3D891F0D2105B12F0031E528 /* TUTEncodingConverter.m in Sources */,
3D4E3CA228EC5C4F001FA9D1 /* IosSqlCipherFade.swift in Sources */,
3D0EB1FC26F4BEE4002E5102 /* AlarmManager.swift in Sources */,
3D69DDFB2AD441D100C6C900 /* KyberPublicKey.swift in Sources */,
3DBA56CA2850AAA6004416BE /* IpcClientRect.swift in Sources */,
3DCB9B8728F711220042A6BB /* SqlCipherStatement.swift in Sources */,
3DC299FD2673668000E1E79F /* QueryUtils.swift in Sources */,
@ -1819,7 +2191,6 @@
3D3AFAE4285B0C350077F302 /* IntegrationInfo.swift in Sources */,
3DBA56D42850AAA6004416BE /* UploadTaskResponse.swift in Sources */,
3DBA56CC2850AAA6004416BE /* ThemeFacadeReceiveDispatcher.swift in Sources */,
3D648B2A2AB98BEA00893C8D /* core.c in Sources */,
3DC299FA267358AF00E1E79F /* ThemeManager.swift in Sources */,
3D3AFAE8285B0DB60077F302 /* IosMobileSystemFacade.swift in Sources */,
3DDE55242AB88D8300A77D14 /* AES.swift in Sources */,
@ -1831,11 +2202,9 @@
3D97821A2739600700DB639C /* URLSession+Sync.swift in Sources */,
3DC5DEDB2858D6A9007364FF /* RsaKeyPair.swift in Sources */,
3D3AFAF2285CB2CF0077F302 /* IosCommonSystemFacade.swift in Sources */,
3D648B262AB98BEA00893C8D /* blake2b.c in Sources */,
3D84F57C27231F1F00858A58 /* Serialization.swift in Sources */,
3D2DB91B2733F43B00BCEF4C /* IosNativeCredentialsFacade.swift in Sources */,
3D4A426529B63E1E00B10451 /* AlarmPersistor.swift in Sources */,
3D4E3CA828EC63A6001FA9D1 /* sqlite3.c in Sources */,
3D84F56D2722CEF900858A58 /* FileUtils.swift in Sources */,
3D2201F8293F750D00366FD2 /* WebAuthnFacade.swift in Sources */,
3DCE7AA7271D63BF0085E40D /* ViewController.swift in Sources */,
@ -1843,7 +2212,6 @@
3D73DA3427319A91008E7A8A /* Operation.swift in Sources */,
3DC5DED82858CB58007364FF /* NativeCryptoFacadeReceiveDispatcher.swift in Sources */,
3DE46D2B2848EBDA00DC9D43 /* IosFileFacade.swift in Sources */,
3D648B212AB98BEA00893C8D /* thread.c in Sources */,
3D4A426729B6453700B10451 /* AlarmScheduler.swift in Sources */,
3DBA56D52850AAA6004416BE /* NativeKey.swift in Sources */,
3D4A426329B63C0E00B10451 /* AlarmCryptor.swift in Sources */,
@ -1854,6 +2222,7 @@
3DF7FA5A2AB2EE3B00DB08D1 /* Argon2.swift in Sources */,
3DBE94BA273147830077A6EA /* RemoteBridge.swift in Sources */,
3D84F5762723112400858A58 /* FileViewer.swift in Sources */,
3D69DDF82AD441C000C6C900 /* KyberKeyPair.swift in Sources */,
3DBA56C72850AAA6004416BE /* FileFacade.swift in Sources */,
3DBA56D12850AAA6004416BE /* CommonNativeFacadeSendDispatcher.swift in Sources */,
3D891F0B2105B12F0031E528 /* TUTCrypto.m in Sources */,
@ -1869,13 +2238,35 @@
3D2201FF293F752D00366FD2 /* WebAuthnRegistrationChallenge.swift in Sources */,
3D84F5732722F35600858A58 /* IosNativeCryptoFacade.swift in Sources */,
3DBA56C82850AAA6004416BE /* MobileFacadeSendDispatcher.swift in Sources */,
3D648B2C2AB98BEA00893C8D /* argon2.c in Sources */,
3D648B2D2AB98BEA00893C8D /* encoding.c in Sources */,
3D69DDFC2AD441D100C6C900 /* KyberPrivateKey.swift in Sources */,
3DC5DED92858CB58007364FF /* RsaPublicKey.swift in Sources */,
3D0EB1F926F49E36002E5102 /* AppDelegate.swift in Sources */,
3D3AFAE3285B0C350077F302 /* MobileSystemfacade.swift in Sources */,
3D9B129A27216DE0002B46A1 /* Response.swift in Sources */,
3D9B12AC27219623002B46A1 /* NotificationSessionKey.swift in Sources */,
3D4E3CA828EC63A6001FA9D1 /* sqlite3.c in Sources */,
3D648B282AB98BEA00893C8D /* ref.c in Sources */,
3D648B2A2AB98BEA00893C8D /* core.c in Sources */,
3D648B262AB98BEA00893C8D /* blake2b.c in Sources */,
3D648B212AB98BEA00893C8D /* thread.c in Sources */,
3D648B2C2AB98BEA00893C8D /* argon2.c in Sources */,
3D648B2D2AB98BEA00893C8D /* encoding.c in Sources */,
3D69DEE82AD445F700C6C900 /* reduce.c in Sources */,
3D69DF072AD445F700C6C900 /* xkcp_sha3.c in Sources */,
3D69DEEA2AD445F700C6C900 /* kem.c in Sources */,
3D69DEE32AD445F700C6C900 /* ntt.c in Sources */,
3D69DEE12AD445F700C6C900 /* symmetric-shake.c in Sources */,
3D69DEE92AD445F700C6C900 /* verify.c in Sources */,
3D69DEFA2AD445F700C6C900 /* common.c in Sources */,
3D69DEF12AD445F700C6C900 /* polyvec.c in Sources */,
3D69DEE02AD445F700C6C900 /* kem.c in Sources */,
3D69DEE22AD445F700C6C900 /* cbd.c in Sources */,
3D69DF052AD445F700C6C900 /* KeccakP-1600-opt64.c in Sources */,
3D69DEE42AD445F700C6C900 /* poly.c in Sources */,
3D69DEEB2AD445F700C6C900 /* indcpa.c in Sources */,
3D69DF0D2AD445F700C6C900 /* fips202.c in Sources */,
3D69DF352AD44D1E00C6C900 /* rand.c in Sources */,
3D69DEF72AD445F700C6C900 /* kem_kyber_1024.c in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@ -1884,6 +2275,7 @@
buildActionMask = 2147483647;
files = (
3D3B516629376E9E00C1B7DA /* ShareUtilsTest.swift in Sources */,
3D9CDA4F2AD58266000B9267 /* KyberTest.swift in Sources */,
3D6A0AEA212C1701001CD791 /* CompatibilityTest.m in Sources */,
3D63A0E5233D0C1400D05259 /* TUTLogTest.m in Sources */,
3D4A426129B638D700B10451 /* AlarmManagerTest.swift in Sources */,
@ -2569,7 +2961,11 @@
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
DEVELOPMENT_TEAM = JKCH89Z3M9;
"GCC_PREPROCESSOR_DEFINITIONS[arch=*]" = "SQLITE_HAS_CODEC=1";
GCC_PREPROCESSOR_DEFINITIONS = "";
"GCC_PREPROCESSOR_DEFINITIONS[arch=*]" = (
"SQLITE_HAS_CODEC=1",
"OQS_ENABLE_KEM_kyber_1024=1",
);
HEADER_SEARCH_PATHS = (
"\"$(TARGET_BUILD_DIR)/usr/local/lib/include\"",
"\"$(BUILT_PRODUCTS_DIR)\"",
@ -2592,8 +2988,13 @@
"-DSQLITE_TEMP_STORE=3",
"-DSQLCIPHER_CRYPTO_CC",
"-DNDEBUG",
"-DKYBER_K=4",
"-DOQS_VERSION_TEXT=\\\"whatever\\\"",
"-DOQS_ENABLE_KEM_kyber_1024=1",
"-DOQS_ENABLE_KEM_KYBER=1",
);
OTHER_LDFLAGS = "";
OTHER_SWIFT_FLAGS = "";
"OTHER_SWIFT_FLAGS[arch=*]" = "-D DEBUG";
PRODUCT_BUNDLE_IDENTIFIER = de.tutao.tutanota;
PRODUCT_NAME = "$(TARGET_NAME)";
@ -2617,7 +3018,11 @@
CODE_SIGN_IDENTITY = "iPhone Distribution";
CODE_SIGN_STYLE = Manual;
DEVELOPMENT_TEAM = JKCH89Z3M9;
"GCC_PREPROCESSOR_DEFINITIONS[arch=*]" = "SQLITE_HAS_CODEC=1";
GCC_PREPROCESSOR_DEFINITIONS = "";
"GCC_PREPROCESSOR_DEFINITIONS[arch=*]" = (
"SQLITE_HAS_CODEC=1",
"OQS_ENABLE_KEM_kyber_1024=1",
);
HEADER_SEARCH_PATHS = (
"\"$(TARGET_BUILD_DIR)/usr/local/lib/include\"",
"\"$(BUILT_PRODUCTS_DIR)\"",
@ -2640,8 +3045,13 @@
"-DSQLITE_TEMP_STORE=3",
"-DSQLCIPHER_CRYPTO_CC",
"-DNDEBUG",
"-DOQS_ENABLE_KEM_kyber_1024=1",
"-DOQS_VERSION_TEXT=\\\"whatever\\\"",
"-DKYBER_K=4",
"-DOQS_ENABLE_KEM_KYBER=1",
);
OTHER_LDFLAGS = "";
OTHER_SWIFT_FLAGS = "";
PRODUCT_BUNDLE_IDENTIFIER = de.tutao.tutanota;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE = "";
@ -2713,6 +3123,7 @@
CURRENT_PROJECT_VERSION = 1;
DEVELOPMENT_TEAM = JKCH89Z3M9;
GENERATE_INFOPLIST_FILE = YES;
HEADER_SEARCH_PATHS = "\"${PROJECT_DIR}/tutanota/include\"/**";
INFOPLIST_FILE = TutanotaShareExtension/Info.plist;
INFOPLIST_KEY_CFBundleDisplayName = TutanotaShareExtension;
INFOPLIST_KEY_NSHumanReadableCopyright = "Copyright © 2023 Tutao GmbH. All rights reserved.";
@ -2748,6 +3159,7 @@
DEVELOPMENT_TEAM = "";
"DEVELOPMENT_TEAM[sdk=iphoneos*]" = JKCH89Z3M9;
GENERATE_INFOPLIST_FILE = YES;
HEADER_SEARCH_PATHS = "\"${PROJECT_DIR}/tutanota/include\"/**";
INFOPLIST_FILE = TutanotaShareExtension/Info.plist;
INFOPLIST_KEY_CFBundleDisplayName = TutanotaShareExtension;
INFOPLIST_KEY_NSHumanReadableCopyright = "Copyright © 2023 Tutao GmbH. All rights reserved.";

View file

@ -108,17 +108,14 @@ private func aesDecrypt(data: Data, withKey key: Data, withPadding: Bool) throws
let data = [UInt8](data) // to allow for slicing
let useMAC = hasMAC(data)
let cKey: Data
let subKeys = try getSubKeys(withAESKey: key, withMAC: useMAC)
let ivOffset: Int
if useMAC {
let subKeys = try getSubKeys(withAESKey: key, withMAC: useMAC)
try verifyMAC(forData: data, withMKey: subKeys.mKey!)
cKey = subKeys.cKey
ivOffset = MAC_IDENTIFIER.count
}
else {
cKey = key
ivOffset = 0
}
@ -134,7 +131,7 @@ private func aesDecrypt(data: Data, withKey key: Data, withPadding: Bool) throws
var output: [UInt8] = []
output.reserveCapacity(encryptedData.count) // allocate upfront to avoid reallocation cost; this may be slightly more due to padding but that's OK
try aesDoCrypt(operation: CCOperation(kCCDecrypt), withKey: cKey, withData: encryptedData, toOutput: &output, withIV: Data(iv), withPadding: withPadding)
try aesDoCrypt(operation: CCOperation(kCCDecrypt), withKey: subKeys.cKey, withData: encryptedData, toOutput: &output, withIV: Data(iv), withPadding: withPadding)
return Data(output)
}

View file

@ -83,6 +83,18 @@ actor IosNativeCryptoFacade: NativeCryptoFacade {
withMemoryCost: UInt(memoryCost)
).wrap()
}
func generateKyberKeypair(_ seed: DataWrapper) async throws -> KyberKeyPair {
return try tutanota.generateKyberKeypair(withSeed: seed.data)
}
func kyberEncapsulate(_ publicKey: KyberPublicKey, _ seed: DataWrapper) async throws -> KyberEncapsulation {
return try tutanota.kyberEncapsulate(publicKey: publicKey, withSeed: seed.data)
}
func kyberDecapsulate(_ privateKey: KyberPrivateKey, _ ciphertext: DataWrapper) async throws -> DataWrapper {
return try tutanota.kyberDecapsulate(ciphertext: ciphertext.data, withPrivateKey: privateKey)
}
}
private func CryptoError(message: String) -> Error {

View file

@ -0,0 +1,102 @@
import Foundation
let KYBER_PUBLIC_KEY_LENGTH = Int(OQS_KEM_kyber_1024_length_public_key)
let KYBER_PRIVATE_KEY_LENGTH = Int(OQS_KEM_kyber_1024_length_secret_key)
let KYBER_CIPHER_TEXT_LENGTH = Int(OQS_KEM_kyber_1024_length_ciphertext)
let KYBER_SHARED_SECRET_LENGTH = Int(OQS_KEM_kyber_1024_length_shared_secret)
/// Generate a keypair for Kyber
///
/// - parameters:
/// - withSeed: random bytes to use for generating keys
func generateKyberKeypair(withSeed seed: Data) -> KyberKeyPair {
injectEntropy(seed: seed)
let kem = KEM(method: OQS_KEM_alg_kyber_1024)
var publicKeyBytes = [UInt8](repeating: 0, count: KYBER_PUBLIC_KEY_LENGTH)
var privateKeyBytes = [UInt8](repeating: 0, count: KYBER_PRIVATE_KEY_LENGTH)
let result = OQS_KEM_keypair(kem.kem, &publicKeyBytes, &privateKeyBytes)
guard result == OQS_SUCCESS else {
fatalError("OQS_KEM_keypair failed to generate a key: \(result)")
}
let publicKey = KyberPublicKey(raw: Data(publicKeyBytes).wrap())
let privateKey = KyberPrivateKey(raw: Data(privateKeyBytes).wrap())
return KyberKeyPair(publicKey: publicKey, privateKey: privateKey)
}
/// Derive a shared secret and a ciphertext from the public key and seed
///
/// - parameters:
/// - publicKey: public key to encrypt the secret
/// - withSeed: random bytes to use for generating the secret
func kyberEncapsulate(publicKey: KyberPublicKey, withSeed seed: Data) throws -> KyberEncapsulation {
try assertCorrectLength(of: publicKey.raw.data, withName: "public key", expectingLength: KYBER_PUBLIC_KEY_LENGTH)
injectEntropy(seed: seed)
let kem = KEM(method: OQS_KEM_alg_kyber_1024)
var cipherTextBytes = [UInt8](repeating: 0, count: KYBER_CIPHER_TEXT_LENGTH)
var sharedSecretBytes = [UInt8](repeating: 0, count: KYBER_SHARED_SECRET_LENGTH)
let result = publicKey.raw.data.withUnsafeBytes{publicKey in OQS_KEM_encaps(kem.kem, &cipherTextBytes, &sharedSecretBytes, publicKey.baseAddress)}
guard result == OQS_SUCCESS else {
throw TUTErrorFactory.createError(withDomain: TUT_CRYPTO_ERROR, message: "OQS_KEM_encaps failed to derive a shared secret and ciphertext: \(result)")
}
return KyberEncapsulation(ciphertext: Data(cipherTextBytes).wrap(), sharedSecret: Data(sharedSecretBytes).wrap())
}
/// Decrypt the ciphertext with the private key to get the shared secret
///
/// - parameters:
/// - ciphertext: ciphertext to decrypt
/// - withPrivateKey: private key to derive the secret from the ciphertext
func kyberDecapsulate(ciphertext: Data, withPrivateKey privateKey: KyberPrivateKey) throws -> DataWrapper {
try assertCorrectLength(of: privateKey.raw.data, withName: "private key", expectingLength: KYBER_PRIVATE_KEY_LENGTH)
try assertCorrectLength(of: ciphertext, withName: "cipher text", expectingLength: KYBER_CIPHER_TEXT_LENGTH)
let kem = KEM(method: OQS_KEM_alg_kyber_1024)
var sharedSecretBytes = [UInt8](repeating: 0, count: KYBER_SHARED_SECRET_LENGTH)
let result = privateKey.raw.data.withUnsafeBytes{privateKey in
ciphertext.withUnsafeBytes{ciphertext in
OQS_KEM_decaps(kem.kem, &sharedSecretBytes, ciphertext.baseAddress, privateKey.baseAddress)}}
guard result == OQS_SUCCESS else {
throw TUTErrorFactory.createError(withDomain: TUT_CRYPTO_ERROR, message: "OQS_KEM_encaps failed to derive a shared secret from ciphertext and private key: \(result)")
}
return Data(sharedSecretBytes).wrap()
}
private class KEM {
let kem: UnsafeMutablePointer<OQS_KEM>
init(method: String) {
guard let result = OQS_KEM_new(method) else {
fatalError("could not create OQS_KEM_new with OQS_KEM_alg_kyber_1024")
}
self.kem = result
}
deinit {
OQS_KEM_free(self.kem)
}
}
private func injectEntropy(seed: Data) {
let result = seed.withUnsafeBytes{seed in TUTA_inject_entropy(seed.baseAddress, seed.count)}
if result < 0 {
NSLog("TUTA_inject_entropy injected too much entropy (%d returned)", result)
}
}
private func assertCorrectLength(of data: Data, withName name: String, expectingLength: Int) throws {
if data.count != expectingLength {
throw TUTErrorFactory.createError(withDomain: TUT_CRYPTO_ERROR, message: "Incorrect \(name) length: \(expectingLength) expected, got \(data.count) instead")
}
}

View file

@ -0,0 +1 @@
../../../../libs/liboqs

View file

@ -0,0 +1,7 @@
/* generated file, don't edit. */
public struct KyberEncapsulation : Codable {
let ciphertext: DataWrapper
let sharedSecret: DataWrapper
}

View file

@ -0,0 +1,7 @@
/* generated file, don't edit. */
public struct KyberKeyPair : Codable {
let publicKey: KyberPublicKey
let privateKey: KyberPrivateKey
}

View file

@ -0,0 +1,6 @@
/* generated file, don't edit. */
public struct KyberPrivateKey : Codable {
let raw: DataWrapper
}

View file

@ -0,0 +1,6 @@
/* generated file, don't edit. */
public struct KyberPublicKey : Codable {
let raw: DataWrapper
}

View file

@ -39,4 +39,15 @@ public protocol NativeCryptoFacade {
_ parallelism: Int,
_ hashLength: Int
) async throws -> DataWrapper
func generateKyberKeypair(
_ seed: DataWrapper
) async throws -> KyberKeyPair
func kyberEncapsulate(
_ publicKey: KyberPublicKey,
_ seed: DataWrapper
) async throws -> KyberEncapsulation
func kyberDecapsulate(
_ privateKey: KyberPrivateKey,
_ ciphertext: DataWrapper
) async throws -> DataWrapper
}

View file

@ -68,6 +68,28 @@ public class NativeCryptoFacadeReceiveDispatcher {
hashLength
)
return toJson(result)
case "generateKyberKeypair":
let seed = try! JSONDecoder().decode(DataWrapper.self, from: arg[0].data(using: .utf8)!)
let result = try await self.facade.generateKyberKeypair(
seed
)
return toJson(result)
case "kyberEncapsulate":
let publicKey = try! JSONDecoder().decode(KyberPublicKey.self, from: arg[0].data(using: .utf8)!)
let seed = try! JSONDecoder().decode(DataWrapper.self, from: arg[1].data(using: .utf8)!)
let result = try await self.facade.kyberEncapsulate(
publicKey,
seed
)
return toJson(result)
case "kyberDecapsulate":
let privateKey = try! JSONDecoder().decode(KyberPrivateKey.self, from: arg[0].data(using: .utf8)!)
let ciphertext = try! JSONDecoder().decode(DataWrapper.self, from: arg[1].data(using: .utf8)!)
let result = try await self.facade.kyberDecapsulate(
privateKey,
ciphertext
)
return toJson(result)
default:
fatalError("licc messed up! \(method)")
}

View file

@ -10,3 +10,6 @@
#import "Crypto/TUTCrypto.h"
#include "Offline/sqlite3.h"
#import "argon2.h"
#include "rand.h"
#include <oqs/kem.h>
#include <oqs/kem_kyber.h>

View file

View file

@ -0,0 +1 @@
../../../libs/liboqs/include/oqs

File diff suppressed because one or more lines are too long

View file

@ -5,36 +5,36 @@ import XCTest
// used for testing Swift code
class CompatibilityTestSwift: XCTestCase {
var testData: [String: Any]?
override func setUp() async throws {
try await super.setUp()
let jsonUrl = Bundle(for: self.classForCoder).url(forResource: "CompatibilityTestData", withExtension: "json")!
let jsonData = try Data.init(contentsOf: jsonUrl)
self.testData = try JSONSerialization.jsonObject(with: jsonData) as? [String: Any]
}
func testArgon2id() {
// same parameters we use everywhere else
let ARGON2ID_HASH_LENGTH: Int = 32
let ARGON2ID_ITERATIONS: UInt = 4
let ARGON2ID_PARALLELISM: UInt = 1
let ARGON2ID_MEMORY_COST: UInt = 32 * 1024
let tests = (testData!["argon2idTests"] as? [[String: String]])!
for test in tests {
let password = TUTEncodingConverter.string(toBytes: test["password"]!)
let expectedHash = TUTEncodingConverter.hex(toBytes: test["keyHex"]!)
let salt = TUTEncodingConverter.hex(toBytes: test["saltHex"]!)
let result = try! generateArgon2idHash(ofPassword: password, ofHashLength: ARGON2ID_HASH_LENGTH, withSalt: salt, withIterations: ARGON2ID_ITERATIONS, withParallelism: ARGON2ID_PARALLELISM, withMemoryCost: ARGON2ID_MEMORY_COST)
XCTAssertEqual(expectedHash, result)
}
}
func testAes128() throws {
try doAes(testKey: "aes128Tests", withMAC: false)
let tests = (testData!["aes128Tests"] as? [[String: String]])!
for test in tests {
let key = TUTEncodingConverter.hex(toBytes: test["hexKey"]!)
@ -42,28 +42,28 @@ class CompatibilityTestSwift: XCTestCase {
let keyToEncrypt256 = TUTEncodingConverter.hex(toBytes: test["keyToEncrypt256"]!)
let encryptedKey128 = TUTEncodingConverter.base64(toBytes: test["encryptedKey128"]!)
let encryptedKey256 = TUTEncodingConverter.base64(toBytes: test["encryptedKey256"]!)
let resultingEncryptedKey128 = try aesEncryptKey(keyToEncrypt128, withKey: key)
let resultingEncryptedKey256 = try aesEncryptKey(keyToEncrypt256, withKey: key)
XCTAssertEqual(encryptedKey128, resultingEncryptedKey128)
XCTAssertEqual(encryptedKey256, resultingEncryptedKey256)
let resultingDecryptedKey128 = try aesDecryptKey(resultingEncryptedKey128, withKey: key)
let resultingDecryptedKey256 = try aesDecryptKey(resultingEncryptedKey256, withKey: key)
XCTAssertEqual(keyToEncrypt128, resultingDecryptedKey128)
XCTAssertEqual(keyToEncrypt256, resultingDecryptedKey256)
}
}
func testAes128Mac() throws {
try doAes(testKey: "aes128MacTests", withMAC: true)
// AES-128 with MAC is not used for keys, so it's not tested here
}
func testAes256() throws {
try doAes(testKey: "aes256Tests", withMAC: true)
let tests = (testData!["aes256Tests"] as? [[String: String]])!
for test in tests {
let key = TUTEncodingConverter.hex(toBytes: test["hexKey"]!)
@ -72,22 +72,22 @@ class CompatibilityTestSwift: XCTestCase {
let keyToEncrypt256 = TUTEncodingConverter.hex(toBytes: test["keyToEncrypt256"]!)
let encryptedKey128 = TUTEncodingConverter.base64(toBytes: test["encryptedKey128"]!)
let encryptedKey256 = TUTEncodingConverter.base64(toBytes: test["encryptedKey256"]!)
// aesEncrypt(key:withKey:) does not support passing in IVs, and AES and TUTCrypto do not currently support mocking, so we use the
// full aesEncrypt function that the key function would've called anyway
let resultingEncryptedKey128 = try aesEncrypt(data: keyToEncrypt128, withKey: key, withIV: iv, withPadding: false, withMAC: true)
let resultingEncryptedKey256 = try aesEncrypt(data: keyToEncrypt256, withKey: key, withIV: iv, withPadding: false, withMAC: true)
XCTAssertEqual(encryptedKey128, resultingEncryptedKey128)
XCTAssertEqual(encryptedKey256, resultingEncryptedKey256)
let resultingDecryptedKey128 = try aesDecryptKey(resultingEncryptedKey128, withKey: key)
let resultingDecryptedKey256 = try aesDecryptKey(resultingEncryptedKey256, withKey: key)
XCTAssertEqual(keyToEncrypt128, resultingDecryptedKey128)
XCTAssertEqual(keyToEncrypt256, resultingDecryptedKey256)
}
}
private func doAes(testKey: String, withMAC: Bool) throws {
let tests = (testData![testKey] as? [[String: Any]])!
for test in tests {
@ -95,11 +95,74 @@ class CompatibilityTestSwift: XCTestCase {
let plainText = TUTEncodingConverter.base64(toBytes: test["plainTextBase64"]! as! String)
let cipherText = TUTEncodingConverter.base64(toBytes: test["cipherTextBase64"]! as! String)
let key = TUTEncodingConverter.hex(toBytes: test["hexKey"]! as! String)
let encrypted = try aesEncrypt(data: plainText, withKey: key, withIV: iv, withPadding: true, withMAC: withMAC)
let decrypted = try aesDecryptData(encrypted, withKey: key)
XCTAssertEqual(cipherText, encrypted)
XCTAssertEqual(plainText, decrypted)
}
}
func testKyber() throws {
let tests = (testData!["kyberEncryptionTests"] as? [[String: Any]])!
for test in tests {
let publicKey = try kyberParsePublicKey(hex: test["publicKey"]! as! String)
let privateKey = try kyberParsePrivateKey(hex: test["privateKey"]! as! String)
let cipherTextBytes = TUTEncodingConverter.hex(toBytes: test["cipherText"]! as! String)
let sharedSecretBytes = TUTEncodingConverter.hex(toBytes: test["sharedSecret"]! as! String)
let seed = TUTEncodingConverter.hex(toBytes: test["seed"]! as! String)
let encaps = try kyberEncapsulate(publicKey: publicKey, withSeed: seed)
XCTAssertEqual(cipherTextBytes, encaps.ciphertext.data)
XCTAssertEqual(sharedSecretBytes, encaps.sharedSecret.data)
let decaps = try kyberDecapsulate(ciphertext: cipherTextBytes, withPrivateKey: privateKey)
XCTAssertEqual(sharedSecretBytes, decaps.data)
}
}
private func hexComponents(fromHex hex: String) throws -> [Data] {
let converted = TUTEncodingConverter.hex(toBytes: hex)
var offset = 0
var d = [Data]()
while offset < converted.count {
// Make sure we can read a full size
guard offset + 2 <= converted.count else {
throw TutanotaError(message: "Badly formatted hex components string (size cutoff)")
}
// Get the nibble count - ensure it's even!
let sizeNibbles = Int(converted[offset]) << 8 | Int(converted[offset + 1]) // big endian
guard sizeNibbles % 2 == 0 else {
throw TutanotaError(message: "Badly formatted hex components string (bad nibble size)")
}
// Convert nibbles to bytes and append it - ensure we have enough!
offset += 2
let sizeBytes = sizeNibbles / 2
guard offset + sizeBytes <= converted.count else {
throw TutanotaError(message: "Badly formatted hex components string (size cutoff)")
}
d.append(Data(converted[offset..<offset+sizeBytes]))
offset += sizeBytes
}
return d
}
private func kyberParsePublicKey(hex: String) throws -> KyberPublicKey {
// key is expected by oqs in the same order t, rho
let components = try hexComponents(fromHex: hex)
return KyberPublicKey(raw: DataWrapper(data:components[0] + components[1]))
}
private func kyberParsePrivateKey(hex: String) throws -> KyberPrivateKey {
// key is expected by oqs in this order (vs how we encode it on the server): s, t, rho, hpk, nonce
let components = try hexComponents(fromHex: hex)
return KyberPrivateKey(raw: DataWrapper(data:components[0] + components[3] + components[4] + components[1] + components[2]))
}
}

View file

@ -0,0 +1,28 @@
import Foundation
import XCTest
@testable import tutanota
class KyberTest : XCTestCase {
func testRoundTrip() throws {
let keypair = generateKyberKeypair(withSeed: generateRandomNumbers(count: 64))
let encaps = try kyberEncapsulate(publicKey: keypair.publicKey, withSeed: generateRandomNumbers(count: 64))
let decaps = try kyberDecapsulate(ciphertext: encaps.ciphertext.data, withPrivateKey: keypair.privateKey)
XCTAssertEqual(decaps.data, encaps.sharedSecret.data)
}
private func generateRandomNumbers(count: Int) -> Data {
var output = Data()
output.reserveCapacity(count)
var rng = SystemRandomNumberGenerator()
while output.count < count {
var random = rng.next()
let asBytes: [UInt8] = withUnsafeBytes(of: &random, Array.init)
output.append(contentsOf: asBytes)
}
output.count = count
return output
}
}

View file

@ -66,6 +66,7 @@ export async function buildWebapp({ version, stage, host, measure, minify, proje
const wasmDir = path.join(projectDir, "/build/wasm")
await fs.emptyDir(wasmDir)
await fs.copy(path.join(projectDir, "/packages/tutanota-crypto/lib/hashes/Argon2id/argon2.wasm"), path.join(wasmDir, "argon2.wasm"))
await fs.copy(path.join(projectDir, "/packages/tutanota-crypto/lib/encryption/Liboqs/liboqs.wasm"), path.join(wasmDir, "liboqs.wasm"))
console.log("started bundling", measure())
const bundle = await rollup({

View file

@ -5,35 +5,115 @@
"receivers": ["ios", "desktop", "android"],
"methods": {
"rsaEncrypt": {
"arg": [{ "publicKey": "RsaPublicKey" }, { "data": "bytes" }, { "seed": "bytes" }],
"arg": [
{
"publicKey": "RsaPublicKey"
},
{
"data": "bytes"
},
{
"seed": "bytes"
}
],
"ret": "bytes"
},
"rsaDecrypt": {
"arg": [{ "privateKey": "RsaPrivateKey" }, { "data": "bytes" }],
"arg": [
{
"privateKey": "RsaPrivateKey"
},
{
"data": "bytes"
}
],
"ret": "bytes"
},
"aesEncryptFile": {
"doc": "Encrypt file specified by the `fileUri`. Returns URI of the encrypted file.",
"arg": [{ "key": "bytes" }, { "fileUri": "string" }, { "iv": "bytes" }],
"arg": [
{
"key": "bytes"
},
{
"fileUri": "string"
},
{
"iv": "bytes"
}
],
"ret": "EncryptedFileInfo"
},
"aesDecryptFile": {
"doc": "Decrypt file specified by the `fileUri`. Returns URI of the decrypted file.",
"arg": [{ "key": "bytes" }, { "fileUri": "string" }],
"arg": [
{
"key": "bytes"
},
{
"fileUri": "string"
}
],
"ret": "string"
},
"generateRsaKey": {
"arg": [{ "seed": "bytes" }],
"arg": [
{
"seed": "bytes"
}
],
"ret": "RsaKeyPair"
},
"argon2idHashRaw": {
"arg": [
{ "password": "bytes" },
{ "salt": "bytes" },
{ "timeCost": "number" },
{ "memoryCost": "number" },
{ "parallelism": "number" },
{ "hashLength": "number" }
{
"password": "bytes"
},
{
"salt": "bytes"
},
{
"timeCost": "number"
},
{
"memoryCost": "number"
},
{
"parallelism": "number"
},
{
"hashLength": "number"
}
],
"ret": "bytes"
},
"generateKyberKeypair": {
"arg": [
{
"seed": "bytes"
}
],
"ret": "KyberKeyPair"
},
"kyberEncapsulate": {
"arg": [
{
"publicKey": "KyberPublicKey"
},
{
"seed": "bytes"
}
],
"ret": "KyberEncapsulation"
},
"kyberDecapsulate": {
"arg": [
{
"privateKey": "KyberPrivateKey"
},
{
"ciphertext": "bytes"
}
],
"ret": "bytes"
}

View file

@ -0,0 +1,8 @@
{
"name": "KyberEncapsulation",
"type": "struct",
"fields": {
"ciphertext": "bytes",
"sharedSecret": "bytes"
}
}

View file

@ -0,0 +1,8 @@
{
"name": "KyberKeyPair",
"type": "struct",
"fields": {
"publicKey": "KyberPublicKey",
"privateKey": "KyberPrivateKey"
}
}

View file

@ -0,0 +1,7 @@
{
"name": "KyberPrivateKey",
"type": "struct",
"fields": {
"raw": "bytes"
}
}

View file

@ -0,0 +1,7 @@
{
"name": "KyberPublicKey",
"type": "struct",
"fields": {
"raw": "bytes"
}
}

25
libs/liboqs/LICENSE.txt Normal file
View file

@ -0,0 +1,25 @@
The MIT license, the text of which is below, applies to liboqs in general.
liboqs includes some third party libraries or modules that are licensed
differently; the corresponding subfolder contains the license that applies in
that case.
Copyright (c) 2016-2021 Open Quantum Safe project
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View file

@ -0,0 +1,151 @@
/**
* \file aes.h
* \brief Header defining the API for OQS AES
*
* SPDX-License-Identifier: MIT
*/
#ifndef OQS_AES_H
#define OQS_AES_H
#include <stdint.h>
#include <stdlib.h>
#if defined(__cplusplus)
extern "C" {
#endif
/**
* Function to fill a key schedule given an initial key for use in ECB mode.
*
* @param key Initial Key.
* @param ctx Abstract data structure for a key schedule.
*/
void OQS_AES128_ECB_load_schedule(const uint8_t *key, void **ctx);
/**
* Function to free a key schedule.
*
* @param ctx Context generated with OQS_AES128_ECB_load_schedule().
*/
void OQS_AES128_free_schedule(void *ctx);
/**
* Function to encrypt blocks of plaintext using ECB mode.
* A schedule based on the key is generated and used internally.
*
* @param plaintext Plaintext to be encrypted.
* @param plaintext_len Length on the plaintext in bytes. Must be a multiple of 16.
* @param key Key to be used for encryption.
* @param ciphertext Pointer to a block of memory which >= in size to the plaintext block. The result will be written here.
* @warning plaintext_len must be a multiple of 16.
*/
void OQS_AES128_ECB_enc(const uint8_t *plaintext, const size_t plaintext_len, const uint8_t *key, uint8_t *ciphertext);
/**
* Same as OQS_AES128_ECB_enc() except a schedule generated by
* OQS_AES128_ECB_load_schedule() is passed rather then a key. This is faster
* if the same schedule is used for multiple encryptions since it does
* not have to be regenerated from the key.
*/
void OQS_AES128_ECB_enc_sch(const uint8_t *plaintext, const size_t plaintext_len, const void *schedule, uint8_t *ciphertext);
/**
* Function to fill a key schedule given an initial key for use in ECB mode encryption.
*
* @param key Initial Key.
* @param ctx Abstract data structure for a key schedule.
*/
void OQS_AES256_ECB_load_schedule(const uint8_t *key, void **ctx);
/**
* Function to initialize a context and fill a key schedule given an initial key for
* use in CTR mode.
*
* @param key Initial Key.
* @param ctx Abstract data structure for a key schedule.
*/
void OQS_AES256_CTR_inc_init(const uint8_t *key, void **ctx);
/**
* Function to fill a context given an IV for use in CTR mode.
*
* Handles a 12- or 16-byte IV. If a 12-byte IV is given, then 4 counter
* bytes are initialized to all zeros.
*
* @param iv Initialization Vector.
* @param iv_len Length of the initialization vector.
* @param ctx Abstract data structure for IV.
*/
void OQS_AES256_CTR_inc_iv(const uint8_t *iv, size_t iv_len, void *ctx);
/**
* Function to fill a context given an IV for use in CTR mode.
* Handles an 8-byte IV passed as a 64-bit unsigned integer,
* counter bytes are initialized to zero.
*
* @param iv Initialization Vector as 64-bit integer.
* @param ctx Abstract data structure for IV.
*/
void OQS_AES256_CTR_inc_ivu64(uint64_t iv, void *ctx);
/**
* Function to free a key schedule.
*
* @param ctx Schedule generated with OQS_AES256_ECB_load_schedule
* or OQS_AES256_CTR_inc_init.
*/
void OQS_AES256_free_schedule(void *ctx);
/**
* Function to encrypt blocks of plaintext using ECB mode.
* A schedule based on the key is generated and used internally.
*
* @param plaintext Plaintext to be encrypted.
* @param plaintext_len Length on the plaintext in bytes. Must be a multiple of 16.
* @param key Key to be used for encryption.
* @param ciphertext Pointer to a block of memory which >= in size to the plaintext block. The result will be written here.
* @warning plaintext_len must be a multiple of 16.
*/
void OQS_AES256_ECB_enc(const uint8_t *plaintext, const size_t plaintext_len, const uint8_t *key, uint8_t *ciphertext);
/**
* Same as OQS_AES256_ECB_enc() except a schedule generated by
* OQS_AES256_ECB_load_schedule() is passed rather then a key. This is faster
* if the same schedule is used for multiple encryptions since it does
* not have to be regenerated from the key.
*/
void OQS_AES256_ECB_enc_sch(const uint8_t *plaintext, const size_t plaintext_len, const void *schedule, uint8_t *ciphertext);
/**
* AES counter mode keystream generator. A context generated by
* OQS_AES256_CTR_inc_init() is passed rather then a key.
*
* Handles a 12- or 16-byte IV. If a 12-byte IV is given, then 4 counter
* bytes are initialized to all zeros.
*
* @param iv 12- or 16-byte initialization vector.
* @param iv_len Lengh of IV in bytes.
* @param ctx Abstract data structure for a key schedule.
* @param out Pointer to a block of memory which is big enough to contain out_len bytes; the result will be written here.
* @param out_len Length of output bytes to generate.
*/
void OQS_AES256_CTR_inc_stream_iv(const uint8_t *iv, size_t iv_len, const void *ctx, uint8_t *out, size_t out_len);
/**
* AES counter mode keystream generator. A context generated by
* OQS_AES256_CTR_inc_init() and OQS_AES256_CTR_inc_iv() is passed
* rather than a key and an IV. The counter is internally updated, which allows
* the function to be called multiple times.
*
* @param ctx Abstract data structure for key schedule and IV.
* @param out Pointer to a block of memory which is big enough to contain out_blks*16 bytes; the result will be written here.
* @param out_blks Length of output blocks to generate, where one block is 16 bytes.
*/
void OQS_AES256_CTR_inc_stream_blks(void *ctx, uint8_t *out, size_t out_blks);
#if defined(__cplusplus)
} // extern "C"
#endif
#endif // OQS_AES_H

View file

@ -0,0 +1,226 @@
/**
* \file common.h
* \brief Utility functions for use in liboqs.
*
* SPDX-License-Identifier: MIT
*/
#ifndef OQS_COMMON_H
#define OQS_COMMON_H
#include <limits.h>
#include <stdint.h>
#include <stdlib.h>
#include <stdio.h>
#include <oqs/oqsconfig.h>
#if defined(__cplusplus)
extern "C" {
#endif
/**
* Macro for terminating the program if x is
* a null pointer.
*/
#define OQS_EXIT_IF_NULLPTR(x, loc) \
do { \
if ( (x) == (void*)0 ) { \
fprintf(stderr, "Unexpected NULL returned from %s API. Exiting.\n", loc); \
exit(EXIT_FAILURE); \
} \
} while (0)
/**
* This macro is intended to replace those assert()s
* involving side-effecting statements in aes/aes_ossl.c.
*
* assert() becomes a no-op when -DNDEBUG is defined,
* which causes compilation failures when the statement
* being checked also results in side-effects.
*
* This is a temporary workaround until a better error
* handling strategy is developed.
*/
#define OQS_OPENSSL_GUARD(x) \
do { \
if( 1 != (x) ) { \
fprintf(stderr, "Error return value from OpenSSL API: %d. Exiting.\n", x); \
exit(EXIT_FAILURE); \
} \
} while (0)
/**
* Certain functions (such as OQS_randombytes_openssl in
* src/rand/rand.c) take in a size_t parameter, but can
* only handle values up to INT_MAX for those parameters.
* This macro is a temporary workaround for such functions.
*/
#define SIZE_T_TO_INT_OR_EXIT(size_t_var_name, int_var_name) \
int int_var_name = 0; \
if (size_t_var_name <= INT_MAX) { \
int_var_name = (int)size_t_var_name; \
} else { \
exit(EXIT_FAILURE); \
}
/**
* Defines which functions should be exposed outside the LibOQS library
*
* By default the visibility of all the symbols is defined to "hidden"
* Only the library API should be marked as default
*
* Example: OQS_API return_value function_name(void);
*/
#if defined(_WIN32)
#define OQS_API __declspec(dllexport)
#else
#define OQS_API __attribute__((visibility("default")))
#endif
#if defined(OQS_SYS_UEFI)
#undef OQS_API
#define OQS_API
#endif
/**
* Represents return values from functions.
*
* Callers should compare with the symbol rather than the individual value.
* For example,
*
* ret = OQS_KEM_encaps(...);
* if (ret == OQS_SUCCESS) { ... }
*
* rather than
*
* if (!OQS_KEM_encaps(...) { ... }
*
*/
typedef enum {
/** Used to indicate that some undefined error occurred. */
OQS_ERROR = -1,
/** Used to indicate successful return from function. */
OQS_SUCCESS = 0,
/** Used to indicate failures in external libraries (e.g., OpenSSL). */
OQS_EXTERNAL_LIB_ERROR_OPENSSL = 50,
} OQS_STATUS;
/**
* CPU runtime detection flags
*/
typedef enum {
OQS_CPU_EXT_INIT, /* Must be first */
/* Start extension list */
OQS_CPU_EXT_ADX,
OQS_CPU_EXT_AES,
OQS_CPU_EXT_AVX,
OQS_CPU_EXT_AVX2,
OQS_CPU_EXT_AVX512,
OQS_CPU_EXT_BMI1,
OQS_CPU_EXT_BMI2,
OQS_CPU_EXT_PCLMULQDQ,
OQS_CPU_EXT_VPCLMULQDQ,
OQS_CPU_EXT_POPCNT,
OQS_CPU_EXT_SSE,
OQS_CPU_EXT_SSE2,
OQS_CPU_EXT_SSE3,
OQS_CPU_EXT_ARM_AES,
OQS_CPU_EXT_ARM_SHA2,
OQS_CPU_EXT_ARM_SHA3,
OQS_CPU_EXT_ARM_NEON,
/* End extension list */
OQS_CPU_EXT_COUNT, /* Must be last */
} OQS_CPU_EXT;
/**
* Checks if the CPU supports a given extension
*
* \return 1 if the given CPU extension is available, 0 otherwise.
*/
OQS_API int OQS_CPU_has_extension(OQS_CPU_EXT ext);
/**
* This currently sets the values in the OQS_CPU_EXTENSIONS
* and prefetches the OpenSSL objects if necessary.
*/
OQS_API void OQS_init(void);
/**
* This function frees prefetched OpenSSL objects
*/
OQS_API void OQS_destroy(void);
/**
* Return library version string.
*/
OQS_API const char *OQS_version(void);
/**
* Constant time comparison of byte sequences `a` and `b` of length `len`.
* Returns 0 if the byte sequences are equal or if `len`=0.
* Returns 1 otherwise.
*
* @param[in] a A byte sequence of length at least `len`.
* @param[in] b A byte sequence of length at least `len`.
* @param[in] len The number of bytes to compare.
*/
OQS_API int OQS_MEM_secure_bcmp(const void *a, const void *b, size_t len);
/**
* Zeros out `len` bytes of memory starting at `ptr`.
*
* Designed to be protected against optimizing compilers which try to remove
* "unnecessary" operations. Should be used for all buffers containing secret
* data.
*
* @param[in] ptr The start of the memory to zero out.
* @param[in] len The number of bytes to zero out.
*/
OQS_API void OQS_MEM_cleanse(void *ptr, size_t len);
/**
* Zeros out `len` bytes of memory starting at `ptr`, then frees `ptr`.
*
* Can be called with `ptr = NULL`, in which case no operation is performed.
*
* Designed to be protected against optimizing compilers which try to remove
* "unnecessary" operations. Should be used for all buffers containing secret
* data.
*
* @param[in] ptr The start of the memory to zero out and free.
* @param[in] len The number of bytes to zero out.
*/
OQS_API void OQS_MEM_secure_free(void *ptr, size_t len);
/**
* Frees `ptr`.
*
* Can be called with `ptr = NULL`, in which case no operation is performed.
*
* Should only be used on non-secret data.
*
* @param[in] ptr The start of the memory to free.
*/
OQS_API void OQS_MEM_insecure_free(void *ptr);
/**
* Internal implementation of C11 aligned_alloc to work around compiler quirks.
*
* Allocates size bytes of uninitialized memory with a base pointer that is
* a multiple of alignment. Alignment must be a power of two and a multiple
* of sizeof(void *). Size must be a multiple of alignment.
*/
void *OQS_MEM_aligned_alloc(size_t alignment, size_t size);
/**
* Free memory allocated with OQS_MEM_aligned_alloc.
*/
void OQS_MEM_aligned_free(void *ptr);
#if defined(__cplusplus)
} // extern "C"
#endif
#endif // OQS_COMMON_H

View file

@ -0,0 +1,285 @@
/**
* \file kem.h
* \brief Key encapsulation mechanisms
*
* The file `tests/example_kem.c` contains two examples on using the OQS_KEM API.
*
* The first example uses the individual scheme's algorithms directly and uses
* no dynamic memory allocation -- all buffers are allocated on the stack, with
* sizes indicated using preprocessor macros. Since algorithms can be disabled at
* compile-time, the programmer should wrap the code in \#ifdefs.
*
* The second example uses an OQS_KEM object to use an algorithm specified at
* runtime. Therefore it uses dynamic memory allocation -- all buffers must be
* malloc'ed by the programmer, with sizes indicated using the corresponding length
* member of the OQS_KEM object in question. Since algorithms can be disabled at
* compile-time, the programmer should check that the OQS_KEM object is not `NULL`.
*
* SPDX-License-Identifier: MIT
*/
#ifndef OQS_KEM_H
#define OQS_KEM_H
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include <oqs/oqs.h>
#if defined(__cplusplus)
extern "C" {
#endif
/** Algorithm identifier for BIKE-L1 KEM (Round-4). */
#define OQS_KEM_alg_bike_l1 "BIKE-L1"
/** Algorithm identifier for BIKE-L3 KEM (Round-4). */
#define OQS_KEM_alg_bike_l3 "BIKE-L3"
/** Algorithm identifier for BIKE-L5 KEM (Round-4). */
#define OQS_KEM_alg_bike_l5 "BIKE-L5"
///// OQS_COPY_FROM_UPSTREAM_FRAGMENT_ALG_IDENTIFIER_START
/** Algorithm identifier for Classic-McEliece-348864 KEM. */
#define OQS_KEM_alg_classic_mceliece_348864 "Classic-McEliece-348864"
/** Algorithm identifier for Classic-McEliece-348864f KEM. */
#define OQS_KEM_alg_classic_mceliece_348864f "Classic-McEliece-348864f"
/** Algorithm identifier for Classic-McEliece-460896 KEM. */
#define OQS_KEM_alg_classic_mceliece_460896 "Classic-McEliece-460896"
/** Algorithm identifier for Classic-McEliece-460896f KEM. */
#define OQS_KEM_alg_classic_mceliece_460896f "Classic-McEliece-460896f"
/** Algorithm identifier for Classic-McEliece-6688128 KEM. */
#define OQS_KEM_alg_classic_mceliece_6688128 "Classic-McEliece-6688128"
/** Algorithm identifier for Classic-McEliece-6688128f KEM. */
#define OQS_KEM_alg_classic_mceliece_6688128f "Classic-McEliece-6688128f"
/** Algorithm identifier for Classic-McEliece-6960119 KEM. */
#define OQS_KEM_alg_classic_mceliece_6960119 "Classic-McEliece-6960119"
/** Algorithm identifier for Classic-McEliece-6960119f KEM. */
#define OQS_KEM_alg_classic_mceliece_6960119f "Classic-McEliece-6960119f"
/** Algorithm identifier for Classic-McEliece-8192128 KEM. */
#define OQS_KEM_alg_classic_mceliece_8192128 "Classic-McEliece-8192128"
/** Algorithm identifier for Classic-McEliece-8192128f KEM. */
#define OQS_KEM_alg_classic_mceliece_8192128f "Classic-McEliece-8192128f"
/** Algorithm identifier for HQC-128 KEM. */
#define OQS_KEM_alg_hqc_128 "HQC-128"
/** Algorithm identifier for HQC-192 KEM. */
#define OQS_KEM_alg_hqc_192 "HQC-192"
/** Algorithm identifier for HQC-256 KEM. */
#define OQS_KEM_alg_hqc_256 "HQC-256"
/** Algorithm identifier for Kyber512 KEM. */
#define OQS_KEM_alg_kyber_512 "Kyber512"
/** Algorithm identifier for Kyber768 KEM. */
#define OQS_KEM_alg_kyber_768 "Kyber768"
/** Algorithm identifier for Kyber1024 KEM. */
#define OQS_KEM_alg_kyber_1024 "Kyber1024"
///// OQS_COPY_FROM_UPSTREAM_FRAGMENT_ALG_IDENTIFIER_END
/** Algorithm identifier for sntrup761 KEM. */
#define OQS_KEM_alg_ntruprime_sntrup761 "sntrup761"
/** Algorithm identifier for FrodoKEM-640-AES KEM. */
#define OQS_KEM_alg_frodokem_640_aes "FrodoKEM-640-AES"
/** Algorithm identifier for FrodoKEM-640-SHAKE KEM. */
#define OQS_KEM_alg_frodokem_640_shake "FrodoKEM-640-SHAKE"
/** Algorithm identifier for FrodoKEM-976-AES KEM. */
#define OQS_KEM_alg_frodokem_976_aes "FrodoKEM-976-AES"
/** Algorithm identifier for FrodoKEM-976-SHAKE KEM. */
#define OQS_KEM_alg_frodokem_976_shake "FrodoKEM-976-SHAKE"
/** Algorithm identifier for FrodoKEM-1344-AES KEM. */
#define OQS_KEM_alg_frodokem_1344_aes "FrodoKEM-1344-AES"
/** Algorithm identifier for FrodoKEM-1344-SHAKE KEM. */
#define OQS_KEM_alg_frodokem_1344_shake "FrodoKEM-1344-SHAKE"
// EDIT-WHEN-ADDING-KEM
///// OQS_COPY_FROM_UPSTREAM_FRAGMENT_ALGS_LENGTH_START
/** Number of algorithm identifiers above. */
#define OQS_KEM_algs_length 26
///// OQS_COPY_FROM_UPSTREAM_FRAGMENT_ALGS_LENGTH_END
/**
* Returns identifiers for available key encapsulation mechanisms in liboqs. Used with OQS_KEM_new.
*
* Note that algorithm identifiers are present in this list even when the algorithm is disabled
* at compile time.
*
* @param[in] i Index of the algorithm identifier to return, 0 <= i < OQS_KEM_algs_length
* @return Algorithm identifier as a string, or NULL.
*/
OQS_API const char *OQS_KEM_alg_identifier(size_t i);
/**
* Returns the number of key encapsulation mechanisms in liboqs. They can be enumerated with
* OQS_KEM_alg_identifier.
*
* Note that some mechanisms may be disabled at compile time.
*
* @return The number of key encapsulation mechanisms.
*/
OQS_API int OQS_KEM_alg_count(void);
/**
* Indicates whether the specified algorithm was enabled at compile-time or not.
*
* @param[in] method_name Name of the desired algorithm; one of the names in `OQS_KEM_algs`.
* @return 1 if enabled, 0 if disabled or not found
*/
OQS_API int OQS_KEM_alg_is_enabled(const char *method_name);
/**
* Key encapsulation mechanism object
*/
typedef struct OQS_KEM {
/** Printable string representing the name of the key encapsulation mechanism. */
const char *method_name;
/**
* Printable string representing the version of the cryptographic algorithm.
*
* Implementations with the same method_name and same alg_version will be interoperable.
* See README.md for information about algorithm compatibility.
*/
const char *alg_version;
/** The NIST security level (1, 2, 3, 4, 5) claimed in this algorithm's original NIST submission. */
uint8_t claimed_nist_level;
/** Whether the KEM offers IND-CCA security (TRUE) or IND-CPA security (FALSE). */
bool ind_cca;
/** The (maximum) length, in bytes, of public keys for this KEM. */
size_t length_public_key;
/** The (maximum) length, in bytes, of secret keys for this KEM. */
size_t length_secret_key;
/** The (maximum) length, in bytes, of ciphertexts for this KEM. */
size_t length_ciphertext;
/** The (maximum) length, in bytes, of shared secrets for this KEM. */
size_t length_shared_secret;
/**
* Keypair generation algorithm.
*
* Caller is responsible for allocating sufficient memory for `public_key` and
* `secret_key`, based on the `length_*` members in this object or the per-scheme
* compile-time macros `OQS_KEM_*_length_*`.
*
* @param[out] public_key The public key represented as a byte string.
* @param[out] secret_key The secret key represented as a byte string.
* @return OQS_SUCCESS or OQS_ERROR
*/
OQS_STATUS (*keypair)(uint8_t *public_key, uint8_t *secret_key);
/**
* Encapsulation algorithm.
*
* Caller is responsible for allocating sufficient memory for `ciphertext` and
* `shared_secret`, based on the `length_*` members in this object or the per-scheme
* compile-time macros `OQS_KEM_*_length_*`.
*
* @param[out] ciphertext The ciphertext (encapsulation) represented as a byte string.
* @param[out] shared_secret The shared secret represented as a byte string.
* @param[in] public_key The public key represented as a byte string.
* @return OQS_SUCCESS or OQS_ERROR
*/
OQS_STATUS (*encaps)(uint8_t *ciphertext, uint8_t *shared_secret, const uint8_t *public_key);
/**
* Decapsulation algorithm.
*
* Caller is responsible for allocating sufficient memory for `shared_secret`, based
* on the `length_*` members in this object or the per-scheme compile-time macros
* `OQS_KEM_*_length_*`.
*
* @param[out] shared_secret The shared secret represented as a byte string.
* @param[in] ciphertext The ciphertext (encapsulation) represented as a byte string.
* @param[in] secret_key The secret key represented as a byte string.
* @return OQS_SUCCESS or OQS_ERROR
*/
OQS_STATUS (*decaps)(uint8_t *shared_secret, const uint8_t *ciphertext, const uint8_t *secret_key);
} OQS_KEM;
/**
* Constructs an OQS_KEM object for a particular algorithm.
*
* Callers should always check whether the return value is `NULL`, which indicates either than an
* invalid algorithm name was provided, or that the requested algorithm was disabled at compile-time.
*
* @param[in] method_name Name of the desired algorithm; one of the names in `OQS_KEM_algs`.
* @return An OQS_KEM for the particular algorithm, or `NULL` if the algorithm has been disabled at compile-time.
*/
OQS_API OQS_KEM *OQS_KEM_new(const char *method_name);
/**
* Keypair generation algorithm.
*
* Caller is responsible for allocating sufficient memory for `public_key` and
* `secret_key`, based on the `length_*` members in this object or the per-scheme
* compile-time macros `OQS_KEM_*_length_*`.
*
* @param[in] kem The OQS_KEM object representing the KEM.
* @param[out] public_key The public key represented as a byte string.
* @param[out] secret_key The secret key represented as a byte string.
* @return OQS_SUCCESS or OQS_ERROR
*/
OQS_API OQS_STATUS OQS_KEM_keypair(const OQS_KEM *kem, uint8_t *public_key, uint8_t *secret_key);
/**
* Encapsulation algorithm.
*
* Caller is responsible for allocating sufficient memory for `ciphertext` and
* `shared_secret`, based on the `length_*` members in this object or the per-scheme
* compile-time macros `OQS_KEM_*_length_*`.
*
* @param[in] kem The OQS_KEM object representing the KEM.
* @param[out] ciphertext The ciphertext (encapsulation) represented as a byte string.
* @param[out] shared_secret The shared secret represented as a byte string.
* @param[in] public_key The public key represented as a byte string.
* @return OQS_SUCCESS or OQS_ERROR
*/
OQS_API OQS_STATUS OQS_KEM_encaps(const OQS_KEM *kem, uint8_t *ciphertext, uint8_t *shared_secret, const uint8_t *public_key);
/**
* Decapsulation algorithm.
*
* Caller is responsible for allocating sufficient memory for `shared_secret`, based
* on the `length_*` members in this object or the per-scheme compile-time macros
* `OQS_KEM_*_length_*`.
*
* @param[in] kem The OQS_KEM object representing the KEM.
* @param[out] shared_secret The shared secret represented as a byte string.
* @param[in] ciphertext The ciphertext (encapsulation) represented as a byte string.
* @param[in] secret_key The secret key represented as a byte string.
* @return OQS_SUCCESS or OQS_ERROR
*/
OQS_API OQS_STATUS OQS_KEM_decaps(const OQS_KEM *kem, uint8_t *shared_secret, const uint8_t *ciphertext, const uint8_t *secret_key);
/**
* Frees an OQS_KEM object that was constructed by OQS_KEM_new.
*
* @param[in] kem The OQS_KEM object to free.
*/
OQS_API void OQS_KEM_free(OQS_KEM *kem);
#ifdef OQS_ENABLE_KEM_BIKE
#include <oqs/kem_bike.h>
#endif /* OQS_ENABLE_KEM_BIKE */
///// OQS_COPY_FROM_UPSTREAM_FRAGMENT_INCLUDE_START
#ifdef OQS_ENABLE_KEM_CLASSIC_MCELIECE
#include <oqs/kem_classic_mceliece.h>
#endif /* OQS_ENABLE_KEM_CLASSIC_MCELIECE */
#ifdef OQS_ENABLE_KEM_HQC
#include <oqs/kem_hqc.h>
#endif /* OQS_ENABLE_KEM_HQC */
#ifdef OQS_ENABLE_KEM_KYBER
#include <oqs/kem_kyber.h>
#endif /* OQS_ENABLE_KEM_KYBER */
///// OQS_COPY_FROM_UPSTREAM_FRAGMENT_INCLUDE_END
#ifdef OQS_ENABLE_KEM_NTRUPRIME
#include <oqs/kem_ntruprime.h>
#endif /* OQS_ENABLE_KEM_NTRUPRIME */
#ifdef OQS_ENABLE_KEM_FRODOKEM
#include <oqs/kem_frodokem.h>
#endif /* OQS_ENABLE_KEM_FRODOKEM */
// EDIT-WHEN-ADDING-KEM
#if defined(__cplusplus)
} // extern "C"
#endif
#endif // OQS_KEM_H

View file

@ -0,0 +1,42 @@
// SPDX-License-Identifier: MIT
#ifndef OQS_KEM_KYBER_H
#define OQS_KEM_KYBER_H
#include <oqs/oqs.h>
#ifdef OQS_ENABLE_KEM_kyber_512
#define OQS_KEM_kyber_512_length_public_key 800
#define OQS_KEM_kyber_512_length_secret_key 1632
#define OQS_KEM_kyber_512_length_ciphertext 768
#define OQS_KEM_kyber_512_length_shared_secret 32
OQS_KEM *OQS_KEM_kyber_512_new(void);
OQS_API OQS_STATUS OQS_KEM_kyber_512_keypair(uint8_t *public_key, uint8_t *secret_key);
OQS_API OQS_STATUS OQS_KEM_kyber_512_encaps(uint8_t *ciphertext, uint8_t *shared_secret, const uint8_t *public_key);
OQS_API OQS_STATUS OQS_KEM_kyber_512_decaps(uint8_t *shared_secret, const uint8_t *ciphertext, const uint8_t *secret_key);
#endif
#ifdef OQS_ENABLE_KEM_kyber_768
#define OQS_KEM_kyber_768_length_public_key 1184
#define OQS_KEM_kyber_768_length_secret_key 2400
#define OQS_KEM_kyber_768_length_ciphertext 1088
#define OQS_KEM_kyber_768_length_shared_secret 32
OQS_KEM *OQS_KEM_kyber_768_new(void);
OQS_API OQS_STATUS OQS_KEM_kyber_768_keypair(uint8_t *public_key, uint8_t *secret_key);
OQS_API OQS_STATUS OQS_KEM_kyber_768_encaps(uint8_t *ciphertext, uint8_t *shared_secret, const uint8_t *public_key);
OQS_API OQS_STATUS OQS_KEM_kyber_768_decaps(uint8_t *shared_secret, const uint8_t *ciphertext, const uint8_t *secret_key);
#endif
#ifdef OQS_ENABLE_KEM_kyber_1024
#define OQS_KEM_kyber_1024_length_public_key 1568
#define OQS_KEM_kyber_1024_length_secret_key 3168
#define OQS_KEM_kyber_1024_length_ciphertext 1568
#define OQS_KEM_kyber_1024_length_shared_secret 32
OQS_KEM *OQS_KEM_kyber_1024_new(void);
OQS_API OQS_STATUS OQS_KEM_kyber_1024_keypair(uint8_t *public_key, uint8_t *secret_key);
OQS_API OQS_STATUS OQS_KEM_kyber_1024_encaps(uint8_t *ciphertext, uint8_t *shared_secret, const uint8_t *public_key);
OQS_API OQS_STATUS OQS_KEM_kyber_1024_decaps(uint8_t *shared_secret, const uint8_t *ciphertext, const uint8_t *secret_key);
#endif
#endif

View file

@ -0,0 +1,25 @@
/**
* \file oqs.h
* \brief Overall header file for liboqs.
*
* C programs using liboqs can include just this one file, and it will include all
* other necessary headers from liboqs.
*
* SPDX-License-Identifier: MIT
*/
#ifndef OQS_H
#define OQS_H
#include <oqs/oqsconfig.h>
#include <oqs/common.h>
#include <oqs/aes.h>
#include <oqs/sha2.h>
#include <oqs/sha3.h>
#include <oqs/sha3x4.h>
#include <oqs/rand.h>
#include <oqs/kem.h>
#include <oqs/sig.h>
#endif // OQS_H

View file

View file

@ -0,0 +1,73 @@
/**
* \file rand.h
* \brief Random number generator.
*
* SPDX-License-Identifier: MIT
*/
#ifndef OQS_RANDOM_H
#define OQS_RANDOM_H
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include <oqs/common.h>
#if defined(__cplusplus)
extern "C" {
#endif
/** Algorithm identifier for system PRNG. */
#define OQS_RAND_alg_system "system"
/** Algorithm identifier for NIST deterministic RNG for KATs. */
#define OQS_RAND_alg_nist_kat "NIST-KAT"
/** Algorithm identifier for using OpenSSL's PRNG. */
#define OQS_RAND_alg_openssl "OpenSSL"
/**
* Switches OQS_randombytes to use the specified algorithm.
*
* @param[in] algorithm The name of the algorithm to use.
* @return OQS_SUCCESS if `algorithm` is a supported algorithm name, OQS_ERROR otherwise.
*/
OQS_API OQS_STATUS OQS_randombytes_switch_algorithm(const char *algorithm);
/**
* Switches OQS_randombytes to use the given function.
*
* This allows additional custom RNGs besides the provided ones. The provided RNG
* function must have the same signature as `OQS_randombytes`.
*
* @param[in] algorithm_ptr Pointer to the RNG function to use.
*/
OQS_API void OQS_randombytes_custom_algorithm(void (*algorithm_ptr)(uint8_t *, size_t));
/**
* Fills the given memory with the requested number of (pseudo)random bytes.
*
* This implementation uses whichever algorithm has been selected by
* OQS_randombytes_switch_algorithm. The default is OQS_randombytes_system, which
* reads bytes directly from `/dev/urandom`.
*
* The caller is responsible for providing a buffer allocated with sufficient room.
*
* @param[out] random_array Pointer to the memory to fill with (pseudo)random bytes
* @param[in] bytes_to_read The number of random bytes to read into memory
*/
OQS_API void OQS_randombytes(uint8_t *random_array, size_t bytes_to_read);
/**
* Initializes the NIST DRBG with a given seed and with 256-bit security.
*
* @param[in] entropy_input The seed; must be exactly 48 bytes
* @param[in] personalization_string An optional personalization string;
* may be NULL; if not NULL, must be at least 48 bytes long
*/
OQS_API void OQS_randombytes_nist_kat_init_256bit(const uint8_t *entropy_input, const uint8_t *personalization_string);
#if defined(__cplusplus)
} // extern "C"
#endif
#endif // OQS_RANDOM_H

View file

@ -0,0 +1,257 @@
/**
* \file sha2.h
* \brief SHA2 functions; not part of the OQS public API
*
* Contains the API and documentation for SHA2 digest implementation
*
* <b>Note this is not part of the OQS public API: implementations within liboqs can use these
* functions, but external consumers of liboqs should not use these functions.</b>
*
* \author Douglas Stebila
*
* SPDX-License-Identifier: MIT
*/
#ifndef OQS_SHA2_H
#define OQS_SHA2_H
#include <stddef.h>
#include <stdint.h>
#if defined(__cplusplus)
extern "C" {
#endif
/** Data structure for the state of the SHA-224 incremental hashing API. */
typedef struct {
/** Internal state */
void *ctx;
} OQS_SHA2_sha224_ctx;
/**
* \brief Process a message with SHA-256 and return the hash code in the output byte array.
*
* \warning The output array must be at least 32 bytes in length.
*
* \param output The output byte array
* \param input The message input byte array
* \param inplen The number of message bytes to process
*/
void OQS_SHA2_sha256(uint8_t *output, const uint8_t *input, size_t inplen);
/** Data structure for the state of the SHA-256 incremental hashing API. */
typedef struct {
/** Internal state */
void *ctx;
} OQS_SHA2_sha256_ctx;
/**
* \brief Allocate and initialize the state for the SHA-256 incremental hashing API.
*
* \warning The state must be released by OQS_SHA2_sha256_inc_finalize
* or OQS_SHA2_sha256_inc_ctx_release.
*
* \param state Pointer to the state
*/
void OQS_SHA2_sha256_inc_init(OQS_SHA2_sha256_ctx *state);
/**
* \brief Duplicate state for the SHA-256 incremental hashing API.
*
* \warning dest must be allocated by the caller. Caller is responsible
* for releasing dest by calling either OQS_SHA2_sha256_inc_finalize or
* OQS_SHA2_sha256_inc_ctx_release.
*
* \param dest The function state to copy into; must be initialized
* \param src The function state to copy; must be initialized
*/
void OQS_SHA2_sha256_inc_ctx_clone(OQS_SHA2_sha256_ctx *dest, const OQS_SHA2_sha256_ctx *src);
/**
* \brief Process blocks with SHA-256 and update the state.
*
* \warning The state must be initialized by OQS_SHA2_sha256_inc_init or OQS_SHA2_sha256_inc_ctx_clone.
*
* \param state The state to update
* \param in Message input byte array
* \param inblocks The number of 64-byte blocks of message bytes to process
*/
void OQS_SHA2_sha256_inc_blocks(OQS_SHA2_sha256_ctx *state, const uint8_t *in, size_t inblocks);
/**
* \brief Process more message bytes with SHA-256 and return the hash code in the output byte array.
*
* \warning The output array must be at least 32 bytes in length. The state is
* deallocated by this function and can not be used again after calling
* this function without calling OQS_SHA2_sha256_inc_init again.
*
* \param out The output byte array
* \param state The state
* \param in Additional message input byte array
* \param inlen The number of additional message bytes to process
*/
void OQS_SHA2_sha256_inc_finalize(uint8_t *out, OQS_SHA2_sha256_ctx *state, const uint8_t *in, size_t inlen);
/**
* \brief Destroy state.
*
* \warning The state is deallocated by this function and can not be used again after calling
* this function without calling OQS_SHA2_sha256_inc_init again.
*
* \param state The state
*/
void OQS_SHA2_sha256_inc_ctx_release(OQS_SHA2_sha256_ctx *state);
/**
* \brief Process a message with SHA-384 and return the hash code in the output byte array.
*
* \warning The output array must be at least 48 bytes in length.
*
* \param output The output byte array
* \param input The message input byte array
* \param inplen The number of message bytes to process
*/
void OQS_SHA2_sha384(uint8_t *output, const uint8_t *input, size_t inplen);
/** Data structure for the state of the SHA-384 incremental hashing API. */
typedef struct {
/** Internal state. */
void *ctx;
} OQS_SHA2_sha384_ctx;
/**
* \brief Allocate and initialize the state for the SHA-384 incremental hashing API.
*
* \warning The state must be released by OQS_SHA2_sha384_inc_finalize
* or OQS_SHA2_sha384_inc_ctx_release.
*
* \param state Pointer to the state
*/
void OQS_SHA2_sha384_inc_init(OQS_SHA2_sha384_ctx *state);
/**
* \brief Duplicate state for the SHA-384 incremental hashing API.
*
* \warning dest must be allocated by the caller. Caller is responsible
* for releasing dest by calling either OQS_SHA2_sha384_inc_finalize or
* OQS_SHA2_sha384_inc_ctx_release.
*
* \param dest The function state to copy into; must be initialized
* \param src The function state to copy; must be initialized
*/
void OQS_SHA2_sha384_inc_ctx_clone(OQS_SHA2_sha384_ctx *dest, const OQS_SHA2_sha384_ctx *src);
/**
* \brief Process blocks with SHA-384 and update the state.
*
* \warning The state must be initialized by OQS_SHA2_sha384_inc_init or OQS_SHA2_sha384_inc_ctx_clone.
*
* \param state The state to update
* \param in Message input byte array
* \param inblocks The number of 128-byte blocks of message bytes to process
*/
void OQS_SHA2_sha384_inc_blocks(OQS_SHA2_sha384_ctx *state, const uint8_t *in, size_t inblocks);
/**
* \brief Process more message bytes with SHA-384 and return the hash code in the output byte array.
*
* \warning The output array must be at least 48 bytes in length. The state is
* deallocated by this function and can not be used again after calling
* this function without calling OQS_SHA2_sha384_inc_init again.
*
* \param out The output byte array
* \param state The state
* \param in Additional message input byte array
* \param inlen The number of additional message bytes to process
*/
void OQS_SHA2_sha384_inc_finalize(uint8_t *out, OQS_SHA2_sha384_ctx *state, const uint8_t *in, size_t inlen);
/**
* \brief Destroy state.
*
* \warning The state is deallocated by this function and can not be used again after calling
* this function without calling OQS_SHA2_sha384_inc_init again.
*
* \param state The state
*/
void OQS_SHA2_sha384_inc_ctx_release(OQS_SHA2_sha384_ctx *state);
/**
* \brief Process a message with SHA-512 and return the hash code in the output byte array.
*
* \warning The output array must be at least 64 bytes in length.
*
* \param output The output byte array
* \param input The message input byte array
* \param inplen The number of message bytes to process
*/
void OQS_SHA2_sha512(uint8_t *output, const uint8_t *input, size_t inplen);
/** Data structure for the state of the SHA-512 incremental hashing API. */
typedef struct {
/** Internal state. */
void *ctx;
} OQS_SHA2_sha512_ctx;
/**
* \brief Allocate and initialize the state for the SHA-512 incremental hashing API.
*
* \warning The state must be released by OQS_SHA2_sha512_inc_finalize
* or OQS_SHA2_sha512_inc_ctx_release.
*
* \param state Pointer to the state
*/
void OQS_SHA2_sha512_inc_init(OQS_SHA2_sha512_ctx *state);
/**
* \brief Duplicate state for the SHA-512 incremental hashing API.
*
* \warning dest must be allocated by the caller. Caller is responsible
* for releasing dest by calling either OQS_SHA2_sha512_inc_finalize or
* OQS_SHA2_sha512_inc_ctx_release.
*
* \param dest The function state to copy into; must be initialized
* \param src The function state to copy; must be initialized
*/
void OQS_SHA2_sha512_inc_ctx_clone(OQS_SHA2_sha512_ctx *dest, const OQS_SHA2_sha512_ctx *src);
/**
* \brief Process blocks with SHA-512 and update the state.
*
* \warning The state must be initialized by OQS_SHA2_sha512_inc_init or OQS_SHA2_sha512_inc_ctx_clone.
*
* \param state The state to update
* \param in Message input byte array
* \param inblocks The number of 128-byte blocks of message bytes to process
*/
void OQS_SHA2_sha512_inc_blocks(OQS_SHA2_sha512_ctx *state, const uint8_t *in, size_t inblocks);
/**
* \brief Process more message bytes with SHA-512 and return the hash code in the output byte array.
*
* \warning The output array must be at least 64 bytes in length. The state is
* deallocated by this function and can not be used again after calling
* this function without calling OQS_SHA2_sha512_inc_init again.
*
* \param out The output byte array
* \param state The state
* \param in Additional message input byte array
* \param inlen The number of additional message bytes to process
*/
void OQS_SHA2_sha512_inc_finalize(uint8_t *out, OQS_SHA2_sha512_ctx *state, const uint8_t *in, size_t inlen);
/**
* \brief Destroy state.
*
* \warning The state is deallocated by this function and can not be used again after calling
* this function without calling OQS_SHA2_sha512_inc_init again.
*
* \param state The state
*/
void OQS_SHA2_sha512_inc_ctx_release(OQS_SHA2_sha512_ctx *state);
#if defined(__cplusplus)
} // extern "C"
#endif
#endif // OQS_SHA2_H

View file

@ -0,0 +1,429 @@
/**
* \file sha3.h
* \brief SHA3 and SHAKE functions; not part of the OQS public API
*
* Contains the API and documentation for SHA3 digest and SHAKE implementations.
*
* <b>Note this is not part of the OQS public API: implementations within liboqs can use these
* functions, but external consumers of liboqs should not use these functions.</b>
*
* \author John Underhill, Douglas Stebila
*
* SPDX-License-Identifier: MIT
*/
#ifndef OQS_SHA3_H
#define OQS_SHA3_H
#include <stddef.h>
#include <stdint.h>
#if defined(__cplusplus)
extern "C" {
#endif
/* SHA3 */
/** The SHA-256 byte absorption rate */
#define OQS_SHA3_SHA3_256_RATE 136
/**
* \brief Process a message with SHA3-256 and return the digest in the output byte array.
*
* \warning The output array must be at least 32 bytes in length.
*
* \param output The output byte array
* \param input The message input byte array
* \param inplen The number of message bytes to process
*/
void OQS_SHA3_sha3_256(uint8_t *output, const uint8_t *input, size_t inplen);
/** Data structure for the state of the incremental SHA3-256 API. */
typedef struct {
/** Internal state. */
void *ctx;
} OQS_SHA3_sha3_256_inc_ctx;
/**
* \brief Initialize the state for the incremental SHA3-256 API.
*
* \warning Caller is responsible for releasing state by calling
* OQS_SHA3_sha3_256_inc_ctx_release.
*
* \param state The function state to be allocated and initialized.
*/
void OQS_SHA3_sha3_256_inc_init(OQS_SHA3_sha3_256_inc_ctx *state);
/**
* \brief The SHA3-256 absorb function.
* Absorb an input into the state.
*
* \param state The function state; must be initialized
* \param input The input array
* \param inlen The length of the input
*/
void OQS_SHA3_sha3_256_inc_absorb(OQS_SHA3_sha3_256_inc_ctx *state, const uint8_t *input, size_t inlen);
/**
* \brief The SHA3-256 finalize-and-squeeze function.
* Finalizes the state and squeezes a 32 byte digest.
*
* \warning Output array must be at least 32 bytes.
* State cannot be used after this without calling OQS_SHA3_sha3_256_inc_reset.
*
* \param output The output byte array
* \param state The function state; must be initialized
*/
void OQS_SHA3_sha3_256_inc_finalize(uint8_t *output, OQS_SHA3_sha3_256_inc_ctx *state);
/**
* \brief Release the state for the SHA3-256 incremental API.
*
* \param state The function state; must be initialized
*/
void OQS_SHA3_sha3_256_inc_ctx_release(OQS_SHA3_sha3_256_inc_ctx *state);
/**
* \brief Resets the state for the SHA3-256 incremental API.
* Alternative to freeing and reinitializing the state.
*
* \param state The function state; must be initialized
*/
void OQS_SHA3_sha3_256_inc_ctx_reset(OQS_SHA3_sha3_256_inc_ctx *state);
/**
* \brief Clone the state for the SHA3-256 incremental API.
*
* \param dest The function state to copy into; must be initialized
* \param src The function state to copy; must be initialized
*/
void OQS_SHA3_sha3_256_inc_ctx_clone(OQS_SHA3_sha3_256_inc_ctx *dest, const OQS_SHA3_sha3_256_inc_ctx *src);
/** The SHA-384 byte absorption rate */
#define OQS_SHA3_SHA3_384_RATE 104
/**
* \brief Process a message with SHA3-384 and return the digest in the output byte array.
*
* \warning The output array must be at least 48 bytes in length.
*
* \param output The output byte array
* \param input The message input byte array
* \param inplen The number of message bytes to process
*/
void OQS_SHA3_sha3_384(uint8_t *output, const uint8_t *input, size_t inplen);
/** Data structure for the state of the incremental SHA3-384 API. */
typedef struct {
/** Internal state. */
void *ctx;
} OQS_SHA3_sha3_384_inc_ctx;
/**
* \brief Initialize the state for the incremental SHA3-384 API.
*
* \warning Caller is responsible for releasing state by calling
* OQS_SHA3_sha3_384_inc_ctx_release.
*
* \param state The function state to be allocated and initialized.
*/
void OQS_SHA3_sha3_384_inc_init(OQS_SHA3_sha3_384_inc_ctx *state);
/**
* \brief The SHA3-384 absorb function.
* Absorb an input into the state.
*
* \param state The function state; must be initialized
* \param input The input array
* \param inlen The length of the input
*/
void OQS_SHA3_sha3_384_inc_absorb(OQS_SHA3_sha3_384_inc_ctx *state, const uint8_t *input, size_t inlen);
/**
* \brief The SHA3-384 finalize-and-squeeze function.
* Finalizes the state and squeezes a 48 byte digest.
*
* \warning Output array must be at least 48 bytes.
* State cannot be used after this without calling OQS_SHA3_sha3_384_inc_reset.
*
* \param output The output byte array
* \param state The function state; must be initialized
*/
void OQS_SHA3_sha3_384_inc_finalize(uint8_t *output, OQS_SHA3_sha3_384_inc_ctx *state);
/**
* \brief Release the state for the SHA3-384 incremental API.
*
* \param state The function state; must be initialized
*/
void OQS_SHA3_sha3_384_inc_ctx_release(OQS_SHA3_sha3_384_inc_ctx *state);
/**
* \brief Resets the state for the SHA3-384 incremental API.
* Alternative to freeing and reinitializing the state.
*
* \param state The function state; must be initialized
*/
void OQS_SHA3_sha3_384_inc_ctx_reset(OQS_SHA3_sha3_384_inc_ctx *state);
/**
* \brief Clone the state for the SHA3-384 incremental API.
*
* \param dest The function state to copy into; must be initialized
* \param src The function state to copy; must be initialized
*/
void OQS_SHA3_sha3_384_inc_ctx_clone(OQS_SHA3_sha3_384_inc_ctx *dest, const OQS_SHA3_sha3_384_inc_ctx *src);
/** The SHA-512 byte absorption rate */
#define OQS_SHA3_SHA3_512_RATE 72
/**
* \brief Process a message with SHA3-512 and return the digest in the output byte array.
*
* \warning The output array must be at least 64 bytes in length.
*
* \param output The output byte array
* \param input The message input byte array
* \param inplen The number of message bytes to process
*/
void OQS_SHA3_sha3_512(uint8_t *output, const uint8_t *input, size_t inplen);
/** Data structure for the state of the incremental SHA3-512 API. */
typedef struct {
/** Internal state. */
void *ctx;
} OQS_SHA3_sha3_512_inc_ctx;
/**
* \brief Initialize the state for the incremental SHA3-512 API.
*
* \warning Caller is responsible for releasing state by calling
* OQS_SHA3_sha3_512_inc_ctx_release.
*
* \param state The function state to be allocated and initialized.
*/
void OQS_SHA3_sha3_512_inc_init(OQS_SHA3_sha3_512_inc_ctx *state);
/**
* \brief The SHA3-512 absorb function.
* Absorb an input into the state.
*
* \param state The function state; must be initialized
* \param input The input array
* \param inlen The length of the input
*/
void OQS_SHA3_sha3_512_inc_absorb(OQS_SHA3_sha3_512_inc_ctx *state, const uint8_t *input, size_t inlen);
/**
* \brief The SHA3-512 finalize-and-squeeze function.
* Finalizes the state and squeezes a 64 byte digest.
*
* \warning Output array must be at least 64 bytes.
* State cannot be used after this without calling OQS_SHA3_sha3_512_inc_reset.
*
* \param output The output byte array
* \param state The function state; must be initialized
*/
void OQS_SHA3_sha3_512_inc_finalize(uint8_t *output, OQS_SHA3_sha3_512_inc_ctx *state);
/**
* \brief Release the state for the SHA3-512 incremental API.
*
* \param state The function state; must be initialized
*/
void OQS_SHA3_sha3_512_inc_ctx_release(OQS_SHA3_sha3_512_inc_ctx *state);
/**
* \brief Resets the state for the SHA3-512 incremental API.
* Alternative to freeing and reinitializing the state.
*
* \param state The function state; must be initialized
*/
void OQS_SHA3_sha3_512_inc_ctx_reset(OQS_SHA3_sha3_512_inc_ctx *state);
/**
* \brief Clone the state for the SHA3-512 incremental API.
*
* \param dest The function state to copy into; must be initialized
* \param src The function state to copy; must be initialized
*/
void OQS_SHA3_sha3_512_inc_ctx_clone(OQS_SHA3_sha3_512_inc_ctx *dest, const OQS_SHA3_sha3_512_inc_ctx *src);
/* SHAKE */
/** The SHAKE-128 byte absorption rate */
#define OQS_SHA3_SHAKE128_RATE 168
/**
* \brief Seed a SHAKE-128 instance, and generate an array of pseudo-random bytes.
*
* \warning The output array length must not be zero.
*
* \param output The output byte array
* \param outlen The number of output bytes to generate
* \param input The input seed byte array
* \param inplen The number of seed bytes to process
*/
void OQS_SHA3_shake128(uint8_t *output, size_t outlen, const uint8_t *input, size_t inplen);
/** Data structure for the state of the incremental SHAKE-128 API. */
typedef struct {
/** Internal state. */
void *ctx;
} OQS_SHA3_shake128_inc_ctx;
/**
* \brief Initialize the state for the incremental SHAKE-128 API.
*
* \warning Caller is responsible for releasing state by calling
* OQS_SHA3_shake128_inc_ctx_release.
*
* \param state The function state to be initialized; must be allocated
*/
void OQS_SHA3_shake128_inc_init(OQS_SHA3_shake128_inc_ctx *state);
/**
* \brief The SHAKE-128 absorb function.
* Absorb an input into the state.
*
* \warning State must be initialized.
*
* \param state The function state; must be initialized
* \param input input buffer
* \param inlen length of input buffer
*/
void OQS_SHA3_shake128_inc_absorb(OQS_SHA3_shake128_inc_ctx *state, const uint8_t *input, size_t inlen);
/**
* \brief The SHAKE-128 finalize function.
* Prepares the state for squeezing.
*
* \param state The function state; must be initialized
*/
void OQS_SHA3_shake128_inc_finalize(OQS_SHA3_shake128_inc_ctx *state);
/**
* \brief The SHAKE-128 squeeze function.
* Extracts to an output byte array.
*
* \param output output buffer
* \param outlen bytes of outbut buffer
* \param state The function state; must be initialized and finalized
*/
void OQS_SHA3_shake128_inc_squeeze(uint8_t *output, size_t outlen, OQS_SHA3_shake128_inc_ctx *state);
/**
* \brief Frees the state for the incremental SHAKE-128 API.
*
* \param state The state to free
*/
void OQS_SHA3_shake128_inc_ctx_release(OQS_SHA3_shake128_inc_ctx *state);
/**
* \brief Copies the state for the SHAKE-128 incremental API.
*
* \warning Caller is responsible for releasing dest by calling
* OQS_SHA3_shake128_inc_ctx_release.
*
* \param dest The function state to copy into; must be initialized
* \param src The function state to copy; must be initialized
*/
void OQS_SHA3_shake128_inc_ctx_clone(OQS_SHA3_shake128_inc_ctx *dest, const OQS_SHA3_shake128_inc_ctx *src);
/**
* \brief Resets the state for the SHAKE-128 incremental API. Allows a context
* to be re-used without free and init calls.
*
* \param state The function state; must be initialized
*/
void OQS_SHA3_shake128_inc_ctx_reset(OQS_SHA3_shake128_inc_ctx *state);
/** The SHAKE-256 byte absorption rate */
#define OQS_SHA3_SHAKE256_RATE 136
/**
* \brief Seed a SHAKE-256 instance, and generate an array of pseudo-random bytes.
*
* \warning The output array length must not be zero.
*
* \param output The output byte array
* \param outlen The number of output bytes to generate
* \param input The input seed byte array
* \param inplen The number of seed bytes to process
*/
void OQS_SHA3_shake256(uint8_t *output, size_t outlen, const uint8_t *input, size_t inplen);
/** Data structure for the state of the incremental SHAKE-256 API. */
typedef struct {
/** Internal state. */
void *ctx;
} OQS_SHA3_shake256_inc_ctx;
/**
* \brief Initialize the state for the incremental SHAKE-256 API.
*
* \param state The function state to be initialized; must be allocated
*/
void OQS_SHA3_shake256_inc_init(OQS_SHA3_shake256_inc_ctx *state);
/**
* \brief The SHAKE-256 absorb function.
* Absorb an input message array directly into the state.
*
* \warning State must be initialized by the caller.
*
* \param state The function state; must be initialized
* \param input input buffer
* \param inlen length of input buffer
*/
void OQS_SHA3_shake256_inc_absorb(OQS_SHA3_shake256_inc_ctx *state, const uint8_t *input, size_t inlen);
/**
* \brief The SHAKE-256 finalize function.
*
* \param state The function state; must be initialized
*/
void OQS_SHA3_shake256_inc_finalize(OQS_SHA3_shake256_inc_ctx *state);
/**
* \brief The SHAKE-256 squeeze function.
* Extracts to an output byte array.
*
* \param output output buffer
* \param outlen bytes of outbut buffer
* \param state The function state; must be initialized
*/
void OQS_SHA3_shake256_inc_squeeze(uint8_t *output, size_t outlen, OQS_SHA3_shake256_inc_ctx *state);
/**
* \brief Frees the state for the incremental SHAKE-256 API.
*
* \param state The state to free
*/
void OQS_SHA3_shake256_inc_ctx_release(OQS_SHA3_shake256_inc_ctx *state);
/**
* \brief Copies the state for the incremental SHAKE-256 API.
*
* \warning dest must be allocated. dest must be freed by calling
* OQS_SHA3_shake256_inc_ctx_release.
*
* \param dest The state to copy into; must be initialized
* \param src The state to copy from; must be initialized
*/
void OQS_SHA3_shake256_inc_ctx_clone(OQS_SHA3_shake256_inc_ctx *dest, const OQS_SHA3_shake256_inc_ctx *src);
/**
* \brief Resets the state for the SHAKE-256 incremental API. Allows a context
* to be re-used without free and init calls.
*
* \param state The function state; must be initialized
*/
void OQS_SHA3_shake256_inc_ctx_reset(OQS_SHA3_shake256_inc_ctx *state);
#if defined(__cplusplus)
} // extern "C"
#endif
#endif // OQS_SHA3_H

View file

@ -0,0 +1,263 @@
/**
* \file shakex4.h
* \brief SHA3, SHAKE, and cSHAKE functions; not part of the OQS public API
*
* Contains the API and documentation for SHA3 digest and SHAKE implementations.
*
* <b>Note this is not part of the OQS public API: implementations within liboqs can use these
* functions, but external consumers of liboqs should not use these functions.</b>
*
* \author John Underhill, Douglas Stebila
*
* SPDX-License-Identifier: MIT
*/
#ifndef OQS_SHA3X4_H
#define OQS_SHA3X4_H
#include <stddef.h>
#include <stdint.h>
#if defined(__cplusplus)
extern "C" {
#endif
/**
* \brief Seed 4 parallel SHAKE-128 instances, and generate 4 arrays of pseudo-random bytes.
*
* \warning The output array length must not be zero.
*
* \param out0 The first output byte array
* \param out1 The second output byte array
* \param out2 The third output byte array
* \param out3 The fourth output byte array
* \param outlen The number of output bytes to generate in every output array
* \param in0 The first input seed byte array
* \param in1 The second input seed byte array
* \param in2 The third input seed byte array
* \param in3 The fourth input seed byte array
* \param inlen The number of seed bytes to process from every input array
*/
void OQS_SHA3_shake128_x4(
uint8_t *out0,
uint8_t *out1,
uint8_t *out2,
uint8_t *out3,
size_t outlen,
const uint8_t *in0,
const uint8_t *in1,
const uint8_t *in2,
const uint8_t *in3,
size_t inlen);
/** Data structure for the state of the four-way parallel incremental SHAKE-128 API. */
typedef struct {
/** Internal state. */
void *ctx;
} OQS_SHA3_shake128_x4_inc_ctx;
/**
* \brief Initialize the state for four-way parallel incremental SHAKE-128 API.
*
* \param state The function state to be initialized; must be allocated
*/
void OQS_SHA3_shake128_x4_inc_init(OQS_SHA3_shake128_x4_inc_ctx *state);
/**
* \brief Four-way parallel SHAKE-128 absorb function.
* Absorb four input messages of the same length into four parallel states.
*
* \warning State must be initialized by the caller.
*
* \param state The function state; must be initialized
* \param in0 The input to be absorbed into first instance
* \param in1 The input to be absorbed into first instance
* \param in2 The input to be absorbed into first instance
* \param in3 The input to be absorbed into first instance
* \param inlen The number of bytes to process from each input array
*/
void OQS_SHA3_shake128_x4_inc_absorb(
OQS_SHA3_shake128_x4_inc_ctx *state,
const uint8_t *in0,
const uint8_t *in1,
const uint8_t *in2,
const uint8_t *in3,
size_t inlen);
/**
* \brief Four-way parallel SHAKE-128 finalize function.
* Prepares the states for squeezing.
*
* \param state The function state; must be initialized
*/
void OQS_SHA3_shake128_x4_inc_finalize(OQS_SHA3_shake128_x4_inc_ctx *state);
/**
* \brief Four-way parallel SHAKE-128 squeeze function.
* Extracts from four parallel states into four output buffers
*
* \param out0 output buffer for the first instance
* \param out1 output buffer for the second instance
* \param out2 output buffer for the third instance
* \param out3 output buffer for the fourth instance
* \param outlen bytes of outbut buffer
* \param state The function state; must be initialized and finalized.
*/
void OQS_SHA3_shake128_x4_inc_squeeze(
uint8_t *out0,
uint8_t *out1,
uint8_t *out2,
uint8_t *out3,
size_t outlen,
OQS_SHA3_shake128_x4_inc_ctx *state);
/**
* \brief Frees the state for the four-way parallel incremental SHAKE-128 API.
*
* \param state The state to free
*/
void OQS_SHA3_shake128_x4_inc_ctx_release(OQS_SHA3_shake128_x4_inc_ctx *state);
/**
* \brief Copies the state for the four-way parallel incremental SHAKE-128 API.
*
* \param dest The state to copy into; must be initialized
* \param src The state to copy from; must be initialized
*/
void OQS_SHA3_shake128_x4_inc_ctx_clone(
OQS_SHA3_shake128_x4_inc_ctx *dest,
const OQS_SHA3_shake128_x4_inc_ctx *src);
/**
* \brief Resets the state for the four-way parallel incremental SHAKE-128 API.
*
* \param state The function state; must be initialized
*/
void OQS_SHA3_shake128_x4_inc_ctx_reset(OQS_SHA3_shake128_x4_inc_ctx *state);
/* SHAKE256 */
/**
* \brief Seed 4 parallel SHAKE-256 instances, and generate 4 arrays of pseudo-random bytes.
*
* Uses a vectorized (AVX2) implementation of SHAKE-256 if available.
*
* \warning The output array length must not be zero.
*
* \param out0 The first output byte array
* \param out1 The second output byte array
* \param out2 The third output byte array
* \param out3 The fourth output byte array
* \param outlen The number of output bytes to generate in every output array
* \param in0 The first input seed byte array
* \param in1 The second input seed byte array
* \param in2 The third input seed byte array
* \param in3 The fourth input seed byte array
* \param inlen The number of seed bytes to process from every input array
*/
void OQS_SHA3_shake256_x4(
uint8_t *out0,
uint8_t *out1,
uint8_t *out2,
uint8_t *out3,
size_t outlen,
const uint8_t *in0,
const uint8_t *in1,
const uint8_t *in2,
const uint8_t *in3,
size_t inlen);
/** Data structure for the state of the four-way parallel incremental SHAKE-256 API. */
typedef struct {
/** Internal state. */
void *ctx;
} OQS_SHA3_shake256_x4_inc_ctx;
/**
* \brief Initialize the state for four-way parallel incremental SHAKE-256 API.
*
* \param state The function state to be initialized; must be allocated
*/
void OQS_SHA3_shake256_x4_inc_init(OQS_SHA3_shake256_x4_inc_ctx *state);
/**
* \brief Four-way parallel SHAKE-256 absorb function.
* Absorb four input messages of the same length into four parallel states.
*
* \warning State must be initialized by the caller.
*
* \param state The function state; must be initialized
* \param in0 The input to be absorbed into first instance
* \param in1 The input to be absorbed into first instance
* \param in2 The input to be absorbed into first instance
* \param in3 The input to be absorbed into first instance
* \param inlen The number of bytes to process from each input array
*/
void OQS_SHA3_shake256_x4_inc_absorb(
OQS_SHA3_shake256_x4_inc_ctx *state,
const uint8_t *in0,
const uint8_t *in1,
const uint8_t *in2,
const uint8_t *in3,
size_t inlen);
/**
* \brief Four-way parallel SHAKE-256 finalize function.
*
* \param state The function state; must be initialized
*/
void OQS_SHA3_shake256_x4_inc_finalize(OQS_SHA3_shake256_x4_inc_ctx *state);
/**
* \brief Four-way parallel SHAKE-256 squeeze function.
* Extracts from four parallel states into four output buffers
*
* \param out0 output buffer for the first instance
* \param out1 output buffer for the second instance
* \param out2 output buffer for the third instance
* \param out3 output buffer for the fourth instance
* \param outlen bytes of outbut buffer
* \param state The function state; must be initialized and finalized
*/
void OQS_SHA3_shake256_x4_inc_squeeze(
uint8_t *out0,
uint8_t *out1,
uint8_t *out2,
uint8_t *out3,
size_t outlen,
OQS_SHA3_shake256_x4_inc_ctx *state);
/**
* \brief Frees the state for the four-way parallel incremental SHAKE-256 API.
*
* \param state The state to free
*/
void OQS_SHA3_shake256_x4_inc_ctx_release(OQS_SHA3_shake256_x4_inc_ctx *state);
/**
* \brief Copies the state for the four-way parallel incremental SHAKE-256 API.
*
* \warning dest must be allocated. dest must be freed by calling
* OQS_SHA3_shake256_inc_ctx_release.
*
* \param dest The state to copy into; must be initialized
* \param src The state to copy from; must be initialized
*/
void OQS_SHA3_shake256_x4_inc_ctx_clone(
OQS_SHA3_shake256_x4_inc_ctx *dest,
const OQS_SHA3_shake256_x4_inc_ctx *src);
/**
* \brief Resets the state for the four-way parallel incremental SHAKE-256 API.
* Allows a context to be re-used without free and init calls.
*
* \param state The function state; must be initialized
*/
void OQS_SHA3_shake256_x4_inc_ctx_reset(OQS_SHA3_shake256_x4_inc_ctx *state);
#if defined(__cplusplus)
} // extern "C"
#endif
#endif // OQS_SHA3_H

View file

@ -0,0 +1,256 @@
/**
* \file sig.h
* \brief Signature schemes
*
* The file `tests/example_sig.c` contains two examples on using the OQS_SIG API.
*
* The first example uses the individual scheme's algorithms directly and uses
* no dynamic memory allocation -- all buffers are allocated on the stack, with
* sizes indicated using preprocessor macros. Since algorithms can be disabled at
* compile-time, the programmer should wrap the code in \#ifdefs.
*
* The second example uses an OQS_SIG object to use an algorithm specified at
* runtime. Therefore it uses dynamic memory allocation -- all buffers must be
* malloc'ed by the programmer, with sizes indicated using the corresponding length
* member of the OQS_SIG object in question. Since algorithms can be disabled at
* compile-time, the programmer should check that the OQS_SIG object is not `NULL`.
*
* SPDX-License-Identifier: MIT
*/
#ifndef OQS_SIG_H
#define OQS_SIG_H
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include <oqs/oqs.h>
#if defined(__cplusplus)
extern "C" {
#endif
///// OQS_COPY_FROM_UPSTREAM_FRAGMENT_ALG_IDENTIFIER_START
/** Algorithm identifier for Dilithium2 */
#define OQS_SIG_alg_dilithium_2 "Dilithium2"
/** Algorithm identifier for Dilithium3 */
#define OQS_SIG_alg_dilithium_3 "Dilithium3"
/** Algorithm identifier for Dilithium5 */
#define OQS_SIG_alg_dilithium_5 "Dilithium5"
/** Algorithm identifier for Falcon-512 */
#define OQS_SIG_alg_falcon_512 "Falcon-512"
/** Algorithm identifier for Falcon-1024 */
#define OQS_SIG_alg_falcon_1024 "Falcon-1024"
/** Algorithm identifier for SPHINCS+-SHA2-128f-simple */
#define OQS_SIG_alg_sphincs_sha2_128f_simple "SPHINCS+-SHA2-128f-simple"
/** Algorithm identifier for SPHINCS+-SHA2-128s-simple */
#define OQS_SIG_alg_sphincs_sha2_128s_simple "SPHINCS+-SHA2-128s-simple"
/** Algorithm identifier for SPHINCS+-SHA2-192f-simple */
#define OQS_SIG_alg_sphincs_sha2_192f_simple "SPHINCS+-SHA2-192f-simple"
/** Algorithm identifier for SPHINCS+-SHA2-192s-simple */
#define OQS_SIG_alg_sphincs_sha2_192s_simple "SPHINCS+-SHA2-192s-simple"
/** Algorithm identifier for SPHINCS+-SHA2-256f-simple */
#define OQS_SIG_alg_sphincs_sha2_256f_simple "SPHINCS+-SHA2-256f-simple"
/** Algorithm identifier for SPHINCS+-SHA2-256s-simple */
#define OQS_SIG_alg_sphincs_sha2_256s_simple "SPHINCS+-SHA2-256s-simple"
/** Algorithm identifier for SPHINCS+-SHAKE-128f-simple */
#define OQS_SIG_alg_sphincs_shake_128f_simple "SPHINCS+-SHAKE-128f-simple"
/** Algorithm identifier for SPHINCS+-SHAKE-128s-simple */
#define OQS_SIG_alg_sphincs_shake_128s_simple "SPHINCS+-SHAKE-128s-simple"
/** Algorithm identifier for SPHINCS+-SHAKE-192f-simple */
#define OQS_SIG_alg_sphincs_shake_192f_simple "SPHINCS+-SHAKE-192f-simple"
/** Algorithm identifier for SPHINCS+-SHAKE-192s-simple */
#define OQS_SIG_alg_sphincs_shake_192s_simple "SPHINCS+-SHAKE-192s-simple"
/** Algorithm identifier for SPHINCS+-SHAKE-256f-simple */
#define OQS_SIG_alg_sphincs_shake_256f_simple "SPHINCS+-SHAKE-256f-simple"
/** Algorithm identifier for SPHINCS+-SHAKE-256s-simple */
#define OQS_SIG_alg_sphincs_shake_256s_simple "SPHINCS+-SHAKE-256s-simple"
///// OQS_COPY_FROM_UPSTREAM_FRAGMENT_ALG_IDENTIFIER_END
// EDIT-WHEN-ADDING-SIG
///// OQS_COPY_FROM_UPSTREAM_FRAGMENT_ALGS_LENGTH_START
/** Number of algorithm identifiers above. */
#define OQS_SIG_algs_length 17
///// OQS_COPY_FROM_UPSTREAM_FRAGMENT_ALGS_LENGTH_END
/**
* Returns identifiers for available signature schemes in liboqs. Used with OQS_SIG_new.
*
* Note that algorithm identifiers are present in this list even when the algorithm is disabled
* at compile time.
*
* @param[in] i Index of the algorithm identifier to return, 0 <= i < OQS_SIG_algs_length
* @return Algorithm identifier as a string, or NULL.
*/
OQS_API const char *OQS_SIG_alg_identifier(size_t i);
/**
* Returns the number of signature mechanisms in liboqs. They can be enumerated with
* OQS_SIG_alg_identifier.
*
* Note that some mechanisms may be disabled at compile time.
*
* @return The number of signature mechanisms.
*/
OQS_API int OQS_SIG_alg_count(void);
/**
* Indicates whether the specified algorithm was enabled at compile-time or not.
*
* @param[in] method_name Name of the desired algorithm; one of the names in `OQS_SIG_algs`.
* @return 1 if enabled, 0 if disabled or not found
*/
OQS_API int OQS_SIG_alg_is_enabled(const char *method_name);
/**
* Signature schemes object
*/
typedef struct OQS_SIG {
/** Printable string representing the name of the signature scheme. */
const char *method_name;
/**
* Printable string representing the version of the cryptographic algorithm.
*
* Implementations with the same method_name and same alg_version will be interoperable.
* See README.md for information about algorithm compatibility.
*/
const char *alg_version;
/** The NIST security level (1, 2, 3, 4, 5) claimed in this algorithm's original NIST submission. */
uint8_t claimed_nist_level;
/** Whether the signature offers EUF-CMA security (TRUE) or not (FALSE). */
bool euf_cma;
/** The (maximum) length, in bytes, of public keys for this signature scheme. */
size_t length_public_key;
/** The (maximum) length, in bytes, of secret keys for this signature scheme. */
size_t length_secret_key;
/** The (maximum) length, in bytes, of signatures for this signature scheme. */
size_t length_signature;
/**
* Keypair generation algorithm.
*
* Caller is responsible for allocating sufficient memory for `public_key` and
* `secret_key`, based on the `length_*` members in this object or the per-scheme
* compile-time macros `OQS_SIG_*_length_*`.
*
* @param[out] public_key The public key represented as a byte string.
* @param[out] secret_key The secret key represented as a byte string.
* @return OQS_SUCCESS or OQS_ERROR
*/
OQS_STATUS (*keypair)(uint8_t *public_key, uint8_t *secret_key);
/**
* Signature generation algorithm.
*
* Caller is responsible for allocating sufficient memory for `signature`,
* based on the `length_*` members in this object or the per-scheme
* compile-time macros `OQS_SIG_*_length_*`.
*
* @param[out] signature The signature on the message represented as a byte string.
* @param[out] signature_len The actual length of the signature. May be smaller than `length_signature` for some algorithms since some algorithms have variable length signatures.
* @param[in] message The message to sign represented as a byte string.
* @param[in] message_len The length of the message to sign.
* @param[in] secret_key The secret key represented as a byte string.
* @return OQS_SUCCESS or OQS_ERROR
*/
OQS_STATUS (*sign)(uint8_t *signature, size_t *signature_len, const uint8_t *message, size_t message_len, const uint8_t *secret_key);
/**
* Signature verification algorithm.
*
* @param[in] message The message represented as a byte string.
* @param[in] message_len The length of the message.
* @param[in] signature The signature on the message represented as a byte string.
* @param[in] signature_len The length of the signature.
* @param[in] public_key The public key represented as a byte string.
* @return OQS_SUCCESS or OQS_ERROR
*/
OQS_STATUS (*verify)(const uint8_t *message, size_t message_len, const uint8_t *signature, size_t signature_len, const uint8_t *public_key);
} OQS_SIG;
/**
* Constructs an OQS_SIG object for a particular algorithm.
*
* Callers should always check whether the return value is `NULL`, which indicates either than an
* invalid algorithm name was provided, or that the requested algorithm was disabled at compile-time.
*
* @param[in] method_name Name of the desired algorithm; one of the names in `OQS_SIG_algs`.
* @return An OQS_SIG for the particular algorithm, or `NULL` if the algorithm has been disabled at compile-time.
*/
OQS_API OQS_SIG *OQS_SIG_new(const char *method_name);
/**
* Keypair generation algorithm.
*
* Caller is responsible for allocating sufficient memory for `public_key` and
* `secret_key`, based on the `length_*` members in this object or the per-scheme
* compile-time macros `OQS_SIG_*_length_*`.
*
* @param[in] sig The OQS_SIG object representing the signature scheme.
* @param[out] public_key The public key represented as a byte string.
* @param[out] secret_key The secret key represented as a byte string.
* @return OQS_SUCCESS or OQS_ERROR
*/
OQS_API OQS_STATUS OQS_SIG_keypair(const OQS_SIG *sig, uint8_t *public_key, uint8_t *secret_key);
/**
* Signature generation algorithm.
*
* Caller is responsible for allocating sufficient memory for `signnature`,
* based on the `length_*` members in this object or the per-scheme
* compile-time macros `OQS_SIG_*_length_*`.
*
* @param[in] sig The OQS_SIG object representing the signature scheme.
* @param[out] signature The signature on the message represented as a byte string.
* @param[out] signature_len The length of the signature.
* @param[in] message The message to sign represented as a byte string.
* @param[in] message_len The length of the message to sign.
* @param[in] secret_key The secret key represented as a byte string.
* @return OQS_SUCCESS or OQS_ERROR
*/
OQS_API OQS_STATUS OQS_SIG_sign(const OQS_SIG *sig, uint8_t *signature, size_t *signature_len, const uint8_t *message, size_t message_len, const uint8_t *secret_key);
/**
* Signature verification algorithm.
*
* @param[in] sig The OQS_SIG object representing the signature scheme.
* @param[in] message The message represented as a byte string.
* @param[in] message_len The length of the message.
* @param[in] signature The signature on the message represented as a byte string.
* @param[in] signature_len The length of the signature.
* @param[in] public_key The public key represented as a byte string.
* @return OQS_SUCCESS or OQS_ERROR
*/
OQS_API OQS_STATUS OQS_SIG_verify(const OQS_SIG *sig, const uint8_t *message, size_t message_len, const uint8_t *signature, size_t signature_len, const uint8_t *public_key);
/**
* Frees an OQS_SIG object that was constructed by OQS_SIG_new.
*
* @param[in] sig The OQS_SIG object to free.
*/
OQS_API void OQS_SIG_free(OQS_SIG *sig);
///// OQS_COPY_FROM_UPSTREAM_FRAGMENT_INCLUDE_START
#ifdef OQS_ENABLE_SIG_DILITHIUM
#include <oqs/sig_dilithium.h>
#endif /* OQS_ENABLE_SIG_DILITHIUM */
#ifdef OQS_ENABLE_SIG_FALCON
#include <oqs/sig_falcon.h>
#endif /* OQS_ENABLE_SIG_FALCON */
#ifdef OQS_ENABLE_SIG_SPHINCS
#include <oqs/sig_sphincs.h>
#endif /* OQS_ENABLE_SIG_SPHINCS */
///// OQS_COPY_FROM_UPSTREAM_FRAGMENT_INCLUDE_END
// EDIT-WHEN-ADDING-SIG
#if defined(__cplusplus)
} // extern "C"
#endif
#endif // OQS_SIG_H

57
libs/liboqs/rand/rand.c Normal file
View file

@ -0,0 +1,57 @@
// Used to allow us to inject entropy into liboqs
#include <stdint.h>
#include <string.h>
#include <stdlib.h>
#include "rand.h"
#define AMOUNT_OF_ENTROPY (64)
static uint8_t entropy[AMOUNT_OF_ENTROPY];
// Current offset of where the next byte of entropy is
//
// if it is equal to the size of of the entropy pool, then there is no more entropy left
static size_t current_offset = sizeof(entropy);
/**
* Overwrite entropy with the contents of the buffer. Up to AMOUNT_OF_ENTROPY can be loaded at once.
*
* @param bytes random bytes to be generated by the caller (NOTE: take care to clear this buffer afterward!)
* @param amount number of bytes in the buffer
* @return how much entropy is left (negative value if the amount is greater than the size of the entropy pool)
*/
long TUTA_inject_entropy(const void *bytes, size_t amount) {
// Cap it at the maximum size of our entropy pool
size_t actual_copy_amount = amount;
if (actual_copy_amount > sizeof(entropy)) {
actual_copy_amount = sizeof(entropy);
}
// clear any entropy that is leftover
memset(entropy, 0, sizeof(entropy));
// Copy in the entropy now
current_offset = sizeof(entropy) - actual_copy_amount;
memcpy(entropy + current_offset, bytes, actual_copy_amount);
return (long) sizeof(entropy) - (long) amount;
}
/**
* randombytes override - use external bytes
*/
void OQS_randombytes(uint8_t *random_array, size_t bytes_to_read) {
// If we don't have enough entropy remaining, crash
size_t remaining_entropy = sizeof(entropy) - current_offset;
if (bytes_to_read > remaining_entropy) {
exit(1);
}
uint8_t *entropy_to_copy = entropy + current_offset;
memcpy(random_array, entropy_to_copy, bytes_to_read);
memset(entropy_to_copy, 0, bytes_to_read); // clear out the bytes we just copied so it only exists in one place
current_offset += bytes_to_read;
}

24
libs/liboqs/rand/rand.h Normal file
View file

@ -0,0 +1,24 @@
#ifndef TUTA_RAND_H
#define TUTA_RAND_H
#include <stdint.h>
#include <stddef.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
* Overwrite entropy with the contents of the buffer. Up to AMOUNT_OF_ENTROPY can be loaded at once.
*
* @param bytes random bytes to be generated by the caller (NOTE: take care to clear this buffer afterward!)
* @param amount number of bytes in the buffer
* @return how much entropy is left (negative value if the amount is greater than the size of the entropy pool)
*/
long TUTA_inject_entropy(const void *bytes, size_t amount);
#ifdef __cplusplus
}
#endif
#endif

View file

@ -0,0 +1,151 @@
/**
* \file aes.h
* \brief Header defining the API for OQS AES
*
* SPDX-License-Identifier: MIT
*/
#ifndef OQS_AES_H
#define OQS_AES_H
#include <stdint.h>
#include <stdlib.h>
#if defined(__cplusplus)
extern "C" {
#endif
/**
* Function to fill a key schedule given an initial key for use in ECB mode.
*
* @param key Initial Key.
* @param ctx Abstract data structure for a key schedule.
*/
void OQS_AES128_ECB_load_schedule(const uint8_t *key, void **ctx);
/**
* Function to free a key schedule.
*
* @param ctx Context generated with OQS_AES128_ECB_load_schedule().
*/
void OQS_AES128_free_schedule(void *ctx);
/**
* Function to encrypt blocks of plaintext using ECB mode.
* A schedule based on the key is generated and used internally.
*
* @param plaintext Plaintext to be encrypted.
* @param plaintext_len Length on the plaintext in bytes. Must be a multiple of 16.
* @param key Key to be used for encryption.
* @param ciphertext Pointer to a block of memory which >= in size to the plaintext block. The result will be written here.
* @warning plaintext_len must be a multiple of 16.
*/
void OQS_AES128_ECB_enc(const uint8_t *plaintext, const size_t plaintext_len, const uint8_t *key, uint8_t *ciphertext);
/**
* Same as OQS_AES128_ECB_enc() except a schedule generated by
* OQS_AES128_ECB_load_schedule() is passed rather then a key. This is faster
* if the same schedule is used for multiple encryptions since it does
* not have to be regenerated from the key.
*/
void OQS_AES128_ECB_enc_sch(const uint8_t *plaintext, const size_t plaintext_len, const void *schedule, uint8_t *ciphertext);
/**
* Function to fill a key schedule given an initial key for use in ECB mode encryption.
*
* @param key Initial Key.
* @param ctx Abstract data structure for a key schedule.
*/
void OQS_AES256_ECB_load_schedule(const uint8_t *key, void **ctx);
/**
* Function to initialize a context and fill a key schedule given an initial key for
* use in CTR mode.
*
* @param key Initial Key.
* @param ctx Abstract data structure for a key schedule.
*/
void OQS_AES256_CTR_inc_init(const uint8_t *key, void **ctx);
/**
* Function to fill a context given an IV for use in CTR mode.
*
* Handles a 12- or 16-byte IV. If a 12-byte IV is given, then 4 counter
* bytes are initialized to all zeros.
*
* @param iv Initialization Vector.
* @param iv_len Length of the initialization vector.
* @param ctx Abstract data structure for IV.
*/
void OQS_AES256_CTR_inc_iv(const uint8_t *iv, size_t iv_len, void *ctx);
/**
* Function to fill a context given an IV for use in CTR mode.
* Handles an 8-byte IV passed as a 64-bit unsigned integer,
* counter bytes are initialized to zero.
*
* @param iv Initialization Vector as 64-bit integer.
* @param ctx Abstract data structure for IV.
*/
void OQS_AES256_CTR_inc_ivu64(uint64_t iv, void *ctx);
/**
* Function to free a key schedule.
*
* @param ctx Schedule generated with OQS_AES256_ECB_load_schedule
* or OQS_AES256_CTR_inc_init.
*/
void OQS_AES256_free_schedule(void *ctx);
/**
* Function to encrypt blocks of plaintext using ECB mode.
* A schedule based on the key is generated and used internally.
*
* @param plaintext Plaintext to be encrypted.
* @param plaintext_len Length on the plaintext in bytes. Must be a multiple of 16.
* @param key Key to be used for encryption.
* @param ciphertext Pointer to a block of memory which >= in size to the plaintext block. The result will be written here.
* @warning plaintext_len must be a multiple of 16.
*/
void OQS_AES256_ECB_enc(const uint8_t *plaintext, const size_t plaintext_len, const uint8_t *key, uint8_t *ciphertext);
/**
* Same as OQS_AES256_ECB_enc() except a schedule generated by
* OQS_AES256_ECB_load_schedule() is passed rather then a key. This is faster
* if the same schedule is used for multiple encryptions since it does
* not have to be regenerated from the key.
*/
void OQS_AES256_ECB_enc_sch(const uint8_t *plaintext, const size_t plaintext_len, const void *schedule, uint8_t *ciphertext);
/**
* AES counter mode keystream generator. A context generated by
* OQS_AES256_CTR_inc_init() is passed rather then a key.
*
* Handles a 12- or 16-byte IV. If a 12-byte IV is given, then 4 counter
* bytes are initialized to all zeros.
*
* @param iv 12- or 16-byte initialization vector.
* @param iv_len Lengh of IV in bytes.
* @param ctx Abstract data structure for a key schedule.
* @param out Pointer to a block of memory which is big enough to contain out_len bytes; the result will be written here.
* @param out_len Length of output bytes to generate.
*/
void OQS_AES256_CTR_inc_stream_iv(const uint8_t *iv, size_t iv_len, const void *ctx, uint8_t *out, size_t out_len);
/**
* AES counter mode keystream generator. A context generated by
* OQS_AES256_CTR_inc_init() and OQS_AES256_CTR_inc_iv() is passed
* rather than a key and an IV. The counter is internally updated, which allows
* the function to be called multiple times.
*
* @param ctx Abstract data structure for key schedule and IV.
* @param out Pointer to a block of memory which is big enough to contain out_blks*16 bytes; the result will be written here.
* @param out_blks Length of output blocks to generate, where one block is 16 bytes.
*/
void OQS_AES256_CTR_inc_stream_blks(void *ctx, uint8_t *out, size_t out_blks);
#if defined(__cplusplus)
} // extern "C"
#endif
#endif // OQS_AES_H

View file

@ -0,0 +1,42 @@
// SPDX-License-Identifier: MIT
#include <stdint.h>
void oqs_aes128_load_schedule_ni(const uint8_t *key, void **_schedule);
void oqs_aes128_free_schedule_ni(void *schedule);
void oqs_aes128_enc_sch_block_ni(const uint8_t *plaintext, const void *_schedule, uint8_t *ciphertext);
void oqs_aes128_ecb_enc_sch_ni(const uint8_t *plaintext, const size_t plaintext_len, const void *schedule, uint8_t *ciphertext);
void oqs_aes128_load_schedule_c(const uint8_t *key, void **_schedule);
void oqs_aes128_free_schedule_c(void *schedule);
void oqs_aes128_ecb_enc_sch_c(const uint8_t *plaintext, const size_t plaintext_len, const void *schedule, uint8_t *ciphertext);
void oqs_aes128_load_schedule_no_bitslice(const uint8_t *key, void **_schedule);
void oqs_aes128_free_schedule_no_bitslice(void *schedule);
void oqs_aes128_enc_sch_block_armv8(const uint8_t *plaintext, const void *_schedule, uint8_t *ciphertext);
void oqs_aes128_ecb_enc_sch_armv8(const uint8_t *plaintext, const size_t plaintext_len, const void *schedule, uint8_t *ciphertext);
void oqs_aes256_load_schedule_ni(const uint8_t *key, void **_schedule);
void oqs_aes256_load_iv_ni(const uint8_t *iv, size_t iv_len, void *_schedule);
void oqs_aes256_load_iv_u64_ni(uint64_t iv, void *_schedule);
void oqs_aes256_free_schedule_ni(void *schedule);
void oqs_aes256_enc_sch_block_ni(const uint8_t *plaintext, const void *_schedule, uint8_t *ciphertext);
void oqs_aes256_ecb_enc_sch_ni(const uint8_t *plaintext, const size_t plaintext_len, const void *schedule, uint8_t *ciphertext);
void oqs_aes256_ctr_enc_sch_ni(const uint8_t *iv, const size_t iv_len, const void *schedule, uint8_t *out, size_t out_len);
void oqs_aes256_ctr_enc_sch_upd_blks_ni(void *schedule, uint8_t *out, size_t out_len);
void oqs_aes256_load_schedule_c(const uint8_t *key, void **_schedule);
void oqs_aes256_load_iv_c(const uint8_t *iv, size_t iv_len, void *_schedule);
void oqs_aes256_load_iv_u64_c(uint64_t iv, void *_schedule);
void oqs_aes256_free_schedule_c(void *schedule);
void oqs_aes256_ecb_enc_sch_c(const uint8_t *plaintext, const size_t plaintext_len, const void *schedule, uint8_t *ciphertext);
void oqs_aes256_ctr_enc_sch_c(const uint8_t *iv, const size_t iv_len, const void *schedule, uint8_t *out, size_t out_len);
void oqs_aes256_ctr_enc_sch_upd_blks_c(void *schedule, uint8_t *out, size_t out_len);
void oqs_aes256_load_schedule_no_bitslice(const uint8_t *key, void **_schedule);
void oqs_aes256_load_iv_armv8(const uint8_t *iv, size_t iv_len, void *_schedule);
void oqs_aes256_free_schedule_no_bitslice(void *schedule);
void oqs_aes256_enc_sch_block_armv8(const uint8_t *plaintext, const void *_schedule, uint8_t *ciphertext);
void oqs_aes256_ecb_enc_sch_armv8(const uint8_t *plaintext, const size_t plaintext_len, const void *schedule, uint8_t *ciphertext);
void oqs_aes256_ctr_enc_sch_armv8(const uint8_t *iv, const size_t iv_len, const void *schedule, uint8_t *out, size_t out_len);
void oqs_aes256_ctr_enc_sch_upd_blks_armv8(void *schedule, uint8_t *out, size_t out_blks);

View file

@ -0,0 +1,355 @@
// SPDX-License-Identifier: Apache-2.0 AND MIT
#if !defined(_WIN32) && !defined(OQS_HAVE_EXPLICIT_BZERO)
// Request memset_s
#define __STDC_WANT_LIB_EXT1__ 1
#endif
#include <oqs/common.h>
#include <errno.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#if !defined(OQS_HAVE_POSIX_MEMALIGN) || defined(__MINGW32__) || defined(__MINGW64__) || defined(_MSC_VER)
#include <malloc.h>
#endif
#if defined(_WIN32)
#include <windows.h>
#endif
#if defined(OQS_USE_OPENSSL)
#include <openssl/evp.h>
#include "ossl_helpers.h"
CRYPTO_ONCE OQS_ONCE_STATIC_FREE;
#endif
/* Identifying the CPU is expensive so we cache the results in cpu_ext_data */
#if defined(OQS_DIST_BUILD)
static unsigned int cpu_ext_data[OQS_CPU_EXT_COUNT] = {0};
#endif
#if defined(OQS_DIST_X86_64_BUILD)
/* set_available_cpu_extensions_x86_64() has been written using:
* https://github.com/google/cpu_features/blob/master/src/cpuinfo_x86.c
*/
#include "x86_64_helpers.h"
static void set_available_cpu_extensions(void) {
/* mark that this function has been called */
cpu_ext_data[OQS_CPU_EXT_INIT] = 1;
cpuid_out leaf_1;
cpuid(&leaf_1, 1);
if (leaf_1.eax == 0) {
return;
}
cpuid_out leaf_7;
cpuid(&leaf_7, 7);
const unsigned int has_xsave = is_bit_set(leaf_1.ecx, 26);
const unsigned int has_osxsave = is_bit_set(leaf_1.ecx, 27);
const uint32_t xcr0_eax = (has_xsave && has_osxsave) ? xgetbv_eax(0) : 0;
cpu_ext_data[OQS_CPU_EXT_AES] = is_bit_set(leaf_1.ecx, 25);
if (has_mask(xcr0_eax, MASK_XMM | MASK_YMM)) {
cpu_ext_data[OQS_CPU_EXT_AVX] = is_bit_set(leaf_1.ecx, 28);
cpu_ext_data[OQS_CPU_EXT_AVX2] = is_bit_set(leaf_7.ebx, 5);
}
cpu_ext_data[OQS_CPU_EXT_PCLMULQDQ] = is_bit_set(leaf_1.ecx, 1);
cpu_ext_data[OQS_CPU_EXT_POPCNT] = is_bit_set(leaf_1.ecx, 23);
cpu_ext_data[OQS_CPU_EXT_BMI1] = is_bit_set(leaf_7.ebx, 3);
cpu_ext_data[OQS_CPU_EXT_BMI2] = is_bit_set(leaf_7.ebx, 8);
cpu_ext_data[OQS_CPU_EXT_ADX] = is_bit_set(leaf_7.ebx, 19);
if (has_mask(xcr0_eax, MASK_XMM)) {
cpu_ext_data[OQS_CPU_EXT_SSE] = is_bit_set(leaf_1.edx, 25);
cpu_ext_data[OQS_CPU_EXT_SSE2] = is_bit_set(leaf_1.edx, 26);
cpu_ext_data[OQS_CPU_EXT_SSE3] = is_bit_set(leaf_1.ecx, 0);
}
if (has_mask(xcr0_eax, MASK_XMM | MASK_YMM | MASK_MASKREG | MASK_ZMM0_15 | MASK_ZMM16_31)) {
unsigned int avx512f = is_bit_set(leaf_7.ebx, 16);
unsigned int avx512bw = is_bit_set(leaf_7.ebx, 30);
unsigned int avx512dq = is_bit_set(leaf_7.ebx, 17);
if (avx512f && avx512bw && avx512dq) {
cpu_ext_data[OQS_CPU_EXT_AVX512] = 1;
}
cpu_ext_data[OQS_CPU_EXT_VPCLMULQDQ] = is_bit_set(leaf_7.ecx, 10);
}
}
#elif defined(OQS_DIST_X86_BUILD)
static void set_available_cpu_extensions(void) {
/* mark that this function has been called */
cpu_ext_data[OQS_CPU_EXT_INIT] = 1;
}
#elif defined(OQS_DIST_ARM64_V8_BUILD)
#if defined(__APPLE__)
#include <sys/sysctl.h>
static unsigned int macos_feature_detection(const char *feature_name) {
int p;
size_t p_len = sizeof(p);
int res = sysctlbyname(feature_name, &p, &p_len, NULL, 0);
if (res != 0) {
return 0;
} else {
return (p != 0) ? 1 : 0;
}
}
static void set_available_cpu_extensions(void) {
/* mark that this function has been called */
cpu_ext_data[OQS_CPU_EXT_ARM_AES] = 1;
cpu_ext_data[OQS_CPU_EXT_ARM_SHA2] = 1;
cpu_ext_data[OQS_CPU_EXT_ARM_SHA3] = macos_feature_detection("hw.optional.armv8_2_sha3");
cpu_ext_data[OQS_CPU_EXT_ARM_NEON] = macos_feature_detection("hw.optional.neon");
cpu_ext_data[OQS_CPU_EXT_INIT] = 1;
}
#elif defined(__FreeBSD__) || defined(__FreeBSD)
#include <sys/auxv.h>
#include <machine/elf.h>
static void set_available_cpu_extensions(void) {
/* mark that this function has been called */
u_long hwcaps = 0;
cpu_ext_data[OQS_CPU_EXT_INIT] = 1;
if (elf_aux_info(AT_HWCAP, &hwcaps, sizeof(u_long))) {
fprintf(stderr, "Error getting HWCAP for ARM on FreeBSD\n");
return;
}
if (hwcaps & HWCAP_AES) {
cpu_ext_data[OQS_CPU_EXT_ARM_AES] = 1;
}
if (hwcaps & HWCAP_ASIMD) {
cpu_ext_data[OQS_CPU_EXT_ARM_NEON] = 1;
}
if (hwcaps & HWCAP_SHA2) {
cpu_ext_data[OQS_CPU_EXT_ARM_SHA2] = 1;
}
#ifdef HWCAP_SHA3
if (hwcaps & HWCAP_SHA3) {
cpu_ext_data[OQS_CPU_EXT_ARM_SHA3] = 1;
}
#endif
}
#elif defined(_WIN32)
static void set_available_cpu_extensions(void) {
/* mark that this function has been called */
cpu_ext_data[OQS_CPU_EXT_INIT] = 1;
BOOL crypto = IsProcessorFeaturePresent(PF_ARM_V8_CRYPTO_INSTRUCTIONS_AVAILABLE);
if (crypto) {
cpu_ext_data[OQS_CPU_EXT_ARM_AES] = 1;
cpu_ext_data[OQS_CPU_EXT_ARM_SHA2] = 1;
}
BOOL neon = IsProcessorFeaturePresent(PF_ARM_VFP_32_REGISTERS_AVAILABLE);
if (neon) {
cpu_ext_data[OQS_CPU_EXT_ARM_NEON] = 1;
}
}
#else
#include <sys/auxv.h>
#include <asm/hwcap.h>
static void set_available_cpu_extensions(void) {
/* mark that this function has been called */
cpu_ext_data[OQS_CPU_EXT_INIT] = 1;
unsigned long int hwcaps = getauxval(AT_HWCAP);
if (hwcaps & HWCAP_AES) {
cpu_ext_data[OQS_CPU_EXT_ARM_AES] = 1;
}
if (hwcaps & HWCAP_SHA2) {
cpu_ext_data[OQS_CPU_EXT_ARM_SHA2] = 1;
}
#ifdef HWCAP_SHA3
if (hwcaps & HWCAP_SHA3) {
cpu_ext_data[OQS_CPU_EXT_ARM_SHA3] = 1;
}
#endif
if (hwcaps & HWCAP_ASIMD) {
cpu_ext_data[OQS_CPU_EXT_ARM_NEON] = 1;
}
}
#endif
#elif defined(OQS_DIST_ARM32v7_BUILD)
#include <sys/auxv.h>
#include <asm/hwcap.h>
static void set_available_cpu_extensions(void) {
/* mark that this function has been called */
cpu_ext_data[OQS_CPU_EXT_INIT] = 1;
unsigned long int hwcaps = getauxval(AT_HWCAP);
unsigned long int hwcaps2 = getauxval(AT_HWCAP2);
if (hwcaps2 & HWCAP2_AES) {
cpu_ext_data[OQS_CPU_EXT_ARM_AES] = 1;
}
if (hwcaps2 & HWCAP2_SHA2) {
cpu_ext_data[OQS_CPU_EXT_ARM_SHA2] = 1;
}
if (hwcaps & HWCAP_NEON) {
cpu_ext_data[OQS_CPU_EXT_ARM_NEON] = 1;
}
}
#elif defined(OQS_DIST_PPC64LE_BUILD)
static void set_available_cpu_extensions(void) {
/* mark that this function has been called */
cpu_ext_data[OQS_CPU_EXT_INIT] = 1;
}
#elif defined(OQS_DIST_S390X_BUILD)
static void set_available_cpu_extensions(void) {
/* mark that this function has been called */
cpu_ext_data[OQS_CPU_EXT_INIT] = 1;
}
#elif defined(OQS_DIST_BUILD)
static void set_available_cpu_extensions(void) {
}
#endif
OQS_API int OQS_CPU_has_extension(OQS_CPU_EXT ext) {
#if defined(OQS_DIST_BUILD)
if (0 == cpu_ext_data[OQS_CPU_EXT_INIT]) {
set_available_cpu_extensions();
}
if (0 < ext && ext < OQS_CPU_EXT_COUNT) {
return (int)cpu_ext_data[ext];
}
#else
(void)ext;
#endif
return 0;
}
OQS_API void OQS_init(void) {
#if defined(OQS_DIST_BUILD)
OQS_CPU_has_extension(OQS_CPU_EXT_INIT);
#endif
return;
}
OQS_API const char *OQS_version(void) {
return OQS_VERSION_TEXT;
}
OQS_API void OQS_destroy(void) {
#if defined(OQS_USE_OPENSSL)
CRYPTO_THREAD_run_once(&OQS_ONCE_STATIC_FREE, oqs_free_ossl_objects);
#endif
return;
}
OQS_API int OQS_MEM_secure_bcmp(const void *a, const void *b, size_t len) {
/* Assume CHAR_BIT = 8 */
uint8_t r = 0;
for (size_t i = 0; i < len; i++) {
r |= ((const uint8_t *)a)[i] ^ ((const uint8_t *)b)[i];
}
// We have 0 <= r < 256, and unsigned int is at least 16 bits.
return 1 & ((-(unsigned int)r) >> 8);
}
OQS_API void OQS_MEM_cleanse(void *ptr, size_t len) {
#if defined(_WIN32)
SecureZeroMemory(ptr, len);
#elif defined(OQS_HAVE_EXPLICIT_BZERO)
explicit_bzero(ptr, len);
#elif defined(__STDC_LIB_EXT1__) || defined(OQS_HAVE_MEMSET_S)
if (0U < len && memset_s(ptr, (rsize_t)len, 0, (rsize_t)len) != 0) {
abort();
}
#else
typedef void *(*memset_t)(void *, int, size_t);
static volatile memset_t memset_func = memset;
memset_func(ptr, 0, len);
#endif
}
OQS_API void OQS_MEM_secure_free(void *ptr, size_t len) {
if (ptr != NULL) {
OQS_MEM_cleanse(ptr, len);
free(ptr); // IGNORE free-check
}
}
OQS_API void OQS_MEM_insecure_free(void *ptr) {
free(ptr); // IGNORE free-check
}
void *OQS_MEM_aligned_alloc(size_t alignment, size_t size) {
#if defined(OQS_HAVE_ALIGNED_ALLOC) // glibc and other implementations providing aligned_alloc
return aligned_alloc(alignment, size);
#else
// Check alignment (power of 2, and >= sizeof(void*)) and size (multiple of alignment)
if (alignment & (alignment - 1) || size & (alignment - 1) || alignment < sizeof(void *)) {
errno = EINVAL;
return NULL;
}
#if defined(OQS_HAVE_POSIX_MEMALIGN)
void *ptr = NULL;
const int err = posix_memalign(&ptr, alignment, size);
if (err) {
errno = err;
ptr = NULL;
}
return ptr;
#elif defined(OQS_HAVE_MEMALIGN)
return memalign(alignment, size);
#elif defined(__MINGW32__) || defined(__MINGW64__)
return __mingw_aligned_malloc(size, alignment);
#elif defined(_MSC_VER)
return _aligned_malloc(size, alignment);
#else
if (!size) {
return NULL;
}
// Overallocate to be able to align the pointer (alignment -1) and to store
// the difference between the pointer returned to the user (ptr) and the
// pointer returned by malloc (buffer). The difference is caped to 255 and
// can be made larger if necessary, but this should be enough for all users
// in liboqs.
//
// buffer ptr
// ↓ ↓
// ...........|...................
// |
// diff = ptr - buffer
const size_t offset = alignment - 1 + sizeof(uint8_t);
uint8_t *buffer = malloc(size + offset);
if (!buffer) {
return NULL;
}
// Align the pointer returned to the user.
uint8_t *ptr = (uint8_t *)(((uintptr_t)(buffer) + offset) & ~(alignment - 1));
ptrdiff_t diff = ptr - buffer;
if (diff > UINT8_MAX) {
// This should never happen in our code, but just to be safe
free(buffer); // IGNORE free-check
errno = EINVAL;
return NULL;
}
// Store the difference one byte ahead the returned poitner so that free
// can reconstruct buffer.
ptr[-1] = diff;
return ptr;
#endif
#endif
}
void OQS_MEM_aligned_free(void *ptr) {
#if defined(OQS_HAVE_ALIGNED_ALLOC) || defined(OQS_HAVE_POSIX_MEMALIGN) || defined(OQS_HAVE_MEMALIGN)
free(ptr); // IGNORE free-check
#elif defined(__MINGW32__) || defined(__MINGW64__)
__mingw_aligned_free(ptr);
#elif defined(_MSC_VER)
_aligned_free(ptr);
#else
if (ptr) {
// Reconstruct the pointer returned from malloc using the difference
// stored one byte ahead of ptr.
uint8_t *u8ptr = ptr;
free(u8ptr - u8ptr[-1]); // IGNORE free-check
}
#endif
}

View file

@ -0,0 +1,226 @@
/**
* \file common.h
* \brief Utility functions for use in liboqs.
*
* SPDX-License-Identifier: MIT
*/
#ifndef OQS_COMMON_H
#define OQS_COMMON_H
#include <limits.h>
#include <stdint.h>
#include <stdlib.h>
#include <stdio.h>
#include <oqs/oqsconfig.h>
#if defined(__cplusplus)
extern "C" {
#endif
/**
* Macro for terminating the program if x is
* a null pointer.
*/
#define OQS_EXIT_IF_NULLPTR(x, loc) \
do { \
if ( (x) == (void*)0 ) { \
fprintf(stderr, "Unexpected NULL returned from %s API. Exiting.\n", loc); \
exit(EXIT_FAILURE); \
} \
} while (0)
/**
* This macro is intended to replace those assert()s
* involving side-effecting statements in aes/aes_ossl.c.
*
* assert() becomes a no-op when -DNDEBUG is defined,
* which causes compilation failures when the statement
* being checked also results in side-effects.
*
* This is a temporary workaround until a better error
* handling strategy is developed.
*/
#define OQS_OPENSSL_GUARD(x) \
do { \
if( 1 != (x) ) { \
fprintf(stderr, "Error return value from OpenSSL API: %d. Exiting.\n", x); \
exit(EXIT_FAILURE); \
} \
} while (0)
/**
* Certain functions (such as OQS_randombytes_openssl in
* src/rand/rand.c) take in a size_t parameter, but can
* only handle values up to INT_MAX for those parameters.
* This macro is a temporary workaround for such functions.
*/
#define SIZE_T_TO_INT_OR_EXIT(size_t_var_name, int_var_name) \
int int_var_name = 0; \
if (size_t_var_name <= INT_MAX) { \
int_var_name = (int)size_t_var_name; \
} else { \
exit(EXIT_FAILURE); \
}
/**
* Defines which functions should be exposed outside the LibOQS library
*
* By default the visibility of all the symbols is defined to "hidden"
* Only the library API should be marked as default
*
* Example: OQS_API return_value function_name(void);
*/
#if defined(_WIN32)
#define OQS_API __declspec(dllexport)
#else
#define OQS_API __attribute__((visibility("default")))
#endif
#if defined(OQS_SYS_UEFI)
#undef OQS_API
#define OQS_API
#endif
/**
* Represents return values from functions.
*
* Callers should compare with the symbol rather than the individual value.
* For example,
*
* ret = OQS_KEM_encaps(...);
* if (ret == OQS_SUCCESS) { ... }
*
* rather than
*
* if (!OQS_KEM_encaps(...) { ... }
*
*/
typedef enum {
/** Used to indicate that some undefined error occurred. */
OQS_ERROR = -1,
/** Used to indicate successful return from function. */
OQS_SUCCESS = 0,
/** Used to indicate failures in external libraries (e.g., OpenSSL). */
OQS_EXTERNAL_LIB_ERROR_OPENSSL = 50,
} OQS_STATUS;
/**
* CPU runtime detection flags
*/
typedef enum {
OQS_CPU_EXT_INIT, /* Must be first */
/* Start extension list */
OQS_CPU_EXT_ADX,
OQS_CPU_EXT_AES,
OQS_CPU_EXT_AVX,
OQS_CPU_EXT_AVX2,
OQS_CPU_EXT_AVX512,
OQS_CPU_EXT_BMI1,
OQS_CPU_EXT_BMI2,
OQS_CPU_EXT_PCLMULQDQ,
OQS_CPU_EXT_VPCLMULQDQ,
OQS_CPU_EXT_POPCNT,
OQS_CPU_EXT_SSE,
OQS_CPU_EXT_SSE2,
OQS_CPU_EXT_SSE3,
OQS_CPU_EXT_ARM_AES,
OQS_CPU_EXT_ARM_SHA2,
OQS_CPU_EXT_ARM_SHA3,
OQS_CPU_EXT_ARM_NEON,
/* End extension list */
OQS_CPU_EXT_COUNT, /* Must be last */
} OQS_CPU_EXT;
/**
* Checks if the CPU supports a given extension
*
* \return 1 if the given CPU extension is available, 0 otherwise.
*/
OQS_API int OQS_CPU_has_extension(OQS_CPU_EXT ext);
/**
* This currently sets the values in the OQS_CPU_EXTENSIONS
* and prefetches the OpenSSL objects if necessary.
*/
OQS_API void OQS_init(void);
/**
* This function frees prefetched OpenSSL objects
*/
OQS_API void OQS_destroy(void);
/**
* Return library version string.
*/
OQS_API const char *OQS_version(void);
/**
* Constant time comparison of byte sequences `a` and `b` of length `len`.
* Returns 0 if the byte sequences are equal or if `len`=0.
* Returns 1 otherwise.
*
* @param[in] a A byte sequence of length at least `len`.
* @param[in] b A byte sequence of length at least `len`.
* @param[in] len The number of bytes to compare.
*/
OQS_API int OQS_MEM_secure_bcmp(const void *a, const void *b, size_t len);
/**
* Zeros out `len` bytes of memory starting at `ptr`.
*
* Designed to be protected against optimizing compilers which try to remove
* "unnecessary" operations. Should be used for all buffers containing secret
* data.
*
* @param[in] ptr The start of the memory to zero out.
* @param[in] len The number of bytes to zero out.
*/
OQS_API void OQS_MEM_cleanse(void *ptr, size_t len);
/**
* Zeros out `len` bytes of memory starting at `ptr`, then frees `ptr`.
*
* Can be called with `ptr = NULL`, in which case no operation is performed.
*
* Designed to be protected against optimizing compilers which try to remove
* "unnecessary" operations. Should be used for all buffers containing secret
* data.
*
* @param[in] ptr The start of the memory to zero out and free.
* @param[in] len The number of bytes to zero out.
*/
OQS_API void OQS_MEM_secure_free(void *ptr, size_t len);
/**
* Frees `ptr`.
*
* Can be called with `ptr = NULL`, in which case no operation is performed.
*
* Should only be used on non-secret data.
*
* @param[in] ptr The start of the memory to free.
*/
OQS_API void OQS_MEM_insecure_free(void *ptr);
/**
* Internal implementation of C11 aligned_alloc to work around compiler quirks.
*
* Allocates size bytes of uninitialized memory with a base pointer that is
* a multiple of alignment. Alignment must be a power of two and a multiple
* of sizeof(void *). Size must be a multiple of alignment.
*/
void *OQS_MEM_aligned_alloc(size_t alignment, size_t size);
/**
* Free memory allocated with OQS_MEM_aligned_alloc.
*/
void OQS_MEM_aligned_free(void *ptr);
#if defined(__cplusplus)
} // extern "C"
#endif
#endif // OQS_COMMON_H

View file

@ -0,0 +1,39 @@
// SPDX-License-Identifier: MIT
#ifndef OQS_OSSL_HELPERS_H
#define OQS_OSSL_HELPERS_H
#if defined(__cplusplus)
extern "C" {
#endif
#if defined(OQS_USE_OPENSSL)
void oqs_free_ossl_objects(void);
const EVP_MD *oqs_sha256(void);
const EVP_MD *oqs_sha384(void);
const EVP_MD *oqs_sha512(void);
const EVP_MD *oqs_shake128(void);
const EVP_MD *oqs_shake256(void);
const EVP_MD *oqs_sha3_256(void);
const EVP_MD *oqs_sha3_384(void);
const EVP_MD *oqs_sha3_512(void);
const EVP_CIPHER *oqs_aes_128_ecb(void);
const EVP_CIPHER *oqs_aes_256_ecb(void);
const EVP_CIPHER *oqs_aes_256_ctr(void);
#endif
#if defined(__cplusplus)
} // extern "C"
#endif
#endif // OQS_OSSL_HELPERS_H

View file

@ -0,0 +1,46 @@
// SPDX-License-Identifier: MIT
#ifndef AES_H
#define AES_H
#include <stdint.h>
#include <stdlib.h>
#include <oqs/aes.h>
#define AES256_KEYBYTES 32
#define AESCTR_NONCEBYTES 12
#define AES_BLOCKBYTES 16
typedef void *aes256ctx;
#define aes256_ecb_keyexp(r, key) OQS_AES256_ECB_load_schedule((key), (r))
#define aes256_ecb(out, in, nblocks, ctx) OQS_AES256_ECB_enc_sch((in), (nblocks) * AES_BLOCKBYTES, *(ctx), (out))
#define aes256_ctr_keyexp(r, key) OQS_AES256_CTR_inc_init((key), (r))
#define aes256_ctr(out, outlen, iv, ctx) OQS_AES256_CTR_inc_stream_iv((iv), AESCTR_NONCEBYTES, *(ctx), (out), (outlen))
#define aes256_ctx_release(ctx) OQS_AES256_free_schedule(*(ctx))
#define aes256ctr_squeezeblocks(out, outlen, state) OQS_AES256_CTR_inc_stream_blks(*state, out, 4*outlen)
#define aes256ctr_squeezeblocks_u64(out, outlen, iv, ctx) OQS_AES256_CTR_inc_stream_ivu64_blks((iv), *(ctx), (out), (4*outlen))
#define aes256ctr_init_key(state, key) OQS_AES256_CTR_inc_init(key, state)
#define aes256ctr_init_iv(state, nonce) OQS_AES256_CTR_inc_iv(nonce, 12, *state)
#define aes256ctr_init_iv_u64(state, nonce) OQS_AES256_CTR_inc_ivu64(nonce, *state)
static inline void aes256ctr_init(void **_schedule, const uint8_t *key, const uint8_t *nonce) {
OQS_AES256_CTR_inc_init(key, _schedule);
OQS_AES256_CTR_inc_iv(nonce, 12, *_schedule);
}
static inline void aes256ctr_init_u64(void **_schedule, const uint8_t *key, uint64_t nonce) {
OQS_AES256_CTR_inc_init(key, _schedule);
OQS_AES256_CTR_inc_ivu64(nonce, *_schedule);
}
static inline void aes256ctr_prf(uint8_t *out, size_t outlen, const uint8_t key[32], uint8_t nonce[12]) {
aes256ctx state;
OQS_AES256_CTR_inc_init(key, &state);
OQS_AES256_CTR_inc_stream_iv(nonce, 12, state, out, outlen);
OQS_AES256_free_schedule(state);
}
#endif

View file

@ -0,0 +1,12 @@
// SPDX-License-Identifier: MIT
#ifndef AES256CTR_H
#define AES256CTR_H
#include "aes.h"
typedef aes256ctx aes256ctr_ctx;
#define AES256CTR_BLOCKBYTES 64
#endif

View file

@ -0,0 +1,61 @@
#ifndef OQS_COMMON_COMPAT_H
#define OQS_COMMON_COMPAT_H
/* This file serves to solve compatibility issues between different
* versions of compilers.
*
* This file is allowed to use #ifdefs and toggle things by compiler versions.
*
* SPDX-License-Identifier: MIT
*
*/
// From https://github.com/gcc-mirror/gcc/blob/af73a8b2027d9ab64944d7dbbb48e207d7790ce6/gcc/config/i386/avxintrin.h#L62-L71
/* Unaligned versions of the vector types */
#define UNALIGNED_VECTOR_POLYFILL_GCC \
typedef float __m256_u __attribute__ ((__vector_size__ (32), __may_alias__, __aligned__ (1))); \
typedef double __m256d_u __attribute__ ((__vector_size__ (32), __may_alias__, __aligned__ (1))); \
typedef long long __m256i_u __attribute__ ((__vector_size__ (32), __may_alias__, __aligned__ (1)));
#if defined(__GNUC__) && !defined(__clang__)
#if ((__GNUC__ << 16) + __GNUC_MINOR__ >= ((7) << 16) + (1)) // at least GCC 7.1
/* Versions of the GCC pre-7.1 don't have __m256*_u types */
UNALIGNED_VECTOR_POLYFILL_GCC
# endif // GCC >= 7.1
#elif defined(__GNUC__) && defined(__clang__)
# if __clang__major__ < 9
/* Versions of Clang pre-9.0 don't have __m256*_u types */
UNALIGNED_VECTOR_POLYFILL_GCC
# endif
#else
// Neither MSVC nor other compilers seem to have these types
#define __m256_u __m256
#define __m256d_u __m256d
#define __m256i_u __m256i
#endif // compiler selector
/************************
* Portable VLA support *
************************/
/* To support MSVC use alloca() instead of VLAs. */
#ifdef _MSC_VER
/* MSVC defines _alloca in malloc.h */
# include <malloc.h>
/* Note: _malloca(), which is recommended over deprecated _alloca,
requires that you call _freea(). So we stick with _alloca */
# define PQCLEAN_VLA(__t,__x,__s) __t *__x = (__t*)_alloca((__s)*sizeof(__t))
#else
# define PQCLEAN_VLA(__t,__x,__s) __t __x[__s]
#endif
#endif // OQS_COMMON_COMPAT_H

View file

@ -0,0 +1,8 @@
// SPDX-License-Identifier: MIT
#ifndef CRYPTO_DECLASSIFY
#define CRYPTO_DECLASSIFY
#define crypto_declassify(x, y)
#endif

View file

@ -0,0 +1,15 @@
// SPDX-License-Identifier: MIT
#include "fips202.h"
void shake128_absorb_once(shake128incctx *state, const uint8_t *in, size_t inlen) {
shake128_inc_ctx_reset(state);
shake128_inc_absorb(state, in, inlen);
shake128_inc_finalize(state);
}
void shake256_absorb_once(shake256incctx *state, const uint8_t *in, size_t inlen) {
shake256_inc_ctx_reset(state);
shake256_inc_absorb(state, in, inlen);
shake256_inc_finalize(state);
}

View file

@ -0,0 +1,68 @@
// SPDX-License-Identifier: MIT
#ifndef FIPS202_H
#define FIPS202_H
#include <oqs/sha3.h>
#define SHAKE128_RATE OQS_SHA3_SHAKE128_RATE
#define shake128 OQS_SHA3_shake128
#define SHAKE256_RATE OQS_SHA3_SHAKE256_RATE
#define shake256 OQS_SHA3_shake256
#define SHA3_256_RATE OQS_SHA3_SHA3_256_RATE
#define sha3_256 OQS_SHA3_sha3_256
#define sha3_256_inc_init OQS_SHA3_sha3_256_inc_init
#define sha3_256_inc_absorb OQS_SHA3_sha3_256_inc_absorb
#define sha3_256_inc_finalize OQS_SHA3_sha3_256_inc_finalize
#define sha3_256_inc_ctx_clone OQS_SHA3_sha3_256_inc_ctx_clone
#define sha3_256_inc_ctx_release OQS_SHA3_sha3_256_inc_ctx_release
#define SHA3_384_RATE OQS_SHA3_SHA3_384_RATE
#define sha3_384 OQS_SHA3_sha3_384
#define sha3_384_inc_init OQS_SHA3_sha3_384_inc_init
#define sha3_384_inc_absorb OQS_SHA3_sha3_384_inc_absorb
#define sha3_384_inc_finalize OQS_SHA3_sha3_384_inc_finalize
#define sha3_384_inc_ctx_clone OQS_SHA3_sha3_384_inc_ctx_clone
#define sha3_384_inc_ctx_release OQS_SHA3_sha3_384_inc_ctx_release
#define SHA3_512_RATE OQS_SHA3_SHA3_512_RATE
#define sha3_512 OQS_SHA3_sha3_512
#define sha3_512_inc_init OQS_SHA3_sha3_512_inc_init
#define sha3_512_inc_absorb OQS_SHA3_sha3_512_inc_absorb
#define sha3_512_inc_finalize OQS_SHA3_sha3_512_inc_finalize
#define sha3_512_inc_ctx_clone OQS_SHA3_sha3_512_inc_ctx_clone
#define sha3_512_inc_ctx_release OQS_SHA3_sha3_512_inc_ctx_release
#define shake128incctx OQS_SHA3_shake128_inc_ctx
#define shake128_inc_init OQS_SHA3_shake128_inc_init
#define shake128_inc_absorb OQS_SHA3_shake128_inc_absorb
#define shake128_inc_finalize OQS_SHA3_shake128_inc_finalize
#define shake128_inc_squeeze OQS_SHA3_shake128_inc_squeeze
#define shake128_inc_ctx_release OQS_SHA3_shake128_inc_ctx_release
#define shake128_inc_ctx_clone OQS_SHA3_shake128_inc_ctx_clone
#define shake128_inc_ctx_reset OQS_SHA3_shake128_inc_ctx_reset
#define shake256incctx OQS_SHA3_shake256_inc_ctx
#define shake256_inc_init OQS_SHA3_shake256_inc_init
#define shake256_inc_absorb OQS_SHA3_shake256_inc_absorb
#define shake256_inc_finalize OQS_SHA3_shake256_inc_finalize
#define shake256_inc_squeeze OQS_SHA3_shake256_inc_squeeze
#define shake256_inc_ctx_release OQS_SHA3_shake256_inc_ctx_release
#define shake256_inc_ctx_clone OQS_SHA3_shake256_inc_ctx_clone
#define shake256_inc_ctx_reset OQS_SHA3_shake256_inc_ctx_reset
#define shake128_absorb_once OQS_SHA3_shake128_absorb_once
void OQS_SHA3_shake128_absorb_once(shake128incctx *state, const uint8_t *in, size_t inlen);
#define shake256_absorb_once OQS_SHA3_shake256_absorb_once
void OQS_SHA3_shake256_absorb_once(shake256incctx *state, const uint8_t *in, size_t inlen);
#define shake128_squeezeblocks(OUT, NBLOCKS, STATE) \
OQS_SHA3_shake128_inc_squeeze(OUT, (NBLOCKS)*OQS_SHA3_SHAKE128_RATE, STATE)
#define shake256_squeezeblocks(OUT, NBLOCKS, STATE) \
OQS_SHA3_shake256_inc_squeeze(OUT, (NBLOCKS)*OQS_SHA3_SHAKE256_RATE, STATE)
#endif

View file

@ -0,0 +1,51 @@
// SPDX-License-Identifier: MIT
#ifndef FIPS202X4_H
#define FIPS202X4_H
#include <oqs/oqsconfig.h>
#ifdef ARCH_X86_64
#include <immintrin.h>
#endif
#include <oqs/sha3x4.h>
#if defined(OQS_DIST_X86_64_BUILD) && defined(OQS_ENABLE_SHA3_xkcp_low_avx2)
#define KeccakP1600times4_PermuteAll_24rounds KeccakP1600times4_PermuteAll_24rounds_avx2
#endif
#define shake128x4incctx OQS_SHA3_shake128_x4_inc_ctx
#define shake128x4_inc_init OQS_SHA3_shake128_x4_inc_init
#define shake128x4_inc_absorb OQS_SHA3_shake128_x4_inc_absorb
#define shake128x4_inc_finalize OQS_SHA3_shake128_x4_inc_finalize
#define shake128x4_inc_squeeze OQS_SHA3_shake128_x4_inc_squeeze
#define shake128x4_inc_ctx_release OQS_SHA3_shake128_x4_inc_ctx_release
#define shake128x4_inc_ctx_clone OQS_SHA3_shake128_x4_inc_ctx_clone
#define shake128x4_inc_ctx_reset OQS_SHA3_shake128_x4_inc_ctx_reset
#define shake256x4incctx OQS_SHA3_shake256_x4_inc_ctx
#define shake256x4_inc_init OQS_SHA3_shake256_x4_inc_init
#define shake256x4_inc_absorb OQS_SHA3_shake256_x4_inc_absorb
#define shake256x4_inc_finalize OQS_SHA3_shake256_x4_inc_finalize
#define shake256x4_inc_squeeze OQS_SHA3_shake256_x4_inc_squeeze
#define shake256x4_inc_ctx_release OQS_SHA3_shake256_x4_inc_ctx_release
#define shake256x4_inc_ctx_clone OQS_SHA3_shake256_x4_inc_ctx_clone
#define shake256x4_inc_ctx_reset OQS_SHA3_shake256_x4_inc_ctx_reset
#define shake256x4 OQS_SHA3_shake256_x4
#define shake128x4 OQS_SHA3_shake128_x4
#define shake128x4_absorb_once OQS_SHA3_shake128_x4_absorb_once
void OQS_SHA3_shake128_x4_absorb_once(shake128x4incctx *state, const uint8_t *in0, const uint8_t *in1, const uint8_t *in2, const uint8_t *in3, size_t inlen);
#define shake256x4_absorb_once OQS_SHA3_shake256_x4_absorb_once
void OQS_SHA3_shake256_x4_absorb_once(shake256x4incctx *state, const uint8_t *in0, const uint8_t *in1, const uint8_t *in2, const uint8_t *in3, size_t inlen);
#define shake128x4_squeezeblocks(OUT0, OUT1, OUT2, OUT3, NBLOCKS, STATE) \
OQS_SHA3_shake128_x4_inc_squeeze(OUT0, OUT1, OUT2, OUT3, (NBLOCKS)*OQS_SHA3_SHAKE128_RATE, STATE)
#define shake256x4_squeezeblocks(OUT0, OUT1, OUT2, OUT3, NBLOCKS, STATE) \
OQS_SHA3_shake256_x4_inc_squeeze(OUT0, OUT1, OUT2, OUT3, (NBLOCKS)*OQS_SHA3_SHAKE256_RATE, STATE)
#endif

View file

@ -0,0 +1,47 @@
#ifndef NISTSEEDEXPANDER_H
#define NISTSEEDEXPANDER_H
//
// rng.h
//
// Created by Bassham, Lawrence E (Fed) on 8/29/17.
// Copyright © 2017 Bassham, Lawrence E (Fed). All rights reserved.
/*
NIST-developed software is provided by NIST as a public service. You may use, copy, and distribute copies of the software in any medium, provided that you keep intact this entire notice. You may improve, modify, and create derivative works of the software or any portion of the software, and you may copy and distribute such modifications or works. Modified works should carry a notice stating that you changed the software and should note the date and nature of any such change. Please explicitly acknowledge the National Institute of Standards and Technology as the source of the software.
NIST-developed software is expressly provided "AS IS." NIST MAKES NO WARRANTY OF ANY KIND, EXPRESS, IMPLIED, IN FACT, OR ARISING BY OPERATION OF LAW, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT, AND DATA ACCURACY. NIST NEITHER REPRESENTS NOR WARRANTS THAT THE OPERATION OF THE SOFTWARE WILL BE UNINTERRUPTED OR ERROR-FREE, OR THAT ANY DEFECTS WILL BE CORRECTED. NIST DOES NOT WARRANT OR MAKE ANY REPRESENTATIONS REGARDING THE USE OF THE SOFTWARE OR THE RESULTS THEREOF, INCLUDING BUT NOT LIMITED TO THE CORRECTNESS, ACCURACY, RELIABILITY, OR USEFULNESS OF THE SOFTWARE.
You are solely responsible for determining the appropriateness of using and distributing the software and you assume all risks associated with its use, including but not limited to the risks and costs of program errors, compliance with applicable laws, damage to or loss of data, programs or equipment, and the unavailability or interruption of operation. This software is not intended to be used in any situation where a failure could cause risk of injury or damage to property. The software developed by NIST employees is not subject to copyright protection within the United States.
*/
// SPDX-License-Identifier: Unknown
// Modified for PQClean by Sebastian Verschoor
//
#include <stddef.h>
#include <stdint.h>
#define NISTSEEDEXPANDER_SEED_LEN 32
#define RNG_SUCCESS ( 0)
#define RNG_BAD_MAXLEN (-1)
#define RNG_BAD_OUTBUF (-2)
#define RNG_BAD_REQ_LEN (-3)
typedef struct {
uint8_t buffer[16];
size_t buffer_pos;
size_t length_remaining;
uint8_t key[NISTSEEDEXPANDER_SEED_LEN];
uint8_t ctr[16];
} AES_XOF_struct;
int
seedexpander_init(AES_XOF_struct *ctx,
const uint8_t *seed,
const uint8_t *diversifier,
size_t maxlen);
int
seedexpander(AES_XOF_struct *ctx, uint8_t *x, size_t xlen);
#endif /* NISTSEEDEXPANDER_H */

View file

@ -0,0 +1,10 @@
// SPDX-License-Identifier: MIT
#ifndef RANDOMBYTES_H
#define RANDOMBYTES_H
#include <oqs/rand.h>
#define randombytes OQS_randombytes
#endif

View file

@ -0,0 +1,33 @@
// SPDX-License-Identifier: MIT
#ifndef SHA2_H
#define SHA2_H
#include <oqs/sha2.h>
#define sha256 OQS_SHA2_sha256
#define sha384 OQS_SHA2_sha384
#define sha512 OQS_SHA2_sha512
#define sha256ctx OQS_SHA2_sha256_ctx
#define sha256_inc_init OQS_SHA2_sha256_inc_init
#define sha256_inc_ctx_clone OQS_SHA2_sha256_inc_ctx_clone
#define sha256_inc_ctx_release OQS_SHA2_sha256_inc_ctx_release
#define sha256_inc_blocks OQS_SHA2_sha256_inc_blocks
#define sha256_inc_finalize OQS_SHA2_sha256_inc_finalize
#define sha384ctx OQS_SHA2_sha384_ctx
#define sha384_inc_init OQS_SHA2_sha384_inc_init
#define sha384_inc_ctx_clone OQS_SHA2_sha384_inc_ctx_clone
#define sha384_inc_ctx_release OQS_SHA2_sha384_inc_ctx_release
#define sha384_inc_blocks OQS_SHA2_sha384_inc_blocks
#define sha384_inc_finalize OQS_SHA2_sha384_inc_finalize
#define sha512ctx OQS_SHA2_sha512_ctx
#define sha512_inc_init OQS_SHA2_sha512_inc_init
#define sha512_inc_ctx_clone OQS_SHA2_sha512_inc_ctx_clone
#define sha512_inc_ctx_release OQS_SHA2_sha512_inc_ctx_release
#define sha512_inc_blocks OQS_SHA2_sha512_inc_blocks
#define sha512_inc_finalize OQS_SHA2_sha512_inc_finalize
#endif

View file

@ -0,0 +1,73 @@
/**
* \file rand.h
* \brief Random number generator.
*
* SPDX-License-Identifier: MIT
*/
#ifndef OQS_RANDOM_H
#define OQS_RANDOM_H
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include <oqs/common.h>
#if defined(__cplusplus)
extern "C" {
#endif
/** Algorithm identifier for system PRNG. */
#define OQS_RAND_alg_system "system"
/** Algorithm identifier for NIST deterministic RNG for KATs. */
#define OQS_RAND_alg_nist_kat "NIST-KAT"
/** Algorithm identifier for using OpenSSL's PRNG. */
#define OQS_RAND_alg_openssl "OpenSSL"
/**
* Switches OQS_randombytes to use the specified algorithm.
*
* @param[in] algorithm The name of the algorithm to use.
* @return OQS_SUCCESS if `algorithm` is a supported algorithm name, OQS_ERROR otherwise.
*/
OQS_API OQS_STATUS OQS_randombytes_switch_algorithm(const char *algorithm);
/**
* Switches OQS_randombytes to use the given function.
*
* This allows additional custom RNGs besides the provided ones. The provided RNG
* function must have the same signature as `OQS_randombytes`.
*
* @param[in] algorithm_ptr Pointer to the RNG function to use.
*/
OQS_API void OQS_randombytes_custom_algorithm(void (*algorithm_ptr)(uint8_t *, size_t));
/**
* Fills the given memory with the requested number of (pseudo)random bytes.
*
* This implementation uses whichever algorithm has been selected by
* OQS_randombytes_switch_algorithm. The default is OQS_randombytes_system, which
* reads bytes directly from `/dev/urandom`.
*
* The caller is responsible for providing a buffer allocated with sufficient room.
*
* @param[out] random_array Pointer to the memory to fill with (pseudo)random bytes
* @param[in] bytes_to_read The number of random bytes to read into memory
*/
OQS_API void OQS_randombytes(uint8_t *random_array, size_t bytes_to_read);
/**
* Initializes the NIST DRBG with a given seed and with 256-bit security.
*
* @param[in] entropy_input The seed; must be exactly 48 bytes
* @param[in] personalization_string An optional personalization string;
* may be NULL; if not NULL, must be at least 48 bytes long
*/
OQS_API void OQS_randombytes_nist_kat_init_256bit(const uint8_t *entropy_input, const uint8_t *personalization_string);
#if defined(__cplusplus)
} // extern "C"
#endif
#endif // OQS_RANDOM_H

View file

@ -0,0 +1,257 @@
/**
* \file sha2.h
* \brief SHA2 functions; not part of the OQS public API
*
* Contains the API and documentation for SHA2 digest implementation
*
* <b>Note this is not part of the OQS public API: implementations within liboqs can use these
* functions, but external consumers of liboqs should not use these functions.</b>
*
* \author Douglas Stebila
*
* SPDX-License-Identifier: MIT
*/
#ifndef OQS_SHA2_H
#define OQS_SHA2_H
#include <stddef.h>
#include <stdint.h>
#if defined(__cplusplus)
extern "C" {
#endif
/** Data structure for the state of the SHA-224 incremental hashing API. */
typedef struct {
/** Internal state */
void *ctx;
} OQS_SHA2_sha224_ctx;
/**
* \brief Process a message with SHA-256 and return the hash code in the output byte array.
*
* \warning The output array must be at least 32 bytes in length.
*
* \param output The output byte array
* \param input The message input byte array
* \param inplen The number of message bytes to process
*/
void OQS_SHA2_sha256(uint8_t *output, const uint8_t *input, size_t inplen);
/** Data structure for the state of the SHA-256 incremental hashing API. */
typedef struct {
/** Internal state */
void *ctx;
} OQS_SHA2_sha256_ctx;
/**
* \brief Allocate and initialize the state for the SHA-256 incremental hashing API.
*
* \warning The state must be released by OQS_SHA2_sha256_inc_finalize
* or OQS_SHA2_sha256_inc_ctx_release.
*
* \param state Pointer to the state
*/
void OQS_SHA2_sha256_inc_init(OQS_SHA2_sha256_ctx *state);
/**
* \brief Duplicate state for the SHA-256 incremental hashing API.
*
* \warning dest must be allocated by the caller. Caller is responsible
* for releasing dest by calling either OQS_SHA2_sha256_inc_finalize or
* OQS_SHA2_sha256_inc_ctx_release.
*
* \param dest The function state to copy into; must be initialized
* \param src The function state to copy; must be initialized
*/
void OQS_SHA2_sha256_inc_ctx_clone(OQS_SHA2_sha256_ctx *dest, const OQS_SHA2_sha256_ctx *src);
/**
* \brief Process blocks with SHA-256 and update the state.
*
* \warning The state must be initialized by OQS_SHA2_sha256_inc_init or OQS_SHA2_sha256_inc_ctx_clone.
*
* \param state The state to update
* \param in Message input byte array
* \param inblocks The number of 64-byte blocks of message bytes to process
*/
void OQS_SHA2_sha256_inc_blocks(OQS_SHA2_sha256_ctx *state, const uint8_t *in, size_t inblocks);
/**
* \brief Process more message bytes with SHA-256 and return the hash code in the output byte array.
*
* \warning The output array must be at least 32 bytes in length. The state is
* deallocated by this function and can not be used again after calling
* this function without calling OQS_SHA2_sha256_inc_init again.
*
* \param out The output byte array
* \param state The state
* \param in Additional message input byte array
* \param inlen The number of additional message bytes to process
*/
void OQS_SHA2_sha256_inc_finalize(uint8_t *out, OQS_SHA2_sha256_ctx *state, const uint8_t *in, size_t inlen);
/**
* \brief Destroy state.
*
* \warning The state is deallocated by this function and can not be used again after calling
* this function without calling OQS_SHA2_sha256_inc_init again.
*
* \param state The state
*/
void OQS_SHA2_sha256_inc_ctx_release(OQS_SHA2_sha256_ctx *state);
/**
* \brief Process a message with SHA-384 and return the hash code in the output byte array.
*
* \warning The output array must be at least 48 bytes in length.
*
* \param output The output byte array
* \param input The message input byte array
* \param inplen The number of message bytes to process
*/
void OQS_SHA2_sha384(uint8_t *output, const uint8_t *input, size_t inplen);
/** Data structure for the state of the SHA-384 incremental hashing API. */
typedef struct {
/** Internal state. */
void *ctx;
} OQS_SHA2_sha384_ctx;
/**
* \brief Allocate and initialize the state for the SHA-384 incremental hashing API.
*
* \warning The state must be released by OQS_SHA2_sha384_inc_finalize
* or OQS_SHA2_sha384_inc_ctx_release.
*
* \param state Pointer to the state
*/
void OQS_SHA2_sha384_inc_init(OQS_SHA2_sha384_ctx *state);
/**
* \brief Duplicate state for the SHA-384 incremental hashing API.
*
* \warning dest must be allocated by the caller. Caller is responsible
* for releasing dest by calling either OQS_SHA2_sha384_inc_finalize or
* OQS_SHA2_sha384_inc_ctx_release.
*
* \param dest The function state to copy into; must be initialized
* \param src The function state to copy; must be initialized
*/
void OQS_SHA2_sha384_inc_ctx_clone(OQS_SHA2_sha384_ctx *dest, const OQS_SHA2_sha384_ctx *src);
/**
* \brief Process blocks with SHA-384 and update the state.
*
* \warning The state must be initialized by OQS_SHA2_sha384_inc_init or OQS_SHA2_sha384_inc_ctx_clone.
*
* \param state The state to update
* \param in Message input byte array
* \param inblocks The number of 128-byte blocks of message bytes to process
*/
void OQS_SHA2_sha384_inc_blocks(OQS_SHA2_sha384_ctx *state, const uint8_t *in, size_t inblocks);
/**
* \brief Process more message bytes with SHA-384 and return the hash code in the output byte array.
*
* \warning The output array must be at least 48 bytes in length. The state is
* deallocated by this function and can not be used again after calling
* this function without calling OQS_SHA2_sha384_inc_init again.
*
* \param out The output byte array
* \param state The state
* \param in Additional message input byte array
* \param inlen The number of additional message bytes to process
*/
void OQS_SHA2_sha384_inc_finalize(uint8_t *out, OQS_SHA2_sha384_ctx *state, const uint8_t *in, size_t inlen);
/**
* \brief Destroy state.
*
* \warning The state is deallocated by this function and can not be used again after calling
* this function without calling OQS_SHA2_sha384_inc_init again.
*
* \param state The state
*/
void OQS_SHA2_sha384_inc_ctx_release(OQS_SHA2_sha384_ctx *state);
/**
* \brief Process a message with SHA-512 and return the hash code in the output byte array.
*
* \warning The output array must be at least 64 bytes in length.
*
* \param output The output byte array
* \param input The message input byte array
* \param inplen The number of message bytes to process
*/
void OQS_SHA2_sha512(uint8_t *output, const uint8_t *input, size_t inplen);
/** Data structure for the state of the SHA-512 incremental hashing API. */
typedef struct {
/** Internal state. */
void *ctx;
} OQS_SHA2_sha512_ctx;
/**
* \brief Allocate and initialize the state for the SHA-512 incremental hashing API.
*
* \warning The state must be released by OQS_SHA2_sha512_inc_finalize
* or OQS_SHA2_sha512_inc_ctx_release.
*
* \param state Pointer to the state
*/
void OQS_SHA2_sha512_inc_init(OQS_SHA2_sha512_ctx *state);
/**
* \brief Duplicate state for the SHA-512 incremental hashing API.
*
* \warning dest must be allocated by the caller. Caller is responsible
* for releasing dest by calling either OQS_SHA2_sha512_inc_finalize or
* OQS_SHA2_sha512_inc_ctx_release.
*
* \param dest The function state to copy into; must be initialized
* \param src The function state to copy; must be initialized
*/
void OQS_SHA2_sha512_inc_ctx_clone(OQS_SHA2_sha512_ctx *dest, const OQS_SHA2_sha512_ctx *src);
/**
* \brief Process blocks with SHA-512 and update the state.
*
* \warning The state must be initialized by OQS_SHA2_sha512_inc_init or OQS_SHA2_sha512_inc_ctx_clone.
*
* \param state The state to update
* \param in Message input byte array
* \param inblocks The number of 128-byte blocks of message bytes to process
*/
void OQS_SHA2_sha512_inc_blocks(OQS_SHA2_sha512_ctx *state, const uint8_t *in, size_t inblocks);
/**
* \brief Process more message bytes with SHA-512 and return the hash code in the output byte array.
*
* \warning The output array must be at least 64 bytes in length. The state is
* deallocated by this function and can not be used again after calling
* this function without calling OQS_SHA2_sha512_inc_init again.
*
* \param out The output byte array
* \param state The state
* \param in Additional message input byte array
* \param inlen The number of additional message bytes to process
*/
void OQS_SHA2_sha512_inc_finalize(uint8_t *out, OQS_SHA2_sha512_ctx *state, const uint8_t *in, size_t inlen);
/**
* \brief Destroy state.
*
* \warning The state is deallocated by this function and can not be used again after calling
* this function without calling OQS_SHA2_sha512_inc_init again.
*
* \param state The state
*/
void OQS_SHA2_sha512_inc_ctx_release(OQS_SHA2_sha512_ctx *state);
#if defined(__cplusplus)
} // extern "C"
#endif
#endif // OQS_SHA2_H

View file

@ -0,0 +1,86 @@
/**
* \file sha2_local.h
* \brief Internal SHA2 functions that enable easy switching between native instructions
* and c implementations
*
* <b>Note this is not part of the OQS public API: implementations within liboqs can use these
* functions, but external consumers of liboqs should not use these functions.</b>
*
* \author Douglas Stebila
*
* SPDX-License-Identifier: MIT
*/
#ifndef OQS_SHA2_LOCAL_H
#define OQS_SHA2_LOCAL_H
#include <stddef.h>
#include <stdint.h>
#if defined(__cplusplus)
extern "C" {
#endif
typedef struct {
uint8_t *ctx;
} sha224ctx;
typedef struct {
uint8_t *ctx;
} sha256ctx;
typedef struct {
uint8_t *ctx;
} sha384ctx;
typedef struct {
uint8_t *ctx;
} sha512ctx;
void oqs_sha2_sha224_inc_init_c(sha224ctx *state);
void oqs_sha2_sha224_inc_ctx_clone_c(sha224ctx *dest, const sha224ctx *src);
void oqs_sha2_sha224_inc_blocks_c(sha224ctx *state, const uint8_t *in, size_t inblocks);
void oqs_sha2_sha224_inc_finalize_c(uint8_t *out, sha224ctx *state, const uint8_t *in, size_t inlen);
void oqs_sha2_sha224_inc_ctx_release_c(sha224ctx *state);
void oqs_sha2_sha256_inc_init_c(sha256ctx *state);
void oqs_sha2_sha256_inc_ctx_clone_c(sha256ctx *dest, const sha256ctx *src);
void oqs_sha2_sha256_inc_blocks_c(sha256ctx *state, const uint8_t *in, size_t inblocks);
void oqs_sha2_sha256_inc_finalize_c(uint8_t *out, sha256ctx *state, const uint8_t *in, size_t inlen);
void oqs_sha2_sha256_inc_ctx_release_c(sha256ctx *state);
void oqs_sha2_sha384(uint8_t *output, const uint8_t *input, size_t inplen);
void oqs_sha2_sha384_inc_init_c(sha384ctx *state);
void oqs_sha2_sha384_inc_ctx_clone_c(sha384ctx *dest, const sha384ctx *src);
void oqs_sha2_sha384_inc_blocks_c(sha384ctx *state, const uint8_t *in, size_t inblocks);
void oqs_sha2_sha384_inc_finalize_c(uint8_t *out, sha384ctx *state, const uint8_t *in, size_t inlen);
void oqs_sha2_sha384_inc_ctx_release_c(sha384ctx *state);
void oqs_sha2_sha512_inc_init_c(sha512ctx *state);
void oqs_sha2_sha512_inc_ctx_clone_c(sha512ctx *dest, const sha512ctx *src);
void oqs_sha2_sha512_inc_blocks_c(sha512ctx *state, const uint8_t *in, size_t inblocks);
void oqs_sha2_sha512_inc_finalize_c(uint8_t *out, sha512ctx *state, const uint8_t *in, size_t inlen);
void oqs_sha2_sha512_inc_ctx_release_c(sha512ctx *state);
// ARMv8 Crypto Extension functions
void oqs_sha2_sha224_inc_blocks_armv8(sha224ctx *state, const uint8_t *in, size_t inblocks);
void oqs_sha2_sha224_armv8(uint8_t *out, const uint8_t *in, size_t inlen);
void oqs_sha2_sha256_inc_blocks_armv8(sha256ctx *state, const uint8_t *in, size_t inblocks);
void oqs_sha2_sha256_armv8(uint8_t *out, const uint8_t *in, size_t inlen);
void oqs_sha2_sha384_inc_init_armv8(sha384ctx *state);
void oqs_sha2_sha384_inc_ctx_clone_armv8(sha384ctx *dest, const sha384ctx *src);
void oqs_sha2_sha384_inc_blocks_armv8(sha384ctx *state, const uint8_t *in, size_t inblocks);
void oqs_sha2_sha384_inc_finalize_armv8(uint8_t *out, sha384ctx *state, const uint8_t *in, size_t inlen);
void oqs_sha2_sha384_inc_ctx_release_armv8(sha384ctx *state);
void oqs_sha2_sha224_c(uint8_t *out, const uint8_t *in, size_t inlen);
void oqs_sha2_sha256_c(uint8_t *out, const uint8_t *in, size_t inlen);
void oqs_sha2_sha384_c(uint8_t *out, const uint8_t *in, size_t inlen);
void oqs_sha2_sha512_c(uint8_t *out, const uint8_t *in, size_t inlen);
#if defined(__cplusplus)
} // extern "C"
#endif
#endif // OQS_SHA2_LOCAL_H

View file

@ -0,0 +1,429 @@
/**
* \file sha3.h
* \brief SHA3 and SHAKE functions; not part of the OQS public API
*
* Contains the API and documentation for SHA3 digest and SHAKE implementations.
*
* <b>Note this is not part of the OQS public API: implementations within liboqs can use these
* functions, but external consumers of liboqs should not use these functions.</b>
*
* \author John Underhill, Douglas Stebila
*
* SPDX-License-Identifier: MIT
*/
#ifndef OQS_SHA3_H
#define OQS_SHA3_H
#include <stddef.h>
#include <stdint.h>
#if defined(__cplusplus)
extern "C" {
#endif
/* SHA3 */
/** The SHA-256 byte absorption rate */
#define OQS_SHA3_SHA3_256_RATE 136
/**
* \brief Process a message with SHA3-256 and return the digest in the output byte array.
*
* \warning The output array must be at least 32 bytes in length.
*
* \param output The output byte array
* \param input The message input byte array
* \param inplen The number of message bytes to process
*/
void OQS_SHA3_sha3_256(uint8_t *output, const uint8_t *input, size_t inplen);
/** Data structure for the state of the incremental SHA3-256 API. */
typedef struct {
/** Internal state. */
void *ctx;
} OQS_SHA3_sha3_256_inc_ctx;
/**
* \brief Initialize the state for the incremental SHA3-256 API.
*
* \warning Caller is responsible for releasing state by calling
* OQS_SHA3_sha3_256_inc_ctx_release.
*
* \param state The function state to be allocated and initialized.
*/
void OQS_SHA3_sha3_256_inc_init(OQS_SHA3_sha3_256_inc_ctx *state);
/**
* \brief The SHA3-256 absorb function.
* Absorb an input into the state.
*
* \param state The function state; must be initialized
* \param input The input array
* \param inlen The length of the input
*/
void OQS_SHA3_sha3_256_inc_absorb(OQS_SHA3_sha3_256_inc_ctx *state, const uint8_t *input, size_t inlen);
/**
* \brief The SHA3-256 finalize-and-squeeze function.
* Finalizes the state and squeezes a 32 byte digest.
*
* \warning Output array must be at least 32 bytes.
* State cannot be used after this without calling OQS_SHA3_sha3_256_inc_reset.
*
* \param output The output byte array
* \param state The function state; must be initialized
*/
void OQS_SHA3_sha3_256_inc_finalize(uint8_t *output, OQS_SHA3_sha3_256_inc_ctx *state);
/**
* \brief Release the state for the SHA3-256 incremental API.
*
* \param state The function state; must be initialized
*/
void OQS_SHA3_sha3_256_inc_ctx_release(OQS_SHA3_sha3_256_inc_ctx *state);
/**
* \brief Resets the state for the SHA3-256 incremental API.
* Alternative to freeing and reinitializing the state.
*
* \param state The function state; must be initialized
*/
void OQS_SHA3_sha3_256_inc_ctx_reset(OQS_SHA3_sha3_256_inc_ctx *state);
/**
* \brief Clone the state for the SHA3-256 incremental API.
*
* \param dest The function state to copy into; must be initialized
* \param src The function state to copy; must be initialized
*/
void OQS_SHA3_sha3_256_inc_ctx_clone(OQS_SHA3_sha3_256_inc_ctx *dest, const OQS_SHA3_sha3_256_inc_ctx *src);
/** The SHA-384 byte absorption rate */
#define OQS_SHA3_SHA3_384_RATE 104
/**
* \brief Process a message with SHA3-384 and return the digest in the output byte array.
*
* \warning The output array must be at least 48 bytes in length.
*
* \param output The output byte array
* \param input The message input byte array
* \param inplen The number of message bytes to process
*/
void OQS_SHA3_sha3_384(uint8_t *output, const uint8_t *input, size_t inplen);
/** Data structure for the state of the incremental SHA3-384 API. */
typedef struct {
/** Internal state. */
void *ctx;
} OQS_SHA3_sha3_384_inc_ctx;
/**
* \brief Initialize the state for the incremental SHA3-384 API.
*
* \warning Caller is responsible for releasing state by calling
* OQS_SHA3_sha3_384_inc_ctx_release.
*
* \param state The function state to be allocated and initialized.
*/
void OQS_SHA3_sha3_384_inc_init(OQS_SHA3_sha3_384_inc_ctx *state);
/**
* \brief The SHA3-384 absorb function.
* Absorb an input into the state.
*
* \param state The function state; must be initialized
* \param input The input array
* \param inlen The length of the input
*/
void OQS_SHA3_sha3_384_inc_absorb(OQS_SHA3_sha3_384_inc_ctx *state, const uint8_t *input, size_t inlen);
/**
* \brief The SHA3-384 finalize-and-squeeze function.
* Finalizes the state and squeezes a 48 byte digest.
*
* \warning Output array must be at least 48 bytes.
* State cannot be used after this without calling OQS_SHA3_sha3_384_inc_reset.
*
* \param output The output byte array
* \param state The function state; must be initialized
*/
void OQS_SHA3_sha3_384_inc_finalize(uint8_t *output, OQS_SHA3_sha3_384_inc_ctx *state);
/**
* \brief Release the state for the SHA3-384 incremental API.
*
* \param state The function state; must be initialized
*/
void OQS_SHA3_sha3_384_inc_ctx_release(OQS_SHA3_sha3_384_inc_ctx *state);
/**
* \brief Resets the state for the SHA3-384 incremental API.
* Alternative to freeing and reinitializing the state.
*
* \param state The function state; must be initialized
*/
void OQS_SHA3_sha3_384_inc_ctx_reset(OQS_SHA3_sha3_384_inc_ctx *state);
/**
* \brief Clone the state for the SHA3-384 incremental API.
*
* \param dest The function state to copy into; must be initialized
* \param src The function state to copy; must be initialized
*/
void OQS_SHA3_sha3_384_inc_ctx_clone(OQS_SHA3_sha3_384_inc_ctx *dest, const OQS_SHA3_sha3_384_inc_ctx *src);
/** The SHA-512 byte absorption rate */
#define OQS_SHA3_SHA3_512_RATE 72
/**
* \brief Process a message with SHA3-512 and return the digest in the output byte array.
*
* \warning The output array must be at least 64 bytes in length.
*
* \param output The output byte array
* \param input The message input byte array
* \param inplen The number of message bytes to process
*/
void OQS_SHA3_sha3_512(uint8_t *output, const uint8_t *input, size_t inplen);
/** Data structure for the state of the incremental SHA3-512 API. */
typedef struct {
/** Internal state. */
void *ctx;
} OQS_SHA3_sha3_512_inc_ctx;
/**
* \brief Initialize the state for the incremental SHA3-512 API.
*
* \warning Caller is responsible for releasing state by calling
* OQS_SHA3_sha3_512_inc_ctx_release.
*
* \param state The function state to be allocated and initialized.
*/
void OQS_SHA3_sha3_512_inc_init(OQS_SHA3_sha3_512_inc_ctx *state);
/**
* \brief The SHA3-512 absorb function.
* Absorb an input into the state.
*
* \param state The function state; must be initialized
* \param input The input array
* \param inlen The length of the input
*/
void OQS_SHA3_sha3_512_inc_absorb(OQS_SHA3_sha3_512_inc_ctx *state, const uint8_t *input, size_t inlen);
/**
* \brief The SHA3-512 finalize-and-squeeze function.
* Finalizes the state and squeezes a 64 byte digest.
*
* \warning Output array must be at least 64 bytes.
* State cannot be used after this without calling OQS_SHA3_sha3_512_inc_reset.
*
* \param output The output byte array
* \param state The function state; must be initialized
*/
void OQS_SHA3_sha3_512_inc_finalize(uint8_t *output, OQS_SHA3_sha3_512_inc_ctx *state);
/**
* \brief Release the state for the SHA3-512 incremental API.
*
* \param state The function state; must be initialized
*/
void OQS_SHA3_sha3_512_inc_ctx_release(OQS_SHA3_sha3_512_inc_ctx *state);
/**
* \brief Resets the state for the SHA3-512 incremental API.
* Alternative to freeing and reinitializing the state.
*
* \param state The function state; must be initialized
*/
void OQS_SHA3_sha3_512_inc_ctx_reset(OQS_SHA3_sha3_512_inc_ctx *state);
/**
* \brief Clone the state for the SHA3-512 incremental API.
*
* \param dest The function state to copy into; must be initialized
* \param src The function state to copy; must be initialized
*/
void OQS_SHA3_sha3_512_inc_ctx_clone(OQS_SHA3_sha3_512_inc_ctx *dest, const OQS_SHA3_sha3_512_inc_ctx *src);
/* SHAKE */
/** The SHAKE-128 byte absorption rate */
#define OQS_SHA3_SHAKE128_RATE 168
/**
* \brief Seed a SHAKE-128 instance, and generate an array of pseudo-random bytes.
*
* \warning The output array length must not be zero.
*
* \param output The output byte array
* \param outlen The number of output bytes to generate
* \param input The input seed byte array
* \param inplen The number of seed bytes to process
*/
void OQS_SHA3_shake128(uint8_t *output, size_t outlen, const uint8_t *input, size_t inplen);
/** Data structure for the state of the incremental SHAKE-128 API. */
typedef struct {
/** Internal state. */
void *ctx;
} OQS_SHA3_shake128_inc_ctx;
/**
* \brief Initialize the state for the incremental SHAKE-128 API.
*
* \warning Caller is responsible for releasing state by calling
* OQS_SHA3_shake128_inc_ctx_release.
*
* \param state The function state to be initialized; must be allocated
*/
void OQS_SHA3_shake128_inc_init(OQS_SHA3_shake128_inc_ctx *state);
/**
* \brief The SHAKE-128 absorb function.
* Absorb an input into the state.
*
* \warning State must be initialized.
*
* \param state The function state; must be initialized
* \param input input buffer
* \param inlen length of input buffer
*/
void OQS_SHA3_shake128_inc_absorb(OQS_SHA3_shake128_inc_ctx *state, const uint8_t *input, size_t inlen);
/**
* \brief The SHAKE-128 finalize function.
* Prepares the state for squeezing.
*
* \param state The function state; must be initialized
*/
void OQS_SHA3_shake128_inc_finalize(OQS_SHA3_shake128_inc_ctx *state);
/**
* \brief The SHAKE-128 squeeze function.
* Extracts to an output byte array.
*
* \param output output buffer
* \param outlen bytes of outbut buffer
* \param state The function state; must be initialized and finalized
*/
void OQS_SHA3_shake128_inc_squeeze(uint8_t *output, size_t outlen, OQS_SHA3_shake128_inc_ctx *state);
/**
* \brief Frees the state for the incremental SHAKE-128 API.
*
* \param state The state to free
*/
void OQS_SHA3_shake128_inc_ctx_release(OQS_SHA3_shake128_inc_ctx *state);
/**
* \brief Copies the state for the SHAKE-128 incremental API.
*
* \warning Caller is responsible for releasing dest by calling
* OQS_SHA3_shake128_inc_ctx_release.
*
* \param dest The function state to copy into; must be initialized
* \param src The function state to copy; must be initialized
*/
void OQS_SHA3_shake128_inc_ctx_clone(OQS_SHA3_shake128_inc_ctx *dest, const OQS_SHA3_shake128_inc_ctx *src);
/**
* \brief Resets the state for the SHAKE-128 incremental API. Allows a context
* to be re-used without free and init calls.
*
* \param state The function state; must be initialized
*/
void OQS_SHA3_shake128_inc_ctx_reset(OQS_SHA3_shake128_inc_ctx *state);
/** The SHAKE-256 byte absorption rate */
#define OQS_SHA3_SHAKE256_RATE 136
/**
* \brief Seed a SHAKE-256 instance, and generate an array of pseudo-random bytes.
*
* \warning The output array length must not be zero.
*
* \param output The output byte array
* \param outlen The number of output bytes to generate
* \param input The input seed byte array
* \param inplen The number of seed bytes to process
*/
void OQS_SHA3_shake256(uint8_t *output, size_t outlen, const uint8_t *input, size_t inplen);
/** Data structure for the state of the incremental SHAKE-256 API. */
typedef struct {
/** Internal state. */
void *ctx;
} OQS_SHA3_shake256_inc_ctx;
/**
* \brief Initialize the state for the incremental SHAKE-256 API.
*
* \param state The function state to be initialized; must be allocated
*/
void OQS_SHA3_shake256_inc_init(OQS_SHA3_shake256_inc_ctx *state);
/**
* \brief The SHAKE-256 absorb function.
* Absorb an input message array directly into the state.
*
* \warning State must be initialized by the caller.
*
* \param state The function state; must be initialized
* \param input input buffer
* \param inlen length of input buffer
*/
void OQS_SHA3_shake256_inc_absorb(OQS_SHA3_shake256_inc_ctx *state, const uint8_t *input, size_t inlen);
/**
* \brief The SHAKE-256 finalize function.
*
* \param state The function state; must be initialized
*/
void OQS_SHA3_shake256_inc_finalize(OQS_SHA3_shake256_inc_ctx *state);
/**
* \brief The SHAKE-256 squeeze function.
* Extracts to an output byte array.
*
* \param output output buffer
* \param outlen bytes of outbut buffer
* \param state The function state; must be initialized
*/
void OQS_SHA3_shake256_inc_squeeze(uint8_t *output, size_t outlen, OQS_SHA3_shake256_inc_ctx *state);
/**
* \brief Frees the state for the incremental SHAKE-256 API.
*
* \param state The state to free
*/
void OQS_SHA3_shake256_inc_ctx_release(OQS_SHA3_shake256_inc_ctx *state);
/**
* \brief Copies the state for the incremental SHAKE-256 API.
*
* \warning dest must be allocated. dest must be freed by calling
* OQS_SHA3_shake256_inc_ctx_release.
*
* \param dest The state to copy into; must be initialized
* \param src The state to copy from; must be initialized
*/
void OQS_SHA3_shake256_inc_ctx_clone(OQS_SHA3_shake256_inc_ctx *dest, const OQS_SHA3_shake256_inc_ctx *src);
/**
* \brief Resets the state for the SHAKE-256 incremental API. Allows a context
* to be re-used without free and init calls.
*
* \param state The function state; must be initialized
*/
void OQS_SHA3_shake256_inc_ctx_reset(OQS_SHA3_shake256_inc_ctx *state);
#if defined(__cplusplus)
} // extern "C"
#endif
#endif // OQS_SHA3_H

View file

@ -0,0 +1,263 @@
/**
* \file shakex4.h
* \brief SHA3, SHAKE, and cSHAKE functions; not part of the OQS public API
*
* Contains the API and documentation for SHA3 digest and SHAKE implementations.
*
* <b>Note this is not part of the OQS public API: implementations within liboqs can use these
* functions, but external consumers of liboqs should not use these functions.</b>
*
* \author John Underhill, Douglas Stebila
*
* SPDX-License-Identifier: MIT
*/
#ifndef OQS_SHA3X4_H
#define OQS_SHA3X4_H
#include <stddef.h>
#include <stdint.h>
#if defined(__cplusplus)
extern "C" {
#endif
/**
* \brief Seed 4 parallel SHAKE-128 instances, and generate 4 arrays of pseudo-random bytes.
*
* \warning The output array length must not be zero.
*
* \param out0 The first output byte array
* \param out1 The second output byte array
* \param out2 The third output byte array
* \param out3 The fourth output byte array
* \param outlen The number of output bytes to generate in every output array
* \param in0 The first input seed byte array
* \param in1 The second input seed byte array
* \param in2 The third input seed byte array
* \param in3 The fourth input seed byte array
* \param inlen The number of seed bytes to process from every input array
*/
void OQS_SHA3_shake128_x4(
uint8_t *out0,
uint8_t *out1,
uint8_t *out2,
uint8_t *out3,
size_t outlen,
const uint8_t *in0,
const uint8_t *in1,
const uint8_t *in2,
const uint8_t *in3,
size_t inlen);
/** Data structure for the state of the four-way parallel incremental SHAKE-128 API. */
typedef struct {
/** Internal state. */
void *ctx;
} OQS_SHA3_shake128_x4_inc_ctx;
/**
* \brief Initialize the state for four-way parallel incremental SHAKE-128 API.
*
* \param state The function state to be initialized; must be allocated
*/
void OQS_SHA3_shake128_x4_inc_init(OQS_SHA3_shake128_x4_inc_ctx *state);
/**
* \brief Four-way parallel SHAKE-128 absorb function.
* Absorb four input messages of the same length into four parallel states.
*
* \warning State must be initialized by the caller.
*
* \param state The function state; must be initialized
* \param in0 The input to be absorbed into first instance
* \param in1 The input to be absorbed into first instance
* \param in2 The input to be absorbed into first instance
* \param in3 The input to be absorbed into first instance
* \param inlen The number of bytes to process from each input array
*/
void OQS_SHA3_shake128_x4_inc_absorb(
OQS_SHA3_shake128_x4_inc_ctx *state,
const uint8_t *in0,
const uint8_t *in1,
const uint8_t *in2,
const uint8_t *in3,
size_t inlen);
/**
* \brief Four-way parallel SHAKE-128 finalize function.
* Prepares the states for squeezing.
*
* \param state The function state; must be initialized
*/
void OQS_SHA3_shake128_x4_inc_finalize(OQS_SHA3_shake128_x4_inc_ctx *state);
/**
* \brief Four-way parallel SHAKE-128 squeeze function.
* Extracts from four parallel states into four output buffers
*
* \param out0 output buffer for the first instance
* \param out1 output buffer for the second instance
* \param out2 output buffer for the third instance
* \param out3 output buffer for the fourth instance
* \param outlen bytes of outbut buffer
* \param state The function state; must be initialized and finalized.
*/
void OQS_SHA3_shake128_x4_inc_squeeze(
uint8_t *out0,
uint8_t *out1,
uint8_t *out2,
uint8_t *out3,
size_t outlen,
OQS_SHA3_shake128_x4_inc_ctx *state);
/**
* \brief Frees the state for the four-way parallel incremental SHAKE-128 API.
*
* \param state The state to free
*/
void OQS_SHA3_shake128_x4_inc_ctx_release(OQS_SHA3_shake128_x4_inc_ctx *state);
/**
* \brief Copies the state for the four-way parallel incremental SHAKE-128 API.
*
* \param dest The state to copy into; must be initialized
* \param src The state to copy from; must be initialized
*/
void OQS_SHA3_shake128_x4_inc_ctx_clone(
OQS_SHA3_shake128_x4_inc_ctx *dest,
const OQS_SHA3_shake128_x4_inc_ctx *src);
/**
* \brief Resets the state for the four-way parallel incremental SHAKE-128 API.
*
* \param state The function state; must be initialized
*/
void OQS_SHA3_shake128_x4_inc_ctx_reset(OQS_SHA3_shake128_x4_inc_ctx *state);
/* SHAKE256 */
/**
* \brief Seed 4 parallel SHAKE-256 instances, and generate 4 arrays of pseudo-random bytes.
*
* Uses a vectorized (AVX2) implementation of SHAKE-256 if available.
*
* \warning The output array length must not be zero.
*
* \param out0 The first output byte array
* \param out1 The second output byte array
* \param out2 The third output byte array
* \param out3 The fourth output byte array
* \param outlen The number of output bytes to generate in every output array
* \param in0 The first input seed byte array
* \param in1 The second input seed byte array
* \param in2 The third input seed byte array
* \param in3 The fourth input seed byte array
* \param inlen The number of seed bytes to process from every input array
*/
void OQS_SHA3_shake256_x4(
uint8_t *out0,
uint8_t *out1,
uint8_t *out2,
uint8_t *out3,
size_t outlen,
const uint8_t *in0,
const uint8_t *in1,
const uint8_t *in2,
const uint8_t *in3,
size_t inlen);
/** Data structure for the state of the four-way parallel incremental SHAKE-256 API. */
typedef struct {
/** Internal state. */
void *ctx;
} OQS_SHA3_shake256_x4_inc_ctx;
/**
* \brief Initialize the state for four-way parallel incremental SHAKE-256 API.
*
* \param state The function state to be initialized; must be allocated
*/
void OQS_SHA3_shake256_x4_inc_init(OQS_SHA3_shake256_x4_inc_ctx *state);
/**
* \brief Four-way parallel SHAKE-256 absorb function.
* Absorb four input messages of the same length into four parallel states.
*
* \warning State must be initialized by the caller.
*
* \param state The function state; must be initialized
* \param in0 The input to be absorbed into first instance
* \param in1 The input to be absorbed into first instance
* \param in2 The input to be absorbed into first instance
* \param in3 The input to be absorbed into first instance
* \param inlen The number of bytes to process from each input array
*/
void OQS_SHA3_shake256_x4_inc_absorb(
OQS_SHA3_shake256_x4_inc_ctx *state,
const uint8_t *in0,
const uint8_t *in1,
const uint8_t *in2,
const uint8_t *in3,
size_t inlen);
/**
* \brief Four-way parallel SHAKE-256 finalize function.
*
* \param state The function state; must be initialized
*/
void OQS_SHA3_shake256_x4_inc_finalize(OQS_SHA3_shake256_x4_inc_ctx *state);
/**
* \brief Four-way parallel SHAKE-256 squeeze function.
* Extracts from four parallel states into four output buffers
*
* \param out0 output buffer for the first instance
* \param out1 output buffer for the second instance
* \param out2 output buffer for the third instance
* \param out3 output buffer for the fourth instance
* \param outlen bytes of outbut buffer
* \param state The function state; must be initialized and finalized
*/
void OQS_SHA3_shake256_x4_inc_squeeze(
uint8_t *out0,
uint8_t *out1,
uint8_t *out2,
uint8_t *out3,
size_t outlen,
OQS_SHA3_shake256_x4_inc_ctx *state);
/**
* \brief Frees the state for the four-way parallel incremental SHAKE-256 API.
*
* \param state The state to free
*/
void OQS_SHA3_shake256_x4_inc_ctx_release(OQS_SHA3_shake256_x4_inc_ctx *state);
/**
* \brief Copies the state for the four-way parallel incremental SHAKE-256 API.
*
* \warning dest must be allocated. dest must be freed by calling
* OQS_SHA3_shake256_inc_ctx_release.
*
* \param dest The state to copy into; must be initialized
* \param src The state to copy from; must be initialized
*/
void OQS_SHA3_shake256_x4_inc_ctx_clone(
OQS_SHA3_shake256_x4_inc_ctx *dest,
const OQS_SHA3_shake256_x4_inc_ctx *src);
/**
* \brief Resets the state for the four-way parallel incremental SHAKE-256 API.
* Allows a context to be re-used without free and init calls.
*
* \param state The function state; must be initialized
*/
void OQS_SHA3_shake256_x4_inc_ctx_reset(OQS_SHA3_shake256_x4_inc_ctx *state);
#if defined(__cplusplus)
} // extern "C"
#endif
#endif // OQS_SHA3_H

View file

@ -0,0 +1,82 @@
/* XKCP calls can be dispatched to platform-specific implementation at runtime.
*
* If this is a dist build we put a "_arch" suffix on each symbol in each xkcp_low
* library that we build. If it's not a dist build, we omit the suffix and only build
* one library. Hence we will either have a single "KeccakP1600_Initialize" or we will have
* one or more symbols of the form "KeccakP1600_Initialize_arch".
*
* This header file defines all of the symbols that might be available.
*
* SPDX-License-Identifier: MIT
*/
#ifndef OQS_SHA3_XKCP_DISPATCH_H
#define OQS_SHA3_XKCP_DISPATCH_H
typedef void KeccakInitFn(void *);
extern KeccakInitFn \
KeccakP1600_Initialize, \
KeccakP1600_Initialize_plain64, \
KeccakP1600_Initialize_avx2;
typedef void KeccakAddByteFn(void *, const uint8_t, unsigned int);
extern KeccakAddByteFn \
KeccakP1600_AddByte, \
KeccakP1600_AddByte_plain64, \
KeccakP1600_AddByte_avx2;
typedef void KeccakAddBytesFn(void *, const uint8_t *, unsigned int, unsigned int);
extern KeccakAddBytesFn \
KeccakP1600_AddBytes, \
KeccakP1600_AddBytes_plain64, \
KeccakP1600_AddBytes_avx2;
typedef void KeccakPermuteFn(void *);
extern KeccakPermuteFn \
KeccakP1600_Permute_24rounds, \
KeccakP1600_Permute_24rounds_plain64, \
KeccakP1600_Permute_24rounds_avx2;
typedef void KeccakExtractBytesFn(const void *, uint8_t *, unsigned int, unsigned int);
extern KeccakExtractBytesFn \
KeccakP1600_ExtractBytes, \
KeccakP1600_ExtractBytes_plain64, \
KeccakP1600_ExtractBytes_avx2;
typedef size_t KeccakFastLoopAbsorbFn(void *, unsigned int, const uint8_t *, size_t);
extern KeccakFastLoopAbsorbFn \
KeccakF1600_FastLoop_Absorb, \
KeccakF1600_FastLoop_Absorb_plain64, \
KeccakF1600_FastLoop_Absorb_avx2;
typedef void KeccakX4InitFn(void *);
extern KeccakX4InitFn \
KeccakP1600times4_InitializeAll, \
KeccakP1600times4_InitializeAll_serial, \
KeccakP1600times4_InitializeAll_avx2;
typedef void KeccakX4AddByteFn(void *, unsigned int, unsigned char, unsigned int);
extern KeccakX4AddByteFn \
KeccakP1600times4_AddByte, \
KeccakP1600times4_AddByte_serial, \
KeccakP1600times4_AddByte_avx2;
typedef void KeccakX4AddBytesFn(void *, unsigned int, const unsigned char *, unsigned int, unsigned int);
extern KeccakX4AddBytesFn \
KeccakP1600times4_AddBytes, \
KeccakP1600times4_AddBytes_serial, \
KeccakP1600times4_AddBytes_avx2;
typedef void KeccakX4PermuteFn(void *);
extern KeccakX4PermuteFn \
KeccakP1600times4_PermuteAll_24rounds, \
KeccakP1600times4_PermuteAll_24rounds_serial, \
KeccakP1600times4_PermuteAll_24rounds_avx2;
typedef void KeccakX4ExtractBytesFn(const void *, unsigned int, unsigned char *, unsigned int, unsigned int);
extern KeccakX4ExtractBytesFn \
KeccakP1600times4_ExtractBytes, \
KeccakP1600times4_ExtractBytes_serial, \
KeccakP1600times4_ExtractBytes_avx2;
#endif // OQS_SHA3_XKCP_DISPATCH_H

View file

@ -0,0 +1,754 @@
/*
The eXtended Keccak Code Package (XKCP)
https://github.com/XKCP/XKCP
The Keccak-p permutations, designed by Guido Bertoni, Joan Daemen, Michaël Peeters and Gilles Van Assche.
Implementation by Gilles Van Assche and Ronny Van Keer, hereby denoted as "the implementer".
For more information, feedback or questions, please refer to the Keccak Team website:
https://keccak.team/
To the extent possible under law, the implementer has waived all copyright
and related or neighboring rights to the source code in this file.
http://creativecommons.org/publicdomain/zero/1.0/
*/
#define declareABCDE \
uint64_t Aba, Abe, Abi, Abo, Abu; \
uint64_t Aga, Age, Agi, Ago, Agu; \
uint64_t Aka, Ake, Aki, Ako, Aku; \
uint64_t Ama, Ame, Ami, Amo, Amu; \
uint64_t Asa, Ase, Asi, Aso, Asu; \
uint64_t Bba, Bbe, Bbi, Bbo, Bbu; \
uint64_t Bga, Bge, Bgi, Bgo, Bgu; \
uint64_t Bka, Bke, Bki, Bko, Bku; \
uint64_t Bma, Bme, Bmi, Bmo, Bmu; \
uint64_t Bsa, Bse, Bsi, Bso, Bsu; \
uint64_t Ca, Ce, Ci, Co, Cu; \
uint64_t Da, De, Di, Do, Du; \
uint64_t Eba, Ebe, Ebi, Ebo, Ebu; \
uint64_t Ega, Ege, Egi, Ego, Egu; \
uint64_t Eka, Eke, Eki, Eko, Eku; \
uint64_t Ema, Eme, Emi, Emo, Emu; \
uint64_t Esa, Ese, Esi, Eso, Esu; \
#define prepareTheta \
Ca = Aba^Aga^Aka^Ama^Asa; \
Ce = Abe^Age^Ake^Ame^Ase; \
Ci = Abi^Agi^Aki^Ami^Asi; \
Co = Abo^Ago^Ako^Amo^Aso; \
Cu = Abu^Agu^Aku^Amu^Asu; \
#ifdef UseBebigokimisa
/* --- Code for round, with prepare-theta (lane complementing pattern 'bebigokimisa') */
/* --- 64-bit lanes mapped to 64-bit words */
#define thetaRhoPiChiIotaPrepareTheta(i, A, E) \
Da = Cu^ROL64(Ce, 1); \
De = Ca^ROL64(Ci, 1); \
Di = Ce^ROL64(Co, 1); \
Do = Ci^ROL64(Cu, 1); \
Du = Co^ROL64(Ca, 1); \
\
A##ba ^= Da; \
Bba = A##ba; \
A##ge ^= De; \
Bbe = ROL64(A##ge, 44); \
A##ki ^= Di; \
Bbi = ROL64(A##ki, 43); \
A##mo ^= Do; \
Bbo = ROL64(A##mo, 21); \
A##su ^= Du; \
Bbu = ROL64(A##su, 14); \
E##ba = Bba ^( Bbe | Bbi ); \
E##ba ^= KeccakF1600RoundConstants[i]; \
Ca = E##ba; \
E##be = Bbe ^((~Bbi)| Bbo ); \
Ce = E##be; \
E##bi = Bbi ^( Bbo & Bbu ); \
Ci = E##bi; \
E##bo = Bbo ^( Bbu | Bba ); \
Co = E##bo; \
E##bu = Bbu ^( Bba & Bbe ); \
Cu = E##bu; \
\
A##bo ^= Do; \
Bga = ROL64(A##bo, 28); \
A##gu ^= Du; \
Bge = ROL64(A##gu, 20); \
A##ka ^= Da; \
Bgi = ROL64(A##ka, 3); \
A##me ^= De; \
Bgo = ROL64(A##me, 45); \
A##si ^= Di; \
Bgu = ROL64(A##si, 61); \
E##ga = Bga ^( Bge | Bgi ); \
Ca ^= E##ga; \
E##ge = Bge ^( Bgi & Bgo ); \
Ce ^= E##ge; \
E##gi = Bgi ^( Bgo |(~Bgu)); \
Ci ^= E##gi; \
E##go = Bgo ^( Bgu | Bga ); \
Co ^= E##go; \
E##gu = Bgu ^( Bga & Bge ); \
Cu ^= E##gu; \
\
A##be ^= De; \
Bka = ROL64(A##be, 1); \
A##gi ^= Di; \
Bke = ROL64(A##gi, 6); \
A##ko ^= Do; \
Bki = ROL64(A##ko, 25); \
A##mu ^= Du; \
Bko = ROL64(A##mu, 8); \
A##sa ^= Da; \
Bku = ROL64(A##sa, 18); \
E##ka = Bka ^( Bke | Bki ); \
Ca ^= E##ka; \
E##ke = Bke ^( Bki & Bko ); \
Ce ^= E##ke; \
E##ki = Bki ^((~Bko)& Bku ); \
Ci ^= E##ki; \
E##ko = (~Bko)^( Bku | Bka ); \
Co ^= E##ko; \
E##ku = Bku ^( Bka & Bke ); \
Cu ^= E##ku; \
\
A##bu ^= Du; \
Bma = ROL64(A##bu, 27); \
A##ga ^= Da; \
Bme = ROL64(A##ga, 36); \
A##ke ^= De; \
Bmi = ROL64(A##ke, 10); \
A##mi ^= Di; \
Bmo = ROL64(A##mi, 15); \
A##so ^= Do; \
Bmu = ROL64(A##so, 56); \
E##ma = Bma ^( Bme & Bmi ); \
Ca ^= E##ma; \
E##me = Bme ^( Bmi | Bmo ); \
Ce ^= E##me; \
E##mi = Bmi ^((~Bmo)| Bmu ); \
Ci ^= E##mi; \
E##mo = (~Bmo)^( Bmu & Bma ); \
Co ^= E##mo; \
E##mu = Bmu ^( Bma | Bme ); \
Cu ^= E##mu; \
\
A##bi ^= Di; \
Bsa = ROL64(A##bi, 62); \
A##go ^= Do; \
Bse = ROL64(A##go, 55); \
A##ku ^= Du; \
Bsi = ROL64(A##ku, 39); \
A##ma ^= Da; \
Bso = ROL64(A##ma, 41); \
A##se ^= De; \
Bsu = ROL64(A##se, 2); \
E##sa = Bsa ^((~Bse)& Bsi ); \
Ca ^= E##sa; \
E##se = (~Bse)^( Bsi | Bso ); \
Ce ^= E##se; \
E##si = Bsi ^( Bso & Bsu ); \
Ci ^= E##si; \
E##so = Bso ^( Bsu | Bsa ); \
Co ^= E##so; \
E##su = Bsu ^( Bsa & Bse ); \
Cu ^= E##su; \
\
/* --- Code for round (lane complementing pattern 'bebigokimisa') */
/* --- 64-bit lanes mapped to 64-bit words */
#define thetaRhoPiChiIota(i, A, E) \
Da = Cu^ROL64(Ce, 1); \
De = Ca^ROL64(Ci, 1); \
Di = Ce^ROL64(Co, 1); \
Do = Ci^ROL64(Cu, 1); \
Du = Co^ROL64(Ca, 1); \
\
A##ba ^= Da; \
Bba = A##ba; \
A##ge ^= De; \
Bbe = ROL64(A##ge, 44); \
A##ki ^= Di; \
Bbi = ROL64(A##ki, 43); \
A##mo ^= Do; \
Bbo = ROL64(A##mo, 21); \
A##su ^= Du; \
Bbu = ROL64(A##su, 14); \
E##ba = Bba ^( Bbe | Bbi ); \
E##ba ^= KeccakF1600RoundConstants[i]; \
E##be = Bbe ^((~Bbi)| Bbo ); \
E##bi = Bbi ^( Bbo & Bbu ); \
E##bo = Bbo ^( Bbu | Bba ); \
E##bu = Bbu ^( Bba & Bbe ); \
\
A##bo ^= Do; \
Bga = ROL64(A##bo, 28); \
A##gu ^= Du; \
Bge = ROL64(A##gu, 20); \
A##ka ^= Da; \
Bgi = ROL64(A##ka, 3); \
A##me ^= De; \
Bgo = ROL64(A##me, 45); \
A##si ^= Di; \
Bgu = ROL64(A##si, 61); \
E##ga = Bga ^( Bge | Bgi ); \
E##ge = Bge ^( Bgi & Bgo ); \
E##gi = Bgi ^( Bgo |(~Bgu)); \
E##go = Bgo ^( Bgu | Bga ); \
E##gu = Bgu ^( Bga & Bge ); \
\
A##be ^= De; \
Bka = ROL64(A##be, 1); \
A##gi ^= Di; \
Bke = ROL64(A##gi, 6); \
A##ko ^= Do; \
Bki = ROL64(A##ko, 25); \
A##mu ^= Du; \
Bko = ROL64(A##mu, 8); \
A##sa ^= Da; \
Bku = ROL64(A##sa, 18); \
E##ka = Bka ^( Bke | Bki ); \
E##ke = Bke ^( Bki & Bko ); \
E##ki = Bki ^((~Bko)& Bku ); \
E##ko = (~Bko)^( Bku | Bka ); \
E##ku = Bku ^( Bka & Bke ); \
\
A##bu ^= Du; \
Bma = ROL64(A##bu, 27); \
A##ga ^= Da; \
Bme = ROL64(A##ga, 36); \
A##ke ^= De; \
Bmi = ROL64(A##ke, 10); \
A##mi ^= Di; \
Bmo = ROL64(A##mi, 15); \
A##so ^= Do; \
Bmu = ROL64(A##so, 56); \
E##ma = Bma ^( Bme & Bmi ); \
E##me = Bme ^( Bmi | Bmo ); \
E##mi = Bmi ^((~Bmo)| Bmu ); \
E##mo = (~Bmo)^( Bmu & Bma ); \
E##mu = Bmu ^( Bma | Bme ); \
\
A##bi ^= Di; \
Bsa = ROL64(A##bi, 62); \
A##go ^= Do; \
Bse = ROL64(A##go, 55); \
A##ku ^= Du; \
Bsi = ROL64(A##ku, 39); \
A##ma ^= Da; \
Bso = ROL64(A##ma, 41); \
A##se ^= De; \
Bsu = ROL64(A##se, 2); \
E##sa = Bsa ^((~Bse)& Bsi ); \
E##se = (~Bse)^( Bsi | Bso ); \
E##si = Bsi ^( Bso & Bsu ); \
E##so = Bso ^( Bsu | Bsa ); \
E##su = Bsu ^( Bsa & Bse ); \
\
#else /* UseBebigokimisa */
/* --- Code for round, with prepare-theta */
/* --- 64-bit lanes mapped to 64-bit words */
#define thetaRhoPiChiIotaPrepareTheta(i, A, E) \
Da = Cu^ROL64(Ce, 1); \
De = Ca^ROL64(Ci, 1); \
Di = Ce^ROL64(Co, 1); \
Do = Ci^ROL64(Cu, 1); \
Du = Co^ROL64(Ca, 1); \
\
A##ba ^= Da; \
Bba = A##ba; \
A##ge ^= De; \
Bbe = ROL64(A##ge, 44); \
A##ki ^= Di; \
Bbi = ROL64(A##ki, 43); \
A##mo ^= Do; \
Bbo = ROL64(A##mo, 21); \
A##su ^= Du; \
Bbu = ROL64(A##su, 14); \
E##ba = Bba ^((~Bbe)& Bbi ); \
E##ba ^= KeccakF1600RoundConstants[i]; \
Ca = E##ba; \
E##be = Bbe ^((~Bbi)& Bbo ); \
Ce = E##be; \
E##bi = Bbi ^((~Bbo)& Bbu ); \
Ci = E##bi; \
E##bo = Bbo ^((~Bbu)& Bba ); \
Co = E##bo; \
E##bu = Bbu ^((~Bba)& Bbe ); \
Cu = E##bu; \
\
A##bo ^= Do; \
Bga = ROL64(A##bo, 28); \
A##gu ^= Du; \
Bge = ROL64(A##gu, 20); \
A##ka ^= Da; \
Bgi = ROL64(A##ka, 3); \
A##me ^= De; \
Bgo = ROL64(A##me, 45); \
A##si ^= Di; \
Bgu = ROL64(A##si, 61); \
E##ga = Bga ^((~Bge)& Bgi ); \
Ca ^= E##ga; \
E##ge = Bge ^((~Bgi)& Bgo ); \
Ce ^= E##ge; \
E##gi = Bgi ^((~Bgo)& Bgu ); \
Ci ^= E##gi; \
E##go = Bgo ^((~Bgu)& Bga ); \
Co ^= E##go; \
E##gu = Bgu ^((~Bga)& Bge ); \
Cu ^= E##gu; \
\
A##be ^= De; \
Bka = ROL64(A##be, 1); \
A##gi ^= Di; \
Bke = ROL64(A##gi, 6); \
A##ko ^= Do; \
Bki = ROL64(A##ko, 25); \
A##mu ^= Du; \
Bko = ROL64(A##mu, 8); \
A##sa ^= Da; \
Bku = ROL64(A##sa, 18); \
E##ka = Bka ^((~Bke)& Bki ); \
Ca ^= E##ka; \
E##ke = Bke ^((~Bki)& Bko ); \
Ce ^= E##ke; \
E##ki = Bki ^((~Bko)& Bku ); \
Ci ^= E##ki; \
E##ko = Bko ^((~Bku)& Bka ); \
Co ^= E##ko; \
E##ku = Bku ^((~Bka)& Bke ); \
Cu ^= E##ku; \
\
A##bu ^= Du; \
Bma = ROL64(A##bu, 27); \
A##ga ^= Da; \
Bme = ROL64(A##ga, 36); \
A##ke ^= De; \
Bmi = ROL64(A##ke, 10); \
A##mi ^= Di; \
Bmo = ROL64(A##mi, 15); \
A##so ^= Do; \
Bmu = ROL64(A##so, 56); \
E##ma = Bma ^((~Bme)& Bmi ); \
Ca ^= E##ma; \
E##me = Bme ^((~Bmi)& Bmo ); \
Ce ^= E##me; \
E##mi = Bmi ^((~Bmo)& Bmu ); \
Ci ^= E##mi; \
E##mo = Bmo ^((~Bmu)& Bma ); \
Co ^= E##mo; \
E##mu = Bmu ^((~Bma)& Bme ); \
Cu ^= E##mu; \
\
A##bi ^= Di; \
Bsa = ROL64(A##bi, 62); \
A##go ^= Do; \
Bse = ROL64(A##go, 55); \
A##ku ^= Du; \
Bsi = ROL64(A##ku, 39); \
A##ma ^= Da; \
Bso = ROL64(A##ma, 41); \
A##se ^= De; \
Bsu = ROL64(A##se, 2); \
E##sa = Bsa ^((~Bse)& Bsi ); \
Ca ^= E##sa; \
E##se = Bse ^((~Bsi)& Bso ); \
Ce ^= E##se; \
E##si = Bsi ^((~Bso)& Bsu ); \
Ci ^= E##si; \
E##so = Bso ^((~Bsu)& Bsa ); \
Co ^= E##so; \
E##su = Bsu ^((~Bsa)& Bse ); \
Cu ^= E##su; \
\
/* --- Code for round */
/* --- 64-bit lanes mapped to 64-bit words */
#define thetaRhoPiChiIota(i, A, E) \
Da = Cu^ROL64(Ce, 1); \
De = Ca^ROL64(Ci, 1); \
Di = Ce^ROL64(Co, 1); \
Do = Ci^ROL64(Cu, 1); \
Du = Co^ROL64(Ca, 1); \
\
A##ba ^= Da; \
Bba = A##ba; \
A##ge ^= De; \
Bbe = ROL64(A##ge, 44); \
A##ki ^= Di; \
Bbi = ROL64(A##ki, 43); \
A##mo ^= Do; \
Bbo = ROL64(A##mo, 21); \
A##su ^= Du; \
Bbu = ROL64(A##su, 14); \
E##ba = Bba ^((~Bbe)& Bbi ); \
E##ba ^= KeccakF1600RoundConstants[i]; \
E##be = Bbe ^((~Bbi)& Bbo ); \
E##bi = Bbi ^((~Bbo)& Bbu ); \
E##bo = Bbo ^((~Bbu)& Bba ); \
E##bu = Bbu ^((~Bba)& Bbe ); \
\
A##bo ^= Do; \
Bga = ROL64(A##bo, 28); \
A##gu ^= Du; \
Bge = ROL64(A##gu, 20); \
A##ka ^= Da; \
Bgi = ROL64(A##ka, 3); \
A##me ^= De; \
Bgo = ROL64(A##me, 45); \
A##si ^= Di; \
Bgu = ROL64(A##si, 61); \
E##ga = Bga ^((~Bge)& Bgi ); \
E##ge = Bge ^((~Bgi)& Bgo ); \
E##gi = Bgi ^((~Bgo)& Bgu ); \
E##go = Bgo ^((~Bgu)& Bga ); \
E##gu = Bgu ^((~Bga)& Bge ); \
\
A##be ^= De; \
Bka = ROL64(A##be, 1); \
A##gi ^= Di; \
Bke = ROL64(A##gi, 6); \
A##ko ^= Do; \
Bki = ROL64(A##ko, 25); \
A##mu ^= Du; \
Bko = ROL64(A##mu, 8); \
A##sa ^= Da; \
Bku = ROL64(A##sa, 18); \
E##ka = Bka ^((~Bke)& Bki ); \
E##ke = Bke ^((~Bki)& Bko ); \
E##ki = Bki ^((~Bko)& Bku ); \
E##ko = Bko ^((~Bku)& Bka ); \
E##ku = Bku ^((~Bka)& Bke ); \
\
A##bu ^= Du; \
Bma = ROL64(A##bu, 27); \
A##ga ^= Da; \
Bme = ROL64(A##ga, 36); \
A##ke ^= De; \
Bmi = ROL64(A##ke, 10); \
A##mi ^= Di; \
Bmo = ROL64(A##mi, 15); \
A##so ^= Do; \
Bmu = ROL64(A##so, 56); \
E##ma = Bma ^((~Bme)& Bmi ); \
E##me = Bme ^((~Bmi)& Bmo ); \
E##mi = Bmi ^((~Bmo)& Bmu ); \
E##mo = Bmo ^((~Bmu)& Bma ); \
E##mu = Bmu ^((~Bma)& Bme ); \
\
A##bi ^= Di; \
Bsa = ROL64(A##bi, 62); \
A##go ^= Do; \
Bse = ROL64(A##go, 55); \
A##ku ^= Du; \
Bsi = ROL64(A##ku, 39); \
A##ma ^= Da; \
Bso = ROL64(A##ma, 41); \
A##se ^= De; \
Bsu = ROL64(A##se, 2); \
E##sa = Bsa ^((~Bse)& Bsi ); \
E##se = Bse ^((~Bsi)& Bso ); \
E##si = Bsi ^((~Bso)& Bsu ); \
E##so = Bso ^((~Bsu)& Bsa ); \
E##su = Bsu ^((~Bsa)& Bse ); \
\
#endif /* UseBebigokimisa */
#define copyFromState(X, state) \
X##ba = state[ 0]; \
X##be = state[ 1]; \
X##bi = state[ 2]; \
X##bo = state[ 3]; \
X##bu = state[ 4]; \
X##ga = state[ 5]; \
X##ge = state[ 6]; \
X##gi = state[ 7]; \
X##go = state[ 8]; \
X##gu = state[ 9]; \
X##ka = state[10]; \
X##ke = state[11]; \
X##ki = state[12]; \
X##ko = state[13]; \
X##ku = state[14]; \
X##ma = state[15]; \
X##me = state[16]; \
X##mi = state[17]; \
X##mo = state[18]; \
X##mu = state[19]; \
X##sa = state[20]; \
X##se = state[21]; \
X##si = state[22]; \
X##so = state[23]; \
X##su = state[24]; \
#define copyToState(state, X) \
state[ 0] = X##ba; \
state[ 1] = X##be; \
state[ 2] = X##bi; \
state[ 3] = X##bo; \
state[ 4] = X##bu; \
state[ 5] = X##ga; \
state[ 6] = X##ge; \
state[ 7] = X##gi; \
state[ 8] = X##go; \
state[ 9] = X##gu; \
state[10] = X##ka; \
state[11] = X##ke; \
state[12] = X##ki; \
state[13] = X##ko; \
state[14] = X##ku; \
state[15] = X##ma; \
state[16] = X##me; \
state[17] = X##mi; \
state[18] = X##mo; \
state[19] = X##mu; \
state[20] = X##sa; \
state[21] = X##se; \
state[22] = X##si; \
state[23] = X##so; \
state[24] = X##su; \
#define copyStateVariables(X, Y) \
X##ba = Y##ba; \
X##be = Y##be; \
X##bi = Y##bi; \
X##bo = Y##bo; \
X##bu = Y##bu; \
X##ga = Y##ga; \
X##ge = Y##ge; \
X##gi = Y##gi; \
X##go = Y##go; \
X##gu = Y##gu; \
X##ka = Y##ka; \
X##ke = Y##ke; \
X##ki = Y##ki; \
X##ko = Y##ko; \
X##ku = Y##ku; \
X##ma = Y##ma; \
X##me = Y##me; \
X##mi = Y##mi; \
X##mo = Y##mo; \
X##mu = Y##mu; \
X##sa = Y##sa; \
X##se = Y##se; \
X##si = Y##si; \
X##so = Y##so; \
X##su = Y##su; \
#if (PLATFORM_BYTE_ORDER == IS_LITTLE_ENDIAN)
#define LOAD64(x) ((x)[0] \
| (uint64_t) (x)[1] << 0x08 \
| (uint64_t) (x)[2] << 0x10 \
| (uint64_t) (x)[3] << 0x18 \
| (uint64_t) (x)[4] << 0x20 \
| (uint64_t) (x)[5] << 0x28 \
| (uint64_t) (x)[6] << 0x30 \
| (uint64_t) (x)[7] << 0x38 )
#else
#define LOAD64(x) ((x)[7] \
| (uint64_t) (x)[6] << 0x08 \
| (uint64_t) (x)[5] << 0x10 \
| (uint64_t) (x)[4] << 0x18 \
| (uint64_t) (x)[3] << 0x20 \
| (uint64_t) (x)[2] << 0x28 \
| (uint64_t) (x)[1] << 0x30 \
| (uint64_t) (x)[0] << 0x38 )
#endif
#define addInput(X, input, laneCount) \
if (laneCount == 21) { \
X##ba ^= LOAD64(input + 0x00); \
X##be ^= LOAD64(input + 0x08); \
X##bi ^= LOAD64(input + 0x10); \
X##bo ^= LOAD64(input + 0x18); \
X##bu ^= LOAD64(input + 0x20); \
X##ga ^= LOAD64(input + 0x28); \
X##ge ^= LOAD64(input + 0x30); \
X##gi ^= LOAD64(input + 0x38); \
X##go ^= LOAD64(input + 0x40); \
X##gu ^= LOAD64(input + 0x48); \
X##ka ^= LOAD64(input + 0x50); \
X##ke ^= LOAD64(input + 0x58); \
X##ki ^= LOAD64(input + 0x60); \
X##ko ^= LOAD64(input + 0x68); \
X##ku ^= LOAD64(input + 0x70); \
X##ma ^= LOAD64(input + 0x78); \
X##me ^= LOAD64(input + 0x80); \
X##mi ^= LOAD64(input + 0x88); \
X##mo ^= LOAD64(input + 0x90); \
X##mu ^= LOAD64(input + 0x98); \
X##sa ^= LOAD64(input + 0xA0); \
} \
else if (laneCount < 16) { \
if (laneCount < 8) { \
if (laneCount < 4) { \
if (laneCount < 2) { \
if (laneCount < 1) { \
} \
else { \
X##ba ^= LOAD64(input + 0x00); \
} \
} \
else { \
X##ba ^= LOAD64(input + 0x00); \
X##be ^= LOAD64(input + 0x08); \
if (laneCount < 3) { \
} \
else { \
X##bi ^= LOAD64(input + 0x10); \
} \
} \
} \
else { \
X##ba ^= LOAD64(input + 0x00); \
X##be ^= LOAD64(input + 0x08); \
X##bi ^= LOAD64(input + 0x10); \
X##bo ^= LOAD64(input + 0x18); \
if (laneCount < 6) { \
if (laneCount < 5) { \
} \
else { \
X##bu ^= LOAD64(input + 0x20); \
} \
} \
else { \
X##bu ^= LOAD64(input + 0x20); \
X##ga ^= LOAD64(input + 0x28); \
if (laneCount < 7) { \
} \
else { \
X##ge ^= LOAD64(input + 0x30); \
} \
} \
} \
} \
else { \
X##ba ^= LOAD64(input + 0x00); \
X##be ^= LOAD64(input + 0x08); \
X##bi ^= LOAD64(input + 0x10); \
X##bo ^= LOAD64(input + 0x18); \
X##bu ^= LOAD64(input + 0x20); \
X##ga ^= LOAD64(input + 0x28); \
X##ge ^= LOAD64(input + 0x30); \
X##gi ^= LOAD64(input + 0x38); \
if (laneCount < 12) { \
if (laneCount < 10) { \
if (laneCount < 9) { \
} \
else { \
X##go ^= LOAD64(input + 0x40); \
} \
} \
else { \
X##go ^= LOAD64(input + 0x40); \
X##gu ^= LOAD64(input + 0x48); \
if (laneCount < 11) { \
} \
else { \
X##ka ^= LOAD64(input + 0x50); \
} \
} \
} \
else { \
X##go ^= LOAD64(input + 0x40); \
X##gu ^= LOAD64(input + 0x48); \
X##ka ^= LOAD64(input + 0x50); \
X##ke ^= LOAD64(input + 0x58); \
if (laneCount < 14) { \
if (laneCount < 13) { \
} \
else { \
X##ki ^= LOAD64(input + 0x60); \
} \
} \
else { \
X##ki ^= LOAD64(input + 0x60); \
X##ko ^= LOAD64(input + 0x68); \
if (laneCount < 15) { \
} \
else { \
X##ku ^= LOAD64(input + 0x70); \
} \
} \
} \
} \
} \
else { \
X##ba ^= LOAD64(input + 0x00); \
X##be ^= LOAD64(input + 0x08); \
X##bi ^= LOAD64(input + 0x10); \
X##bo ^= LOAD64(input + 0x18); \
X##bu ^= LOAD64(input + 0x20); \
X##ga ^= LOAD64(input + 0x28); \
X##ge ^= LOAD64(input + 0x30); \
X##gi ^= LOAD64(input + 0x38); \
X##go ^= LOAD64(input + 0x40); \
X##gu ^= LOAD64(input + 0x48); \
X##ka ^= LOAD64(input + 0x50); \
X##ke ^= LOAD64(input + 0x58); \
X##ki ^= LOAD64(input + 0x60); \
X##ko ^= LOAD64(input + 0x68); \
X##ku ^= LOAD64(input + 0x70); \
X##ma ^= LOAD64(input + 0x78); \
if (laneCount < 24) { \
if (laneCount < 20) { \
if (laneCount < 18) { \
if (laneCount < 17) { \
} \
else { \
X##me ^= LOAD64(input + 0x80); \
} \
} \
else { \
X##me ^= LOAD64(input + 0x80); \
X##mi ^= LOAD64(input + 0x88); \
if (laneCount < 19) { \
} \
else { \
X##mo ^= LOAD64(input + 0x90); \
} \
} \
} \
else { \
X##me ^= LOAD64(input + 0x80); \
X##mi ^= LOAD64(input + 0x88); \
X##mo ^= LOAD64(input + 0x90); \
X##mu ^= LOAD64(input + 0x98); \
if (laneCount < 22) { \
if (laneCount < 21) { \
} \
else { \
X##sa ^= LOAD64(input + 0xA0); \
} \
} \
else { \
X##sa ^= LOAD64(input + 0xA0); \
X##se ^= LOAD64(input + 0xA8); \
if (laneCount < 23) { \
} \
else { \
X##si ^= LOAD64(input + 0xA8); \
} \
} \
} \
} \
else { \
X##me ^= LOAD64(input + 0x80); \
X##mi ^= LOAD64(input + 0x88); \
X##mo ^= LOAD64(input + 0x90); \
X##mu ^= LOAD64(input + 0x98); \
X##sa ^= LOAD64(input + 0xA0); \
X##se ^= LOAD64(input + 0xA8); \
X##si ^= LOAD64(input + 0xB0); \
X##so ^= LOAD64(input + 0xB8); \
if (laneCount < 25) { \
} \
else { \
X##su ^= LOAD64(input + 0xC0); \
} \
} \
}

View file

@ -0,0 +1,86 @@
/*
The eXtended Keccak Code Package (XKCP)
https://github.com/XKCP/XKCP
The Keccak-p permutations, designed by Guido Bertoni, Joan Daemen, Michaël Peeters and Gilles Van Assche.
Implementation by Gilles Van Assche and Ronny Van Keer, hereby denoted as "the implementer".
For more information, feedback or questions, please refer to the Keccak Team website:
https://keccak.team/
To the extent possible under law, the implementer has waived all copyright
and related or neighboring rights to the source code in this file.
http://creativecommons.org/publicdomain/zero/1.0/
---
Please refer to SnP-documentation.h for more details.
*/
#ifndef _KeccakP_1600_SnP_h_
#define _KeccakP_1600_SnP_h_
#include "brg_endian.h"
#include "KeccakP-1600-opt64-config.h"
#include <stddef.h>
#define KeccakP1600_implementation_plain64 "generic 64-bit optimized implementation (" KeccakP1600_implementation_config ")"
#define KeccakP1600_stateSizeInBytes_plain64 200
#define KeccakP1600_stateAlignment_plain64 8
#define KeccakF1600_FastLoop_supported_plain64
#define KeccakP1600_12rounds_FastLoop_supported_plain64
#if defined(ADD_SYMBOL_SUFFIX)
#define KECCAK_SYMBOL_SUFFIX plain64
#define KECCAK_IMPL_NAMESPACE(x) x##_plain64
#else
#define KECCAK_IMPL_NAMESPACE(x) x
#define KeccakP1600_implementation KeccakP1600_implementation_plain64
#define KeccakP1600_stateSizeInBytes KeccakP1600_stateSizeInBytes_plain64
#define KeccakP1600_stateAlignment KeccakP1600_stateAlignment_plain64
#define KeccakF1600_FastLoop_supported KeccakF1600_FastLoop_supported_plain64
#define KeccakP1600_12rounds_FastLoop_supported KeccakP1600_12rounds_FastLoop_supported_plain64
#endif
#define KeccakP1600_StaticInitialize KECCAK_IMPL_NAMESPACE(KeccakP1600_StaticInitialize)
void KeccakP1600_StaticInitialize(void);
#define KeccakP1600_Initialize KECCAK_IMPL_NAMESPACE(KeccakP1600_Initialize)
void KeccakP1600_Initialize(void *state);
#define KeccakP1600_AddByte KECCAK_IMPL_NAMESPACE(KeccakP1600_AddByte)
void KeccakP1600_AddByte(void *state, unsigned char data, unsigned int offset);
#define KeccakP1600_AddBytes KECCAK_IMPL_NAMESPACE(KeccakP1600_AddBytes)
void KeccakP1600_AddBytes(void *state, const unsigned char *data, unsigned int offset, unsigned int length);
#define KeccakP1600_OverwriteBytes KECCAK_IMPL_NAMESPACE(KeccakP1600_OverwriteBytes)
void KeccakP1600_OverwriteBytes(void *state, const unsigned char *data, unsigned int offset, unsigned int length);
#define KeccakP1600_OverwriteWithZeroes KECCAK_IMPL_NAMESPACE(KeccakP1600_OverwriteWithZeroes)
void KeccakP1600_OverwriteWithZeroes(void *state, unsigned int byteCount);
#define KeccakP1600_Permute_Nrounds KECCAK_IMPL_NAMESPACE(KeccakP1600_Permute_Nrounds)
void KeccakP1600_Permute_Nrounds(void *state, unsigned int nrounds);
#define KeccakP1600_Permute_12rounds KECCAK_IMPL_NAMESPACE(KeccakP1600_Permute_12rounds)
void KeccakP1600_Permute_12rounds(void *state);
#define KeccakP1600_Permute_24rounds KECCAK_IMPL_NAMESPACE(KeccakP1600_Permute_24rounds)
void KeccakP1600_Permute_24rounds(void *state);
#define KeccakP1600_ExtractBytes KECCAK_IMPL_NAMESPACE(KeccakP1600_ExtractBytes)
void KeccakP1600_ExtractBytes(const void *state, unsigned char *data, unsigned int offset, unsigned int length);
#define KeccakP1600_ExtractAndAddBytes KECCAK_IMPL_NAMESPACE(KeccakP1600_ExtractAndAddBytes)
void KeccakP1600_ExtractAndAddBytes(const void *state, const unsigned char *input, unsigned char *output, unsigned int offset, unsigned int length);
#define KeccakF1600_FastLoop_Absorb KECCAK_IMPL_NAMESPACE(KeccakF1600_FastLoop_Absorb)
size_t KeccakF1600_FastLoop_Absorb(void *state, unsigned int laneCount, const unsigned char *data, size_t dataByteLen);
#define KeccakP1600_12rounds_FastLoop_Absorb KECCAK_IMPL_NAMESPACE(KeccakP1600_12rounds_FastLoop_Absorb)
size_t KeccakP1600_12rounds_FastLoop_Absorb(void *state, unsigned int laneCount, const unsigned char *data, size_t dataByteLen);
#endif

View file

@ -0,0 +1,6 @@
/*
This file defines some parameters of the implementation in the parent directory.
*/
#define KeccakP1600_implementation_config "all rounds unrolled"
#define KeccakP1600_fullUnrolling

View file

@ -0,0 +1,519 @@
/*
The eXtended Keccak Code Package (XKCP)
https://github.com/XKCP/XKCP
The Keccak-p permutations, designed by Guido Bertoni, Joan Daemen, Michaël Peeters and Gilles Van Assche.
Implementation by Gilles Van Assche and Ronny Van Keer, hereby denoted as "the implementer".
For more information, feedback or questions, please refer to the Keccak Team website:
https://keccak.team/
To the extent possible under law, the implementer has waived all copyright
and related or neighboring rights to the source code in this file.
http://creativecommons.org/publicdomain/zero/1.0/
---
This file implements Keccak-p[1600] in a SnP-compatible way.
Please refer to SnP-documentation.h for more details.
This implementation comes with KeccakP-1600-SnP.h in the same folder.
Please refer to LowLevel.build for the exact list of other files it must be combined with.
*/
#include <stdint.h>
#include <string.h>
#include <stdlib.h>
#include "brg_endian.h"
#include "KeccakP-1600-SnP.h"
#include "KeccakP-1600-opt64-config.h"
#define UseBebigokimisa
#if defined(_MSC_VER)
#define ROL64(a, offset) _rotl64(a, offset)
#elif defined(KeccakP1600_useSHLD)
#define ROL64(x,N) ({ \
register uint64_t __out; \
register uint64_t __in = x; \
__asm__ ("shld %2,%0,%0" : "=r"(__out) : "0"(__in), "i"(N)); \
__out; \
})
#else
#define ROL64(a, offset) ((((uint64_t)a) << offset) ^ (((uint64_t)a) >> (64-offset)))
#endif
#include "KeccakP-1600-64.macros"
#define FullUnrolling
#include "KeccakP-1600-unrolling.macros"
#include "SnP-Relaned.h"
static const uint64_t KeccakF1600RoundConstants[24] = {
0x0000000000000001ULL,
0x0000000000008082ULL,
0x800000000000808aULL,
0x8000000080008000ULL,
0x000000000000808bULL,
0x0000000080000001ULL,
0x8000000080008081ULL,
0x8000000000008009ULL,
0x000000000000008aULL,
0x0000000000000088ULL,
0x0000000080008009ULL,
0x000000008000000aULL,
0x000000008000808bULL,
0x800000000000008bULL,
0x8000000000008089ULL,
0x8000000000008003ULL,
0x8000000000008002ULL,
0x8000000000000080ULL,
0x000000000000800aULL,
0x800000008000000aULL,
0x8000000080008081ULL,
0x8000000000008080ULL,
0x0000000080000001ULL,
0x8000000080008008ULL
};
/* ---------------------------------------------------------------- */
void KeccakP1600_StaticInitialize(void) { }
/* ---------------------------------------------------------------- */
void KeccakP1600_Initialize(void *state) {
memset(state, 0, 200);
((uint64_t *)state)[ 1] = ~(uint64_t)0;
((uint64_t *)state)[ 2] = ~(uint64_t)0;
((uint64_t *)state)[ 8] = ~(uint64_t)0;
((uint64_t *)state)[12] = ~(uint64_t)0;
((uint64_t *)state)[17] = ~(uint64_t)0;
((uint64_t *)state)[20] = ~(uint64_t)0;
}
/* ---------------------------------------------------------------- */
void KeccakP1600_AddBytesInLane(void *state, unsigned int lanePosition, const unsigned char *data, unsigned int offset, unsigned int length) {
#if (PLATFORM_BYTE_ORDER == IS_LITTLE_ENDIAN)
uint64_t lane;
if (length == 0) {
return;
}
if (length == 1) {
lane = data[0];
} else {
lane = 0;
memcpy(&lane, data, length);
}
lane <<= offset * 8;
#else
uint64_t lane = 0;
unsigned int i;
for (i = 0; i < length; i++) {
lane |= ((uint64_t)data[i]) << ((i + offset) * 8);
}
#endif
((uint64_t *)state)[lanePosition] ^= lane;
}
/* ---------------------------------------------------------------- */
void KeccakP1600_AddLanes(void *state, const unsigned char *data, unsigned int laneCount) {
#if (PLATFORM_BYTE_ORDER == IS_LITTLE_ENDIAN)
unsigned int i = 0;
/* If either pointer is misaligned, fall back to byte-wise xor. */
if (((((uintptr_t)state) & 7) != 0) || ((((uintptr_t)data) & 7) != 0)) {
for (i = 0; i < laneCount * 8; i++) {
((unsigned char *)state)[i] ^= data[i];
}
} else {
/* Otherwise... */
for ( ; (i + 8) <= laneCount; i += 8) {
((uint64_t *)state)[i + 0] ^= ((const uint64_t *)data)[i + 0];
((uint64_t *)state)[i + 1] ^= ((const uint64_t *)data)[i + 1];
((uint64_t *)state)[i + 2] ^= ((const uint64_t *)data)[i + 2];
((uint64_t *)state)[i + 3] ^= ((const uint64_t *)data)[i + 3];
((uint64_t *)state)[i + 4] ^= ((const uint64_t *)data)[i + 4];
((uint64_t *)state)[i + 5] ^= ((const uint64_t *)data)[i + 5];
((uint64_t *)state)[i + 6] ^= ((const uint64_t *)data)[i + 6];
((uint64_t *)state)[i + 7] ^= ((const uint64_t *)data)[i + 7];
}
for ( ; (i + 4) <= laneCount; i += 4) {
((uint64_t *)state)[i + 0] ^= ((const uint64_t *)data)[i + 0];
((uint64_t *)state)[i + 1] ^= ((const uint64_t *)data)[i + 1];
((uint64_t *)state)[i + 2] ^= ((const uint64_t *)data)[i + 2];
((uint64_t *)state)[i + 3] ^= ((const uint64_t *)data)[i + 3];
}
for ( ; (i + 2) <= laneCount; i += 2) {
((uint64_t *)state)[i + 0] ^= ((const uint64_t *)data)[i + 0];
((uint64_t *)state)[i + 1] ^= ((const uint64_t *)data)[i + 1];
}
if (i < laneCount) {
((uint64_t *)state)[i + 0] ^= ((const uint64_t *)data)[i + 0];
}
}
#else
unsigned int i;
const uint8_t *curData = data;
for (i = 0; i < laneCount; i++, curData += 8) {
uint64_t lane = (uint64_t)curData[0]
| ((uint64_t)curData[1] << 8)
| ((uint64_t)curData[2] << 16)
| ((uint64_t)curData[3] << 24)
| ((uint64_t)curData[4] << 32)
| ((uint64_t)curData[5] << 40)
| ((uint64_t)curData[6] << 48)
| ((uint64_t)curData[7] << 56);
((uint64_t *)state)[i] ^= lane;
}
#endif
}
/* ---------------------------------------------------------------- */
#if (PLATFORM_BYTE_ORDER == IS_LITTLE_ENDIAN)
void KeccakP1600_AddByte(void *state, unsigned char byte, unsigned int offset) {
((unsigned char *)state)[offset] ^= byte;
}
#else
void KeccakP1600_AddByte(void *state, unsigned char byte, unsigned int offset) {
uint64_t lane = byte;
lane <<= (offset % 8) * 8;
((uint64_t *)state)[offset / 8] ^= lane;
}
#endif
/* ---------------------------------------------------------------- */
void KeccakP1600_AddBytes(void *state, const unsigned char *data, unsigned int offset, unsigned int length) {
SnP_AddBytes(state, data, offset, length, KeccakP1600_AddLanes, KeccakP1600_AddBytesInLane, 8);
}
/* ---------------------------------------------------------------- */
void KeccakP1600_OverwriteBytesInLane(void *state, unsigned int lanePosition, const unsigned char *data, unsigned int offset, unsigned int length) {
#if (PLATFORM_BYTE_ORDER == IS_LITTLE_ENDIAN)
if ((lanePosition == 1) || (lanePosition == 2) || (lanePosition == 8) || (lanePosition == 12) || (lanePosition == 17) || (lanePosition == 20)) {
unsigned int i;
for (i = 0; i < length; i++) {
((unsigned char *)state)[lanePosition * 8 + offset + i] = ~data[i];
}
} else {
memcpy((unsigned char *)state + lanePosition * 8 + offset, data, length);
}
#else
uint64_t lane = ((uint64_t *)state)[lanePosition];
unsigned int i;
for (i = 0; i < length; i++) {
lane &= ~((uint64_t)0xFF << ((offset + i) * 8));
if ((lanePosition == 1) || (lanePosition == 2) || (lanePosition == 8) || (lanePosition == 12) || (lanePosition == 17) || (lanePosition == 20)) {
lane |= (uint64_t)(data[i] ^ 0xFF) << ((offset + i) * 8);
} else {
lane |= (uint64_t)data[i] << ((offset + i) * 8);
}
}
((uint64_t *)state)[lanePosition] = lane;
#endif
}
/* ---------------------------------------------------------------- */
void KeccakP1600_OverwriteLanes(void *state, const unsigned char *data, unsigned int laneCount) {
#if (PLATFORM_BYTE_ORDER == IS_LITTLE_ENDIAN)
unsigned int lanePosition;
for (lanePosition = 0; lanePosition < laneCount; lanePosition++) {
memcpy(((uint64_t *)state) + lanePosition, data, sizeof(uint64_t));
if ((lanePosition == 1) || (lanePosition == 2) || (lanePosition == 8) || (lanePosition == 12) || (lanePosition == 17) || (lanePosition == 20)) {
((uint64_t *)state)[lanePosition] = ~((uint64_t *)state)[lanePosition];
}
}
#else
unsigned int lanePosition;
const uint8_t *curData = data;
for (lanePosition = 0; lanePosition < laneCount; lanePosition++, curData += 8) {
uint64_t lane = (uint64_t)curData[0]
| ((uint64_t)curData[1] << 8)
| ((uint64_t)curData[2] << 16)
| ((uint64_t)curData[3] << 24)
| ((uint64_t)curData[4] << 32)
| ((uint64_t)curData[5] << 40)
| ((uint64_t)curData[6] << 48)
| ((uint64_t)curData[7] << 56);
if ((lanePosition == 1) || (lanePosition == 2) || (lanePosition == 8) || (lanePosition == 12) || (lanePosition == 17) || (lanePosition == 20)) {
((uint64_t *)state)[lanePosition] = ~lane;
} else {
((uint64_t *)state)[lanePosition] = lane;
}
}
#endif
}
/* ---------------------------------------------------------------- */
void KeccakP1600_OverwriteBytes(void *state, const unsigned char *data, unsigned int offset, unsigned int length) {
SnP_OverwriteBytes(state, data, offset, length, KeccakP1600_OverwriteLanes, KeccakP1600_OverwriteBytesInLane, 8);
}
/* ---------------------------------------------------------------- */
void KeccakP1600_OverwriteWithZeroes(void *state, unsigned int byteCount) {
#if (PLATFORM_BYTE_ORDER == IS_LITTLE_ENDIAN)
unsigned int lanePosition;
for (lanePosition = 0; lanePosition < byteCount / 8; lanePosition++)
if ((lanePosition == 1) || (lanePosition == 2) || (lanePosition == 8) || (lanePosition == 12) || (lanePosition == 17) || (lanePosition == 20)) {
((uint64_t *)state)[lanePosition] = ~(uint64_t)0;
} else {
((uint64_t *)state)[lanePosition] = 0;
}
if (byteCount % 8 != 0) {
lanePosition = byteCount / 8;
if ((lanePosition == 1) || (lanePosition == 2) || (lanePosition == 8) || (lanePosition == 12) || (lanePosition == 17) || (lanePosition == 20)) {
memset((unsigned char *)state + lanePosition * 8, 0xFF, byteCount % 8);
} else {
memset((unsigned char *)state + lanePosition * 8, 0, byteCount % 8);
}
}
#else
unsigned int i, j;
for (i = 0; i < byteCount; i += 8) {
unsigned int lanePosition = i / 8;
if (i + 8 <= byteCount) {
if ((lanePosition == 1) || (lanePosition == 2) || (lanePosition == 8) || (lanePosition == 12) || (lanePosition == 17) || (lanePosition == 20)) {
((uint64_t *)state)[lanePosition] = ~(uint64_t)0;
} else {
((uint64_t *)state)[lanePosition] = 0;
}
} else {
uint64_t lane = ((uint64_t *)state)[lanePosition];
for (j = 0; j < byteCount % 8; j++) {
if ((lanePosition == 1) || (lanePosition == 2) || (lanePosition == 8) || (lanePosition == 12) || (lanePosition == 17) || (lanePosition == 20)) {
lane |= (uint64_t)0xFF << (j * 8);
} else {
lane &= ~((uint64_t)0xFF << (j * 8));
}
}
((uint64_t *)state)[lanePosition] = lane;
}
}
#endif
}
/* ---------------------------------------------------------------- */
void KeccakP1600_Permute_Nrounds(void *state, unsigned int nr) {
declareABCDE
unsigned int i;
uint64_t *stateAsLanes = (uint64_t *)state;
copyFromState(A, stateAsLanes)
roundsN(nr)
copyToState(stateAsLanes, A)
}
/* ---------------------------------------------------------------- */
void KeccakP1600_Permute_24rounds(void *state) {
declareABCDE
uint64_t *stateAsLanes = (uint64_t *)state;
copyFromState(A, stateAsLanes)
rounds24
copyToState(stateAsLanes, A)
}
/* ---------------------------------------------------------------- */
void KeccakP1600_Permute_12rounds(void *state) {
declareABCDE
uint64_t *stateAsLanes = (uint64_t *)state;
copyFromState(A, stateAsLanes)
rounds12
copyToState(stateAsLanes, A)
}
/* ---------------------------------------------------------------- */
void KeccakP1600_ExtractBytesInLane(const void *state, unsigned int lanePosition, unsigned char *data, unsigned int offset, unsigned int length) {
uint64_t lane = ((const uint64_t *)state)[lanePosition];
if ((lanePosition == 1) || (lanePosition == 2) || (lanePosition == 8) || (lanePosition == 12) || (lanePosition == 17) || (lanePosition == 20)) {
lane = ~lane;
}
#if (PLATFORM_BYTE_ORDER == IS_LITTLE_ENDIAN)
{
uint64_t lane1[1];
lane1[0] = lane;
memcpy(data, (uint8_t *)lane1 + offset, length);
}
#else
unsigned int i;
lane >>= offset * 8;
for (i = 0; i < length; i++) {
data[i] = lane & 0xFF;
lane >>= 8;
}
#endif
}
/* ---------------------------------------------------------------- */
#if (PLATFORM_BYTE_ORDER != IS_LITTLE_ENDIAN)
static void fromWordToBytes(uint8_t *bytes, const uint64_t word) {
unsigned int i;
for (i = 0; i < (64 / 8); i++) {
bytes[i] = (word >> (8 * i)) & 0xFF;
}
}
#endif
void KeccakP1600_ExtractLanes(const void *state, unsigned char *data, unsigned int laneCount) {
#if (PLATFORM_BYTE_ORDER == IS_LITTLE_ENDIAN)
memcpy(data, state, laneCount * 8);
#else
for (unsigned int i = 0; i < laneCount; i++) {
fromWordToBytes(data + (i * 8), ((const uint64_t *)state)[i]);
}
#endif
#define COMPL(lane) for(unsigned int i=0; i<8; i++) data[8*lane+i] = ~data[8*lane+i]
if (laneCount > 1) {
COMPL(1);
if (laneCount > 2) {
COMPL(2);
if (laneCount > 8) {
COMPL(8);
if (laneCount > 12) {
COMPL(12);
if (laneCount > 17) {
COMPL(17);
if (laneCount > 20) {
COMPL(20);
}
}
}
}
}
}
#undef COMPL
}
/* ---------------------------------------------------------------- */
void KeccakP1600_ExtractBytes(const void *state, unsigned char *data, unsigned int offset, unsigned int length) {
SnP_ExtractBytes(state, data, offset, length, KeccakP1600_ExtractLanes, KeccakP1600_ExtractBytesInLane, 8);
}
/* ---------------------------------------------------------------- */
void KeccakP1600_ExtractAndAddBytesInLane(const void *state, unsigned int lanePosition, const unsigned char *input, unsigned char *output, unsigned int offset, unsigned int length) {
uint64_t lane = ((const uint64_t *)state)[lanePosition];
if ((lanePosition == 1) || (lanePosition == 2) || (lanePosition == 8) || (lanePosition == 12) || (lanePosition == 17) || (lanePosition == 20)) {
lane = ~lane;
}
#if (PLATFORM_BYTE_ORDER == IS_LITTLE_ENDIAN)
{
unsigned int i;
for (i = 0; i < length; i++) {
output[i] = input[i] ^ ((uint8_t *)&lane)[offset + i];
}
}
#else
unsigned int i;
lane >>= offset * 8;
for (i = 0; i < length; i++) {
output[i] = input[i] ^ (lane & 0xFF);
lane >>= 8;
}
#endif
}
/* ---------------------------------------------------------------- */
void KeccakP1600_ExtractAndAddLanes(const void *state, const unsigned char *input, unsigned char *output, unsigned int laneCount) {
unsigned int i;
#if (PLATFORM_BYTE_ORDER != IS_LITTLE_ENDIAN)
unsigned char temp[8];
unsigned int j;
#else
uint64_t lane;
#endif
for (i = 0; i < laneCount; i++) {
#if (PLATFORM_BYTE_ORDER == IS_LITTLE_ENDIAN)
memcpy(&lane, input + 8 * i, sizeof(uint64_t));
lane ^= ((const uint64_t *)state)[i];
memcpy(output + 8 * i, &lane, sizeof(uint64_t));
#else
fromWordToBytes(temp, ((const uint64_t *)state)[i]);
for (j = 0; j < 8; j++) {
output[i * 8 + j] = input[i * 8 + j] ^ temp[j];
}
#endif
}
#define COMPL(lane) for(i=0; i<8; i++) output[8*lane+i] = ~output[8*lane+i]
if (laneCount > 1) {
COMPL(1);
if (laneCount > 2) {
COMPL(2);
if (laneCount > 8) {
COMPL(8);
if (laneCount > 12) {
COMPL(12);
if (laneCount > 17) {
COMPL(17);
if (laneCount > 20) {
COMPL(20);
}
}
}
}
}
}
#undef COMPL
}
/* ---------------------------------------------------------------- */
void KeccakP1600_ExtractAndAddBytes(const void *state, const unsigned char *input, unsigned char *output, unsigned int offset, unsigned int length) {
SnP_ExtractAndAddBytes(state, input, output, offset, length, KeccakP1600_ExtractAndAddLanes, KeccakP1600_ExtractAndAddBytesInLane, 8);
}
/* ---------------------------------------------------------------- */
size_t KeccakF1600_FastLoop_Absorb(void *state, unsigned int laneCount, const unsigned char *data, size_t dataByteLen) {
size_t originalDataByteLen = dataByteLen;
declareABCDE
uint64_t *stateAsLanes = (uint64_t *)state;
copyFromState(A, stateAsLanes)
while (dataByteLen >= laneCount * 8) {
addInput(A, data, laneCount)
rounds24
data += laneCount * 8;
dataByteLen -= laneCount * 8;
}
copyToState(stateAsLanes, A)
return originalDataByteLen - dataByteLen;
}
/* ---------------------------------------------------------------- */
size_t KeccakP1600_12rounds_FastLoop_Absorb(void *state, unsigned int laneCount, const unsigned char *data, size_t dataByteLen) {
size_t originalDataByteLen = dataByteLen;
declareABCDE
uint64_t *stateAsLanes = (uint64_t *)state;
copyFromState(A, stateAsLanes)
while (dataByteLen >= laneCount * 8) {
addInput(A, data, laneCount)
rounds12
data += laneCount * 8;
dataByteLen -= laneCount * 8;
}
copyToState(stateAsLanes, A)
return originalDataByteLen - dataByteLen;
}

View file

@ -0,0 +1,305 @@
/*
The eXtended Keccak Code Package (XKCP)
https://github.com/XKCP/XKCP
The Keccak-p permutations, designed by Guido Bertoni, Joan Daemen, Michaël Peeters and Gilles Van Assche.
Implementation by Gilles Van Assche and Ronny Van Keer, hereby denoted as "the implementer".
For more information, feedback or questions, please refer to the Keccak Team website:
https://keccak.team/
To the extent possible under law, the implementer has waived all copyright
and related or neighboring rights to the source code in this file.
http://creativecommons.org/publicdomain/zero/1.0/
*/
#if (defined(FullUnrolling))
#define rounds24 \
prepareTheta \
thetaRhoPiChiIotaPrepareTheta( 0, A, E) \
thetaRhoPiChiIotaPrepareTheta( 1, E, A) \
thetaRhoPiChiIotaPrepareTheta( 2, A, E) \
thetaRhoPiChiIotaPrepareTheta( 3, E, A) \
thetaRhoPiChiIotaPrepareTheta( 4, A, E) \
thetaRhoPiChiIotaPrepareTheta( 5, E, A) \
thetaRhoPiChiIotaPrepareTheta( 6, A, E) \
thetaRhoPiChiIotaPrepareTheta( 7, E, A) \
thetaRhoPiChiIotaPrepareTheta( 8, A, E) \
thetaRhoPiChiIotaPrepareTheta( 9, E, A) \
thetaRhoPiChiIotaPrepareTheta(10, A, E) \
thetaRhoPiChiIotaPrepareTheta(11, E, A) \
thetaRhoPiChiIotaPrepareTheta(12, A, E) \
thetaRhoPiChiIotaPrepareTheta(13, E, A) \
thetaRhoPiChiIotaPrepareTheta(14, A, E) \
thetaRhoPiChiIotaPrepareTheta(15, E, A) \
thetaRhoPiChiIotaPrepareTheta(16, A, E) \
thetaRhoPiChiIotaPrepareTheta(17, E, A) \
thetaRhoPiChiIotaPrepareTheta(18, A, E) \
thetaRhoPiChiIotaPrepareTheta(19, E, A) \
thetaRhoPiChiIotaPrepareTheta(20, A, E) \
thetaRhoPiChiIotaPrepareTheta(21, E, A) \
thetaRhoPiChiIotaPrepareTheta(22, A, E) \
thetaRhoPiChiIota(23, E, A) \
#define rounds12 \
prepareTheta \
thetaRhoPiChiIotaPrepareTheta(12, A, E) \
thetaRhoPiChiIotaPrepareTheta(13, E, A) \
thetaRhoPiChiIotaPrepareTheta(14, A, E) \
thetaRhoPiChiIotaPrepareTheta(15, E, A) \
thetaRhoPiChiIotaPrepareTheta(16, A, E) \
thetaRhoPiChiIotaPrepareTheta(17, E, A) \
thetaRhoPiChiIotaPrepareTheta(18, A, E) \
thetaRhoPiChiIotaPrepareTheta(19, E, A) \
thetaRhoPiChiIotaPrepareTheta(20, A, E) \
thetaRhoPiChiIotaPrepareTheta(21, E, A) \
thetaRhoPiChiIotaPrepareTheta(22, A, E) \
thetaRhoPiChiIota(23, E, A) \
#define rounds6 \
prepareTheta \
thetaRhoPiChiIotaPrepareTheta(18, A, E) \
thetaRhoPiChiIotaPrepareTheta(19, E, A) \
thetaRhoPiChiIotaPrepareTheta(20, A, E) \
thetaRhoPiChiIotaPrepareTheta(21, E, A) \
thetaRhoPiChiIotaPrepareTheta(22, A, E) \
thetaRhoPiChiIota(23, E, A) \
#define rounds4 \
prepareTheta \
thetaRhoPiChiIotaPrepareTheta(20, A, E) \
thetaRhoPiChiIotaPrepareTheta(21, E, A) \
thetaRhoPiChiIotaPrepareTheta(22, A, E) \
thetaRhoPiChiIota(23, E, A) \
#elif (Unrolling == 12)
#define rounds24 \
prepareTheta \
for(i=0; i<24; i+=12) { \
thetaRhoPiChiIotaPrepareTheta(i , A, E) \
thetaRhoPiChiIotaPrepareTheta(i+ 1, E, A) \
thetaRhoPiChiIotaPrepareTheta(i+ 2, A, E) \
thetaRhoPiChiIotaPrepareTheta(i+ 3, E, A) \
thetaRhoPiChiIotaPrepareTheta(i+ 4, A, E) \
thetaRhoPiChiIotaPrepareTheta(i+ 5, E, A) \
thetaRhoPiChiIotaPrepareTheta(i+ 6, A, E) \
thetaRhoPiChiIotaPrepareTheta(i+ 7, E, A) \
thetaRhoPiChiIotaPrepareTheta(i+ 8, A, E) \
thetaRhoPiChiIotaPrepareTheta(i+ 9, E, A) \
thetaRhoPiChiIotaPrepareTheta(i+10, A, E) \
thetaRhoPiChiIotaPrepareTheta(i+11, E, A) \
} \
#define rounds12 \
prepareTheta \
thetaRhoPiChiIotaPrepareTheta(12, A, E) \
thetaRhoPiChiIotaPrepareTheta(13, E, A) \
thetaRhoPiChiIotaPrepareTheta(14, A, E) \
thetaRhoPiChiIotaPrepareTheta(15, E, A) \
thetaRhoPiChiIotaPrepareTheta(16, A, E) \
thetaRhoPiChiIotaPrepareTheta(17, E, A) \
thetaRhoPiChiIotaPrepareTheta(18, A, E) \
thetaRhoPiChiIotaPrepareTheta(19, E, A) \
thetaRhoPiChiIotaPrepareTheta(20, A, E) \
thetaRhoPiChiIotaPrepareTheta(21, E, A) \
thetaRhoPiChiIotaPrepareTheta(22, A, E) \
thetaRhoPiChiIota(23, E, A) \
#define rounds6 \
prepareTheta \
thetaRhoPiChiIotaPrepareTheta(18, A, E) \
thetaRhoPiChiIotaPrepareTheta(19, E, A) \
thetaRhoPiChiIotaPrepareTheta(20, A, E) \
thetaRhoPiChiIotaPrepareTheta(21, E, A) \
thetaRhoPiChiIotaPrepareTheta(22, A, E) \
thetaRhoPiChiIota(23, E, A) \
#define rounds4 \
prepareTheta \
thetaRhoPiChiIotaPrepareTheta(20, A, E) \
thetaRhoPiChiIotaPrepareTheta(21, E, A) \
thetaRhoPiChiIotaPrepareTheta(22, A, E) \
thetaRhoPiChiIota(23, E, A) \
#elif (Unrolling == 6)
#define rounds24 \
prepareTheta \
for(i=0; i<24; i+=6) { \
thetaRhoPiChiIotaPrepareTheta(i , A, E) \
thetaRhoPiChiIotaPrepareTheta(i+1, E, A) \
thetaRhoPiChiIotaPrepareTheta(i+2, A, E) \
thetaRhoPiChiIotaPrepareTheta(i+3, E, A) \
thetaRhoPiChiIotaPrepareTheta(i+4, A, E) \
thetaRhoPiChiIotaPrepareTheta(i+5, E, A) \
} \
#define rounds12 \
prepareTheta \
for(i=12; i<24; i+=6) { \
thetaRhoPiChiIotaPrepareTheta(i , A, E) \
thetaRhoPiChiIotaPrepareTheta(i+1, E, A) \
thetaRhoPiChiIotaPrepareTheta(i+2, A, E) \
thetaRhoPiChiIotaPrepareTheta(i+3, E, A) \
thetaRhoPiChiIotaPrepareTheta(i+4, A, E) \
thetaRhoPiChiIotaPrepareTheta(i+5, E, A) \
} \
#define rounds6 \
prepareTheta \
thetaRhoPiChiIotaPrepareTheta(18, A, E) \
thetaRhoPiChiIotaPrepareTheta(19, E, A) \
thetaRhoPiChiIotaPrepareTheta(20, A, E) \
thetaRhoPiChiIotaPrepareTheta(21, E, A) \
thetaRhoPiChiIotaPrepareTheta(22, A, E) \
thetaRhoPiChiIota(23, E, A) \
#define rounds4 \
prepareTheta \
thetaRhoPiChiIotaPrepareTheta(20, A, E) \
thetaRhoPiChiIotaPrepareTheta(21, E, A) \
thetaRhoPiChiIotaPrepareTheta(22, A, E) \
thetaRhoPiChiIota(23, E, A) \
#elif (Unrolling == 4)
#define rounds24 \
prepareTheta \
for(i=0; i<24; i+=4) { \
thetaRhoPiChiIotaPrepareTheta(i , A, E) \
thetaRhoPiChiIotaPrepareTheta(i+1, E, A) \
thetaRhoPiChiIotaPrepareTheta(i+2, A, E) \
thetaRhoPiChiIotaPrepareTheta(i+3, E, A) \
} \
#define rounds12 \
prepareTheta \
for(i=12; i<24; i+=4) { \
thetaRhoPiChiIotaPrepareTheta(i , A, E) \
thetaRhoPiChiIotaPrepareTheta(i+1, E, A) \
thetaRhoPiChiIotaPrepareTheta(i+2, A, E) \
thetaRhoPiChiIotaPrepareTheta(i+3, E, A) \
} \
#define rounds6 \
prepareTheta \
for(i=18; i<24; i+=2) { \
thetaRhoPiChiIotaPrepareTheta(i , A, E) \
thetaRhoPiChiIotaPrepareTheta(i+1, E, A) \
} \
#define rounds4 \
prepareTheta \
thetaRhoPiChiIotaPrepareTheta(20, A, E) \
thetaRhoPiChiIotaPrepareTheta(21, E, A) \
thetaRhoPiChiIotaPrepareTheta(22, A, E) \
thetaRhoPiChiIota(23, E, A) \
#elif (Unrolling == 3)
#define rounds24 \
prepareTheta \
for(i=0; i<24; i+=3) { \
thetaRhoPiChiIotaPrepareTheta(i , A, E) \
thetaRhoPiChiIotaPrepareTheta(i+1, E, A) \
thetaRhoPiChiIotaPrepareTheta(i+2, A, E) \
copyStateVariables(A, E) \
} \
#define rounds12 \
prepareTheta \
for(i=12; i<24; i+=3) { \
thetaRhoPiChiIotaPrepareTheta(i , A, E) \
thetaRhoPiChiIotaPrepareTheta(i+1, E, A) \
thetaRhoPiChiIotaPrepareTheta(i+2, A, E) \
copyStateVariables(A, E) \
} \
#define rounds6 \
prepareTheta \
for(i=18; i<24; i+=3) { \
thetaRhoPiChiIotaPrepareTheta(i , A, E) \
thetaRhoPiChiIotaPrepareTheta(i+1, E, A) \
thetaRhoPiChiIotaPrepareTheta(i+2, A, E) \
copyStateVariables(A, E) \
} \
#define rounds4 \
prepareTheta \
for(i=20; i<24; i+=2) { \
thetaRhoPiChiIotaPrepareTheta(i , A, E) \
thetaRhoPiChiIotaPrepareTheta(i+1, E, A) \
} \
#elif (Unrolling == 2)
#define rounds24 \
prepareTheta \
for(i=0; i<24; i+=2) { \
thetaRhoPiChiIotaPrepareTheta(i , A, E) \
thetaRhoPiChiIotaPrepareTheta(i+1, E, A) \
} \
#define rounds12 \
prepareTheta \
for(i=12; i<24; i+=2) { \
thetaRhoPiChiIotaPrepareTheta(i , A, E) \
thetaRhoPiChiIotaPrepareTheta(i+1, E, A) \
} \
#define rounds6 \
prepareTheta \
for(i=18; i<24; i+=2) { \
thetaRhoPiChiIotaPrepareTheta(i , A, E) \
thetaRhoPiChiIotaPrepareTheta(i+1, E, A) \
} \
#define rounds4 \
prepareTheta \
for(i=20; i<24; i+=2) { \
thetaRhoPiChiIotaPrepareTheta(i , A, E) \
thetaRhoPiChiIotaPrepareTheta(i+1, E, A) \
} \
#elif (Unrolling == 1)
#define rounds24 \
prepareTheta \
for(i=0; i<24; i++) { \
thetaRhoPiChiIotaPrepareTheta(i , A, E) \
copyStateVariables(A, E) \
} \
#define rounds12 \
prepareTheta \
for(i=12; i<24; i++) { \
thetaRhoPiChiIotaPrepareTheta(i , A, E) \
copyStateVariables(A, E) \
} \
#define rounds6 \
prepareTheta \
for(i=18; i<24; i++) { \
thetaRhoPiChiIotaPrepareTheta(i , A, E) \
copyStateVariables(A, E) \
} \
#define rounds4 \
prepareTheta \
for(i=20; i<24; i++) { \
thetaRhoPiChiIotaPrepareTheta(i , A, E) \
copyStateVariables(A, E) \
} \
#else
#error "Unrolling is not correctly specified!"
#endif
#define roundsN(__nrounds) \
prepareTheta \
i = 24 - (__nrounds); \
if ((i&1) != 0) { \
thetaRhoPiChiIotaPrepareTheta(i, A, E) \
copyStateVariables(A, E) \
++i; \
} \
for( /* empty */; i<24; i+=2) { \
thetaRhoPiChiIotaPrepareTheta(i , A, E) \
thetaRhoPiChiIotaPrepareTheta(i+1, E, A) \
}

View file

@ -0,0 +1,141 @@
/*
The eXtended Keccak Code Package (XKCP)
https://github.com/XKCP/XKCP
Implementation by Gilles Van Assche and Ronny Van Keer, hereby denoted as "the implementer".
For more information, feedback or questions, please refer to the Keccak Team website:
https://keccak.team/
To the extent possible under law, the implementer has waived all copyright
and related or neighboring rights to the source code in this file.
http://creativecommons.org/publicdomain/zero/1.0/
---
This file contains macros that help implement a permutation in a SnP-compatible way.
It converts an implementation that implement state input/output functions
in a lane-oriented fashion (i.e., using SnP_AddLanes() and SnP_AddBytesInLane,
and similarly for Overwite, Extract and ExtractAndAdd) to the byte-oriented SnP.
Please refer to SnP-documentation.h for more details.
*/
#ifndef _SnP_Relaned_h_
#define _SnP_Relaned_h_
#define SnP_AddBytes(state, data, offset, length, SnP_AddLanes, SnP_AddBytesInLane, SnP_laneLengthInBytes) \
{ \
if ((offset) == 0) { \
SnP_AddLanes(state, data, (length)/SnP_laneLengthInBytes); \
SnP_AddBytesInLane(state, \
(length)/SnP_laneLengthInBytes, \
(data)+((length)/SnP_laneLengthInBytes)*SnP_laneLengthInBytes, \
0, \
(length)%SnP_laneLengthInBytes); \
} \
else { \
unsigned int _sizeLeft = (length); \
unsigned int _lanePosition = (offset)/SnP_laneLengthInBytes; \
unsigned int _offsetInLane = (offset)%SnP_laneLengthInBytes; \
const unsigned char *_curData = (data); \
while(_sizeLeft > 0) { \
unsigned int _bytesInLane = SnP_laneLengthInBytes - _offsetInLane; \
if (_bytesInLane > _sizeLeft) \
_bytesInLane = _sizeLeft; \
SnP_AddBytesInLane(state, _lanePosition, _curData, _offsetInLane, _bytesInLane); \
_sizeLeft -= _bytesInLane; \
_lanePosition++; \
_offsetInLane = 0; \
_curData += _bytesInLane; \
} \
} \
}
#define SnP_OverwriteBytes(state, data, offset, length, SnP_OverwriteLanes, SnP_OverwriteBytesInLane, SnP_laneLengthInBytes) \
{ \
if ((offset) == 0) { \
SnP_OverwriteLanes(state, data, (length)/SnP_laneLengthInBytes); \
SnP_OverwriteBytesInLane(state, \
(length)/SnP_laneLengthInBytes, \
(data)+((length)/SnP_laneLengthInBytes)*SnP_laneLengthInBytes, \
0, \
(length)%SnP_laneLengthInBytes); \
} \
else { \
unsigned int _sizeLeft = (length); \
unsigned int _lanePosition = (offset)/SnP_laneLengthInBytes; \
unsigned int _offsetInLane = (offset)%SnP_laneLengthInBytes; \
const unsigned char *_curData = (data); \
while(_sizeLeft > 0) { \
unsigned int _bytesInLane = SnP_laneLengthInBytes - _offsetInLane; \
if (_bytesInLane > _sizeLeft) \
_bytesInLane = _sizeLeft; \
SnP_OverwriteBytesInLane(state, _lanePosition, _curData, _offsetInLane, _bytesInLane); \
_sizeLeft -= _bytesInLane; \
_lanePosition++; \
_offsetInLane = 0; \
_curData += _bytesInLane; \
} \
} \
}
#define SnP_ExtractBytes(state, data, offset, length, SnP_ExtractLanes, SnP_ExtractBytesInLane, SnP_laneLengthInBytes) \
{ \
if ((offset) == 0) { \
SnP_ExtractLanes(state, data, (length)/SnP_laneLengthInBytes); \
SnP_ExtractBytesInLane(state, \
(length)/SnP_laneLengthInBytes, \
(data)+((length)/SnP_laneLengthInBytes)*SnP_laneLengthInBytes, \
0, \
(length)%SnP_laneLengthInBytes); \
} \
else { \
unsigned int _sizeLeft = (length); \
unsigned int _lanePosition = (offset)/SnP_laneLengthInBytes; \
unsigned int _offsetInLane = (offset)%SnP_laneLengthInBytes; \
unsigned char *_curData = (data); \
while(_sizeLeft > 0) { \
unsigned int _bytesInLane = SnP_laneLengthInBytes - _offsetInLane; \
if (_bytesInLane > _sizeLeft) \
_bytesInLane = _sizeLeft; \
SnP_ExtractBytesInLane(state, _lanePosition, _curData, _offsetInLane, _bytesInLane); \
_sizeLeft -= _bytesInLane; \
_lanePosition++; \
_offsetInLane = 0; \
_curData += _bytesInLane; \
} \
} \
}
#define SnP_ExtractAndAddBytes(state, input, output, offset, length, SnP_ExtractAndAddLanes, SnP_ExtractAndAddBytesInLane, SnP_laneLengthInBytes) \
{ \
if ((offset) == 0) { \
SnP_ExtractAndAddLanes(state, input, output, (length)/SnP_laneLengthInBytes); \
SnP_ExtractAndAddBytesInLane(state, \
(length)/SnP_laneLengthInBytes, \
(input)+((length)/SnP_laneLengthInBytes)*SnP_laneLengthInBytes, \
(output)+((length)/SnP_laneLengthInBytes)*SnP_laneLengthInBytes, \
0, \
(length)%SnP_laneLengthInBytes); \
} \
else { \
unsigned int _sizeLeft = (length); \
unsigned int _lanePosition = (offset)/SnP_laneLengthInBytes; \
unsigned int _offsetInLane = (offset)%SnP_laneLengthInBytes; \
const unsigned char *_curInput = (input); \
unsigned char *_curOutput = (output); \
while(_sizeLeft > 0) { \
unsigned int _bytesInLane = SnP_laneLengthInBytes - _offsetInLane; \
if (_bytesInLane > _sizeLeft) \
_bytesInLane = _sizeLeft; \
SnP_ExtractAndAddBytesInLane(state, _lanePosition, _curInput, _curOutput, _offsetInLane, _bytesInLane); \
_sizeLeft -= _bytesInLane; \
_lanePosition++; \
_offsetInLane = 0; \
_curInput += _bytesInLane; \
_curOutput += _bytesInLane; \
} \
} \
}
#endif

View file

@ -0,0 +1,121 @@
/*
---------------------------------------------------------------------------
Copyright (c) 1998-2008, Brian Gladman, Worcester, UK. All rights reserved.
LICENSE TERMS
The redistribution and use of this software (with or without changes)
is allowed without the payment of fees or royalties provided that:
1. source code distributions include the above copyright notice, this
list of conditions and the following disclaimer;
2. binary distributions include the above copyright notice, this list
of conditions and the following disclaimer in their documentation;
3. the name of the copyright holder is not used to endorse products
built using this software without specific written permission.
DISCLAIMER
This software is provided 'as is' with no explicit or implied warranties
in respect of its properties, including, but not limited to, correctness
and/or fitness for purpose.
---------------------------------------------------------------------------
Issue Date: 20/12/2007
Changes for ARM 9/9/2010
*/
#ifndef _BRG_ENDIAN_H
#define _BRG_ENDIAN_H
#define IS_BIG_ENDIAN 4321 /* byte 0 is most significant (mc68k) */
#define IS_LITTLE_ENDIAN 1234 /* byte 0 is least significant (i386) */
/* Now attempt to set the define for platform byte order using any */
/* of the four forms SYMBOL, _SYMBOL, __SYMBOL & __SYMBOL__, which */
/* seem to encompass most endian symbol definitions */
#if defined( BIG_ENDIAN ) && defined( LITTLE_ENDIAN )
# if defined( BYTE_ORDER ) && BYTE_ORDER == BIG_ENDIAN
# define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN
# elif defined( BYTE_ORDER ) && BYTE_ORDER == LITTLE_ENDIAN
# define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN
# endif
#elif defined( BIG_ENDIAN )
# define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN
#elif defined( LITTLE_ENDIAN )
# define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN
#endif
#if defined( _BIG_ENDIAN ) && defined( _LITTLE_ENDIAN )
# if defined( _BYTE_ORDER ) && _BYTE_ORDER == _BIG_ENDIAN
# define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN
# elif defined( _BYTE_ORDER ) && _BYTE_ORDER == _LITTLE_ENDIAN
# define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN
# endif
#elif defined( _BIG_ENDIAN )
# define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN
#elif defined( _LITTLE_ENDIAN )
# define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN
#endif
#if defined( __BIG_ENDIAN ) && defined( __LITTLE_ENDIAN )
# if defined( __BYTE_ORDER ) && __BYTE_ORDER == __BIG_ENDIAN
# define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN
# elif defined( __BYTE_ORDER ) && __BYTE_ORDER == __LITTLE_ENDIAN
# define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN
# endif
#elif defined( __BIG_ENDIAN )
# define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN
#elif defined( __LITTLE_ENDIAN )
# define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN
#endif
#if defined( __BIG_ENDIAN__ ) && defined( __LITTLE_ENDIAN__ )
# if defined( __BYTE_ORDER__ ) && __BYTE_ORDER__ == __BIG_ENDIAN__
# define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN
# elif defined( __BYTE_ORDER__ ) && __BYTE_ORDER__ == __LITTLE_ENDIAN__
# define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN
# endif
#elif defined( __BIG_ENDIAN__ )
# define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN
#elif defined( __LITTLE_ENDIAN__ )
# define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN
#endif
/* if the platform byte order could not be determined, then try to */
/* set this define using common machine defines */
#if !defined(PLATFORM_BYTE_ORDER)
#if defined( __alpha__ ) || defined( __alpha ) || defined( i386 ) || \
defined( __i386__ ) || defined( _M_I86 ) || defined( _M_IX86 ) || \
defined( __OS2__ ) || defined( sun386 ) || defined( __TURBOC__ ) || \
defined( vax ) || defined( vms ) || defined( VMS ) || \
defined( __VMS ) || defined( _M_X64 )
# define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN
#elif defined( AMIGA ) || defined( applec ) || defined( __AS400__ ) || \
defined( _CRAY ) || defined( __hppa ) || defined( __hp9000 ) || \
defined( ibm370 ) || defined( mc68000 ) || defined( m68k ) || \
defined( __MRC__ ) || defined( __MVS__ ) || defined( __MWERKS__ ) || \
defined( sparc ) || defined( __sparc) || defined( SYMANTEC_C ) || \
defined( __VOS__ ) || defined( __TIGCC__ ) || defined( __TANDEM ) || \
defined( THINK_C ) || defined( __VMCMS__ ) || defined( _AIX ) || \
defined( __s390__ ) || defined( __s390x__ ) || defined( __zarch__ )
# define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN
#elif defined(__arm__)
# ifdef __BIG_ENDIAN
# define PLATFORM_BYTE_ORDER IS_BIG_ENDIAN
# else
# define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN
# endif
#else
# define PLATFORM_BYTE_ORDER IS_LITTLE_ENDIAN
#endif
#endif
#endif

View file

@ -0,0 +1,388 @@
/**
* \file sha3_xkcp.c
* \brief Implementation of the OQS SHA3 API using the XKCP low interface.
* The high level keccak_absorb, squeezeblocks, etc. are based on fips202.c
* from PQClean (https://github.com/PQClean/PQClean/tree/master/common)
*
* SPDX-License-Identifier: MIT
*/
#include "sha3.h"
#include "xkcp_dispatch.h"
#include <oqs/common.h>
#include <stddef.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#define KECCAK_CTX_ALIGNMENT 32
#define _KECCAK_CTX_BYTES (200+sizeof(uint64_t))
#define KECCAK_CTX_BYTES (KECCAK_CTX_ALIGNMENT * \
((_KECCAK_CTX_BYTES + KECCAK_CTX_ALIGNMENT - 1)/KECCAK_CTX_ALIGNMENT))
/* The first call to Keccak_Initialize will be routed through dispatch, which
* updates all of the function pointers used below.
*/
static KeccakInitFn Keccak_Dispatch;
static KeccakInitFn *Keccak_Initialize_ptr = &Keccak_Dispatch;
static KeccakAddByteFn *Keccak_AddByte_ptr = NULL;
static KeccakAddBytesFn *Keccak_AddBytes_ptr = NULL;
static KeccakPermuteFn *Keccak_Permute_ptr = NULL;
static KeccakExtractBytesFn *Keccak_ExtractBytes_ptr = NULL;
static KeccakFastLoopAbsorbFn *Keccak_FastLoopAbsorb_ptr = NULL;
static void Keccak_Dispatch(void *state) {
// TODO: Simplify this when we have a Windows-compatible AVX2 implementation of SHA3
#if defined(OQS_DIST_X86_64_BUILD)
#if defined(OQS_ENABLE_SHA3_xkcp_low_avx2)
if (OQS_CPU_has_extension(OQS_CPU_EXT_AVX2)) {
Keccak_Initialize_ptr = &KeccakP1600_Initialize_avx2;
Keccak_AddByte_ptr = &KeccakP1600_AddByte_avx2;
Keccak_AddBytes_ptr = &KeccakP1600_AddBytes_avx2;
Keccak_Permute_ptr = &KeccakP1600_Permute_24rounds_avx2;
Keccak_ExtractBytes_ptr = &KeccakP1600_ExtractBytes_avx2;
Keccak_FastLoopAbsorb_ptr = &KeccakF1600_FastLoop_Absorb_avx2;
} else {
Keccak_Initialize_ptr = &KeccakP1600_Initialize_plain64;
Keccak_AddByte_ptr = &KeccakP1600_AddByte_plain64;
Keccak_AddBytes_ptr = &KeccakP1600_AddBytes_plain64;
Keccak_Permute_ptr = &KeccakP1600_Permute_24rounds_plain64;
Keccak_ExtractBytes_ptr = &KeccakP1600_ExtractBytes_plain64;
Keccak_FastLoopAbsorb_ptr = &KeccakF1600_FastLoop_Absorb_plain64;
}
#else // Windows
Keccak_Initialize_ptr = &KeccakP1600_Initialize_plain64;
Keccak_AddByte_ptr = &KeccakP1600_AddByte_plain64;
Keccak_AddBytes_ptr = &KeccakP1600_AddBytes_plain64;
Keccak_Permute_ptr = &KeccakP1600_Permute_24rounds_plain64;
Keccak_ExtractBytes_ptr = &KeccakP1600_ExtractBytes_plain64;
Keccak_FastLoopAbsorb_ptr = &KeccakF1600_FastLoop_Absorb_plain64;
#endif
#else
Keccak_Initialize_ptr = &KeccakP1600_Initialize;
Keccak_AddByte_ptr = &KeccakP1600_AddByte;
Keccak_AddBytes_ptr = &KeccakP1600_AddBytes;
Keccak_Permute_ptr = &KeccakP1600_Permute_24rounds;
Keccak_ExtractBytes_ptr = &KeccakP1600_ExtractBytes;
Keccak_FastLoopAbsorb_ptr = &KeccakF1600_FastLoop_Absorb;
#endif
(*Keccak_Initialize_ptr)(state);
}
/*************************************************
* Name: keccak_inc_reset
*
* Description: Initializes the incremental Keccak state to zero.
*
* Arguments: - uint64_t *s: pointer to input/output incremental state
* First 25 values represent Keccak state.
* 26th value represents either the number of absorbed bytes
* that have not been permuted, or not-yet-squeezed bytes.
**************************************************/
static void keccak_inc_reset(uint64_t *s) {
(*Keccak_Initialize_ptr)(s);
s[25] = 0;
}
/*************************************************
* Name: keccak_inc_absorb
*
* Description: Incremental keccak absorb
* Preceded by keccak_inc_reset, succeeded by keccak_inc_finalize
*
* Arguments: - uint64_t *s: pointer to input/output incremental state
* First 25 values represent Keccak state.
* 26th value represents either the number of absorbed bytes
* that have not been permuted, or not-yet-squeezed bytes.
* - uint32_t r: rate in bytes (e.g., 168 for SHAKE128)
* - const uint8_t *m: pointer to input to be absorbed into s
* - size_t mlen: length of input in bytes
**************************************************/
static void keccak_inc_absorb(uint64_t *s, uint32_t r, const uint8_t *m,
size_t mlen) {
uint64_t c = r - s[25];
if (s[25] && mlen >= c) {
(*Keccak_AddBytes_ptr)(s, m, (unsigned int)s[25], (unsigned int)c);
(*Keccak_Permute_ptr)(s);
mlen -= c;
m += c;
s[25] = 0;
}
#ifdef KeccakF1600_FastLoop_supported
if (mlen >= r) {
c = (*Keccak_FastLoop_Absorb_ptr)(s, r / 8, m, mlen);
mlen -= c;
m += c;
}
#else
while (mlen >= r) {
(*Keccak_AddBytes_ptr)(s, m, 0, r);
(*Keccak_Permute_ptr)(s);
mlen -= r;
m += r;
}
#endif
(*Keccak_AddBytes_ptr)(s, m, (unsigned int)s[25], (unsigned int)mlen);
s[25] += mlen;
}
/*************************************************
* Name: keccak_inc_finalize
*
* Description: Finalizes Keccak absorb phase, prepares for squeezing
*
* Arguments: - uint64_t *s: pointer to input/output incremental state
* First 25 values represent Keccak state.
* 26th value represents either the number of absorbed bytes
* that have not been permuted, or not-yet-squeezed bytes.
* - uint32_t r: rate in bytes (e.g., 168 for SHAKE128)
* - uint8_t p: domain-separation byte for different
* Keccak-derived functions
**************************************************/
static void keccak_inc_finalize(uint64_t *s, uint32_t r, uint8_t p) {
/* After keccak_inc_absorb, we are guaranteed that s[25] < r,
so we can always use one more byte for p in the current state. */
(*Keccak_AddByte_ptr)(s, p, (unsigned int)s[25]);
(*Keccak_AddByte_ptr)(s, 0x80, (unsigned int)(r - 1));
s[25] = 0;
}
/*************************************************
* Name: keccak_inc_squeeze
*
* Description: Incremental Keccak squeeze; can be called on byte-level
*
* Arguments: - uint8_t *h: pointer to output bytes
* - size_t outlen: number of bytes to be squeezed
* - uint64_t *s: pointer to input/output incremental state
* First 25 values represent Keccak state.
* 26th value represents either the number of absorbed bytes
* that have not been permuted, or not-yet-squeezed bytes.
* - uint32_t r: rate in bytes (e.g., 168 for SHAKE128)
**************************************************/
static void keccak_inc_squeeze(uint8_t *h, size_t outlen,
uint64_t *s, uint32_t r) {
while (outlen > s[25]) {
(*Keccak_ExtractBytes_ptr)(s, h, (unsigned int)(r - s[25]), (unsigned int)s[25]);
(*Keccak_Permute_ptr)(s);
h += s[25];
outlen -= s[25];
s[25] = r;
}
(*Keccak_ExtractBytes_ptr)(s, h, (unsigned int)(r - s[25]), (unsigned int)outlen);
s[25] -= outlen;
}
/* SHA3-256 */
void OQS_SHA3_sha3_256(uint8_t *output, const uint8_t *input, size_t inlen) {
OQS_SHA3_sha3_256_inc_ctx s;
OQS_SHA3_sha3_256_inc_init(&s);
OQS_SHA3_sha3_256_inc_absorb(&s, input, inlen);
OQS_SHA3_sha3_256_inc_finalize(output, &s);
OQS_SHA3_sha3_256_inc_ctx_release(&s);
}
void OQS_SHA3_sha3_256_inc_init(OQS_SHA3_sha3_256_inc_ctx *state) {
state->ctx = OQS_MEM_aligned_alloc(KECCAK_CTX_ALIGNMENT, KECCAK_CTX_BYTES);
if (state->ctx == NULL) {
exit(111);
}
keccak_inc_reset((uint64_t *)state->ctx);
}
void OQS_SHA3_sha3_256_inc_absorb(OQS_SHA3_sha3_256_inc_ctx *state, const uint8_t *input, size_t inlen) {
keccak_inc_absorb((uint64_t *)state->ctx, OQS_SHA3_SHA3_256_RATE, input, inlen);
}
void OQS_SHA3_sha3_256_inc_finalize(uint8_t *output, OQS_SHA3_sha3_256_inc_ctx *state) {
keccak_inc_finalize((uint64_t *)state->ctx, OQS_SHA3_SHA3_256_RATE, 0x06);
keccak_inc_squeeze(output, 32, (uint64_t *)state->ctx, OQS_SHA3_SHA3_256_RATE);
}
void OQS_SHA3_sha3_256_inc_ctx_release(OQS_SHA3_sha3_256_inc_ctx *state) {
OQS_MEM_aligned_free(state->ctx);
}
void OQS_SHA3_sha3_256_inc_ctx_clone(OQS_SHA3_sha3_256_inc_ctx *dest, const OQS_SHA3_sha3_256_inc_ctx *src) {
memcpy(dest->ctx, src->ctx, KECCAK_CTX_BYTES);
}
void OQS_SHA3_sha3_256_inc_ctx_reset(OQS_SHA3_sha3_256_inc_ctx *state) {
keccak_inc_reset((uint64_t *)state->ctx);
}
/* SHA3-384 */
void OQS_SHA3_sha3_384(uint8_t *output, const uint8_t *input, size_t inlen) {
OQS_SHA3_sha3_384_inc_ctx s;
OQS_SHA3_sha3_384_inc_init(&s);
OQS_SHA3_sha3_384_inc_absorb(&s, input, inlen);
OQS_SHA3_sha3_384_inc_finalize(output, &s);
OQS_SHA3_sha3_384_inc_ctx_release(&s);
}
void OQS_SHA3_sha3_384_inc_init(OQS_SHA3_sha3_384_inc_ctx *state) {
state->ctx = OQS_MEM_aligned_alloc(KECCAK_CTX_ALIGNMENT, KECCAK_CTX_BYTES);
if (state->ctx == NULL) {
exit(111);
}
keccak_inc_reset((uint64_t *)state->ctx);
}
void OQS_SHA3_sha3_384_inc_absorb(OQS_SHA3_sha3_384_inc_ctx *state, const uint8_t *input, size_t inlen) {
keccak_inc_absorb((uint64_t *)state->ctx, OQS_SHA3_SHA3_384_RATE, input, inlen);
}
void OQS_SHA3_sha3_384_inc_finalize(uint8_t *output, OQS_SHA3_sha3_384_inc_ctx *state) {
keccak_inc_finalize((uint64_t *)state->ctx, OQS_SHA3_SHA3_384_RATE, 0x06);
keccak_inc_squeeze(output, 48, (uint64_t *)state->ctx, OQS_SHA3_SHA3_384_RATE);
}
void OQS_SHA3_sha3_384_inc_ctx_release(OQS_SHA3_sha3_384_inc_ctx *state) {
OQS_MEM_aligned_free(state->ctx);
}
void OQS_SHA3_sha3_384_inc_ctx_clone(OQS_SHA3_sha3_384_inc_ctx *dest, const OQS_SHA3_sha3_384_inc_ctx *src) {
memcpy(dest->ctx, src->ctx, KECCAK_CTX_BYTES);
}
void OQS_SHA3_sha3_384_inc_ctx_reset(OQS_SHA3_sha3_384_inc_ctx *state) {
keccak_inc_reset((uint64_t *)state->ctx);
}
/* SHA3-512 */
void OQS_SHA3_sha3_512(uint8_t *output, const uint8_t *input, size_t inlen) {
OQS_SHA3_sha3_512_inc_ctx s;
OQS_SHA3_sha3_512_inc_init(&s);
OQS_SHA3_sha3_512_inc_absorb(&s, input, inlen);
OQS_SHA3_sha3_512_inc_finalize(output, &s);
OQS_SHA3_sha3_512_inc_ctx_release(&s);
}
void OQS_SHA3_sha3_512_inc_init(OQS_SHA3_sha3_512_inc_ctx *state) {
state->ctx = OQS_MEM_aligned_alloc(KECCAK_CTX_ALIGNMENT, KECCAK_CTX_BYTES);
if (state->ctx == NULL) {
exit(111);
}
keccak_inc_reset((uint64_t *)state->ctx);
}
void OQS_SHA3_sha3_512_inc_absorb(OQS_SHA3_sha3_512_inc_ctx *state, const uint8_t *input, size_t inlen) {
keccak_inc_absorb((uint64_t *)state->ctx, OQS_SHA3_SHA3_512_RATE, input, inlen);
}
void OQS_SHA3_sha3_512_inc_finalize(uint8_t *output, OQS_SHA3_sha3_512_inc_ctx *state) {
keccak_inc_finalize((uint64_t *)state->ctx, OQS_SHA3_SHA3_512_RATE, 0x06);
keccak_inc_squeeze(output, 64, (uint64_t *)state->ctx, OQS_SHA3_SHA3_512_RATE);
}
void OQS_SHA3_sha3_512_inc_ctx_release(OQS_SHA3_sha3_512_inc_ctx *state) {
OQS_MEM_aligned_free(state->ctx);
}
void OQS_SHA3_sha3_512_inc_ctx_clone(OQS_SHA3_sha3_512_inc_ctx *dest, const OQS_SHA3_sha3_512_inc_ctx *src) {
memcpy(dest->ctx, src->ctx, KECCAK_CTX_BYTES);
}
void OQS_SHA3_sha3_512_inc_ctx_reset(OQS_SHA3_sha3_512_inc_ctx *state) {
keccak_inc_reset((uint64_t *)state->ctx);
}
/* SHAKE128 */
void OQS_SHA3_shake128(uint8_t *output, size_t outlen, const uint8_t *input, size_t inlen) {
OQS_SHA3_shake128_inc_ctx s;
OQS_SHA3_shake128_inc_init(&s);
OQS_SHA3_shake128_inc_absorb(&s, input, inlen);
OQS_SHA3_shake128_inc_finalize(&s);
OQS_SHA3_shake128_inc_squeeze(output, outlen, &s);
OQS_SHA3_shake128_inc_ctx_release(&s);
}
/* SHAKE128 incremental */
void OQS_SHA3_shake128_inc_init(OQS_SHA3_shake128_inc_ctx *state) {
state->ctx = OQS_MEM_aligned_alloc(KECCAK_CTX_ALIGNMENT, KECCAK_CTX_BYTES);
if (state->ctx == NULL) {
exit(111);
}
keccak_inc_reset((uint64_t *)state->ctx);
}
void OQS_SHA3_shake128_inc_absorb(OQS_SHA3_shake128_inc_ctx *state, const uint8_t *input, size_t inlen) {
keccak_inc_absorb((uint64_t *)state->ctx, OQS_SHA3_SHAKE128_RATE, input, inlen);
}
void OQS_SHA3_shake128_inc_finalize(OQS_SHA3_shake128_inc_ctx *state) {
keccak_inc_finalize((uint64_t *)state->ctx, OQS_SHA3_SHAKE128_RATE, 0x1F);
}
void OQS_SHA3_shake128_inc_squeeze(uint8_t *output, size_t outlen, OQS_SHA3_shake128_inc_ctx *state) {
keccak_inc_squeeze(output, outlen, (uint64_t *)state->ctx, OQS_SHA3_SHAKE128_RATE);
}
void OQS_SHA3_shake128_inc_ctx_clone(OQS_SHA3_shake128_inc_ctx *dest, const OQS_SHA3_shake128_inc_ctx *src) {
memcpy(dest->ctx, src->ctx, KECCAK_CTX_BYTES);
}
void OQS_SHA3_shake128_inc_ctx_release(OQS_SHA3_shake128_inc_ctx *state) {
OQS_MEM_aligned_free(state->ctx);
}
void OQS_SHA3_shake128_inc_ctx_reset(OQS_SHA3_shake128_inc_ctx *state) {
keccak_inc_reset((uint64_t *)state->ctx);
}
/* SHAKE256 */
void OQS_SHA3_shake256(uint8_t *output, size_t outlen, const uint8_t *input, size_t inlen) {
OQS_SHA3_shake256_inc_ctx s;
OQS_SHA3_shake256_inc_init(&s);
OQS_SHA3_shake256_inc_absorb(&s, input, inlen);
OQS_SHA3_shake256_inc_finalize(&s);
OQS_SHA3_shake256_inc_squeeze(output, outlen, &s);
OQS_SHA3_shake256_inc_ctx_release(&s);
}
/* SHAKE256 incremental */
void OQS_SHA3_shake256_inc_init(OQS_SHA3_shake256_inc_ctx *state) {
state->ctx = OQS_MEM_aligned_alloc(KECCAK_CTX_ALIGNMENT, KECCAK_CTX_BYTES);
if (state->ctx == NULL) {
exit(111);
}
keccak_inc_reset((uint64_t *)state->ctx);
}
void OQS_SHA3_shake256_inc_absorb(OQS_SHA3_shake256_inc_ctx *state, const uint8_t *input, size_t inlen) {
keccak_inc_absorb((uint64_t *)state->ctx, OQS_SHA3_SHAKE256_RATE, input, inlen);
}
void OQS_SHA3_shake256_inc_finalize(OQS_SHA3_shake256_inc_ctx *state) {
keccak_inc_finalize((uint64_t *)state->ctx, OQS_SHA3_SHAKE256_RATE, 0x1F);
}
void OQS_SHA3_shake256_inc_squeeze(uint8_t *output, size_t outlen, OQS_SHA3_shake256_inc_ctx *state) {
keccak_inc_squeeze(output, outlen, state->ctx, OQS_SHA3_SHAKE256_RATE);
}
void OQS_SHA3_shake256_inc_ctx_release(OQS_SHA3_shake256_inc_ctx *state) {
OQS_MEM_aligned_free(state->ctx);
}
void OQS_SHA3_shake256_inc_ctx_clone(OQS_SHA3_shake256_inc_ctx *dest, const OQS_SHA3_shake256_inc_ctx *src) {
memcpy(dest->ctx, src->ctx, KECCAK_CTX_BYTES);
}
void OQS_SHA3_shake256_inc_ctx_reset(OQS_SHA3_shake256_inc_ctx *state) {
keccak_inc_reset((uint64_t *)state->ctx);
}

View file

@ -0,0 +1,67 @@
/* This file has been written using:
* https://github.com/vectorclass/version2/blob/master/instrset_detect.cpp
* https://github.com/google/cpu_features/blob/master/src/cpuinfo_x86.c
* SPDX-License-Identifier: Apache-2.0
*/
#include <stdint.h>
#if defined(_MSC_VER)
#include <immintrin.h>
#include <intrin.h>
#endif
#define MASK_XMM 0x2
#define MASK_YMM 0x4
#define MASK_MASKREG 0x20
#define MASK_ZMM0_15 0x40
#define MASK_ZMM16_31 0x80
typedef struct {
uint32_t eax;
uint32_t ebx;
uint32_t ecx;
uint32_t edx;
} cpuid_out;
static inline uint32_t xgetbv_eax(uint32_t xcr) {
#if defined(__GNUC__) || defined(__clang__)
uint32_t eax;
__asm__ ( ".byte 0x0f, 0x01, 0xd0" : "=a"(eax) : "c"(xcr));
return eax;
#elif defined(_MSC_VER)
return _xgetbv(xcr) & 0xFFFF;
#else
#error "Only GCC, Clang, and MSVC are supported."
#endif
}
static unsigned int has_mask(const uint32_t value, const uint32_t mask) {
return (value & mask) == mask;
}
static inline unsigned int is_bit_set(const uint32_t val, const unsigned int bit_pos) {
return val & (1 << bit_pos) ? 1 : 0;
}
static inline void cpuid(cpuid_out *out, const uint32_t eax_leaf) {
const uint32_t ecx_leaf = 0;
#if defined(__GNUC__) || defined(__clang__)
uint32_t eax, ebx, ecx, edx;
__asm__("cpuid" : "=a"(eax), "=b"(ebx), "=c"(ecx), "=d"(edx) : "a"(eax_leaf), "c"(ecx_leaf) : );
out->eax = eax;
out->ebx = ebx;
out->ecx = ecx;
out->edx = edx;
#elif defined(_MSC_VER)
uint32_t output[4];
__cpuidex(output, eax_leaf, ecx_leaf);
out->eax = output[0];
out->ebx = output[1];
out->ecx = output[2];
out->edx = output[3];
#else
#error "Only GCC, Clang, and MSVC are supported."
#endif
}

418
libs/liboqs/src/kem/kem.c Normal file
View file

@ -0,0 +1,418 @@
// SPDX-License-Identifier: MIT
#include <assert.h>
#include <stdlib.h>
#if defined(_WIN32)
#include <string.h>
#define strcasecmp _stricmp
#else
#include <strings.h>
#endif
#include <oqs/oqs.h>
OQS_API const char *OQS_KEM_alg_identifier(size_t i) {
// EDIT-WHEN-ADDING-KEM
const char *a[OQS_KEM_algs_length] = {
OQS_KEM_alg_bike_l1,
OQS_KEM_alg_bike_l3,
OQS_KEM_alg_bike_l5,
///// OQS_COPY_FROM_UPSTREAM_FRAGMENT_ALG_IDENTIFIER_START
OQS_KEM_alg_classic_mceliece_348864,
OQS_KEM_alg_classic_mceliece_348864f,
OQS_KEM_alg_classic_mceliece_460896,
OQS_KEM_alg_classic_mceliece_460896f,
OQS_KEM_alg_classic_mceliece_6688128,
OQS_KEM_alg_classic_mceliece_6688128f,
OQS_KEM_alg_classic_mceliece_6960119,
OQS_KEM_alg_classic_mceliece_6960119f,
OQS_KEM_alg_classic_mceliece_8192128,
OQS_KEM_alg_classic_mceliece_8192128f,
OQS_KEM_alg_hqc_128,
OQS_KEM_alg_hqc_192,
OQS_KEM_alg_hqc_256,
OQS_KEM_alg_kyber_512,
OQS_KEM_alg_kyber_768,
OQS_KEM_alg_kyber_1024,
///// OQS_COPY_FROM_UPSTREAM_FRAGMENT_ALG_IDENTIFIER_END
OQS_KEM_alg_ntruprime_sntrup761,
OQS_KEM_alg_frodokem_640_aes,
OQS_KEM_alg_frodokem_640_shake,
OQS_KEM_alg_frodokem_976_aes,
OQS_KEM_alg_frodokem_976_shake,
OQS_KEM_alg_frodokem_1344_aes,
OQS_KEM_alg_frodokem_1344_shake,
};
if (i >= OQS_KEM_algs_length) {
return NULL;
} else {
return a[i];
}
}
OQS_API int OQS_KEM_alg_count(void) {
return OQS_KEM_algs_length;
}
OQS_API int OQS_KEM_alg_is_enabled(const char *method_name) {
if (method_name == NULL) {
return 0;
} else if (0 == strcasecmp(method_name, OQS_KEM_alg_bike_l1)) {
#ifdef OQS_ENABLE_KEM_bike_l1
return 1;
#else
return 0;
#endif
} else if (0 == strcasecmp(method_name, OQS_KEM_alg_bike_l3)) {
#ifdef OQS_ENABLE_KEM_bike_l3
return 1;
#else
return 0;
#endif
} else if (0 == strcasecmp(method_name, OQS_KEM_alg_bike_l5)) {
#ifdef OQS_ENABLE_KEM_bike_l5
return 1;
#else
return 0;
#endif
///// OQS_COPY_FROM_UPSTREAM_FRAGMENT_ENABLED_CASE_START
} else if (0 == strcasecmp(method_name, OQS_KEM_alg_classic_mceliece_348864)) {
#ifdef OQS_ENABLE_KEM_classic_mceliece_348864
return 1;
#else
return 0;
#endif
} else if (0 == strcasecmp(method_name, OQS_KEM_alg_classic_mceliece_348864f)) {
#ifdef OQS_ENABLE_KEM_classic_mceliece_348864f
return 1;
#else
return 0;
#endif
} else if (0 == strcasecmp(method_name, OQS_KEM_alg_classic_mceliece_460896)) {
#ifdef OQS_ENABLE_KEM_classic_mceliece_460896
return 1;
#else
return 0;
#endif
} else if (0 == strcasecmp(method_name, OQS_KEM_alg_classic_mceliece_460896f)) {
#ifdef OQS_ENABLE_KEM_classic_mceliece_460896f
return 1;
#else
return 0;
#endif
} else if (0 == strcasecmp(method_name, OQS_KEM_alg_classic_mceliece_6688128)) {
#ifdef OQS_ENABLE_KEM_classic_mceliece_6688128
return 1;
#else
return 0;
#endif
} else if (0 == strcasecmp(method_name, OQS_KEM_alg_classic_mceliece_6688128f)) {
#ifdef OQS_ENABLE_KEM_classic_mceliece_6688128f
return 1;
#else
return 0;
#endif
} else if (0 == strcasecmp(method_name, OQS_KEM_alg_classic_mceliece_6960119)) {
#ifdef OQS_ENABLE_KEM_classic_mceliece_6960119
return 1;
#else
return 0;
#endif
} else if (0 == strcasecmp(method_name, OQS_KEM_alg_classic_mceliece_6960119f)) {
#ifdef OQS_ENABLE_KEM_classic_mceliece_6960119f
return 1;
#else
return 0;
#endif
} else if (0 == strcasecmp(method_name, OQS_KEM_alg_classic_mceliece_8192128)) {
#ifdef OQS_ENABLE_KEM_classic_mceliece_8192128
return 1;
#else
return 0;
#endif
} else if (0 == strcasecmp(method_name, OQS_KEM_alg_classic_mceliece_8192128f)) {
#ifdef OQS_ENABLE_KEM_classic_mceliece_8192128f
return 1;
#else
return 0;
#endif
} else if (0 == strcasecmp(method_name, OQS_KEM_alg_hqc_128)) {
#ifdef OQS_ENABLE_KEM_hqc_128
return 1;
#else
return 0;
#endif
} else if (0 == strcasecmp(method_name, OQS_KEM_alg_hqc_192)) {
#ifdef OQS_ENABLE_KEM_hqc_192
return 1;
#else
return 0;
#endif
} else if (0 == strcasecmp(method_name, OQS_KEM_alg_hqc_256)) {
#ifdef OQS_ENABLE_KEM_hqc_256
return 1;
#else
return 0;
#endif
} else if (0 == strcasecmp(method_name, OQS_KEM_alg_kyber_512)) {
#ifdef OQS_ENABLE_KEM_kyber_512
return 1;
#else
return 0;
#endif
} else if (0 == strcasecmp(method_name, OQS_KEM_alg_kyber_768)) {
#ifdef OQS_ENABLE_KEM_kyber_768
return 1;
#else
return 0;
#endif
} else if (0 == strcasecmp(method_name, OQS_KEM_alg_kyber_1024)) {
#ifdef OQS_ENABLE_KEM_kyber_1024
return 1;
#else
return 0;
#endif
///// OQS_COPY_FROM_UPSTREAM_FRAGMENT_ENABLED_CASE_END
} else if (0 == strcasecmp(method_name, OQS_KEM_alg_ntruprime_sntrup761)) {
#ifdef OQS_ENABLE_KEM_ntruprime_sntrup761
return 1;
#else
return 0;
#endif
} else if (0 == strcasecmp(method_name, OQS_KEM_alg_frodokem_640_aes)) {
#ifdef OQS_ENABLE_KEM_frodokem_640_aes
return 1;
#else
return 0;
#endif
} else if (0 == strcasecmp(method_name, OQS_KEM_alg_frodokem_640_shake)) {
#ifdef OQS_ENABLE_KEM_frodokem_640_shake
return 1;
#else
return 0;
#endif
} else if (0 == strcasecmp(method_name, OQS_KEM_alg_frodokem_976_aes)) {
#ifdef OQS_ENABLE_KEM_frodokem_976_aes
return 1;
#else
return 0;
#endif
} else if (0 == strcasecmp(method_name, OQS_KEM_alg_frodokem_976_shake)) {
#ifdef OQS_ENABLE_KEM_frodokem_976_shake
return 1;
#else
return 0;
#endif
} else if (0 == strcasecmp(method_name, OQS_KEM_alg_frodokem_1344_aes)) {
#ifdef OQS_ENABLE_KEM_frodokem_1344_aes
return 1;
#else
return 0;
#endif
} else if (0 == strcasecmp(method_name, OQS_KEM_alg_frodokem_1344_shake)) {
#ifdef OQS_ENABLE_KEM_frodokem_1344_shake
return 1;
#else
return 0;
#endif
// EDIT-WHEN-ADDING-KEM
} else {
return 0;
}
}
OQS_API OQS_KEM *OQS_KEM_new(const char *method_name) {
if (method_name == NULL) {
return NULL;
}
if (0 == strcasecmp(method_name, OQS_KEM_alg_bike_l1)) {
#ifdef OQS_ENABLE_KEM_bike_l1
return OQS_KEM_bike_l1_new();
#else
return NULL;
#endif
} else if (0 == strcasecmp(method_name, OQS_KEM_alg_bike_l3)) {
#ifdef OQS_ENABLE_KEM_bike_l3
return OQS_KEM_bike_l3_new();
#else
return NULL;
#endif
} else if (0 == strcasecmp(method_name, OQS_KEM_alg_bike_l5)) {
#ifdef OQS_ENABLE_KEM_bike_l5
return OQS_KEM_bike_l5_new();
#else
return NULL;
#endif
///// OQS_COPY_FROM_UPSTREAM_FRAGMENT_NEW_CASE_START
} else if (0 == strcasecmp(method_name, OQS_KEM_alg_classic_mceliece_348864)) {
#ifdef OQS_ENABLE_KEM_classic_mceliece_348864
return OQS_KEM_classic_mceliece_348864_new();
#else
return NULL;
#endif
} else if (0 == strcasecmp(method_name, OQS_KEM_alg_classic_mceliece_348864f)) {
#ifdef OQS_ENABLE_KEM_classic_mceliece_348864f
return OQS_KEM_classic_mceliece_348864f_new();
#else
return NULL;
#endif
} else if (0 == strcasecmp(method_name, OQS_KEM_alg_classic_mceliece_460896)) {
#ifdef OQS_ENABLE_KEM_classic_mceliece_460896
return OQS_KEM_classic_mceliece_460896_new();
#else
return NULL;
#endif
} else if (0 == strcasecmp(method_name, OQS_KEM_alg_classic_mceliece_460896f)) {
#ifdef OQS_ENABLE_KEM_classic_mceliece_460896f
return OQS_KEM_classic_mceliece_460896f_new();
#else
return NULL;
#endif
} else if (0 == strcasecmp(method_name, OQS_KEM_alg_classic_mceliece_6688128)) {
#ifdef OQS_ENABLE_KEM_classic_mceliece_6688128
return OQS_KEM_classic_mceliece_6688128_new();
#else
return NULL;
#endif
} else if (0 == strcasecmp(method_name, OQS_KEM_alg_classic_mceliece_6688128f)) {
#ifdef OQS_ENABLE_KEM_classic_mceliece_6688128f
return OQS_KEM_classic_mceliece_6688128f_new();
#else
return NULL;
#endif
} else if (0 == strcasecmp(method_name, OQS_KEM_alg_classic_mceliece_6960119)) {
#ifdef OQS_ENABLE_KEM_classic_mceliece_6960119
return OQS_KEM_classic_mceliece_6960119_new();
#else
return NULL;
#endif
} else if (0 == strcasecmp(method_name, OQS_KEM_alg_classic_mceliece_6960119f)) {
#ifdef OQS_ENABLE_KEM_classic_mceliece_6960119f
return OQS_KEM_classic_mceliece_6960119f_new();
#else
return NULL;
#endif
} else if (0 == strcasecmp(method_name, OQS_KEM_alg_classic_mceliece_8192128)) {
#ifdef OQS_ENABLE_KEM_classic_mceliece_8192128
return OQS_KEM_classic_mceliece_8192128_new();
#else
return NULL;
#endif
} else if (0 == strcasecmp(method_name, OQS_KEM_alg_classic_mceliece_8192128f)) {
#ifdef OQS_ENABLE_KEM_classic_mceliece_8192128f
return OQS_KEM_classic_mceliece_8192128f_new();
#else
return NULL;
#endif
} else if (0 == strcasecmp(method_name, OQS_KEM_alg_hqc_128)) {
#ifdef OQS_ENABLE_KEM_hqc_128
return OQS_KEM_hqc_128_new();
#else
return NULL;
#endif
} else if (0 == strcasecmp(method_name, OQS_KEM_alg_hqc_192)) {
#ifdef OQS_ENABLE_KEM_hqc_192
return OQS_KEM_hqc_192_new();
#else
return NULL;
#endif
} else if (0 == strcasecmp(method_name, OQS_KEM_alg_hqc_256)) {
#ifdef OQS_ENABLE_KEM_hqc_256
return OQS_KEM_hqc_256_new();
#else
return NULL;
#endif
} else if (0 == strcasecmp(method_name, OQS_KEM_alg_kyber_512)) {
#ifdef OQS_ENABLE_KEM_kyber_512
return OQS_KEM_kyber_512_new();
#else
return NULL;
#endif
} else if (0 == strcasecmp(method_name, OQS_KEM_alg_kyber_768)) {
#ifdef OQS_ENABLE_KEM_kyber_768
return OQS_KEM_kyber_768_new();
#else
return NULL;
#endif
} else if (0 == strcasecmp(method_name, OQS_KEM_alg_kyber_1024)) {
#ifdef OQS_ENABLE_KEM_kyber_1024
return OQS_KEM_kyber_1024_new();
#else
return NULL;
#endif
///// OQS_COPY_FROM_UPSTREAM_FRAGMENT_NEW_CASE_END
} else if (0 == strcasecmp(method_name, OQS_KEM_alg_ntruprime_sntrup761)) {
#ifdef OQS_ENABLE_KEM_ntruprime_sntrup761
return OQS_KEM_ntruprime_sntrup761_new();
#else
return NULL;
#endif
} else if (0 == strcasecmp(method_name, OQS_KEM_alg_frodokem_640_aes)) {
#ifdef OQS_ENABLE_KEM_frodokem_640_aes
return OQS_KEM_frodokem_640_aes_new();
#else
return NULL;
#endif
} else if (0 == strcasecmp(method_name, OQS_KEM_alg_frodokem_640_shake)) {
#ifdef OQS_ENABLE_KEM_frodokem_640_shake
return OQS_KEM_frodokem_640_shake_new();
#else
return NULL;
#endif
} else if (0 == strcasecmp(method_name, OQS_KEM_alg_frodokem_976_aes)) {
#ifdef OQS_ENABLE_KEM_frodokem_976_aes
return OQS_KEM_frodokem_976_aes_new();
#else
return NULL;
#endif
} else if (0 == strcasecmp(method_name, OQS_KEM_alg_frodokem_976_shake)) {
#ifdef OQS_ENABLE_KEM_frodokem_976_shake
return OQS_KEM_frodokem_976_shake_new();
#else
return NULL;
#endif
} else if (0 == strcasecmp(method_name, OQS_KEM_alg_frodokem_1344_aes)) {
#ifdef OQS_ENABLE_KEM_frodokem_1344_aes
return OQS_KEM_frodokem_1344_aes_new();
#else
return NULL;
#endif
} else if (0 == strcasecmp(method_name, OQS_KEM_alg_frodokem_1344_shake)) {
#ifdef OQS_ENABLE_KEM_frodokem_1344_shake
return OQS_KEM_frodokem_1344_shake_new();
#else
return NULL;
#endif
// EDIT-WHEN-ADDING-KEM
} else {
return NULL;
}
}
OQS_API OQS_STATUS OQS_KEM_keypair(const OQS_KEM *kem, uint8_t *public_key, uint8_t *secret_key) {
if (kem == NULL) {
return OQS_ERROR;
} else {
return kem->keypair(public_key, secret_key);
}
}
OQS_API OQS_STATUS OQS_KEM_encaps(const OQS_KEM *kem, uint8_t *ciphertext, uint8_t *shared_secret, const uint8_t *public_key) {
if (kem == NULL) {
return OQS_ERROR;
} else {
return kem->encaps(ciphertext, shared_secret, public_key);
}
}
OQS_API OQS_STATUS OQS_KEM_decaps(const OQS_KEM *kem, uint8_t *shared_secret, const uint8_t *ciphertext, const uint8_t *secret_key) {
if (kem == NULL) {
return OQS_ERROR;
} else {
return kem->decaps(shared_secret, ciphertext, secret_key);
}
}
OQS_API void OQS_KEM_free(OQS_KEM *kem) {
OQS_MEM_insecure_free(kem);
}

285
libs/liboqs/src/kem/kem.h Normal file
View file

@ -0,0 +1,285 @@
/**
* \file kem.h
* \brief Key encapsulation mechanisms
*
* The file `tests/example_kem.c` contains two examples on using the OQS_KEM API.
*
* The first example uses the individual scheme's algorithms directly and uses
* no dynamic memory allocation -- all buffers are allocated on the stack, with
* sizes indicated using preprocessor macros. Since algorithms can be disabled at
* compile-time, the programmer should wrap the code in \#ifdefs.
*
* The second example uses an OQS_KEM object to use an algorithm specified at
* runtime. Therefore it uses dynamic memory allocation -- all buffers must be
* malloc'ed by the programmer, with sizes indicated using the corresponding length
* member of the OQS_KEM object in question. Since algorithms can be disabled at
* compile-time, the programmer should check that the OQS_KEM object is not `NULL`.
*
* SPDX-License-Identifier: MIT
*/
#ifndef OQS_KEM_H
#define OQS_KEM_H
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include <oqs/oqs.h>
#if defined(__cplusplus)
extern "C" {
#endif
/** Algorithm identifier for BIKE-L1 KEM (Round-4). */
#define OQS_KEM_alg_bike_l1 "BIKE-L1"
/** Algorithm identifier for BIKE-L3 KEM (Round-4). */
#define OQS_KEM_alg_bike_l3 "BIKE-L3"
/** Algorithm identifier for BIKE-L5 KEM (Round-4). */
#define OQS_KEM_alg_bike_l5 "BIKE-L5"
///// OQS_COPY_FROM_UPSTREAM_FRAGMENT_ALG_IDENTIFIER_START
/** Algorithm identifier for Classic-McEliece-348864 KEM. */
#define OQS_KEM_alg_classic_mceliece_348864 "Classic-McEliece-348864"
/** Algorithm identifier for Classic-McEliece-348864f KEM. */
#define OQS_KEM_alg_classic_mceliece_348864f "Classic-McEliece-348864f"
/** Algorithm identifier for Classic-McEliece-460896 KEM. */
#define OQS_KEM_alg_classic_mceliece_460896 "Classic-McEliece-460896"
/** Algorithm identifier for Classic-McEliece-460896f KEM. */
#define OQS_KEM_alg_classic_mceliece_460896f "Classic-McEliece-460896f"
/** Algorithm identifier for Classic-McEliece-6688128 KEM. */
#define OQS_KEM_alg_classic_mceliece_6688128 "Classic-McEliece-6688128"
/** Algorithm identifier for Classic-McEliece-6688128f KEM. */
#define OQS_KEM_alg_classic_mceliece_6688128f "Classic-McEliece-6688128f"
/** Algorithm identifier for Classic-McEliece-6960119 KEM. */
#define OQS_KEM_alg_classic_mceliece_6960119 "Classic-McEliece-6960119"
/** Algorithm identifier for Classic-McEliece-6960119f KEM. */
#define OQS_KEM_alg_classic_mceliece_6960119f "Classic-McEliece-6960119f"
/** Algorithm identifier for Classic-McEliece-8192128 KEM. */
#define OQS_KEM_alg_classic_mceliece_8192128 "Classic-McEliece-8192128"
/** Algorithm identifier for Classic-McEliece-8192128f KEM. */
#define OQS_KEM_alg_classic_mceliece_8192128f "Classic-McEliece-8192128f"
/** Algorithm identifier for HQC-128 KEM. */
#define OQS_KEM_alg_hqc_128 "HQC-128"
/** Algorithm identifier for HQC-192 KEM. */
#define OQS_KEM_alg_hqc_192 "HQC-192"
/** Algorithm identifier for HQC-256 KEM. */
#define OQS_KEM_alg_hqc_256 "HQC-256"
/** Algorithm identifier for Kyber512 KEM. */
#define OQS_KEM_alg_kyber_512 "Kyber512"
/** Algorithm identifier for Kyber768 KEM. */
#define OQS_KEM_alg_kyber_768 "Kyber768"
/** Algorithm identifier for Kyber1024 KEM. */
#define OQS_KEM_alg_kyber_1024 "Kyber1024"
///// OQS_COPY_FROM_UPSTREAM_FRAGMENT_ALG_IDENTIFIER_END
/** Algorithm identifier for sntrup761 KEM. */
#define OQS_KEM_alg_ntruprime_sntrup761 "sntrup761"
/** Algorithm identifier for FrodoKEM-640-AES KEM. */
#define OQS_KEM_alg_frodokem_640_aes "FrodoKEM-640-AES"
/** Algorithm identifier for FrodoKEM-640-SHAKE KEM. */
#define OQS_KEM_alg_frodokem_640_shake "FrodoKEM-640-SHAKE"
/** Algorithm identifier for FrodoKEM-976-AES KEM. */
#define OQS_KEM_alg_frodokem_976_aes "FrodoKEM-976-AES"
/** Algorithm identifier for FrodoKEM-976-SHAKE KEM. */
#define OQS_KEM_alg_frodokem_976_shake "FrodoKEM-976-SHAKE"
/** Algorithm identifier for FrodoKEM-1344-AES KEM. */
#define OQS_KEM_alg_frodokem_1344_aes "FrodoKEM-1344-AES"
/** Algorithm identifier for FrodoKEM-1344-SHAKE KEM. */
#define OQS_KEM_alg_frodokem_1344_shake "FrodoKEM-1344-SHAKE"
// EDIT-WHEN-ADDING-KEM
///// OQS_COPY_FROM_UPSTREAM_FRAGMENT_ALGS_LENGTH_START
/** Number of algorithm identifiers above. */
#define OQS_KEM_algs_length 26
///// OQS_COPY_FROM_UPSTREAM_FRAGMENT_ALGS_LENGTH_END
/**
* Returns identifiers for available key encapsulation mechanisms in liboqs. Used with OQS_KEM_new.
*
* Note that algorithm identifiers are present in this list even when the algorithm is disabled
* at compile time.
*
* @param[in] i Index of the algorithm identifier to return, 0 <= i < OQS_KEM_algs_length
* @return Algorithm identifier as a string, or NULL.
*/
OQS_API const char *OQS_KEM_alg_identifier(size_t i);
/**
* Returns the number of key encapsulation mechanisms in liboqs. They can be enumerated with
* OQS_KEM_alg_identifier.
*
* Note that some mechanisms may be disabled at compile time.
*
* @return The number of key encapsulation mechanisms.
*/
OQS_API int OQS_KEM_alg_count(void);
/**
* Indicates whether the specified algorithm was enabled at compile-time or not.
*
* @param[in] method_name Name of the desired algorithm; one of the names in `OQS_KEM_algs`.
* @return 1 if enabled, 0 if disabled or not found
*/
OQS_API int OQS_KEM_alg_is_enabled(const char *method_name);
/**
* Key encapsulation mechanism object
*/
typedef struct OQS_KEM {
/** Printable string representing the name of the key encapsulation mechanism. */
const char *method_name;
/**
* Printable string representing the version of the cryptographic algorithm.
*
* Implementations with the same method_name and same alg_version will be interoperable.
* See README.md for information about algorithm compatibility.
*/
const char *alg_version;
/** The NIST security level (1, 2, 3, 4, 5) claimed in this algorithm's original NIST submission. */
uint8_t claimed_nist_level;
/** Whether the KEM offers IND-CCA security (TRUE) or IND-CPA security (FALSE). */
bool ind_cca;
/** The (maximum) length, in bytes, of public keys for this KEM. */
size_t length_public_key;
/** The (maximum) length, in bytes, of secret keys for this KEM. */
size_t length_secret_key;
/** The (maximum) length, in bytes, of ciphertexts for this KEM. */
size_t length_ciphertext;
/** The (maximum) length, in bytes, of shared secrets for this KEM. */
size_t length_shared_secret;
/**
* Keypair generation algorithm.
*
* Caller is responsible for allocating sufficient memory for `public_key` and
* `secret_key`, based on the `length_*` members in this object or the per-scheme
* compile-time macros `OQS_KEM_*_length_*`.
*
* @param[out] public_key The public key represented as a byte string.
* @param[out] secret_key The secret key represented as a byte string.
* @return OQS_SUCCESS or OQS_ERROR
*/
OQS_STATUS (*keypair)(uint8_t *public_key, uint8_t *secret_key);
/**
* Encapsulation algorithm.
*
* Caller is responsible for allocating sufficient memory for `ciphertext` and
* `shared_secret`, based on the `length_*` members in this object or the per-scheme
* compile-time macros `OQS_KEM_*_length_*`.
*
* @param[out] ciphertext The ciphertext (encapsulation) represented as a byte string.
* @param[out] shared_secret The shared secret represented as a byte string.
* @param[in] public_key The public key represented as a byte string.
* @return OQS_SUCCESS or OQS_ERROR
*/
OQS_STATUS (*encaps)(uint8_t *ciphertext, uint8_t *shared_secret, const uint8_t *public_key);
/**
* Decapsulation algorithm.
*
* Caller is responsible for allocating sufficient memory for `shared_secret`, based
* on the `length_*` members in this object or the per-scheme compile-time macros
* `OQS_KEM_*_length_*`.
*
* @param[out] shared_secret The shared secret represented as a byte string.
* @param[in] ciphertext The ciphertext (encapsulation) represented as a byte string.
* @param[in] secret_key The secret key represented as a byte string.
* @return OQS_SUCCESS or OQS_ERROR
*/
OQS_STATUS (*decaps)(uint8_t *shared_secret, const uint8_t *ciphertext, const uint8_t *secret_key);
} OQS_KEM;
/**
* Constructs an OQS_KEM object for a particular algorithm.
*
* Callers should always check whether the return value is `NULL`, which indicates either than an
* invalid algorithm name was provided, or that the requested algorithm was disabled at compile-time.
*
* @param[in] method_name Name of the desired algorithm; one of the names in `OQS_KEM_algs`.
* @return An OQS_KEM for the particular algorithm, or `NULL` if the algorithm has been disabled at compile-time.
*/
OQS_API OQS_KEM *OQS_KEM_new(const char *method_name);
/**
* Keypair generation algorithm.
*
* Caller is responsible for allocating sufficient memory for `public_key` and
* `secret_key`, based on the `length_*` members in this object or the per-scheme
* compile-time macros `OQS_KEM_*_length_*`.
*
* @param[in] kem The OQS_KEM object representing the KEM.
* @param[out] public_key The public key represented as a byte string.
* @param[out] secret_key The secret key represented as a byte string.
* @return OQS_SUCCESS or OQS_ERROR
*/
OQS_API OQS_STATUS OQS_KEM_keypair(const OQS_KEM *kem, uint8_t *public_key, uint8_t *secret_key);
/**
* Encapsulation algorithm.
*
* Caller is responsible for allocating sufficient memory for `ciphertext` and
* `shared_secret`, based on the `length_*` members in this object or the per-scheme
* compile-time macros `OQS_KEM_*_length_*`.
*
* @param[in] kem The OQS_KEM object representing the KEM.
* @param[out] ciphertext The ciphertext (encapsulation) represented as a byte string.
* @param[out] shared_secret The shared secret represented as a byte string.
* @param[in] public_key The public key represented as a byte string.
* @return OQS_SUCCESS or OQS_ERROR
*/
OQS_API OQS_STATUS OQS_KEM_encaps(const OQS_KEM *kem, uint8_t *ciphertext, uint8_t *shared_secret, const uint8_t *public_key);
/**
* Decapsulation algorithm.
*
* Caller is responsible for allocating sufficient memory for `shared_secret`, based
* on the `length_*` members in this object or the per-scheme compile-time macros
* `OQS_KEM_*_length_*`.
*
* @param[in] kem The OQS_KEM object representing the KEM.
* @param[out] shared_secret The shared secret represented as a byte string.
* @param[in] ciphertext The ciphertext (encapsulation) represented as a byte string.
* @param[in] secret_key The secret key represented as a byte string.
* @return OQS_SUCCESS or OQS_ERROR
*/
OQS_API OQS_STATUS OQS_KEM_decaps(const OQS_KEM *kem, uint8_t *shared_secret, const uint8_t *ciphertext, const uint8_t *secret_key);
/**
* Frees an OQS_KEM object that was constructed by OQS_KEM_new.
*
* @param[in] kem The OQS_KEM object to free.
*/
OQS_API void OQS_KEM_free(OQS_KEM *kem);
#ifdef OQS_ENABLE_KEM_BIKE
#include <oqs/kem_bike.h>
#endif /* OQS_ENABLE_KEM_BIKE */
///// OQS_COPY_FROM_UPSTREAM_FRAGMENT_INCLUDE_START
#ifdef OQS_ENABLE_KEM_CLASSIC_MCELIECE
#include <oqs/kem_classic_mceliece.h>
#endif /* OQS_ENABLE_KEM_CLASSIC_MCELIECE */
#ifdef OQS_ENABLE_KEM_HQC
#include <oqs/kem_hqc.h>
#endif /* OQS_ENABLE_KEM_HQC */
#ifdef OQS_ENABLE_KEM_KYBER
#include <oqs/kem_kyber.h>
#endif /* OQS_ENABLE_KEM_KYBER */
///// OQS_COPY_FROM_UPSTREAM_FRAGMENT_INCLUDE_END
#ifdef OQS_ENABLE_KEM_NTRUPRIME
#include <oqs/kem_ntruprime.h>
#endif /* OQS_ENABLE_KEM_NTRUPRIME */
#ifdef OQS_ENABLE_KEM_FRODOKEM
#include <oqs/kem_frodokem.h>
#endif /* OQS_ENABLE_KEM_FRODOKEM */
// EDIT-WHEN-ADDING-KEM
#if defined(__cplusplus)
} // extern "C"
#endif
#endif // OQS_KEM_H

View file

@ -0,0 +1,42 @@
// SPDX-License-Identifier: MIT
#ifndef OQS_KEM_KYBER_H
#define OQS_KEM_KYBER_H
#include <oqs/oqs.h>
#ifdef OQS_ENABLE_KEM_kyber_512
#define OQS_KEM_kyber_512_length_public_key 800
#define OQS_KEM_kyber_512_length_secret_key 1632
#define OQS_KEM_kyber_512_length_ciphertext 768
#define OQS_KEM_kyber_512_length_shared_secret 32
OQS_KEM *OQS_KEM_kyber_512_new(void);
OQS_API OQS_STATUS OQS_KEM_kyber_512_keypair(uint8_t *public_key, uint8_t *secret_key);
OQS_API OQS_STATUS OQS_KEM_kyber_512_encaps(uint8_t *ciphertext, uint8_t *shared_secret, const uint8_t *public_key);
OQS_API OQS_STATUS OQS_KEM_kyber_512_decaps(uint8_t *shared_secret, const uint8_t *ciphertext, const uint8_t *secret_key);
#endif
#ifdef OQS_ENABLE_KEM_kyber_768
#define OQS_KEM_kyber_768_length_public_key 1184
#define OQS_KEM_kyber_768_length_secret_key 2400
#define OQS_KEM_kyber_768_length_ciphertext 1088
#define OQS_KEM_kyber_768_length_shared_secret 32
OQS_KEM *OQS_KEM_kyber_768_new(void);
OQS_API OQS_STATUS OQS_KEM_kyber_768_keypair(uint8_t *public_key, uint8_t *secret_key);
OQS_API OQS_STATUS OQS_KEM_kyber_768_encaps(uint8_t *ciphertext, uint8_t *shared_secret, const uint8_t *public_key);
OQS_API OQS_STATUS OQS_KEM_kyber_768_decaps(uint8_t *shared_secret, const uint8_t *ciphertext, const uint8_t *secret_key);
#endif
#ifdef OQS_ENABLE_KEM_kyber_1024
#define OQS_KEM_kyber_1024_length_public_key 1568
#define OQS_KEM_kyber_1024_length_secret_key 3168
#define OQS_KEM_kyber_1024_length_ciphertext 1568
#define OQS_KEM_kyber_1024_length_shared_secret 32
OQS_KEM *OQS_KEM_kyber_1024_new(void);
OQS_API OQS_STATUS OQS_KEM_kyber_1024_keypair(uint8_t *public_key, uint8_t *secret_key);
OQS_API OQS_STATUS OQS_KEM_kyber_1024_encaps(uint8_t *ciphertext, uint8_t *shared_secret, const uint8_t *public_key);
OQS_API OQS_STATUS OQS_KEM_kyber_1024_decaps(uint8_t *shared_secret, const uint8_t *ciphertext, const uint8_t *secret_key);
#endif
#endif

View file

@ -0,0 +1,127 @@
// SPDX-License-Identifier: MIT
#include <stdlib.h>
#include <oqs/kem_kyber.h>
#if defined(OQS_ENABLE_KEM_kyber_1024)
OQS_KEM *OQS_KEM_kyber_1024_new(void) {
OQS_KEM *kem = malloc(sizeof(OQS_KEM));
if (kem == NULL) {
return NULL;
}
kem->method_name = OQS_KEM_alg_kyber_1024;
kem->alg_version = "https://github.com/pq-crystals/kyber/commit/28413dfbf523fdde181246451c2bd77199c0f7ff";
kem->claimed_nist_level = 5;
kem->ind_cca = true;
kem->length_public_key = OQS_KEM_kyber_1024_length_public_key;
kem->length_secret_key = OQS_KEM_kyber_1024_length_secret_key;
kem->length_ciphertext = OQS_KEM_kyber_1024_length_ciphertext;
kem->length_shared_secret = OQS_KEM_kyber_1024_length_shared_secret;
kem->keypair = OQS_KEM_kyber_1024_keypair;
kem->encaps = OQS_KEM_kyber_1024_encaps;
kem->decaps = OQS_KEM_kyber_1024_decaps;
return kem;
}
extern int pqcrystals_kyber1024_ref_keypair(uint8_t *pk, uint8_t *sk);
extern int pqcrystals_kyber1024_ref_enc(uint8_t *ct, uint8_t *ss, const uint8_t *pk);
extern int pqcrystals_kyber1024_ref_dec(uint8_t *ss, const uint8_t *ct, const uint8_t *sk);
#if defined(OQS_ENABLE_KEM_kyber_1024_avx2)
extern int pqcrystals_kyber1024_avx2_keypair(uint8_t *pk, uint8_t *sk);
extern int pqcrystals_kyber1024_avx2_enc(uint8_t *ct, uint8_t *ss, const uint8_t *pk);
extern int pqcrystals_kyber1024_avx2_dec(uint8_t *ss, const uint8_t *ct, const uint8_t *sk);
#endif
#if defined(OQS_ENABLE_KEM_kyber_1024_aarch64)
extern int PQCLEAN_KYBER1024_AARCH64_crypto_kem_keypair(uint8_t *pk, uint8_t *sk);
extern int PQCLEAN_KYBER1024_AARCH64_crypto_kem_enc(uint8_t *ct, uint8_t *ss, const uint8_t *pk);
extern int PQCLEAN_KYBER1024_AARCH64_crypto_kem_dec(uint8_t *ss, const uint8_t *ct, const uint8_t *sk);
#endif
OQS_API OQS_STATUS OQS_KEM_kyber_1024_keypair(uint8_t *public_key, uint8_t *secret_key) {
#if defined(OQS_ENABLE_KEM_kyber_1024_avx2)
#if defined(OQS_DIST_BUILD)
if (OQS_CPU_has_extension(OQS_CPU_EXT_AVX2) && OQS_CPU_has_extension(OQS_CPU_EXT_BMI2) && OQS_CPU_has_extension(OQS_CPU_EXT_POPCNT)) {
#endif /* OQS_DIST_BUILD */
return (OQS_STATUS) pqcrystals_kyber1024_avx2_keypair(public_key, secret_key);
#if defined(OQS_DIST_BUILD)
} else {
return (OQS_STATUS) pqcrystals_kyber1024_ref_keypair(public_key, secret_key);
}
#endif /* OQS_DIST_BUILD */
#elif defined(OQS_ENABLE_KEM_kyber_1024_aarch64)
#if defined(OQS_DIST_BUILD)
if (OQS_CPU_has_extension(OQS_CPU_EXT_ARM_NEON)) {
#endif /* OQS_DIST_BUILD */
return (OQS_STATUS) PQCLEAN_KYBER1024_AARCH64_crypto_kem_keypair(public_key, secret_key);
#if defined(OQS_DIST_BUILD)
} else {
return (OQS_STATUS) pqcrystals_kyber1024_ref_keypair(public_key, secret_key);
}
#endif /* OQS_DIST_BUILD */
#else
return (OQS_STATUS) pqcrystals_kyber1024_ref_keypair(public_key, secret_key);
#endif
}
OQS_API OQS_STATUS OQS_KEM_kyber_1024_encaps(uint8_t *ciphertext, uint8_t *shared_secret, const uint8_t *public_key) {
#if defined(OQS_ENABLE_KEM_kyber_1024_avx2)
#if defined(OQS_DIST_BUILD)
if (OQS_CPU_has_extension(OQS_CPU_EXT_AVX2) && OQS_CPU_has_extension(OQS_CPU_EXT_BMI2) && OQS_CPU_has_extension(OQS_CPU_EXT_POPCNT)) {
#endif /* OQS_DIST_BUILD */
return (OQS_STATUS) pqcrystals_kyber1024_avx2_enc(ciphertext, shared_secret, public_key);
#if defined(OQS_DIST_BUILD)
} else {
return (OQS_STATUS) pqcrystals_kyber1024_ref_enc(ciphertext, shared_secret, public_key);
}
#endif /* OQS_DIST_BUILD */
#elif defined(OQS_ENABLE_KEM_kyber_1024_aarch64)
#if defined(OQS_DIST_BUILD)
if (OQS_CPU_has_extension(OQS_CPU_EXT_ARM_NEON)) {
#endif /* OQS_DIST_BUILD */
return (OQS_STATUS) PQCLEAN_KYBER1024_AARCH64_crypto_kem_enc(ciphertext, shared_secret, public_key);
#if defined(OQS_DIST_BUILD)
} else {
return (OQS_STATUS) pqcrystals_kyber1024_ref_enc(ciphertext, shared_secret, public_key);
}
#endif /* OQS_DIST_BUILD */
#else
return (OQS_STATUS) pqcrystals_kyber1024_ref_enc(ciphertext, shared_secret, public_key);
#endif
}
OQS_API OQS_STATUS OQS_KEM_kyber_1024_decaps(uint8_t *shared_secret, const uint8_t *ciphertext, const uint8_t *secret_key) {
#if defined(OQS_ENABLE_KEM_kyber_1024_avx2)
#if defined(OQS_DIST_BUILD)
if (OQS_CPU_has_extension(OQS_CPU_EXT_AVX2) && OQS_CPU_has_extension(OQS_CPU_EXT_BMI2) && OQS_CPU_has_extension(OQS_CPU_EXT_POPCNT)) {
#endif /* OQS_DIST_BUILD */
return (OQS_STATUS) pqcrystals_kyber1024_avx2_dec(shared_secret, ciphertext, secret_key);
#if defined(OQS_DIST_BUILD)
} else {
return (OQS_STATUS) pqcrystals_kyber1024_ref_dec(shared_secret, ciphertext, secret_key);
}
#endif /* OQS_DIST_BUILD */
#elif defined(OQS_ENABLE_KEM_kyber_1024_aarch64)
#if defined(OQS_DIST_BUILD)
if (OQS_CPU_has_extension(OQS_CPU_EXT_ARM_NEON)) {
#endif /* OQS_DIST_BUILD */
return (OQS_STATUS) PQCLEAN_KYBER1024_AARCH64_crypto_kem_dec(shared_secret, ciphertext, secret_key);
#if defined(OQS_DIST_BUILD)
} else {
return (OQS_STATUS) pqcrystals_kyber1024_ref_dec(shared_secret, ciphertext, secret_key);
}
#endif /* OQS_DIST_BUILD */
#else
return (OQS_STATUS) pqcrystals_kyber1024_ref_dec(shared_secret, ciphertext, secret_key);
#endif
}
#endif

View file

@ -0,0 +1,6 @@
Public Domain (https://creativecommons.org/share-your-work/public-domain/cc0/);
or Apache 2.0 License (https://www.apache.org/licenses/LICENSE-2.0.html).
For Keccak and AES we are using public-domain
code from sources and by authors listed in
comments on top of the respective files.

View file

@ -0,0 +1,75 @@
#ifndef API_H
#define API_H
#include <stdint.h>
#define pqcrystals_kyber512_SECRETKEYBYTES 1632
#define pqcrystals_kyber512_PUBLICKEYBYTES 800
#define pqcrystals_kyber512_CIPHERTEXTBYTES 768
#define pqcrystals_kyber512_BYTES 32
#define pqcrystals_kyber512_ref_SECRETKEYBYTES pqcrystals_kyber512_SECRETKEYBYTES
#define pqcrystals_kyber512_ref_PUBLICKEYBYTES pqcrystals_kyber512_PUBLICKEYBYTES
#define pqcrystals_kyber512_ref_CIPHERTEXTBYTES pqcrystals_kyber512_CIPHERTEXTBYTES
#define pqcrystals_kyber512_ref_BYTES pqcrystals_kyber512_BYTES
int pqcrystals_kyber512_ref_keypair(uint8_t *pk, uint8_t *sk);
int pqcrystals_kyber512_ref_enc(uint8_t *ct, uint8_t *ss, const uint8_t *pk);
int pqcrystals_kyber512_ref_dec(uint8_t *ss, const uint8_t *ct, const uint8_t *sk);
#define pqcrystals_kyber512_90s_ref_SECRETKEYBYTES pqcrystals_kyber512_SECRETKEYBYTES
#define pqcrystals_kyber512_90s_ref_PUBLICKEYBYTES pqcrystals_kyber512_PUBLICKEYBYTES
#define pqcrystals_kyber512_90s_ref_CIPHERTEXTBYTES pqcrystals_kyber512_CIPHERTEXTBYTES
#define pqcrystals_kyber512_90s_ref_BYTES pqcrystals_kyber512_BYTES
int pqcrystals_kyber512_90s_ref_keypair(uint8_t *pk, uint8_t *sk);
int pqcrystals_kyber512_90s_ref_enc(uint8_t *ct, uint8_t *ss, const uint8_t *pk);
int pqcrystals_kyber512_90s_ref_dec(uint8_t *ss, const uint8_t *ct, const uint8_t *sk);
#define pqcrystals_kyber768_SECRETKEYBYTES 2400
#define pqcrystals_kyber768_PUBLICKEYBYTES 1184
#define pqcrystals_kyber768_CIPHERTEXTBYTES 1088
#define pqcrystals_kyber768_BYTES 32
#define pqcrystals_kyber768_ref_SECRETKEYBYTES pqcrystals_kyber768_SECRETKEYBYTES
#define pqcrystals_kyber768_ref_PUBLICKEYBYTES pqcrystals_kyber768_PUBLICKEYBYTES
#define pqcrystals_kyber768_ref_CIPHERTEXTBYTES pqcrystals_kyber768_CIPHERTEXTBYTES
#define pqcrystals_kyber768_ref_BYTES pqcrystals_kyber768_BYTES
int pqcrystals_kyber768_ref_keypair(uint8_t *pk, uint8_t *sk);
int pqcrystals_kyber768_ref_enc(uint8_t *ct, uint8_t *ss, const uint8_t *pk);
int pqcrystals_kyber768_ref_dec(uint8_t *ss, const uint8_t *ct, const uint8_t *sk);
#define pqcrystals_kyber768_90s_ref_SECRETKEYBYTES pqcrystals_kyber768_SECRETKEYBYTES
#define pqcrystals_kyber768_90s_ref_PUBLICKEYBYTES pqcrystals_kyber768_PUBLICKEYBYTES
#define pqcrystals_kyber768_90s_ref_CIPHERTEXTBYTES pqcrystals_kyber768_CIPHERTEXTBYTES
#define pqcrystals_kyber768_90s_ref_BYTES pqcrystals_kyber768_BYTES
int pqcrystals_kyber768_90s_ref_keypair(uint8_t *pk, uint8_t *sk);
int pqcrystals_kyber768_90s_ref_enc(uint8_t *ct, uint8_t *ss, const uint8_t *pk);
int pqcrystals_kyber768_90s_ref_dec(uint8_t *ss, const uint8_t *ct, const uint8_t *sk);
#define pqcrystals_kyber1024_SECRETKEYBYTES 3168
#define pqcrystals_kyber1024_PUBLICKEYBYTES 1568
#define pqcrystals_kyber1024_CIPHERTEXTBYTES 1568
#define pqcrystals_kyber1024_BYTES 32
#define pqcrystals_kyber1024_ref_SECRETKEYBYTES pqcrystals_kyber1024_SECRETKEYBYTES
#define pqcrystals_kyber1024_ref_PUBLICKEYBYTES pqcrystals_kyber1024_PUBLICKEYBYTES
#define pqcrystals_kyber1024_ref_CIPHERTEXTBYTES pqcrystals_kyber1024_CIPHERTEXTBYTES
#define pqcrystals_kyber1024_ref_BYTES pqcrystals_kyber1024_BYTES
int pqcrystals_kyber1024_ref_keypair(uint8_t *pk, uint8_t *sk);
int pqcrystals_kyber1024_ref_enc(uint8_t *ct, uint8_t *ss, const uint8_t *pk);
int pqcrystals_kyber1024_ref_dec(uint8_t *ss, const uint8_t *ct, const uint8_t *sk);
#define pqcrystals_kyber1024_90s_ref_SECRETKEYBYTES pqcrystals_kyber1024_SECRETKEYBYTES
#define pqcrystals_kyber1024_90s_ref_PUBLICKEYBYTES pqcrystals_kyber1024_PUBLICKEYBYTES
#define pqcrystals_kyber1024_90s_ref_CIPHERTEXTBYTES pqcrystals_kyber1024_CIPHERTEXTBYTES
#define pqcrystals_kyber1024_90s_ref_BYTES pqcrystals_kyber1024_BYTES
int pqcrystals_kyber1024_90s_ref_keypair(uint8_t *pk, uint8_t *sk);
int pqcrystals_kyber1024_90s_ref_enc(uint8_t *ct, uint8_t *ss, const uint8_t *pk);
int pqcrystals_kyber1024_90s_ref_dec(uint8_t *ss, const uint8_t *ct, const uint8_t *sk);
#endif

View file

@ -0,0 +1,128 @@
#include <stdint.h>
#include "params.h"
#include "cbd.h"
/*************************************************
* Name: load32_littleendian
*
* Description: load 4 bytes into a 32-bit integer
* in little-endian order
*
* Arguments: - const uint8_t *x: pointer to input byte array
*
* Returns 32-bit unsigned integer loaded from x
**************************************************/
static uint32_t load32_littleendian(const uint8_t x[4])
{
uint32_t r;
r = (uint32_t)x[0];
r |= (uint32_t)x[1] << 8;
r |= (uint32_t)x[2] << 16;
r |= (uint32_t)x[3] << 24;
return r;
}
/*************************************************
* Name: load24_littleendian
*
* Description: load 3 bytes into a 32-bit integer
* in little-endian order.
* This function is only needed for Kyber-512
*
* Arguments: - const uint8_t *x: pointer to input byte array
*
* Returns 32-bit unsigned integer loaded from x (most significant byte is zero)
**************************************************/
#if KYBER_ETA1 == 3
static uint32_t load24_littleendian(const uint8_t x[3])
{
uint32_t r;
r = (uint32_t)x[0];
r |= (uint32_t)x[1] << 8;
r |= (uint32_t)x[2] << 16;
return r;
}
#endif
/*************************************************
* Name: cbd2
*
* Description: Given an array of uniformly random bytes, compute
* polynomial with coefficients distributed according to
* a centered binomial distribution with parameter eta=2
*
* Arguments: - poly *r: pointer to output polynomial
* - const uint8_t *buf: pointer to input byte array
**************************************************/
static void cbd2(poly *r, const uint8_t buf[2*KYBER_N/4])
{
unsigned int i,j;
uint32_t t,d;
int16_t a,b;
for(i=0;i<KYBER_N/8;i++) {
t = load32_littleendian(buf+4*i);
d = t & 0x55555555;
d += (t>>1) & 0x55555555;
for(j=0;j<8;j++) {
a = (d >> (4*j+0)) & 0x3;
b = (d >> (4*j+2)) & 0x3;
r->coeffs[8*i+j] = a - b;
}
}
}
/*************************************************
* Name: cbd3
*
* Description: Given an array of uniformly random bytes, compute
* polynomial with coefficients distributed according to
* a centered binomial distribution with parameter eta=3.
* This function is only needed for Kyber-512
*
* Arguments: - poly *r: pointer to output polynomial
* - const uint8_t *buf: pointer to input byte array
**************************************************/
#if KYBER_ETA1 == 3
static void cbd3(poly *r, const uint8_t buf[3*KYBER_N/4])
{
unsigned int i,j;
uint32_t t,d;
int16_t a,b;
for(i=0;i<KYBER_N/4;i++) {
t = load24_littleendian(buf+3*i);
d = t & 0x00249249;
d += (t>>1) & 0x00249249;
d += (t>>2) & 0x00249249;
for(j=0;j<4;j++) {
a = (d >> (6*j+0)) & 0x7;
b = (d >> (6*j+3)) & 0x7;
r->coeffs[4*i+j] = a - b;
}
}
}
#endif
void poly_cbd_eta1(poly *r, const uint8_t buf[KYBER_ETA1*KYBER_N/4])
{
#if KYBER_ETA1 == 2
cbd2(r, buf);
#elif KYBER_ETA1 == 3
cbd3(r, buf);
#else
#error "This implementation requires eta1 in {2,3}"
#endif
}
void poly_cbd_eta2(poly *r, const uint8_t buf[KYBER_ETA2*KYBER_N/4])
{
#if KYBER_ETA2 == 2
cbd2(r, buf);
#else
#error "This implementation requires eta2 = 2"
#endif
}

View file

@ -0,0 +1,14 @@
#ifndef CBD_H
#define CBD_H
#include <stdint.h>
#include "params.h"
#include "poly.h"
#define poly_cbd_eta1 KYBER_NAMESPACE(poly_cbd_eta1)
void poly_cbd_eta1(poly *r, const uint8_t buf[KYBER_ETA1*KYBER_N/4]);
#define poly_cbd_eta2 KYBER_NAMESPACE(poly_cbd_eta2)
void poly_cbd_eta2(poly *r, const uint8_t buf[KYBER_ETA2*KYBER_N/4]);
#endif

View file

@ -0,0 +1,331 @@
#include <stddef.h>
#include <stdint.h>
#include "params.h"
#include "indcpa.h"
#include "polyvec.h"
#include "poly.h"
#include "ntt.h"
#include "symmetric.h"
#include "randombytes.h"
/*************************************************
* Name: pack_pk
*
* Description: Serialize the public key as concatenation of the
* serialized vector of polynomials pk
* and the public seed used to generate the matrix A.
*
* Arguments: uint8_t *r: pointer to the output serialized public key
* polyvec *pk: pointer to the input public-key polyvec
* const uint8_t *seed: pointer to the input public seed
**************************************************/
static void pack_pk(uint8_t r[KYBER_INDCPA_PUBLICKEYBYTES],
polyvec *pk,
const uint8_t seed[KYBER_SYMBYTES])
{
size_t i;
polyvec_tobytes(r, pk);
for(i=0;i<KYBER_SYMBYTES;i++)
r[i+KYBER_POLYVECBYTES] = seed[i];
}
/*************************************************
* Name: unpack_pk
*
* Description: De-serialize public key from a byte array;
* approximate inverse of pack_pk
*
* Arguments: - polyvec *pk: pointer to output public-key polynomial vector
* - uint8_t *seed: pointer to output seed to generate matrix A
* - const uint8_t *packedpk: pointer to input serialized public key
**************************************************/
static void unpack_pk(polyvec *pk,
uint8_t seed[KYBER_SYMBYTES],
const uint8_t packedpk[KYBER_INDCPA_PUBLICKEYBYTES])
{
size_t i;
polyvec_frombytes(pk, packedpk);
for(i=0;i<KYBER_SYMBYTES;i++)
seed[i] = packedpk[i+KYBER_POLYVECBYTES];
}
/*************************************************
* Name: pack_sk
*
* Description: Serialize the secret key
*
* Arguments: - uint8_t *r: pointer to output serialized secret key
* - polyvec *sk: pointer to input vector of polynomials (secret key)
**************************************************/
static void pack_sk(uint8_t r[KYBER_INDCPA_SECRETKEYBYTES], polyvec *sk)
{
polyvec_tobytes(r, sk);
}
/*************************************************
* Name: unpack_sk
*
* Description: De-serialize the secret key; inverse of pack_sk
*
* Arguments: - polyvec *sk: pointer to output vector of polynomials (secret key)
* - const uint8_t *packedsk: pointer to input serialized secret key
**************************************************/
static void unpack_sk(polyvec *sk, const uint8_t packedsk[KYBER_INDCPA_SECRETKEYBYTES])
{
polyvec_frombytes(sk, packedsk);
}
/*************************************************
* Name: pack_ciphertext
*
* Description: Serialize the ciphertext as concatenation of the
* compressed and serialized vector of polynomials b
* and the compressed and serialized polynomial v
*
* Arguments: uint8_t *r: pointer to the output serialized ciphertext
* poly *pk: pointer to the input vector of polynomials b
* poly *v: pointer to the input polynomial v
**************************************************/
static void pack_ciphertext(uint8_t r[KYBER_INDCPA_BYTES], polyvec *b, poly *v)
{
polyvec_compress(r, b);
poly_compress(r+KYBER_POLYVECCOMPRESSEDBYTES, v);
}
/*************************************************
* Name: unpack_ciphertext
*
* Description: De-serialize and decompress ciphertext from a byte array;
* approximate inverse of pack_ciphertext
*
* Arguments: - polyvec *b: pointer to the output vector of polynomials b
* - poly *v: pointer to the output polynomial v
* - const uint8_t *c: pointer to the input serialized ciphertext
**************************************************/
static void unpack_ciphertext(polyvec *b, poly *v, const uint8_t c[KYBER_INDCPA_BYTES])
{
polyvec_decompress(b, c);
poly_decompress(v, c+KYBER_POLYVECCOMPRESSEDBYTES);
}
/*************************************************
* Name: rej_uniform
*
* Description: Run rejection sampling on uniform random bytes to generate
* uniform random integers mod q
*
* Arguments: - int16_t *r: pointer to output buffer
* - unsigned int len: requested number of 16-bit integers (uniform mod q)
* - const uint8_t *buf: pointer to input buffer (assumed to be uniformly random bytes)
* - unsigned int buflen: length of input buffer in bytes
*
* Returns number of sampled 16-bit integers (at most len)
**************************************************/
static unsigned int rej_uniform(int16_t *r,
unsigned int len,
const uint8_t *buf,
unsigned int buflen)
{
unsigned int ctr, pos;
uint16_t val0, val1;
ctr = pos = 0;
while(ctr < len && pos + 3 <= buflen) {
val0 = ((buf[pos+0] >> 0) | ((uint16_t)buf[pos+1] << 8)) & 0xFFF;
val1 = ((buf[pos+1] >> 4) | ((uint16_t)buf[pos+2] << 4)) & 0xFFF;
pos += 3;
if(val0 < KYBER_Q)
r[ctr++] = val0;
if(ctr < len && val1 < KYBER_Q)
r[ctr++] = val1;
}
return ctr;
}
#define gen_a(A,B) gen_matrix(A,B,0)
#define gen_at(A,B) gen_matrix(A,B,1)
/*************************************************
* Name: gen_matrix
*
* Description: Deterministically generate matrix A (or the transpose of A)
* from a seed. Entries of the matrix are polynomials that look
* uniformly random. Performs rejection sampling on output of
* a XOF
*
* Arguments: - polyvec *a: pointer to ouptput matrix A
* - const uint8_t *seed: pointer to input seed
* - int transposed: boolean deciding whether A or A^T is generated
**************************************************/
#define GEN_MATRIX_NBLOCKS ((12*KYBER_N/8*(1 << 12)/KYBER_Q + XOF_BLOCKBYTES)/XOF_BLOCKBYTES)
// Not static for benchmarking
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;
xof_init(&state, seed);
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);
}
}
}
xof_release(&state);
}
/*************************************************
* Name: indcpa_keypair
*
* Description: Generates public and private key for the CPA-secure
* public-key encryption scheme underlying Kyber
*
* Arguments: - uint8_t *pk: pointer to output public key
* (of length KYBER_INDCPA_PUBLICKEYBYTES bytes)
* - uint8_t *sk: pointer to output private key
(of length KYBER_INDCPA_SECRETKEYBYTES bytes)
**************************************************/
void indcpa_keypair(uint8_t pk[KYBER_INDCPA_PUBLICKEYBYTES],
uint8_t sk[KYBER_INDCPA_SECRETKEYBYTES])
{
unsigned int i;
uint8_t buf[2*KYBER_SYMBYTES];
const uint8_t *publicseed = buf;
const uint8_t *noiseseed = buf+KYBER_SYMBYTES;
uint8_t nonce = 0;
polyvec a[KYBER_K], e, pkpv, skpv;
randombytes(buf, KYBER_SYMBYTES);
hash_g(buf, buf, KYBER_SYMBYTES);
gen_a(a, publicseed);
for(i=0;i<KYBER_K;i++)
poly_getnoise_eta1(&skpv.vec[i], noiseseed, nonce++);
for(i=0;i<KYBER_K;i++)
poly_getnoise_eta1(&e.vec[i], noiseseed, nonce++);
polyvec_ntt(&skpv);
polyvec_ntt(&e);
// matrix-vector multiplication
for(i=0;i<KYBER_K;i++) {
polyvec_basemul_acc_montgomery(&pkpv.vec[i], &a[i], &skpv);
poly_tomont(&pkpv.vec[i]);
}
polyvec_add(&pkpv, &pkpv, &e);
polyvec_reduce(&pkpv);
pack_sk(sk, &skpv);
pack_pk(pk, &pkpv, publicseed);
}
/*************************************************
* Name: indcpa_enc
*
* Description: Encryption function of the CPA-secure
* public-key encryption scheme underlying Kyber.
*
* Arguments: - uint8_t *c: pointer to output ciphertext
* (of length KYBER_INDCPA_BYTES bytes)
* - const uint8_t *m: pointer to input message
* (of length KYBER_INDCPA_MSGBYTES bytes)
* - const uint8_t *pk: pointer to input public key
* (of length KYBER_INDCPA_PUBLICKEYBYTES)
* - const uint8_t *coins: pointer to input random coins used as seed
* (of length KYBER_SYMBYTES) to deterministically
* generate all randomness
**************************************************/
void indcpa_enc(uint8_t c[KYBER_INDCPA_BYTES],
const uint8_t m[KYBER_INDCPA_MSGBYTES],
const uint8_t pk[KYBER_INDCPA_PUBLICKEYBYTES],
const uint8_t coins[KYBER_SYMBYTES])
{
unsigned int i;
uint8_t seed[KYBER_SYMBYTES];
uint8_t nonce = 0;
polyvec sp, pkpv, ep, at[KYBER_K], b;
poly v, k, epp;
unpack_pk(&pkpv, seed, pk);
poly_frommsg(&k, m);
gen_at(at, seed);
for(i=0;i<KYBER_K;i++)
poly_getnoise_eta1(sp.vec+i, coins, nonce++);
for(i=0;i<KYBER_K;i++)
poly_getnoise_eta2(ep.vec+i, coins, nonce++);
poly_getnoise_eta2(&epp, coins, nonce++);
polyvec_ntt(&sp);
// matrix-vector multiplication
for(i=0;i<KYBER_K;i++)
polyvec_basemul_acc_montgomery(&b.vec[i], &at[i], &sp);
polyvec_basemul_acc_montgomery(&v, &pkpv, &sp);
polyvec_invntt_tomont(&b);
poly_invntt_tomont(&v);
polyvec_add(&b, &b, &ep);
poly_add(&v, &v, &epp);
poly_add(&v, &v, &k);
polyvec_reduce(&b);
poly_reduce(&v);
pack_ciphertext(c, &b, &v);
}
/*************************************************
* Name: indcpa_dec
*
* Description: Decryption function of the CPA-secure
* public-key encryption scheme underlying Kyber.
*
* Arguments: - uint8_t *m: pointer to output decrypted message
* (of length KYBER_INDCPA_MSGBYTES)
* - const uint8_t *c: pointer to input ciphertext
* (of length KYBER_INDCPA_BYTES)
* - const uint8_t *sk: pointer to input secret key
* (of length KYBER_INDCPA_SECRETKEYBYTES)
**************************************************/
void indcpa_dec(uint8_t m[KYBER_INDCPA_MSGBYTES],
const uint8_t c[KYBER_INDCPA_BYTES],
const uint8_t sk[KYBER_INDCPA_SECRETKEYBYTES])
{
polyvec b, skpv;
poly v, mp;
unpack_ciphertext(&b, &v, c);
unpack_sk(&skpv, sk);
polyvec_ntt(&b);
polyvec_basemul_acc_montgomery(&mp, &skpv, &b);
poly_invntt_tomont(&mp);
poly_sub(&mp, &v, &mp);
poly_reduce(&mp);
poly_tomsg(m, &mp);
}

View file

@ -0,0 +1,25 @@
#ifndef INDCPA_H
#define INDCPA_H
#include <stdint.h>
#include "params.h"
#include "polyvec.h"
#define gen_matrix KYBER_NAMESPACE(gen_matrix)
void gen_matrix(polyvec *a, const uint8_t seed[KYBER_SYMBYTES], int transposed);
#define indcpa_keypair KYBER_NAMESPACE(indcpa_keypair)
void indcpa_keypair(uint8_t pk[KYBER_INDCPA_PUBLICKEYBYTES],
uint8_t sk[KYBER_INDCPA_SECRETKEYBYTES]);
#define indcpa_enc KYBER_NAMESPACE(indcpa_enc)
void indcpa_enc(uint8_t c[KYBER_INDCPA_BYTES],
const uint8_t m[KYBER_INDCPA_MSGBYTES],
const uint8_t pk[KYBER_INDCPA_PUBLICKEYBYTES],
const uint8_t coins[KYBER_SYMBYTES]);
#define indcpa_dec KYBER_NAMESPACE(indcpa_dec)
void indcpa_dec(uint8_t m[KYBER_INDCPA_MSGBYTES],
const uint8_t c[KYBER_INDCPA_BYTES],
const uint8_t sk[KYBER_INDCPA_SECRETKEYBYTES]);
#endif

View file

@ -0,0 +1,127 @@
#include <stddef.h>
#include <stdint.h>
#include "params.h"
#include "kem.h"
#include "indcpa.h"
#include "verify.h"
#include "symmetric.h"
#include "randombytes.h"
/*************************************************
* Name: crypto_kem_keypair
*
* Description: Generates public and private key
* for CCA-secure Kyber key encapsulation mechanism
*
* Arguments: - uint8_t *pk: pointer to output public key
* (an already allocated array of KYBER_PUBLICKEYBYTES bytes)
* - uint8_t *sk: pointer to output private key
* (an already allocated array of KYBER_SECRETKEYBYTES bytes)
*
* Returns 0 (success)
**************************************************/
int crypto_kem_keypair(uint8_t *pk,
uint8_t *sk)
{
size_t i;
indcpa_keypair(pk, sk);
for(i=0;i<KYBER_INDCPA_PUBLICKEYBYTES;i++)
sk[i+KYBER_INDCPA_SECRETKEYBYTES] = pk[i];
hash_h(sk+KYBER_SECRETKEYBYTES-2*KYBER_SYMBYTES, pk, KYBER_PUBLICKEYBYTES);
/* Value z for pseudo-random output on reject */
randombytes(sk+KYBER_SECRETKEYBYTES-KYBER_SYMBYTES, KYBER_SYMBYTES);
return 0;
}
/*************************************************
* Name: crypto_kem_enc
*
* Description: Generates cipher text and shared
* secret for given public key
*
* Arguments: - uint8_t *ct: pointer to output cipher text
* (an already allocated array of KYBER_CIPHERTEXTBYTES bytes)
* - uint8_t *ss: pointer to output shared secret
* (an already allocated array of KYBER_SSBYTES bytes)
* - const uint8_t *pk: pointer to input public key
* (an already allocated array of KYBER_PUBLICKEYBYTES bytes)
*
* Returns 0 (success)
**************************************************/
int crypto_kem_enc(uint8_t *ct,
uint8_t *ss,
const uint8_t *pk)
{
uint8_t buf[2*KYBER_SYMBYTES];
/* Will contain key, coins */
uint8_t kr[2*KYBER_SYMBYTES];
randombytes(buf, KYBER_SYMBYTES);
/* Don't release system RNG output */
hash_h(buf, buf, KYBER_SYMBYTES);
/* Multitarget countermeasure for coins + contributory KEM */
hash_h(buf+KYBER_SYMBYTES, pk, KYBER_PUBLICKEYBYTES);
hash_g(kr, buf, 2*KYBER_SYMBYTES);
/* coins are in kr+KYBER_SYMBYTES */
indcpa_enc(ct, buf, pk, kr+KYBER_SYMBYTES);
/* overwrite coins in kr with H(c) */
hash_h(kr+KYBER_SYMBYTES, ct, KYBER_CIPHERTEXTBYTES);
/* hash concatenation of pre-k and H(c) to k */
kdf(ss, kr, 2*KYBER_SYMBYTES);
return 0;
}
/*************************************************
* Name: crypto_kem_dec
*
* Description: Generates shared secret for given
* cipher text and private key
*
* Arguments: - uint8_t *ss: pointer to output shared secret
* (an already allocated array of KYBER_SSBYTES bytes)
* - const uint8_t *ct: pointer to input cipher text
* (an already allocated array of KYBER_CIPHERTEXTBYTES bytes)
* - const uint8_t *sk: pointer to input private key
* (an already allocated array of KYBER_SECRETKEYBYTES bytes)
*
* Returns 0.
*
* On failure, ss will contain a pseudo-random value.
**************************************************/
int crypto_kem_dec(uint8_t *ss,
const uint8_t *ct,
const uint8_t *sk)
{
size_t i;
int fail;
uint8_t buf[2*KYBER_SYMBYTES];
/* Will contain key, coins */
uint8_t kr[2*KYBER_SYMBYTES];
uint8_t cmp[KYBER_CIPHERTEXTBYTES];
const uint8_t *pk = sk+KYBER_INDCPA_SECRETKEYBYTES;
indcpa_dec(buf, ct, sk);
/* Multitarget countermeasure for coins + contributory KEM */
for(i=0;i<KYBER_SYMBYTES;i++)
buf[KYBER_SYMBYTES+i] = sk[KYBER_SECRETKEYBYTES-2*KYBER_SYMBYTES+i];
hash_g(kr, buf, 2*KYBER_SYMBYTES);
/* coins are in kr+KYBER_SYMBYTES */
indcpa_enc(cmp, buf, pk, kr+KYBER_SYMBYTES);
fail = verify(ct, cmp, KYBER_CIPHERTEXTBYTES);
/* overwrite coins in kr with H(c) */
hash_h(kr+KYBER_SYMBYTES, ct, KYBER_CIPHERTEXTBYTES);
/* Overwrite pre-k with z on re-encryption failure */
cmov(kr, sk+KYBER_SECRETKEYBYTES-KYBER_SYMBYTES, KYBER_SYMBYTES, fail);
/* hash concatenation of pre-k and H(c) to k */
kdf(ss, kr, 2*KYBER_SYMBYTES);
return 0;
}

View file

@ -0,0 +1,41 @@
#ifndef KEM_H
#define KEM_H
#include <stdint.h>
#include "params.h"
#define CRYPTO_SECRETKEYBYTES KYBER_SECRETKEYBYTES
#define CRYPTO_PUBLICKEYBYTES KYBER_PUBLICKEYBYTES
#define CRYPTO_CIPHERTEXTBYTES KYBER_CIPHERTEXTBYTES
#define CRYPTO_BYTES KYBER_SSBYTES
#if (KYBER_K == 2)
#ifdef KYBER_90S
#define CRYPTO_ALGNAME "Kyber512-90s"
#else
#define CRYPTO_ALGNAME "Kyber512"
#endif
#elif (KYBER_K == 3)
#ifdef KYBER_90S
#define CRYPTO_ALGNAME "Kyber768-90s"
#else
#define CRYPTO_ALGNAME "Kyber768"
#endif
#elif (KYBER_K == 4)
#ifdef KYBER_90S
#define CRYPTO_ALGNAME "Kyber1024-90s"
#else
#define CRYPTO_ALGNAME "Kyber1024"
#endif
#endif
#define crypto_kem_keypair KYBER_NAMESPACE(keypair)
int crypto_kem_keypair(uint8_t *pk, uint8_t *sk);
#define crypto_kem_enc KYBER_NAMESPACE(enc)
int crypto_kem_enc(uint8_t *ct, uint8_t *ss, const uint8_t *pk);
#define crypto_kem_dec KYBER_NAMESPACE(dec)
int crypto_kem_dec(uint8_t *ss, const uint8_t *ct, const uint8_t *sk);
#endif

Some files were not shown because too many files have changed in this diff Show more