RE: [EXTERNAL] RE: DH_compute_key () - replacement in 3.0
From: Narayana, Sunil Kumar Sent: Thursday, December 17, 2020 8:17 AM To: Sands, Daniel ; openssl-users@openssl.org Subject: [EXTERNAL] RE: DH_compute_key () - replacement in 3.0 Hi, For the equivalent replacement of DH_compute_key in 3.0, we tried to perform the steps suggested in earlier mail below Our steps are as follows, but we see EVP_PKEY_derive fails to perform. please suggest if any steps are wrong or missing here. //input - BIGNUM - pubkey, privkey, p , //output - sharedsecret Evp_compute_key(unsigned char* sharedSecret, unsigned int len, BIGNUM *pubkey, BIGNUM *privkey, BIGNUM* dh_p) { OSSL_PARAM params[5]; unsigned char* p_str = BN_bn2dec (dh_p); unsigned char* pub_str = BN_bn2dec (pubkey); unsigned char* priv_str = BN_bn2dec (privkey); params[0] = OSSL_PARAM_construct_BN(OSSL_PKEY_PARAM_FFC_P, p_str, strlen(p_str)); params[1] = OSSL_PARAM_construct_uint(OSSL_PKEY_PARAM_FFC_G, ); params[2] = OSSL_PARAM_construct_BN(OSSL_PKEY_PARAM_PUB_KEY, pub_str, strlen(pub_str)); params[3] = OSSL_PARAM_construct_BN(OSSL_PKEY_PARAM_PRIV_KEY, priv_str, strlen(priv_str)); params[4] = OSSL_PARAM_construct_end(); gctx = EVP_PKEY_CTX_new_from_name(NULL, "DH", NULL); EVP_PKEY_derive_init(gctx) EVP_PKEY_CTX_set_params(gctx, params) /* Determine buffer length */ EVP_PKEY_derive(gctx, NULL, ) EVP_PKEY_derive(gctx, sharedSecret, ) } Note - EVP_PKEY_derive -- call fails what is wrong in the steps can you please g To derive a shared secret, you also need your peer’s public key. It will also be presented as an EVP_PKEY structure.
Re: private key not available for client_cert_cb
Hi, I'm able to setup the engine now, but as soon as I attempt to execute the command ENGINE_set_default(pkey_engine, ENGINE_METHOD_ALL); ,I see all kinds of middleware exceptions being generated: Exception thrown at 0x773046D2 in GENCom.exe: Microsoft C++ exception: unsigned long at memory location 0x07FCFA00. Exception thrown at 0x773046D2 in GENCom.exe: Microsoft C++ exception: AI::Middleware::CMWException at memory location 0x032FD2D0. Exception thrown at 0x773046D2 in GENCom.exe: Microsoft C++ exception: AI::Middleware::CMWException at memory location 0x032FD2D0. Exception thrown at 0x773046D2 in GENCom.exe: Microsoft C++ exception: AI::Middleware::CMWException at memory location 0x032FD2D0. Exception thrown at 0x773046D2 in GENCom.exe: Microsoft C++ exception: AI::Middleware::CMWException at memory location 0x032FD2D0. Exception thrown at 0x773046D2 in GENCom.exe: Microsoft C++ exception: AI::Middleware::CMWException at memory location 0x032FD2D0. Exception thrown at 0x773046D2 in GENCom.exe: Microsoft C++ exception: AI::Middleware::CMWException at memory location 0x032FD2D0. Exception thrown at 0x773046D2 in GENCom.exe: Microsoft C++ exception: AI::Middleware::CMWException at memory location 0x032FD2D0. Exception thrown at 0x773046D2 in GENCom.exe: Microsoft C++ exception: AI::Middleware::CMWException at memory location 0x032FD2D0. . . . Do you have any idea what is causing these errors? Am I missing something in the configuration? When I use the OpenSSL command line debugger, there are no errors: OpenSSL> engine -t dynamic -pre "SO_PATH:C:\\Users\\whipp\\junk4\\libp11-libp11-0.4.11\\src\\pkcs11.dll" -pre ID:pkcs11 -pre LIST_ADD:1 -pre LOAD -pre "MODULE_PATH:C:\Program Files (x86)\HID Global\ActivClient\\acpkcs211.dll" (dynamic) Dynamic engine loading support [Success]: SO_PATH:C:\\Users\\whipp\\junk4\\libp11-libp11-0.4.11\\src\\pkcs11.dll [Success]: ID:pkcs11 [Success]: LIST_ADD:1 [Success]: LOAD [Success]: MODULE_PATH:C:\Program Files (x86)\HID Global\ActivClient\\acpkcs211.dll Loaded: (pkcs11) pkcs11 engine [ available ] OpenSSL> Here is what my simplified code looks like: char* enginePluginLibrary = "C:\\Users\\whipp\\junk4\\libp11-libp11-0.4.11\\src\\pkcs11.dll"; char* pkcs11MiddlewareLibrary = "C:\\Program Files (x86)\\HID Global\\ActivClient\\acpkcs211.dll"; ENGINE_load_builtin_engines(); ENGINE_register_all_complete(); ENGINE *pkey_engine = ENGINE_by_id("dynamic"); ENGINE_ctrl_cmd_string(pkey_engine, "SO_PATH", enginePluginLibrary, 0); ENGINE_ctrl_cmd_string(pkey_engine, "ID", "pkcs11", 0); ENGINE_ctrl_cmd_string(pkey_engine, "LIST_ADD", "1", 0); ENGINE_ctrl_cmd_string(pkey_engine, "LOAD", NULL, 0); ENGINE_ctrl_cmd_string(pkey_engine, "MODULE_PATH", pkcs11MiddlewareLibrary, 0); ENGINE_set_default(pkey_engine, ENGINE_METHOD_ALL); Thanks! George On 2020-12-17 8:39 p.m., Jan Just Keijser wrote: On 17/12/20 14:55, George wrote: Ok. So I use the libp11 project DLL file for the SO_PATH and my smart card middleware DLL for the MODULE_PATH when setting up the OpenSSL Engine? yes just like in the example I posted below. I would recommend the p11 wiki page to do it using the command line first - much easier to test & debug. JJK
Re: private key not available for client_cert_cb
On 17/12/20 14:55, George wrote: Ok. So I use the libp11 project DLL file for the SO_PATH and my smart card middleware DLL for the MODULE_PATH when setting up the OpenSSL Engine? yes just like in the example I posted below. I would recommend the p11 wiki page to do it using the command line first - much easier to test & debug. JJK On 2020-12-17 3:22 a.m., Jan Just Keijser wrote: Hi, On 16/12/20 20:26, George wrote: Hi, I've been looking at the code in the pppd EAP-TLS patch, but I can't seem to load the engine with the pkcs11 DLL. It is failing with the error: error:2507606A:DSO support routines:WIN32_BIND_FUNC:could not bind to the requested symbol name I've verified the path is correct. I am using OpenSSL1.0.2u with the FIPS Object Module 2.0.16 in Windows 10. Do I need to do anything special to allow loading of DLLs in OpenSSL? Here is what I am trying to do: char* engine_name = "C:\\Users\\whipp\\junk4\\ActivClient\\acpkcs211.dll"; ENGINE_load_builtin_engines(); ENGINE_register_all_complete(); ENGINE *pkey_engine = ENGINE_by_id("dynamic"); ENGINE_ctrl_cmd_string(pkey_engine, "SO_PATH", engine_name, 0); ENGINE_ctrl_cmd_string(pkey_engine, "ID", "pkcs11", 0); ENGINE_ctrl_cmd_string(pkey_engine, "LOAD", NULL, 0); Do you see anything wrong with this? I forgot to mention that loading a PKCS11 driver from within OpenSSL is a 2 stage rocket: first stage: load the engine_pkcs11 module using char* engine_name = "|C:\\Windows\\System32\\pkcs11.dll"| This is a separate piece of code and is part of the libp11 project: https://github.com/OpenSC/libp11 (it also has a nice wiki that explains how to do it on the command line using OPENSSL.EXE) Then create an openssl.cnf section like this: |openssl_conf = openssl_init [openssl_init] engines = engine_section [engine_section] pkcs11 = pkcs11_section [pkcs11_section] engine_id = pkcs11 dynamic_path = "C:\Windows\System32\opensc-pkcs11.dll" MODULE_path = "||C:\Users\whipp\junk4\ActivClient\acpkcs211.dll" PIN = "0001password" init = 0| and load that (see the EAP-TLS code for an example or read https://stackoverflow.com/questions/41119744/pkcs11-engine-for-openssl for a similar question). HTH, JJK On 2020-12-15 4:38 a.m., Jan Just Keijser wrote: Hi, On 14/12/20 21:01, George wrote: Ok, so I am not actually going to populate EVP_PKEY with a private key in the callback function: int (*client_cert_cb)(SSL *ssl, X509 **x509, *EVP_PKEY **pkey*)? Instead, I will call EVP_PKEY *ENGINE_load_private_key(ENGINE *e, const char *key_id, UI_METHOD *ui_method, void *callback_data); to get the EVP_PKEY, which will be used by OpenSSL to access the Smart Card. Once I get the resulting EVP_PKEY using ENGINE_load_private_key(...), how do I assign it to pkey in the callback function? If I had private key I would use something like EVP_PKEY_assign_RSA(..) Since I don't actually have a private key, should I use something else? like Michael pointed out, my eap-tls code is just an example of how you could handle a pkcs11 device; it does not us a callback at all, but my code loads the client cert+key upfront and avoids having to use a client callback altogether. I guess you could also use a client callback for this (perhaps in combination with SSL_CTX_set_client_cert_engine()) . In that case you would get the (pseudo) key from the engine like this EVP_PKEY *engine_key = ENGINE_load_private_key(ENGINE *e, const char *key_id, UI_METHOD *ui_method, void *callback_data); and then set pkey = _key; and see if that works. Note that the ENGINE_load_private_key() function *does* return a EVP_PKEY struct but that does not mean the entire private key is contained in it; a private key consists of a modulus and a private part (exponent, prime1, prime2, exponent1, exponent2 etc). the ENGINE_load_private_key() call will return a struct containing the modulus but not the rest. You then use the engine to do the actual encryption and decryption. HTH, JJK
RE: DH_compute_key () - replacement in 3.0
Hi, For the equivalent replacement of DH_compute_key in 3.0, we tried to perform the steps suggested in earlier mail below Our steps are as follows, but we see EVP_PKEY_derive fails to perform. please suggest if any steps are wrong or missing here. //input - BIGNUM - pubkey, privkey, p , //output - sharedsecret Evp_compute_key(unsigned char* sharedSecret, unsigned int len, BIGNUM *pubkey, BIGNUM *privkey, BIGNUM* dh_p) { OSSL_PARAM params[5]; unsigned char* p_str = BN_bn2dec (dh_p); unsigned char* pub_str = BN_bn2dec (pubkey); unsigned char* priv_str = BN_bn2dec (privkey); params[0] = OSSL_PARAM_construct_BN(OSSL_PKEY_PARAM_FFC_P, p_str, strlen(p_str)); params[1] = OSSL_PARAM_construct_uint(OSSL_PKEY_PARAM_FFC_G, ); params[2] = OSSL_PARAM_construct_BN(OSSL_PKEY_PARAM_PUB_KEY, pub_str, strlen(pub_str)); params[3] = OSSL_PARAM_construct_BN(OSSL_PKEY_PARAM_PRIV_KEY, priv_str, strlen(priv_str)); params[4] = OSSL_PARAM_construct_end(); gctx = EVP_PKEY_CTX_new_from_name(NULL, "DH", NULL); EVP_PKEY_derive_init(gctx) EVP_PKEY_CTX_set_params(gctx, params) /* Determine buffer length */ EVP_PKEY_derive(gctx, NULL, ) EVP_PKEY_derive(gctx, sharedSecret, ) } Note - EVP_PKEY_derive -- call fails what is wrong in the steps can you please g From: Sands, Daniel Sent: 16 December 2020 05:00 To: Narayana, Sunil Kumar ; openssl-users@openssl.org Subject: RE: [EXTERNAL] RE: DH_compute_key () - replacement in 3.0 NOTICE: This email was received from an EXTERNAL sender We do have generated the key using EVP_PKEY_gen as suggested in earlier emails, but since this was a non-ephemeral and we wanted to store the key in "raw" octet bytes, so we did extracted the whole DH priv/pub key pair out from the key generated via EVP_PKEY_gen ( using as suggested… EVP_PKEY_get_raw_public_key (pkey, pub, ) ) Now, at a later stage in application we have to compute the Secret key using the stored key’s (in above step). As of now, these keys are in uchar format, but are converted to BIGNUM and given to DH_compute_key as below. BIGNUM *bn_publicKey; dh->priv_key = BN_bin2bn(privateKey, octet_len, NULL); bn_publicKey = BN_bin2bn(publicKey, octet_len, NULL); rv = DH_compute_key(sharedSecret, bn_publicKey, dh); So in order to keep the existing frame work in place and just replace the DH_compute_key, we should be using the dh->priv_key/ bn_publicKey to compute shared secret key. So we require to convert the BIGNUM key types to EVP_KEY types to use in EVP_PKEY_derive_init, EVP_PKEY_derive_set_peer, and EVP_PKEY_derive to get shared secret Please suggest… Is it possible to change the format of your raw blob? If so, you can use i2d_PrivateKey or friends to output the entire private key to your raw data blob, and use d2i_PrivateKey et al to read it back into a working EVP_PKEY in a single call. Otherwise, one shortcut you can do to avoid all the params work is to create a static array since you should already know how many params you need. But you need the public key, the private key, the generator (g), and the prime modulus (p). The following (untested) code ought to work. OSSL_PARAM params[5]; params[0] = OSSL_PARAM_construct_BN(OSSL_PKEY_PARAM_FFC_P, , ); params[1] = OSSL_PARAM_construct_uint(OSSL_PKEY_PARAM_FFC_G, ); params[2] = OSSL_PARAM_construct_BN(OSSL_PKEY_PARAM_PUB_KEY, , ); params[3] = OSSL_PARAM_construct_BN(OSSL_PKEY_PARAM_PRIV_KEY, , ); params[4] = OSSL_PARAM_construct_end(); my_key_ctx = EVP_PKEY_CTX_new_from_name(NULL, “DH”, NULL); EVP_PKEY_derive_init(my_key_ctx); EVP_PKEY_CTX_set_params(my_key_ctx, params); … --- Notice: This e-mail together with any attachments may contain information of Ribbon Communications Inc. that is confidential and/or proprietary for the sole use of the intended recipient. Any review, disclosure, reliance or distribution by others or forwarding without express permission is strictly prohibited. If you are not the intended recipient, please notify the sender immediately and then delete all copies, including any attachments. ---
Re: private key not available for client_cert_cb
Ok. So I use the libp11 project DLL file for the SO_PATH and my smart card middleware DLL for the MODULE_PATH when setting up the OpenSSL Engine? Thanks, George On 2020-12-17 3:22 a.m., Jan Just Keijser wrote: Hi, On 16/12/20 20:26, George wrote: Hi, I've been looking at the code in the pppd EAP-TLS patch, but I can't seem to load the engine with the pkcs11 DLL. It is failing with the error: error:2507606A:DSO support routines:WIN32_BIND_FUNC:could not bind to the requested symbol name I've verified the path is correct. I am using OpenSSL1.0.2u with the FIPS Object Module 2.0.16 in Windows 10. Do I need to do anything special to allow loading of DLLs in OpenSSL? Here is what I am trying to do: char* engine_name = "C:\\Users\\whipp\\junk4\\ActivClient\\acpkcs211.dll"; ENGINE_load_builtin_engines(); ENGINE_register_all_complete(); ENGINE *pkey_engine = ENGINE_by_id("dynamic"); ENGINE_ctrl_cmd_string(pkey_engine, "SO_PATH", engine_name, 0); ENGINE_ctrl_cmd_string(pkey_engine, "ID", "pkcs11", 0); ENGINE_ctrl_cmd_string(pkey_engine, "LOAD", NULL, 0); Do you see anything wrong with this? I forgot to mention that loading a PKCS11 driver from within OpenSSL is a 2 stage rocket: first stage: load the engine_pkcs11 module using char* engine_name = "|C:\\Windows\\System32\\pkcs11.dll"| This is a separate piece of code and is part of the libp11 project: https://github.com/OpenSC/libp11 (it also has a nice wiki that explains how to do it on the command line using OPENSSL.EXE) Then create an openssl.cnf section like this: |openssl_conf = openssl_init [openssl_init] engines = engine_section [engine_section] pkcs11 = pkcs11_section [pkcs11_section] engine_id = pkcs11 dynamic_path = "C:\Windows\System32\opensc-pkcs11.dll" MODULE_path = "||C:\Users\whipp\junk4\ActivClient\acpkcs211.dll" PIN = "0001password" init = 0| and load that (see the EAP-TLS code for an example or read https://stackoverflow.com/questions/41119744/pkcs11-engine-for-openssl for a similar question). HTH, JJK On 2020-12-15 4:38 a.m., Jan Just Keijser wrote: Hi, On 14/12/20 21:01, George wrote: Ok, so I am not actually going to populate EVP_PKEY with a private key in the callback function: int (*client_cert_cb)(SSL *ssl, X509 **x509, *EVP_PKEY **pkey*)? Instead, I will call EVP_PKEY *ENGINE_load_private_key(ENGINE *e, const char *key_id, UI_METHOD *ui_method, void *callback_data); to get the EVP_PKEY, which will be used by OpenSSL to access the Smart Card. Once I get the resulting EVP_PKEY using ENGINE_load_private_key(...), how do I assign it to pkey in the callback function? If I had private key I would use something like EVP_PKEY_assign_RSA(..) Since I don't actually have a private key, should I use something else? like Michael pointed out, my eap-tls code is just an example of how you could handle a pkcs11 device; it does not us a callback at all, but my code loads the client cert+key upfront and avoids having to use a client callback altogether. I guess you could also use a client callback for this (perhaps in combination with SSL_CTX_set_client_cert_engine()) . In that case you would get the (pseudo) key from the engine like this EVP_PKEY *engine_key = ENGINE_load_private_key(ENGINE *e, const char *key_id, UI_METHOD *ui_method, void *callback_data); and then set pkey = _key; and see if that works. Note that the ENGINE_load_private_key() function *does* return a EVP_PKEY struct but that does not mean the entire private key is contained in it; a private key consists of a modulus and a private part (exponent, prime1, prime2, exponent1, exponent2 etc). the ENGINE_load_private_key() call will return a struct containing the modulus but not the rest. You then use the engine to do the actual encryption and decryption. HTH, JJK
Re: Set custom bn_mod_exp functions in openssl 1.1.1
On Thu, 2020-12-17 at 15:16 +0530, prudvi raj wrote: > Hi, > > I need to set custom accelerated functions for bn_mod_exp methods in > openssl 1.1.1, while upgrading for openssl 1.0.2. Here's the code > snippet () : > -- > static DH_METHOD Intoto_DH_Method; > static RSA_METHOD Intoto_RSA_Method; > static DSA_METHOD Intoto_DSA_Method; > > void updatePublicKeyMethods() > { > Intoto_DH_Method = *(DH_get_default_method()); > Intoto_DH_Method.bn_mod_exp = Intoto_DH_mod_exp; > DH_set_default_method(_DH_Method); > > Intoto_RSA_Method = *(RSA_get_default_method()); > Intoto_RSA_Method.bn_mod_exp = Intoto_RSA_mod_exp; > RSA_set_default_method(_RSA_Method); > > Intoto_DSA_Method = *(DSA_get_default_method()); > Intoto_DSA_Method.bn_mod_exp = Intoto_DSA_mod_exp; > DSA_set_default_method(_DSA_Method); > > return; > } > -- > As RSA_METHOD,DSA_METHOD & DH_METHOD objects are Opaque now , Can > anyone help me with what would be the replacement for above code ?? There is RSA_meth_set_bn_mod_exp() function and the respective equivalents for DH and DSA. Of course you'll also have to use RSA_meth_dup() to duplicate the default method before you can manipulate it. And you'll need to free it once you stop using the OpenSSL functions. -- Tomáš Mráz No matter how far down the wrong road you've gone, turn back. Turkish proverb [You'll know whether the road is wrong if you carefully listen to your conscience.]
Set custom bn_mod_exp functions in openssl 1.1.1
Hi, I need to set custom accelerated functions for bn_mod_exp methods in openssl 1.1.1, while upgrading for openssl 1.0.2. Here's the code snippet () : -- static DH_METHOD Intoto_DH_Method; static RSA_METHOD Intoto_RSA_Method; static DSA_METHOD Intoto_DSA_Method; void updatePublicKeyMethods() { Intoto_DH_Method = *(DH_get_default_method()); Intoto_DH_Method.bn_mod_exp = Intoto_DH_mod_exp; DH_set_default_method(_DH_Method); Intoto_RSA_Method = *(RSA_get_default_method()); Intoto_RSA_Method.bn_mod_exp = Intoto_RSA_mod_exp; RSA_set_default_method(_RSA_Method); Intoto_DSA_Method = *(DSA_get_default_method()); Intoto_DSA_Method.bn_mod_exp = Intoto_DSA_mod_exp; DSA_set_default_method(_DSA_Method); return; } -- As RSA_METHOD,DSA_METHOD & DH_METHOD objects are Opaque now , Can anyone help me with what would be the replacement for above code ?? Thanks, Prudvi
Openssl - windows mobile
Hi, I am trying to connect SSL server through windows mobile, but when I add connection code not able to execute the executable in emulator. It says the specified program requires a newer version of windows. But when I remove openssl code I can able to execute in emulator. Please help. Regards, Geetha.
Re: private key not available for client_cert_cb
Hi, On 16/12/20 20:26, George wrote: Hi, I've been looking at the code in the pppd EAP-TLS patch, but I can't seem to load the engine with the pkcs11 DLL. It is failing with the error: error:2507606A:DSO support routines:WIN32_BIND_FUNC:could not bind to the requested symbol name I've verified the path is correct. I am using OpenSSL1.0.2u with the FIPS Object Module 2.0.16 in Windows 10. Do I need to do anything special to allow loading of DLLs in OpenSSL? Here is what I am trying to do: char* engine_name = "C:\\Users\\whipp\\junk4\\ActivClient\\acpkcs211.dll"; ENGINE_load_builtin_engines(); ENGINE_register_all_complete(); ENGINE *pkey_engine = ENGINE_by_id("dynamic"); ENGINE_ctrl_cmd_string(pkey_engine, "SO_PATH", engine_name, 0); ENGINE_ctrl_cmd_string(pkey_engine, "ID", "pkcs11", 0); ENGINE_ctrl_cmd_string(pkey_engine, "LOAD", NULL, 0); Do you see anything wrong with this? I forgot to mention that loading a PKCS11 driver from within OpenSSL is a 2 stage rocket: first stage: load the engine_pkcs11 module using char* engine_name = "|C:\\Windows\\System32\\pkcs11.dll"| This is a separate piece of code and is part of the libp11 project: https://github.com/OpenSC/libp11 (it also has a nice wiki that explains how to do it on the command line using OPENSSL.EXE) Then create an openssl.cnf section like this: |openssl_conf = openssl_init [openssl_init] engines = engine_section [engine_section] pkcs11 = pkcs11_section [pkcs11_section] engine_id = pkcs11 dynamic_path = "C:\Windows\System32\opensc-pkcs11.dll" MODULE_path = "||C:\Users\whipp\junk4\ActivClient\acpkcs211.dll" PIN = "0001password" init = 0| and load that (see the EAP-TLS code for an example or read https://stackoverflow.com/questions/41119744/pkcs11-engine-for-openssl for a similar question). HTH, JJK On 2020-12-15 4:38 a.m., Jan Just Keijser wrote: Hi, On 14/12/20 21:01, George wrote: Ok, so I am not actually going to populate EVP_PKEY with a private key in the callback function: int (*client_cert_cb)(SSL *ssl, X509 **x509, *EVP_PKEY **pkey*)? Instead, I will call EVP_PKEY *ENGINE_load_private_key(ENGINE *e, const char *key_id, UI_METHOD *ui_method, void *callback_data); to get the EVP_PKEY, which will be used by OpenSSL to access the Smart Card. Once I get the resulting EVP_PKEY using ENGINE_load_private_key(...), how do I assign it to pkey in the callback function? If I had private key I would use something like EVP_PKEY_assign_RSA(..) Since I don't actually have a private key, should I use something else? like Michael pointed out, my eap-tls code is just an example of how you could handle a pkcs11 device; it does not us a callback at all, but my code loads the client cert+key upfront and avoids having to use a client callback altogether. I guess you could also use a client callback for this (perhaps in combination with SSL_CTX_set_client_cert_engine()) . In that case you would get the (pseudo) key from the engine like this EVP_PKEY *engine_key = ENGINE_load_private_key(ENGINE *e, const char *key_id, UI_METHOD *ui_method, void *callback_data); and then set pkey = _key; and see if that works. Note that the ENGINE_load_private_key() function *does* return a EVP_PKEY struct but that does not mean the entire private key is contained in it; a private key consists of a modulus and a private part (exponent, prime1, prime2, exponent1, exponent2 etc). the ENGINE_load_private_key() call will return a struct containing the modulus but not the rest. You then use the engine to do the actual encryption and decryption. HTH, JJK