Added test code for Mozilla-like keypair generation and the writing of a certificate

git-svn-id: https://www.opensc-project.org/svnp/opensc/trunk@1300 c6295689-39f2-0310-b995-f0e70906c6a9
This commit is contained in:
sth 2003-07-24 11:29:08 +00:00
parent 3a61c4fe97
commit 4cbd578bc0
1 changed files with 165 additions and 13 deletions

View File

@ -70,6 +70,7 @@ const struct option options[] = {
{ "quiet", 0, 0, 'q' },
{ "test", 0, 0, 't' },
{ "moz-cert", 1, 0, 'z' },
{ 0, 0, 0, 0 }
};
@ -93,12 +94,14 @@ const char *option_help[] = {
"Specify the label of the object",
"Specify number of the slot to use",
"Specify label of the slot to use",
"Set the CKA_ID of an object, >args>= the (new) CKA_ID",
"Specify the input file",
"Specify the output file",
"Specify the module to load",
"Quiet operation",
"Test (best used with the --login or --pin option)",
"Test (best used with the --login or --pin option)",
"Test Mozilla-like keypair gen and cert req, <arg>=certfile"
};
const char * app_name = "pkcs11-tool"; /* for utils.c */
@ -144,8 +147,9 @@ static void show_cert(CK_SESSION_HANDLE, CK_OBJECT_HANDLE);
static void sign_data(CK_SLOT_ID,
CK_SESSION_HANDLE, CK_OBJECT_HANDLE);
static void hash_data(CK_SLOT_ID, CK_SESSION_HANDLE);
static void gen_keypair(CK_SLOT_ID, CK_SESSION_HANDLE);
static void write_object(CK_SLOT_ID slot, CK_SESSION_HANDLE session);
static int gen_keypair(CK_SLOT_ID, CK_SESSION_HANDLE,
CK_OBJECT_HANDLE *, CK_OBJECT_HANDLE *);
static int write_object(CK_SLOT_ID slot, CK_SESSION_HANDLE session);
static void set_id_attr(CK_SLOT_ID slot, CK_SESSION_HANDLE session);
static int find_object(CK_SESSION_HANDLE, CK_OBJECT_CLASS,
CK_OBJECT_HANDLE_PTR,
@ -167,6 +171,7 @@ static void p11_perror(const char *, CK_RV);
static const char * CKR2Str(CK_ULONG res);
static int p11_test(CK_SLOT_ID slot, CK_SESSION_HANDLE session);
static int hex_to_bin(const char *in, CK_BYTE *out, size_t *outlen);
static void test_kpgen_certwrite(CK_SLOT_ID slot, CK_SESSION_HANDLE session);
/* win32 needs this in open(2) */
#ifndef O_BINARY
@ -190,6 +195,7 @@ main(int argc, char * const argv[])
int do_write_object = 0;
int do_set_id = 0;
int do_test = 0;
int do_test_kpgen_certwrite = 0;
int need_session = 0;
int opt_login = 0;
int do_change_pin = 0;
@ -197,7 +203,7 @@ main(int argc, char * const argv[])
CK_RV rv;
while (1) {
c = getopt_long(argc, argv, "ILMOa:d:e:hi:klm:o:p:scqty:w:",
c = getopt_long(argc, argv, "ILMOa:d:e:hi:klm:o:p:scqty:w:z:",
options, &long_optind);
if (c == -1)
break;
@ -300,6 +306,11 @@ main(int argc, char * const argv[])
do_test = 1;
action_count++;
break;
case 'z':
do_test_kpgen_certwrite = 1;
opt_file_to_write = optarg;
action_count++;
break;
case 'q':
opt_quiet++;
break;
@ -448,8 +459,10 @@ skip_login:
if (do_hash)
hash_data(opt_slot, session);
if (do_gen_keypair)
gen_keypair(opt_slot, session);
if (do_gen_keypair) {
CK_OBJECT_HANDLE hPublicKey, hPrivateKey;
gen_keypair(opt_slot, session, &hPublicKey, &hPrivateKey);
}
if (do_write_object) {
if (opt_object_class_str == NULL)
@ -468,6 +481,9 @@ skip_login:
if (do_test)
p11_test(opt_slot, session);
if (do_test_kpgen_certwrite)
test_kpgen_certwrite(opt_slot, session);
end:
if (session)
p11->C_CloseSession(session);
@ -776,10 +792,10 @@ hash_data(CK_SLOT_ID slot, CK_SESSION_HANDLE session)
#define FILL_ATTR(attr, typ, val, len) {(attr).type=(typ); (attr).pValue=(val); (attr).ulValueLen=len;}
void
gen_keypair(CK_SLOT_ID slot, CK_SESSION_HANDLE session)
int
gen_keypair(CK_SLOT_ID slot, CK_SESSION_HANDLE session,
CK_OBJECT_HANDLE *hPublicKey, CK_OBJECT_HANDLE *hPrivateKey)
{
CK_OBJECT_HANDLE hPublicKey, hPrivateKey;
CK_MECHANISM mechanism = {CKM_RSA_PKCS_KEY_PAIR_GEN, NULL_PTR, 0};
CK_ULONG modulusBits = 768;
CK_BYTE publicExponent[] = { 3 };
@ -828,17 +844,19 @@ gen_keypair(CK_SLOT_ID slot, CK_SESSION_HANDLE session)
rv = p11->C_GenerateKeyPair(session, &mechanism,
publicKeyTemplate, n_pubkey_attr,
privateKeyTemplate, n_privkey_attr,
&hPublicKey, &hPrivateKey);
hPublicKey, hPrivateKey);
if (rv != CKR_OK)
p11_fatal("C_GenerateKeyPair", rv);
printf("Key pair generated:\n");
show_object(session, hPrivateKey);
show_object(session, hPublicKey);
show_object(session, *hPrivateKey);
show_object(session, *hPublicKey);
return 1;
}
/* Currently only for certificates (-type cert) */
void
int
write_object(CK_SLOT_ID slot, CK_SESSION_HANDLE session)
{
CK_BBOOL true = TRUE;
@ -908,6 +926,8 @@ write_object(CK_SLOT_ID slot, CK_SESSION_HANDLE session)
printf("Generated private key:\n");
show_object(session, privkey_obj);
}
return 1;
}
void
@ -2173,6 +2193,138 @@ p11_test(CK_SLOT_ID slot, CK_SESSION_HANDLE session)
return errors;
}
/* Does about the same as Mozilla does when you go to an on-line CA
* for obtaining a certificate: key pair generation, signing the
* cert request + some other tests, writing certs and changing
* some attributes.
*/
static void
test_kpgen_certwrite(CK_SLOT_ID slot, CK_SESSION_HANDLE session)
{
CK_MECHANISM mech = {CKM_RSA_PKCS, NULL_PTR, 0};
CK_MECHANISM_TYPE *mech_type = NULL;
CK_OBJECT_HANDLE pub_key, priv_key;
CK_ULONG i, num_mechs = 0;
CK_RV rv;
CK_BYTE buf[20], *tmp;
CK_BYTE md5_and_digestinfo[34] = "\x30\x20\x30\x0c\x06\x08\x2a\x86\x48\x86\xf7\x0d\x02\x05\x05\x00\x04\x10";
CK_BYTE *data, sig[512];
CK_ULONG data_len, sig_len;
CK_BYTE *id = "abcdefghijklmnopqrst";
CK_ULONG id_len = 20;
CK_BYTE *label = "Just a label";
CK_ULONG label_len = 12;
CK_ATTRIBUTE attribs[3] = {
{CKA_ID, id, id_len},
{CKA_LABEL, label, label_len},
{CKA_SUBJECT, "This won't be used in our lib", 29}
};
unsigned char cert[5000];
int cert_len;
FILE *f;
get_mechanisms(slot, &mech_type, &num_mechs);
for (i = 0; i < num_mechs; i++) {
if (mech_type[i] == CKM_RSA_PKCS_KEY_PAIR_GEN)
break;
}
if (i == num_mechs) {
printf("ERR: no \"CKM_RSA_PKCS_KEY_PAIR_GEN\" found in the mechanism list\n");
return;
}
f = fopen(opt_file_to_write, "rb");
if (f == NULL)
fatal("Couldn't open file \"%s\"\n", opt_file_to_write);
fclose(f);
/* Get for a not-yet-existing ID */
while(find_object(session, CKO_PRIVATE_KEY, &priv_key, id, id_len, 0))
id[0]++;
printf("\n*** Generating a 1024 bit RSA key pair ***\n");
if (!gen_keypair(slot, session, &pub_key, &priv_key))
return;
tmp = getID(session, priv_key, &opt_object_id_len);
if (opt_object_id == NULL || opt_object_id_len == 0) {
printf("ERR: newly generated private key has no (or an empty) CKA_ID\n");
return;
}
memcpy(opt_object_id, tmp, opt_object_id_len);
printf("\n*** Changing the CKA_ID of private and public key into one of 20 bytes ***\n");
rv = p11->C_SetAttributeValue(session, priv_key, attribs, 1);
if (rv != CKR_OK)
p11_fatal("C_SetAttributeValue(priv_key)", rv);
rv = p11->C_SetAttributeValue(session, pub_key, attribs, 1);
if (rv != CKR_OK)
p11_fatal("C_SetAttributeValue(pub_key)", rv);
printf("\n*** Do a signature and verify it (presumably to test the keys) ***\n");
data = buf;
data_len = 20;
rv = p11->C_SignInit(session, &mech, priv_key);
if (rv != CKR_OK)
p11_fatal("C_SignInit", rv);
rv = p11->C_Sign(session, data, data_len, NULL, &sig_len);
if (rv != CKR_OK)
p11_fatal("C_Sign", rv);
printf("sig_len = %d\n", sig_len);
sig_len = 20;
rv = p11->C_Sign(session, data, data_len, sig, &sig_len);
if (rv != CKR_BUFFER_TOO_SMALL) {
printf("ERR: C_Sign() didn't return CKR_BUFFER_TO_SMALL but %s\n", CKR2Str(rv));
return;
}
rv = p11->C_Sign(session, data, data_len, sig, &sig_len);
if (rv != CKR_OK)
p11_fatal("C_Sign", rv);
rv = p11->C_VerifyInit(session, &mech, pub_key);
if (rv != CKR_OK)
p11_fatal("C_VerifyInit", rv);
rv = p11->C_Verify(session, data, data_len, sig, sig_len);
if (rv != CKR_OK)
p11_fatal("C_Verify", rv);
printf("\n*** Signing the certificate request ***\n");
/* Sign the certificate request */
data = md5_and_digestinfo;
data_len = 20;
rv = p11->C_SignInit(session, &mech, priv_key);
rv = p11->C_Sign(session, data, data_len, sig, &sig_len);
if (rv != CKR_OK)
p11_fatal("C_SignInit", rv);
if (rv != CKR_OK)
p11_fatal("C_Sign", rv);
printf("\n*** In real life, the cert req should be sent to the CA ***\n");
printf("\n*** Changing the CKA_LABEL, CKA_ID and CKA_SUBJECT of the public key ***\n");
rv = p11->C_SetAttributeValue(session, pub_key, attribs, 3);
if (rv != CKR_OK)
p11_fatal("C_SetAttributeValue", rv);
printf("\n*** Put a cert on the card (NOTE: doesn't correspond with the key!) ***\n");
opt_object_class = CKO_CERTIFICATE;
memcpy(opt_object_id, id, id_len);
opt_object_id_len = id_len;
opt_object_label = label;
if (!write_object(slot, session))
return;
printf("\n==> OK, successfull! Should work with Mozilla\n");
}
const char *
p11_flag_names(struct flag_info *list, CK_FLAGS value)
{