random technical thoughts from the Nominet technical team

Beware setting a guaranteed restore point

1 Star2 Stars3 Stars4 Stars5 Stars (No Ratings Yet)
Loading ... Loading ...
Posted by jason on Feb 22nd, 2007

Oracle Flashback database is a new 10g feature that in theory allows you to “flash” the database back to a certain point in time, assuming you have the flashback logs covering the period you want to flashback to. While I was not keen on using this in production (too new & maybe too much overhead) I thought it seemed ideal for our testing & beta environments so that changes could be tested and then the test database flashed back to a consistent point. We had a reason for using this quite recently and it was not a happy experience. To setup flashback database is quite straightforward:

SQL> alter system set db_recovery_file_dest_size = SPACE;

SQL> alter system set db_recovery_file_dest = 'your flashback destination';

SQL> alter system set db_flashback_retention_target = 86400;

Where SPACE is an amount of space you want to allocate in your flashback destination - which is a filesystem/raw partition/ASM diskgroup. The retention target is the time in seconds that you want to be able to flash back to.

You now need to have the database in the mount state and run the following:

SQL> alter database flashback on;

You are now good to go and can open the database. You can check you have flashback enabled by running the following:

SQL> select flashback_on from v$database;

FLASHBACK_ON
------------------
YES

So there came a time when we actually wanted to flash back. I was using the following query to determine how far back the database could go:

SQL> select * from v$flashback_database_log;

OLDEST_FLASHBACK_SCN OLDEST_FL RETENTION_TARGET FLASHBACK_SIZE ESTIMATED_FLASHBACK_SIZE
-------------------- --------- ---------------- -------------- ------------------------
916940214              27-DEC-06      172800     7368949760           3064135680

So this looked good and seemed to indicate we could flashback several months. So we tried going back a couple of weeks:

SQL> flashback database to timestamp to_date('01/02/2007 00:01:01', 'DD/MM/YYYY HH24:MI:SS');

flashback database to timestamp to_date('01/02/2007 00:01:01', 'DD/MM/YYYY HH24:MI:SS')

*

ERROR at line 1:

ORA-38726: Flashback database logging is not on.

We checked the flashback status from v$database again - we had not looked at this for a while:

SQL>  select flashback_on from v$database;

FLASHBACK_ON
------------------
RESTORE POINT ONLY

It was at this point we realised that at some point earlier we had created a guaranteed restore point. To confuse things even further this restore point was created just before upgrading to 10.2.0.3 from 10.2.0.2 and we wanted to flashback to before the upgrade. You can check what restore points you have set with the following:

SQL> select name, scn, time, guarantee_flashback_database from v$restore_point;

NAME                SCN          TIME       GUA
--------------------------------------------------
BEFORE_UPGRADE      922353434    12-Feb-07   YES

We could attempt to flashback to the restore point but an open resetlogs failed.

We have now tested on both 10.2.0.2 and 10.2.0.3 and it seems like creating a guaranteed restore point DOES NOT set the flashback_on column to restore point only - it always remains at yes. The only thing I can conclude is that doing the upgrade screwed with the flashback database - I guess you can’t use flashback to undo a database upgrade! Beware though that with the guaranteed restore point, in theory the flash recovery area will keep filling up and could eventually cause you to run out of space - you can use the drop restore point command to get rid of your guaranteed restore points.

Recovering Oracle Clusterware after losing a VIP

1 Star2 Stars3 Stars4 Stars5 Stars (1 votes, average: 4 out of 5)
Loading ... Loading ...
Posted by jason on Feb 19th, 2007

It is fairly common knowledge that in Oracle 10gR2 clusterware, before the 10.2.0.3 patchset, that there is a real dependency on the public interface that the clusterware VIP is running on. Should this interface fail then Oracle will decide to bring down (crash) all database instances including ASM instances running on the affected node. Here is how we recovered when after upgrading some cisco switches we lost our VIP interfaces on a RAC cluster:

No Instances were running and in the alert log for the instance the last entry was:

ORA-15064: communication failure with ASM instance
ASMB: terminating instance due to error 15064

I had assumed there was a problem with ASM but looking in the Clusterware logs (/opt/oracle/product/crs/log/servername/crsd/crsd.log) showed that the first problem was with the vip:

