Skip to content

Instantly share code, notes, and snippets.

@bonedaddy
Last active July 17, 2020 22:50
Show Gist options
  • Save bonedaddy/0a86b1af8cda249c02ae0cc4970a83ad to your computer and use it in GitHub Desktop.
Save bonedaddy/0a86b1af8cda249c02ae0cc4970a83ad to your computer and use it in GitHub Desktop.
#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