Add yaca_key_derive_dh() implementation. 13/80113/1
authorDariusz Michaluk <d.michaluk@samsung.com>
Mon, 11 Jul 2016 10:30:52 +0000 (12:30 +0200)
committerDariusz Michaluk <d.michaluk@samsung.com>
Thu, 14 Jul 2016 14:37:34 +0000 (16:37 +0200)
Change-Id: I8b71e7f1a75a83aa48af5e5c46088e831400b571

src/key.c

index 51a3993..60112fa 100644 (file)
--- a/src/key.c
+++ b/src/key.c
@@ -1290,12 +1290,79 @@ API void yaca_key_destroy(yaca_key_h key)
        }
 }
 
-API int yaca_key_derive_dh(UNUSED const yaca_key_h prv_key,
-                           UNUSED const yaca_key_h pub_key,
-                           UNUSED yaca_key_h *sym_key)
+API int yaca_key_derive_dh(const yaca_key_h prv_key,
+                           const yaca_key_h pub_key,
+                           yaca_key_h *sym_key)
 {
-       //TODO NOT_IMPLEMENTED
-       return YACA_ERROR_INVALID_PARAMETER;
+       int ret;
+       struct yaca_key_evp_s *lprv_key = key_get_evp(prv_key);
+       struct yaca_key_evp_s *lpub_key = key_get_evp(pub_key);
+       struct yaca_key_simple_s *nk = NULL;
+       size_t nk_len;
+       EVP_PKEY_CTX *ctx;
+
+       if (lprv_key == NULL || lpub_key == NULL || sym_key == NULL ||
+           (!(lprv_key->key.type == YACA_KEY_TYPE_DH_PRIV &&
+              lpub_key->key.type == YACA_KEY_TYPE_DH_PUB)
+           &&
+            !(lprv_key->key.type == YACA_KEY_TYPE_EC_PRIV &&
+              lpub_key->key.type == YACA_KEY_TYPE_EC_PUB)))
+               return YACA_ERROR_INVALID_PARAMETER;
+
+       ctx = EVP_PKEY_CTX_new(lprv_key->evp, NULL);
+       if (ctx == NULL) {
+               ret = YACA_ERROR_INTERNAL;
+               ERROR_DUMP(ret);
+               goto exit;
+       }
+
+       ret = EVP_PKEY_derive_init(ctx);
+       if (ret != 1) {
+               ret = YACA_ERROR_INTERNAL;
+               ERROR_DUMP(ret);
+               goto exit;
+       }
+
+       ret = EVP_PKEY_derive_set_peer(ctx, lpub_key->evp);
+       if (ret != 1) {
+               ret = YACA_ERROR_INTERNAL;
+               ERROR_DUMP(ret);
+               goto exit;
+       }
+
+       ret = EVP_PKEY_derive(ctx, NULL, &nk_len);
+       if (ret != 1) {
+               ret = YACA_ERROR_INTERNAL;
+               ERROR_DUMP(ret);
+               goto exit;
+       }
+
+       if (nk_len == 0 || nk_len > SIZE_MAX / 8) {
+               ret = YACA_ERROR_INVALID_PARAMETER;
+               goto exit;
+       }
+
+       ret = yaca_zalloc(sizeof(struct yaca_key_simple_s) + nk_len, (void**)&nk);
+       if (ret != YACA_ERROR_NONE)
+               goto exit;
+
+       ret = EVP_PKEY_derive(ctx, (unsigned char*)nk->d, &nk_len);
+       if (ret != 1) {
+               ret = YACA_ERROR_INTERNAL;
+               ERROR_DUMP(ret);
+               goto exit;
+       }
+
+       nk->bit_len = nk_len * 8;
+       nk->key.type = YACA_KEY_TYPE_SYMMETRIC;
+       *sym_key = (yaca_key_h)nk;
+       nk = NULL;
+       ret = YACA_ERROR_NONE;
+
+exit:
+       EVP_PKEY_CTX_free(ctx);
+       yaca_free(nk);
+       return ret;
 }
 
 API int yaca_key_derive_pbkdf2(const char *password,