Skip to content

Move all code using EVP_PKEY_assign and EVP_PKEY_get0 into legacy-only modules #508

@VladGud

Description

@VladGud

Move all code using EVP_PKEY_assign and EVP_PKEY_get0 into legacy-only modules

Summary

Extract all functions using deprecated EVP_PKEY internal accessors (EVP_PKEY_assign, EVP_PKEY_get0) into separate legacy-only modules (gost_ameth_legacy.c, gost_pmeth_legacy.c) that are compiled only when GOST_ENABLE_LEGACY is enabled.

Problem Description

The current implementation uses deprecated OpenSSL EVP_PKEY internal accessors scattered throughout multiple files:

  • EVP_PKEY_assign(pkey, nid, key_data) - Directly assigns algorithm-specific key data to an EVP_PKEY without going through proper OpenSSL provider interfaces
  • EVP_PKEY_get0(pkey) - Directly retrieves raw algorithm-specific key data from EVP_PKEY, bypassing encapsulation

These functions are deprecated because they:

  1. Break encapsulation by exposing internal EVP_PKEY structure layout
  2. Are not available in OpenSSL builds with OPENSSL_NO_DEPRECATED flag
  3. Prevent migration to provider-based EVP_PKEY implementations
  4. Create tight coupling to OpenSSL internal APIs

Current usage

These deprecated accessors are used in:

  • gost_ameth.c - ASN1 method implementations
  • gost_pmeth.c - PKEYmethod implementations for key generation, signing, MAC operations

Required Changes

1. Create gost_ameth_legacy.c

Move all functions from gost_ameth.c that call EVP_PKEY_assign or EVP_PKEY_get0:

Functions to extract:

  • All ASN1 key encoding/decoding functions that use EVP_PKEY_get0 to access EC_KEY
  • All functions that use EVP_PKEY_assign to set EC_KEY in pkey

File structure:

/*
 * gost_ameth_legacy.c - Legacy ENGINE-based ASN1 methods
 * Contains all ASN1 method implementations that depend on
 * EVP_PKEY_assign and EVP_PKEY_get0.
 * Only compiled when GOST_ENABLE_LEGACY is enabled.
 */

#include "gost_lcl.h"
#include "e_gost_err.h"


/* Legacy ASN1 implementations using EVP_PKEY internals */
static int gost_ameth_keybuf_to_priv_key(...)
{
    EVP_PKEY *pkey = EVP_PKEY_new();
    if (!pkey)
        return 0;
    
    /* Use EVP_PKEY_get0 / EVP_PKEY_assign here */
    EC_KEY *ec = ECP_KEY_new();
    /* ... */
    if (!EVP_PKEY_assign(pkey, NID_id_GostR3410_2001, ec)) {
        EC_KEY_free(ec);
        EVP_PKEY_free(pkey);
        return 0;
    }
    
    return 1;
}

/* ... other extracted functions ... */

2. Create gost_pmeth_legacy.c

Move all functions from gost_pmeth.c that call EVP_PKEY_assign or EVP_PKEY_get0:

Functions to extract:

  • pkey_gost2001_paramgen()
  • pkey_gost2012_paramgen()
  • pkey_gost2001cp_keygen()
  • pkey_gost2012cp_keygen()
  • pkey_gost_mac_keygen_base()
  • pkey_gost_mac_keygen_12()
  • pkey_gost_mac_keygen()
  • pkey_gost_magma_mac_keygen()
  • pkey_gost_grasshopper_mac_keygen()
  • pkey_gost_ec_cp_sign() and related
  • pkey_gost_ec_cp_verify() and related

File structure:

/*
 * gost_pmeth_legacy.c - Legacy ENGINE-based PKEY methods
 * Contains all EVP_PKEY_METHOD implementations that depend on
 * EVP_PKEY_assign and EVP_PKEY_get0.
 * Only compiled when GOST_ENABLE_LEGACY is enabled.
 */

#include "gost_lcl.h"
#include "e_gost_err.h"

/* Legacy paramgen implementations using EVP_PKEY internals */
static int pkey_gost2001_paramgen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
{
    struct gost_pmeth_data *data = EVP_PKEY_CTX_get_data(ctx);
    EC_KEY *ec = NULL;

    if (!data || data->sign_param_nid == NID_undef) {
        GOSTerr(GOST_F_PKEY_GOST2001_PARAMGEN, GOST_R_NO_PARAMETERS_SET);
        return 0;
    }

    ec = internal_ec_paramgen(data->sign_param_nid);
    if (!ec)
        return 0;

    if (!EVP_PKEY_assign(pkey, NID_id_GostR3410_2001, ec)) {
        EC_KEY_free(ec);
        return 0;
    }
    return 1;
}

