Ejemplo n.º 1
0
/*----------------------------------------------------------------------------*/
static zrtp_status_t zrtp_dh_init(void *s)
{
	struct BigNum* p = NULL;
	struct BigNum* p_1 = NULL;
	uint8_t* p_data = NULL;
	unsigned int p_data_length = 0;
	zrtp_pk_scheme_t *self = (zrtp_pk_scheme_t *) s;
	
	switch (self->base.id) {
		case ZRTP_PKTYPE_DH2048:
			p = &self->base.zrtp->P_2048;
			p_1 = &self->base.zrtp->P_2048_1;
			p_data = self->base.zrtp->P_2048_data;
			p_data_length = sizeof(self->base.zrtp->P_2048_data);
			break;
		case ZRTP_PKTYPE_DH3072:
			p = &self->base.zrtp->P_3072;
			p_1 = &self->base.zrtp->P_3072_1;
			p_data = self->base.zrtp->P_3072_data;
			p_data_length = sizeof(self->base.zrtp->P_3072_data);
			break;
		default:
			return zrtp_status_bad_param;
	}
	
    bnBegin(p);
    bnInsertBigBytes(p, (const unsigned char *)p_data, 0, p_data_length);
		
    bnBegin(p_1);
    bnCopy(p_1, p);
    bnSub(p_1, &self->base.zrtp->one);
    
    return zrtp_status_ok;
}
Ejemplo n.º 2
0
int rsa_ENCRYPTPRIVATE(RSA_CTX *ctx,unsigned char *data,unsigned long 
int *datLen){
int t;
struct BigNum enc,m;
/* encrypt (sign) data with private key */
/* datLen must be == to bitsize/8 */
if(*datLen!=ctx->bits/8)
	return BADDATALEN;
bnBegin(&enc);
bnBegin(&m);
t=bnInsertLittleBytes(&m,(void*)data,0,ctx->bits/8);
if(t<0){
	bnEnd(&enc);
	bnEnd(&m);
	return BADTHINGS;
}
t=bnExpMod(&enc,&m,&ctx->d,&ctx->n);
if(t<0){
	bnEnd(&enc);
	bnEnd(&m);
	return BADMOD;
}
bnExtractLittleBytes(&enc,(void*)data,0,ctx->bits/8);
bnEnd(&enc);
bnEnd(&m);
return OK;
}
Ejemplo n.º 3
0
int rsa_ENCRYPTPUBLIC(RSA_CTX *ctx,unsigned char *data,unsigned long int 
*datLen){
int t;
struct BigNum enc,m;
/* encrypt data using public key */
/* datLen must be == to bitsize/8 */
if(*datLen!=ctx->bits/8)
	return BADDATALEN;
bnBegin(&enc);
bnBegin(&m);
t=bnInsertLittleBytes(&m,(void*)data,0,ctx->bits/8);
if(t<0){
	bnEnd(&enc);
	bnEnd(&m);
	return BADTHINGS;
}
t=bnExpMod(&enc,&m,&ctx->e,&ctx->n);
if(t<0){
	bnEnd(&enc);
	bnEnd(&m);
	return BADTHINGS;
}
bnExtractLittleBytes(&enc,(void*)data,0,(ctx->bits/8));
bnEnd(&enc);
bnEnd(&m);
return OK;
}
Ejemplo n.º 4
0
int rsa_DECRYPTPUBLIC(RSA_CTX *ctx,unsigned char *data,unsigned long 
int *datLen){
int t;
struct BigNum enc,m;
/* decrypt (verify) data encrypted with private key (verfied by public key) */
/* datLen must be == to bitsize/8 */
if(*datLen!=ctx->bits/8)
	return BADDATALEN;
bnBegin(&enc);
bnBegin(&m);
t=bnInsertLittleBytes(&m,(void*)data,0,ctx->bits/8);
if(t<0){
	bnEnd(&enc);
	bnEnd(&m);
	return BADTHINGS;
}
t=bnExpMod(&enc,&m,&ctx->e,&ctx->n);
if(t<0){
	bnEnd(&enc);
	bnEnd(&m);
	return BADMOD;
}
bnExtractLittleBytes(&enc,(void*)data,0,ctx->bits/8);
bnEnd(&enc);
bnEnd(&m);
return OK;
}
Ejemplo n.º 5
0
static zrtp_status_t zrtp_dh_initialize( zrtp_pk_scheme_t *self,
										 zrtp_dh_crypto_context_t *dh_cc)
{
	unsigned char* buffer = zrtp_sys_alloc(sizeof(zrtp_uchar128_t));
	struct BigNum* p = _zrtp_get_p(self);
	zrtp_time_t start_ts = zrtp_time_now();
	
	ZRTP_LOG(1,(_ZTU_,"\tDH TEST: %.4s zrtp_dh_initialize() START. now=%llums.\n", self->base.type, start_ts));
	
	if (!buffer) {
		return zrtp_status_alloc_fail;
	}
	if (!p) {
		zrtp_sys_free(buffer);
		return zrtp_status_bad_param;
	}
	
	if (64 != zrtp_randstr(self->base.zrtp, buffer, 64)) {
		zrtp_sys_free(buffer);
		return zrtp_status_rng_fail;
	}

	bnBegin(&dh_cc->sv);
	bnInsertBigBytes(&dh_cc->sv, (const unsigned char *)buffer, 0, self->sv_length);
	bnBegin(&dh_cc->pv);
	bnExpMod(&dh_cc->pv, &self->base.zrtp->G, &dh_cc->sv, p);
	
	zrtp_sys_free(buffer);
	
	ZRTP_LOG(1,(_ZTU_,"\tDH TEST: zrtp_dh_initialize() for %.4s was executed ts=%llums d=%llums.\n", self->base.type, zrtp_time_now(), zrtp_time_now()-start_ts));
	return zrtp_status_ok;
}
Ejemplo n.º 6
0
void
pubKeyBegin(struct PubKey *pub)
{
	if (pub) {
		bnBegin(&pub->n);
		bnBegin(&pub->e);
	}
}
Ejemplo n.º 7
0
void
secKeyBegin(struct SecKey *sec)
{
	if (sec) {
		bnBegin(&sec->d);
		bnBegin(&sec->p);
		bnBegin(&sec->q);
		bnBegin(&sec->u);
	}
}
Ejemplo n.º 8
0
/*----------------------------------------------------------------------------*/
zrtp_status_t zrtp_prepare_pkt(zrtp_global_t* zrtp)
{
    bnInit();
    bnBegin(&zrtp->one);
    bnSetQ(&zrtp->one, 1);
    bnBegin(&zrtp->G);
    bnSetQ(&zrtp->G, 2);

    return zrtp_status_ok;
}
Ejemplo n.º 9
0
/*----------------------------------------------------------------------------*/
static zrtp_status_t zrtp_dh_self_test(zrtp_pk_scheme_t *self)
{
	zrtp_status_t s = zrtp_status_ok;
	zrtp_dh_crypto_context_t alice_cc;
	zrtp_dh_crypto_context_t bob_cc;
	struct BigNum alice_k;
	struct BigNum bob_k;
	zrtp_time_t start_ts = zrtp_time_now();
	
	ZRTP_LOG(3, (_ZTU_, "PKS %.4s testing... ", self->base.type));
	
	bnBegin(&alice_k);
	bnBegin(&bob_k);
	
	do {	
		/* Both sides initalise DH schemes and compute secret and public values. */
		s = self->initialize(self, &alice_cc);
		if (zrtp_status_ok != s) {
			break;
		}
		s = self->initialize(self, &bob_cc);
		if (zrtp_status_ok != s) {
			break;
		}
		
		/* Both sides validate public values. (to provide exact performance estimation) */
		s = self->validate(self, &bob_cc.pv);
		if (zrtp_status_ok != s) {
			break;
		}
		s = self->validate(self, &alice_cc.pv);
		if (zrtp_status_ok != s) {
			break;
		}
		
		/* Compute secret keys and compare them. */
		s = self->compute(self, &alice_cc, &alice_k, &bob_cc.pv);
		if (zrtp_status_ok != s) {
			break;
		}
		s= self->compute(self, &bob_cc, &bob_k, &alice_cc.pv);
		if (zrtp_status_ok != s) {
			break;
		}
				
		s = (0 == bnCmp(&alice_k, &bob_k)) ? zrtp_status_ok : zrtp_status_algo_fail;
	} while (0);

	bnEnd(&alice_k);
	bnEnd(&bob_k);
		
	ZRTP_LOGC(3, ("%s (%llu ms)\n", zrtp_log_status2str(s), (zrtp_time_now()-start_ts)/2));
	
	return s;
}
Ejemplo n.º 10
0
/*
 * Generate a PGPPubKey from a PGPSecKey
 */
static PGPPubKey *
dsaPubkey(PGPSecKey const *seckey)
{
	DSAsecPlus const *sec = (DSAsecPlus *)seckey->priv;
	PGPPubKey *pubkey;
	DSApub *pub;
	PGPContextRef		context;
	PGPMemoryMgrRef		mgr	= NULL;

	pgpAssertAddrValid( seckey, PGPSecKey );
	context	= seckey->context;
	mgr	= PGPGetContextMemoryMgr( context );

	ASSERTDSA(seckey->pkAlg);
	pub = (DSApub *)pgpContextMemAlloc( context,
		sizeof(*pub), kPGPMemoryMgrFlags_Clear);
	if (pub) {
		pubkey = (PGPPubKey *)pgpContextMemAlloc( context,
			sizeof(*pubkey), kPGPMemoryMgrFlags_Clear);
		if (pubkey) {
			pubkey->context	= context;
			
			bnBegin(&pub->p, mgr, FALSE );
			bnBegin(&pub->q, mgr, FALSE );
			bnBegin(&pub->g, mgr, FALSE );
			bnBegin(&pub->y, mgr, FALSE );
			if (bnCopy(&pub->p, &sec->s.p) >= 0
			    && bnCopy(&pub->q, &sec->s.q) >= 0
			    && bnCopy(&pub->g, &sec->s.g) >= 0
			    && bnCopy(&pub->y, &sec->s.y) >= 0)
			{
				dsaFillPubkey(pubkey, pub);
				pubkey->pkAlg = seckey->pkAlg;
				memcpy(pubkey->keyID, seckey->keyID,
				       sizeof(pubkey->keyID));
				return pubkey;
			}
			/* Failed = clean up and return NULL */
			bnEnd(&pub->p);
			bnEnd(&pub->q);
			bnEnd(&pub->g);
			bnEnd(&pub->y);
			pgpContextMemFree( context, pubkey);
		}
		pgpContextMemFree( context, pub);
	}
	return NULL;
}
Ejemplo n.º 11
0
/* Creates a new bignum */
	PGPError
