Skip to content

Instantly share code, notes, and snippets.

@melvyniandrag
Created August 25, 2017 19:33
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save melvyniandrag/42e577d69e2350082f3b01fef686772d to your computer and use it in GitHub Desktop.
Save melvyniandrag/42e577d69e2350082f3b01fef686772d to your computer and use it in GitHub Desktop.
Integrating OpenSSL and MPI for testing purposes.
#include <mpi.h>
#include <openssl/evp.h>
#include <openssl/ec.h>
#include <iostream>
#include <cstring>
#include <cassert>
void handleErrors(){
;
}
void ecdh(size_t *secret_len)
{
MPI_Init(NULL, NULL);
// Find out rank, size
int world_rank;
MPI_Comm_rank(MPI_COMM_WORLD, &world_rank);
int world_size;
MPI_Comm_size(MPI_COMM_WORLD, &world_size);
std::cout << "starting computation on processor :" << world_rank << std::endl;
EVP_PKEY_CTX *pctx;
EVP_PKEY_CTX *kctx;
EVP_PKEY_CTX *ctx;
unsigned char *secret;
EVP_PKEY *pkey = NULL;
EVP_PKEY *peerkey;
EVP_PKEY *params = NULL;
/* NB: assumes pkey, peerkey have been already set up */
/* Create the context for parameter generation */
if(NULL == (pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_EC, NULL)))
handleErrors();
/* Initialise the parameter generation */
if(1 != EVP_PKEY_paramgen_init(pctx)) handleErrors();
/* We're going to use the ANSI X9.62 Prime 256v1 curve */
if(1 != EVP_PKEY_CTX_set_ec_paramgen_curve_nid(pctx, NID_X9_62_prime256v1)) handleErrors();
/* Create the parameter object params */
if (!EVP_PKEY_paramgen(pctx, &params)) handleErrors();
/* Create the context for the key generation */
if(NULL == (kctx = EVP_PKEY_CTX_new(params, NULL))) handleErrors();
/* Generate the key */
if(1 != EVP_PKEY_keygen_init(kctx)) handleErrors();
if (1 != EVP_PKEY_keygen(kctx, &pkey)) handleErrors();
/* Get the peer's public key, and provide the peer with our public key -
* how this is done will be specific to your circumstances */
assert( ( world_rank == 1 ) || ( world_rank == 0 ) );
const size_t KeySize = sizeof( EVP_PKEY );
std::cout << "Data transmission size: " << KeySize << std::endl;
const int Destination = ( world_rank + 1 ) % 2;
const int Source = Destination;
const int Tag = 0;
std::cout << "Begining mpi transaction on processor: " << world_rank << ", talking to processor: " << Destination << std::endl;
if( world_rank == 0 )
{
MPI_Send(pkey, KeySize, MPI_BYTE, Destination, Tag, MPI_COMM_WORLD);
}
else
{
MPI_Recv(peerkey, KeySize, MPI_BYTE, Source, Tag, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
}
std::cout << "Finishing first transmission and begining the next one." << std::endl;
if( world_rank == 0 )
{
MPI_Recv(peerkey, KeySize, MPI_BYTE, Source, Tag, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
}
else
{
MPI_Send(pkey, KeySize, MPI_BYTE, Destination, Tag, MPI_COMM_WORLD);
}
std::cout << "Finishing mpi transaction on processor: " << world_rank << std::endl;
/* Create the context for the shared secret derivation */
if(NULL == (ctx = EVP_PKEY_CTX_new(pkey, NULL))) handleErrors();
/* Initialise */
if(1 != EVP_PKEY_derive_init(ctx)) handleErrors();
/* Provide the peer public key */
if(1 != EVP_PKEY_derive_set_peer(ctx, peerkey)) handleErrors();
/* Determine buffer length for shared secret */
if(1 != EVP_PKEY_derive(ctx, NULL, secret_len)) handleErrors();
/* Create the buffer */
if(NULL == (secret = static_cast<unsigned char*>( OPENSSL_malloc(*secret_len)) )) handleErrors();
/* Derive the shared secret */
if(1 != (EVP_PKEY_derive(ctx, secret, secret_len))) handleErrors();
EVP_PKEY_CTX_free(ctx);
EVP_PKEY_free(peerkey);
EVP_PKEY_free(pkey);
EVP_PKEY_CTX_free(kctx);
EVP_PKEY_free(params);
EVP_PKEY_CTX_free(pctx);
/* Never use a derived secret directly. Typically it is passed
* through some hash function to produce a key */
std::cout << world_rank << " made secret : " << secret << std::endl;
MPI_Finalize();
}
int main(int argc, char** argv){
size_t secretLen = 0;
ecdh( &secretLen );
std::cout << secretLen << std::endl;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment