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_cx()” 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
fa 3f 33 5c d9 d3 3b 2f a4 4f 87 17 73 09 c0 23
c7 56 40 ce 5f 3f 61 b1 b7 94 43 98 9f d0 cc c0
cd 38 e2 94 c4 64 a0 8f 3d fe e4 03 18 5f 83 9d
da 04 42 3a f3 ad c1 3b 0c f3 60 f9 f8 c8 bc 95
83 2f 67 9b b7 3a 38 fe 79 66 30 80 7f 17 00 31
71 ee 2e c6 cd 7b 09 f3 09 eb c0 bd 45 4b 88 a9
36 23 87 71 a0 12 78 ba c5 34 be 8e ca c4 07 73
cd ea a9 90 c2 bf 31 aa ee ba 49 18 74 2e 9b 8c
97 94 cb 11 5e cd fc 24 e5 84 e4 9f 17 5a ac 2b
6d a5 61 bf 5d 3e 00 49 99 b0 90 32 33 02 42 ac
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
6c 9e dc 13 82 19 cd 49 7a fc 2c f0 52 ad 74 4a
da f5 e5 71 50 d3 f9 e6 fc eb 67 6c 82 fa 00 e6
8f 2f 0a a0 9d c7 a6 85 5f 8e 93 07 53 9c e5 b3
23 9b fe 36 88 e5 7f f4 cf 81 13 dc 58 de e6 e1
d5 fe bf 5b db 5d a1 63 29 3e 96 13 d2 1a b6 b2
1f 95 73 90 97 86 ce e3 de 08 8d bc a3 11 9f 04
f5 f4 8d 8f 32 29 2c 91 74 0f 85 ab 75 3a c3 58
3e e9 30 48 f2 ae 67 08 f7 14 ce 0c 73 50 3b d4
94 aa 15 a3 79 e1 5b 27 a4 80 b9 71 53 5b 46 13
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:

0x7fff739f3000 16:10:25.4294968080 [opensc-pkcs11] 
card-piv.c:2310:piv_validate_general_authentication: returning with: -1208 
(Card does not support the requested operation)
0x7fff739f3000 16:10:25.784 [opensc-pkcs11] card-piv.c:2419:piv_decipher: 
returning with: -1208 (Card does not support the requested operation)
0x7fff739f3000 16:10:25.784 [opensc-pkcs11] sec.c:44:sc_decipher: returning 
with: -1208 (Card does not support the requested operation)
0x7fff739f3000 16:10:25.784 [opensc-pkcs11] 
card-piv.c:2221:piv_set_security_env: called
0x7fff739f3000 16:10:25.784 [opensc-pkcs11] 
card-piv.c:2252:piv_set_security_env: returning with: 0 (Success)
0x7fff739f3000 16:10:25.140552804762384 [opensc-pkcs11] 
sec.c:72:sc_set_security_env: returning with: 0 (Success)
0x7fff739f3000 16:10:25.784 [opensc-pkcs11] card-piv.c:2417:piv_decipher: called
0x7fff739f3000 16:10:25.4294968080 [opensc-pkcs11] 
card-piv.c:2281:piv_validate_general_authentication: called
0x7fff739f3000 16:10:25.4294968080 [opensc-pkcs11] 
card-piv.c:2310:piv_validate_general_authentication: returning with: -1208 
(Card does not support the requested operation)
0x7fff739f3000 16:10:25.784 [opensc-pkcs11] card-piv.c:2419:piv_decipher: 
returning with: -1208 (Card does not support the requested operation)
0x7fff739f3000 16:10:25.784 [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()”:

0x7fff739f3000 16:12:35.132 [opensc-pkcs11] 
reader-pcsc.c:313:refresh_attributes: returning with: 0 (Success)
0x7fff739f3000 16:12:35.140733193388164 [opensc-pkcs11] 
reader-pcsc.c:389:pcsc_detect_card_presence: returning with: 5
0x7fff739f3000 16:12:35.4294967435 [opensc-pkcs11] sec.c:206:sc_pin_cmd: 
returning with: 0 (Success)
0x7fff739f3000 16:12:37.939 [opensc-pkcs11] sec.c:206:sc_pin_cmd: returning 
with: 0 (Success)
0x7fff739f3000 16:12:37.940 [opensc-pkcs11] 
card-piv.c:2221:piv_set_security_env: called
0x7fff739f3000 16:12:37.940 [opensc-pkcs11] 
card-piv.c:2252:piv_set_security_env: returning with: 0 (Success)
0x7fff739f3000 16:12:37.140295106724780 [opensc-pkcs11] 
sec.c:72:sc_set_security_env: returning with: 0 (Success)
0x7fff739f3000 16:12:37.940 [opensc-pkcs11] card-piv.c:2417:piv_decipher: called
0x7fff739f3000 16:12:37.140733193388972 [opensc-pkcs11] 
card-piv.c:2281:piv_validate_general_authentication: called
0x7fff739f3000 16:12:37.4294968236 [opensc-pkcs11] 
card-piv.c:454:piv_general_io: called
0x7fff739f3000 16:12:38.608 [opensc-pkcs11] card-piv.c:2419:piv_decipher: 
returning with: 256
0x7fff739f3000 16:12:38.608 [opensc-pkcs11] sec.c:44:sc_decipher: returning 
with: 256
0x7fff739f3000 16:12:38.609 [opensc-pkcs11] card-piv.c:2819:piv_finish: called
0x7fff739f3000 16:12:38.140295106724457 [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
-- 
openssl-users mailing list
To unsubscribe: https://mta.openssl.org/mailman/listinfo/openssl-users

Reply via email to