}
}
-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,