2007-02-13 11:05:50.090: [CRSAPP][1520634208]0CheckResource error for ora.server1.vip error code = 1
2007-02-13 11:05:50.092: [CRSRES][1520634208]0In stateChanged, ora.server1.vip target is ONLINE
2007-02-13 11:05:50.093: [CRSRES][1520634208]0ora.server1.vip on server1 went OFFLINE unexpectedly
2007-02-13 11:05:50.093: [CRSRES][1520634208]0StopResource: setting CLI values

Taking a look at the status of various resources with crs_stat showed several to be offline and some running on the wrong node:

/opt/oracle/product/crs/bin/crs_stat -t -v
Name           Type           R/RA   F/FT   Target    State     Host
----------------------------------------------------------------------
ora.SERVER1.inst application    0/5    0/0    ONLINE    UNKNOWN   server1
ora.SERVER2.inst application    0/5    0/0    ONLINE    OFFLINE
ora.SERVER.db    application    0/0    0/1    OFFLINE   OFFLINE
ora....SM1.asm   application    0/5    0/0    ONLINE    OFFLINE
ora....C1.lsnr   application    0/5    0/0    ONLINE    OFFLINE
ora....ac1.gsd   application    0/5    0/0    ONLINE    ONLINE    server1
ora....ac1.ons   application    1/3    0/0    ONLINE    OFFLINE
ora....ac1.vip   application    0/0    0/0    ONLINE    OFFLINE
ora....SM2.asm   application    0/5    0/0    ONLINE    OFFLINE
ora....C2.lsnr   application    0/5    0/0    ONLINE    OFFLINE
ora....ac2.gsd   application    0/5    0/0    ONLINE    ONLINE    server2
ora....ac2.ons   application    0/3    0/0    ONLINE    ONLINE    server2
ora....ac2.vip   application    0/0    0/0    ONLINE    ONLINE    server1

The first thing to do is bring the VIP online on the affected host:

srvctl start nodeapps -n server1

Start the ASM instance:

srvctl start asm -n server1

Clusterware was still showing the INSTANCE on server1 as being in an UNKNOWN state. I could not start it so had to stop (even though it was not running) and then start it to make it work:

srvctl stop instance -d SERVER -i SERVER1
srvctl start instance -d SERVER -i SERVER1

Finally you need start a listener:

srvctl start listener -n SERVER1

With the latest 10.2.0.3 patchset a lot of this goes away BUT the VIP still has to be restarted with the nodeapps command above AND the listener also gets stopped so must also still be restarted. Seems like a small network blip on your public VIP interface is still going to cause your RAC cluster some pain. Makes bonding your interfaces seem even more important.

DNSSEC Signers and OpenSSL

1 Star2 Stars3 Stars4 Stars5 Stars (No Ratings Yet)
Loading ... Loading ...
Posted by jad on Feb 19th, 2007

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.

  1. Use the OpenSSL EVP API.
  2. When you need to put the public keys into the zone ask openssl for them
  3. Always use openssl to handle the keys. If you want them put in a file then tell openssl to do it.

The EVP API is a high level layer of abstraction that can be used with message digests, symmetric ciphers and public key algorithms like RSA and DSA. This is an example of some code that will use EVP to sign the message “Hello World!” with RSA SHA1 using a key with the id=63 in the SCA6000 keystore. It uses the opensc pkcs11 engine to talk to the keystore. (This code is hacked together from examples in the openssl man pages)

#include <stdio.h>
#include <stdlib.h>
#include <openssl/engine.h>
#include <openssl/conf.h>

int main(int argc, char *argv[])
{
    ENGINE *e;
    const char *engine_id = "pkcs11";
    const char *key_id = "63";
    UI_METHOD *ui_method;
    EVP_PKEY *priv_key;
    void *cb_data;
    const char *config_name = NULL;
    const EVP_MD *md_type;
    EVP_MD_CTX ctx;
    unsigned char sig[256];
    unsigned int s, i;

    if(!argv[1]) {
        printf("Usage: EVP_signer digestnamen");
        exit(1);
    }

    /* Load the config file */
    OPENSSL_config(config_name);

    /* Register engine */
    printf("Registering enginen");
    e = ENGINE_by_id(engine_id);
    if(!e) {
        /* the engine isn't available */
        printf("The engine isn't availablen");
        return;
    }
    if(!ENGINE_init(e)) {
        /* the engine couldn't initialise, release 'e' */
        printf("The engine couldn't initialisen");
        ENGINE_free(e);
        return;
    }
    if(!ENGINE_register_RSA(e)){
        /* This should only happen when 'e' can't initialise, but the previous
        * statement suggests it did. */
        printf("This should not happenn");
        abort();
    }

    /* Load private key */
    printf("Loading private keyn");
    priv_key = ENGINE_load_private_key(e, key_id, ui_method, &cb_data);

    /* Create a message to sign */
    printf("Creating messagen");
    char message[] = "Hello World!";

    /* initializes a signing context */
    printf("Init ctxn");
    OpenSSL_add_all_digests();
    md_type = EVP_get_digestbyname(argv[1]);
    if(!md_type) {
        printf("Unknown message digest %sn", argv[1]);
        exit(1);
    }
    EVP_MD_CTX_init(&ctx);
    EVP_SignInit(&ctx, md_type);

    /* Update the context with the message */
    printf("Update ctxn");
    EVP_SignUpdate(&ctx, message, strlen(message));

    /* Do the signing */
    printf("SIGN!n");
    EVP_SignFinal(&ctx, sig, &s, priv_key);

    /* Print out the sig */
    printf("Sig is: ");
    for(i = 0; i < s; i++) printf("%02x", sig[i]);
    printf("n");

    /* Cleanup */
    printf("Cleanupn");
    EVP_MD_CTX_cleanup(&ctx);
    /* Release the functional reference from ENGINE_init() */
    ENGINE_finish(e);
    /* Release the structural reference from ENGINE_by_id() */
    ENGINE_free(e);

}

Changing behaviour of home, end, page up and page down in OSX

1 Star2 Stars3 Stars4 Stars5 Stars (No Ratings Yet)
Loading ... Loading ...
Posted by jay on Feb 13th, 2007

I find the default OSX key behaviour for home, end, page up and page down a bit irritating. The default is for home and end to go respectively to the beginning and end of the document, whilst page up and page down move the screen without moving the caret. My strong preference is for the home and end to go to the beginning and end of the line and for page up and page down to move the caret as well as the document. These behaviours are actually the Windows standard.

I could probably get used to the OSX way but there are so many applications I use that do it the Windows way that I’m forever getting confused between the two methods. So all round it is easier to just switch apps that follow the OSX guidelines to do it the other way. Be warned though that some apps might still have their own way of doing this.

There is a great article on this at the TextMate Blog with lots of detail, but here is the same info in one easy step (well almost):

Create a new directory and file called ~/Library/KeyBindings/DefaultKeyBinding.dict with the following content:

{

    /* home */

    "\UF729"  = "moveToBeginningOfLine:";

    "$\UF729" = "moveToBeginningOfLineAndModifySelection:";    /* end */

    "\UF72B"  = "moveToEndOfLine:";

    "$\UF72B" = "moveToEndOfLineAndModifySelection:";

/* page up/down */

    "\UF72C"  = "pageUp:";

    "\UF72D"  = "pageDown:";

}

And then restart your OSX application and it will pick these up.

Using a SCA6000 part 2

1 Star2 Stars3 Stars4 Stars5 Stars (1 votes, average: 5 out of 5)
Loading ... Loading ...
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?

Using a SCA6000

1 Star2 Stars3 Stars4 Stars5 Stars (1 votes, average: 5 out of 5)
Loading ... Loading ...
Posted by jad on Feb 9th, 2007

I have been playing with a Sun Cryptographic Accelerator 6000. This is a PCIe card that acts an Hardware Security Module (HSM) and a crypto accelerator. Here is a quick tutorial on starting to use one.

I installed the card in a Sun T2000 server. This machine already has a crypto accelerator but hopefully we will turn that one off and just use the SCA6000 during this testing.

Once the software, drivers and patches are installed, the card can be initialized using the scamgr utility. The allows you to set up a security officer, users and keystore as well as configuring various security settings. I created a security officer called “jad” and a keystore called “Nominet”.

The SCA6000 stores the keystore on disk. This keystore is protected by a master key that is held in the SCA6000’s firmware. By default the master key can be backed up by the security officer. However the master key can be locked to prevent backups by issuing the set lock command in the scamgr utility. Once you do this the master key can not be recovered and the lock can only be removed by zeroizing the board.

The first problem that I came across was how to generate an RSA key directly in the keystore. As far as I can tell there is no utility for doing this. You are expected to write an application that does this using the libpkcs11 functions. Luckily I found some examples.

1. Slots and Tokens