PGPNewBigNum(
	PGPMemoryMgrRef	mgr,
	PGPBoolean		secure,
	PGPBigNumRef *	newBN )
{
	PGPError		err	= kPGPError_NoErr;
	PGPBigNumRef	ref;
	
	PGPValidatePtr( newBN );
	*newBN	= kPGPInvalidBigNumRef;
	
	ref	= (PGPBigNumRef) PGPNewData( mgr,
			sizeof( **newBN ), kPGPMemoryMgrFlags_Clear);
	if ( IsntNull( ref ) )
	{
		bnBegin( &ref->bn, mgr, secure );
		*newBN	= ref;
	}
	else
	{
		err	= kPGPError_OutOfMemory;
	}
	
	return( err );
}
Ejemplo n.º 12
0
int
main(void)
{
	struct BigNum p, q, d, u;
	int i;
	clock_t interval;
	static unsigned const sizetable[] = {
		384, 512, 513, 514, 515, 768, 1024, 1536, 2048, 0
	};
	unsigned const *sizeptr = sizetable;

	bnInit();
	bnRandSeed(1);
	bnBegin(&p);
	bnBegin(&q);
	bnBegin(&d);
	bnBegin(&u);

	while (*sizeptr) {
		printf("Generating a %u-bit RSA key\n", *sizeptr);

		interval = clock();
		i = genRsaKey(&p, &q, &d, &u, *sizeptr, 17, stdout);
		interval = clock() - interval;
		printf("genRsaKey returned %d.  %ld.%06ld s\n", i,
			interval / 1000000, interval % 1000000);
		fputs("p = ", stdout);
		bnPrint(stdout, &p);
		fputs("\nq = ", stdout);
		bnPrint(stdout, &q);
		fputs("\nd = ", stdout);
		bnPrint(stdout, &d);
		fputs("\nu = ", stdout);
		bnPrint(stdout, &u);
		putchar('\n');

		sizeptr++;
	}

	bnEnd(&p);
	bnEnd(&q);
	bnEnd(&d);
	bnEnd(&u);

	return 0;
}
Ejemplo n.º 13
0
int rsa_INIT(RSA_CTX *ctx,unsigned long int bitlen){
/* e is <i> always </i> 3 ;) */
int t;
bnBegin(&ctx->n);
bnBegin(&ctx->e);
bnBegin(&ctx->d);
t=bnSetQ(&ctx->e,(unsigned long int)3);
if(t<0){
	bnEnd(&ctx->n);
	bnEnd(&ctx->e);
	bnEnd(&ctx->d);
	return BADTHINGS;
}
ctx->bits=bitlen;
ctx->ebits=sizeof(unsigned long int);
return OK;
}
Ejemplo n.º 14
0
int
bnPrint10(FILE *f, char const *prefix, BigNum const *bn,
	char const *suffix)
{
	BigNum pbig, pbig1;
	BigNum ten, zero, rem;
	char buf[3000];			/* up to 9000 bits */
	int bufi = sizeof(buf)-1;
	int n;

	buf[bufi] = '\0';
	bnBegin (&pbig);
	bnBegin (&pbig1);
	bnBegin (&rem);
	
	bnBegin (&ten);
	bnAddQ (&ten, 10);
	bnBegin (&zero);

	bnCopy (&pbig, bn);
	
	while (bnCmp (&pbig, &zero) != 0) {
		bnDivMod (&pbig1, &rem, &pbig, &ten);
		bnCopy (&pbig, &pbig1);
		n = bnLSWord (&rem);
		buf[--bufi] = n + '0';
	}

	bnEnd (&pbig);
	bnEnd (&pbig1);
	bnEnd (&rem);

	if (prefix && fputs(prefix, f) < 0)
		return EOF;

	fputs (buf+bufi, f);
	pgpClearMemory (buf, sizeof(buf));

	return suffix ?	fputs(suffix, f) : 0;
}
Ejemplo n.º 15
0
int32_t ZrtpDH::checkPubKey(uint8_t *pubKeyBytes) const
{

    /* ECC validation (partial), NIST SP800-56A, section 5.6.2.6 */
    if (pkType == EC25 || pkType == EC38 || pkType == E414) {

        dhCtx* tmpCtx = static_cast<dhCtx*>(ctx);
        EcPoint pub;

        INIT_EC_POINT(&pub);
        int32_t len = getPubKeySize() / 2;

        bnInsertBigBytes(pub.x, pubKeyBytes, 0, len);
        bnInsertBigBytes(pub.y, pubKeyBytes+len, 0, len);

        return ecCheckPubKey(&tmpCtx->curve, &pub);
    }

    if (pkType == E255) {
        return 1;
    }

    BigNum pubKeyOther;
    bnBegin(&pubKeyOther);
    bnInsertBigBytes(&pubKeyOther, pubKeyBytes, 0, getDhSize());

    if (pkType == DH2K) {
        if (bnCmp(&bnP2048MinusOne, &pubKeyOther) == 0) {
            return 0;
        }
    }
    else if (pkType == DH3K) {
        if (bnCmp(&bnP3072MinusOne, &pubKeyOther) == 0) {
            return 0;

        }
    }
    else {
        return 0;
    }
    if (bnCmpQ(&pubKeyOther, 1) == 0) {
        return 0;
    }

    bnEnd(&pubKeyOther);
    return 1;
}
Ejemplo n.º 16
0
int32_t ZrtpDH::generatePublicKey()
{
    dhCtx* tmpCtx = static_cast<dhCtx*>(ctx);

    bnBegin(&tmpCtx->pubKey);
    switch (pkType) {
    case DH2K:
        bnExpMod(&tmpCtx->pubKey, &two, &tmpCtx->privKey, &bnP2048);
        break;

    case DH3K:
        bnExpMod(&tmpCtx->pubKey, &two, &tmpCtx->privKey, &bnP3072);
        break;

    case EC25:
    case EC38:
    case E255:
    case E414:
        while (!ecdhGeneratePublic(&tmpCtx->curve, &tmpCtx->pubPoint, &tmpCtx->privKey))
            ecGenerateRandomNumber(&tmpCtx->curve, &tmpCtx->privKey);
    }
    return 0;
}
Ejemplo n.º 17
0
/*
 * Return 1 if (sig,siglen) is a valid MPI which signs
 * hash, of type h.  Verify that the type is SHA.1 and
 * the hash itself matches.
 */
static int
dsaVerify(PGPPubKey const *pubkey, PGPByte const *sig,
	size_t siglen, PGPHashVTBL const *h, PGPByte const *hash,
	PGPPublicKeyMessageFormat format)
{
#if PGP_VERIFY_DISABLE /* [ */

	(void)pubkey;
	(void)sig;
	(void)siglen;
	(void)h;
	(void)hash;
	(void)format;
	return kPGPError_FeatureNotAvailable;

#else /* PGP_VERIFY_DISABLE */  /* ]  [ */

	DSApub const *pub = (DSApub *)pubkey->priv;
	BigNum r, s, w, u2;
	int i;
	unsigned qbytes;
	size_t off;
	PGPMemoryMgrRef	mgr	= PGPGetContextMemoryMgr( pubkey->context );

	ASSERTDSA(pubkey->pkAlg);

	/* Hashsize must be at least as big as size of q for legal sig */
	if (h->hashsize*8 < bnBits(&pub->q)) {
		return 0;
	}

#if 0
	/* Allow generalizations of SHA, as long as they are big enough */
	if (h->algorithm != kPGPHashAlgorithm_SHA)
		return 0;	/* No match for sure! */
#endif

	bnBegin(&r, mgr, FALSE );
	bnBegin(&s, mgr, FALSE );
	bnBegin(&w, mgr, FALSE );
	bnBegin(&u2, mgr, FALSE );

	qbytes = bnBytes(&pub->q);

	/* sig holds two values.  Get first, r, from sig. */
	off = 0;
	if (format == kPGPPublicKeyMessageFormat_X509) {
		/* Parse SEQUENCE header for 509 sig data */
		PGPByte const *sigp = sig + off;
		PGPUInt32 len;
		if (pgpBnX509TagLen(&sigp, &len) != X509_TAG_SEQUENCE) {
			i = kPGPError_MalformedKeyComponent;
			goto done;
		}
		off += sigp - sig;
		if (len != siglen - off) {
			i = kPGPError_MalformedKeyComponent;
			goto done;
		}
	}
	i = pgpBnGetFormatted(&r, sig+off, siglen-off, qbytes, format);
	if (i <= 0)
		goto fail;
	/* Get 2nd value, s, from SIG */
	off += i;
	i = pgpBnGetFormatted(&s, sig+off, siglen-off, qbytes, format);
	if (i <= 0)
		goto fail;
	off += i;
	if (off != siglen) {
		i = kPGPError_BadSignatureSize;
		goto done;
	}

	/*
	 * Sanity-check r and s against the subprime q.  Both should
	 * be less than q.  If not, the signature is clearly bad.
	 */
	if (bnCmp(&r, &pub->q) >= 0 || bnCmp(&s, &pub->q) >= 0) {
		i = 0;	/* FAIL */
		goto done;
	}
	
	/* Reconstruct hash as u2 */
	if (bnInsertBigBytes(&u2, hash, 0, bnBytes(&pub->q)) < 0)
		goto nomem;

	/*
	 * Calculate DSS check function....
	 * Given signature (r,s) and hash H (in bn), compute:
	 * w = s^-1 mod q
	 * u1 = H * w mod q
	 * u2 = r * w mod q
	 * v = g^u1 * y^u2 mod p
	 * if v == r mod q, the signature checks.
	 *
	 * To save space, we put u1 into s, H into u2, and v into w.
	 */
	if (bnInv(&w, &s, &pub->q) < 0)
		goto nomem;
	if (bnMul(&s, &u2, &w) < 0 || bnMod(&s, &s, &pub->q) < 0)
		goto nomem;
	if (bnMul(&u2, &r, &w) < 0 || bnMod(&u2, &u2, &pub->q) < 0)
		goto nomem;

        /* Now for the expensive part... */

        if (bnDoubleExpMod(&w, &pub->g, &s, &pub->y, &u2, &pub->p) < 0)
                goto nomem;
        if (bnMod(&w, &w, &pub->q) < 0)
                goto nomem;

	/* Compare result with r, should be equal */
	i = bnCmp(&w, &r) == 0;

	goto done;

fail:
	if (!i)
		i = kPGPError_BadSignatureSize;
	goto done;
nomem:
	i = kPGPError_OutOfMemory;
	goto done;
done:
	bnEnd(&u2);
	bnEnd(&w);
	bnEnd(&s);
	bnEnd(&r);

	return i;

#endif /* PGP_VERIFY_DISABLE */ /* ] */
}
Ejemplo n.º 18
0
/*
 * This performs a modular exponentiation using the Chinese Remainder
 * Algorithm when the modulus is known to have two relatively prime
 * factors n = p * q, and u = p^-1 (mod q) has been precomputed.
 *
 * The chinese remainder algorithm lets a computation mod n be performed
 * mod p and mod q, and the results combined.  Since it takes
 * (considerably) more than twice as long to perform modular exponentiation
 * mod n as it does to perform it mod p and mod q, time is saved.
 *
 * If x is the desired result, let xp and xq be the values of x mod p
 * and mod q, respectively.  Obviously, x = xp + p * k for some k.
 * Taking this mod q, xq == xp + p*k (mod q), so p*k == xq-xp (mod q)
 * and k == p^-1 * (xq-xp) (mod q), so k = u * (xq-xp mod q) mod q.
 * After that, x = xp + p * k.
 *
 * Another savings comes from reducing the exponent d modulo phi(p)
 * and phi(q).  Here, we assume that p and q are prime, so phi(p) = p-1
 * and phi(q) = q-1.
 */
