Merge branch 'master' of github.com:cyassl/cyassl

This commit is contained in:
John Safranek 2013-08-23 10:12:17 -07:00
commit 0002ba4ee8
11 changed files with 339 additions and 22 deletions

View File

@ -289,6 +289,19 @@ then
fi
# Public Key Callbacks
AC_ARG_ENABLE([pkcallbacks],
[ --enable-pkcallbacks Enable Public Key Callbacks (default: disabled)],
[ ENABLED_PKCALLBACKS=$enableval ],
[ ENABLED_PKCALLBACKS=no ]
)
if test "$ENABLED_PKCALLBACKS" = "yes"
then
AM_CFLAGS="$AM_CFLAGS -DHAVE_PK_CALLBACKS"
fi
# SNIFFER
AC_ARG_ENABLE([sniffer],
[AS_HELP_STRING([--enable-sniffer],[ Enable CyaSSL sniffer support (default: disabled) ])],[
@ -1498,6 +1511,7 @@ echo " * CRL-MONITOR: $ENABLED_CRL_MONITOR"
echo " * Persistent session cache: $ENABLED_SAVESESSION"
echo " * Persistent cert cache: $ENABLED_SAVECERT"
echo " * Atomic User Record Layer: $ENABLED_ATOMICUSER"
echo " * Public Key Callbacks: $ENABLED_PKCALLBACKS"
echo " * NTRU: $ENABLED_NTRU"
echo " * SNI: $ENABLED_SNI"
echo " * Maximum Fragment Length: $ENABLED_MAX_FRAGMENT"

View File

@ -1245,8 +1245,8 @@ void ecc_free(ecc_key* key)
key The corresponding public ECC key
return MP_OKAY if successful (even if the signature is not valid)
*/
int ecc_verify_hash(const byte* sig, word32 siglen, byte* hash, word32 hashlen,
int* stat, ecc_key* key)
int ecc_verify_hash(const byte* sig, word32 siglen, const byte* hash,
word32 hashlen, int* stat, ecc_key* key)
{
ecc_point *mG, *mQ;
mp_int r;
@ -1324,7 +1324,7 @@ int ecc_verify_hash(const byte* sig, word32 siglen, byte* hash, word32 hashlen,
/* truncate down to byte size, may be all that's needed */
if ( (CYASSL_BIT_SIZE * hashlen) > orderBits)
hashlen = (orderBits + CYASSL_BIT_SIZE - 1)/CYASSL_BIT_SIZE;
err = mp_read_unsigned_bin(&e, (byte*)hash, hashlen);
err = mp_read_unsigned_bin(&e, hash, hashlen);
/* may still need bit truncation too */
if (err == MP_OKAY && (CYASSL_BIT_SIZE * hashlen) > orderBits)

View File

@ -356,7 +356,7 @@ CYASSL_LOCAL int ValidateDate(const byte* date, byte format, int dateType);
CYASSL_LOCAL int DecodeECC_DSA_Sig(const byte* sig, word32 sigLen,
mp_int* r, mp_int* s);
/* private key helpers */
CYASSL_LOCAL int EccPrivateKeyDecode(const byte* input,word32* inOutIdx,
CYASSL_API int EccPrivateKeyDecode(const byte* input,word32* inOutIdx,
ecc_key*,word32);
#endif

View File

@ -91,8 +91,8 @@ CYASSL_API
int ecc_sign_hash(const byte* in, word32 inlen, byte* out, word32 *outlen,
RNG* rng, ecc_key* key);
CYASSL_API
int ecc_verify_hash(const byte* sig, word32 siglen, byte* hash, word32 hashlen,
int* stat, ecc_key* key);
int ecc_verify_hash(const byte* sig, word32 siglen, const byte* hash,
word32 hashlen, int* stat, ecc_key* key);
CYASSL_API
void ecc_init(ecc_key* key);
CYASSL_API

View File

@ -1264,6 +1264,12 @@ struct CYASSL_CTX {
CallbackMacEncrypt MacEncryptCb; /* Atomic User Mac/Encrypt Cb */
CallbackDecryptVerify DecryptVerifyCb; /* Atomic User Decrypt/Verify Cb */
#endif
#ifdef HAVE_PK_CALLBACKS
#ifdef HAVE_ECC
CallbackEccSign EccSignCb; /* User EccSign Callback handler */
CallbackEccVerify EccVerifyCb; /* User EccVerify Callback handler */
#endif /* HAVE_ECC */
#endif /* HAVE_PK_CALLBACKS */
};
@ -1556,6 +1562,11 @@ typedef struct Buffers {
#ifdef CYASSL_DTLS
CYASSL_DTLS_CTX dtlsCtx; /* DTLS connection context */
#endif
#ifdef HAVE_PK_CALLBACKS
#ifdef HAVE_ECC
buffer peerEccDsaKey; /* we own for Ecc Verify Callbacks */
#endif /* HAVE_ECC */
#endif /* HAVE_PK_CALLBACKS */
} Buffers;
typedef struct Options {
@ -1831,6 +1842,12 @@ struct CYASSL {
void* MacEncryptCtx; /* Atomic User Mac/Encrypt Callback Context */
void* DecryptVerifyCtx; /* Atomic User Decrypt/Verify Callback Context */
#endif
#ifdef HAVE_PK_CALLBACKS
#ifdef HAVE_ECC
void* EccSignCtx; /* Ecc Sign Callback Context */
void* EccVerifyCtx; /* Ecc Verify Callback Context */
#endif /* HAVE_ECC */
#endif /* HAVE_PK_CALLBACKS */
};

View File

@ -1004,6 +1004,27 @@ enum BulkCipherAlgorithm {
cyassl_rabbit
};
/* Public Key Callback support */
typedef int (*CallbackEccSign)(CYASSL* ssl,
const unsigned char* in, unsigned int inSz,
unsigned char* out, unsigned int* outSz,
const unsigned char* keyDer, unsigned int keySz,
void* ctx);
CYASSL_API void CyaSSL_CTX_SetEccSignCb(CYASSL_CTX*, CallbackEccSign);
CYASSL_API void CyaSSL_SetEccSignCtx(CYASSL* ssl, void *ctx);
CYASSL_API void* CyaSSL_GetEccSignCtx(CYASSL* ssl);
typedef int (*CallbackEccVerify)(CYASSL* ssl,
const unsigned char* sig, unsigned int sigSz,
const unsigned char* hash, unsigned int hashSz,
const unsigned char* keyDer, unsigned int keySz,
int* result, void* ctx);
CYASSL_API void CyaSSL_CTX_SetEccVerifyCb(CYASSL_CTX*, CallbackEccVerify);
CYASSL_API void CyaSSL_SetEccVerifyCtx(CYASSL* ssl, void *ctx);
CYASSL_API void* CyaSSL_GetEccVerifyCtx(CYASSL* ssl);
#ifndef NO_CERTS
CYASSL_API void CyaSSL_CTX_SetCACb(CYASSL_CTX*, CallbackCACache);

View File

@ -15,6 +15,13 @@
#include <cyassl/ctaocrypt/arc4.h>
#include <cyassl/ctaocrypt/hmac.h>
#endif
#ifdef HAVE_PK_CALLBACKS
#include <cyassl/ctaocrypt/random.h>
#include <cyassl/ctaocrypt/asn.h>
#ifdef HAVE_ECC
#include <cyassl/ctaocrypt/ecc.h>
#endif /* HAVE_ECC */
#endif /*HAVE_PK_CALLBACKS */
#ifdef USE_WINDOWS_API
#include <winsock2.h>
@ -1493,6 +1500,66 @@ static INLINE void FreeAtomicUser(CYASSL* ssl)
#endif /* ATOMIC_USER */
#ifdef HAVE_PK_CALLBACKS
static INLINE int myEccSign(CYASSL* ssl, const byte* in, word32 inSz,
byte* out, word32* outSz, const byte* key, word32 keySz, void* ctx)
{
RNG rng;
int ret;
word32 idx = 0;
ecc_key myKey;
(void)ssl;
(void)ctx;
InitRng(&rng);
ecc_init(&myKey);
ret = EccPrivateKeyDecode(key, &idx, &myKey, keySz);
if (ret == 0)
ret = ecc_sign_hash(in, inSz, out, outSz, &rng, &myKey);
ecc_free(&myKey);
return ret;
}
static INLINE int myEccVerify(CYASSL* ssl, const byte* sig, word32 sigSz,
const byte* hash, word32 hashSz, const byte* key, word32 keySz,
int* result, void* ctx)
{
int ret;
ecc_key myKey;
(void)ssl;
(void)ctx;
ecc_init(&myKey);
ret = ecc_import_x963(key, keySz, &myKey);
if (ret == 0)
ret = ecc_verify_hash(sig, sigSz, hash, hashSz, result, &myKey);
ecc_free(&myKey);
return ret;
}
static INLINE void SetupPkCallbacks(CYASSL_CTX* ctx, CYASSL* ssl)
{
(void)ctx;
(void)ssl;
#ifdef HAVE_ECC
CyaSSL_CTX_SetEccSignCb(ctx, myEccSign);
CyaSSL_CTX_SetEccVerifyCb(ctx, myEccVerify);
#endif /* HAVE_ECC */
}
#endif /* HAVE_PK_CALLBACKS */
#if defined(__hpux__) || defined(__MINGW32__)
/* HP/UX doesn't have strsep, needed by test/suites.c */

View File

@ -146,6 +146,9 @@ static void Usage(void)
#ifdef ATOMIC_USER
printf("-U Atomic User Record Layer Callbacks\n");
#endif
#ifdef HAVE_PK_CALLBACKS
printf("-P Public Key Callbacks\n");
#endif
}
@ -190,6 +193,7 @@ THREAD_RETURN CYASSL_THREAD client_test(void* args)
int useClientCert = 1;
int fewerPackets = 0;
int atomicUser = 0;
int pkCallbacks = 0;
char* cipherList = NULL;
char* verifyCert = (char*)caCert;
char* ourCert = (char*)cliCert;
@ -226,11 +230,12 @@ THREAD_RETURN CYASSL_THREAD client_test(void* args)
(void)sslResume;
(void)trackMemory;
(void)atomicUser;
(void)pkCallbacks;
StackTrap();
while ((ch = mygetopt(argc, argv,
"?gdusmNrtfxUh:p:v:l:A:c:k:b:zS:L:ToO:")) != -1) {
"?gdusmNrtfxUPh:p:v:l:A:c:k:b:zS:L:ToO:")) != -1) {
switch (ch) {
case '?' :
Usage();
@ -276,6 +281,12 @@ THREAD_RETURN CYASSL_THREAD client_test(void* args)
#endif
break;
case 'P' :
#ifdef HAVE_PK_CALLBACKS
pkCallbacks = 1;
#endif
break;
case 'h' :
host = myoptarg;
domain = myoptarg;
@ -608,6 +619,10 @@ THREAD_RETURN CYASSL_THREAD client_test(void* args)
#ifdef ATOMIC_USER
if (atomicUser)
SetupAtomicUser(ctx, ssl);
#endif
#ifdef HAVE_PK_CALLBACKS
if (pkCallbacks)
SetupPkCallbacks(ctx, ssl);
#endif
if (matchName && doPeerCheck)
CyaSSL_check_domain_name(ssl, domain);

View File

@ -432,6 +432,12 @@ int InitSSL_Ctx(CYASSL_CTX* ctx, CYASSL_METHOD* method)
ctx->MacEncryptCb = NULL;
ctx->DecryptVerifyCb = NULL;
#endif
#ifdef HAVE_PK_CALLBACKS
#ifdef HAVE_ECC
ctx->EccSignCb = NULL;
ctx->EccVerifyCb = NULL;
#endif /* HAVE_ECC */
#endif /* HAVE_PK_CALLBACKS */
if (InitMutex(&ctx->countMutex) < 0) {
CYASSL_MSG("Mutex error on CTX init");
@ -1271,6 +1277,12 @@ int InitSSL(CYASSL* ssl, CYASSL_CTX* ctx)
ssl->buffers.clearOutputBuffer.length = 0;
ssl->buffers.prevSent = 0;
ssl->buffers.plainSz = 0;
#ifdef HAVE_PK_CALLBACKS
#ifdef HAVE_ECC
ssl->buffers.peerEccDsaKey.buffer = 0;
ssl->buffers.peerEccDsaKey.length = 0;
#endif /* HAVE_ECC */
#endif /* HAVE_PK_CALLBACKS */
#ifdef KEEP_PEER_CERT
InitX509(&ssl->peerCert, 0);
@ -1484,6 +1496,13 @@ int InitSSL(CYASSL* ssl, CYASSL_CTX* ctx)
ssl->MacEncryptCtx = NULL;
ssl->DecryptVerifyCtx = NULL;
#endif
#ifdef HAVE_PK_CALLBACKS
#ifdef HAVE_ECC
ssl->EccSignCtx = NULL;
ssl->EccVerifyCtx = NULL;
#endif /* HAVE_ECC */
#endif /* HAVE_PK_CALLBACKS */
/* all done with init, now can return errors, call other stuff */
/* increment CTX reference count */
@ -1692,6 +1711,11 @@ void SSL_ResourceFree(CYASSL* ssl)
XFREE(ssl->eccDsaKey, ssl->heap, DYNAMIC_TYPE_ECC);
}
#endif
#ifdef HAVE_PK_CALLBACKS
#ifdef HAVE_ECC
XFREE(ssl->buffers.peerEccDsaKey.buffer, ssl->heap, DYNAMIC_TYPE_ECC);
#endif /* HAVE_ECC */
#endif /* HAVE_PK_CALLBACKS */
#ifdef HAVE_TLS_EXTENSIONS
TLSX_FreeAll(ssl->extensions);
#endif
@ -1779,6 +1803,12 @@ void FreeHandshakeResources(CYASSL* ssl)
ssl->eccDsaKey = NULL;
}
#endif
#ifdef HAVE_PK_CALLBACKS
#ifdef HAVE_ECC
XFREE(ssl->buffers.peerEccDsaKey.buffer, ssl->heap, DYNAMIC_TYPE_ECC);
ssl->buffers.peerEccDsaKey.buffer = NULL;
#endif /* HAVE_ECC */
#endif /* HAVE_PK_CALLBACKS */
}
@ -3234,8 +3264,24 @@ static int DoCertificate(CYASSL* ssl, byte* input, word32* inOutIdx)
ssl->peerEccDsaKey) != 0) {
ret = PEER_KEY_ERROR;
}
else
else {
ssl->peerEccDsaKeyPresent = 1;
#ifdef HAVE_PK_CALLBACKS
#ifdef HAVE_ECC
ssl->buffers.peerEccDsaKey.buffer =
XMALLOC(dCert.pubKeySize,
ssl->heap, DYNAMIC_TYPE_ECC);
if (ssl->buffers.peerEccDsaKey.buffer == NULL)
ret = MEMORY_ERROR;
else {
XMEMCPY(ssl->buffers.peerEccDsaKey.buffer,
dCert.publicKey, dCert.pubKeySize);
ssl->buffers.peerEccDsaKey.length =
dCert.pubKeySize;
}
#endif /* HAVE_ECC */
#endif /*HAVE_PK_CALLBACKS */
}
}
break;
#endif /* HAVE_ECC */
@ -7471,6 +7517,15 @@ static void PickHashSigAlgo(CYASSL* ssl,
byte* digest = hash256;
word32 digestSz = SHA256_DIGEST_SIZE;
#endif
byte doUserEcc = 0;
#ifdef HAVE_PK_CALLBACKS
#ifdef HAVE_ECC
if (ssl->ctx->EccVerifyCb)
doUserEcc = 1;
#endif /* HAVE_ECC */
#endif /*HAVE_PK_CALLBACKS */
if (!ssl->peerEccDsaKeyPresent)
return NO_PEER_KEY;
@ -7494,9 +7549,21 @@ static void PickHashSigAlgo(CYASSL* ssl,
#endif
}
}
ret = ecc_verify_hash(signature, sigLen, digest, digestSz,
&verify, ssl->peerEccDsaKey);
if (doUserEcc) {
#ifdef HAVE_PK_CALLBACKS
#ifdef HAVE_ECC
ret = ssl->ctx->EccVerifyCb(ssl, signature, sigLen,
digest, digestSz,
ssl->buffers.peerEccDsaKey.buffer,
ssl->buffers.peerEccDsaKey.length,
&verify, ssl->EccVerifyCtx);
#endif /* HAVE_ECC */
#endif /*HAVE_PK_CALLBACKS */
}
else {
ret = ecc_verify_hash(signature, sigLen, digest, digestSz,
&verify, ssl->peerEccDsaKey);
}
if (ret != 0 || verify == 0)
return VERIFY_SIGN_ERROR;
}
@ -7861,6 +7928,14 @@ static void PickHashSigAlgo(CYASSL* ssl,
digestSz = SHA256_DIGEST_SIZE;
digest = ssl->certHashes.sha256;
#endif
byte doUserEcc = 0;
#ifdef HAVE_PK_CALLBACKS
#ifdef HAVE_ECC
if (ssl->ctx->EccSignCb)
doUserEcc = 1;
#endif /* HAVE_ECC */
#endif /*HAVE_PK_CALLBACKS */
if (IsAtLeastTLSv1_2(ssl)) {
if (ssl->suites->hashAlgo == sha_mac) {
@ -7883,8 +7958,21 @@ static void PickHashSigAlgo(CYASSL* ssl,
}
}
ret = ecc_sign_hash(digest, digestSz, encodedSig,
&localSz, ssl->rng, &eccKey);
if (doUserEcc) {
#ifdef HAVE_PK_CALLBACKS
#ifdef HAVE_ECC
ret = ssl->ctx->EccSignCb(ssl, digest, digestSz,
encodedSig, &localSz,
ssl->buffers.key.buffer,
ssl->buffers.key.length,
ssl->EccSignCtx);
#endif /* HAVE_ECC */
#endif /*HAVE_PK_CALLBACKS */
}
else {
ret = ecc_sign_hash(digest, digestSz, encodedSig,
&localSz, ssl->rng, &eccKey);
}
if (ret == 0) {
length = localSz;
c16toa((word16)length, verify + extraSz); /* prepend hdr */
@ -8395,6 +8483,14 @@ static void PickHashSigAlgo(CYASSL* ssl,
word32 digestSz = SHA256_DIGEST_SIZE;
#endif
word32 sz = sigSz;
byte doUserEcc = 0;
#ifdef HAVE_PK_CALLBACKS
#ifdef HAVE_ECC
if (ssl->ctx->EccSignCb)
doUserEcc = 1;
#endif /* HAVE_ECC */
#endif /*HAVE_PK_CALLBACKS */
if (IsAtLeastTLSv1_2(ssl)) {
if (ssl->suites->hashAlgo == sha_mac) {
@ -8417,8 +8513,21 @@ static void PickHashSigAlgo(CYASSL* ssl,
}
}
ret = ecc_sign_hash(digest, digestSz,
if (doUserEcc) {
#ifdef HAVE_PK_CALLBACKS
#ifdef HAVE_ECC
ret = ssl->ctx->EccSignCb(ssl, digest, digestSz,
output + LENGTH_SZ + idx, &sz,
ssl->buffers.key.buffer,
ssl->buffers.key.length,
ssl->EccSignCtx);
#endif /* HAVE_ECC */
#endif /*HAVE_PK_CALLBACKS */
}
else {
ret = ecc_sign_hash(digest, digestSz,
output + LENGTH_SZ + idx, &sz, ssl->rng, &dsaKey);
}
#ifndef NO_RSA
FreeRsaKey(&rsaKey);
#endif
@ -9709,6 +9818,14 @@ static void PickHashSigAlgo(CYASSL* ssl,
int err = -1;
byte* digest = ssl->certHashes.sha;
word32 digestSz = SHA_DIGEST_SIZE;
byte doUserEcc = 0;
#ifdef HAVE_PK_CALLBACKS
#ifdef HAVE_ECC
if (ssl->ctx->EccVerifyCb)
doUserEcc = 1;
#endif /* HAVE_ECC */
#endif /*HAVE_PK_CALLBACKS */
CYASSL_MSG("Doing ECC peer cert verify");
@ -9729,9 +9846,20 @@ static void PickHashSigAlgo(CYASSL* ssl,
#endif
}
}
err = ecc_verify_hash(sig, sz, digest, digestSz,
&verify, ssl->peerEccDsaKey);
if (doUserEcc) {
#ifdef HAVE_PK_CALLBACKS
#ifdef HAVE_ECC
ret = ssl->ctx->EccVerifyCb(ssl, sig, sz, digest, digestSz,
ssl->buffers.peerEccDsaKey.buffer,
ssl->buffers.peerEccDsaKey.length,
&verify, ssl->EccVerifyCtx);
#endif /* HAVE_ECC */
#endif /*HAVE_PK_CALLBACKS */
}
else {
err = ecc_verify_hash(sig, sz, digest, digestSz,
&verify, ssl->peerEccDsaKey);
}
if (err == 0 && verify == 1)
ret = 0; /* verified */
}

View File

@ -7225,8 +7225,8 @@ CYASSL_X509* CyaSSL_X509_load_certificate_file(const char* fname, int format)
}
if (dynamic) XFREE(fileBuffer, NULL, DYNAMIC_TYPE_FILE);
// At this point we want `der` to have the certificate in DER format
// ready to be decoded.
/* At this point we want `der` to have the certificate in DER format */
/* ready to be decoded. */
if (der.buffer != NULL) {
DecodedCert cert;
@ -10385,3 +10385,58 @@ int CyaSSL_CTX_OCSP_set_override_url(CYASSL_CTX* ctx, const char* url)
}
#ifndef NO_CERTS
#ifdef HAVE_PK_CALLBACKS
#ifdef HAVE_ECC
void CyaSSL_CTX_SetEccSignCb(CYASSL_CTX* ctx, CallbackEccSign cb)
{
if (ctx)
ctx->EccSignCb = cb;
}
void CyaSSL_SetEccSignCtx(CYASSL* ssl, void *ctx)
{
if (ssl)
ssl->EccSignCtx = ctx;
}
void* CyaSSL_GetEccSignCtx(CYASSL* ssl)
{
if (ssl)
return ssl->EccSignCtx;
return NULL;
}
void CyaSSL_CTX_SetEccVerifyCb(CYASSL_CTX* ctx, CallbackEccVerify cb)
{
if (ctx)
ctx->EccVerifyCb = cb;
}
void CyaSSL_SetEccVerifyCtx(CYASSL* ssl, void *ctx)
{
if (ssl)
ssl->EccVerifyCtx = ctx;
}
void* CyaSSL_GetEccVerifyCtx(CYASSL* ssl)
{
if (ssl)
return ssl->EccVerifyCtx;
return NULL;
}
#endif /* HAVE_ECC */
#endif /* HAVE_PK_CALLBACKS */
#endif /* NO_CERTS */

View File

@ -1042,7 +1042,7 @@ void TLSX_FreeAll(TLSX* list)
break;
case TRUNCATED_HMAC:
// Nothing to do.
/* Nothing to do. */
break;
}
@ -1081,7 +1081,7 @@ static word16 TLSX_GetSize(TLSX* list, byte* semaphore, byte isRequest)
break;
case TRUNCATED_HMAC:
// empty extension.
/* empty extension. */
break;
}
@ -1125,7 +1125,7 @@ static word16 TLSX_Write(TLSX* list, byte* output, byte* semaphore,
break;
case TRUNCATED_HMAC:
// empty extension.
/* empty extension. */
break;
}