Hi everyone, here is a bug report with a patch for pkcs11-tool.
I'm no expert on this subject, so feedback is very welcome. it looks good in general, except maybe more return codes/ error checking etc., and a different code path if pkcs11-tool is compiled without openssl. the author asks about two attributes where he isn't sure what to do best. I don't know either, so if anyone can take care of the bug&patch, that would be great. Thanks, Andreas ---------- Weitergeleitete Nachricht ---------- Betreff: patch for pkcs11-tool - write pubkey objects Datum: Montag 15 März 2010 Von: Jaroslav Benkovský <jaroslav.benkov...@nic.cz> An: b...@opensc-project.org Hello, the attached patch allows pkcs11-tool to write RSA public keys to a device. I am not sure why it was left out at all, but I need it to get opendnssec working with externally generated keys and SCA6000 and this patch allows me to do that. I am not sure with CKA_WRAP=FALSE & CKA_ENCRYPT=FALSE, but I set it to be the same as device generated keys I have there. If you have any comments, questions, etc, write me. Regards, Jarda Benkovsky -------------------------------------------------------------
--- pkcs11-tool.c.orig 2010-03-12 17:00:58.002129280 +0100 +++ pkcs11-tool.c 2010-03-15 16:08:56.113081803 +0100 @@ -1178,30 +1178,47 @@ RSA_GET_BN(exponent_2, r->dmq1); RSA_GET_BN(coefficient, r->iqmp); } + +static void parse_rsa_public_key(struct rsakey_info *rsa, + unsigned char *data, int len) +{ + RSA *r = NULL; + const unsigned char *p; + + p = data; + r = d2i_RSA_PUBKEY(NULL, &p, len); + + if (!r) { + r = d2i_RSAPublicKey(NULL, &p, len); + } + + if (!r) { + /* ERR_print_errors_fp(stderr); */ + util_fatal("OpenSSL error during RSA public key parsing"); + } + RSA_GET_BN(modulus, r->n); + RSA_GET_BN(public_exponent, r->e); +} #endif #define MAX_OBJECT_SIZE 5000 -/* Currently only for certificates (-type cert), - private keys (-type privkey) and data objetcs (-type data). +/* Currently for certificates (-type cert), private keys (-type privkey), + public keys (-type pubkey) and data objects (-type data). Note: only RSA private keys are supported. */ static int write_object(CK_SLOT_ID slot, CK_SESSION_HANDLE session) { CK_BBOOL _true = TRUE; + CK_BBOOL _false = FALSE; unsigned char contents[MAX_OBJECT_SIZE]; int contents_len = 0; unsigned char certdata[MAX_OBJECT_SIZE]; int certdata_len = 0; FILE *f; - CK_OBJECT_HANDLE cert_obj, privkey_obj, data_obj; - CK_ATTRIBUTE cert_templ[20], privkey_templ[20], data_templ[20]; - int n_cert_attr = 0, n_privkey_attr = 0, n_data_attr = 0; + CK_OBJECT_HANDLE cert_obj, privkey_obj, pubkey_obj, data_obj; + CK_ATTRIBUTE cert_templ[20], privkey_templ[20], pubkey_templ[20], data_templ[20]; + int n_cert_attr = 0, n_privkey_attr = 0, n_pubkey_attr = 0, n_data_attr = 0; struct sc_object_id oid; -#if 0 - CK_ATTRIBUTE pubkey_templ[20]; - CK_OBJECT_HANDLE pubkey_obj; - int n_pubkey_attr = 0; -#endif CK_RV rv; int need_to_parse_certdata = 0; #ifdef ENABLE_OPENSSL @@ -1249,6 +1266,13 @@ util_fatal("No OpenSSL support, cannot parse RSA private key\n"); #endif } + if (opt_object_class == CKO_PUBLIC_KEY) { +#ifdef ENABLE_OPENSSL + parse_rsa_public_key(&rsa, contents, contents_len); +#else + util_fatal("No OpenSSL support, cannot parse RSA public key\n"); +#endif + } if (opt_object_class == CKO_CERTIFICATE) { CK_OBJECT_CLASS clazz = CKO_CERTIFICATE; @@ -1338,6 +1362,49 @@ #endif } else + if (opt_object_class == CKO_PUBLIC_KEY) { + CK_OBJECT_CLASS clazz = CKO_PUBLIC_KEY; + CK_KEY_TYPE type = CKK_RSA; + CK_ULONG modulus_bits = rsa.modulus_len * 8; + + FILL_ATTR(pubkey_templ[0], CKA_CLASS, &clazz, sizeof(clazz)); + FILL_ATTR(pubkey_templ[1], CKA_KEY_TYPE, &type, sizeof(type)); + FILL_ATTR(pubkey_templ[2], CKA_TOKEN, &_true, sizeof(_true)); + FILL_ATTR(pubkey_templ[3], CKA_PRIVATE, &_true, sizeof(_true)); + n_pubkey_attr = 4; + + if (opt_object_label != NULL) { + FILL_ATTR(pubkey_templ[n_pubkey_attr], CKA_LABEL, + opt_object_label, strlen(opt_object_label)); + n_pubkey_attr++; + } + if (opt_object_id_len != 0) { + FILL_ATTR(pubkey_templ[n_pubkey_attr], CKA_ID, + opt_object_id, opt_object_id_len); + n_pubkey_attr++; + } +#ifdef ENABLE_OPENSSL + if (cert.subject_len != 0) { + FILL_ATTR(pubkey_templ[n_pubkey_attr], CKA_SUBJECT, + cert.subject, cert.subject_len); + n_pubkey_attr++; + } + FILL_ATTR(pubkey_templ[n_pubkey_attr], CKA_WRAP, &_false, sizeof(_false)); + n_pubkey_attr++; + FILL_ATTR(pubkey_templ[n_pubkey_attr], CKA_ENCRYPT, &_false, sizeof(_false)); + n_pubkey_attr++; + FILL_ATTR(pubkey_templ[n_pubkey_attr], CKA_MODULUS, + rsa.modulus, rsa.modulus_len); + n_pubkey_attr++; + FILL_ATTR(pubkey_templ[n_pubkey_attr], CKA_MODULUS_BITS, + &modulus_bits, sizeof (modulus_bits)); + n_pubkey_attr++; + FILL_ATTR(pubkey_templ[n_pubkey_attr], CKA_PUBLIC_EXPONENT, + rsa.public_exponent, rsa.public_exponent_len); + n_pubkey_attr++; +#endif + } + else if (opt_object_class == CKO_DATA) { CK_OBJECT_CLASS clazz = CKO_DATA; FILL_ATTR(data_templ[0], CKA_CLASS, &clazz, sizeof(clazz)); @@ -1392,7 +1459,6 @@ show_object(session, cert_obj); } -#if 0 if (n_pubkey_attr) { rv = p11->C_CreateObject(session, pubkey_templ, n_pubkey_attr, &pubkey_obj); if (rv != CKR_OK) @@ -1401,7 +1467,6 @@ printf("Generated public key:\n"); show_object(session, pubkey_obj); } -#endif if (n_privkey_attr) { rv = p11->C_CreateObject(session, privkey_templ, n_privkey_attr, &privkey_obj);
_______________________________________________ opensc-devel mailing list opensc-devel@lists.opensc-project.org http://www.opensc-project.org/mailman/listinfo/opensc-devel