static int
bnExpModCRA(BigNum *x, BigNum const *d,
	BigNum const *p, BigNum const *q, BigNum const *u)
{
	BigNum xp, xq, k;
	int i;
	PGPMemoryMgrRef	mgr	= x->mgr;

bndPrintf("Performing Chinese Remainder Algorithm\n");
bndPut("x = ", x);
bndPut("p = ", p);
bndPut("q = ", q);
bndPut("d = ", d);
bndPut("u = ", u);

	bnBegin(&xp, mgr, TRUE);
	bnBegin(&xq, mgr, TRUE);
	bnBegin(&k, mgr, TRUE);

	/* Compute xp = (x mod p) ^ (d mod p-1) mod p */
	if (bnCopy(&xp, p) < 0)		/* First, use xp to hold p-1 */
		goto fail;
	(void)bnSubQ(&xp, 1);		/* p > 1, so subtracting is safe. */
	if (bnMod(&k, d, &xp) < 0)	/* k = d mod (p-1) */
		goto fail;
bndPut("d mod p-1 = ", &k);
	if (bnMod(&xp, x, p) < 0)	/* Now xp = (x mod p) */
		goto fail;
bndPut("x mod p = ", &xp);
	if (bnExpMod(&xp, &xp, &k, p) < 0)	/* xp = (x mod p)^k mod p */
		goto fail;
bndPut("xp = x^d mod p = ", &xp);

	/* Compute xq = (x mod q) ^ (d mod q-1) mod q */
	if (bnCopy(&xq, q) < 0)		/* First, use xq to hold q-1 */
		goto fail;
	(void)bnSubQ(&xq, 1);		/* q > 1, so subtracting is safe. */
	if (bnMod(&k, d, &xq) < 0)	/* k = d mod (q-1) */
		goto fail;
bndPut("d mod q-1 = ", &k);
	if (bnMod(&xq, x, q) < 0)	/* Now xq = (x mod q) */
		goto fail;
bndPut("x mod q = ", &xq);
	if (bnExpMod(&xq, &xq, &k, q) < 0)	/* xq = (x mod q)^k mod q */
		goto fail;
bndPut("xq = x^d mod q = ", &xq);

	/* xp < p and PGP has p < q, so this is a no-op, but just in case */
	if (bnMod(&k, &xp, q) < 0)
		goto fail;	
bndPut("xp mod q = ", &k);
	
	i = bnSub(&xq, &k);
bndPut("xq - xp = ", &xq);
bndPrintf("With sign %d\n", i);
	if (i < 0)
		goto fail;
	if (i) {
		/*
		 * Borrow out - xq-xp is negative, so bnSub returned
		 * xp-xq instead, the negative of the true answer.
		 * Add q back (which is subtracting from the negative)
		 * so the sign flips again.
		 */
		i = bnSub(&xq, q);
		if (i < 0)
			goto fail;
bndPut("xq - xp mod q = ", &xq);
bndPrintf("With sign %d\n", i);		/* Must be 1 */
	}

	/* Compute k = xq * u mod q */
	if (bnMul(&k, u, &xq) < 0)
		goto fail;
bndPut("(xq-xp) * u = ", &k);
	if (bnMod(&k, &k, q) < 0)
		goto fail;
bndPut("k = (xq-xp)*u % q = ", &k);

	/* Now x = k * p + xp is the final answer */
	if (bnMul(x, &k, p) < 0)
		goto fail;
bndPut("k * p = ", x);
	if (bnAdd(x, &xp) < 0)
		goto fail;
bndPut("k*p + xp = ", x);

#if BNDEBUG	/* @@@ DEBUG - do it the slow way for comparison */
	if (bnMul(&xq, p, q) < 0)
		goto fail;
bndPut("n = p*q = ", &xq);
	if (bnExpMod(&xp, x, d, &xq) < 0)
		goto fail;
bndPut("x^d mod n = ", &xp);
	if (bnCmp(x, &xp) != 0) {
bndPrintf("Nasty!!!\n");
		goto fail;
	}
	bnSetQ(&k, 17);
	bnExpMod(&xp, &xp, &k, &xq);
bndPut("x^17 mod n = ", &xp);
#endif

	bnEnd(&xp);
	bnEnd(&xq);
	bnEnd(&k);
	return 0;

fail:
	bnEnd(&xp);
	bnEnd(&xq);
	bnEnd(&k);
	return kPGPError_OutOfMemory;
}
Ejemplo n.º 19
0
/*
 * Similar, but searches forward from the given starting value in steps of
 * "step" rather than 1.  The step size must be even, and bn must be odd.
 * Among other possibilities, this can be used to generate "strong"
 * primes, where p-1 has a large prime factor.
 */
int
bnPrimeGenStrong(BigNum *bn, BigNum const *step,
	int (*f)(void *arg, int c), void *arg)
{
	int retval;
	unsigned p, prev;
	BigNum a, e;
	int modexps = 0;
#ifdef MSDOS
	unsigned char *sieve;
#else
	unsigned char sieve[SIEVE];
#endif
	PGPBoolean		isSecure	= bn->isSecure;
	PGPMemoryMgrRef	mgr	= bn->mgr;

#ifdef MSDOS
	sieve = bniMemAlloc(SIEVE);
	if (!sieve)
		return -1;
#endif

	/* Step must be even and bn must be odd */
	pgpAssert((bnLSWord(step) & 1) == 0);
	pgpAssert((bnLSWord(bn) & 1) == 1);

	bnBegin(&a, mgr, isSecure);
	bnBegin(&e, mgr, isSecure);

	for (;;) {
		if (sieveBuildBig(sieve, SIEVE, bn, step, 0) < 0)
			goto failed;

		p = prev = 0;
		if (sieve[0] & 1 || (p = sieveSearch(sieve, SIEVE, p)) != 0) {
			do {
				/*
				 * Adjust bn to have the right value,
				 * adding (p-prev) * 2*step.
				 */
				pgpAssert(p >= prev);
				/* Compute delta into a */
				if (bnMulQ(&a, step, p-prev) < 0)
					goto failed;
				if (bnAdd(bn, &a) < 0)
					goto failed;
				prev = p;

				retval = primeTest(bn, &e, &a, f, arg);
				if (retval <= 0)
					goto done;	/* Success! */
				modexps += retval;
				if (f && (retval = f(arg, '.')) < 0)
					goto done;

				/* And try again */
				p = sieveSearch(sieve, SIEVE, p);
			} while (p);
		}

		/* Ran out of sieve space - increase bn and keep trying. */
#if SIEVE*8 == 65536
		/* Corner case that will never actually happen */
		if (!prev) {
			if (bnAdd(bn, step) < 0)
				goto failed;
			p = 65535;
		} else {
			p = (unsigned)(SIEVE*8 - prev);
		}
#else
		p = SIEVE*8 - prev;
#endif
		if (bnMulQ(&a, step, p) < 0 || bnAdd(bn, &a) < 0)
			goto failed;
		if (f && (retval = f(arg, '/')) < 0)
			goto done;
	} /* for (;;) */

failed:
	retval = -1;

done:

	bnEnd(&e);
	bnEnd(&a);
#ifdef MSDOS
	bniMemFree(sieve, SIEVE);
#else
	bniMemWipe(sieve, sizeof(sieve));
#endif
	return retval < 0 ? retval : modexps + CONFIRMTESTS;
}
Ejemplo n.º 20
0
/*
 * Modifies the bignum to return a nearby (slightly larger) number which
 * is a probable prime.  Returns >=0 on success or -1 on failure (out of
 * memory).  The return value is the number of unsuccessful modular
 * exponentiations performed.  This never gives up searching.
 *
 * All other arguments are optional.  They may be NULL.  They are:
 *
 * unsigned (*randfunc)(unsigned limit)
 * For better distributed numbers, supply a non-null pointer to a
 * function which returns a random x, 0 <= x < limit.  (It may make it
 * simpler to know that 0 < limit <= SHUFFLE, so you need at most a byte.)
 * The program generates a large window of sieve data and then does
 * pseudoprimality tests on the data.  If a randfunc function is supplied,
 * the candidates which survive sieving are shuffled with a window of
 * size SHUFFLE before testing to increase the uniformity of the prime
 * selection.  This isn't perfect, but it reduces the correlation between
 * the size of the prime-free gap before a prime and the probability
 * that that prime will be found by a sequential search.
 *
 * If randfunc is NULL, sequential search is used.  If you want sequential
 * search, note that the search begins with the given number; if you're
 * trying to generate consecutive primes, you must increment the previous
 * one by two before calling this again.
 *
 * int (*f)(void *arg, int c), void *arg
 * The function f argument, if non-NULL, is called with progress indicator
 * characters for printing.  A dot (.) is written every time a primality test
 * is failed, a star (*) every time one is passed, and a slash (/) in the
 * (very rare) case that the sieve was emptied without finding a prime
 * and is being refilled.  f is also passed the void *arg argument for
 * private context storage.  If f returns < 0, the test aborts and returns
 * that value immediately.  (bn is set to the last value tested, so you
 * can increment bn and continue.)
 *
 * The "exponent" argument, and following unsigned numbers, are exponents
 * for which an inverse is desired, modulo p.  For a d to exist such that
 * (x^e)^d == x (mod p), then d*e == 1 (mod p-1), so gcd(e,p-1) must be 1.
 * The prime returned is constrained to not be congruent to 1 modulo
 * any of the zero-terminated list of 16-bit numbers.  Note that this list
 * should contain all the small prime factors of e.  (You'll have to test
 * for large prime factors of e elsewhere, but the chances of needing to
 * generate another prime are low.)
 *
 * The list is terminated by a 0, and may be empty.
 */
