Skip to content
Permalink
main
Switch branches/tags

Name already in use

A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?
Go to file
 
 
Cannot retrieve contributors at this time
/*
* example_kem.c
*
* Minimal example of a Diffie-Hellman-style post-quantum key encapsulation
* implemented in liboqs.
*
* SPDX-License-Identifier: MIT
*/
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <oqs/oqs.h>
/* Cleaning up memory etc */
void cleanup_stack(uint8_t *secret_key, size_t secret_key_len,
uint8_t *shared_secret_e, uint8_t *shared_secret_d,
size_t shared_secret_len);
void cleanup_heap(uint8_t *secret_key, uint8_t *shared_secret_e,
uint8_t *shared_secret_d, uint8_t *public_key,
uint8_t *ciphertext, OQS_KEM *kem);
/* This function gives an example of the operations performed by both
* the decapsulator and the encapsulator in a single KEM session,
* using only compile-time macros and allocating variables
* statically on the stack, calling a specific algorithm's functions
* directly.
*
* The macros OQS_KEM_frodokem_640_aes_length_* and the functions
* OQS_KEM_frodokem_640_aes_* are only defined if the algorithm
* FrodoKEM-640-AES was enabled at compile-time which must be
* checked using the OQS_ENABLE_KEM_frodokem_640_aes macro.
*
* <oqs/oqsconfig.h>, which is included in <oqs/oqs.h>, contains macros
* indicating which algorithms were enabled when this instance of liboqs
* was compiled.
*/
static OQS_STATUS example_stack(void) {
#ifndef OQS_ENABLE_KEM_frodokem_640_aes // if FrodoKEM-640-AES was not enabled at compile-time
printf("[example_stack] OQS_KEM_frodokem_640_aes was not enabled at "
"compile-time.\n");
return OQS_ERROR;
#else
uint8_t public_key[OQS_KEM_frodokem_640_aes_length_public_key];
uint8_t secret_key[OQS_KEM_frodokem_640_aes_length_secret_key];
uint8_t ciphertext[OQS_KEM_frodokem_640_aes_length_ciphertext];
uint8_t shared_secret_e[OQS_KEM_frodokem_640_aes_length_shared_secret];
uint8_t shared_secret_d[OQS_KEM_frodokem_640_aes_length_shared_secret];
OQS_STATUS rc = OQS_KEM_frodokem_640_aes_keypair(public_key, secret_key);
if (rc != OQS_SUCCESS) {
fprintf(stderr, "ERROR: OQS_KEM_frodokem_640_aes_keypair failed!\n");
cleanup_stack(secret_key, OQS_KEM_frodokem_640_aes_length_secret_key,
shared_secret_e, shared_secret_d,
OQS_KEM_frodokem_640_aes_length_shared_secret);
return OQS_ERROR;
}
rc = OQS_KEM_frodokem_640_aes_encaps(ciphertext, shared_secret_e, public_key);
if (rc != OQS_SUCCESS) {
fprintf(stderr, "ERROR: OQS_KEM_frodokem_640_aes_encaps failed!\n");
cleanup_stack(secret_key, OQS_KEM_frodokem_640_aes_length_secret_key,
shared_secret_e, shared_secret_d,
OQS_KEM_frodokem_640_aes_length_shared_secret);
return OQS_ERROR;
}
rc = OQS_KEM_frodokem_640_aes_decaps(shared_secret_d, ciphertext, secret_key);
if (rc != OQS_SUCCESS) {
fprintf(stderr, "ERROR: OQS_KEM_frodokem_640_aes_decaps failed!\n");
cleanup_stack(secret_key, OQS_KEM_frodokem_640_aes_length_secret_key,
shared_secret_e, shared_secret_d,
OQS_KEM_frodokem_640_aes_length_shared_secret);
return OQS_ERROR;
}
printf("[example_stack] OQS_KEM_frodokem_640_aes operations completed.\n");
return OQS_SUCCESS; // success!
#endif
}
/* This function gives an example of the operations performed by both
* the decapsulator and the encapsulator in a single KEM session,
* allocating variables dynamically on the heap and calling the generic
* OQS_KEM object.
*
* This does not require the use of compile-time macros to check if the
* algorithm in question was enabled at compile-time; instead, the caller
* must check that the OQS_KEM object returned is not NULL.
*/
static OQS_STATUS example_heap(void) {
OQS_KEM *kem = NULL;
uint8_t *public_key = NULL;
uint8_t *secret_key = NULL;
uint8_t *ciphertext = NULL;
uint8_t *shared_secret_e = NULL;
uint8_t *shared_secret_d = NULL;
kem = OQS_KEM_new(OQS_KEM_alg_frodokem_640_aes);
if (kem == NULL) {
printf("[example_heap] OQS_KEM_frodokem_640_aes was not enabled at "
"compile-time.\n");
return OQS_ERROR;
}
public_key = malloc(kem->length_public_key);
secret_key = malloc(kem->length_secret_key);
ciphertext = malloc(kem->length_ciphertext);
shared_secret_e = malloc(kem->length_shared_secret);
shared_secret_d = malloc(kem->length_shared_secret);
if ((public_key == NULL) || (secret_key == NULL) || (ciphertext == NULL) ||
(shared_secret_e == NULL) || (shared_secret_d == NULL)) {
fprintf(stderr, "ERROR: malloc failed!\n");
cleanup_heap(secret_key, shared_secret_e, shared_secret_d, public_key,
ciphertext, kem);
return OQS_ERROR;
}
OQS_STATUS rc = OQS_KEM_keypair(kem, public_key, secret_key);
if (rc != OQS_SUCCESS) {
fprintf(stderr, "ERROR: OQS_KEM_keypair failed!\n");
cleanup_heap(secret_key, shared_secret_e, shared_secret_d, public_key,
ciphertext, kem);
return OQS_ERROR;
}
rc = OQS_KEM_encaps(kem, ciphertext, shared_secret_e, public_key);
if (rc != OQS_SUCCESS) {
fprintf(stderr, "ERROR: OQS_KEM_encaps failed!\n");
cleanup_heap(secret_key, shared_secret_e, shared_secret_d, public_key,
ciphertext, kem);
return OQS_ERROR;
}
rc = OQS_KEM_decaps(kem, shared_secret_d, ciphertext, secret_key);
if (rc != OQS_SUCCESS) {
fprintf(stderr, "ERROR: OQS_KEM_decaps failed!\n");
cleanup_heap(secret_key, shared_secret_e, shared_secret_d, public_key,
ciphertext, kem);
return OQS_ERROR;
}
printf("[example_heap] OQS_KEM_frodokem_640_aes operations completed.\n");
cleanup_heap(secret_key, shared_secret_e, shared_secret_d, public_key,
ciphertext, kem);
return OQS_SUCCESS; // success
}
int main(void) {
if (example_stack() == OQS_SUCCESS && example_heap() == OQS_SUCCESS) {
return EXIT_SUCCESS;
} else {
return EXIT_FAILURE;
}
}
void cleanup_stack(uint8_t *secret_key, size_t secret_key_len,
uint8_t *shared_secret_e, uint8_t *shared_secret_d,
size_t shared_secret_len) {
OQS_MEM_cleanse(secret_key, secret_key_len);
OQS_MEM_cleanse(shared_secret_e, shared_secret_len);
OQS_MEM_cleanse(shared_secret_d, shared_secret_len);
}
void cleanup_heap(uint8_t *secret_key, uint8_t *shared_secret_e,
uint8_t *shared_secret_d, uint8_t *public_key,
uint8_t *ciphertext, OQS_KEM *kem) {
if (kem != NULL) {
OQS_MEM_secure_free(secret_key, kem->length_secret_key);
OQS_MEM_secure_free(shared_secret_e, kem->length_shared_secret);
OQS_MEM_secure_free(shared_secret_d, kem->length_shared_secret);
}
OQS_MEM_insecure_free(public_key);
OQS_MEM_insecure_free(ciphertext);
OQS_KEM_free(kem);
}