SYS_STATUS
RxHDCP_GenVR(BYTE Vr[])
{
	// extern void SHA_Simple(void *p, LONG len, BYTE *output);

    int i, n ;

    n = cDownStream*5+10 ;
    for(i = n ; i < 64 ; i++)
    {
        SHABuff[i] = 0 ;
    }
	for(i = 0 ; i < 64 ; i++)
	{
		HDMIRX_DEBUG_PRINTF2(("%02X ",(int)SHABuff[i]));
		if(0==((i+1)%8))HDMIRX_DEBUG_PRINTF2(("\n"));
	}
	HDMIRX_DEBUG_PRINTF(("n=%2X\n",(int)n));
    SHA_Simple(SHABuff, (LONG)n, Vr);
	HDMIRX_DEBUG_PRINTF2(("SHA[]: "));
	for(i = 0 ; i < 20 ; i++)
	{
		HDMIRX_DEBUG_PRINTF2(("%02X ",(int)Vr[i]));
	}
	HDMIRX_DEBUG_PRINTF2(("\n"));
    return ER_SUCCESS ;
}
Пример #2
0
void RSAKey::Sign( const CString &data, CString &out ) const
{
	Bignum in;
	{
		unsigned char hash[20];
		SHA_Simple(data.data(), data.size(), hash);

		int nbytes = (bignum_bitcount(this->modulus) - 1) / 8;
		unsigned char *bytes = new unsigned char[nbytes];

		memset( bytes, 0xFF, nbytes );
		bytes[0] = 1;
		memcpy( bytes + nbytes - 20, hash, 20 );

		in = bignum_from_bytes(bytes, nbytes);
		delete [] bytes;
	}

	Bignum outnum = rsa_privkey_op(in, this);
	delete [] in;

	int siglen;
	unsigned char *bytes = bignum_to_bytes( outnum, &siglen );
	delete [] outnum;

	out = CString( (const char *) bytes, siglen );
	delete [] bytes;
}
Пример #3
0
static unsigned char *dss_sign(void *key, char *data, int datalen, int *siglen)
{
    struct dss_key *dss = (struct dss_key *) key;
    Bignum k, gkp, hash, kinv, hxr, r, s;
    unsigned char digest[20];
    unsigned char *bytes;
    int nbytes, i;

    SHA_Simple(data, datalen, digest);

    k = dss_gen_k("DSA deterministic k generator", dss->q, dss->x,
                  digest, sizeof(digest));
    kinv = modinv(k, dss->q);	       /* k^-1 mod q */
    assert(kinv);

    /*
     * Now we have k, so just go ahead and compute the signature.
     */
    gkp = modpow(dss->g, k, dss->p);   /* g^k mod p */
    r = bigmod(gkp, dss->q);	       /* r = (g^k mod p) mod q */
    freebn(gkp);

    hash = bignum_from_bytes(digest, 20);
    hxr = bigmuladd(dss->x, r, hash);  /* hash + x*r */
    s = modmul(kinv, hxr, dss->q);     /* s = k^-1 * (hash + x*r) mod q */
    freebn(hxr);
    freebn(kinv);
    freebn(k);
    freebn(hash);

    /*
     * Signature blob is
     * 
     *   string  "ssh-dss"
     *   string  two 20-byte numbers r and s, end to end
     * 
     * i.e. 4+7 + 4+40 bytes.
     */
    nbytes = 4 + 7 + 4 + 40;
    bytes = snewn(nbytes, unsigned char);
    PUT_32BIT(bytes, 7);
    memcpy(bytes + 4, "ssh-dss", 7);
    PUT_32BIT(bytes + 4 + 7, 40);
    for (i = 0; i < 20; i++) {
	bytes[4 + 7 + 4 + i] = bignum_byte(r, 19 - i);
	bytes[4 + 7 + 4 + 20 + i] = bignum_byte(s, 19 - i);
    }
    freebn(r);
    freebn(s);

    *siglen = nbytes;
    return bytes;
}
Пример #4
0
static int rsa2_verifysig(void *key, char *sig, int siglen,
			  char *data, int datalen)
{
    struct RSAKey *rsa = (struct RSAKey *) key;
    Bignum in, out;
    char *p;
    int slen;
    int bytes, i, j, ret;
    unsigned char hash[20];

    getstring(&sig, &siglen, &p, &slen);
    if (!p || slen != 7 || memcmp(p, "ssh-rsa", 7)) {
	return 0;
    }
    in = getmp(&sig, &siglen);
    out = modpow(in, rsa->exponent, rsa->modulus);
    freebn(in);

    ret = 1;

    bytes = (bignum_bitcount(rsa->modulus)+7) / 8;
    /* Top (partial) byte should be zero. */
    if (bignum_byte(out, bytes - 1) != 0)
	ret = 0;
    /* First whole byte should be 1. */
    if (bignum_byte(out, bytes - 2) != 1)
	ret = 0;
    /* Most of the rest should be FF. */
    for (i = bytes - 3; i >= 20 + ASN1_LEN; i--) {
	if (bignum_byte(out, i) != 0xFF)
	    ret = 0;
    }
    /* Then we expect to see the asn1_weird_stuff. */
    for (i = 20 + ASN1_LEN - 1, j = 0; i >= 20; i--, j++) {
	if (bignum_byte(out, i) != asn1_weird_stuff[j])
	    ret = 0;
    }
    /* Finally, we expect to see the SHA-1 hash of the signed data. */
    SHA_Simple(data, datalen, hash);
    for (i = 19, j = 0; i >= 0; i--, j++) {
	if (bignum_byte(out, i) != hash[j])
	    ret = 0;
    }
    freebn(out);

    return ret;
}
Пример #5
0
static unsigned char *rsa2_sign(void *key, char *data, int datalen,
				int *siglen)
{
    struct RSAKey *rsa = (struct RSAKey *) key;
    unsigned char *bytes;
    int nbytes;
    unsigned char hash[20];
    Bignum in, out;
    int i, j;

    SHA_Simple(data, datalen, hash);

    nbytes = (bignum_bitcount(rsa->modulus) - 1) / 8;
    assert(1 <= nbytes - 20 - ASN1_LEN);
    bytes = snewn(nbytes, unsigned char);

    bytes[0] = 1;
    for (i = 1; i < nbytes - 20 - ASN1_LEN; i++)
	bytes[i] = 0xFF;
    for (i = nbytes - 20 - ASN1_LEN, j = 0; i < nbytes - 20; i++, j++)
	bytes[i] = asn1_weird_stuff[j];
    for (i = nbytes - 20, j = 0; i < nbytes; i++, j++)
	bytes[i] = hash[j];

    in = bignum_from_bytes(bytes, nbytes);
    sfree(bytes);

    out = rsa_privkey_op(in, rsa);
    freebn(in);

    nbytes = (bignum_bitcount(out) + 7) / 8;
    bytes = snewn(4 + 7 + 4 + nbytes, unsigned char);
    PUT_32BIT(bytes, 7);
    memcpy(bytes + 4, "ssh-rsa", 7);
    PUT_32BIT(bytes + 4 + 7, nbytes);
    for (i = 0; i < nbytes; i++)
	bytes[4 + 7 + 4 + i] = bignum_byte(out, nbytes - 1 - i);
    freebn(out);

    *siglen = 4 + 7 + 4 + nbytes;
    return bytes;
}
Пример #6
0
bool RSAKey::Verify( const CString &data, const CString &sig ) const
{
	Bignum in, out;
	int bytes, i, j;
	unsigned char hash[20];

	in = bignum_from_bytes( (const unsigned char *) sig.data(), sig.size() );

	/* Base (in) must be smaller than the modulus. */
	if( bignum_cmp(in, this->modulus) >= 0 )
	{
		freebn(in);
		return false;
	}
	out = modpow(in, this->exponent, this->modulus);
	freebn(in);

	bool ret = true;

	bytes = (bignum_bitcount(this->modulus)+7) / 8;
	/* Top (partial) byte should be zero. */
	if (bignum_byte(out, bytes - 1) != 0)
		ret = 0;
	/* First whole byte should be 1. */
	if (bignum_byte(out, bytes - 2) != 1)
		ret = 0;
	/* Most of the rest should be FF. */
	for (i = bytes - 3; i >= 20; i--) {
		if (bignum_byte(out, i) != 0xFF)
			ret = 0;
	}
	/* Finally, we expect to see the SHA-1 hash of the signed data. */
	SHA_Simple( data.data(), data.size(), hash );
	for (i = 19, j = 0; i >= 0; i--, j++) {
		if (bignum_byte(out, i) != hash[j])
			ret = false;
	}
	freebn(out);

	return ret;
}
Пример #7
0
static unsigned char *dss_sign(void *key, char *data, int datalen, int *siglen)
{
    /*
     * The basic DSS signing algorithm is:
     * 
     *  - invent a random k between 1 and q-1 (exclusive).
     *  - Compute r = (g^k mod p) mod q.
     *  - Compute s = k^-1 * (hash + x*r) mod q.
     * 
     * This has the dangerous properties that:
     * 
     *  - if an attacker in possession of the public key _and_ the
     *    signature (for example, the host you just authenticated
     *    to) can guess your k, he can reverse the computation of s
     *    and work out x = r^-1 * (s*k - hash) mod q. That is, he
     *    can deduce the private half of your key, and masquerade
     *    as you for as long as the key is still valid.
     * 
     *  - since r is a function purely of k and the public key, if
     *    the attacker only has a _range of possibilities_ for k
     *    it's easy for him to work through them all and check each
     *    one against r; he'll never be unsure of whether he's got
     *    the right one.
     * 
     *  - if you ever sign two different hashes with the same k, it
     *    will be immediately obvious because the two signatures
     *    will have the same r, and moreover an attacker in
     *    possession of both signatures (and the public key of
     *    course) can compute k = (hash1-hash2) * (s1-s2)^-1 mod q,
     *    and from there deduce x as before.
     * 
     *  - the Bleichenbacher attack on DSA makes use of methods of
     *    generating k which are significantly non-uniformly
     *    distributed; in particular, generating a 160-bit random
     *    number and reducing it mod q is right out.
     * 
     * For this reason we must be pretty careful about how we
     * generate our k. Since this code runs on Windows, with no
     * particularly good system entropy sources, we can't trust our
     * RNG itself to produce properly unpredictable data. Hence, we
     * use a totally different scheme instead.
     * 
     * What we do is to take a SHA-512 (_big_) hash of the private
     * key x, and then feed this into another SHA-512 hash that
     * also includes the message hash being signed. That is:
     * 
     *   proto_k = SHA512 ( SHA512(x) || SHA160(message) )
     * 
     * This number is 512 bits long, so reducing it mod q won't be
     * noticeably non-uniform. So
     * 
     *   k = proto_k mod q
     * 
     * This has the interesting property that it's _deterministic_:
     * signing the same hash twice with the same key yields the
     * same signature.
     * 
     * Despite this determinism, it's still not predictable to an
     * attacker, because in order to repeat the SHA-512
     * construction that created it, the attacker would have to
     * know the private key value x - and by assumption he doesn't,
     * because if he knew that he wouldn't be attacking k!
     *
     * (This trick doesn't, _per se_, protect against reuse of k.
     * Reuse of k is left to chance; all it does is prevent
     * _excessively high_ chances of reuse of k due to entropy
     * problems.)
     * 
     * Thanks to Colin Plumb for the general idea of using x to
     * ensure k is hard to guess, and to the Cambridge University
     * Computer Security Group for helping to argue out all the
     * fine details.
     */
    struct dss_key *dss = (struct dss_key *) key;
    SHA512_State ss;
    unsigned char digest[20], digest512[64];
    Bignum proto_k, k, gkp, hash, kinv, hxr, r, s;
    unsigned char *bytes;
    int nbytes, i;

    SHA_Simple(data, datalen, digest);

    /*
     * Hash some identifying text plus x.
     */
    SHA512_Init(&ss);
    SHA512_Bytes(&ss, "DSA deterministic k generator", 30);
    sha512_mpint(&ss, dss->x);
    SHA512_Final(&ss, digest512);

    /*
     * Now hash that digest plus the message hash.
     */
    SHA512_Init(&ss);
    SHA512_Bytes(&ss, digest512, sizeof(digest512));
    SHA512_Bytes(&ss, digest, sizeof(digest));
    SHA512_Final(&ss, digest512);

    memset(&ss, 0, sizeof(ss));

    /*
     * Now convert the result into a bignum, and reduce it mod q.
     */
    proto_k = bignum_from_bytes(digest512, 64);
    k = bigmod(proto_k, dss->q);
    freebn(proto_k);

    memset(digest512, 0, sizeof(digest512));

    /*
     * Now we have k, so just go ahead and compute the signature.
     */
    gkp = modpow(dss->g, k, dss->p);   /* g^k mod p */
    r = bigmod(gkp, dss->q);	       /* r = (g^k mod p) mod q */
    freebn(gkp);

    hash = bignum_from_bytes(digest, 20);
    kinv = modinv(k, dss->q);	       /* k^-1 mod q */
    hxr = bigmuladd(dss->x, r, hash);  /* hash + x*r */
    s = modmul(kinv, hxr, dss->q);     /* s = k^-1 * (hash + x*r) mod q */
    freebn(hxr);
    freebn(kinv);
    freebn(hash);

    /*
     * Signature blob is
     * 
     *   string  "ssh-dss"
     *   string  two 20-byte numbers r and s, end to end
     * 
     * i.e. 4+7 + 4+40 bytes.
     */
    nbytes = 4 + 7 + 4 + 40;
    bytes = snewn(nbytes, unsigned char);
    PUT_32BIT(bytes, 7);
    memcpy(bytes + 4, "ssh-dss", 7);
    PUT_32BIT(bytes + 4 + 7, 40);
    for (i = 0; i < 20; i++) {
	bytes[4 + 7 + 4 + i] = bignum_byte(r, 19 - i);
	bytes[4 + 7 + 4 + 20 + i] = bignum_byte(s, 19 - i);
    }
    freebn(r);
    freebn(s);

    *siglen = nbytes;
    return bytes;
}
Пример #8
0
static int dss_verifysig(void *key, char *sig, int siglen,
			 char *data, int datalen)
{
    struct dss_key *dss = (struct dss_key *) key;
    char *p;
    int slen;
    char hash[20];
    Bignum r, s, w, gu1p, yu2p, gu1yu2p, u1, u2, sha, v;
    int ret;

    if (!dss->p)
	return 0;

#ifdef DEBUG_DSS
    {
	int i;
	printf("sig:");
	for (i = 0; i < siglen; i++)
	    printf("  %02x", (unsigned char) (sig[i]));
	printf("\n");
    }
#endif
    /*
     * Commercial SSH (2.0.13) and OpenSSH disagree over the format
     * of a DSA signature. OpenSSH is in line with the IETF drafts:
     * it uses a string "ssh-dss", followed by a 40-byte string
     * containing two 160-bit integers end-to-end. Commercial SSH
     * can't be bothered with the header bit, and considers a DSA
     * signature blob to be _just_ the 40-byte string containing
     * the two 160-bit integers. We tell them apart by measuring
     * the length: length 40 means the commercial-SSH bug, anything
     * else is assumed to be IETF-compliant.
     */
    if (siglen != 40) {		       /* bug not present; read admin fields */
	getstring(&sig, &siglen, &p, &slen);
	if (!p || slen != 7 || memcmp(p, "ssh-dss", 7)) {
	    return 0;
	}
	sig += 4, siglen -= 4;	       /* skip yet another length field */
    }
    r = get160(&sig, &siglen);
    s = get160(&sig, &siglen);
    if (!r || !s)
	return 0;

    /*
     * Step 1. w <- s^-1 mod q.
     */
    w = modinv(s, dss->q);

    /*
     * Step 2. u1 <- SHA(message) * w mod q.
     */
    SHA_Simple(data, datalen, (unsigned char *)hash);
    p = hash;
    slen = 20;
    sha = get160(&p, &slen);
    u1 = modmul(sha, w, dss->q);

    /*
     * Step 3. u2 <- r * w mod q.
     */
    u2 = modmul(r, w, dss->q);

    /*
     * Step 4. v <- (g^u1 * y^u2 mod p) mod q.
     */
    gu1p = modpow(dss->g, u1, dss->p);
    yu2p = modpow(dss->y, u2, dss->p);
    gu1yu2p = modmul(gu1p, yu2p, dss->p);
    v = modmul(gu1yu2p, One, dss->q);

    /*
     * Step 5. v should now be equal to r.
     */

    ret = !bignum_cmp(v, r);

    freebn(w);
    freebn(sha);
    freebn(gu1p);
    freebn(yu2p);
    freebn(gu1yu2p);
    freebn(v);
    freebn(r);
    freebn(s);

    return ret;
}
Пример #9
0
static int LAME_ssh2_load_userkey(char *passphrase)
{
	int passlen = strlen(passphrase);
	unsigned char out[sizeof(cur_salt->private_blob)];
	AES_KEY akey;
	unsigned char iv[32];

	/* Decrypt the private blob. */
	if (cur_salt->cipher) {
		unsigned char key[40];
		SHA_CTX s;
		if (cur_salt->private_blob_len % cur_salt->cipherblk)
			goto error;

		SHA1_Init(&s);
		SHA1_Update(&s, (void*)"\0\0\0\0", 4);
		SHA1_Update(&s, passphrase, passlen);
		SHA1_Final(key + 0, &s);
		SHA1_Init(&s);
		SHA1_Update(&s, (void*)"\0\0\0\1", 4);
		SHA1_Update(&s, passphrase, passlen);
		SHA1_Final(key + 20, &s);
		memset(iv, 0, 32);
		memset(&akey, 0, sizeof(AES_KEY));
		if(AES_set_decrypt_key(key, 256, &akey) < 0) {
			fprintf(stderr, "AES_set_decrypt_key failed!\n");
		}
		AES_cbc_encrypt(cur_salt->private_blob, out , cur_salt->private_blob_len, &akey, iv, AES_DECRYPT);
	}
	/* Verify the MAC. */
	{
		char realmac[41];
		unsigned char binary[20];
		unsigned char *macdata;
		unsigned char macdata_ar[4*5+sizeof(cur_salt->alg)+sizeof(cur_salt->encryption)+sizeof(cur_salt->comment)+sizeof(cur_salt->public_blob_len)+sizeof(cur_salt->private_blob_len)+1];
		int maclen;
		int i;
		if (cur_salt->old_fmt) {
			/* MAC (or hash) only covers the private blob. */
			macdata = out;
			maclen = cur_salt->private_blob_len;
		} else {
			unsigned char *p;
			int namelen = strlen(cur_salt->alg);
			int enclen = strlen(cur_salt->encryption);
			int commlen = strlen(cur_salt->comment);
			maclen = (4 + namelen +
					4 + enclen +
					4 + commlen +
					4 + cur_salt->public_blob_len +
					4 + cur_salt->private_blob_len);
			p = macdata_ar;
#define DO_STR(s,len) PUT_32BIT(p,(len));memcpy(p+4,(s),(len));p+=4+(len)
			DO_STR(cur_salt->alg, namelen);
			DO_STR(cur_salt->encryption, enclen);
			DO_STR(cur_salt->comment, commlen);
			DO_STR(cur_salt->public_blob, cur_salt->public_blob_len);
			DO_STR(out, cur_salt->private_blob_len);
			macdata = macdata_ar;
		}
		if (cur_salt->is_mac) {
			SHA_CTX s;
			unsigned char mackey[20];
			unsigned int length = 20;
			// HMAC_CTX ctx;
			char header[] = "putty-private-key-file-mac-key";
			SHA1_Init(&s);
			SHA1_Update(&s, header, sizeof(header)-1);
			if (cur_salt->cipher && passphrase)
				SHA_Update(&s, passphrase, passlen);
			SHA1_Final(mackey, &s);
			hmac_sha1(mackey, 20, macdata, maclen, binary, length);
			/* HMAC_Init(&ctx, mackey, 20, EVP_sha1());
			 * HMAC_Update(&ctx, macdata, maclen);
			 * HMAC_Final(&ctx, binary, &length);
			 * HMAC_CTX_cleanup(&ctx); */
		} else {
			SHA_Simple(macdata, maclen, binary);
		}
		for (i = 0; i < 20; i++)
			sprintf(realmac + 2 * i, "%02x", binary[i]);

		if (strcmp(cur_salt->mac, realmac) == 0)
			return 1;
	}

error:
	return 0;
}
Пример #10
0
unsigned char *sc_sig(void *f, int try_write_syslog, sc_lib *sclib,
                      const char *token_label, const char *password_s,
                      char *sigdata, int sigdata_len, int *sigblob_len) {
    CK_RV rv  = 0; 
    char msg[SC_STR_MAX_LEN] = "";
    CK_SESSION_HANDLE session = 0;
    const char *pwd = password_s;
    /* TEMPLATES: */
    CK_BBOOL  bTrue = 1;
    CK_OBJECT_CLASS  class_private_key = CKO_PRIVATE_KEY;
    CK_KEY_TYPE      key_type  = CKK_RSA;
    CK_ATTRIBUTE key_template[] = {
        { CKA_CLASS,    &class_private_key,  sizeof (class_private_key) },
        { CKA_KEY_TYPE, &key_type,           sizeof (key_type) },
        { CKA_TOKEN,    &bTrue,              sizeof (bTrue) },
        { CKA_SIGN,     &bTrue,              sizeof (bTrue) },
        { CKA_PRIVATE,  &bTrue,              sizeof (bTrue) }
    };
    CK_ATTRIBUTE key_getattributes[] = { 
        {CKA_ID, NULL_PTR, 0},             /* ID to search the key */
        {CKA_MODULUS, NULL_PTR, 0}
    };
    /* STORE OBJECTS AND ATTRIBUTES */
    int max_o = 20;
    CK_OBJECT_HANDLE list[max_o];
    CK_ULONG found = 0;
    CK_OBJECT_HANDLE pO;
    int ii,j;

    unsigned char *ret = NULL;
    *sigblob_len = 0;

    session = sc_get_session(f, try_write_syslog, sclib->m_fl, token_label);
    if(session == 0) {
        return NULL;
    }
  
    rv = sclib->m_fl->C_Login(session, CKU_USER, (CK_CHAR_PTR)pwd, strlen(pwd));
    if (CKR_OK != rv) {
        logevent(f, "sc: Login failed");
        sclib->m_fl->C_CloseSession(session);
        return NULL;
    }
    rv = sclib->m_fl->C_FindObjectsInit(session, key_template, 4);
    if (CKR_OK != rv) {
        sprintf(msg, "sc: C_FindObjectsInit priv key failed, 0x%.4x", (int)rv);
        goto err;
    }
    rv = sclib->m_fl->C_FindObjects(session, list, max_o-1, &found);
    if (CKR_OK != rv) {
        sprintf(msg, "sc: C_FindObjects priv key failed, 0x%.4x", (int)rv);
        goto err;
    } 
    rv = sclib->m_fl->C_FindObjectsFinal(session);
    if (CKR_OK != rv) {
        sprintf(msg, "sc: C_FindObjectsFinal priv key failed, 0x%.4x", (int)rv);
        goto err;
    }
    if (found < 1) {
        sprintf(msg, "sc: No priv keys found");
        goto err;
    }
    for(ii=0; ii<found; ii++) {
        pO = list[ii];
        int ts = 1;//sizeof (key_getattributes) / sizeof (CK_ATTRIBUTE);
        int nr;
        sc_write_syslog("1");
        for(nr=0;nr<ts;nr++) {
            key_getattributes[nr].ulValueLen = 0;
            key_getattributes[nr].pValue = NULL;
        }
        rv = sclib->m_fl->C_GetAttributeValue(session, pO, key_getattributes, ts);
        if(CKR_OK == rv) {
            for(nr=0;nr<ts;nr++) {
                key_getattributes[nr].pValue = calloc(sizeof(char *),key_getattributes[nr].ulValueLen+1);
            }
            if(sclib->m_fl->C_GetAttributeValue(session, pO, key_getattributes, ts) == CKR_OK) {
                if(strncmp(key_getattributes[0].pValue, sclib->m_KeyID, key_getattributes[0].ulValueLen) == 0) {
                    CK_BYTE signature[500];    
                    CK_ULONG signature_length = 500;
                    CK_MECHANISM mechanism = { CKM_RSA_PKCS, NULL_PTR, 0 };
                    unsigned char *bytes;
                    Bignum out;
                    int nbytes;
                    int r;
                    unsigned char hash_sha[20];
                    
                    char p_buf[key_getattributes[0].ulValueLen+1];
                    memset(p_buf, 0, key_getattributes[0].ulValueLen+1);
                    strncpy(p_buf, key_getattributes[0].pValue, key_getattributes[0].ulValueLen);
                    sprintf(msg, "sc: Found pkey: %s", p_buf);
                    logevent(f, msg);
                    if(try_write_syslog) sc_write_syslog(msg);
                    
                    rv = sclib->m_fl->C_SignInit(session, &mechanism, pO);
                    if (CKR_OK != rv) {
                        free(key_getattributes[0].pValue);
                        free(key_getattributes[1].pValue);
                        sprintf(msg, "sc: SignInit failed, 0x%.4x", (int)rv);
                        goto err;
                    }

                    /* rsa2_sign() */
                    SHA_Simple(sigdata, sigdata_len, hash_sha);
                    //        MD5Simple(sigdata, sigdata_len, hash_md5);
                    {
                        int message_len = sizeof(id_sha1) + sizeof(hash_sha);
                        CK_BYTE message[message_len];
                        for(j=0;j<sizeof(id_sha1);j++) message[j] = id_sha1[j]; 
                        memcpy((char *) &message[sizeof(id_sha1)], hash_sha, sizeof(hash_sha));
                        
                        rv = sclib->m_fl->C_Sign(session, message, message_len, signature, &signature_length);
                        if (CKR_OK != rv) {
                            free(key_getattributes[0].pValue); 
                            free(key_getattributes[1].pValue); 
                            sprintf(msg, "sc: Sign failed, 0x%.4x", (int)rv);
                            goto err;
                        }
                    }

                    out = bignum_from_bytes(signature, signature_length);
                    nbytes = (bignum_bitcount(out) + 7) / 8;
                    *sigblob_len = 4 + 7 + 4 + nbytes;
                    bytes = calloc(sizeof(char *), *sigblob_len);
                    SC_PUT_32BIT(bytes, 7);
                    memcpy(bytes + 4, "ssh-rsa", 7);
                    SC_PUT_32BIT(bytes + 4 + 7, nbytes);
                    for (r = 0; r < nbytes; r++)
                        bytes[4 + 7 + 4 + r] = bignum_byte(out, nbytes - 1 - r);
                    ret = bytes;
                    
                    free(out);
                    free(key_getattributes[0].pValue); 
                    free(key_getattributes[1].pValue); 
                    break;
                }
            } else {
                logevent(f, "sc: GetAttributeValue failed, no data loaded");
            }
            free(key_getattributes[0].pValue); 
            free(key_getattributes[1].pValue); 
        } else {
            sprintf(msg, "sc: GetAttributeValue failed (pkey), 0x%.4x", (int)rv);
            logevent(f, msg);
            if(try_write_syslog) sc_write_syslog(msg);
        }
    }

    sclib->m_fl->C_Logout(session);
    sclib->m_fl->C_CloseSession(session);
    return ret;

 err:
    logevent(f, msg);
    if(try_write_syslog) sc_write_syslog(msg);
    sclib->m_fl->C_Logout(session);
    sclib->m_fl->C_CloseSession(session);
    if(ret != NULL) free(ret);
    /* just return an invalid signature ... */
    *sigblob_len = 1;
    return " ";
}