Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add a native wrapper for Key Agreements - DH & EC
- Loading branch information
Showing
5 changed files
with
219 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
#include "jssl.h" | ||
#include <openssl/evp.h> | ||
|
||
typedef enum key_agreement_algorithm { | ||
DIFFIE_HELLMAN, // Diffie-Hellman | ||
ELLIPTIC_CURVE // Elliptic-Curve | ||
} key_agreement_algorithm; | ||
|
||
typedef struct shared_secret { | ||
byte *bytes; | ||
int length; | ||
} shared_secret; | ||
|
||
typedef struct key_agreement { | ||
OSSL_LIB_CTX *libctx; | ||
key_agreement_algorithm algorithm; | ||
EVP_PKEY *private_key; | ||
EVP_PKEY *peer_public_key; | ||
shared_secret *secret; | ||
} key_agreement; | ||
|
||
typedef struct key_pair { | ||
EVP_PKEY *key; | ||
//EVP_PKEY_CTX *ctx; | ||
} key_pair; | ||
|
||
key_pair *generate_key(key_agreement_algorithm algo); | ||
|
||
key_agreement* init_key_agreement(key_agreement_algorithm algo, OSSL_LIB_CTX *libctx); | ||
|
||
void set_private_key(key_agreement *agreement, key_pair *private_key); | ||
|
||
void set_peer_key(key_agreement *agreement, key_pair *peer_public_key); | ||
|
||
shared_secret *generate_shared_secret(key_agreement *agreement); | ||
|
||
int get_shared_secret_bytes(key_agreement *agreement, byte secret[]); | ||
|
||
key_pair *generate_key(key_agreement_algorithm algo); | ||
|
||
void free_key_agreement(key_agreement *this); | ||
|
||
void free_shared_secret(shared_secret *this); | ||
|
||
void free_key_pair(key_pair *this); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,115 @@ | ||
#include "keyagreement.h" | ||
|
||
key_agreement* init_key_agreement(key_agreement_algorithm algo, OSSL_LIB_CTX *libctx) { | ||
key_agreement agreement = {0}; | ||
key_agreement *new_agreement = (key_agreement*)malloc(sizeof(key_agreement)); | ||
*new_agreement = agreement; | ||
new_agreement->algorithm = algo; | ||
new_agreement->libctx = libctx; | ||
} | ||
|
||
void set_private_key(key_agreement *agreement, key_pair *private_key) { | ||
agreement->private_key = private_key->key; | ||
} | ||
|
||
void set_peer_key(key_agreement *agreement, key_pair *peer_public_key) { | ||
agreement->peer_public_key = peer_public_key->key; | ||
} | ||
|
||
shared_secret *generate_shared_secret(key_agreement *agreement) { | ||
if (agreement->private_key == NULL || agreement->peer_public_key == NULL) { | ||
return NULL; | ||
} | ||
|
||
EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new_from_pkey(agreement->libctx, agreement->private_key, NULL); | ||
if (ctx == NULL) { | ||
return NULL; | ||
} | ||
|
||
if (EVP_PKEY_derive_init(ctx) <= 0) { | ||
return NULL; | ||
} | ||
|
||
if (EVP_PKEY_derive_set_peer(ctx, agreement->peer_public_key) <= 0) { | ||
return NULL; | ||
} | ||
|
||
size_t secret_length = 0; | ||
if (EVP_PKEY_derive(ctx, NULL, &secret_length) <= 0) { | ||
return NULL; | ||
} | ||
|
||
byte *secret_bytes = OPENSSL_malloc(secret_length); | ||
|
||
if (secret_bytes == NULL) { | ||
return NULL; | ||
} | ||
|
||
if (EVP_PKEY_derive(ctx, secret_bytes, &secret_length) <= 0) { | ||
return NULL; | ||
} | ||
|
||
shared_secret *secret = (shared_secret*)malloc(sizeof(shared_secret)); | ||
secret->bytes = secret_bytes; | ||
secret->length = secret_length; | ||
agreement->secret = secret; | ||
return secret; | ||
} | ||
|
||
int get_shared_secret(key_agreement *agreement, byte secret[]) { | ||
if (secret != NULL) { | ||
memcpy(secret, agreement->secret->bytes, agreement->secret->length); | ||
} | ||
return agreement->secret->length; | ||
} | ||
|
||
key_pair *generate_key(key_agreement_algorithm algo) { | ||
EVP_PKEY_CTX *pctx = NULL; | ||
EVP_PKEY *key = NULL; | ||
OSSL_PARAM params[2]; | ||
if (algo == DIFFIE_HELLMAN) { | ||
if(NULL == (pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_DH, NULL))) { | ||
return NULL; | ||
} | ||
params[0] = OSSL_PARAM_construct_utf8_string("group", "ffdhe2048", 0); | ||
params[1] = OSSL_PARAM_construct_end(); | ||
} else { | ||
if(NULL == (pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_EC, NULL))) { | ||
return NULL; | ||
} | ||
params[0] = OSSL_PARAM_construct_utf8_string("group", "prime256v1", 0); | ||
params[1] = OSSL_PARAM_construct_end(); | ||
} | ||
|
||
if(EVP_PKEY_keygen_init(pctx) <= 0) { | ||
return NULL; | ||
} | ||
|
||
EVP_PKEY_CTX_set_params(pctx, params); | ||
|
||
if(EVP_PKEY_keygen(pctx, &key) <= 0) { | ||
return NULL; | ||
} | ||
key_pair *new_key = (key_pair*) malloc(sizeof(key_pair)); | ||
new_key->key = key; | ||
return new_key; | ||
} | ||
|
||
void free_shared_secret(shared_secret *this) { | ||
free(this->bytes); | ||
free(this); | ||
} | ||
|
||
void free_key_agreement(key_agreement *this) { | ||
EVP_PKEY_free(this->private_key); | ||
EVP_PKEY_free(this->peer_public_key); | ||
free_shared_secret(this->secret); | ||
free(this); | ||
} | ||
|
||
void free_key_pair(key_pair *this) { | ||
EVP_PKEY_free(this->key); | ||
free(this); | ||
} | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
#include "jssl.h" | ||
#include "keyagreement.h" | ||
|
||
int compare(shared_secret *s1, shared_secret *s2) { | ||
if (s1 == NULL || s2 == NULL) return 0; | ||
|
||
if (s1->length != s2->length) return 0; | ||
|
||
for(int i = 0; i < s1->length; i++) { | ||
if (s1->bytes[i] != s2->bytes[i]) return 0; | ||
} | ||
|
||
return 1; | ||
} | ||
|
||
void test(key_agreement_algorithm algo, OSSL_LIB_CTX *libctx) { | ||
switch(algo) { | ||
case DIFFIE_HELLMAN: printf("Testing DIFFIE_HELLMAN key-agreement: "); break; | ||
case ELLIPTIC_CURVE: printf("Testing ELLIPTIC_CURVE key-agreement: "); break; | ||
} | ||
|
||
shared_secret *alice_secret, *bob_secret; | ||
|
||
key_pair *alice_key = generate_key(algo); | ||
key_pair *bob_key = generate_key(algo); | ||
|
||
key_agreement *alice = init_key_agreement(algo, libctx); | ||
set_private_key(alice, alice_key); | ||
set_peer_key(alice, bob_key); | ||
alice_secret = generate_shared_secret(alice); | ||
|
||
|
||
key_agreement *bob = init_key_agreement(algo, libctx); | ||
set_private_key(bob, bob_key); | ||
set_peer_key(bob, alice_key); | ||
bob_secret = generate_shared_secret(bob); | ||
|
||
if (compare(alice_secret, bob_secret)) { | ||
printf(" PASSED\n"); | ||
} | ||
|
||
free_key_agreement(alice); | ||
free_key_agreement(bob); | ||
} | ||
|
||
int main(int argc, char *argv[]) { | ||
OSSL_LIB_CTX *libctx = load_openssl_fips_provider("/usr/local/ssl/openssl.cnf"); | ||
test(DIFFIE_HELLMAN, libctx); | ||
test(ELLIPTIC_CURVE, libctx); | ||
} | ||
|