Ejemplo n.º 1
0
/*
 * Initialise DH for a standard group.
 */
void *dh_setup_group(const struct ssh_kex *kex)
{
    struct dh_ctx *ctx = snew(struct dh_ctx);
    ctx->p = bignum_from_bytes(kex->pdata, kex->plen);
    ctx->g = bignum_from_bytes(kex->gdata, kex->glen);
    dh_init(ctx);
    return ctx;
}
Ejemplo n.º 2
0
/*
 * Initialise DH for a standard group.
 */
void *dh_setup_group(const struct ssh_kex *kex)
{
    const struct dh_extra *extra = (const struct dh_extra *)kex->extra;
    struct dh_ctx *ctx = snew(struct dh_ctx);
    ctx->p = bignum_from_bytes(extra->pdata, extra->plen);
    ctx->g = bignum_from_bytes(extra->gdata, extra->glen);
    dh_init(ctx);
    return ctx;
}
Ejemplo n.º 3
0
int rsaencrypt(unsigned char *data, int length, struct RSAKey *key)
{
    Bignum b1, b2;
    int i;
    unsigned char *p;

    if (key->bytes < length + 4)
	return 0;		       /* RSA key too short! */

    memmove(data + key->bytes - length, data, length);
    data[0] = 0;
    data[1] = 2;

    for (i = 2; i < key->bytes - length - 1; i++) {
	do {
	    data[i] = random_byte();
	} while (data[i] == 0);
    }
    data[key->bytes - length - 1] = 0;

    b1 = bignum_from_bytes(data, key->bytes);

    b2 = modpow(b1, key->exponent, key->modulus);

    p = data;
    for (i = key->bytes; i--;) {
	*p++ = bignum_byte(b2, i);
    }

    freebn(b1);
    freebn(b2);

    return 1;
}
Ejemplo n.º 4
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;
}
Ejemplo n.º 5
0
static Bignum get160(char **data, int *datalen)
{
    Bignum b;

    b = bignum_from_bytes((unsigned char *)*data, 20);
    *data += 20;
    *datalen -= 20;

    return b;
}
Ejemplo n.º 6
0
static Bignum getmp(char **data, int *datalen)
{
    char *p;
    int length;
    Bignum b;

    getstring(data, datalen, &p, &length);
    if (!p)
	return NULL;
    b = bignum_from_bytes((unsigned char *)p, length);
    return b;
}
Ejemplo n.º 7
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;
}
Ejemplo n.º 8
0
bool RSAKey::Encrypt( CString &buf ) const
{
	Bignum bn = bignum_from_bytes( (unsigned char *) buf.data(), buf.size() );
	Bignum encrypted_bn = Encrypt( bn );
	delete [] bn;

	int len;
	unsigned char *bytes = bignum_to_buffer( encrypted_bn, &len );
	buf = CString( (const char *) bytes, len );
	delete [] encrypted_bn;

	return true;
}
Ejemplo n.º 9
0
Archivo: sshdh.c Proyecto: Riatre/PuTTY
/*
 * DH stage 1: invent a number x between 1 and q, and compute e =
 * g^x mod p. Return e.
 * 
 * If `nbits' is greater than zero, it is used as an upper limit
 * for the number of bits in x. This is safe provided that (a) you
 * use twice as many bits in x as the number of bits you expect to
 * use in your session key, and (b) the DH group is a safe prime
 * (which SSH demands that it must be).
 * 
 * P. C. van Oorschot, M. J. Wiener
 * "On Diffie-Hellman Key Agreement with Short Exponents".
 * Advances in Cryptology: Proceedings of Eurocrypt '96
 * Springer-Verlag, May 1996.
 */
Bignum dh_create_e(void *handle, int nbits)
{
    struct dh_ctx *ctx = (struct dh_ctx *)handle;
    int i;

    int nbytes;
    unsigned char *buf;

    nbytes = (bignum_bitcount(ctx->qmask) + 7) / 8;
    buf = snewn(nbytes, unsigned char);

    do {
	/*
	 * Create a potential x, by ANDing a string of random bytes
	 * with qmask.
	 */
	if (ctx->x)
	    freebn(ctx->x);
	if (nbits == 0 || nbits > bignum_bitcount(ctx->qmask)) {
	    for (i = 0; i < nbytes; i++)
		buf[i] = bignum_byte(ctx->qmask, i) & random_byte();
	    ctx->x = bignum_from_bytes(buf, nbytes);
	} else {
	    int b, nb;
	    ctx->x = bn_power_2(nbits);
	    b = nb = 0;
	    for (i = 0; i < nbits; i++) {
		if (nb == 0) {
		    nb = 8;
		    b = random_byte();
		}
		bignum_set_bit(ctx->x, i, b & 1);
		b >>= 1;
		nb--;
	    }
	}
    } while (bignum_cmp(ctx->x, One) <= 0 || bignum_cmp(ctx->x, ctx->q) >= 0);

    sfree(buf);

    /*
     * Done. Now compute e = g^x mod p.
     */
    ctx->e = modpow(ctx->g, ctx->x, ctx->p);

    return ctx->e;
}
Ejemplo n.º 10
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;
}
Ejemplo n.º 11
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;
}
Ejemplo n.º 12
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;
}
Ejemplo n.º 13
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 " ";
}
Ejemplo n.º 14
0
unsigned char *sc_get_pub(void *f, int try_write_syslog, sc_lib *sclib,
                          const char *token_label, const char *cert_label,
                          char **algorithm, int *blob_len) {
    /* return pub_key and blob_len */
    unsigned char *pub_key = NULL;

    /* some local helper: */
    int i;
    char msg[SC_STR_MAX_LEN] = "";

    /* STORE OBJECTS AND ATTRIBUTES */
    CK_SESSION_HANDLE session = 0;

    /* OPEN SESSION */    
    session = sc_get_session(f, try_write_syslog, sclib->m_fl, token_label);
    if(session == 0) {
        return NULL;
    }

    /* SEARCH THE SPECIFIED CERTIFICATE AND DETERMINE THE ID */
    {
        sc_cert_list *cl;
        sc_cert_list *pcl;
        msg[0]='\0';
        cl = sc_get_cert_list(sclib, session, msg);
        if(cl == NULL) goto err;
        if(strlen(msg) > 0) {
            logevent(f, msg);
            if(try_write_syslog) sc_write_syslog(msg);
        }
        pcl = cl;
        while(pcl != NULL) {
            int len = strlen(cert_label);
            if(pcl->cert_attr[0].ulValueLen < len) len = pcl->cert_attr[0].ulValueLen;
            if(strncmp(cert_label, pcl->cert_attr[0].pValue, len) == 0) {
                sclib->m_KeyID = calloc(sizeof(char *), pcl->cert_attr[1].ulValueLen+1);
                strncpy(sclib->m_KeyID, pcl->cert_attr[1].pValue, pcl->cert_attr[1].ulValueLen);
                char p_buf[pcl->cert_attr[0].ulValueLen+1];
                memset(p_buf, 0, pcl->cert_attr[0].ulValueLen+1);
                strncpy(p_buf, pcl->cert_attr[0].pValue, pcl->cert_attr[0].ulValueLen);
                sprintf(msg, "sc: Found cert: %s", p_buf);
                logevent(f, msg);
                if(try_write_syslog) sc_write_syslog(msg);
                sprintf(msg, "sc: Found cert: %s", sclib->m_KeyID);
                logevent(f, msg);
                if(try_write_syslog) sc_write_syslog(msg);
                break;
            }
            pcl = pcl->next;
        }
        sc_free_cert_list(cl);
    }

    /* NOW GET THE PUB KEY FOR THIS CERT */
    if(sclib->m_KeyID == NULL) {
        sprintf(msg, "sc: No cert found: %s", cert_label);
        goto err;
    }
    {
        sc_pub_list  *pl;
        sc_pub_list  *ppl;
        msg[0]='\0';
        pl = sc_get_pub_list(sclib, session, msg);
        if(pl == NULL) goto err;
        if(strlen(msg) > 0) {
            logevent(f, msg);
            if(try_write_syslog) sc_write_syslog(msg);
        }
        ppl = pl;
        while(ppl != NULL) {
            if(strncmp(sclib->m_KeyID, ppl->pub_attr[0].pValue, ppl->pub_attr[0].ulValueLen) == 0) {
                // attr 0: id
                // attr 2: modulus
                // attr 3: exponent
                unsigned char *p, *blob;
                unsigned char *expo, *modu;
                int elen, mlen;
                elen = ((8 * ppl->pub_attr[3].ulValueLen) + 8) / 8;
                mlen = ((8 * ppl->pub_attr[2].ulValueLen) + 8) / 8;

                char p_buf[ppl->pub_attr[0].ulValueLen+1];
                memset(p_buf, 0, ppl->pub_attr[0].ulValueLen+1);
                strncpy(p_buf, ppl->pub_attr[0].pValue, ppl->pub_attr[0].ulValueLen);
                sprintf(msg, "sc: Found key: %s", p_buf);
                logevent(f, msg);
                if(try_write_syslog) sc_write_syslog(msg);          

                expo = bignum_from_bytes(ppl->pub_attr[3].pValue, ppl->pub_attr[3].ulValueLen);
                modu = bignum_from_bytes(ppl->pub_attr[2].pValue, ppl->pub_attr[2].ulValueLen);
                *algorithm = calloc(sizeof(char *), strlen("ssh-rsa")+1);
                strcpy(*algorithm, "ssh-rsa");
                /* ugly (but used in pagent prototype) */
                if(sclib->rsakey != NULL) {
                    free(sclib->rsakey->exponent);
                    free(sclib->rsakey->modulus);
                    free(sclib->rsakey);
                }
                sclib->rsakey = calloc(1, sizeof(struct RSAKey));
                sclib->rsakey->exponent = expo;
                sclib->rsakey->modulus = modu;

                *blob_len = 19 + elen + mlen;
                blob = calloc(sizeof(char *), *blob_len);
                p = blob;
                SC_PUT_32BIT(p, 7);
                p += 4;
                memcpy(p, "ssh-rsa", 7);
                p += 7;
                SC_PUT_32BIT(p, elen);
                p += 4;
                for (i = elen; i--;) *p++ = bignum_byte(expo, i);
                SC_PUT_32BIT(p, mlen);
                p += 4;
                for (i = mlen; i--;)
                    *p++ = bignum_byte(modu, i);
                pub_key = blob;

                sclib->m_SshPK = calloc(sizeof(char *), *blob_len);
                memcpy(sclib->m_SshPK, blob, *blob_len);         
                sclib->m_SshPK_len = *blob_len;

                sclib->m_SshPk_alg = calloc(sizeof(char *), strlen("ssh-rsa")+1);
                strcpy(sclib->m_SshPk_alg, "ssh-rsa");

                sprintf(msg, "sc: Blob: %i (%i,%i)", *blob_len, elen, mlen);
                logevent(f, msg);
                if(try_write_syslog) sc_write_syslog(msg);

                {
                    char *buffi = sc_base64key(blob, *blob_len);
                    sprintf(msg, "sc: ssh-rsa %s token-key", buffi);
                    logevent(f, msg);
                    if(try_write_syslog) sc_write_syslog(msg);
                    free(buffi);
                }
                //used in sclib free(expo);
                //free(modu);
                break;
            }
            ppl = ppl->next;
        }
        sc_free_pub_list(pl);
    }
    if(sclib->m_SshPK == NULL) {
        sprintf(msg, "sc: No pub key found: %s", cert_label);
        goto err;
    }
    sclib->m_fl->C_CloseSession(session);
    return pub_key;
    
 err:
    logevent(f, msg);
    if(try_write_syslog) sc_write_syslog(msg);
    sclib->m_fl->C_CloseSession(session);
    return NULL;
}
Ejemplo n.º 15
0
Bignum *dss_gen_k(const char *id_string, Bignum modulus, Bignum private_key,
                  unsigned char *digest, int digest_len)
{
    /*
     * 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.
     */
    SHA512_State ss;
    unsigned char digest512[64];
    Bignum proto_k, k;

    /*
     * Hash some identifying text plus x.
     */
    SHA512_Init(&ss);
    SHA512_Bytes(&ss, id_string, strlen(id_string) + 1);
    sha512_mpint(&ss, private_key);
    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, digest_len);

    while (1) {
        SHA512_State ss2 = ss;         /* structure copy */
        SHA512_Final(&ss2, digest512);

        smemclr(&ss2, sizeof(ss2));

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

        if (bignum_cmp(k, One) != 0 && bignum_cmp(k, Zero) != 0) {
            smemclr(&ss, sizeof(ss));
            smemclr(digest512, sizeof(digest512));
            return k;
        }

        /* Very unlikely we get here, but if so, k was unsuitable. */
        freebn(k);
        /* Perturb the hash to think of a different k. */
        SHA512_Bytes(&ss, "x", 1);
        /* Go round and try again. */
    }
}