Last active
July 17, 2020 22:50
-
-
Save bonedaddy/0a86b1af8cda249c02ae0cc4970a83ad to your computer and use it in GitHub Desktop.
This file contains hidden or 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
#include <wolfssl/options.h> | |
#include <wolfssl/wolfcrypt/sha256.h> | |
#include <stdio.h> | |
#include "mbedtls/ecdsa.h" | |
#include "mbedtls/pk.h" | |
#include "mbedtls/asn1write.h" | |
#include "mbedtls/bignum.h" | |
#include "mbedtls/config.h" | |
#include "mbedtls/ctr_drbg.h" | |
#include "mbedtls/entropy.h" | |
#include "mbedtls/error.h" | |
#include "mbedtls/oid.h" | |
#include "mbedtls/platform.h" | |
#include "mbedtls/x509.h" | |
#include <assert.h> | |
typedef struct ecdsa_public_key { | |
unsigned char *data; | |
int len; | |
} ecdsa_public_key_t; | |
typedef struct ecdsa_private_key { | |
mbedtls_pk_context pk_ctx; | |
mbedtls_ecdsa_context ecdsa_ctx; | |
pthread_mutex_t mutex; | |
} ecdsa_private_key_t; | |
ecdsa_public_key_t *libp2p_crypto_ecdsa_keypair_public(ecdsa_private_key_t *pk); | |
ecdsa_private_key_t * | |
libp2p_crypto_ecdsa_pem_to_private_key(unsigned char *pem_input); | |
int libp2p_crypto_ecdsa_keypair_generation(unsigned char *output, | |
mbedtls_ecp_group_id curve); | |
void print_mbedtls_error(int errcode); | |
void print_mbedtls_error(int errcode) { | |
char buffer[1024]; | |
mbedtls_strerror(errcode, buffer, 1024); | |
printf("mbedtls failure detected:\t%s\n", buffer); | |
} | |
ecdsa_private_key_t * | |
libp2p_crypto_ecdsa_pem_to_private_key(unsigned char *pem_input) { | |
mbedtls_pk_context pk_context; | |
mbedtls_ecdsa_context ecdsa_context; | |
mbedtls_pk_init(&pk_context); | |
mbedtls_ecdsa_init(&ecdsa_context); | |
int rc = mbedtls_pk_parse_key(&pk_context, pem_input, | |
strlen((char *)pem_input) + 1, NULL, 0); | |
if (rc != 0) { | |
print_mbedtls_error(rc); | |
return NULL; | |
} | |
rc = mbedtls_ecdsa_from_keypair(&ecdsa_context, mbedtls_pk_ec(pk_context)); | |
if (rc != 0) { | |
print_mbedtls_error(rc); | |
return NULL; | |
} | |
ecdsa_private_key_t *pk = malloc(sizeof(ecdsa_private_key_t) + | |
sizeof(pk_context) + sizeof(ecdsa_context)); | |
pk->ecdsa_ctx = ecdsa_context; | |
pk->pk_ctx = pk_context; | |
pthread_mutex_init(&pk->mutex, NULL); | |
return pk; | |
} | |
/*! | |
* @brief frees up resources allocated for the public key | |
*/ | |
int libp2p_crypto_ecdsa_free_public(ecdsa_public_key_t *pk) { | |
free(pk->data); | |
free(pk); | |
return 0; | |
} | |
/*! | |
* @brief frees up resources allocated for the private key | |
*/ | |
int libp2p_crypto_ecdsa_free(ecdsa_private_key_t *pk) { | |
mbedtls_pk_free(&pk->pk_ctx); | |
mbedtls_ecdsa_free(&pk->ecdsa_ctx); | |
pthread_mutex_destroy(&pk->mutex); | |
free(pk); | |
return 0; | |
} | |
int main(void) { | |
unsigned char *output = calloc(sizeof(unsigned char), 1024); | |
int rc = | |
libp2p_crypto_ecdsa_keypair_generation(output, MBEDTLS_ECP_DP_SECP256R1); | |
assert(rc == 1); | |
ecdsa_private_key_t *priv_key = libp2p_crypto_ecdsa_pem_to_private_key(output); | |
ecdsa_public_key_t *pub_key = libp2p_crypto_ecdsa_keypair_public(priv_key); | |
Sha256 sha; | |
unsigned char *p = calloc(sizeof(unsigned char), 1024); | |
wc_InitSha256(&sha); | |
wc_Sha256Update(&sha, pub_key->data, pub_key->len); | |
wc_Sha256Final(&sha, p); | |
wc_Sha256Free(&sha); | |
printf("len %lu\n", strlen((char *)p)); | |
libp2p_crypto_ecdsa_free(priv_key); | |
libp2p_crypto_ecdsa_free_public(pub_key); | |
free(output); | |
free(p); | |
} | |
ecdsa_public_key_t *libp2p_crypto_ecdsa_keypair_public(ecdsa_private_key_t *pk) { | |
unsigned char output_buf[1024]; | |
int rc = mbedtls_pk_write_pubkey_pem(&pk->pk_ctx, output_buf, 1024); | |
if (rc != 0) { | |
print_mbedtls_error(rc); | |
return NULL; | |
} | |
int len; | |
for (int i = 0; i < 1024; i++) { | |
if (output_buf[i] == '\0') { | |
len = i; | |
break; | |
} | |
} | |
ecdsa_public_key_t *pub_key = | |
calloc(sizeof(ecdsa_public_key_t), sizeof(ecdsa_public_key_t)); | |
pub_key->data = calloc(sizeof(unsigned char), len); | |
pub_key->len = len; | |
memcpy(pub_key->data, output_buf, len); | |
return pub_key; | |
} | |
int libp2p_crypto_ecdsa_keypair_generation(unsigned char *output, | |
mbedtls_ecp_group_id curve) { | |
mbedtls_pk_context ecdsa_key_pair; | |
mbedtls_entropy_context entropy_context; | |
mbedtls_ctr_drbg_context ctr_drb_context; | |
/*! * @todo figure out if we need this | |
*/ | |
const char *pers = "ecdsa"; | |
// initialize mbedtls context(s) | |
mbedtls_ctr_drbg_init(&ctr_drb_context); | |
mbedtls_entropy_init(&entropy_context); | |
mbedtls_pk_init(&ecdsa_key_pair); | |
mbedtls_pk_setup(&ecdsa_key_pair, mbedtls_pk_info_from_type(MBEDTLS_PK_ECKEY)); | |
// seed entropy generation | |
int rc = mbedtls_ctr_drbg_seed(&ctr_drb_context, mbedtls_entropy_func, | |
&entropy_context, (const unsigned char *)pers, | |
strlen(pers) != 0); | |
if (rc != 0) { | |
print_mbedtls_error(rc); | |
// TODO(bonedaddy): free up memory | |
return 0; | |
} | |
// generate the actual ecdsa keypair | |
rc = mbedtls_ecdsa_genkey(mbedtls_pk_ec(ecdsa_key_pair), curve, | |
mbedtls_ctr_drbg_random, &ctr_drb_context | |
); | |
if (rc != 0) { | |
print_mbedtls_error(rc); | |
return 0; | |
} | |
// write the private key in PEM format to output | |
rc = mbedtls_pk_write_key_pem(&ecdsa_key_pair, output, 1024); | |
if (rc != 0) { | |
print_mbedtls_error(rc); | |
return 0; | |
} | |
// free up allocated resources | |
mbedtls_pk_free(&ecdsa_key_pair); | |
mbedtls_ctr_drbg_free(&ctr_drb_context); | |
mbedtls_entropy_free(&entropy_context); | |
return 1; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment