Example #1
0
/*
	Add a pre-shared key and ID to the static table in the first NULL spot
*/
int32 matrixSslLoadPsk(sslKeys_t *keys, unsigned char *key, uint32 keyLen,
				unsigned char *id, uint32 idLen)
{
	psPsk_t		*psk, *list;

	if (keys == NULL || key == NULL || id == NULL) {
		return PS_ARG_FAIL;
	}
	if (keyLen > SSL_PSK_MAX_KEY_SIZE) {
		psTraceIntInfo("Can't add PSK.  Key too large: %d\n", keyLen);
		return PS_ARG_FAIL;
	}

	if (idLen > SSL_PSK_MAX_ID_SIZE) {
		psTraceIntInfo("Can't add PSK.  Key ID too large: %d\n", idLen);
		return PS_ARG_FAIL;
	}

	if (keyLen < 1 || idLen < 1) {
		psTraceInfo("Can't add PSK. Both key and identity length must be >0\n");
		return PS_ARG_FAIL;
	}
	
	if ((psk = psMalloc(keys->pool, sizeof(psPsk_t))) == NULL) {
		return PS_MEM_FAIL;
	}
	memset(psk, 0, sizeof(psPsk_t));
	
	if ((psk->pskKey = psMalloc(keys->pool, keyLen)) == NULL) {
		psFree(psk);
		return PS_MEM_FAIL;
	}
	if ((psk->pskId = psMalloc(keys->pool, idLen)) == NULL) {
		psFree(psk->pskKey);
		psFree(psk);
		return PS_MEM_FAIL;
	}
	memcpy(psk->pskKey, key, keyLen);
	psk->pskLen = keyLen;
	
	memcpy(psk->pskId, id, idLen);
	psk->pskIdLen = idLen;
	
	if (keys->pskKeys == NULL) {
		keys->pskKeys = psk;
	} else {
		list = keys->pskKeys;
		while (list->next != NULL) {
			list = list->next;
		}
		list->next = psk;
	}
		
	return 0;
}
Example #2
0
File: corelib.c Project: B-Rich/NUL
/*
	Creates a simple linked list from a given stream and separator char
	
	Memory info:
	Callers do not have to free 'items' on function failure.
*/
int32 psParseList(psPool_t *pool, char *list, const char separator,
		psList_t **items)
{
	psList_t	*litems, *start, *prev;
	uint32		itemLen, listLen;
	char		*tmp;

	*items = NULL;
	prev = NULL;
	
	listLen = (int32)strlen(list) + 1;
	if (listLen == 1) {
		return PS_ARG_FAIL;
	}
	start = litems = psMalloc(pool, sizeof(psList_t));
	if (litems == NULL) {
		return PS_MEM_FAIL;
	}
	memset(litems, 0, sizeof(psList_t));

	while (listLen > 0) {
		itemLen = 0;
		tmp = list;
		if (litems == NULL) {
			litems = psMalloc(pool, sizeof(psList_t));
			if (litems == NULL) {
				psFreeList(start);
				return PS_MEM_FAIL;
			}
			memset(litems, 0, sizeof(psList_t));
			prev->next = litems;
			
		}
		while (*list != separator && *list != '\0') {
			itemLen++;
			listLen--;
			list++;
		}
		litems->item = psMalloc(pool, itemLen + 1);
		if (litems->item == NULL) {
			psFreeList(start);
			return PS_MEM_FAIL;
		}
		litems->len = itemLen;
		memset(litems->item, 0x0, itemLen + 1);
		memcpy(litems->item, tmp, itemLen);
		list++;
		listLen--;
		prev = litems;
		litems = litems->next;
	}
	*items = start;
	return PS_SUCCESS;
}
Example #3
0
/*
	Implementation specific date parser.
	Does not actually verify the date
*/
int32 getValidity(psPool_t *pool, unsigned char **pp, int32 len,
					   char **notBefore, char **notAfter)
{
	unsigned char	*p = *pp, *end;
	int32			seqLen, timeLen;

	end = p + len;
	if (len < 1 || *(p++) != (ASN_SEQUENCE | ASN_CONSTRUCTED) || 
			asnParseLength(&p, len - 1, &seqLen) < 0 || (end - p) < seqLen) {
		return -1;
	}
/*
	Have notBefore and notAfter times in UTCTime or GeneralizedTime formats
*/
	if ((end - p) < 1 || ((*p != ASN_UTCTIME) && (*p != ASN_GENERALIZEDTIME))) {
		return -1;
	}
	p++;
/*
	Allocate them as null terminated strings
*/
	if (asnParseLength(&p, seqLen, &timeLen) < 0 || (end - p) < timeLen) {
		return -1;
	}
	*notBefore = psMalloc(pool, timeLen + 1);
	if (*notBefore == NULL) {
		return -8; /* SSL_MEM_ERROR */
	}
	memcpy(*notBefore, p, timeLen);
	(*notBefore)[timeLen] = '\0';
	p = p + timeLen;
	if ((end - p) < 1 || ((*p != ASN_UTCTIME) && (*p != ASN_GENERALIZEDTIME))) {
		return -1;
	}
	p++;
	if (asnParseLength(&p, seqLen - timeLen, &timeLen) < 0 || 
			(end - p) < timeLen) {
		return -1;
	}
	*notAfter = psMalloc(pool, timeLen + 1);
	if (*notAfter == NULL) {
		return -8; /* SSL_MEM_ERROR */
	}
	memcpy(*notAfter, p, timeLen);
	(*notAfter)[timeLen] = '\0';
	p = p + timeLen;

	*pp = p;
	return 0;
}
Example #4
0
/*
	Could be optional.  If the tag doesn't contain the value from the left
	of the IMPLICIT keyword we don't have a match and we don't incr the pointer.
*/
int32 getImplicitBitString(psPool_t *pool, unsigned char **pp, int32 len, 
						int32 impVal, unsigned char **bitString, int32 *bitLen)
{
	unsigned char	*p = *pp;
	int32			ignore_bits;

	if (len < 1) {
		return -1;
	}
/*
	We don't treat this case as an error, because of the optional nature.
*/	
	if (*p != (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | impVal)) {
		return 0;
	}

	p++;
	if (asnParseLength(&p, len, bitLen) < 0) {
		return -1;
	}
	ignore_bits = *p++;
	sslAssert(ignore_bits == 0);

	*bitString = psMalloc(pool, *bitLen);
	if (*bitString == NULL) {
		return -8; /* SSL_MEM_ERROR */
	}
	memcpy(*bitString, p, *bitLen);
	*pp = p + *bitLen;
	return 0;
}
Example #5
0
/**
    Allocate a buffer and read in a file.
    @note Caller must free 'buf' parameter on success.
    Callers do not need to free buf on function failure.

    Two variants: psGetFileBuf takes in a filename, psGetFileBufFp takes in
    a pointer to an already opened FILE.
 */
