| /* |
| Licensed to the Apache Software Foundation (ASF) under one |
| or more contributor license agreements. See the NOTICE file |
| distributed with this work for additional information |
| regarding copyright ownership. The ASF licenses this file |
| to you under the Apache License, Version 2.0 (the |
| "License"); you may not use this file except in compliance |
| with the License. You may obtain a copy of the License at |
| |
| http://www.apache.org/licenses/LICENSE-2.0 |
| |
| Unless required by applicable law or agreed to in writing, |
| software distributed under the License is distributed on an |
| "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| KIND, either express or implied. See the License for the |
| specific language governing permissions and limitations |
| under the License. |
| */ |
| |
| /* |
| 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 <amcl/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<32; 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]; |
| |
| #pragma omp parallel for |
| for(i=0; i<NTHREADS; i++) |
| { |
| rc = pqnist_sike_keys(seedkeys[i], SIKEpk[i], SIKEsk[i]); |
| if (rc) |
| { |
| fprintf(stderr, "FAILURE pqnist_keys rc: %d\n", rc); |
| OQS_MEM_cleanse(SIKEsk[i], OQS_KEM_sike_p751_length_secret_key); |
| 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, "FAILURE 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, "FAILURE 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, "FAILURE 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); |
| OCT_clear(&P[i]); |
| OCT_clear(&C[i]); |
| } |
| |
| KILL_CSPRNG(&RNG); |
| |
| printf("SUCCESS\n"); |
| exit(EXIT_SUCCESS); |
| } |