int
bnPrimeGen(BigNum *bn, unsigned (*randfunc)(unsigned),
         int (*f)(void *arg, int c), void *arg, unsigned exponent, ...)
{
	int retval;
	int modexps = 0;
	unsigned short offsets[SHUFFLE];
	unsigned i, j;
	unsigned p, q, prev;
	BigNum a, e;
#ifdef MSDOS
	unsigned char *sieve;
#else
	unsigned char sieve[SIEVE];
#endif

#ifdef MSDOS
	sieve = bniMemAlloc(SIEVE);
	if (!sieve)
		return -1;
#endif
	PGPBoolean		isSecure	= TRUE;
	PGPMemoryMgrRef	mgr	= bn->mgr;

	bnBegin(&a, mgr, isSecure);
	bnBegin(&e, mgr, isSecure);

#if 0	/* Self-test (not used for production) */
{
	BigNum t;
	static unsigned char const prime1[] = {5};
	static unsigned char const prime2[] = {7};
	static unsigned char const prime3[] = {11};
	static unsigned char const prime4[] = {1, 1}; /* 257 */
	static unsigned char const prime5[] = {0xFF, 0xF1}; /* 65521 */
	static unsigned char const prime6[] = {1, 0, 1}; /* 65537 */
	static unsigned char const prime7[] = {1, 0, 3}; /* 65539 */
	/* A small prime: 1234567891 */
	static unsigned char const prime8[] = {0x49, 0x96, 0x02, 0xD3};
	/* A slightly larger prime: 12345678901234567891 */
	static unsigned char const prime9[] = {
		0xAB, 0x54, 0xA9, 0x8C, 0xEB, 0x1F, 0x0A, 0xD3 };
	/*
	 * No, 123456789012345678901234567891 isn't prime; it's just a
	 * lucky, easy-to-remember conicidence.  (You have to go to
	 * ...4567907 for a prime.)
	 */
	static struct {
		unsigned char const *prime;
		unsigned size;
	} const primelist[] = {
		{ prime1, sizeof(prime1) },
		{ prime2, sizeof(prime2) },
		{ prime3, sizeof(prime3) },
		{ prime4, sizeof(prime4) },
		{ prime5, sizeof(prime5) },
		{ prime6, sizeof(prime6) },
		{ prime7, sizeof(prime7) },
		{ prime8, sizeof(prime8) },
		{ prime9, sizeof(prime9) } };

	bnBegin(&t);

	for (i = 0; i < sizeof(primelist)/sizeof(primelist[0]); i++) {
			bnInsertBytes(&t, primelist[i].prime, 0,
				      primelist[i].size);
			bnCopy(&e, &t);
			(void)bnSubQ(&e, 1);
			bnTwoExpMod(&a, &e, &t);
			p = bnBits(&a);
			if (p != 1) {
				printf(
			"Bug: Fermat(2) %u-bit output (1 expected)\n", p);
				fputs("Prime = 0x", stdout);
				for (j = 0; j < primelist[i].size; j++)
					printf("%02X", primelist[i].prime[j]);
				putchar('\n');
			}
			bnSetQ(&a, 3);
			bnExpMod(&a, &a, &e, &t);
			p = bnBits(&a);
			if (p != 1) {
				printf(
			"Bug: Fermat(3) %u-bit output (1 expected)\n", p);
				fputs("Prime = 0x", stdout);
				for (j = 0; j < primelist[i].size; j++)
					printf("%02X", primelist[i].prime[j]);
				putchar('\n');
			}
		}

	bnEnd(&t);
}
#endif

	/* First, make sure that bn is odd. */
	if ((bnLSWord(bn) & 1) == 0)
		(void)bnAddQ(bn, 1);

retry:
	/* Then build a sieve starting at bn. */
	sieveBuild(sieve, SIEVE, bn, 2, 0);

	/* Do the extra exponent sieving */
	if (exponent) {
		va_list ap;
		unsigned t = exponent;

		va_start(ap, exponent);

		do {
			/* The exponent had better be odd! */
			pgpAssert(t & 1);

			i = bnModQ(bn, t);
			/* Find 1-i */
			if (i == 0)
				i = 1;
			else if (--i)
				i = t - i;

			/* Divide by 2, modulo the exponent */
			i = (i & 1) ? i/2 + t/2 + 1 : i/2;

			/* Remove all following multiples from the sieve. */
			sieveSingle(sieve, SIEVE, i, t);

			/* Get the next exponent value */
			t = va_arg(ap, unsigned);
		} while (t);

		va_end(ap);
	}

	/* Fill up the offsets array with the first SHUFFLE candidates */
	i = p = 0;
	/* Get first prime */
	if (sieve[0] & 1 || (p = sieveSearch(sieve, SIEVE, p)) != 0) {
		offsets[i++] = p;
		p = sieveSearch(sieve, SIEVE, p);
	}
	/*
	 * Okay, from this point onwards, p is always the next entry
	 * from the sieve, that has not been added to the shuffle table,
	 * and is 0 iff the sieve has been exhausted.
	 *
	 * If we want to shuffle, then fill the shuffle table until the
	 * sieve is exhausted or the table is full.
	 */
	if (randfunc && p) {
		do {
			offsets[i++] = p;
			p = sieveSearch(sieve, SIEVE, p);
		} while (p && i < SHUFFLE);
	}

	/* Choose a random candidate for experimentation */
	prev = 0;
	while (i) {
		/* Pick a random entry from the shuffle table */
		j = randfunc ? randfunc(i) : 0;
		q = offsets[j];	/* The entry to use */

		/* Replace the entry with some more data, if possible */
		if (p) {
			offsets[j] = p;
			p = sieveSearch(sieve, SIEVE, p);
		} else {
			offsets[j] = offsets[--i];
			offsets[i] = 0;
		}

		/* Adjust bn to have the right value */
		if ((q > prev ? bnAddMult(bn, q-prev, 2)
		              : bnSubMult(bn, prev-q, 2)) < 0)
			goto failed;
		prev = q;

		/* Now do the Fermat tests */
		retval = primeTest(bn, &e, &a, f, arg);
		if (retval <= 0)
			goto done;	/* Success or error */
		modexps += retval;
		if (f && (retval = f(arg, '.')) < 0)
			goto done;
	}

	/* Ran out of sieve space - increase bn and keep trying. */
	if (bnAddMult(bn, SIEVE*8-prev, 2) < 0)
		goto failed;
	if (f && (retval = f(arg, '/')) < 0)
		goto done;
	goto retry;

failed:
	retval = -1;
done:
	bnEnd(&e);
	bnEnd(&a);
	bniMemWipe(offsets, sizeof(offsets));
#ifdef MSDOS
	bniMemFree(sieve, SIEVE);
#else
	bniMemWipe(sieve, sizeof(sieve));
#endif

	return retval < 0 ? retval : modexps + CONFIRMTESTS;
}
Ejemplo n.º 21
0
int rsa_INIT_e(RSA_CTX *ctx){
bnBegin(&ctx->e);
ctx->ebits=sizeof(unsigned long int);
return OK;
}
Ejemplo n.º 22
0
int rsa_INIT_d(RSA_CTX *ctx,unsigned long int bitlen){
bnBegin(&ctx->d);
ctx->bits=bitlen;
return OK;
}
Ejemplo n.º 23
0
/*----------------------------------------------------------------------------*/
zrtp_status_t zrtp_stream_attach(zrtp_session_t *session, zrtp_stream_t** stream)
{
    uint32_t i = 0;
	zrtp_status_t s = zrtp_status_fail;
    zrtp_stream_t* new_stream = NULL;	
    
	ZRTP_LOG(3, (_ZTU_,"ATTACH NEW STREAM to sID=%d:\n", session->id));
	
	/*
	 * Initialize first unused stream. If there are no available streams return error.
	 */
    zrtp_mutex_lock(session->streams_protector);
    for (i=0; i<ZRTP_MAX_STREAMS_PER_SESSION; i++) {
		if (ZRTP_STATE_NONE == session->streams[i].state) {
			new_stream = &session->streams[i];
			zrtp_memset(new_stream, 0, sizeof(zrtp_stream_t));
			break;
 		}
    }
	zrtp_mutex_unlock(session->streams_protector);

	if (!new_stream) {
		ZRTP_LOG(1, (_ZTU_,"\tWARNING! Can't attach one more stream. Limit is reached."
					 " Use #ZRTP_MAX_STREAMS_PER_SESSION. sID=%u\n", session->id));
		return zrtp_status_alloc_fail;
	}
	
	/*
	 * Initialize the private data stream with default initial values	 
	 */
	zrtp_mutex_init(&new_stream->stream_protector);
	_zrtp_change_state(new_stream, ZRTP_STATE_ACTIVE);
	new_stream->mode	= ZRTP_STREAM_MODE_CLEAR;
	new_stream->id		= session->zrtp->streams_count++;
	new_stream->session = session;
	new_stream->zrtp	= session->zrtp;
	new_stream->mitm_mode = ZRTP_MITM_MODE_UNKN;
	new_stream->is_hello_received = 0;
	
	ZSTR_SET_EMPTY(new_stream->cc.hmackey);
	ZSTR_SET_EMPTY(new_stream->cc.peer_hmackey);
	ZSTR_SET_EMPTY(new_stream->cc.zrtp_key);
	ZSTR_SET_EMPTY(new_stream->cc.peer_zrtp_key);

	new_stream->dh_cc.initialized_with	= ZRTP_COMP_UNKN;
	bnBegin(&new_stream->dh_cc.peer_pv);
	ZSTR_SET_EMPTY(new_stream->dh_cc.dhss);		
	
	ZRTP_LOG(3, (_ZTU_,"\tEmpty slot was found - initializing new stream with ID=%u.\n", new_stream->id));

	do {
	zrtp_string32_t hash_buff = ZSTR_INIT_EMPTY(hash_buff);
	zrtp_hash_t *hash = zrtp_comp_find(ZRTP_CC_HASH, ZRTP_HASH_SHA256, new_stream->zrtp);		
	s = zrtp_status_algo_fail;
		
	if (sizeof(uint16_t) !=  zrtp_randstr( new_stream->zrtp,
										  (uint8_t*)&new_stream->media_ctx.high_out_zrtp_seq,
										  sizeof(uint16_t))) {
		break;
	}	

	/*
	 * Compute and store message hashes to prevent DoS attacks.
	 * Generate H0 as a random nonce and compute H1, H2 and H3
	 * using the leftmost 128 bits from every hash.
	 * Then insert these directly into the message structures.
     */

	zrtp_memset(&new_stream->messages, 0, sizeof(new_stream->messages));
	ZSTR_SET_EMPTY(new_stream->messages.h0);
	ZSTR_SET_EMPTY(new_stream->messages.signaling_hash);

	/* Generate Random nonce, compute H1 and store in the DH packet */
	new_stream->messages.h0.length = (uint16_t)zrtp_randstr( new_stream->zrtp,
															 (unsigned char*)new_stream->messages.h0.buffer,
															 ZRTP_MESSAGE_HASH_SIZE);
	if (ZRTP_MESSAGE_HASH_SIZE != new_stream->messages.h0.length) {		
		break;
	}

	s = hash->hash(hash, ZSTR_GV(new_stream->messages.h0), ZSTR_GV(hash_buff));
	if (zrtp_status_ok != s) {
		break;
	}
	zrtp_memcpy(new_stream->messages.dhpart.hash, hash_buff.buffer, ZRTP_MESSAGE_HASH_SIZE);	

	/* Compute H2 for the Commit */		
	s = hash->hash_c(hash, (char*)new_stream->messages.dhpart.hash, ZRTP_MESSAGE_HASH_SIZE, ZSTR_GV(hash_buff));
	if (zrtp_status_ok != s) {
		break;
	}
	zrtp_memcpy(new_stream->messages.commit.hash, hash_buff.buffer, ZRTP_MESSAGE_HASH_SIZE);	

	/* Compute H3 for the Hello message */
	s = hash->hash_c(hash, (char*)new_stream->messages.commit.hash, ZRTP_MESSAGE_HASH_SIZE, ZSTR_GV(hash_buff));
	if (zrtp_status_ok != s) {
		break;
	}
	zrtp_memcpy(new_stream->messages.hello.hash, hash_buff.buffer, ZRTP_MESSAGE_HASH_SIZE);
	
	s = zrtp_status_ok;
	} while (0);
	
	if (zrtp_status_ok != s) {
		ZRTP_LOG(1, (_ZTU_,"\tERROR! Fail to compute messages hashes <%s>.\n", zrtp_log_status2str(s)));
		return s;
	}
	
    /*
	 * Preparing HELLO based on user's profile
	 */
	ZRTP_LOG(3, (_ZTU_,"\tPreparing ZRTP Hello according to the Session profile.\n"));
	{
	zrtp_packet_Hello_t* hello = &new_stream->messages.hello;	
	uint8_t i = 0;
	int8_t* comp_ptr = NULL;

	/* Set Protocol Version and ClientID */
	zrtp_memcpy(hello->version, ZRTP_PROTOCOL_VERSION, ZRTP_VERSION_SIZE);
	zrtp_memcpy(hello->cliend_id, session->zrtp->client_id.buffer, session->zrtp->client_id.length);
		
	/* Set flags. */
	hello->pasive	=  (ZRTP_LICENSE_MODE_PASSIVE == session->zrtp->lic_mode) ? 1 : 0;
	hello->uflag	= (ZRTP_LICENSE_MODE_UNLIMITED == session->zrtp->lic_mode) ? 1 : 0;
	hello->mitmflag = session->zrtp->is_mitm;	
	hello->sigflag	= 0;	
		
	zrtp_memcpy(hello->zid, session->zid.buffer, session->zid.length);
	
	comp_ptr = (int8_t*)hello->comp;
	i = 0;
	while ( session->profile.hash_schemes[i]) {
		zrtp_memcpy( comp_ptr,
					 zrtp_comp_id2type(ZRTP_CC_HASH, session->profile.hash_schemes[i++]),
					 ZRTP_COMP_TYPE_SIZE );
		comp_ptr += ZRTP_COMP_TYPE_SIZE;
	}
	hello->hc = i;	

	i = 0;
	while (session->profile.cipher_types[i]) {
		zrtp_memcpy( comp_ptr,
					 zrtp_comp_id2type(ZRTP_CC_CIPHER, session->profile.cipher_types[i++]),
					 ZRTP_COMP_TYPE_SIZE );
		comp_ptr += ZRTP_COMP_TYPE_SIZE;
	}
	hello->cc = i;

	i = 0;
	while (session->profile.auth_tag_lens[i] ) {
		zrtp_memcpy( comp_ptr,
					 zrtp_comp_id2type(ZRTP_CC_ATL, session->profile.auth_tag_lens[i++]),
					 ZRTP_COMP_TYPE_SIZE );
		comp_ptr += ZRTP_COMP_TYPE_SIZE;
	}
	hello->ac = i;

	i = 0;
	while (session->profile.pk_schemes[i] ) {
		zrtp_memcpy( comp_ptr,
					 zrtp_comp_id2type(ZRTP_CC_PKT, session->profile.pk_schemes[i++]),
					 ZRTP_COMP_TYPE_SIZE );
		comp_ptr += ZRTP_COMP_TYPE_SIZE;
	}
	hello->kc = i;

	i = 0;
	while (session->profile.sas_schemes[i]) {
		zrtp_memcpy( comp_ptr,
					zrtp_comp_id2type(ZRTP_CC_SAS, session->profile.sas_schemes[i++]),
					ZRTP_COMP_TYPE_SIZE );
		comp_ptr += ZRTP_COMP_TYPE_SIZE;
	}
	hello->sc = i;

	/*
	 * Hmac will appear at the end of the message, after the dynamic portion.
	 * i is the length of the dynamic part.
	 */	
	i = (hello->hc + hello->cc + hello->ac + hello->kc + hello->sc) * ZRTP_COMP_TYPE_SIZE;
	_zrtp_packet_fill_msg_hdr( new_stream,
							   ZRTP_HELLO,
							   ZRTP_HELLO_STATIC_SIZE + i + ZRTP_HMAC_SIZE,
							   &hello->hdr);
	}
	
	*stream = new_stream;
	
	ZRTP_LOG(3, (_ZTU_,"ATTACH NEW STREAM - DONE.\n"));
    return zrtp_status_ok;
}
Ejemplo n.º 24
0
static int
dsaUnlock(PGPSecKey *seckey, PGPEnv const *env,
	  char const *phrase, size_t plen, PGPBoolean hashedPhrase)
{
	DSAsecPlus *sec = (DSAsecPlus *)seckey->priv;
	BigNum x;
	PGPCFBContext *cfb = NULL;
	unsigned v;
	unsigned alg;
	unsigned checksum;
	int i;
	PGPMemoryMgrRef		mgr	= NULL;
	
	mgr	= PGPGetContextMemoryMgr( seckey->context );

	bnBegin(&x, mgr, TRUE);

	ASSERTDSA(seckey->pkAlg);

	/* Check packet for basic consistency */
	i = pgpBnParse(sec->cryptkey, sec->cklen, 4, &v, NULL, NULL, NULL);
	if (i <= 0)
		goto fail;

	/* OK, read the public data */
	i = pgpBnGetPlain(&sec->s.p, sec->cryptkey+v, sec->cklen-v);
	if (i <= 0)
		goto fail;
	v += i;
	i = pgpBnGetPlain(&sec->s.q, sec->cryptkey+v, sec->cklen-v);
	if (i <= 0)
		goto fail;
	v += i;
	i = pgpBnGetPlain(&sec->s.g, sec->cryptkey+v, sec->cklen-v);
	if (i <= 0)
		goto fail;
	v += i;
	i = pgpBnGetPlain(&sec->s.y, sec->cryptkey+v, sec->cklen-v);
	if (i <= 0)
		goto fail;
	v += i;

	/* Get the encryption algorithm (cipher number).  0 == no encryption */
	alg  = sec->cryptkey[v];

	/* If the phrase is empty, set it to NULL */
	if (plen == 0)
		phrase = NULL;
	/*
	 * We need a pass if it is encrypted, and we cannot have a
	 * password if it is NOT encrypted.  I.e., this is a logical
	 * xor (^^)
	 */
	if (!phrase != !sec->cryptkey[v])
		goto badpass;

	i = pgpCipherSetup(sec->cryptkey + v, sec->cklen - v, phrase, plen,
					   hashedPhrase, env, &cfb);
	if (i < 0)
		goto done;
	v += i;

	checksum = 0;
	i = pgpBnGetNew(&x, sec->cryptkey + v, sec->cklen - v, cfb, &checksum);
	if (i <= 0)
		goto badpass;
	v += i;
	if (bnCmp(&x, &sec->s.q) >= 0)
		goto badpass;	/* Wrong passphrase: x must be < q */

	/* Check that we ended in the right place */
	if (sec->cklen - v != 2) {
		i = kPGPError_KEY_LONG;
		goto fail;
	}
	checksum &= 0xffff;
	if (checksum != pgpChecksumGetNew(sec->cryptkey+v, cfb))
		goto badpass;

	/*
	 * Note that the "nomem" case calls bnEnd()
	 * more than once, but this is guaranteed harmless.
 	 */
	if (bnCopy(&sec->s.x, &x) < 0)
		goto nomem;

	i = 1;	/* Decrypted! */
	sec->locked = 0;
	goto done;

nomem:
	i = kPGPError_OutOfMemory;
	goto done;
fail:
	if (!i)
		i = kPGPError_KeyPacketTruncated;
	goto done;
badpass:
	i = 0;	/* Incorrect passphrase */
	goto done;
done:
	bnEnd(&x);
	if (cfb)
		PGPFreeCFBContext(cfb);
	return i;
}
Ejemplo n.º 25
0
/*
 * lhs-rhs.  dest and src may be the same, but bnSetQ(dest, 0) is faster.
 * if dest < src, returns error and dest is undefined.
 */
	PGPError
PGPBigNumSubtract(
	PGPBigNumRef	lhs,
	PGPBigNumRef	rhs,
	PGPBigNumRef	dest,
	PGPBoolean *	underflowPtr )
{
	PGPError	err	= kPGPError_NoErr;
	int			bnError;
	PGPBoolean	underflow	= FALSE;
	
	if ( IsntNull( underflowPtr ) )
		*underflowPtr	= FALSE;
		
	pgpValidateBigNum( lhs );
	pgpValidateBigNum( rhs );
	pgpValidateBigNum( dest );
	
	if ( lhs == dest )
	{
		bnError	= bnSub( &dest->bn, &rhs->bn );
		underflow	= (bnError == 1);
		bnError		= 0;
	}
	else if ( rhs == dest )
	{
		BigNum	temp;
		PGPBoolean	secure;
		
		secure	= lhs->bn.isSecure || rhs->bn.isSecure ||
					dest->bn.isSecure;
		bnBegin( &temp, dest->bn.mgr, secure );
			bnError	= bnCopy( &temp, &lhs->bn );
			if ( bnError == 0 )
			{
				bnError	= bnSub( &temp, &rhs->bn );
				underflow	= (bnError == 1);
				bnError		= 0;
				
				bnError	= bnCopy( &dest->bn, &temp );
			}
		bnEnd( &temp );
	}
	else
	{
		bnError	= bnCopy( &dest->bn, &lhs->bn );
		if ( bnError == 0 )
		{
			bnError	= bnSub( &dest->bn, &rhs->bn );
			underflow	= (bnError == 1);
			bnError		= 0;
		}
	}
	
	if ( IsntNull( underflowPtr ) )
		*underflowPtr	= underflow;
		
	if ( bnError == -1 )
		err	= kPGPError_OutOfMemory;
	
	return( err );
}
Ejemplo n.º 26
0
/*
 * Turn the algorithm-specific parts of a public key into a PGPPubKey
 * structure.  A public key's DSA-specific part is:
 *
 *  0      2+i  MPI for prime
 * 2+i     2+t  MPI for order
 * 4+i+t   2+u	MPI for generator
 * 6+i+t+u 2+v	MPI for public key
 * 8+i+t+u+v
 */
PGPPubKey *
dsaPubFromBuf(
	PGPContextRef	context,
	PGPByte const *	buf,
	size_t			size,
	PGPError *		error)
{
	PGPPubKey *pubkey;
	DSApub *pub;
	unsigned i, t, u, v;
	int w;
	PGPError	err = kPGPError_OutOfMemory;
	PGPMemoryMgrRef	mgr	= PGPGetContextMemoryMgr( context );
	
	bnInit();

	w = pgpBnParse(buf, size, 4, &i, &t, &u, &v);
	if (w < 0) {
		*error = (PGPError)w;
		return NULL;
	}
	if (t <= i+2 || (buf[t-1] & 1) == 0) {	/* Too small or even prime p */
		*error = kPGPError_MalformedKeyComponent;
		return NULL;
	}
	if (u <= t+2 || (buf[u-1] & 1) == 0) {	/* Too small or even order q */
		*error = kPGPError_MalformedKeyComponent;
		return NULL;
	}
	pub = (DSApub *)pgpContextMemAlloc( context,
		sizeof(*pub), kPGPMemoryMgrFlags_Clear);
	if (pub) {
		pubkey = (PGPPubKey *)pgpContextMemAlloc( context,
			sizeof(*pubkey), kPGPMemoryMgrFlags_Clear);
		if (pubkey) {
			pubkey->context	= context;
			
			bnBegin(&pub->p, mgr, FALSE );
			bnBegin(&pub->q, mgr, FALSE );
			bnBegin(&pub->g, mgr, FALSE );
			bnBegin(&pub->y, mgr, FALSE );
			if (bnInsertBigBytes(&pub->p, buf+i+2, 0, t-i-2) >= 0
			 && bnInsertBigBytes(&pub->q, buf+t+2, 0, u-t-2) >= 0
			 && bnInsertBigBytes(&pub->g, buf+u+2, 0, v-u-2) >= 0
			 && bnInsertBigBytes(&pub->y, buf+v+2, 0, w-v-2) >= 0)
			{
				if (dsaKeyTooBig (pub, NULL)) {
					err = kPGPError_KeyTooLarge;
				} else {
					dsaFillPubkey(pubkey, pub);
					*error = 0;
					return pubkey;
				}
			}
			/* Failed = clean up and return NULL */
			bnEnd(&pub->p);
			bnEnd(&pub->q);
			bnEnd(&pub->g);
			bnEnd(&pub->y);
			pgpContextMemFree( context, pubkey);
		}
		pgpContextMemFree( context, pub);
	}
	*error = err;
	return NULL;
}
Ejemplo n.º 27
0
/*
 * Modifies the given bnq to return a prime slightly larger, and then
 * modifies the given bnp to be a prime which is == 1 (mod bnq).
 * This is done by decreasing bnp until it is == 1 (mod 2*bnq), and
 * then searching forward in steps of 2*bnq.
 * Returns >=0 on success or -1 on failure (out of memory).  On
 * success, the return value is the number of modular exponentiations
 * performed (excluding the final confirmation).
 * This never gives up searching.
 *
 * int (*f)(void *arg, int c), void *arg
 * The function f argument, if non-NULL, is called with progress indicator
 * characters for printing.  A dot (.) is written every time a primality test
 * is failed, a star (*) every time one is passed, and a slash (/) in the
 * case that the sieve was emptied without finding a prime and is being
 * refilled.  f is also passed the void *arg argument for private
 * context storage.  If f returns < 0, the test aborts and returns
 * that value immediately.
 *
 * Apologies to structured programmers for all the GOTOs.
 */
int
dsaPrimeGen(BigNum *bnq, BigNum *bnp,
	int (*f)(void *arg, int c), void *arg)
{
	int retval;
	unsigned p, prev;
	BigNum a, e;
	int modexps = 0;
#ifdef MSDOS
	unsigned char *sieve;
#else
	unsigned char sieve[SIEVE];
#endif

#ifdef MSDOS
	sieve = bniMemAlloc(SIEVE);
	if (!sieve)
		return -1;
#endif

	bnBegin(&a);
	bnBegin(&e);

	/* Phase 1: Search forwards from bnq for a suitable prime. */

	/* First, make sure that bnq is odd. */
	(void)bnAddQ(bnq, ~bnLSWord(bnq) & 1);

	for (;;) {
		if (sieveBuild(sieve, SIEVE, bnq, 2, 1) < 0)
			goto failed;

		p = prev = 0;
		if (sieve[0] & 1 || (p = sieveSearch(sieve, SIEVE, p)) != 0) {
			do {
				/*
				 * Adjust bn to have the right value,
				 * incrementing in steps of < 65536.
				 * 32767 = 65535/2.
				 */
				pgpAssert(p >= prev);
				prev = p-prev;	/* Delta - add 2*prev to bn */
#if SIEVE*8*2 >= 65536
				while (prev > 32767) {
					if (bnAddQ(bnq, 2*32767) < 0)
						goto failed;
					prev -= 32767;
				}
#endif
				if (bnAddQ(bnq, 2*prev) < 0)
					goto failed;
				prev = p;

				retval = primeTest(bnq, &e, &a, f, arg);
				if (retval <= 0)
					goto phase2;	/* Success! */
				modexps += retval;
				if (f && (retval = f(arg, '.')) < 0)
					goto done;

				/* And try again */
				p = sieveSearch(sieve, SIEVE, p);
			} while (p);
		}

		/* Ran out of sieve space - increase bn and keep trying. */
#if SIEVE*8*2 >= 65536
		p = ((SIEVE-1)*8+7) - prev;	/* Number of steps (of 2) */
		while (p >= 32737) {
			if (bnAddQ(bnq, 2*32767) < 0)
				goto failed;
			p -= 32767;
		}
		if (bnAddQ(bnq, 2*(p+1)) < 0)
			goto failed;
#else
		if (bnAddQ(bnq, SIEVE*8*2 - prev) < 0)
			goto failed;
#endif
		if (f && (retval = f(arg, '/')) < 0)
			goto done;
	} /* for (;;) */

	/*
	 * Phase 2: find a suitable prime bnp == 1 (mod bnq).
	 */

	/*
	 * Since bnp will be, and bnq is, odd, bnp-1 must be a multiple
	 * of 2*bnq.  So start by subtracting the excess.
	 */

phase2:
	/* Double bnq until end of bnp search. */
	if (bnAdd(bnq, bnq) < 0)
		goto failed;

	bnMod(&a, bnp, bnq);
	if (bnBits(&a)) {	/* Will always be true, but... */
		(void)bnSubQ(&a, 1);
		if (bnSub(bnp, &a)) 	/* Also error on underflow */
			goto failed;
	}

	/* Okay, now we're ready. */

	for (;;) {
		if (sieveBuildBig(sieve, SIEVE, bnp, bnq, 0) < 0)
			goto failed;
		if (f && (retval = f(arg, '/')) < 0)
			goto done;

		p = prev = 0;
		if (sieve[0] & 1 || (p = sieveSearch(sieve, SIEVE, p)) != 0) {
			do {
				/*
				 * Adjust bn to have the right value,
				 * adding (p-prev) * 2*bnq.
				 */
				pgpAssert(p >= prev);
				/* Compute delta into a */
				if (bnMulQ(&a, bnq, p-prev) < 0)
					goto failed;
				if (bnAdd(bnp, &a) < 0)
					goto failed;
				prev = p;

				retval = primeTest(bnp, &e, &a, f, arg);
				if (retval <= 0)
					goto done;	/* Success! */
				modexps += retval;
				if (f && (retval = f(arg, '.')) < 0)
					goto done;

				/* And try again */
				p = sieveSearch(sieve, SIEVE, p);
			} while (p);
		}

		/* Ran out of sieve space - increase bn and keep trying. */
#if SIEVE*8 == 65536
		if (prev) {
			p = (unsigned)(SIEVE*8ul - prev);
		} else {
			/* Corner case that will never actually happen */
			if (bnAdd(bnp, bnq) < 0)
				goto failed;
			p = 65535;
		}
#else
		p = SIEVE*8 - prev;
#endif
		/* Add p * bnq to bnp */
		if (bnMulQ(&a, bnq, p) < 0)
			goto failed;
		if (bnAdd(bnp, &a) < 0)
			goto failed;
	} /* for (;;) */

failed:
	retval = -1;

done:
	/* Shift bnq back down by the extra bit again. */
	bnRShift(bnq, 1);	/* Harmless even if bnq is random */

	bnEnd(&e);
	bnEnd(&a);
#ifdef MSDOS
	bniMemFree(sieve, SIEVE);
#else
	bniMemWipe(sieve, sizeof(sieve));
#endif
	return retval < 0 ? retval : modexps + 2*CONFIRMTESTS;
}
Ejemplo n.º 28
0
/*---------------------------------------------------------------------------*/
static zrtp_status_t _derive_s0(zrtp_stream_t* stream, int is_initiator)
{
	static const zrtp_string32_t zrtp_kdf_label	= ZSTR_INIT_WITH_CONST_CSTRING(ZRTP_KDF_STR);
	static const zrtp_string32_t zrtp_sess_label = ZSTR_INIT_WITH_CONST_CSTRING(ZRTP_SESS_STR);
	static const zrtp_string32_t zrtp_multi_label = ZSTR_INIT_WITH_CONST_CSTRING(ZRTP_MULTI_STR);
	static const zrtp_string32_t zrtp_presh_label = ZSTR_INIT_WITH_CONST_CSTRING(ZRTP_PRESH_STR);
	
	zrtp_session_t *session = stream->session;
	zrtp_secrets_t* secrets  = &session->secrets;
	zrtp_proto_crypto_t* cc  = stream->protocol->cc;
	void* hash_ctx = NULL;
	char print_buff[256];

	switch (stream->mode)
	{
	/*
	 * S0 computing for FULL DH exchange	 
	 * S0 computing.  s0 is the master shared secret used for all
	 * cryptographic operations.  In particular, note the inclusion
	 * of "total_hash", a hash of all packets exchanged up to this
	 * point.  This belatedly detects any tampering with earlier
	 * packets, e.g. bid-down attacks.
	 *
	 * s0 = hash( 1 | DHResult | "ZRTP-HMAC-KDF" | ZIDi | ZIDr |
	 *                        total_hash | len(s1) | s1 | len(s2) | s2 | len(s3) | s3 )
	 * The constant 1 and all lengths are 32 bits big-endian values.
	 * The fields without length prefixes are fixed-witdh:
	 * - DHresult is fixed to the width of the DH prime.
	 * - The hash type string and ZIDs are fixed width.
	 * - total_hash is fixed by the hash negotiation.
	 * The constant 1 is per NIST SP 800-56A section 5.8.1, and is
	 * a counter which can be incremented to generate more than 256
	 * bits of key material.
	 * ========================================================================
	 */
	case ZRTP_STREAM_MODE_DH:
	{
		zrtp_proto_secret_t *C[3] = { 0, 0, 0};
		int i = 0;
		uint32_t comp_length = 0;
		zrtp_stringn_t *zidi = NULL, *zidr = NULL;
		struct BigNum dhresult;
#if (defined(ZRTP_USE_STACK_MINIM) && (ZRTP_USE_STACK_MINIM == 1))
		zrtp_uchar1024_t* buffer = zrtp_sys_alloc( sizeof(zrtp_uchar1024_t) );
		if (!buffer) {
			return zrtp_status_alloc_fail;
		}
#else
		zrtp_uchar1024_t holder;
		zrtp_uchar1024_t* buffer = &holder;
#endif

		ZRTP_LOG(3,(_ZTU_,"\tDERIVE S0 from DH exchange and RS secrets...\n"));
		ZRTP_LOG(3,(_ZTU_,"\t       my rs1ID:%s\n", hex2str(cc->rs1.id.buffer, cc->rs1.id.length, print_buff, sizeof(print_buff))));
		ZRTP_LOG(3,(_ZTU_,"\t      his rs1ID:%s\n", hex2str((const char*)stream->messages.peer_dhpart.rs1ID, ZRTP_RSID_SIZE, print_buff, sizeof(print_buff))));
		ZRTP_LOG(3,(_ZTU_,"\t his rs1ID comp:%s\n", hex2str(cc->rs1.peer_id.buffer, cc->rs1.peer_id.length, print_buff, sizeof(print_buff))));

		ZRTP_LOG(3,(_ZTU_,"\t       my rs2ID:%s\n", hex2str(cc->rs2.id.buffer, cc->rs2.id.length, print_buff, sizeof(print_buff))));
		ZRTP_LOG(3,(_ZTU_,"\t      his rs2ID:%s\n", hex2str((const char*)stream->messages.peer_dhpart.rs2ID, ZRTP_RSID_SIZE, print_buff, sizeof(print_buff))));
		ZRTP_LOG(3,(_ZTU_,"\t his rs2ID comp:%s\n", hex2str(cc->rs2.peer_id.buffer, cc->rs2.peer_id.length, print_buff, sizeof(print_buff))));

		ZRTP_LOG(3,(_ZTU_,"\t      my pbxsID:%s\n", hex2str(cc->pbxs.id.buffer, cc->pbxs.id.length, print_buff, sizeof(print_buff))));
		ZRTP_LOG(3,(_ZTU_,"\t     his pbxsID:%s\n", hex2str((const char*)stream->messages.peer_dhpart.pbxsID, ZRTP_RSID_SIZE, print_buff, sizeof(print_buff))));
		ZRTP_LOG(3,(_ZTU_,"\this pbxsID comp:%s\n", hex2str(cc->pbxs.peer_id.buffer, cc->pbxs.peer_id.length, print_buff, sizeof(print_buff))));

		hash_ctx = session->hash->hash_begin(session->hash);
		if (0 == hash_ctx) {
			ZRTP_LOG(1,(_ZTU_, "\tERROR! can't start hash calculation for S0 computing. ID=%u.\n", stream->id));
			return zrtp_status_fail;
		}

		/*
		 * NIST requires a 32-bit big-endian integer counter to be included
		 * in the hash each time the hash is computed, which we have set to
		 * the fixed value of 1, because we only compute the hash once.
		 */
		comp_length = zrtp_hton32(1L);
		session->hash->hash_update(session->hash, hash_ctx, (const int8_t*)&comp_length, 4);

		
		switch (stream->pubkeyscheme->base.id) {
			case ZRTP_PKTYPE_DH2048:
			case ZRTP_PKTYPE_DH3072:
			case ZRTP_PKTYPE_DH4096:
				comp_length = stream->pubkeyscheme->pv_length;
				ZRTP_LOG(3,(_ZTU_,"DH comp_length=%u\n", comp_length));
				break;
			case ZRTP_PKTYPE_EC256P:
			case ZRTP_PKTYPE_EC384P:
			case ZRTP_PKTYPE_EC521P:
				comp_length = stream->pubkeyscheme->pv_length/2;
				ZRTP_LOG(3,(_ZTU_,"ECDH comp_length=%u\n", comp_length));
				break;
			default:
				break;
		}
		
		bnBegin(&dhresult);
		stream->pubkeyscheme->compute(stream->pubkeyscheme,
									  &stream->dh_cc,
									  &dhresult,
									  &stream->dh_cc.peer_pv);
				
		bnExtractBigBytes(&dhresult, (uint8_t *)buffer, 0, comp_length);
		session->hash->hash_update(session->hash, hash_ctx, (const int8_t*)buffer, comp_length);
		bnEnd(&dhresult);

#if (defined(ZRTP_USE_STACK_MINIM) && (ZRTP_USE_STACK_MINIM == 1))
		zrtp_sys_free(buffer);
#endif
		
		/* Add "ZRTP-HMAC-KDF" to the S0 hash */		
		session->hash->hash_update( session->hash, hash_ctx,
									(const int8_t*)&zrtp_kdf_label.buffer,
									zrtp_kdf_label.length);

		/* Then Initiator's and Responder's ZIDs */
		if (stream->protocol->type == ZRTP_STATEMACHINE_INITIATOR) {
			zidi = ZSTR_GV(stream->session->zrtp->zid);
			zidr = ZSTR_GV(stream->session->peer_zid);
		} else {
			zidr = ZSTR_GV(stream->session->zrtp->zid);
			zidi = ZSTR_GV(stream->session->peer_zid);
		}
		
		session->hash->hash_update(session->hash, hash_ctx, (const int8_t*)&zidi->buffer, zidi->length);
		session->hash->hash_update(session->hash, hash_ctx, (const int8_t*)&zidr->buffer, zidr->length);
		session->hash->hash_update(session->hash, hash_ctx, (const int8_t*)&cc->mes_hash.buffer, cc->mes_hash.length);

		/* If everything is OK - RS1 should much */
		if (!zrtp_memcmp(cc->rs1.peer_id.buffer, stream->messages.peer_dhpart.rs1ID, ZRTP_RSID_SIZE))
		{
			C[0] = &cc->rs1;
			secrets->matches |= ZRTP_BIT_RS1;
		}
		/* If we have lost our RS1 - remote party should use backup (RS2) instead */
		else if (!zrtp_memcmp(cc->rs1.peer_id.buffer, stream->messages.peer_dhpart.rs2ID, ZRTP_RSID_SIZE))
		{
			C[0] = &cc->rs1;
			secrets->matches |= ZRTP_BIT_RS1;
			ZRTP_LOG(2,(_ZTU_,"\tINFO! We have lost our RS1 from previous broken exchange"
						" - remote party will use RS2 backup. ID=%u\n", stream->id));
		}
		/* If remote party lost it's secret - we will use backup */
		else if (!zrtp_memcmp(cc->rs2.peer_id.buffer, stream->messages.peer_dhpart.rs1ID, ZRTP_RSID_SIZE))
		{
			C[0] = &cc->rs2;
			cc->rs1 = cc->rs2;
			secrets->matches |= ZRTP_BIT_RS1;
			secrets->cached  |= ZRTP_BIT_RS1;
			ZRTP_LOG(2,(_ZTU_,"\tINFO! Remote party has lost it's RS1 - use RS2 backup. ID=%u\n", stream->id));
		}
		else
		{			
			secrets->matches &= ~ZRTP_BIT_RS1;

			zrtp_cache_set_verified(session->zrtp->cache, ZSTR_GV(session->peer_zid), 0);
			zrtp_cache_reset_secure_since(session->zrtp->cache, ZSTR_GV(session->peer_zid));

			ZRTP_LOG(2,(_ZTU_,"\tINFO! Our RS1 doesn't equal to other-side's one %s. ID=%u\n",
						cc->rs1.secret->_cachedflag ? " - drop verified!" : "", stream->id));
		}

		if (!zrtp_memcmp(cc->rs2.peer_id.buffer, stream->messages.peer_dhpart.rs2ID, ZRTP_RSID_SIZE)) {
			secrets->matches |= ZRTP_BIT_RS2;
			if (0 == C[0]) {
				C[0] = &cc->rs2;
			}
		}
		

		if (secrets->auxs &&
			(!zrtp_memcmp(stream->messages.peer_dhpart.auxsID, cc->auxs.peer_id.buffer, ZRTP_RSID_SIZE)) ) {
			C[1] =&cc->auxs;
	    	secrets->matches |= ZRTP_BIT_AUX;
		}

		if ( secrets->pbxs &&
			(!zrtp_memcmp(stream->messages.peer_dhpart.pbxsID, cc->pbxs.peer_id.buffer, ZRTP_RSID_SIZE)) ) {	
			C[2] = &cc->pbxs;
			secrets->matches |= ZRTP_BIT_PBX;
		}

		/* Finally hashing matched shared secrets */
		for (i=0; i<3; i++) {
			/*
			 * Some of the shared secrets s1 through s5 may have lengths of zero
			 * if they are null (not shared), and are each preceded by a 4-octet
			 * length field. For example, if s4 is null, len(s4) is 00 00 00 00,
			 * and s4 itself would be absent from the hash calculation, which
			 * means len(s5) would immediately follow len(s4).
			 */
			comp_length = C[i] ? zrtp_hton32(ZRTP_RS_SIZE) : 0;
			session->hash->hash_update(session->hash, hash_ctx, (const int8_t*)&comp_length, 4);
			if (C[i]) {
				session->hash->hash_update( session->hash,
											 hash_ctx,
											 (const int8_t*)C[i]->secret->value.buffer,
											 C[i]->secret->value.length );
				ZRTP_LOG(3,(_ZTU_,"\tUse S%d in calculations.\n", i+1));
			}
		}

		session->hash->hash_end(session->hash, hash_ctx, ZSTR_GV(cc->s0));
	} break; /* S0 for for DH and Preshared streams */

	/*
	 * Compute all possible combinations of preshared_key:
	 * hash(len(rs1) | rs1 | len(auxsecret) | auxsecret | len(pbxsecret) | pbxsecret)	 
	 * Find matched preshared_key and derive S0 from it:
	 * s0 = KDF(preshared_key, "ZRTP Stream Key", KDF_Context, negotiated hash length) 
	 *
	 * INFO: Take into account that RS1 and RS2 may be swapped.
	 * If no matched were found - generate DH commit.
	 * ========================================================================
	 */
	case ZRTP_STREAM_MODE_PRESHARED:
	{
		zrtp_status_t s				= zrtp_status_ok;
		zrtp_string32_t presh_key	= ZSTR_INIT_EMPTY(presh_key);		

		ZRTP_LOG(3,(_ZTU_,"\tDERIVE S0 for PRESHARED from cached secret. ID=%u\n", stream->id));

		/* Use the same hash as we used for Commitment */
		if (is_initiator)
		{
			s = _zrtp_compute_preshared_key( session,											 
											 ZSTR_GV(session->secrets.rs1->value),
											 (session->secrets.auxs->_cachedflag) ? ZSTR_GV(session->secrets.auxs->value) : NULL,
											 (session->secrets.pbxs->_cachedflag) ? ZSTR_GV(session->secrets.pbxs->value) : NULL,
											 ZSTR_GV(presh_key),
											 NULL);
			if (zrtp_status_ok != s) {
				return s;
			}
			
			secrets->matches |= ZRTP_BIT_RS1;
			if (session->secrets.auxs->_cachedflag) {				
				secrets->matches |= ZRTP_BIT_AUX;
			}
			if (session->secrets.pbxs->_cachedflag) {			
				secrets->matches |= ZRTP_BIT_PBX;
			}
		}
		/*
		 * Let's find appropriate hv key for Responder:
		 * <RS1, 0, 0>, <RS1, AUX, 0>, <RS1, 0, PBX>, <RS1, AUX, PBX>.
		 */
		else
		{
			int res=-1;
			char* peer_key_id		= (char*)stream->messages.peer_commit.hv+ZRTP_HV_NONCE_SIZE;
			zrtp_string8_t key_id	= ZSTR_INIT_EMPTY(key_id);
			
			do {
				/* RS1 MUST be available at this stage.*/
				s = _zrtp_compute_preshared_key( session,							 
												 ZSTR_GV(secrets->rs1->value),
												 NULL,
												 NULL,
												 ZSTR_GV(presh_key),
												 ZSTR_GV(key_id));
				if (zrtp_status_ok == s) {
					res = zrtp_memcmp(peer_key_id, key_id.buffer, ZRTP_HV_KEY_SIZE);
					if (0 == res) {
						secrets->matches |= ZRTP_BIT_RS1;
						break;
					}
				}				
				
				if (session->secrets.pbxs->_cachedflag)
				{
					s = _zrtp_compute_preshared_key( session,											 
													 ZSTR_GV(secrets->rs1->value),
													 NULL,
													 ZSTR_GV(secrets->pbxs->value),
													 ZSTR_GV(presh_key),
													 ZSTR_GV(key_id));
					if (zrtp_status_ok == s) {
						res = zrtp_memcmp(peer_key_id, key_id.buffer, ZRTP_HV_KEY_SIZE);
						if (0 == res) {
							secrets->matches |= ZRTP_BIT_PBX;
							break;
						}
					}
				}
				
				if (session->secrets.auxs->_cachedflag)
				{
					s = _zrtp_compute_preshared_key( session,													 
													 ZSTR_GV(secrets->rs1->value),
													 ZSTR_GV(secrets->auxs->value),
													 NULL,
													 ZSTR_GV(presh_key),
													 ZSTR_GV(key_id));
					if (zrtp_status_ok == s) {
						res = zrtp_memcmp(peer_key_id, key_id.buffer, ZRTP_HV_KEY_SIZE);
						if (0 == res) {
							secrets->matches |= ZRTP_BIT_AUX;
							break;
						}
					}
				}
				
				if ((session->secrets.pbxs->_cachedflag) && (session->secrets.auxs->_cachedflag))
				{
					s = _zrtp_compute_preshared_key( session,													 
													 ZSTR_GV(secrets->rs1->value),
													 ZSTR_GV(secrets->auxs->value),
													 ZSTR_GV(secrets->pbxs->value),
													 ZSTR_GV(presh_key),
													 ZSTR_GV(key_id));
					if (zrtp_status_ok == s) {
						res = zrtp_memcmp(peer_key_id, key_id.buffer, ZRTP_HV_KEY_SIZE);
						if (0 == res) {
							secrets->matches |= ZRTP_BIT_AUX;
							secrets->matches |= ZRTP_BIT_PBX;
							break;
						}
					}
				}
				
			} while (0);
			
			if (0 != res) {
				ZRTP_LOG(3,(_ZTU_,"\tINFO! Matched Key wasn't found - initate DH exchange.\n"));
				secrets->cached = 0;
				secrets->rs1->_cachedflag = 0;
				
				_zrtp_machine_start_initiating_secure(stream);
				return zrtp_status_ok;				
			}
		}
		
		ZRTP_LOG(3,(_ZTU_,"\tUse RS1, %s, %s in calculations.\n", 
					   (session->secrets.matches & ZRTP_BIT_AUX) ? "AUX" : "NULL",
					   (session->secrets.matches & ZRTP_BIT_PBX) ? "PBX" : "NULL"));		
		
		_zrtp_kdf( stream,
				   ZSTR_GV(presh_key),
				   ZSTR_GV(zrtp_presh_label),
				   ZSTR_GV(stream->protocol->cc->kdf_context),
				   session->hash->digest_length,
				   ZSTR_GV(cc->s0));
	} break;

		
	/*
	 * For FAST Multistream:
	 * s0n = KDF(ZRTPSess, "ZRTP Multistream Key", KDF_Context, negotiated hash length) 
	 * ========================================================================
	 */
	case ZRTP_STREAM_MODE_MULT:
	{
		ZRTP_LOG(3,(_ZTU_,"\tDERIVE S0 for MULTISTREAM from ZRTP Session key... ID=%u\n", stream->id));
		_zrtp_kdf( stream,
				   ZSTR_GV(session->zrtpsess),
				   ZSTR_GV(zrtp_multi_label),
				   ZSTR_GV(stream->protocol->cc->kdf_context),
				   session->hash->digest_length,
				   ZSTR_GV(cc->s0));
	} break;
		
	default: break;
	}
	
	
	/*
	 * Compute ZRTP session key for FULL streams only:
	 * ZRTPSess = KDF(s0, "ZRTP Session Key", KDF_Context, negotiated hash length)
	 */
	if (!ZRTP_IS_STREAM_MULT(stream)) {
		if (session->zrtpsess.length == 0) {
			_zrtp_kdf( stream,
					   ZSTR_GV(cc->s0),
					   ZSTR_GV(zrtp_sess_label),
					   ZSTR_GV(stream->protocol->cc->kdf_context),
					   session->hash->digest_length,
					   ZSTR_GV(session->zrtpsess));
		}
	}
	
	return zrtp_status_ok;
}
Ejemplo n.º 29
0
static int
dsaSign(PGPSecKey *seckey, PGPHashVTBL const *h, PGPByte const *hash,
	PGPByte *sig, size_t *siglen, PGPRandomContext const *rc,
	PGPPublicKeyMessageFormat format)
{
#if PGP_SIGN_DISABLE /* [ */

	(void)seckey;
	(void)h;
	(void)hash;
	(void)sig;
	(void)siglen;
	(void)rc;
	(void)format;
	return kPGPError_FeatureNotAvailable;

#else /* PGP_SIGN_DISABLE */  /* ]  [ */

	DSAsecPlus *sec = (DSAsecPlus *)seckey->priv;
	BigNum r, s, bn, k;
	unsigned t;
	unsigned qbits;
	unsigned qbytes;
	int i;
	PGPRandomContext *rc2;
	PGPMemoryMgrRef		mgr	= NULL;
	
	mgr	= PGPGetContextMemoryMgr( seckey->context );

	(void)h;
	/* We don't need this argument, although other algorithms may... */
	(void)format;

	ASSERTDSA(seckey->pkAlg);
	/* Allow generalizations of SHA as long as they are big enough */
#if 0
	pgpAssert(h->algorithm == kPGPHashAlgorithm_SHA);
#else
	pgpAssert(h->hashsize*8 >= bnBits(&sec->s.q));
	/* Make sure that q is the right size of we are using regular SHA hash */
	pgpAssert( ! (h->algorithm == kPGPHashAlgorithm_SHA
				&& bnBits(&sec->s.q) != h->hashsize*8) );
#endif

	if (sec->locked)
		return kPGPError_KeyIsLocked;

	/*
	 * DSA requires a secret k.  This k is *very* important
	 * to keep secret.  Consider, the DSA signing equations are:
	 * r = (g^k mod p) mod q, and
	 * s = k^-1 * (H(m) + x*r) mod q,
	 * so if you know k (and, the signature r, s and H), then
	 * x = r^-1 * (k*s - H(m))
	 * If we ever pick two k values the same, then
	 * r = (g^k mod p) mod q is the same for both signatures, and
	 * s1 = k^-1 * (H1 + x * r) 
	 * s2 = k^-1 * (H2 + x * r) 
	 * k = (H1-H2) / (s1-s2)
	 * and proceed from there.
	 *
	 * So we need to make *very* sure there's no problem.  To make
	 * sure, we add a layer on top of the passed-in RNG.  We assume
	 * the passed-in RNG is good enough to never repeat (not a
	 * difficult task), and apply an additional X9.17 generator on
	 * top of that, seeded with the secret x, which is destroyed
	 * before leaving this function.
	 *
	 * In addition, we add entropy from the hash to the original RNG.
	 * This will prevent us from using the same k value twice if the
	 * messages are different.
	 */
	pgpRandomAddBytes(rc, hash, bnBytes(&sec->s.q));
	rc2 = pgpRandomCreateX9_17( rc->context, kPGPCipherAlgorithm_CAST5, rc);
	if (!rc2)
		return kPGPError_OutOfMemory;
	pgpRandomBnSeed(rc2, &sec->s.x);

	/*
	 * Of these values, only k is inherently sensitive, but others may
	 * hold some intermediate results we would prefer not to have leaked.
	 * So mark all as sensitive.
	 */
	bnBegin(&r, mgr, TRUE );
	bnBegin(&s, mgr, TRUE );
	bnBegin(&bn, mgr, TRUE );
	bnBegin(&k, mgr, TRUE );

	/*
	 * Choose the random k value to be used for this signature.
	 * Make it a bit bigger than q so it is fairly uniform mod q.
	 */
	qbits = bnBits(&sec->s.q);
	qbytes = bnBytes(&sec->s.q);
	if (pgpBnGenRand(&k, rc2, qbits+8, 0, 1, qbits) < 0 ||
	    bnMod(&k, &k, &sec->s.q) < 0)
		goto nomem;
	
	/* Raise g to k power mod p then mod q to get r */
	if (bnExpMod(&r, &sec->s.g, &k, &sec->s.p) < 0 ||
	    bnMod(&r, &r, &sec->s.q) < 0)
		goto nomem;
	      
	/* r*x mod q into s */
	if (bnMul(&s, &r, &sec->s.x) < 0 ||
	    bnMod(&s, &s, &sec->s.q) < 0)
		goto nomem;

	/* Pack message hash M into buffer bn */
	if (bnInsertBigBytes(&bn, hash, 0, bnBytes(&sec->s.q)) < 0)
		goto nomem;
	if (bnMod(&bn, &bn, &sec->s.q) < 0)
		goto nomem;

	/* Add into s */
	if (bnAdd(&s, &bn) < 0 ||
	    bnMod(&s, &s, &sec->s.q) < 0)
		goto nomem;

	/* Divide by k, mod q (k inverse held in bn) */
	if (bnInv(&bn, &k, &sec->s.q) < 0 ||
	    bnMul(&s, &s, &bn) < 0 ||
	    bnMod(&s, &s, &sec->s.q) < 0)
		goto nomem;

	/* That's it, now to pack r and then s into the buffer */
	t = 0;
	if (format == kPGPPublicKeyMessageFormat_X509) {
		/* Put in SEQUENCE header for 509 sig data */
		PGPUInt32 len_seq, lenlen_seq;
		/* Count size of sequence, counting a 0 byte if hi bit is set */
		if (8*qbytes == bnBits(&r))
			len_seq = pgpBnX509LenLen(qbytes+1) + 1 + qbytes+1;
		else
			len_seq = pgpBnX509LenLen(qbytes) + 1 + qbytes;
		if (8*qbytes == bnBits(&s))
			len_seq += pgpBnX509LenLen(qbytes+1) + 1 + qbytes+1;
		else
			len_seq += pgpBnX509LenLen(qbytes) + 1 + qbytes;
		lenlen_seq = pgpBnX509LenLen(len_seq);
		sig[t++] = X509_TAG_SEQUENCE | X509_TAG_CONSTRUCTED;
		if (--lenlen_seq == 0) {
			sig[t++] = len_seq;
		} else {
			sig[t++] = 0x80 | lenlen_seq;
			len_seq <<= 8 * (4-lenlen_seq);
			while (lenlen_seq--) {
				sig[t++] = (PGPByte)(len_seq >> 24);
				len_seq <<= 8;
			}
		}
	}
Ejemplo n.º 30
0
int rsa_GENKEYS(RSA_CTX *ctx,unsigned char *s1,unsigned char *s2){
int t,c;
unsigned long int MB=(ctx->bits)/2;
struct BigNum bn;
struct BigNum p,q;
int len=MB/8;
if(ctx->bits==0)
	return BADDATALEN;
bnBegin(&bn);
bnBegin(&p);
bnBegin(&q);
t=bnInsertBigBytes(&p,(void*)s1,0,len);
c=bnInsertBigBytes(&q,(void*)s2,0,len);
if(t<0 || c<0){
	bnEnd(&bn);
	bnEnd(&p);
	bnEnd(&q);
	return BADTHINGS;
}
t=primeGen(&p,NULL,NULL,NULL,1,3,5,0);
c=primeGen(&q,NULL,NULL,NULL,1,3,5,0);
if(t<0 || c<0){
	bnEnd(&bn);
	bnEnd(&p);
	bnEnd(&q);
	return BADTHINGS;
}

t=bnMul(&ctx->n,&p,&q);
if(t<0){
	bnEnd(&bn);
	bnEnd(&p);
	bnEnd(&q);
	return BADTHINGS;
}
t=bnSubQ(&p,1);
if(t<0){
	bnEnd(&bn);
	bnEnd(&p);
	bnEnd(&q);
        return BADTHINGS;
}
t=bnSubQ(&q,1);
if(t<0){
	bnEnd(&bn);
	bnEnd(&p);
	bnEnd(&q);
        return BADTHINGS;
}
t=bnMul(&bn,&p,&q);
if(t<0){
	bnEnd(&bn);
	bnEnd(&p);
	bnEnd(&q);
        return BADTHINGS;
}
t=bnInv(&ctx->d,&ctx->e,&bn);
if(t<0){
	bnEnd(&bn);
	bnEnd(&p);
	bnEnd(&q);
        return BADTHINGS;
}
bnEnd(&bn);
bnEnd(&p);
bnEnd(&q);
return OK;
}