int32 psGetFileBufFp(psPool_t *pool, FILE *fp, unsigned char **buf,
    int32 *bufLen)
{
    struct stat f_stat;
    size_t tmp = 0;
    int fno = fileno(fp);

    if (fstat(fno, &f_stat) != 0)
    {
        fclose(fp);
        psTraceIntCore("Unable to stat fp %d\n", fno);
        return PS_PLATFORM_FAIL;
    }
    *buf = psMalloc(pool, (size_t) (f_stat.st_size + 1));
    if (*buf == NULL)
    {
        fclose(fp);
        return PS_MEM_FAIL;
    }
    memset(*buf, 0x0, (size_t) f_stat.st_size + 1);

    while (((tmp = fread(*buf + *bufLen, sizeof(char), 512, fp)) > 0) &&
           (*bufLen < f_stat.st_size))
    {
        *bufLen += (int32) tmp;
    }
    fclose(fp);
    return PS_SUCCESS;
}
Example #6
0
/*
 *	Strtok substitute
 */
static int32 parseList(psPool_t *pool, const char *list, const char *sep,
					   char **item)
{
	int32	start, listLen;
	char	*tmp;

	start = listLen = (int32)strlen(list) + 1;
	if (start == 1) {
		*item = NULL;
		return 0;
	}
	tmp = *item = psMalloc(pool, listLen);
	if (tmp == NULL) {
		return -8; /* SSL_MEM_ERROR */
	}
	memset(*item, 0, listLen);
	while (listLen > 0) {
		if (*list == sep[0]) {
			list++;
			listLen--;
			break;
		}
		if (*list == 0) {
			break;
		}
		*tmp++ = *list++;
		listLen--;
	}
	return start - listLen;
}
Example #7
0
/*
    Binary to struct helper for RSA public keys.
*/
int32 matrixRsaParsePubKey(psPool_t *pool, unsigned char *keyBuf,
                              int32 keyBufLen, sslRsaKey_t **key)
{
    unsigned char   *p, *end;
    int32           len;

    p = keyBuf;
    end = p + keyBufLen;
/*
    Supporting both the PKCS#1 RSAPublicKey format and the
    X.509 SubjectPublicKeyInfo format.  If encoding doesn't start with
    the SEQUENCE identifier for the SubjectPublicKeyInfo format, jump down
    to the RSAPublicKey subset parser and try that
*/
    if (getSequence(&p, (int32)(end - p), &len) == 0) {
        if (getAlgorithmIdentifier(&p, (int32)(end - p), &len, 1) < 0) {
            return -1;
        }
    }
/*
    Now have the DER stream to extract from in asnp
 */
    *key = psMalloc(pool, sizeof(sslRsaKey_t));
    if (*key == NULL) {
        return -8; /* SSL_MEM_ERROR */
    }
    memset(*key, 0x0, sizeof(sslRsaKey_t));
    if (getPubKey(pool, &p, (int32)(end - p), *key) < 0) {
        matrixRsaFreeKey(*key);
        *key = NULL;
        matrixStrDebugMsg("Unable to ASN parse public key\n", NULL);
        return -1;
    }
    return 0;
}
Example #8
0
/*
	In-memory version of matrixX509ReadPubKey.
	This function was written strictly for clarity in the PeerSec crypto API
	subset.  It extracts only the public key from a certificate file for use
	in the lower level encrypt/decrypt RSA routines.
*/
int32 matrixX509ParsePubKey(psPool_t *pool, unsigned char *certBuf,
							int32 certLen, sslRsaKey_t **key)
{
	sslRsaKey_t		*lkey;
	sslRsaCert_t	*certStruct;
	int32			err;

	if (matrixX509ParseCert(pool, certBuf, certLen, &certStruct) < 0) {
		matrixX509FreeCert(certStruct);
		return -1;
	}
	lkey = *key = psMalloc(pool, sizeof(sslRsaKey_t));
	memset(lkey, 0x0, sizeof(sslRsaKey_t));

	if ((err = _mp_init_multi(pool, &lkey->e, &lkey->N, NULL,
			NULL, NULL,	NULL, NULL,	NULL)) != MP_OKAY) {
		matrixX509FreeCert(certStruct);
		psFree(lkey);
		return err;
	}
	mp_copy(&certStruct->publicKey.e, &lkey->e);
	mp_copy(&certStruct->publicKey.N, &lkey->N);

	mp_shrink(&lkey->e);
	mp_shrink(&lkey->N);

	lkey->size = certStruct->publicKey.size;

	matrixX509FreeCert(certStruct);

	return 0;
}
Example #9
0
/*
	Return the file contents given a file name in a single allocated buffer.
	Not a good routine to use generally with the fixed mem stuff.  Not 
	actually doing a 'binary' file read.  Only using the 'r' attribute since
	all the cert and key files are text.
*/
int32 psGetFileBin(psPool_t *pool, const char *fileName, unsigned char **bin,
				 int32 *binLen)
{
	FILE	*fp;
	struct	stat	fstat;
	size_t	tmp = 0;

	*binLen = 0;
	*bin = NULL;

	if (fileName == NULL) {
		return -1;
	}
	if ((stat(fileName, &fstat) != 0) || (fp = fopen(fileName, "r")) == NULL) {
		return -7; /* FILE_NOT_FOUND */
	}

	*bin = psMalloc(pool, fstat.st_size + 1);
	if (*bin == NULL) {
		return -8; /* SSL_MEM_ERROR */
	}
	memset(*bin, 0x0, fstat.st_size + 1);
	while (((tmp = fread(*bin + *binLen, sizeof(char), 512, fp)) > 0) &&
			(*binLen < fstat.st_size)) { 
		*binLen += (int32)tmp;
	}
	fclose(fp);
	return 0;
}
Example #10
0
/*
	Currently just returning the raw BIT STRING and size in bytes
*/
int32 getSignature(psPool_t *pool, unsigned char **pp, int32 len,
						unsigned char **sig, int32 *sigLen)
{
	unsigned char	*p = *pp, *end;
	int32			ignore_bits, llen;
	
	end = p + len;
	if (len < 1 || (*(p++) != ASN_BIT_STRING) ||
			asnParseLength(&p, len - 1, &llen) < 0 || (end - p) < llen) {
		return -1;
	}
	ignore_bits = *p++;
/*
	We assume this is always 0.
*/
	sslAssert(ignore_bits == 0);
/*
	Length included the ignore_bits byte
*/
	*sigLen = llen - 1;
	*sig = psMalloc(pool, *sigLen);
	if (*sig == NULL) {
		return -8; /* SSL_MEM_ERROR */
	}
	memcpy(*sig, p, *sigLen);
	*pp = p + *sigLen;
	return 0;
}
Example #11
0
/*
	Although a certificate serial number is encoded as an integer type, that
	doesn't prevent it from being abused as containing a variable length
	binary value.  Get it here.
*/	
int32 getSerialNum(psPool_t *pool, unsigned char **pp, int32 len, 
						unsigned char **sn, int32 *snLen)
{
	unsigned char	*p = *pp;
	int32			vlen;

	if ((*p != (ASN_CONTEXT_SPECIFIC | ASN_PRIMITIVE | 2)) &&
			(*p != ASN_INTEGER)) {
		matrixStrDebugMsg("ASN getSerialNumber failed\n", NULL);
		return -1;
	}
	p++;

	if (len < 1 || asnParseLength(&p, len - 1, &vlen) < 0) {
		matrixStrDebugMsg("ASN getSerialNumber failed\n", NULL);
		return -1;
	}
	*snLen = vlen;
	*sn = psMalloc(pool, vlen);
	if (*sn == NULL) {
		return -8; /* SSL_MEM_ERROR */
	}
	memcpy(*sn, p, vlen);
	p += vlen;
	*pp = p;
	return 0;
}
Example #12
0
/*
	Memory info:
	Caller must free 'buf' parameter on success 
	Callers do not need to free buf on function failure
*/
int32 psGetFileBuf(psPool_t *pool, const char *fileName, unsigned char **buf,
				int32 *bufLen)
{
	FILE	*fp;
	struct	stat	fstat;
	size_t	tmp = 0;

	*bufLen = 0;
	*buf = NULL;

	if (fileName == NULL) {
		return PS_ARG_FAIL;
	}
	if ((stat(fileName, &fstat) != 0) || (fp = fopen(fileName, "r")) == NULL) {
		psTraceStrCore("Unable to open %s\n", (char*)fileName);
		return PS_PLATFORM_FAIL;
	}

	*buf = psMalloc(pool, (size_t)(fstat.st_size + 1));
	if (*buf == NULL) {
		return PS_MEM_FAIL;
	}
	memset(*buf, 0x0, (size_t)fstat.st_size + 1);

	while (((tmp = fread(*buf + *bufLen, sizeof(char), 512, fp)) > 0) &&
			(*bufLen < fstat.st_size)) { 
		*bufLen += (int32)tmp;
	}
	fclose(fp);
	return PS_SUCCESS;
}
Example #13
0
/*
	Allows for semi-colon delimited list of certificates for cert chaining.
	Also allows multiple certificiates in a single file.
	
	HOWERVER, in both cases the first in the list must be the identifying
	cert of the application. Each subsequent cert is the parent of the previous
*/
int32 readCertChain(psPool_t *pool, const char *certFiles,
					sslLocalCert_t *lkeys)
{
	sslLocalCert_t	*currCert;
	unsigned char	*certBin, *tmp;
	sslChainLen_t	chain;
	int32			certLen, i;

	if (certFiles == NULL) {
		return 0;
	}

	if (matrixX509ReadCert(pool, certFiles, &certBin, &certLen, &chain) < 0) {
		matrixStrDebugMsg("Error reading cert file %s\n", (char*)certFiles);
		return -1;
	}
/*
	The first cert is allocated in the keys struct.  All others in
	linked list are allocated here.
*/
	i = 0;
	tmp = certBin;
	while (chain[i] != 0) {
		if (i == 0) {
			currCert = lkeys;
		} else {
			currCert->next = psMalloc(pool, sizeof(sslLocalCert_t));
			if (currCert->next == NULL) {
				psFree(tmp);
				return -8; /* SSL_MEM_ERROR */
			}
			memset(currCert->next, 0x0, sizeof(sslLocalCert_t));
			currCert = currCert->next;
		}
		currCert->certBin = psMalloc(pool, chain[i]);
		memcpy(currCert->certBin, certBin, chain[i]);
		currCert->certLen = chain[i];
		certBin += chain[i]; certLen -= chain[i];
		i++;
	}
	psFree(tmp);
	sslAssert(certLen == 0);
	return 0;
}
Example #14
0
/*
	Allocate a new psPubKey_t and memset empty 
*/
psPubKey_t * psNewPubKey(psPool_t *pool) {

	psPubKey_t *ret;

	ret = psMalloc(pool, sizeof(psPubKey_t));

	if (ret == NULL) {
		psError("Memory allocation error in psNewPubKey\n");
		return NULL;
	}
	memset(ret, 0x0, sizeof(psPubKey_t));
	ret->key = psMalloc(pool, sizeof(pubKeyUnion_t));
	if (ret->key == NULL) {
		psFree(ret);
		psError("Memory allocation error in psNewPubKey\n");
		return NULL;
	}
	memset(ret->key, 0x0, sizeof(pubKeyUnion_t));
	return ret;
}
Example #15
0
/* SessionID management functions for clients that wish to perform
	session resumption.  This structure handles both the traditional resumption
	mechanism and the server-stateless session ticket mechanism
*/
int32 matrixSslNewSessionId(sslSessionId_t **sess)
{
	sslSessionId_t	*ses;

	if ((ses = psMalloc(MATRIX_NO_POOL, sizeof(sslSessionId_t))) == NULL) {
		return PS_MEM_FAIL;
	}
	memset(ses, 0x0, sizeof(sslSessionId_t));
	*sess = ses;
	return PS_SUCCESS;
}
Example #16
0
/* Return a string representation of the socket address passed. The return
 * value is allocated with malloc() */
