diff --git a/lib/crypto.c b/lib/crypto.c index d2e99df..41e8abd 100644 --- a/lib/crypto.c +++ b/lib/crypto.c @@ -26,12 +26,15 @@ #include #include #include +#include #include #include #include #include +#include "utils.h" + struct aes_ctx_s { EVP_CIPHER_CTX *cipher_ctx; uint8_t key[AES_128_BLOCK_SIZE]; @@ -355,24 +358,17 @@ const unsigned char* ed25519_secret_key(const ed25519_key_t *key) { return (const unsigned char *) key->ed_secret; } -int extract_evp_private_key(unsigned char *privkey, int keylen, EVP_PKEY *key) { +int +extract_evp_private_key(unsigned char *privkey, int keylen, char *data) { int count = 0; unsigned int val; unsigned int part1 = 0; int part = 0; unsigned char start[4] = { 0x20, 0x20, 0x20, 0x20 }; - int bufsize = 512; /*should be big enough */ - void *buf = malloc(bufsize); - BIO *bp = BIO_new(BIO_s_mem()); - EVP_PKEY_print_private(bp, key, 0, NULL); - BIO_read(bp, buf, bufsize); - BIO_free(bp); + printf("%s\n", data); - char *data = (char *) buf; - //printf("%s\n", data); - - for (int i = 0; i < bufsize ; i ++ ) { + for (int i = 0; i < strlen(data); i ++ ) { if (memcmp(data, start, 4)) { data ++; } else { @@ -408,13 +404,12 @@ int extract_evp_private_key(unsigned char *privkey, int keylen, EVP_PKEY *key) { } } - free (buf); if (count != keylen) goto error; - //for (int i = 0; i < keylen; i++) { - // printf("%2.2x ", *(privkey + i)); - //} - //printf("\n"); + for (int i = 0; i < keylen; i++) { + printf("%2.2x ", *(privkey + i)); + } + printf("\n"); return 0; error:; @@ -422,27 +417,68 @@ int extract_evp_private_key(unsigned char *privkey, int keylen, EVP_PKEY *key) { return -1; } -ed25519_key_t *ed25519_key_generate(void) { +ed25519_key_t *ed25519_key_generate(const char *keyfile) { ed25519_key_t *key; EVP_PKEY_CTX *pctx; - + BIO *bp; + FILE *file; + bool new_pk = false; + + key = calloc(1, sizeof(ed25519_key_t)); assert(key); - - pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_ED25519, NULL); - if (!pctx) { - handle_error(__func__); + + if (keyfile) { + file = fopen(keyfile, "r"); + if (file) { + bp = BIO_new_fp(file, BIO_NOCLOSE); + key->pkey = PEM_read_PrivateKey(file, NULL, NULL, NULL); + BIO_free(bp); + fclose(file); + if (!key->pkey) { + new_pk = true; + } + } else { + new_pk = true; + } + } else { + new_pk = true; } - if (!EVP_PKEY_keygen_init(pctx)) { - handle_error(__func__); - } - if (!EVP_PKEY_keygen(pctx, &key->pkey)) { - handle_error(__func__); - } - EVP_PKEY_CTX_free(pctx); - extract_evp_private_key(key->ed_secret, ED25519_KEY_SIZE, *(&key->pkey)); + if (new_pk) { + pctx = EVP_PKEY_CTX_new_id(EVP_PKEY_ED25519, NULL); + if (!pctx) { + handle_error(__func__); + } + if (!EVP_PKEY_keygen_init(pctx)) { + handle_error(__func__); + } + if (!EVP_PKEY_keygen(pctx, &key->pkey)) { + handle_error(__func__); + } + EVP_PKEY_CTX_free(pctx); + if (keyfile) { + file = fopen(keyfile, "w"); + if (file) { + bp = BIO_new_fp(file, BIO_NOCLOSE); + PEM_write_bio_PrivateKey(bp, key->pkey, NULL, NULL, 0, NULL, NULL); + BIO_free(bp); + fclose(file); + } else { + printf("fopen failed, errno = %d\n", errno); + } + } + } + int bufsize = 512; /*should be big enough */ + void *buf = malloc(bufsize); + bp = BIO_new(BIO_s_mem()); + EVP_PKEY_print_private(bp, key->pkey, 0, NULL); + BIO_read(bp, buf, bufsize); + BIO_free(bp); + + private_key_from_EVP_PKEY_print_private(key->ed_secret, ED25519_KEY_SIZE, (char *) buf); + free(buf); return key; } diff --git a/lib/utils.c b/lib/utils.c index 561e79b..e21ef7f 100644 --- a/lib/utils.c +++ b/lib/utils.c @@ -196,6 +196,60 @@ char *utils_pk_to_string(const unsigned char *pk, int pk_len) { return pk_str; } +int +private_key_from_EVP_PKEY_print_private(unsigned char *privkey, int keylen, char *data) { + int count = 0; + unsigned int val; + unsigned int part1 = 0; + int part = 0; + unsigned char start[4] = { 0x20, 0x20, 0x20, 0x20 }; + + /* data must be output of EVP_PKEY_print_private */ + + for (int i = 0; i < strlen(data); i ++ ) { + if (memcmp(data, start, 4)) { + data ++; + } else { + data += 4; + break; + } + } + + int datalen = strlen(data); + for (int i = 0; (count < keylen && i < datalen); i++) { + val = 64; + if ('0' <= *data && *data <= '9') val = *data - '0'; + if ('a' <= *data && *data <= 'f') val = 10 + *data - 'a'; + if ('A' <= *data && *data <= 'F') val = 10 + *data - 'A'; + if (val == 64) { + data++; + continue; + } + part++; + part = part% 2; + switch (part) { + case 1: + part1 = val; + data++; + break; + case 0: + privkey[count] = (unsigned char) (val + (part1 << 4)); + count++; + data++; + break; + default: + break; + } + } + + if (count != keylen) goto error; + + return 0; + error:; + memset(privkey, 0, keylen); + return -1; +} + char *utils_data_to_string(const unsigned char *data, int datalen, int chars_per_line) { assert(datalen >= 0); assert(chars_per_line > 0); diff --git a/lib/utils.h b/lib/utils.h index d557e2f..447c2cc 100644 --- a/lib/utils.h +++ b/lib/utils.h @@ -30,4 +30,6 @@ char *utils_data_to_string(const unsigned char *data, int datalen, int chars_per char *utils_data_to_text(const char *data, int datalen); void ntp_timestamp_to_time(uint64_t ntp_timestamp, char *timestamp, size_t maxsize); void ntp_timestamp_to_seconds(uint64_t ntp_timestamp, char *timestamp, size_t maxsize); + +int private_key_from_EVP_PKEY_print_private(unsigned char *privkey, int keylen, char *data); #endif