blob: 73fe7b0da08041beea7ea7aaeab03d266d05ce30 [file] [log] [blame]
/*
Encapsulate a secret and use the secret to encrypt a message
Decapsulate the secret and use the secret to decrypt the encrypted message
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <amcl/utils.h>
#include <amcl/randapi.h>
#include <amcl/bls_BLS381.h>
#include <oqs/oqs.h>
#include <pqnist/pqnist.h>
#define NTHREADS 8
#define MAXSIZE 256
#define G2LEN 4*BFS_BLS381
int main()
{
int i,rc;
// Seed value for CSPRNG
char seed[PQNIST_SEED_LENGTH];
octet SEED = {sizeof(seed),sizeof(seed),seed};
// Seed value for key generation
char seedkeys[NTHREADS][PQNIST_SEED_LENGTH];
csprng RNG;
// Initialization vector
char iv[PQNIST_AES_IV_LENGTH];
octet IV= {sizeof(iv),sizeof(iv),iv};
// Message to be sent to Bob
char p[NTHREADS][MAXSIZE];
octet P[NTHREADS];
// AES CBC ciphertext
char c[NTHREADS][MAXSIZE];
octet C[NTHREADS];
// non random seed value
for (i=0; i<PQNIST_SEED_LENGTH; i++) SEED.val[i]=i+1;
printf("SEED: ");
OCT_output(&SEED);
printf("\n");
// initialise random number generator
CREATE_CSPRNG(&RNG,&SEED);
// Initialise key generation seed
for(i=0; i<NTHREADS; i++)
{
for(int j=0; j<PQNIST_SEED_LENGTH; j++)
{
seedkeys[i][j] = i;
}
}
// Bob's SIKE keys
uint8_t SIKEpk[NTHREADS][OQS_KEM_sike_p751_length_public_key];
uint8_t SIKEsk[NTHREADS][OQS_KEM_sike_p751_length_secret_key];
// Alice's BLS keys (not used)
char BLSpk[NTHREADS][G2LEN];
char BLSsk[NTHREADS][BGS_BLS381];
#pragma omp parallel for
for(i=0; i<NTHREADS; i++)
{
rc = pqnist_keys(seedkeys[i], SIKEpk[i], SIKEsk[i], BLSpk[i], BLSsk[i]);
if (rc)
{
fprintf(stderr, "ERROR pqnist_keys rc: %d\n", rc);
exit(EXIT_FAILURE);
}
int j = OQS_KEM_sike_p751_length_public_key;
printf("Bob SIKE pklen %d pk: ", j);
amcl_print_hex(SIKEpk[i], j);
j = OQS_KEM_sike_p751_length_secret_key;
printf("Bob SIKE sklen %d sk: ", j);
amcl_print_hex(SIKEsk[i], j);
}
// Alice
for(i=0; i<NTHREADS; i++)
{
bzero(p[i],sizeof(p[i]));
P[i].max = MAXSIZE;
P[i].len = sprintf(p[i], "Hello Bob! This is a message from Alice %d", i);
P[i].val = p[i];
// Pad message
int l = 16 - (P[i].len % 16);
if (l < 16)
{
OCT_jbyte(&P[i],0,l);
}
}
// Random initialization value
generateRandom(&RNG,&IV);
printf("Alice IV: ");
OCT_output(&IV);
// Copy plaintext
for(i=0; i<NTHREADS; i++)
{
C[i].val = c[i];
C[i].max = MAXSIZE;
OCT_copy(&C[i],&P[i]);
printf("Alice Plaintext: ");
OCT_output_string(&C[i]);
printf("\n");
}
// SIKE encapsulated key
uint8_t ek[NTHREADS][OQS_KEM_sike_p751_length_ciphertext];
#pragma omp parallel for
for(i=0; i<NTHREADS; i++)
{
// Generate an AES which is ecapsulated using SIKE. Use this key to
// AES encrypt the K parameter.
rc = pqnist_encapsulate_encrypt(C[i].val, C[i].len, IV.val, SIKEpk[i], ek[i]);
if(rc)
{
fprintf(stderr, "ERROR pqnist_encapsulate_encrypt rc: %d\n", rc);
exit(EXIT_FAILURE);
}
printf("Alice ciphertext: ");
OCT_output(&C[i]);
printf("Alice ek %lu ek: ", sizeof(ek[i]));
amcl_print_hex(ek[i], sizeof(ek[i]));
printf("\n");
}
// Bob
#pragma omp parallel for
for(i=0; i<NTHREADS; i++)
{
// Obtain encapsulated AES key and decrypt C
rc = pqnist_decapsulate_decrypt(C[i].val, C[i].len, IV.val, SIKEsk[i], ek[i]);
if(rc)
{
fprintf(stderr, "ERROR pqnist_decapsulate_decrypt rc: %d\n", rc);
exit(EXIT_FAILURE);
}
printf("Bob Plaintext: ");
OCT_output(&C[i]);
printf("Bob Plaintext: ");
OCT_output_string(&C[i]);
printf("\n");
// Compare sent and recieved message (returns 0 for failure)
rc = OCT_comp(&P[i],&C[i]);
if(!rc)
{
fprintf(stderr, "ERROR OCT_comp rc: %d\n", rc);
exit(EXIT_FAILURE);
}
}
// clear memory
OCT_clear(&IV);
for(i=0; i<NTHREADS; i++)
{
OQS_MEM_cleanse(SIKEsk[i], OQS_KEM_sike_p751_length_secret_key);
OQS_MEM_cleanse(BLSsk[i], OQS_SIG_picnic_L5_FS_length_secret_key);
OCT_clear(&P[i]);
OCT_clear(&C[i]);
}
KILL_CSPRNG(&RNG);
exit(EXIT_SUCCESS);
}