A slot is the connecting point for applications that use cryptographic services. There are 4 types of slots available through the pkcs11 library.

  • Keystore slot
  • Sun Metaslot
  • Hardware slot
  • Sun Softtoken slot

In this example we will use the Sun Metaslot. See the SCA6000 user guide for an full explanation of what these slots are. The code shown here is a hacked version of the examples from Sun. Please check they really work before using them.

A token is the abstraction of a device that can perform cryptography. In addition, tokens can store information for use in cryptographic operations. A single token can support one or more mechanisms. Tokens can represent hardware, as in an accelerator board. A token can be plugged into a slot.

Configure the Sun Metaslot to use the SCA6000 keystore. (The Sun Metaslot can only access 1 keystore.)

% cryptoadm enable metaslot token=Nominet

Ensure that the keys can not be revealed on the host memory

% cryptoadm disable metaslot auto-key-migrate

You can view the metaslot like this

% cryptoadm list -v metaslot
System-wide Meta Slot Configuration:
------------------------------------
Status: enabled
Sensitive Token Object Automatic Migrate: disabled
Persistent object store token: Nominet

Detailed Meta Slot Information:
-------------------------------
actual status: enabled.
Description: Sun Metaslot
Token Present: True
Token Label: Sun Metaslot
Manufacturer ID: Sun Microsystems, Inc.
Model: 1.0
Serial Number:
Hardware Version: 0.0
Firmware Version: 0.0
UTC Time:
PIN Length: 0-253
Flags: CKF_RNG CKF_LOGIN_REQUIRED CKF_USER_PIN_INITIALIZED CKF_TOKEN_INITIALIZED CKF_SO_PIN_LOCKED

The following code will use libpkcs11 to display a list of slots

#include <stdio.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/types.h>
#include <security/cryptoki.h>
#include <security/pkcs11.h>

void
main(int argc, char **argv)
{
        CK_RV   rv;
        CK_MECHANISM genmech;
        CK_SESSION_HANDLE hSession;
        CK_SESSION_INFO sessInfo;
        CK_SLOT_ID_PTR pSlotList = NULL_PTR;
        CK_SLOT_ID SlotID;
        CK_ULONG ulSlotCount = 0;
        CK_MECHANISM_INFO mech_info;
        int i = 0;

        CK_OBJECT_HANDLE privatekey, publickey;

        /* Initialize the CRYPTOKI library */
        rv = C_Initialize(NULL_PTR);

        if (rv != CKR_OK) {
                fprintf(stderr, "C_Initialize: Error = 0x%.8Xn", rv);
                exit(1);
        }

        /* Get slot list for memory alloction */
        rv = C_GetSlotList(0, NULL_PTR, &ulSlotCount);

        if ((rv == CKR_OK) && (ulSlotCount > 0)) {
                fprintf(stdout, "slotCount = %dn", ulSlotCount);
                pSlotList = malloc(ulSlotCount * sizeof (CK_SLOT_ID));

                if (pSlotList == NULL) {
                        fprintf(stderr, "System error: unable to allocate "
                            "memoryn");
                        exit(1);
                }

                /* Get the slot list for processing */
                rv = C_GetSlotList(0, pSlotList, &ulSlotCount);
                if (rv != CKR_OK) {
                        fprintf(stderr, "GetSlotList failed: unable to get "
                            "slot count.n");
                        goto cleanup;
                }
        } else {
                fprintf(stderr, "GetSlotList failed: unable to get slot "
                    "list.n");
                exit(1);
        }

        /* Print slot info */
        for (i = 0; i < ulSlotCount; i++) {
                SlotID = pSlotList[i];
                fprintf(stdout, "Slot found: %d - ", SlotID);
                CK_SLOT_INFO Info;
                CK_TOKEN_INFO TInfo;
                rv = C_GetSlotInfo(SlotID, &Info);
                fprintf(stdout, "Slot Description: %sn", Info.slotDescription);
                fprintf(stdout, "Slot Flags: 0x%.8Xn", Info.flags);
                /* Get Token info for each slot */
                rv = C_GetTokenInfo(SlotID, &TInfo);
                fprintf(stdout, "Token Label: %sn", TInfo.label);
                fprintf(stdout, "Token Flags: 0x%.8Xn", TInfo.flags);
                fprintf(stdout, "Token manufacturerID: %sn", TInfo.manufacturerID);
                fprintf(stdout, "Token model: %sn", TInfo.model);
                fprintf(stdout, "Token serialNumber: %sn", TInfo.serialNumber);
                fprintf(stdout, "Token ulMaxSessionCount: %ldn", TInfo.ulMaxSessionCount);
                fprintf(stdout, "Token ulSessionCount: %ldn", TInfo.ulSessionCount);
                fprintf(stdout, "Token ulMaxRwSessionCount: %ldn", TInfo.ulMaxRwSessionCount);
                fprintf(stdout, "Token ulRwSessionCount: %ldn", TInfo.ulRwSessionCount);
                fprintf(stdout, "Token ulMaxPinLen: %ldn", TInfo.ulMaxPinLen);
                fprintf(stdout, "Token ulMinPinLen: %ldn", TInfo.ulMinPinLen);
                fprintf(stdout, "Token ulTotalPublicMemory: %ldn", TInfo.ulTotalPublicMemory);
                fprintf(stdout, "Token ulFreePublicMemory: %ldn", TInfo.ulFreePublicMemory);
                fprintf(stdout, "Token ulTotalPrivateMemory: %ldn", TInfo.ulTotalPrivateMemory);
                fprintf(stdout, "Token ulFreePrivateMemory: %ldn", TInfo.ulFreePrivateMemory);
                fprintf(stdout, "Token hardwareVersion: %dn", TInfo.hardwareVersion);
                fprintf(stdout, "Token firmwareVersion: %dn", TInfo.firmwareVersion);
                fprintf(stdout, "Token utcTime: %cn", TInfo.utcTime);          

                fprintf(stdout, "n");
        }

cleanup:
        if (pSlotList)
                free(pSlotList);

}

