Beispiel #1
0
int
rsa_private_encrypt(unitptr outbuf, byteptr inbuf, short bytes,
	 unitptr E, unitptr D, unitptr P, unitptr Q, unitptr U, unitptr N)
/* Encrypt a message digest with a private key.
 * Returns <0 on error:
 * -1: generic error
 * -4: Key too big
 * -5: Key too small
 */
{
	unit temp[MAX_UNIT_PRECISION];
	unit DP[MAX_UNIT_PRECISION], DQ[MAX_UNIT_PRECISION];
	byte *p;
	int i;
	unsigned int blocksize;

	/* PGP doesn't store these coefficents, so we need to compute them. */
	mp_move(temp,P);
	mp_dec(temp);
	mp_mod(DP,D,temp);
	mp_move(temp,Q);
	mp_dec(temp);
	mp_mod(DQ,D,temp);

	p = (byte *)temp;


	/* We are building the mpi in place, except for a possible
	 * byte-order swap to little-endian at the end.  Thus, we
	 * need to fill the buffer with leading 0's in the unused
	 * most significant byte positions.
	 */
	blocksize = countbytes(N) - 1;	/* Space available for data */
	for (i = units2bytes(global_precision) - blocksize; i > 0; --i)
		*p++ = 0;

	i = blocksize - 2 - bytes;		/* Padding needed */
	i -= sizeof(asn_array);		/* Space for type encoding */
	if (i < 0) {
		i = -4;			/* Error code */
		goto Cleanup;
	}
	*p++ = MD_ENCRYPTED_BYTE;	/* Type byte */
	memset(p, ~0, i);		/* All 1's padding */
	p += i;
	*p++ = 0;			/* Zero framing byte */
	memcpy(p, asn_array, sizeof(asn_array)); /* ASN data */
	p += sizeof(asn_array);
	memcpy(p, inbuf, bytes);	/* User data */

	mp_convert_order((byte *)temp);
	i = mp_modexp_crt(outbuf, temp, P, Q, DP, DQ, U);	/* Encrypt */
	if (i < 0)
		i = -1;

Cleanup:
	burn(temp);

	return i;
} /* rsa_private_encrypt */
Beispiel #2
0
void
mpi_dec(mpi *n)
{
    if (n->size == 0) {	/* Make it -1 */
        ASSERT(n->sign == 0);
        MPI_SIZE(n, 1);
        n->digits[0] = 1;
        n->sign = 1;
        return;
    }

    if (n->sign) {
        if (mp_inc(n->digits, n->size)) {
            MPI_MIN_ALLOC(n, n->size + 1);
            n->digits[n->size++] = 1;
        }
    } else {
        mp_dec(n->digits, n->size);
        n->size -= (n->digits[n->size - 1] == 0);
    }
}
Beispiel #3
0
/* We expect to find random padding and an encryption key */
int
rsa_private_decrypt(byteptr outbuf, unitptr inbuf,
	 unitptr E, unitptr D, unitptr P, unitptr Q, unitptr U, unitptr N)
/* Decrypt an encryption key using a private key.  Returns the number of bytes
 * extracted, or <0 on error.
 * -1: Generic error
 * -3: Key too big
 * -4: Key too small
 * -5: Maybe malformed RSA
 * -7: Unknown conventional algorithm
 * -9: Malformed RSA packet
 */
{
	byte *back;
	byte *front;
	unsigned int blocksize;
	unit temp[MAX_UNIT_PRECISION];
	unit DP[MAX_UNIT_PRECISION], DQ[MAX_UNIT_PRECISION];
	int i;

	/* PGP doesn't store (d mod p-1) and (d mod q-1), so compute 'em */
	mp_move(temp,P);
	mp_dec(temp);
	mp_mod(DP,D,temp);
	mp_move(temp,Q);
	mp_dec(temp);
	mp_mod(DQ,D,temp);

	i = mp_modexp_crt(temp, inbuf, P, Q, DP, DQ, U);
	mp_burn(DP);
	mp_burn(DQ);
	if (i < 0) {
		mp_burn(temp);
		return -1;
	}
	mp_convert_order((byte *)temp);
	front = (byte *)temp;			/* Start of block */
	i = units2bytes(global_precision);
	back = (byte *)front + i;		/* End of block */
	blocksize = countbytes(N) - 1;
	i -= blocksize;				/* Expected # of leading 0's */

	if (i < 0)				/* This shouldn't happen */
		goto Corrupted;
	while (i--)				/* Extra bytes should be 0 */
		if (*front++)
			goto Corrupted;

	/* How to distinguish old PGP from PKCS formats.
	 * PGP packets have a trailing type byte (CK_ENCRYPTED_BYTE),
	 * while PKCS formats have it leading.
	 */
	if (front[0] != CK_ENCRYPTED_BYTE && back[-1] == CK_ENCRYPTED_BYTE) {
		/* PGP 2.0 format  - padding at the end */
		if (back[-1] != CK_ENCRYPTED_BYTE)
			goto Corrupted;
		while (*--back)	/* Skip non-zero random padding */
			;
	} else {
		/* PKCS format - padding at the beginning */
		if (*front++ != CK_ENCRYPTED_BYTE)
			goto Corrupted;
		while (*front++)	/* Skip non-zero random padding */
			;
	}
	if (back <= front)
		goto Corrupted;
	blocksize = back-front;

	memcpy(outbuf, front, blocksize);
	mp_burn(temp);
	return blocksize;

Corrupted:
	mp_burn(temp);
	return -9;
} /* rsa_private_decrypt */