[openssl-users] How to properly use ui_method in ENGINE_load_private_key()?

Blumenthal, Uri - 0553 - MITLL uri at ll.mit.edu
Mon Feb 29 22:51:52 UTC 2016


I am writing an app that needs to use RSA keys on a PKCS11-accessible
token to encrypt and decrypt symmetric keys. For the context (no pun
intended :) think of creating or mounting an existing encrypted file
system.

To begin with, and to grasp the finer details of the programmatic
interface of libcrypto, I’m “sculpting” my code after apps/pkeyutl.c and
apps/apps.c.

When I use “init_ctx()” that in turn calls “load_key()” method in “apps.o”
(and link my code with “apps.o” in addition to “-lcrypto”), everything
works fine:

We expect an RSA token for this demo...
Input buffer:
01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f 10
10 0f 0e 0d 0c 0b 0a 09 08 07 06 05 04 03 02 01

encrypt: allocating 256 bytes (rv=1)
RSA encryption succeeded (rv=1 len=256):
10 e5 a6 95 63 48 54 3f e2 84 7f 9c 39 6f 8c cd
9a ef 18 3b 66 32 46 bf 9f d4 76 91 ce 98 5d 33
cd a7 cf 4e b7 d5 98 51 2d e3 8e 4f 09 52 1d 0f
.. .. .. .. .. .. .. .. .. ..
fc 46 db 1d 8e 1d 7e 7e a4 a1 e3 c8 60 43 28 26
ef c4 84 d2 0d cf 92 61 75 bc 0c d9 47 b1 bb 9e
78 00 32 b8 4b 35 c2 08 ad f6 f7 f8 bf e1 13 b1
PKCS#11 token PIN: xxxxxxxx

decrypt: allocating 256 bytes (rv=1)
RSA decryption succeeded (rv=1 len=32):
01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f 10
10 0f 0e 0d 0c 0b 0a 09 08 07 06 05 04 03 02 01

However when I try to call the EVP methods directly instead of going
through the routines provided in apps.c, the decryption fails:

……

Encrypted symmetric key (256 bytes):
76 f8 e9 b0 38 45 b5 fd b4 8e 96 f9 8a 86 ab 5a
83 42 a4 b8 7e 06 e0 b7 ae 8c 7f 6c 5e 68 bd eb
bf 3f 87 0c f8 0e 90 8f cd ec 01 f7 80 a8 71 00
3d 7a 5d 30 db 7f 7b 18 e2 de c0 c2 9e 07 ca 1f
.. .. .. .. .. .. .. .. .. ..

f2 c5 4b 0e 1d c7 57 3b 9f f4 a3 55 09 37 1a 47
68 0c e4 fc 86 1e d0 cc 3d 4d d7 25 7c 40 77 ba
74 a5 ce 60 03 ea d4 54 a2 58 52 b5 aa bf 4a d2

PKCS#11 token PIN: xxxxxxxx

unwrap: loaded privkey of size 256
unwrap: allocating 256 bytes...
unwrap: decrypt returned 1 (0 bytes)
unwrapping returned 1
Decrypted symmetric key (0 bytes):

You can see that up to the actual loading of the private key things are
the same, and both variants of the app (the one using apps.c, and the one
trying to directly call the EVP API) show the same prompt for the token
PIN, and in both cases it appears (though I’m not sure at all of that)
that the private key handle gets loaded.

The opens-debug.log file shows that there was a problem with the
authentication to the token:

 [opensc-pkcs11] card-piv.c:2221:piv_set_security_env: called
 [opensc-pkcs11] card-piv.c:2252:piv_set_security_env: returning with: 0
(Success)
 [opensc-pkcs11] sec.c:72:sc_set_security_env: returning with: 0 (Success)
 [opensc-pkcs11] card-piv.c:2417:piv_decipher: called
 [opensc-pkcs11] card-piv.c:2281:piv_validate_general_authentication:
called
 [opensc-pkcs11] card-piv.c:2310:piv_validate_general_authentication:
returning with: -1208 (Card does not support the requested operation)
 [opensc-pkcs11] card-piv.c:2419:piv_decipher: returning with: -1208 (Card
does not support the requested operation)
 [opensc-pkcs11] sec.c:44:sc_decipher: returning with: -1208 (Card does
not support the requested operation)


This differs from what the log shows when the private key was loaded with
“load_key()”:
...
 [opensc-pkcs11] sec.c:206:sc_pin_cmd: returning with: 0 (Success)
 [opensc-pkcs11] sec.c:206:sc_pin_cmd: returning with: 0 (Success)
 [opensc-pkcs11] card-piv.c:2221:piv_set_security_env: called
 [opensc-pkcs11] card-piv.c:2252:piv_set_security_env: returning with: 0
(Success)
 [opensc-pkcs11] sec.c:72:sc_set_security_env: returning with: 0 (Success)
 [opensc-pkcs11] card-piv.c:2417:piv_decipher: called
 [opensc-pkcs11] card-piv.c:2281:piv_validate_general_authentication:
called
 [opensc-pkcs11] card-piv.c:454:piv_general_io: called
 [opensc-pkcs11] card-piv.c:2419:piv_decipher: returning with: 256
 [opensc-pkcs11] sec.c:44:sc_decipher: returning with: 256
 [opensc-pkcs11] card-piv.c:2819:piv_finish: called
 [opensc-pkcs11] ctx.c:818:sc_release_context: called


Here’s the relevant excerpt from the code that fails:

 /* Retrieve the handle to private key on the token */
 /* Here need to get user PIN somehow ... */
 PW_CB_DATA cb_data;
 cb_data.password = NULL;
 cb_data.prompt_info = "id_03";
 privkey = ENGINE_load_private_key(*e, "id_03", NULL, &cb_data);
 if (privkey == NULL) {
   fprintf(stderr, "unwrap: failed to get handle to privkey id_03\n");
   goto end;
 }
 printf("unwrap: loaded privkey of size %1d\n", EVP_PKEY_size(privkey));

 /* Create context */
 ctx = EVP_PKEY_CTX_new(privkey, NULL);
 EVP_PKEY_free(privkey);
 if (ctx == NULL) {
   fprintf(stderr, "unwrap: failed to create context\n");
   goto end;
 }
 rv = EVP_PKEY_decrypt_init(ctx);
 EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_PADDING);
 if (rv <= 0) {
   fprintf(stderr, "unwrap: failed to initialize decrypt_ctx (rv=%d\n",
rv);
   goto end;
 }

 /* Unwrap the encrypted key */
 *olen = 0;
 rv = EVP_PKEY_decrypt(ctx, NULL, olen, in, inlen);
 if ((rv <= 0) || (*olen == 0)) {
   fprintf(stderr, "unwrap: failed to get required output buf len
(rv=%d)\n", rv);
   goto end;
 }
 printf("unwrap: allocating %1lu bytes...\n", *olen);
 *out = OPENSSL_malloc(*olen);
 if (*out == NULL) {
   fprintf(stderr, "unwrap: failed to allocate output buf (%1lu bytes)\n",
*olen);
   rv = -1;
   goto end;
 }
 rv = EVP_PKEY_decrypt(ctx, *out, olen, in, inlen);
 if (rv <= 0) {
   OPENSSL_free(*out);
   fprintf(stderr, "unwrap: failed to decrypt (rv=%d)\n", rv);
   goto end;
 }
 printf("unwrap: decrypt returned %d (%1lu bytes)\n", rv, *olen);


I tried, but could not figure out from looking at “apps.c” what structures
and methods I need to pass to “ENGINE_load_private_key()”, and how to
properly initialize them. Web searches did not help.

I’d appreciate guidance, as I’d rather not pull the entire “apps.c” into
the app I’m building, it it can be avoided.

Thanks!
--
Regards,
Uri Blumenthal



More information about the openssl-users mailing list