From 44822be1342157167807fa3602de469071411095 Mon Sep 17 00:00:00 2001 From: Lukasz Pawelczyk Date: Mon, 2 May 2016 17:48:47 +0200 Subject: [PATCH] Make it possible to generate private keys with yaca_key_gen() Change-Id: I7d4928ab27dad85cd52f3cff60ff9a9e61ae261f --- api/yaca/key.h | 8 ++-- src/key.c | 136 ++++++++++++++++++++++++++++++++++++++++++++++----------- 2 files changed, 115 insertions(+), 29 deletions(-) diff --git a/api/yaca/key.h b/api/yaca/key.h index c7e3727..e1126a6 100644 --- a/api/yaca/key.h +++ b/api/yaca/key.h @@ -113,16 +113,18 @@ int yaca_key_export(const yaca_key_h key, size_t *data_len); /** - * @brief yaca_key_gen Generates a secure symmetric key (or an initialization vector). + * @brief yaca_key_gen Generates a secure key (or an initialization vector). * - * @param[out] sym_key Newly generated key (must be freed with yaca_key_free()). + * This function is used to generate symmetric and private asymmetric keys. + * + * @param[out] key Newly generated key (must be freed with yaca_key_free()). * @param[in] key_type Type of the key to be generated. * @param[in] key_bits Length of the key (in bits) to be generated. * * @return 0 on success, negative on error. * @see #yaca_key_type_e, #yaca_key_bits_e, yaca_key_gen_pair(), yaca_key_free() */ -int yaca_key_gen(yaca_key_h *sym_key, +int yaca_key_gen(yaca_key_h *key, yaca_key_type_e key_type, size_t key_bits); diff --git a/src/key.c b/src/key.c index 5c0d43c..2ba3fe9 100644 --- a/src/key.c +++ b/src/key.c @@ -523,6 +523,88 @@ free_bio: return ret; } +int gen_simple(struct yaca_key_simple_s **out, size_t key_bits) +{ + assert(out != NULL); + + int ret; + struct yaca_key_simple_s *nk; + size_t key_byte_len = key_bits / 8; + + if (key_byte_len > SIZE_MAX - sizeof(struct yaca_key_simple_s)) + return YACA_ERROR_TOO_BIG_ARGUMENT; + + nk = yaca_zalloc(sizeof(struct yaca_key_simple_s) + key_byte_len); + if (nk == NULL) + return YACA_ERROR_OUT_OF_MEMORY; + + nk->bits = key_bits; + + ret = yaca_rand_bytes(nk->d, key_byte_len); + if (ret != 0) + return ret; + + *out = nk; + return 0; +} + +int gen_evp_rsa(struct yaca_key_evp_s **out, size_t key_bits) +{ + assert(out != NULL); + assert(key_bits > 0); + assert(key_bits % 8 == 0); + + int ret; + struct yaca_key_evp_s *nk; + EVP_PKEY_CTX *ctx; + EVP_PKEY *pkey = NULL; + + nk = yaca_zalloc(sizeof(struct yaca_key_evp_s)); + if (nk == NULL) + return YACA_ERROR_OUT_OF_MEMORY; + + ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_RSA, NULL); + if (ctx == NULL) { + ret = YACA_ERROR_INTERNAL; + ERROR_DUMP(ret); + goto free_nk; + } + + ret = EVP_PKEY_keygen_init(ctx); + if (ret != 1) { + ret = YACA_ERROR_INTERNAL; + ERROR_DUMP(ret); + goto free_ctx; + } + + ret = EVP_PKEY_CTX_set_rsa_keygen_bits(ctx, key_bits); + if (ret != 1) { + ret = YACA_ERROR_INTERNAL; + ERROR_DUMP(ret); + goto free_ctx; + } + + ret = EVP_PKEY_keygen(ctx, &pkey); + if (ret != 1) { + ret = YACA_ERROR_INTERNAL; + ERROR_DUMP(ret); + goto free_ctx; + } + + nk->evp = pkey; + + *out = nk; + nk = NULL; + ret = 0; + +free_ctx: + EVP_PKEY_CTX_free(ctx); +free_nk: + yaca_free(nk); + + return ret; +} + struct yaca_key_simple_s *key_get_simple(const yaca_key_h key) { struct yaca_key_simple_s *k; @@ -659,49 +741,51 @@ API int yaca_key_export(const yaca_key_h key, return YACA_ERROR_INVALID_ARGUMENT; } -API int yaca_key_gen(yaca_key_h *sym_key, +// TODO: this NEEDS random number generator initialized +// there is some other TODO elsewhere about it +API int yaca_key_gen(yaca_key_h *key, yaca_key_type_e key_type, size_t key_bits) { int ret; - struct yaca_key_simple_s *nk = NULL; - size_t key_byte_len = key_bits / 8; + struct yaca_key_simple_s *nk_simple = NULL; + struct yaca_key_evp_s *nk_evp = NULL; - if (sym_key == NULL || key_bits % 8 != 0) + if (key == NULL || key_bits == 0 || key_bits % 8 != 0) return YACA_ERROR_INVALID_ARGUMENT; switch(key_type) { case YACA_KEY_TYPE_SYMMETRIC: case YACA_KEY_TYPE_IV: - break; - case YACA_KEY_TYPE_DES: - return YACA_ERROR_NOT_IMPLEMENTED; - default: - return YACA_ERROR_INVALID_ARGUMENT; - } - - if (key_byte_len > SIZE_MAX - sizeof(struct yaca_key_simple_s)) - return YACA_ERROR_TOO_BIG_ARGUMENT; + ret = gen_simple(&nk_simple, key_bits); + if (ret != 0) + return ret; - nk = yaca_zalloc(sizeof(struct yaca_key_simple_s) + key_byte_len); - if (nk == NULL) - return YACA_ERROR_OUT_OF_MEMORY; + nk_simple->key.type = key_type; - nk->bits = key_bits; - nk->key.type = key_type; + *key = (yaca_key_h)nk_simple; + return 0; - ret = yaca_rand_bytes(nk->d, key_byte_len); - if (ret != 0) - goto err; + case YACA_KEY_TYPE_RSA_PRIV: + ret = gen_evp_rsa(&nk_evp, key_bits); + if (ret != 0) + return ret; - *sym_key = (yaca_key_h)nk; + nk_evp->key.type = key_type; - return 0; + *key = (yaca_key_h)nk_evp; + return 0; -err: - yaca_free(nk); - return ret; + case YACA_KEY_TYPE_DES: + case YACA_KEY_TYPE_DSA_PRIV: + case YACA_KEY_TYPE_DH_PRIV: + case YACA_KEY_TYPE_ECDSA_PRIV: + case YACA_KEY_TYPE_ECDH_PRIV: + return YACA_ERROR_NOT_IMPLEMENTED; + default: + return YACA_ERROR_INVALID_ARGUMENT; + } } API int yaca_key_extract_public(const yaca_key_h prv_key, yaca_key_h *pub_key) -- 2.7.4