yaca_key_extract_public() public function 62/68462/16
authorLukasz Pawelczyk <l.pawelczyk@samsung.com>
Mon, 2 May 2016 11:50:46 +0000 (13:50 +0200)
committerLukasz Pawelczyk <l.pawelczyk@samsung.com>
Wed, 11 May 2016 11:04:24 +0000 (13:04 +0200)
The idea is to remove yaca_key_gen_pair() and always generate using
yaca_key_gen(). The latter will always generate private keys for
asymmetric types. Public key will be extracted (if needed) using the
function implemented here.

This approach has an advantage that we can extract public keys for
private keys imported from external sources. Previously this was
impossible.

Change-Id: I081c81eb37ed3267518aac21a9bf36063ef0e901

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

index 3a829d5..c7e3727 100644 (file)
@@ -127,6 +127,17 @@ int yaca_key_gen(yaca_key_h *sym_key,
                  size_t key_bits);
 
 /**
+ * @brief yaca_key_extract_public  Extracts public key from a private one.
+ *
+ * @param[in]  prv_key   Private key to extract the public one from.
+ * @param[out] pub_key   Extracted public key (must be freed with yaca_key_free()).
+ *
+ * @return 0 on success, negative on error.
+ * @see yaca_key_gen(), yaca_key_import(), yaca_key_free()
+ */
+int yaca_key_extract_public(const yaca_key_h prv_key, yaca_key_h *pub_key);
+
+/**
  * @brief yaca_key_gen_pair  Generates a new key pair.
  *
  * @param[out] prv_key   Newly generated private key (must be freed with yaca_key_free()).
index a8fb8ff..5c0d43c 100644 (file)
--- a/src/key.c
+++ b/src/key.c
@@ -704,6 +704,73 @@ err:
        return ret;
 }
 
+API int yaca_key_extract_public(const yaca_key_h prv_key, yaca_key_h *pub_key)
+{
+       int ret;
+       struct yaca_key_evp_s *evp_key = key_get_evp(prv_key);
+       struct yaca_key_evp_s *nk = NULL;
+       RSA *rsa_pub = NULL;
+
+       if (prv_key == YACA_KEY_NULL || evp_key == NULL || pub_key == NULL)
+               return YACA_ERROR_INVALID_ARGUMENT;
+
+       nk = yaca_zalloc(sizeof(struct yaca_key_evp_s));
+       if (nk == NULL)
+               return YACA_ERROR_OUT_OF_MEMORY;
+
+       nk->evp = EVP_PKEY_new();
+       if (nk->evp == NULL) {
+               ret = YACA_ERROR_OUT_OF_MEMORY;
+               ERROR_DUMP(ret);
+               goto free_key;
+       }
+
+       switch(prv_key->type)
+       {
+       case YACA_KEY_TYPE_RSA_PRIV:
+               assert(EVP_PKEY_type(evp_key->evp->type) == EVP_PKEY_RSA);
+
+               rsa_pub = RSAPublicKey_dup(EVP_PKEY_get0(evp_key->evp));
+               if (rsa_pub == NULL) {
+                       ret = YACA_ERROR_INTERNAL;
+                       ERROR_DUMP(ret);
+                       goto free_evp;
+               }
+
+               ret = EVP_PKEY_assign_RSA(nk->evp, rsa_pub);
+               if (ret != 1) {
+                       ret = YACA_ERROR_INTERNAL;
+                       ERROR_DUMP(ret);
+                       goto free_rsa;
+               }
+
+               *pub_key = (yaca_key_h)nk;
+               (*pub_key)->type = YACA_KEY_TYPE_RSA_PUB;
+
+               return 0;
+
+       case YACA_KEY_TYPE_DSA_PRIV:
+       case YACA_KEY_TYPE_ECDSA_PRIV:
+               ret = YACA_ERROR_NOT_IMPLEMENTED;
+               goto free_evp;
+
+       default:
+               ret = YACA_ERROR_INVALID_ARGUMENT;
+               goto free_evp;
+       }
+
+       return YACA_ERROR_INVALID_ARGUMENT;
+
+free_rsa:
+       RSA_free(rsa_pub);
+free_evp:
+       EVP_PKEY_free(nk->evp);
+free_key:
+       yaca_free(nk);
+
+       return ret;
+}
+
 API int yaca_key_gen_pair(yaca_key_h *prv_key,
                           yaca_key_h *pub_key,
                           yaca_key_type_e key_type,