static unsigned char *getaddrstring(struct sockaddr *addr,
    int withport)
{

    char hbuf[NI_MAXHOST], sbuf[NI_MAXSERV];
    char *retstring = NULL;
    int ret;
    unsigned int len;

    len = sizeof(struct sockaddr_storage);
    /* Some platforms such as Solaris 8 require that len is the length
     * of the specific structure. Some older linux systems (glibc 2.1.3
     * such as debian potato) have sockaddr_storage.__ss_family instead
     * but we'll ignore them */
#  ifdef HAVE_STRUCT_SOCKADDR_STORAGE_SS_FAMILY
    if (addr->ss_family == AF_INET)
    {
        len = sizeof(struct sockaddr_in);
    }
#   ifdef AF_INET6
    if (addr->ss_family == AF_INET6)
    {
        len = sizeof(struct sockaddr_in6);
    }
#   endif
#  endif

    ret = getnameinfo((struct sockaddr *) addr, len, hbuf, sizeof(hbuf),
        sbuf, sizeof(sbuf), NI_NUMERICSERV | NI_NUMERICHOST);

    if (ret != 0)
    {
        /* This is a fairly bad failure - it'll fallback to IP if it
         * just can't resolve */
        _psTrace("failed lookup for getaddrstring");
        strcpy(hbuf, "UNKNOWN");
        strcpy(sbuf, "?");
    }

    if (withport)
    {
        len = strlen(hbuf) + 2 + strlen(sbuf);
        retstring = (char *) psMalloc(MATRIX_NO_POOL, len);
        snprintf(retstring, len, "%s:%s", hbuf, sbuf);
    }
    else
    {
        retstring = strdup(hbuf);
    }

    return (unsigned char *) retstring;
}
Example #17
0
/* SessionID management functions for clients that wish to perform
	session resumption.  This structure handles both the traditional resumption
	mechanism and the server-stateless session ticket mechanism
*/
int32 matrixSslNewSessionId(sslSessionId_t **sess, void *poolUserPtr)
{
	sslSessionId_t	*ses;
	psPool_t		*pool = NULL;

	if ((ses = psMalloc(pool, sizeof(sslSessionId_t))) == NULL) {
		return PS_MEM_FAIL;
	}
	memset(ses, 0x0, sizeof(sslSessionId_t));
	ses->pool = pool;
	*sess = ses;
	return PS_SUCCESS;
}
Example #18
0
File: osdep.c Project: texane/bano
/*
    Memory info:
    Caller must free 'buf' parameter on success
    Callers do not need to free buf on function failure
*/
int32 psGetFileBuf(psPool_t *pool, const char *fileName, unsigned char **buf,
                int32 *bufLen)
{
	DWORD	dwAttributes;
	HANDLE	hFile;
	int32	size;
	DWORD	tmp = 0;

	*bufLen = 0;
	*buf = NULL;

	dwAttributes = GetFileAttributesA(fileName);
	if (dwAttributes != 0xFFFFFFFF && dwAttributes & FILE_ATTRIBUTE_DIRECTORY) {
		psTraceStrCore("Unable to find %s\n", (char*)fileName);
        return PS_PLATFORM_FAIL;
	}

	if ((hFile = CreateFileA(fileName, GENERIC_READ,
			FILE_SHARE_READ && FILE_SHARE_WRITE, NULL, OPEN_EXISTING,
			FILE_ATTRIBUTE_NORMAL, NULL)) == INVALID_HANDLE_VALUE) {
		psTraceStrCore("Unable to open %s\n", (char*)fileName);
        return PS_PLATFORM_FAIL;
	}
	
/*
 *	 Get the file size.
 */
	size = GetFileSize(hFile, NULL);

	*buf = psMalloc(pool, size + 1);
	if (*buf == NULL) {
		CloseHandle(hFile);
		return PS_MEM_FAIL;
	}
	memset(*buf, 0x0, size + 1);
	
	while (*bufLen < size) { 
		if (ReadFile(hFile, *buf + *bufLen,
				(size-*bufLen > 512 ? 512 : size-*bufLen), &tmp, NULL)
				== FALSE) {
			psFree(*buf);
			psTraceStrCore("Unable to read %s\n", (char*)fileName);
			CloseHandle(hFile);
			return PS_PLATFORM_FAIL;
		}
		*bufLen += (int32)tmp;
	}

	CloseHandle(hFile);
	return PS_SUCCESS;
}
Example #19
0
File: tls.c Project: B-Rich/NUL
/*
	Allocate a tlsExtenstion_t structure
*/
int32 matrixSslNewHelloExtension(tlsExtension_t **extension)
{
	psPool_t		*pool = NULL;
	tlsExtension_t	*ext;
	
   
    ext = psMalloc(pool, sizeof(tlsExtension_t));
    if (ext == NULL) {
        return PS_MEM_FAIL;
    }
    memset(ext, 0x0, sizeof(tlsExtension_t));
    ext->pool = pool;
   
    *extension = ext;
    return PS_SUCCESS;
}
Example #20
0
/*
	Must call to allocate the key structure now.  After which, LoadRsaKeys,
	LoadDhParams and/or LoadPskKey can be called 
	
	Memory info:
	Caller must free keys with matrixSslDeleteKeys on function success
	Caller does not need to free keys on function failure
*/
int32 matrixSslNewKeys(sslKeys_t **keys)
{
	psPool_t	*pool = NULL;
	sslKeys_t	*lkeys;
	
	
	lkeys = psMalloc(pool, sizeof(sslKeys_t));
	if (lkeys == NULL) {
		return PS_MEM_FAIL;
	}
	memset(lkeys, 0x0, sizeof(sslKeys_t));
	lkeys->pool = pool;
	
	*keys = lkeys;
	return PS_SUCCESS;
}
Example #21
0
/*
	Binary to struct helper for RSA public keys
*/
int32 matrixRsaParsePubKey(psPool_t *pool, unsigned char *keyBuf,
							  int32 keyBufLen, sslRsaKey_t **key)
{
/*
	Now have the DER stream to extract from in asnp
 */
	*key = psMalloc(pool, sizeof(sslRsaKey_t));
	if (*key == NULL) {
		return -8; /* SSL_MEM_ERROR */
	}
	memset(*key, 0x0, sizeof(sslRsaKey_t));

	if (getPubKey(pool, &keyBuf, keyBufLen, *key) < 0) {
		matrixRsaFreeKey(*key);
		*key = NULL;
		matrixStrDebugMsg("Unable to ASN parse public key\n", NULL);
		return -1;
	}
	return 0;
}
Example #22
0
/* If the required size is known, grow the buffer here so the caller doesn't
	have to go through the REQUEST_RECV logic of matrixSslReceivedData

	The return value MAY be larger than the requested size if the inbuf
	is already larger than what was requested.
*/
int32 matrixSslGetReadbufOfSize(ssl_t *ssl, int32 size, unsigned char **buf)
{
	unsigned char *p;

	if (!ssl || !buf) {
		return PS_ARG_FAIL;
	}
	psAssert(ssl && ssl->insize > 0 && ssl->inbuf != NULL);

	if ((ssl->insize - ssl->inlen) >= size) {
		/* Already enough room in current buffer */
		return matrixSslGetReadbuf(ssl, buf);
	}

	/* Going to have to grow... but do we have to realloc to save data? */
	if (ssl->inlen == 0) {
		/* buffer is empty anyway so can free before alloc and help keep high
			water mark down */
		psFree(ssl->inbuf, ssl->bufferPool);
		ssl->inbuf = NULL;
		if ((ssl->inbuf = psMalloc(ssl->bufferPool, size)) == NULL) {
			ssl->insize = 0;
			return PS_MEM_FAIL;
		}
		ssl->insize = size;
		*buf = ssl->inbuf;
		return ssl->insize;
	} else {
		/* realloc with: total size = current size + requested size */
		if ((p = psRealloc(ssl->inbuf, ssl->inlen + size, ssl->bufferPool))
				== NULL) {
			ssl->inbuf = NULL; ssl->insize = 0; ssl->inlen = 0;
			return PS_MEM_FAIL;
		}
		ssl->inbuf = p;
		ssl->insize = ssl->inlen + size;
		*buf = ssl->inbuf + ssl->inlen;
		return size;
	}
	return PS_FAILURE; /* can't hit */
}
Example #23
0
/*
    Public GCM encrypt function.  This will just perform the encryption.  The
    tag should be fetched with psAesGetGCMTag
 */
void psAesEncryptGCM(psAesGcm_t *ctx, const unsigned char *pt, unsigned char *ct, uint32_t len)
{
    unsigned long long ciphertext_len;
    unsigned char *resultEncryption;

    resultEncryption = psMalloc(NULL, len + sizeof(ctx->Tag));

    /* libsodium will put the (cipher text and the tag) in the result, */
    crypto_aead_aes256gcm_encrypt_afternm(resultEncryption, &ciphertext_len,
        (const unsigned char *) pt, (unsigned long long) len,
        (const unsigned char *) ctx->Aad, (unsigned long long) ctx->AadLen,
        NULL, (const unsigned char *) ctx->IV,
        (crypto_aead_aes256gcm_state *) &(ctx->libSodiumCtx));

    /* Copy the authentication tag in context to be able to retrieve it later */
    memcpy(ctx->Tag, (resultEncryption + len), sizeof(ctx->Tag));

    /* Copy the ciphertext in destination */
    memcpy(ct, resultEncryption, len);

    psFree(resultEncryption, NULL);
}
Example #24
0
/*
    Get session information from the ssl structure and populate the given
    session structure.  Session will contain a copy of the relevant session
    information, suitable for creating a new, resumed session.
*/
int32 matrixSslGetSessionId(ssl_t *ssl, sslSessionId_t **session)
{
    sslSessionId_t *lsession;

    if (ssl == NULL || ssl->flags & SSL_FLAGS_SERVER) {
        return -1;
    }

    if (ssl->cipher != NULL && ssl->cipher->id != SSL_NULL_WITH_NULL_NULL &&
            ssl->sessionIdLen == SSL_MAX_SESSION_ID_SIZE) {
        *session = lsession = psMalloc(PEERSEC_BASE_POOL,
            sizeof(sslSessionId_t));
        if (lsession == NULL) {
            return SSL_MEM_ERROR;
        }
        lsession->cipherId = ssl->cipher->id;
        memcpy(lsession->id, ssl->sessionId, ssl->sessionIdLen);
        memcpy(lsession->masterSecret, ssl->sec.masterSecret,
            SSL_HS_MASTER_SIZE);
        return 0;
    }
    return -1;
}
Example #25
0
/*
    New SSL protocol context
    This structure is associated with a single SSL connection.  Each socket
    using SSL should be associated with a new SSL context.

    certBuf and privKey ARE NOT duplicated within the server context, in order
    to minimize memory usage with multiple simultaneous requests.  They must
    not be deleted by caller until all server contexts using them are deleted.
*/
int32 matrixSslNewSession(ssl_t **ssl, sslKeys_t *keys, sslSessionId_t *session,
                        int32 flags)
{
    psPool_t    *pool = NULL;
    ssl_t       *lssl;

/*
    First API level chance to make sure a user is not attempting to use
    client or server support that was not built into this library compile
*/
#ifndef USE_SERVER_SIDE_SSL
    if (flags & SSL_FLAGS_SERVER) {
        matrixStrDebugMsg("MatrixSSL lib not compiled with server support\n",
            NULL);
        return -1;
    }
#endif
#ifndef USE_CLIENT_SIDE_SSL
    if (!(flags & SSL_FLAGS_SERVER)) {
        matrixStrDebugMsg("MatrixSSL lib not compiled with client support\n",
            NULL);
        return -1;
    }
#endif
    if (flags & SSL_FLAGS_CLIENT_AUTH) {
        matrixStrDebugMsg("MatrixSSL lib not compiled with client " \
            "authentication support\n", NULL);
        return -1;
    }

    if (flags & SSL_FLAGS_SERVER) {
        if (keys == NULL) {
            matrixStrDebugMsg("NULL keys in  matrixSslNewSession\n", NULL);
            return -1;
        }
        if (session != NULL) {
            matrixStrDebugMsg("Server session must be NULL\n", NULL);
            return -1;
        }
    }

    *ssl = lssl = psMalloc(pool, sizeof(ssl_t));
    if (lssl == NULL) {
        return SSL_MEM_ERROR;
    }
    memset(lssl, 0x0, sizeof(ssl_t));

    lssl->pool = pool;
    lssl->cipher = sslGetCipherSpec(SSL_NULL_WITH_NULL_NULL);
    sslActivateReadCipher(lssl);
    sslActivateWriteCipher(lssl);
    sslActivatePublicCipher(lssl);

    lssl->recordHeadLen = SSL3_HEADER_LEN;
    lssl->hshakeHeadLen = SSL3_HANDSHAKE_HEADER_LEN;

    if (flags & SSL_FLAGS_SERVER) {
        lssl->flags |= SSL_FLAGS_SERVER;
/*
        Client auth can only be requested by server, not set by client
*/
        if (flags & SSL_FLAGS_CLIENT_AUTH) {
            lssl->flags |= SSL_FLAGS_CLIENT_AUTH;
        }
        lssl->hsState = SSL_HS_CLIENT_HELLO;
    } else {
/*
        Client is first to set protocol version information based on
        compile and/or the 'flags' parameter so header information in
        the handshake messages will be correctly set.
*/
        lssl->majVer = SSL3_MAJ_VER;
        lssl->minVer = SSL3_MIN_VER;
        lssl->hsState = SSL_HS_SERVER_HELLO;
        if (session != NULL && session->cipherId != SSL_NULL_WITH_NULL_NULL) {
            lssl->cipher = sslGetCipherSpec(session->cipherId);
            if (lssl->cipher == NULL) {
                matrixStrDebugMsg("Invalid session id to matrixSslNewSession\n",
                    NULL);
            } else {
                memcpy(lssl->sec.masterSecret, session->masterSecret,
                    SSL_HS_MASTER_SIZE);
                lssl->sessionIdLen = SSL_MAX_SESSION_ID_SIZE;
                memcpy(lssl->sessionId, session->id, SSL_MAX_SESSION_ID_SIZE);
            }
        }
    }
    lssl->err = SSL_ALERT_NONE;
    lssl->keys = keys;

    return 0;
}
Example #26
0
/*
	Parse an X509 ASN.1 certificate stream
	http://www.faqs.org/rfcs/rfc2459.html section 4.1
*/
int32 matrixX509ParseCert(psPool_t *pool, unsigned char *pp, int32 size, 
						sslRsaCert_t **outcert)
{
	sslRsaCert_t		*cert;
	sslMd5Context_t		md5Ctx;
	sslSha1Context_t	sha1Ctx;
	unsigned char		*p, *end, *certStart, *certEnd;
	int32				certLen, len, parsing;
#ifdef USE_MD2
	sslMd2Context_t		md2Ctx;
#endif /* USE_MD2 */

/*
	Allocate the cert structure right away.  User MUST always call
	matrixX509FreeCert regardless of whether this function succeeds.
	memset is important because the test for NULL is what is used
	to determine what to free
*/
	*outcert = cert = psMalloc(pool, sizeof(sslRsaCert_t));
	if (cert == NULL) {
		return -8; /* SSL_MEM_ERROR */
	}
	memset(cert, '\0', sizeof(sslRsaCert_t));

	p = pp;
	end = p + size;
/*
		Certificate  ::=  SEQUENCE  {
		tbsCertificate		TBSCertificate,
		signatureAlgorithm	AlgorithmIdentifier,
		signatureValue		BIT STRING	}
*/
	parsing = 1;
	while (parsing) {
		if (getSequence(&p, (int32)(end - p), &len) < 0) {
			matrixStrDebugMsg("Initial cert parse error\n", NULL);
			return -1;
		}
		certStart = p;
/*	
		TBSCertificate  ::=  SEQUENCE  {
		version			[0]		EXPLICIT Version DEFAULT v1,
		serialNumber			CertificateSerialNumber,
		signature				AlgorithmIdentifier,
		issuer					Name,
		validity				Validity,
		subject					Name,
		subjectPublicKeyInfo	SubjectPublicKeyInfo,
		issuerUniqueID	[1]		IMPLICIT UniqueIdentifier OPTIONAL,
							-- If present, version shall be v2 or v3
		subjectUniqueID	[2]	IMPLICIT UniqueIdentifier OPTIONAL,
							-- If present, version shall be v2 or v3
		extensions		[3]	EXPLICIT Extensions OPTIONAL
							-- If present, version shall be v3	}
*/
		if (getSequence(&p, (int32)(end - p), &len) < 0) {
			matrixStrDebugMsg("ASN sequence parse error\n", NULL);
			return -1;
		}
		certEnd = p + len;
		certLen = (int32)(certEnd - certStart);

/*
		Version  ::=  INTEGER  {  v1(0), v2(1), v3(2)  }
*/
		if (getExplicitVersion(&p, (int32)(end - p), 0, &cert->version) < 0) {
			matrixStrDebugMsg("ASN version parse error\n", NULL);
			return -1;
		}
		if (cert->version != 2) {
			matrixIntDebugMsg("Warning: non-v3 certificate version: %d\n",
			cert->version);
		}
/*
		CertificateSerialNumber  ::=  INTEGER
*/
		if (getSerialNum(pool, &p, (int32)(end - p), &cert->serialNumber,
				&cert->serialNumberLen) < 0) {
			matrixStrDebugMsg("ASN serial number parse error\n", NULL);
			return -1;
		}
/*
		AlgorithmIdentifier  ::=  SEQUENCE  {
		algorithm				OBJECT IDENTIFIER,
		parameters				ANY DEFINED BY algorithm OPTIONAL }
*/
		if (getAlgorithmIdentifier(&p, (int32)(end - p),
				&cert->certAlgorithm, 0) < 0) {
			return -1;
		}
/*
		Name ::= CHOICE {
		RDNSequence }

		RDNSequence ::= SEQUENCE OF RelativeDistinguishedName

		RelativeDistinguishedName ::= SET OF AttributeTypeAndValue

		AttributeTypeAndValue ::= SEQUENCE {
		type	AttributeType,
		value	AttributeValue }

		AttributeType ::= OBJECT IDENTIFIER

		AttributeValue ::= ANY DEFINED BY AttributeType
*/
		if (getDNAttributes(pool, &p, (int32)(end - p), &cert->issuer) < 0) {
			return -1;
		}
/*
		Validity ::= SEQUENCE {
		notBefore	Time,
		notAfter	Time	}
*/
		if (getValidity(pool, &p, (int32)(end - p), &cert->notBefore,
				&cert->notAfter) < 0) {
			return -1;
		}
/*
		Subject DN
*/
		if (getDNAttributes(pool, &p, (int32)(end - p), &cert->subject) < 0) {
			return -1;
		}
/*
		SubjectPublicKeyInfo  ::=  SEQUENCE  {
		algorithm			AlgorithmIdentifier,
		subjectPublicKey	BIT STRING	}
*/
		if (getSequence(&p, (int32)(end - p), &len) < 0) {
			return -1;
		}
		if (getAlgorithmIdentifier(&p, (int32)(end - p),
				&cert->pubKeyAlgorithm, 1) < 0) {
			return -1;
		}
		if (getPubKey(pool, &p, (int32)(end - p), &cert->publicKey) < 0) {
			return -1;
		}
/*
		As the next three values are optional, we can do a specific test here
*/
		if (*p != (ASN_SEQUENCE | ASN_CONSTRUCTED)) {
			if (getImplicitBitString(pool, &p, (int32)(end - p), IMPLICIT_ISSUER_ID,
					&cert->uniqueUserId, &cert->uniqueUserIdLen) < 0 ||
				getImplicitBitString(pool, &p, (int32)(end - p), IMPLICIT_SUBJECT_ID,
					&cert->uniqueSubjectId, &cert->uniqueSubjectIdLen) < 0 ||
				getExplicitExtensions(pool, &p, (int32)(end - p), EXPLICIT_EXTENSION,
					&cert->extensions) < 0) {
				matrixStrDebugMsg("There was an error parsing a certificate\n", NULL);
				matrixStrDebugMsg("extension.  This is likely caused by an\n", NULL);
				matrixStrDebugMsg("extension format that is not currently\n", NULL);
				matrixStrDebugMsg("recognized.  Please email [email protected]\n", NULL);
				matrixStrDebugMsg("to add support for the extension.\n\n", NULL);
				return -1;
			}
		}
/*
		This is the end of the cert.  Do a check here to be certain
*/
		if (certEnd != p) {
			return -1;
		}
/*
		Certificate signature info
*/
		if (getAlgorithmIdentifier(&p, (int32)(end - p),
				&cert->sigAlgorithm, 0) < 0) {
			return -1;
		}
/*
		Signature algorithm must match that specified in TBS cert
*/
		if (cert->certAlgorithm != cert->sigAlgorithm) {
			matrixStrDebugMsg("Parse error: mismatched signature type\n", NULL);
			return -1; 
		}
/*
		Compute the hash of the cert here for CA validation
*/
		if (cert->certAlgorithm == OID_RSA_MD5) {
			matrixMd5Init(&md5Ctx);
			matrixMd5Update(&md5Ctx, certStart, certLen);
			matrixMd5Final(&md5Ctx, cert->sigHash);
		} else if (cert->certAlgorithm == OID_RSA_SHA1) {
			matrixSha1Init(&sha1Ctx);
			matrixSha1Update(&sha1Ctx, certStart, certLen);
			matrixSha1Final(&sha1Ctx, cert->sigHash);
		}
#ifdef USE_MD2
		else if (cert->certAlgorithm == OID_RSA_MD2) {
			matrixMd2Init(&md2Ctx);
			matrixMd2Update(&md2Ctx, certStart, certLen);
			matrixMd2Final(&md2Ctx, cert->sigHash);
		}
#endif /* USE_MD2 */

		if (getSignature(pool, &p, (int32)(end - p), &cert->signature,
				&cert->signatureLen) < 0) {
			return -1;
		}
/*
		The ability to parse additional chained certs is a PKI product
		feature addition.  Chaining in MatrixSSL is handled internally.
*/
		if (p != end) {
			cert->next = psMalloc(pool, sizeof(sslRsaCert_t));
			cert = cert->next;
			memset(cert, '\0', sizeof(sslRsaCert_t));
		} else {
			parsing = 0;
		}
	}
		
	return (int32)(p - pp);
}
Example #27
0
/*
	Preferred version for commercial users who make use of memory pools.

	This use of the sslKeys_t param implies this is for use in the MatrixSSL
	product (input to matrixSslNewSession).  However, we didn't want to
	expose this API at the matrixSsl.h level due to the pool parameter. This
	is strictly an API that commerical users will have access to.
*/
int32 matrixRsaParseKeysMem(psPool_t *pool, sslKeys_t **keys,
			unsigned char *certBuf,	int32 certLen, unsigned char *privBuf,
			int32 privLen, unsigned char *trustedCABuf, int32 trustedCALen)
{
	sslKeys_t		*lkeys;
	sslLocalCert_t	*current, *next;
	unsigned char	*binPtr;
	int32			len, lenOh, i;
#ifdef USE_CLIENT_SIDE_SSL
	sslRsaCert_t	*currentCA, *nextCA;
#endif /* USE_CLIENT_SIDE_SSL */

	*keys = lkeys = psMalloc(pool, sizeof(sslKeys_t));
	if (lkeys == NULL) {
		return -8; /* SSL_MEM_ERROR */
	}
	memset(lkeys, 0x0, sizeof(sslKeys_t));
/*
	The buffers are just the ASN.1 streams so the intermediate parse
	that used to be here is gone.  Doing a straight memcpy for this
	and passing that along to X509ParseCert
*/
	i = 0;
	current = &lkeys->cert;
	binPtr = certBuf;
/*
	Need to check for a chain here.  Only way to do this is to read off the
	length id from the DER stream for each.  The chain must be just a stream
	of DER certs with the child-most cert always first.
*/
	while (certLen > 0) {
		if (getSequence(&certBuf, certLen, &len) < 0) {
			matrixStrDebugMsg("Unable to parse length of cert stream\n", NULL);
			matrixRsaFreeKeys(lkeys);
			return -1;
		}
/*
		Account for the overhead of storing the length itself
*/
		lenOh = (int32)(certBuf - binPtr);
		len += lenOh;
		certBuf -= lenOh;
/*
		First cert is already malloced
*/
		if (i > 0) {
			next = psMalloc(pool, sizeof(sslLocalCert_t));
			memset(next, 0x0, sizeof(sslLocalCert_t));
			current->next = next;
			current = next;
		}
		current->certBin = psMalloc(pool, len);
		memcpy(current->certBin, certBuf, len);
		current->certLen = len;
		certLen -= len;
		certBuf += len;
		binPtr = certBuf;
		i++;
	}

/*
	Parse private key
*/
	if (privLen > 0) {
		if (matrixRsaParsePrivKey(pool, privBuf, privLen,
				&lkeys->cert.privKey) < 0) {
			matrixStrDebugMsg("Error reading private key mem\n", NULL);
			matrixRsaFreeKeys(lkeys);
			return -1;
		}
	}


/*
	Trusted CAs
*/
#ifdef USE_CLIENT_SIDE_SSL
	if (trustedCABuf != NULL && trustedCALen > 0) {
		i = 0;
		binPtr = trustedCABuf;
		currentCA = NULL;
/*
		Need to check for list here.  Only way to do this is to read off the
		length id from the DER stream for each.
*/
		while (trustedCALen > 0) {
			if (getSequence(&trustedCABuf, trustedCALen, &len) < 0) {
				matrixStrDebugMsg("Unable to parse length of CA stream\n",
					NULL);
				matrixRsaFreeKeys(lkeys);
				return -1;
			}
/*
			Account for the overhead of storing the length itself
*/
			lenOh = (int32)(trustedCABuf - binPtr);
			len += lenOh;
			trustedCABuf -= lenOh;

			if (matrixX509ParseCert(pool, trustedCABuf, len, &currentCA) < 0) {
				matrixStrDebugMsg("Error parsing CA cert\n", NULL);
				matrixRsaFreeKeys(lkeys);
				return -1;
			}
/*
			First cert should be assigned to lkeys
*/
			if (i == 0) {
				lkeys->caCerts = currentCA;
				nextCA = lkeys->caCerts;
			} else {
				nextCA->next = currentCA;
				nextCA = currentCA;
			}
			currentCA = currentCA->next;
			trustedCALen -= len;
			trustedCABuf += len;
			binPtr = trustedCABuf;
			i++;
		}
	}
#endif /* USE_CLIENT_SIDE_SSL */

	return 0;
}
Example #28
0
/*
 *	Public API to return a binary buffer from a cert.  Suitable to send
 *	over the wire.  Caller must free 'out' if this function returns success (0)
 *	Parse .pem files according to http://www.faqs.org/rfcs/rfc1421.html
 */
