Ejemplo n.º 1
0
/*
	Pad a value to be encrypted by RSA, according to PKCS#1 v1.5
	http://www.rsasecurity.com/rsalabs/pkcs/pkcs-1/
	When encrypting a value with RSA, the value is first padded to be 
	equal to the public key size using the following method:
		00 <id> <data> 00 <value to be encrypted>
	- id denotes a public or private key operation
	- if id is private, data is however many non-zero bytes it takes to pad the
		value to the key length (randomLen = keyLen - 3 - valueLen).
	- if id is public, data is FF for the same length as described above
	- There must be at least 8 bytes of data.
*/
static int32 sslPadRSA(unsigned char *in, int32 inlen, unsigned char *out,
					   int32 outlen, int32 cryptType)
{
	unsigned char	*c;
	int32			randomLen;
	
	randomLen = outlen - 3 - inlen;
	if (randomLen < 8) {
		matrixIntDebugMsg("RSA encryption data too large: %d\n", inlen);
		return -1;
	}
	c = out;
	*c = 0x00;
	c++;
	*c = (unsigned char)cryptType;
	c++;
	if (cryptType == RSA_PUBLIC) {
		while (randomLen-- > 0) {
			*c++ = 0xFF;
		}
	} else {
		if (sslGetEntropy(c, randomLen) < 0) {
			matrixStrDebugMsg("Error gathering RSA pad entropy\n", NULL);
			return -1;
		}
/*
		SECURITY:  Read through the random data and change all 0x0 to 0x01.
		This is per spec that no random bytes should be 0
*/
		while (randomLen-- > 0) {
			if (*c == 0x0) {
				*c = 0x01;
			}
			c++;
		}
	}
	*c = 0x00;
	c++;
	memcpy(c, in, inlen);
	
	return outlen;
}
Ejemplo n.º 2
0
/*
	Write out the ServerHello message
*/
static int32 writeServerHello(ssl_t *ssl, sslBuf_t *out)
{
	unsigned char	*c, *end, *encryptStart;
	char			padLen;
	int32				messageSize, rc;
	time_t			t;

	c = out->end;
	end = out->buf + out->size;
/*
	Calculate the size of the message up front, and verify we have room
	We assume there will be a sessionId in the message, and make adjustments
	below if there is no sessionId.
*/
	messageSize =
		ssl->recordHeadLen +
		ssl->hshakeHeadLen +
		38 + SSL_MAX_SESSION_ID_SIZE;
/*
	First 4 bytes of the serverRandom are the unix time to prevent replay
	attacks, the rest are random
*/
	t = time(0);
	ssl->sec.serverRandom[0] = (unsigned char)((t & 0xFF000000) >> 24);
	ssl->sec.serverRandom[1] = (unsigned char)((t & 0xFF0000) >> 16);
	ssl->sec.serverRandom[2] = (unsigned char)((t & 0xFF00) >> 8);
	ssl->sec.serverRandom[3] = (unsigned char)(t & 0xFF);
	if (sslGetEntropy(ssl->sec.serverRandom + 4, SSL_HS_RANDOM_SIZE - 4) < 0) {
		matrixStrDebugMsg("Error gathering serverRandom entropy\n", NULL);
		return SSL_ERROR;
	}
/*
	We register session here because at this point the serverRandom value is
	populated.  If we are able to register the session, the sessionID and
	sessionIdLen fields will be non-NULL, otherwise the session couldn't
	be registered.
*/
	if (!(ssl->flags & SSL_FLAGS_RESUMED)) {
		matrixRegisterSession(ssl);
	}
	messageSize -= (SSL_MAX_SESSION_ID_SIZE - ssl->sessionIdLen);

	if ((rc = writeRecordHeader(ssl, SSL_RECORD_TYPE_HANDSHAKE,
			SSL_HS_SERVER_HELLO, &messageSize, &padLen, &encryptStart,
			&end, &c)) < 0) {
		return rc;
	}
/*
	First two fields in the ServerHello message are the major and minor
	SSL protocol versions we agree to talk with
*/
	*c = ssl->majVer; c++;
	*c = ssl->minVer; c++;
/*
	The next 32 bytes are the server's random value, to be combined with
	the client random and premaster for key generation later
*/
	memcpy(c, ssl->sec.serverRandom, SSL_HS_RANDOM_SIZE);
	c += SSL_HS_RANDOM_SIZE;
/*
	The next data is a single byte containing the session ID length,
	and up to 32 bytes containing the session id.
	First register the session, which will give us a session id and length
	if not all session slots in the table are used
*/
	*c = ssl->sessionIdLen; c++;
	if (ssl->sessionIdLen > 0) {
        memcpy(c, ssl->sessionId, ssl->sessionIdLen);
		c += ssl->sessionIdLen;
	}
/*
	Two byte cipher suite we've chosen based on the list sent by the client
	and what we support.
	One byte compression method (always zero)
*/
	*c = (ssl->cipher->id & 0xFF00) >> 8; c++;
	*c = ssl->cipher->id & 0xFF; c++;
	*c = 0; c++;

	if ((rc = encryptRecord(ssl, SSL_RECORD_TYPE_HANDSHAKE, messageSize,
			padLen, encryptStart, out, &c)) < 0) {
		return rc;
	}
/*
	If we're resuming a session, we now have the clientRandom, master and 
	serverRandom, so we can derive keys which we'll be using shortly.
*/
	if (ssl->flags & SSL_FLAGS_RESUMED) {
		sslDeriveKeys(ssl);
	}
/*
	Verify that we've calculated the messageSize correctly, really this
	should never fail; it's more of an implementation verification
*/
	if (c - out->end != messageSize) {
		return SSL_ERROR;
	}
	out->end = c;
	return SSL_SUCCESS;
}
Ejemplo n.º 3
0
/*
	Public API wrapper around sslGetEntropy
*/
int32 matrixGetRandomBytes(unsigned char *bytes, int32 size)
{
		return sslGetEntropy(bytes, size);
}
Ejemplo n.º 4
0
static int32 tim_mp_exptmod(psPool_t *pool, 
						  mp_int *c, mp_int *e, mp_int *d, mp_int *n, mp_int *m)
{
	int32			err;
	mp_int			r, tmp, tmp2;
	unsigned char	*rtmp;
	unsigned long	rlen;
/*
	pick random r
 */
	rlen = mp_unsigned_bin_size(n);

	rtmp = psMalloc(pool, rlen);
	if (rtmp == NULL) {
		return -8; /* SSL_MEM_ERROR */
	}
	sslGetEntropy(rtmp, rlen);

	if ((err = _mp_init_multi(pool, &r, &tmp, &tmp2, NULL, NULL, NULL, NULL,
			NULL)) != MP_OKAY) {
		psFree(rtmp);
		return -1;
	}
/*
	read in r
 */
	if ((err = mp_read_unsigned_bin(&r, rtmp, rlen)) != MP_OKAY) {
		goto __ERR;
	}
/*
	compute tmp = r^e
 */
	if ((err = mp_exptmod(pool, &r, e, n, &tmp)) != MP_OKAY) {
		goto __ERR;
	}
/*
	multiply C into the mix
 */
	if ((err = mp_mulmod(pool, c, &tmp, n, &tmp)) != MP_OKAY) {
		goto __ERR;
	}
/*
	raise to d
 */
	if ((err = mp_exptmod(pool, &tmp, d, n, &tmp)) != MP_OKAY) {
		goto __ERR;
	}
/*
	invert r and multiply
 */
	if ((err = mp_invmod(pool, &r, n, &tmp2)) != MP_OKAY) {
		goto __ERR;
	}
/*
	multiply and we are totally set
 */
	if ((err = mp_mulmod(pool, &tmp, &tmp2, n, m)) != MP_OKAY) {
		goto __ERR;
	}

__ERR:  _mp_clear_multi(&r, &tmp, &tmp2, NULL, NULL, NULL, NULL, NULL);
	psFree(rtmp);
	return err;
}