Make it possible to generate private keys with yaca_key_gen() 63/68463/16
authorLukasz Pawelczyk <l.pawelczyk@samsung.com>
Mon, 2 May 2016 15:48:47 +0000 (17:48 +0200)
committerLukasz Pawelczyk <l.pawelczyk@samsung.com>
Wed, 11 May 2016 11:04:24 +0000 (13:04 +0200)
Change-Id: I7d4928ab27dad85cd52f3cff60ff9a9e61ae261f

api/yaca/key.h
src/key.c

index c7e3727..e1126a6 100644 (file)
@@ -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);
 
index 5c0d43c..2ba3fe9 100644 (file)
--- 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)