#include "sslContext.h"
#include "sslUtils.h"
#include "sslMemory.h"
#include "sslDebug.h"
#include <sys/time.h>
#include <fcntl.h> // for open
#include <unistd.h> // for read
#include <errno.h> // for errno
#include <Security/SecFramework.h>
#include <Security/SecRandom.h>
#ifndef NDEBUG
void SSLDump(const unsigned char *data, unsigned long len)
{
unsigned long i;
for(i=0;i<len;i++)
{
if((i&0xf)==0) printf("%04lx :",i);
printf(" %02x", data[i]);
if((i&0xf)==0xf) printf("\n");
}
printf("\n");
}
#endif
unsigned int
SSLDecodeInt(const uint8_t *p, size_t length)
{
unsigned int val = 0;
assert(length > 0 && length <= 4); while (length--)
val = (val << 8) | *p++;
return val;
}
uint8_t *
SSLEncodeInt(uint8_t *p, unsigned int value, size_t length)
{
unsigned char *retVal = p + length;
assert(length > 0 && length <= 4); while (length--)
{ p[length] = (uint8_t)value;
value >>= 8;
}
return retVal;
}
size_t
SSLDecodeSize(const uint8_t *p, size_t length)
{
unsigned int val = 0;
assert(length > 0 && length <= 4); while (length--)
val = (val << 8) | *p++;
return val;
}
uint8_t *
SSLEncodeSize(uint8_t *p, size_t value, size_t length)
{
unsigned char *retVal = p + length;
assert(length > 0 && length <= 4); while (length--)
{ p[length] = (uint8_t)value;
value >>= 8;
}
return retVal;
}
uint8_t *
SSLEncodeUInt64(uint8_t *p, sslUint64 value)
{
p = SSLEncodeInt(p, value.high, 4);
return SSLEncodeInt(p, value.low, 4);
}
uint8_t *
SSLEncodeHandshakeHeader(SSLContext *ctx, SSLRecord *rec, SSLHandshakeType type, size_t msglen)
{
uint8_t *charPtr;
charPtr = rec->contents.data;
*charPtr++ = type;
charPtr = SSLEncodeSize(charPtr, msglen, 3);
if(rec->protocolVersion == DTLS_Version_1_0) {
charPtr = SSLEncodeInt(charPtr, ctx->hdskMessageSeq, 2);
charPtr = SSLEncodeInt(charPtr, 0, 3);
charPtr = SSLEncodeSize(charPtr, msglen, 3);
}
return charPtr;
}
void
IncrementUInt64(sslUint64 *v)
{ if (++v->low == 0)
++v->high;
}
#if ENABLE_DTLS
void
SSLDecodeUInt64(const uint8_t *p, size_t length, sslUint64 *v)
{
assert(length > 0 && length <= 8);
if(length<=4) {
v->low=SSLDecodeInt(p, length);
v->high=0;
} else {
v->high=SSLDecodeInt(p, length-4);
v->low=SSLDecodeInt(p+length-4, 4);
}
}
#endif
#ifdef USE_SSLCERTIFICATE
size_t
SSLGetCertificateChainLength(const SSLCertificate *c)
{
size_t rtn = 0;
while (c)
{
rtn++;
c = c->next;
}
return rtn;
}
OSStatus sslDeleteCertificateChain(
SSLCertificate *certs,
SSLContext *ctx)
{
SSLCertificate *cert;
SSLCertificate *nextCert;
assert(ctx != NULL);
cert=certs;
while(cert != NULL) {
nextCert = cert->next;
SSLFreeBuffer(&cert->derCert, ctx);
sslFree(cert);
cert = nextCert;
}
return noErr;
}
#endif
Boolean sslIsSessionActive(const SSLContext *ctx)
{
assert(ctx != NULL);
switch(ctx->state) {
case SSL_HdskStateUninit:
case SSL_HdskStateServerUninit:
case SSL_HdskStateClientUninit:
case SSL_HdskStateGracefulClose:
case SSL_HdskStateErrorClose:
return false;
default:
return true;
}
}
#if SSL_DEBUG
const char *protocolVersStr(SSLProtocolVersion prot)
{
switch(prot) {
case SSL_Version_Undetermined: return "SSL_Version_Undetermined";
case SSL_Version_2_0: return "SSL_Version_2_0";
case SSL_Version_3_0: return "SSL_Version_3_0";
case TLS_Version_1_0: return "TLS_Version_1_0";
case TLS_Version_1_1: return "TLS_Version_1_1";
case TLS_Version_1_2: return "TLS_Version_1_2";
default: sslErrorLog("protocolVersStr: bad prot\n"); return "BAD PROTOCOL";
}
return NULL;
}
#endif
OSStatus sslIoRead(
SSLBuffer buf,
size_t *actualLength,
SSLContext *ctx)
{
size_t dataLength = buf.length;
OSStatus ortn;
*actualLength = 0;
ortn = (ctx->ioCtx.read)(ctx->ioCtx.ioRef,
buf.data,
&dataLength);
*actualLength = dataLength;
return ortn;
}
OSStatus sslIoWrite(
SSLBuffer buf,
size_t *actualLength,
SSLContext *ctx)
{
size_t dataLength = buf.length;
OSStatus ortn;
*actualLength = 0;
ortn = (ctx->ioCtx.write)(ctx->ioCtx.ioRef,
buf.data,
&dataLength);
*actualLength = dataLength;
return ortn;
}
OSStatus sslTime(uint32_t *tim)
{
time_t t;
time(&t);
*tim = (uint32_t)t;
return noErr;
}
OSStatus sslRand(SSLContext *ctx, SSLBuffer *buf)
{
assert(buf != NULL);
assert(buf->data != NULL);
if(buf->length == 0) {
sslErrorLog("sslRand: zero buf->length\n");
return noErr;
}
return SecRandomCopyBytes(kSecRandomDefault, buf->length, buf->data) ? errSSLCrypto : noErr;
}
OSStatus sslVerifyProtVersion(
SSLContext *ctx,
SSLProtocolVersion peerVersion, SSLProtocolVersion *negVersion) {
if ((ctx->isDTLS)
? peerVersion > ctx->minProtocolVersion
: peerVersion < ctx->minProtocolVersion) {
return errSSLNegotiation;
}
if ((ctx->isDTLS)
? peerVersion < ctx->maxProtocolVersion
: peerVersion > ctx->maxProtocolVersion) {
if (ctx->protocolSide == kSSLClientSide) {
return errSSLNegotiation;
}
*negVersion = ctx->maxProtocolVersion;
} else {
*negVersion = peerVersion;
}
return noErr;
}
OSStatus sslGetMaxProtVersion(
SSLContext *ctx,
SSLProtocolVersion *version) {
if (ctx->maxProtocolVersion == SSL_Version_Undetermined)
return badReqErr;
*version = ctx->maxProtocolVersion;
return noErr;
}