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

Reply via email to