Compile like this

gcc -lpkcs11 getslot.c

and run

% ./a.out
slotCount = 3
Slot found: 0 - Slot Description: Sun Metaslot                                       Sun Microsystems, Inc.
Slot Flags: 0x00000001
Token Label: Sun Metaslot                    Sun Microsystems, Inc.          1.0
Token Flags: 0x0040040D
Token manufacturerID: Sun Microsystems, Inc.          1.0
Token model: 1.0
Token serialNumber:
Token ulMaxSessionCount: 0
Token ulSessionCount: 0
Token ulMaxRwSessionCount: 0
Token ulRwSessionCount: 0
Token ulMaxPinLen: 253
Token ulMinPinLen: 0
Token ulTotalPublicMemory: -1
Token ulFreePublicMemory: -1
Token ulTotalPrivateMemory: -1
Token ulFreePrivateMemory: -1
Token hardwareVersion: -4195448
Token firmwareVersion: -4195456
Token utcTime:  

Slot found: 1 - Slot Description: ncp/0 Crypto Accel Asym 1.0                         SUNWncp
Slot Flags: 0x00000005
Token Label: ncp/0 Crypto Accel Asym 1.0     SUNWncp                         NCP1
Token Flags: 0x00000002
Token manufacturerID: SUNWncp                         NCP1
Token model: NCP1
Token serialNumber:
Token ulMaxSessionCount: -1
Token ulSessionCount: -1
Token ulMaxRwSessionCount: -1
Token ulRwSessionCount: -1
Token ulMaxPinLen: -1
Token ulMinPinLen: -1
Token ulTotalPublicMemory: -1
Token ulFreePublicMemory: -1
Token ulTotalPrivateMemory: -1
Token ulFreePrivateMemory: -1
Token hardwareVersion: -4195448
Token firmwareVersion: -4195456
Token utcTime:  

Slot found: 2 - Slot Description: Sun Crypto Softtoken                                Sun Microsystems, Inc.
Slot Flags: 0x00000001
Token Label: Sun Software PKCS#11 softtoken  Sun Microsystems, Inc.          1.0
Token Flags: 0x0008062D
Token manufacturerID: Sun Microsystems, Inc.          1.0
Token model: 1.0
Token serialNumber:
Token ulMaxSessionCount: 0
Token ulSessionCount: 0
Token ulMaxRwSessionCount: 0
Token ulRwSessionCount: 0
Token ulMaxPinLen: 256
Token ulMinPinLen: 1
Token ulTotalPublicMemory: -1
Token ulFreePublicMemory: -1
Token ulTotalPrivateMemory: -1
Token ulFreePrivateMemory: -1
Token hardwareVersion: -4195448
Token firmwareVersion: -4195456
Token utcTime:

So we want to put our key in slot 0, the Sun Metaslot. The following code generates a 2048 bit RSA SHA1 key with a public exponent of 5 in the Metaslot.

#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 = 2048;
static CK_BYTE public_exponent[] = {5};

void
main(int argc, char **argv)
{
        CK_RV   rv;
        CK_MECHANISM genmech;
        CK_SESSION_HANDLE hSession;
        CK_SESSION_INFO sessInfo;
        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_PUBLIC_EXPONENT, &public_exponent,
                    sizeof (public_exponent)}
        };

    /* Set private key. */
        CK_ATTRIBUTE privatekey_template[] = {
                {CKA_SIGN, &truevalue, sizeof (truevalue)},
                {CKA_TOKEN, &falsevalue, sizeof (falsevalue)},
                {CKA_SENSITIVE, &truevalue, sizeof (truevalue)},
                {CKA_EXTRACTABLE, &truevalue, sizeof (truevalue)}
        };

    /* 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;

        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_SERIAL_SESSION, NULL_PTR, NULL_PTR,
            &hSession);

        if (rv != CKR_OK) {
                fprintf(stderr, "C_OpenSession: 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);

                                                                                                                                                               }

Running it gives

% ./a.out
Generating keypair....
Public Key data:
        Modulus bits: 2048
        Modulus: a961e7d4c295334bec912f4aef7d86c5519ca1983b9d8258e7b8edd500dad4a267c7fd721e30c5dff9127eb5c55a6d98270cbe754c52fa8cad6927c863ad76acd2c4bdde19d41d745b7bd707f65c0d94b4ec8000664e31529e5086676672a635ad263daeb2e471ced8869da27a387406fa4d9df0aa24743629d5fbb803a1cef4dd505375e4a50b110744268a2f8b2ea3409bccc2b117eebea6f44a0584d331a2bb0cb9744e0361657cbd024014cf23f5cb7a3fe754bb591da5110340902bdd575ae27dd805dc3ab32ad1f19d2b5acc6728b84e57e668d3acb97271ac7f65b0881cae99b2f9e140f7527db2d6ae4799d8f0833976579dcf67cb9d7a820be50209
        Public Exponent: 05

So now I think we have a key in the keystore. Next I will try to figure out how we prove that the key really is in the keystore and how to use it from openssl…

Setting jabber priority in iChat

1 Star2 Stars3 Stars4 Stars5 Stars (1 votes, average: 2 out of 5)
Loading ... Loading ...
Posted by jay on Feb 9th, 2007

Some people I know use iChat as their jabber client because it supports video over xmpp. However the client is quite rudimentary and there is no way through the interface of setting the priority, which you need if you want to use multiple clients.

However this can be done by editing the config file.

  • The file is ~/Library/Preferences/com.apple.iChat.Jabber.plist
  • Find the active account you want to set it for.
  • There is a setting called Priority and changing that seems to work fine.

Veritas Cluster Server (VCS): Adding a New Application

1 Star2 Stars3 Stars4 Stars5 Stars (1 votes, average: 5 out of 5)
Loading ... Loading ...
Posted by patrick on Feb 1st, 2007

The easisest way to add a new application into an existing Veritas Cluster Server (VCS) configuration is to edit the file /etc/VRTSvcs/conf/config/main.cf, usually by copying an existing, similar entry. However this requires shutting down the whole VCS environment, which may not always be possible.

The commands below show how to add a new application while VCS is running.

The example application to be added is called omelette. This application is to be added into a new group called omelette_group. This new group will run on the servers plate1 and plate2, with plate1 being its preferred server. omelette_group is dependent upon the existing group egg_group.

haconf –makerw

hagrp -add omelette_group
hagrp -modify omelette_group SystemList plate1 0 plate2 1
hagrp -autoenable omelette_group -sys plate1
hagrp -link omelette_group egg_group online local firm
hagrp -modify omelette_group OnlineRetryLimit 3

hares -add omelette Application omelette_group
hares -modify omelette StartProgram "/opt/scripts/omelette start"
hares -modify omelette StopProgram "/opt/scripts/omelette stop"
hares -modify omelette PidFiles "/var/run/omelette.pid"
hares -modify omelette Enabled 1

haconf -dump –makero

hagrp –online omelette_group –sys plate1

To check it has been added successfully:

cat /etc/VRTSvcs/conf/config/main.cf

hares -display omelette

Recent Posts

Highest Rated

Categories

Archives

Meta: