コード例 #1
0
ファイル: pgpBigNum.c プロジェクト: ysangkok/pgp-unix-6.5.8
/* dest = src^-1, modulo "mod".  dest may be the same as src. */
	PGPError
PGPBigNumInv(
	PGPBigNumRef	src, 
	PGPBigNumRef	mod,
	PGPBigNumRef	dest )
{
	PGPError	err	= kPGPError_NoErr;
	int			bnError	= 0;
	
	pgpValidateBigNum( src );
	pgpValidateBigNum( mod );
	pgpValidateBigNum( dest );
	
	bnError	= bnInv( &dest->bn, &src->bn, &mod->bn );
	if ( IsBNError( bnError ) )
	{
		if ( bnError == 1 )
			err	 = kPGPError_BigNumNoInverse;
		else
			err	= kPGPError_OutOfMemory;
	}

	return( err );
}
コード例 #2
0
ファイル: pgpDSAKey.c プロジェクト: ysangkok/pgp-win32-6.5.8
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;
			}
		}
	}
コード例 #3
0
ファイル: pgpDSAKey.c プロジェクト: ysangkok/pgp-win32-6.5.8
/*
 * 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 */ /* ] */
}
コード例 #4
0
ファイル: rsa.c プロジェクト: jhsquirrel/lclib
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;
}
コード例 #5
0
ファイル: keygen.c プロジェクト: AbrahamJewowich/FreeSWITCH
int
genRsaKey(struct PubKey *pub, struct SecKey *sec,
	  unsigned bits, unsigned exp, FILE *file)
{
	int modexps = 0;
	struct BigNum t;	/* Temporary */
	int i;
	struct Progress progress;

	progress.f = file;
	progress.column = 0;
	progress.wrap = 78;

	if (bnSetQ(&pub->e, exp))
		return -1;

	/* Find p - choose a starting place */
	if (genRandBn(&sec->p, bits/2, 0xC0, 1) < 0)
		return -1;
	/* And search for a prime */
	i = primeGen(&sec->p, randRange, file ? genProgress : 0, &progress,
	             exp, 0);
	if (i < 0)
		goto error;
	modexps = i;
	assert(bnModQ(&sec->p, exp) != 1);
bndPut("p = ", &sec->p);

	do {
		/* Visual separator between the two progress indicators */
		if (file)
			genProgress(&progress, ' ');

		if (genRandBn(&sec->q, (bits+1)/2, 0xC0, 1) < 0)
			goto error;
		if (bnCopy(&pub->n, &sec->q) < 0)
			goto error;
		if (bnSub(&pub->n, &sec->p) < 0)
			goto error;
		/* Note that bnSub(a,b) returns abs(a-b) */
	} while (bnBits(&pub->n) < bits/2-5);

	if (file)
		fflush(file);	/* Ensure the separators are visible */

	i = primeGen(&sec->q, randRange, file ? genProgress : 0, &progress,
	             exp, 0);
	if (i < 0)
		goto error;
	modexps += i;
	assert(bnModQ(&sec->p, exp) != 1);
bndPut("q = ", &sec->q);

	/* Wash the random number pool. */
	randFlush();

	/* Ensure that q is larger */
	if (bnCmp(&sec->p, &sec->q) > 0)
		bnSwap(&sec->p, &sec->q);
bndPut("p = ", &sec->p);
bndPut("q = ", &sec->q);


	/*
	 * Now we dive into a large amount of fiddling to compute d,
	 * the decryption exponent, from the encryption exponent.
	 * We require that e*d == 1 (mod p-1) and e*d == 1 (mod q-1).
	 * This can alomost be done via the Chinese Remainder Algorithm,
	 * but it doesn't quite apply, because p-1 and q-1 are not
	 * realitvely prime.  Our task is to massage these into
	 * two numbers a and b such that a*b = lcm(p-1,q-1) and
	 * gcd(a,b) = 1.  The technique is not well documented,
	 * so I'll describe it here.
	 * First, let d = gcd(p-1,q-1), then let a' = (p-1)/d and
	 * b' = (q-1)/d.  By the definition of the gcd, gcd(a',b') at
	 * this point is 1, but a'*b' is a factor of d shy of the desired
	 * value.  We have to produce a = a' * d1 and b = b' * d2 such
	 * d1*d2 = d and gcd(a,b) is 1.  This will be the case iff
	 * gcd(a,d2) = gcd(b,d1) = 1.  Since GCD is associative and
	 * (gcd(x,y,z) = gcd(x,gcd(y,z)) = gcd(gcd(x,y),z), etc.),
	 * gcd(a',b') = 1 implies that gcd(a',b',d) = 1 which implies
	 * that gcd(a',gcd(b',d)) = gcd(gcd(a',d),b') = 1.  So you can
	 * extract gcd(b',d) from d and make it part of d2, and the
	 * same for d1.  And iterate?  A pessimal example is x = 2*6^k
	 * and y = 3*6^k.  gcd(x,y) = 6^k and we have to divvy it up
	 * somehow so that all the factors of 2 go to x and all the
	 * factors of 3 go to y, ending up with a = 2*2^k and b = 3*3^k.
	 *
	 * Aah, f**k it.  It's simpler to do one big inverse for now.
	 * Later I'll figure out how to get this to work properly.
	 */

	/* Decrement q temporarily */
	(void)bnSubQ(&sec->q, 1);
	/* And u = p-1, to be divided by gcd(p-1,q-1) */
	if (bnCopy(&sec->u, &sec->p) < 0)
		goto error;
	(void)bnSubQ(&sec->u, 1);
bndPut("p-1 = ", &sec->u);
bndPut("q-1 = ", &sec->q);
	/* Use t to store gcd(p-1,q-1) */
	bnBegin(&t);
	if (bnGcd(&t, &sec->q, &sec->u) < 0) {
		bnEnd(&t);
		goto error;
	}
bndPut("t = gcd(p-1,q-1) = ", &t);

	/* Let d = (p-1) / gcd(p-1,q-1) (n is scratch for the remainder) */
	i = bnDivMod(&sec->d, &pub->n, &sec->u, &t);
bndPut("(p-1)/t = ", &sec->d);
bndPut("(p-1)%t = ", &pub->n);
	bnEnd(&t);
	if (i < 0)
		goto error;
	assert(bnBits(&pub->n) == 0);
	/* Now we have q-1 and d = (p-1) / gcd(p-1,q-1) */
	/* Find the product, n = lcm(p-1,q-1) = c * d */
	if (bnMul(&pub->n, &sec->q, &sec->d) < 0)
		goto error;
bndPut("(p-1)*(q-1)/t = ", &pub->n);
	/* Find the inverse of the exponent mod n */
	i = bnInv(&sec->d, &pub->e, &pub->n);
bndPut("e = ", &pub->e);
bndPut("d = ", &sec->d);
	if (i < 0)
		goto error;
	assert(!i);	/* We should NOT get an error here */
	/*
	 * Now we have the comparatively simple task of computing
	 * u = p^-1 mod q.
	 */
#if BNDEBUG
	bnMul(&sec->u, &sec->d, &pub->e);
bndPut("d * e = ", &sec->u);
	bnMod(&pub->n, &sec->u, &sec->q);
bndPut("d * e = ", &sec->u);
bndPut("q-1 = ", &sec->q);
bndPut("d * e % (q-1)= ", &pub->n);
	bnNorm(&pub->n);
	bnSubQ(&sec->p, 1);
bndPut("d * e = ", &sec->u);
	bnMod(&sec->u, &sec->u, &sec->p);
bndPut("p-1 = ", &sec->p);
bndPut("d * e % (p-1)= ", &sec->u);
	bnNorm(&sec->u);
	bnAddQ(&sec->p, 1);
#endif

	/* But it *would* be nice to have q back first. */
	(void)bnAddQ(&sec->q, 1);

bndPut("p = ", &sec->p);
bndPut("q = ", &sec->q);

	/* Now compute u = p^-1 mod q */
	i = bnInv(&sec->u, &sec->p, &sec->q);
	if (i < 0)
		goto error;
bndPut("u = p^-1 % q = ", &sec->u);
	assert(!i);	/* p and q had better be relatively prime! */

#if BNDEBUG
	bnMul(&pub->n, &sec->u, &sec->p);
bndPut("u * p = ", &pub->n);
	bnMod(&pub->n, &pub->n, &sec->q);
bndPut("u * p % q = ", &pub->n);
	bnNorm(&pub->n);
#endif
	/* And finally,  n = p * q */
	if (bnMul(&pub->n, &sec->p, &sec->q) < 0)
		goto error;
bndPut("n = p * q = ", &pub->n);
	/* And that's it... success! */
	if (file)
		putc('\n', file);	/* Signal done */
	return modexps;

error:
	if (file)
		fputs("?\n", file);	/* Signal error */

	return -1;
}