Using a SCA6000 part 2
Posted by jad on Feb 13th, 2007
The other day I blogged about using a SCA6000. I showed an example that I hoped would create a RSA key in the keystore.
Further investigation revealed that I was wrong. There were two things wrong with the code. First, the code shown was missing a call to C_Login to login to the keystore. Second, both the public and private key templates used by the C_GenerateKeyPair function needed to have the CKA_Token attribute set to true.
Here is the corrected code.
#include <stdio.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/types.h>
#include <security/cryptoki.h>
#include <security/pkcs11.h>
#define BUFFERSIZ 8192
/* Define key template */
static CK_BBOOL truevalue = TRUE;
static CK_BBOOL falsevalue = FALSE;
static CK_ULONG modulusbits = 512;
static CK_BYTE public_exponent[] = {3};
static CK_BYTE myid[] = {123};
static CK_CHAR mylabel[] = "i am a key";
void
main(int argc, char **argv)
{
CK_RV rv;
CK_MECHANISM genmech;
CK_SESSION_HANDLE hSession;
CK_SESSION_INFO sessInfo;
CK_UTF8CHAR pin[32], plabel;
int error, i = 0;
CK_OBJECT_HANDLE privatekey, publickey;
/* Set public key. */
CK_ATTRIBUTE publickey_template[] = {
{CKA_VERIFY, &truevalue, sizeof (truevalue)},
{CKA_MODULUS_BITS, &modulusbits, sizeof (modulusbits)},
{CKA_TOKEN, &truevalue, sizeof (truevalue)},
{CKA_PUBLIC_EXPONENT, &public_exponent,
sizeof (public_exponent)}
};
/* Set private key. */
CK_ATTRIBUTE privatekey_template[] = {
{CKA_SIGN, &truevalue, sizeof (truevalue)},
{CKA_TOKEN, &truevalue, sizeof (truevalue)},
{CKA_PRIVATE, &truevalue, sizeof (truevalue)},
{CKA_SENSITIVE, &truevalue, sizeof (truevalue)},
{CKA_LABEL, mylabel, sizeof (mylabel)},
{CKA_ID, myid, sizeof (myid)}
};
/* Create sample message. */
CK_ATTRIBUTE getattributes[] = {
{CKA_MODULUS_BITS, NULL_PTR, 0},
{CKA_MODULUS, NULL_PTR, 0},
{CKA_PUBLIC_EXPONENT, NULL_PTR, 0}
};
CK_ULONG messagelen, slen, template_size, template_size1;
uchar_t *message = (uchar_t *)"Simple message for signing & verifying.";
uchar_t *modulus, *pub_exponent;
char sign[BUFFERSIZ];
slen = BUFFERSIZ;
messagelen = strlen((char *)message);
/* Set up mechanism for generating key pair */
genmech.mechanism = CKM_RSA_PKCS_KEY_PAIR_GEN;
genmech.pParameter = NULL_PTR;
genmech.ulParameterLen = 0;
/* Initialize the CRYPTOKI library */
rv = C_Initialize(NULL_PTR);
if (rv != CKR_OK) {
fprintf(stderr, "C_Initialize: Error = 0x%.8Xn", rv);
exit(1);
}
/* Open a session on the slot found */
rv = C_OpenSession(0, CKF_RW_SESSION+CKF_SERIAL_SESSION, NULL_PTR, NULL_PTR,
&hSession);
if (rv != CKR_OK) {
fprintf(stderr, "C_OpenSession: rv = 0x%.8Xn", rv);
error = 1;
goto exit_program;
}
/* Login to the Nominet Token (Keystore) */
strcpy (pin, "nominet1:abc123");
rv = C_Login(hSession, CKU_USER, pin, sizeof (pin) );
if (rv != CKR_OK) {
fprintf(stderr, "C_Login: rv = 0x%.8Xn", rv);
error = 1;
goto exit_program;
}
fprintf(stdout, "Generating keypair....n");
/* Generate Key pair for signing/verifying */
rv = C_GenerateKeyPair(hSession, &genmech, publickey_template,
(sizeof (publickey_template) / sizeof (CK_ATTRIBUTE)),
privatekey_template,
(sizeof (privatekey_template) / sizeof (CK_ATTRIBUTE)),
&publickey, &privatekey);
if (rv != CKR_OK) {
fprintf(stderr, "C_GenerateKeyPair: rv = 0x%.8Xn", rv);
error = 1;
goto exit_session;
}
/* Display the publickey. */
template_size = sizeof (getattributes) / sizeof (CK_ATTRIBUTE);
rv = C_GetAttributeValue(hSession, publickey, getattributes,
template_size);
if (rv != CKR_OK) {
/* not fatal, we can still sign/verify if this failed */
fprintf(stderr, "C_GetAttributeValue: rv = 0x%.8Xn", rv);
error = 1;
} else {
/* Allocate memory to hold the data we want */
for (i = 0; i < template_size; i++) {
getattributes[i].pValue =
malloc (getattributes[i].ulValueLen *
sizeof(CK_VOID_PTR));
if (getattributes[i].pValue == NULL) {
int j;
for (j = 0; j < i; j++)
free(getattributes[j].pValue);
goto exit_session;
}
}
/* Call again to get actual attributes */
rv = C_GetAttributeValue(hSession, publickey, getattributes,
template_size);
if (rv != CKR_OK) {
/* not fatal, we can still sign/verify if failed */
fprintf(stderr,
"C_GetAttributeValue: rv = 0x%.8Xn", rv);
error = 1;
} else {
/* Display public key values */
fprintf(stdout, "Public Key data:ntModulus bits: "
"%dn",
*((CK_ULONG_PTR)(getattributes[0].pValue)));
fprintf(stdout, "tModulus: ");
modulus = (uchar_t *)getattributes[1].pValue;
for (i = 0; i < getattributes[1].ulValueLen; i++) {
fprintf(stdout, "%.2x", modulus[i]);
}
fprintf(stdout, "ntPublic Exponent: ");
pub_exponent = (uchar_t *)getattributes[2].pValue;
for (i = 0; i< getattributes[2].ulValueLen; i++) {
fprintf(stdout, "%.2x", pub_exponent[i]);
}
fprintf(stdout, "n");
}
}
exit_session:
(void) C_CloseSession(hSession);
exit_program:
(void) C_Finalize(NULL_PTR);
for (i = 0; i < template_size; i++) {
if (getattributes[i].pValue != NULL)
free(getattributes[i].pValue);
}
exit(error);
}
To show that the key really was in the keystore I used pkcs11-tool. This is part of opensc.
-bash-3.00$ /opt/opensc/bin/pkcs11-tool --module=/usr/lib/libpkcs11.so -p nominet1:abc123 -O --slot 0 Private Key Object; RSA label: i am a key ID: 7b Usage: decrypt, sign, unwrap Public Key Object; RSA 512 bits label: Usage: encrypt, verify, wrap
Now how do I use this key?

February 19th, 2007 at 11:46 am
[…] We have been playing with the various dnssec zone signers to see how they could work with crypto hardware like the SCA6000 I blogged about the other day. However all of them expect the public and private keys to be stored on disk and have their own code to push these keys into openssl. Clearly this makes telling them to use a key stored in an HSM impossible. Based on our initial observations we suggest that signers should take the following approach. […]
September 4th, 2008 at 12:02 pm
Hi jad,
this was a great article, knowledge about sca6000 seems to be rare. May I ask you if you came along the situation to hardware reset your board? Because I have some problems here with that. I cannot reinitialize the board with “scamgr -D” anymore. I get the output:
C_GetMechanismList returned no mechanisms.
C_GetMechanismList returned no mechanisms.
No token was found with the required mechanisms.
Thank you very much.
kind regards
Rene
PS: sorry for putting in an url to the sun forum, but thats where I posted all the details if you have a minute. Thank you for sharing your knowledge anyway!
http://forums.sun.com/thread.jspa?threadID=5328473&tstart=0