/* ... other extracted functions ... */

/* Registration function called from main register_pmeth_gost */
int register_pmeth_gost_legacy(int id, EVP_PKEY_METHOD **pmeth, int flags)
{
    /* Set up methods for legacy-only cases */
    switch (id) {
    case NID_id_GostR3410_2001:
        EVP_PKEY_meth_set_keygen(*pmeth, NULL, pkey_gost2001cp_keygen);
        break;
    case NID_id_GostR3410_2012_256:
        EVP_PKEY_meth_set_keygen(*pmeth, NULL, pkey_gost2012cp_keygen);
        break;
    /* ... */
    }
    return 1;
}

3. Update gost_ameth.c

Remove all functions that use EVP_PKEY_assign or EVP_PKEY_get0. Keep only the common infrastructure:

/* gost_ameth.c - ASN1 method implementations (provider-compatible) */

#include "gost_lcl.h"
#include "e_gost_err.h"

/* Common ASN1 infrastructure that doesn't depend on EVP_PKEY internals */
static int gost_ameth_foo() { ... }

/* Conditional inclusion of legacy implementations */
#ifdef GOST_ENABLE_LEGACY
#include "gost_ameth_legacy.c"
#endif

/* For provider-only builds, these return error */
#ifndef GOST_ENABLE_LEGACY
static int gost_ameth_keybuf_to_priv_key_stub(...)
{
    GOSTerr(GOST_F_AMETH, GOST_R_LEGACY_DISABLED);
    return 0;
}
/* ... other stubs ... */
#endif

4. Update gost_pmeth.c

Remove all functions that use EVP_PKEY_assign or EVP_PKEY_get0.

5. Update CMakeLists.txt or build system

Add conditional compilation:

# Legacy support (default: ON for backward compatibility)
option(GOST_ENABLE_LEGACY "Enable legacy ENGINE-based implementations" ON)

if(GOST_ENABLE_LEGACY)
    target_sources(gost_engine PRIVATE
        gost_ameth_legacy.c
        gost_pmeth_legacy.c
    )
    target_compile_definitions(gost_engine PRIVATE GOST_ENABLE_LEGACY)
endif()

target_sources(gost_engine PRIVATE
    gost_ameth.c
    gost_pmeth.c
    # ... other sources ...
)

Files to Create

  • gost_ameth_legacy.c - Legacy ASN1 method implementations
  • gost_pmeth_legacy.c - Legacy PKEY method implementations

Files to Modify

  • gost_ameth.c - Remove legacy functions, keep common code
  • gost_pmeth.c - Remove legacy functions, update registration to delegate to legacy module
  • CMakeLists.txt or build system - Add conditional compilation

Compilation behavior

When GOST_ENABLE_LEGACY=ON (default):

  • gost_ameth_legacy.c and gost_pmeth_legacy.c are compiled
  • Full backward compatibility with existing ENGINE-based code
  • Uses EVP_PKEY_assign and EVP_PKEY_get0

When GOST_ENABLE_LEGACY is not set:

  • gost_ameth_legacy.c and gost_pmeth_legacy.c are NOT compiled
  • Legacy paramgen/keygen operations return error
  • Compatible with OpenSSL builds with OPENSSL_NO_DEPRECATED
  • Provider-only mode (future work will implement provider interfaces)

Acceptance Criteria

  • All EVP_PKEY_assign calls moved to legacy modules
  • All EVP_PKEY_get0 calls moved to legacy modules
  • Code compiles with GOST_ENABLE_LEGACY=ON (default) - all tests pass
  • Code compiles with GOST_ENABLE_LEGACY=OFF - legacy operations fail gracefully with clear error

Testing

  • Compile with -DGOST_ENABLE_LEGACY=ON (default) - all tests pass
  • Compile with -DGOST_ENABLE_LEGACY=OFF - legacy operations fail with GOST_R_LEGACY_DISABLED
  • Test with OpenSSL compiled with OPENSSL_NO_DEPRECATED and GOST_ENABLE_LEGACY=OFF

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions