Index: src/p11_ops.c
===================================================================
--- src/p11_ops.c	(revision 108)
+++ src/p11_ops.c	(working copy)
@@ -35,7 +35,7 @@
 	CK_MECHANISM mechanism;
 	int rv, ssl = ((type == NID_md5_sha1) ? 1 : 0);
 	unsigned char *encoded = NULL;
-	int sigsize;
+	int keysize;
 	CK_ULONG ck_sigsize;
 
 	if (key == NULL)
@@ -45,17 +45,27 @@
 	slot = TOKEN2SLOT(priv->parent);
 	session = PRIVSLOT(slot)->session;
 	
-	sigsize=PKCS11_get_key_size(key);
-	ck_sigsize=sigsize;
+	keysize=PKCS11_get_key_size(key);
 
+	/* The *caller* will either *know* the signature length OR work it out
+	 * by making two calls to this api. The 1st call will compute the length,
+	 * returning it via siglen, but will fail with CKR_BUFFER_TO_SMALL. The
+	 * second call will provide the appropriate memory and its size.
+	 * clobering the contents of siglen (as previously done) is completely
+	 * the WRONG thing to do. In the case where the caller is using the api
+	 * to work out the require size, it is likely but neither certain nor
+	 * required that *siglen will equal ZERO.*/
+
+	ck_sigsize=(CK_ULONG)*siglen; /* unsigned int -> CK_ULONG coersion */
+
 	if (ssl) {
 		if((m_len != 36) /* SHA1 + MD5 */ ||
-		   ((m_len + RSA_PKCS1_PADDING_SIZE) > sigsize)) {
+		   ((m_len + RSA_PKCS1_PADDING_SIZE) > keysize)) {
 			return(0); /* the size is wrong */
 		}
 	} else {
 		ASN1_TYPE parameter = { V_ASN1_NULL, { NULL } };
- 		ASN1_STRING digest = { m_len, V_ASN1_OCTET_STRING, (unsigned char *)m };
+		ASN1_STRING digest = { m_len, V_ASN1_OCTET_STRING, (unsigned char *)m };
 		X509_ALGOR algor = { NULL, &parameter };
 		X509_SIG digest_info = { &algor, &digest };
 		int size;
@@ -65,8 +75,8 @@
 		   /* Get the size of the encoded DigestInfo */
 		   (size = i2d_X509_SIG(&digest_info, NULL)) &&
 		   /* Check that size is compatible with PKCS#11 padding */
-		   (size + RSA_PKCS1_PADDING_SIZE <= sigsize) &&
-		   (encoded = (unsigned char *) malloc(sigsize))) {
+		   (size + RSA_PKCS1_PADDING_SIZE <= keysize) &&
+		   (encoded = (unsigned char *) malloc(keysize))) {
 			unsigned char *tmp = encoded;
 			/* Actually do the encoding */
 			i2d_X509_SIG(&digest_info,&tmp);
@@ -80,16 +90,16 @@
 	memset(&mechanism, 0, sizeof(mechanism));
 	mechanism.mechanism = CKM_RSA_PKCS;
 
-	/* API is somewhat fishy here. *siglen is 0 on entry (cleared
-	 * by OpenSSL). The library assumes that the memory passed
-	 * by the caller is always big enough */
+	/* (The API is _not_ fishy here. Calling with *siglen == 0, or *any* value
+	 * smaller than that required for the result, is HOW the caller is expected
+	 * to work out the required size of the signature result buffer. */
 	if((rv = CRYPTOKI_call(ctx, C_SignInit
 			       (session, &mechanism, priv->object))) == 0) {
 		rv = CRYPTOKI_call(ctx, C_Sign
 				   (session, (CK_BYTE *) m, m_len,
 				    sigret, &ck_sigsize));
 	}
-	*siglen = ck_sigsize;
+	*siglen = (unsigned int)ck_sigsize;
 	free(encoded);
 
 	if (rv) {