int32 matrixX509ReadCert(psPool_t *pool, const char *fileName,
					unsigned char **out, int32 *outLen, sslChainLen_t *chain)
{
	int32			certBufLen, rc, certChainLen, i;
	unsigned char	*oneCert[MAX_CHAIN_LENGTH];
	unsigned char	*certPtr, *tmp;
	char			*certFile, *start, *end, *certBuf;
	const char		sep[] = ";";

/*
	Init chain array and output params
*/
	for (i=0; i < MAX_CHAIN_LENGTH; i++) {
		oneCert[i] = NULL;
		(*chain)[i] = 0;
	}
	*outLen = certChainLen = i = 0;
	rc = -1;

/*
	For PKI product purposes, this routine now accepts a chain of certs.
*/
	if (fileName != NULL) {
		fileName += parseList(pool, fileName, sep, &certFile);
	} else {
		return 0;
	}

	while (certFile != NULL) {
	
		if (i == MAX_CHAIN_LENGTH) {
			matrixIntDebugMsg("Exceeded maximum cert chain length of %d\n",
				MAX_CHAIN_LENGTH);
			psFree(certFile);
			rc = -1;
			goto err;
		}
		if ((rc = psGetFileBin(pool, certFile, (unsigned char**)&certBuf,
				&certBufLen)) < 0) {
			matrixStrDebugMsg("Couldn't open file %s\n", certFile);
			goto err;
		}
		psFree(certFile);
		certPtr = (unsigned char*)certBuf;
		start = end = certBuf;

		while (certBufLen > 0) {
			if (((start = strstr(certBuf, "-----BEGIN")) != NULL) && 
					((start = strstr(certBuf, "CERTIFICATE-----")) != NULL) &&
					(end = strstr(start, "-----END")) != NULL) {
				start += strlen("CERTIFICATE-----");
				(*chain)[i] = (int32)(end - start);
				end += strlen("-----END CERTIFICATE-----");
				while (*end == '\r' || *end == '\n' || *end == '\t' || *end == ' ') {
					end++;
				}
			} else {
				psFree(certPtr);
				rc = -1;
				goto err;
			}
			oneCert[i] = psMalloc(pool, (*chain)[i]);
			certBufLen -= (int32)(end - certBuf);
			certBuf = end;
			memset(oneCert[i], '\0', (*chain)[i]);

			if (ps_base64_decode((unsigned char*)start, (*chain)[i], oneCert[i],
					&(*chain)[i]) != 0) {
				psFree(certPtr);
				matrixStrDebugMsg("Unable to base64 decode certificate\n", NULL);
				rc = -1;
				goto err;
			}
			certChainLen += (*chain)[i];
			i++;
			if (i == MAX_CHAIN_LENGTH) { 
				matrixIntDebugMsg("Exceeded maximum cert chain length of %d\n", 
					MAX_CHAIN_LENGTH); 
				psFree(certPtr); 
				rc = -1; 
				goto err; 
			} 
		}
		psFree(certPtr);
/*
		Check for more files
*/
		fileName += parseList(pool, fileName, sep, &certFile);
	}

	*outLen = certChainLen;
/*
	Don't bother stringing them together if only one was passed in
*/
	if (i == 1) {
		sslAssert(certChainLen == (*chain)[0]);
		*out = oneCert[0];
		return 0;
	} else {
		*out = tmp = psMalloc(pool, certChainLen);
		for (i=0; i < MAX_CHAIN_LENGTH; i++) {
			if (oneCert[i]) {
				memcpy(tmp, oneCert[i], (*chain)[i]);
				tmp += (*chain)[i];
			}
		}
		rc = 0;
	}

err:
	for (i=0; i < MAX_CHAIN_LENGTH; i++) {
		if (oneCert[i]) psFree(oneCert[i]);
	}
	return rc;
}
Example #29
0
/*
	Preferred version for commercial users who make use of memory pools.

	This use of the sslKeys_t param implies this is for use in the MatrixSSL
	product (input to matrixSslNewSession).  However, we didn't want to
	expose this API at the matrixSsl.h level due to the pool parameter. This
	is strictly an API that commerical users will have access to
*/
int32 matrixRsaReadKeysEx(psPool_t *pool, sslKeys_t **keys,
				const char *certFile, const char *privFile,
				const char *privPass, const char *trustedCAFiles)
{
	sslKeys_t		*lkeys;
	unsigned char	*privKeyMem;
	int32			rc, privKeyMemLen;
#ifdef USE_CLIENT_SIDE_SSL
	sslRsaCert_t	*currCert, *prevCert = NULL;
	unsigned char	*caCert, *caStream;
	sslChainLen_t	chain;
	int32			caCertLen, first, i;
#endif /* USE_CLIENT_SIDE_SSL */

	*keys = lkeys = psMalloc(pool, sizeof(sslKeys_t));
	if (lkeys == NULL) {
		return -8; /* SSL_MEM_ERROR */
	}
	memset(lkeys, 0x0, sizeof(sslKeys_t));
/*
	Load certificate files.  Any additional certificate files should chain
	to the root CA held on the other side.
*/
	rc = readCertChain(pool, certFile, &lkeys->cert);
	if (rc < 0 ) {
		matrixRsaFreeKeys(lkeys);
		return rc;
	}
/*
	The first cert in certFile must be associated with the provided
	private key. 
*/
	if (privFile) {
		rc = matrixRsaReadPrivKey(pool, privFile, privPass, &privKeyMem,
			&privKeyMemLen);
		if (rc < 0) {
			matrixStrDebugMsg("Error reading private key file: %s\n",
				(char*)privFile);
			matrixRsaFreeKeys(lkeys);
			return rc;
		}
		rc = matrixRsaParsePrivKey(pool, privKeyMem, privKeyMemLen,
			&lkeys->cert.privKey);
		if (rc < 0) {
			matrixStrDebugMsg("Error parsing private key file: %s\n",
				(char*)privFile);
			psFree(privKeyMem);
			matrixRsaFreeKeys(lkeys);
			return rc;
		}
		psFree(privKeyMem);
	}

#ifdef USE_CLIENT_SIDE_SSL
/*
	Now deal with Certificate Authorities
*/
	if (trustedCAFiles != NULL) {
		if (matrixX509ReadCert(pool, trustedCAFiles, &caCert, &caCertLen,
				&chain) < 0 || caCert == NULL) {
			matrixStrDebugMsg("Error reading CA cert files %s\n",
				(char*)trustedCAFiles);
			matrixRsaFreeKeys(lkeys);
			return -1;
		}

		caStream = caCert;
		i = first = 0;
		while (chain[i] != 0) {
/*
			Don't allow one bad cert to ruin the whole bunch if possible
*/
			if (matrixX509ParseCert(pool, caStream, chain[i], &currCert) < 0) {
				matrixX509FreeCert(currCert);
				matrixStrDebugMsg("Error parsing CA cert %s\n",
					(char*)trustedCAFiles);
				caStream += chain[i]; caCertLen -= chain[i];
				i++;
				continue;
			}
		
			if (first == 0) {
				lkeys->caCerts = currCert;
			} else {
				prevCert->next = currCert;
			}
			first++;
			prevCert = currCert;
			currCert = NULL;
			caStream += chain[i]; caCertLen -= chain[i];
			i++;
		}
		sslAssert(caCertLen == 0);
		psFree(caCert);
	}
/*
	Check to see that if a set of CAs were passed in at least
	one ended up being valid.
*/
	if (trustedCAFiles != NULL && lkeys->caCerts == NULL) {
		matrixStrDebugMsg("No valid CA certs in %s\n",
			(char*)trustedCAFiles);
		matrixRsaFreeKeys(lkeys);
		return -1;
	}
#endif /* USE_CLIENT_SIDE_SSL */
	return 0; 
}
Example #30
0
/*
	Calls a user defined callback to allow for manual validation of the
	certificate.
*/
int32 matrixX509UserValidator(psPool_t *pool, sslRsaCert_t *subjectCert,
			int32 (*certValidator)(sslCertInfo_t *t, void *arg), void *arg)
{
	sslCertInfo_t	*cert, *current, *next;
	int32			rc;

	if (certValidator == NULL) {
		return 0;
	}
/*
	Pass the entire certificate chain to the user callback.
*/
	current = cert = psMalloc(pool, sizeof(sslCertInfo_t));
	if (current == NULL) {
		return -8; /* SSL_MEM_ERROR */
	}
	memset(cert, 0x0, sizeof(sslCertInfo_t));
	while (subjectCert) {
		
		current->issuer.commonName = subjectCert->issuer.commonName;
		current->issuer.country = subjectCert->issuer.country;
		current->issuer.locality = subjectCert->issuer.locality;
		current->issuer.organization = subjectCert->issuer.organization;
		current->issuer.orgUnit = subjectCert->issuer.orgUnit;
		current->issuer.state = subjectCert->issuer.state;

		current->subject.commonName = subjectCert->subject.commonName;
		current->subject.country = subjectCert->subject.country;
		current->subject.locality = subjectCert->subject.locality;
		current->subject.organization = subjectCert->subject.organization;
		current->subject.orgUnit = subjectCert->subject.orgUnit;
		current->subject.state = subjectCert->subject.state;

		current->serialNumber = subjectCert->serialNumber;
		current->serialNumberLen = subjectCert->serialNumberLen;
		current->verified = subjectCert->valid;
		current->notBefore = subjectCert->notBefore;
		current->notAfter = subjectCert->notAfter;

		current->subjectAltName.dns = (char*)subjectCert->extensions.san.dns;
		current->subjectAltName.uri = (char*)subjectCert->extensions.san.uri;
		current->subjectAltName.email = (char*)subjectCert->extensions.san.email;
	
		if (subjectCert->certAlgorithm == OID_RSA_MD5 ||
				subjectCert->certAlgorithm == OID_RSA_MD2) {
			current->sigHashLen = SSL_MD5_HASH_SIZE;
		} else if (subjectCert->certAlgorithm == OID_RSA_SHA1) {
			current->sigHashLen = SSL_SHA1_HASH_SIZE;
		}
		current->sigHash = (char*)subjectCert->sigHash;
		if (subjectCert->next) {
			next = psMalloc(pool, sizeof(sslCertInfo_t));
			if (next == NULL) {
				while (cert) {
					next = cert->next;
					psFree(cert);
					cert = next;
				}
				return -8; /* SSL_MEM_ERROR */
			}
			memset(next, 0x0, sizeof(sslCertInfo_t));
			current->next = next;
			current = next;
		}
		subjectCert = subjectCert->next;
	}
/*
	The user callback
*/
	rc = certValidator(cert, arg);
/*
	Free the chain
*/
	while (cert) {
		next = cert->next;
		psFree(cert);
		cert = next;
	}
	return rc;
}