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

Conflicts:
	ctaocrypt/test/test.c
	cyassl/ctaocrypt/pkcs7.h
This commit is contained in:
John Safranek 2014-01-15 13:23:26 -08:00
commit 85c5c29e7a
12 changed files with 685 additions and 164 deletions

View File

@ -439,8 +439,8 @@ CYASSL_LOCAL int GetLength(const byte* input, word32* inOutIdx, int* len,
}
static int GetSequence(const byte* input, word32* inOutIdx, int* len,
word32 maxIdx)
CYASSL_LOCAL int GetSequence(const byte* input, word32* inOutIdx, int* len,
word32 maxIdx)
{
int length = -1;
word32 idx = *inOutIdx;
@ -456,7 +456,8 @@ static int GetSequence(const byte* input, word32* inOutIdx, int* len,
}
static int GetSet(const byte* input, word32* inOutIdx, int* len, word32 maxIdx)
CYASSL_LOCAL int GetSet(const byte* input, word32* inOutIdx, int* len,
word32 maxIdx)
{
int length = -1;
word32 idx = *inOutIdx;
@ -473,7 +474,7 @@ static int GetSet(const byte* input, word32* inOutIdx, int* len, word32 maxIdx)
/* winodws header clash for WinCE using GetVersion */
static int GetMyVersion(const byte* input, word32* inOutIdx, int* version)
CYASSL_LOCAL int GetMyVersion(const byte* input, word32* inOutIdx, int* version)
{
word32 idx = *inOutIdx;
@ -537,7 +538,7 @@ static int GetExplicitVersion(const byte* input, word32* inOutIdx, int* version)
}
static int GetInt(mp_int* mpi, const byte* input, word32* inOutIdx,
CYASSL_LOCAL int GetInt(mp_int* mpi, const byte* input, word32* inOutIdx,
word32 maxIdx)
{
word32 i = *inOutIdx;
@ -593,7 +594,7 @@ static int GetObjectId(const byte* input, word32* inOutIdx, word32* oid,
}
static int GetAlgoId(const byte* input, word32* inOutIdx, word32* oid,
CYASSL_LOCAL int GetAlgoId(const byte* input, word32* inOutIdx, word32* oid,
word32 maxIdx)
{
int length;
@ -6064,39 +6065,9 @@ int CompareOcspReqResp(OcspRequest* req, OcspResponse* resp)
#endif
#ifdef HAVE_CRL
/* initialize decoded CRL */
void InitDecodedCRL(DecodedCRL* dcrl)
{
CYASSL_MSG("InitDecodedCRL");
dcrl->certBegin = 0;
dcrl->sigIndex = 0;
dcrl->sigLength = 0;
dcrl->signatureOID = 0;
dcrl->certs = NULL;
dcrl->totalCerts = 0;
}
/* free decoded CRL resources */
void FreeDecodedCRL(DecodedCRL* dcrl)
{
RevokedCert* tmp = dcrl->certs;
CYASSL_MSG("FreeDecodedCRL");
while(tmp) {
RevokedCert* next = tmp->next;
XFREE(tmp, NULL, DYNAMIC_TYPE_REVOKED);
tmp = next;
}
}
/* store SHA1 hash of NAME */
static int GetNameHash(const byte* source, word32* idx, byte* hash, int maxIdx)
CYASSL_LOCAL int GetNameHash(const byte* source, word32* idx, byte* hash,
int maxIdx)
{
Sha sha;
int length; /* length of all distinguished names */
@ -6131,6 +6102,37 @@ static int GetNameHash(const byte* source, word32* idx, byte* hash, int maxIdx)
}
#ifdef HAVE_CRL
/* initialize decoded CRL */
void InitDecodedCRL(DecodedCRL* dcrl)
{
CYASSL_MSG("InitDecodedCRL");
dcrl->certBegin = 0;
dcrl->sigIndex = 0;
dcrl->sigLength = 0;
dcrl->signatureOID = 0;
dcrl->certs = NULL;
dcrl->totalCerts = 0;
}
/* free decoded CRL resources */
void FreeDecodedCRL(DecodedCRL* dcrl)
{
RevokedCert* tmp = dcrl->certs;
CYASSL_MSG("FreeDecodedCRL");
while(tmp) {
RevokedCert* next = tmp->next;
XFREE(tmp, NULL, DYNAMIC_TYPE_REVOKED);
tmp = next;
}
}
/* Get Revoked Cert list, 0 on success */
static int GetRevoked(const byte* buff, word32* idx, DecodedCRL* dcrl,
int maxIdx)

View File

@ -147,10 +147,87 @@ const byte base64Encode[] = { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J',
};
/* make sure *i (idx) won't exceed max, store and possibly escape to out,
* raw means use e w/o decode, 0 on success */
static int Escape(int escaped, byte e, byte* out, word32* i, word32 max,
int raw)
{
int doEscape = 0;
word32 needed = 1;
word32 idx = *i;
byte basic;
byte plus = 0;
byte equals = 0;
byte newline = 0;
if (raw)
basic = e;
else
basic = base64Encode[e];
/* check whether to escape */
if (escaped) {
switch ((char)basic) {
case '+' :
plus = 1;
doEscape = 1;
needed += 2;
break;
case '=' :
equals = 1;
doEscape = 1;
needed += 2;
break;
case '\n' :
newline = 1;
doEscape = 1;
needed += 2;
break;
default:
/* do nothing */
break;
}
}
/* check size */
if ( (idx+needed) > max) {
CYASSL_MSG("Escape buffer max too small");
return BUFFER_E;
}
/* store it */
if (doEscape == 0) {
out[idx++] = basic;
}
else {
out[idx++] = '%'; /* start escape */
if (plus) {
out[idx++] = '2';
out[idx++] = 'B';
}
else if (equals) {
out[idx++] = '3';
out[idx++] = 'D';
}
else if (newline) {
out[idx++] = '0';
out[idx++] = 'A';
}
}
*i = idx;
return 0;
}
/* internal worker, handles both escaped and normal line endings */
static int DoBase64_Encode(const byte* in, word32 inLen, byte* out,
word32* outLen, int escaped)
{
int ret = 0;
word32 i = 0,
j = 0,
n = 0; /* new line counter */
@ -163,6 +240,8 @@ static int DoBase64_Encode(const byte* in, word32 inLen, byte* out,
outSz += addSz;
/* if escaped we can't predetermine size for one pass encoding, but
* make sure we have enough if no escapes are in input */
if (outSz > *outLen) return BAD_FUNC_ARG;
while (inLen > 2) {
@ -177,26 +256,25 @@ static int DoBase64_Encode(const byte* in, word32 inLen, byte* out,
byte e4 = b3 & 0x3F;
/* store */
out[i++] = base64Encode[e1];
out[i++] = base64Encode[e2];
out[i++] = base64Encode[e3];
out[i++] = base64Encode[e4];
ret = Escape(escaped, e1, out, &i, *outLen, 0);
if (ret != 0) break;
ret = Escape(escaped, e2, out, &i, *outLen, 0);
if (ret != 0) break;
ret = Escape(escaped, e3, out, &i, *outLen, 0);
if (ret != 0) break;
ret = Escape(escaped, e4, out, &i, *outLen, 0);
if (ret != 0) break;
inLen -= 3;
if ((++n % (PEM_LINE_SZ / 4)) == 0 && inLen) {
if (escaped) {
out[i++] = '%';
out[i++] = '0';
out[i++] = 'A';
}
else
out[i++] = '\n';
ret = Escape(escaped, '\n', out, &i, *outLen, 1);
if (ret != 0) break;
}
}
/* last integral */
if (inLen) {
if (inLen && ret == 0) {
int twoBytes = (inLen == 2);
byte b1 = in[j++];
@ -206,24 +284,29 @@ static int DoBase64_Encode(const byte* in, word32 inLen, byte* out,
byte e2 = ((b1 & 0x3) << 4) | (b2 >> 4);
byte e3 = (b2 & 0xF) << 2;
out[i++] = base64Encode[e1];
out[i++] = base64Encode[e2];
out[i++] = (twoBytes) ? base64Encode[e3] : PAD;
out[i++] = PAD;
ret = Escape(escaped, e1, out, &i, *outLen, 0);
if (ret == 0)
ret = Escape(escaped, e2, out, &i, *outLen, 0);
if (ret == 0) {
/* third */
if (twoBytes)
ret = Escape(escaped, e3, out, &i, *outLen, 0);
else
ret = Escape(escaped, '=', out, &i, *outLen, 1);
}
/* fourth always pad */
if (ret == 0)
ret = Escape(escaped, '=', out, &i, *outLen, 1);
}
if (escaped) {
out[i++] = '%';
out[i++] = '0';
out[i++] = 'A';
}
else
out[i++] = '\n';
if (i != outSz)
return ASN_INPUT_E;
*outLen = outSz;
if (ret == 0)
ret = Escape(escaped, '\n', out, &i, *outLen, 1);
return 0;
if (i != outSz && escaped == 0 && ret == 0)
return ASN_INPUT_E;
*outLen = i;
return ret;
}

View File

@ -335,6 +335,14 @@ void CTaoCryptErrorString(int error, char* buffer)
XSTRNCPY(buffer, "Setting cert request attributes error", max);
break;
case PKCS7_OID_E:
XSTRNCPY(buffer, "PKCS#7 error: mismatched OID value", max);
break;
case PKCS7_RECIP_E:
XSTRNCPY(buffer, "PKCS#7 error: no matching recipient found", max);
break;
default:
XSTRNCPY(buffer, "unknown error number", max);

View File

@ -114,6 +114,33 @@ CYASSL_LOCAL int SetContentType(int pkcs7TypeOID, byte* output)
}
int GetContentType(const byte* input, word32* inOutIdx, word32* oid,
word32 maxIdx)
{
int length;
word32 i = *inOutIdx;
byte b;
*oid = 0;
CYASSL_ENTER("GetContentType");
b = input[i++];
if (b != ASN_OBJECT_ID)
return ASN_OBJECT_ID_E;
if (GetLength(input, &i, &length, maxIdx) < 0)
return ASN_PARSE_E;
while(length--) {
*oid += input[i];
i++;
}
*inOutIdx = i;
return 0;
}
int PKCS7_InitWithCert(PKCS7* pkcs7, byte* cert, word32 certSz)
{
@ -556,6 +583,8 @@ CYASSL_LOCAL int CreateRecipientInfo(const byte* cert, word32 certSz,
return ALGO_ID_E;
keyEncAlgSz = SetAlgoID(keyEncAlgo, keyAlgArray, keyType, 0);
if (keyEncAlgSz == 0)
return BAD_FUNC_ARG;
/* EncryptedKey */
InitRsaKey(&pubKey, 0);
@ -642,6 +671,13 @@ int PKCS7_EncodeEnvelopeData(PKCS7* pkcs7, byte* output, word32 outputSz)
byte contentEncAlgo[MAX_ALGO_SZ];
byte encContentOctet[MAX_OCTET_STR_SZ];
if (pkcs7 == NULL || pkcs7->content == NULL || pkcs7->contentSz == 0 ||
pkcs7->encryptOID == 0 || pkcs7->singleCert == NULL)
return BAD_FUNC_ARG;
if (output == NULL || outputSz == 0)
return BAD_FUNC_ARG;
switch (pkcs7->encryptOID) {
case DESb:
blockKeySz = DES_KEYLEN;
@ -662,7 +698,7 @@ int PKCS7_EncodeEnvelopeData(PKCS7* pkcs7, byte* output, word32 outputSz)
/* version */
verSz = SetMyVersion(0, ver, 0);
/* generate random content enc key */
/* generate random content encryption key */
InitRng(&rng);
RNG_GenerateBlock(&rng, contentKeyPlain, blockKeySz);
@ -680,8 +716,13 @@ int PKCS7_EncodeEnvelopeData(PKCS7* pkcs7, byte* output, word32 outputSz)
/* EncryptedContentInfo */
contentTypeSz = SetContentType(pkcs7->contentOID, contentType);
if (contentTypeSz == 0)
return BAD_FUNC_ARG;
contentEncAlgoSz = SetAlgoID(pkcs7->encryptOID, contentEncAlgo,
blkType, 0);
if (contentEncAlgoSz == 0)
return BAD_FUNC_ARG;
/* allocate memory for encrypted content, pad if necessary */
padSz = DES_BLOCK_SIZE - (pkcs7->contentSz % DES_BLOCK_SIZE);
@ -696,7 +737,7 @@ int PKCS7_EncodeEnvelopeData(PKCS7* pkcs7, byte* output, word32 outputSz)
dynamicFlag = 1;
for (i = 0; i < padSz; i++) {
plain[pkcs7->contentSz + i + 1] = padSz;
plain[pkcs7->contentSz + i] = padSz;
}
} else {
@ -711,16 +752,17 @@ int PKCS7_EncodeEnvelopeData(PKCS7* pkcs7, byte* output, word32 outputSz)
return MEMORY_E;
}
/* use NULL iv for now */
byte tmpIv[blockKeySz];
XMEMSET(tmpIv, 0, sizeof(tmpIv));
if (pkcs7->encryptOID == DESb) {
Des des;
RNG_GenerateBlock(&rng, tmpIv, (word32)sizeof(tmpIv));
Des_SetKey(&des, contentKeyPlain, tmpIv, DES_ENCRYPTION);
Des_CbcEncrypt(&des, encryptedContent, plain, desOutSz);
} else if (pkcs7->encryptOID == DES3b) {
Des3 des3;
RNG_GenerateBlock(&rng, tmpIv, (word32)sizeof(tmpIv));
Des3_SetKey(&des3, contentKeyPlain, tmpIv, DES_ENCRYPTION);
Des3_CbcEncrypt(&des3, encryptedContent, plain, desOutSz);
}
@ -784,6 +826,10 @@ int PKCS7_EncodeEnvelopeData(PKCS7* pkcs7, byte* output, word32 outputSz)
#ifdef NO_RC4
FreeRng(&rng);
#endif
XMEMSET(contentKeyPlain, 0, MAX_CONTENT_KEY_LEN);
XMEMSET(contentKeyEnc, 0, MAX_ENCRYPTED_KEY_SZ);
if (dynamicFlag)
XFREE(plain, NULL, DYNAMMIC_TYPE_TMP_BUFFER);
XFREE(encryptedContent, NULL, DYNAMIC_TYPE_TMP_BUFFER);
@ -791,6 +837,219 @@ int PKCS7_EncodeEnvelopeData(PKCS7* pkcs7, byte* output, word32 outputSz)
return idx;
}
CYASSL_API int PKCS7_DecodeEnvelopedData(PKCS7* pkcs7, byte* pkiMsg,
word32 pkiMsgSz, byte* output,
word32 outputSz)
{
int recipFound = 0;
int ret, version, length;
word32 savedIdx = 0, idx = 0;
word32 contentType, encOID;
byte issuerHash[SHA_DIGEST_SIZE];
mp_int serialNum;
DecodedCert decoded;
int encryptedKeySz, keySz;
byte tmpIv[DES3_KEYLEN];
byte encryptedKey[MAX_ENCRYPTED_KEY_SZ];
byte* decryptedKey = NULL;
RsaKey privKey;
int encryptedContentSz;
byte padLen;
byte* encryptedContent = NULL;
if (pkcs7 == NULL || pkcs7->singleCert == NULL ||
pkcs7->singleCertSz == 0 || pkcs7->privateKey == NULL ||
pkcs7->privKeySize == 0)
return BAD_FUNC_ARG;
if (pkiMsg == NULL || pkiMsgSz == 0 ||
output == NULL || outputSz == 0)
return BAD_FUNC_ARG;
/* parse recipient cert */
InitDecodedCert(&decoded, pkcs7->singleCert, pkcs7->singleCertSz, 0);
ret = ParseCert(&decoded, CA_TYPE, NO_VERIFY, 0);
if (ret < 0) {
FreeDecodedCert(&decoded);
return ret;
}
/* load private key */
InitRsaKey(&privKey, 0);
ret = RsaPrivateKeyDecode(pkcs7->privateKey, &idx, &privKey,
pkcs7->privKeySize);
if (ret != 0) {
CYASSL_MSG("Failed to decode RSA private key");
return ret;
}
idx = 0;
/* read past ContentInfo, verify type */
if (GetSequence(pkiMsg, &idx, &length, pkiMsgSz) < 0)
return ASN_PARSE_E;
if (GetContentType(pkiMsg, &idx, &contentType, pkiMsgSz) < 0)
return ASN_PARSE_E;
if (contentType != ENVELOPED_DATA) {
CYASSL_MSG("PKCS#7 input not of type EnvelopedData");
return PKCS7_OID_E;
}
if (pkiMsg[idx++] != (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0))
return ASN_PARSE_E;
if (GetLength(pkiMsg, &idx, &length, pkiMsgSz) < 0)
return ASN_PARSE_E;
/* remove EnvelopedData */
if (GetSequence(pkiMsg, &idx, &length, pkiMsgSz) < 0)
return ASN_PARSE_E;
if (GetMyVersion(pkiMsg, &idx, &version) < 0)
return ASN_PARSE_E;
if (version != 0) {
CYASSL_MSG("PKCS#7 envelopedData needs to be of version 0");
return ASN_VERSION_E;
}
/* walk through RecipientInfo set, find correct recipient */
if (GetSet(pkiMsg, &idx, &length, pkiMsgSz) < 0)
return ASN_PARSE_E;
savedIdx = idx;
recipFound = 0;
/* when looking for next recipient, use first sequence and version to
* indicate there is another, if not, move on */
while(recipFound == 0) {
/* remove RecipientInfo */
if (GetSequence(pkiMsg, &idx, &length, pkiMsgSz) < 0) {
if (recipFound == 0) {
return ASN_PARSE_E;
} else {
idx = savedIdx;
break;
}
}
if (GetMyVersion(pkiMsg, &idx, &version) < 0) {
if (recipFound == 0) {
return ASN_PARSE_E;
} else {
idx = savedIdx;
break;
}
}
if (version != 0)
return ASN_VERSION_E;
/* remove IssuerAndSerialNumber */
if (GetSequence(pkiMsg, &idx, &length, pkiMsgSz) < 0)
return ASN_PARSE_E;
if (GetNameHash(pkiMsg, &idx, issuerHash, pkiMsgSz) < 0)
return ASN_PARSE_E;
if (XMEMCMP(issuerHash, decoded.issuerHash, SHA_DIGEST_SIZE) == 0) {
recipFound = 1;
}
if (GetInt(&serialNum, pkiMsg, &idx, pkiMsgSz) < 0)
return ASN_PARSE_E;
if (GetAlgoId(pkiMsg, &idx, &encOID, pkiMsgSz) < 0)
return ASN_PARSE_E;
if (encOID != RSAk)
return ALGO_ID_E;
/* read encryptedKey */
if (pkiMsg[idx++] != ASN_OCTET_STRING)
return ASN_PARSE_E;
if (GetLength(pkiMsg, &idx, &encryptedKeySz, pkiMsgSz) < 0)
return ASN_PARSE_E;
if (recipFound == 1)
XMEMCPY(encryptedKey, &pkiMsg[idx], encryptedKeySz);
idx += encryptedKeySz;
/* update good idx */
savedIdx = idx;
}
if (recipFound == 0) {
CYASSL_MSG("No recipient found in envelopedData that matches input");
return PKCS7_RECIP_E;
}
/* remove EncryptedContentInfo */
if (GetSequence(pkiMsg, &idx, &length, pkiMsgSz) < 0)
return ASN_PARSE_E;
if (GetContentType(pkiMsg, &idx, &contentType, pkiMsgSz) < 0)
return ASN_PARSE_E;
if (GetAlgoId(pkiMsg, &idx, &encOID, pkiMsgSz) < 0)
return ASN_PARSE_E;
/* read encryptedContent */
if (pkiMsg[idx++] != ASN_OCTET_STRING)
return ASN_PARSE_E;
if (GetLength(pkiMsg, &idx, &encryptedContentSz, pkiMsgSz) < 0)
return ASN_PARSE_E;
encryptedContent = XMALLOC(encryptedContentSz, NULL,
DYNAMIC_TYPE_TMP_BUFFER);
XMEMCPY(encryptedContent, &pkiMsg[idx], encryptedContentSz);
/* decrypt encryptedKey */
keySz = RsaPrivateDecryptInline(encryptedKey, encryptedKeySz,
&decryptedKey, &privKey);
if (keySz < 0)
return keySz;
/* decrypt encryptedContent, using NULL iv for now */
XMEMSET(tmpIv, 0, sizeof(tmpIv));
if (encOID == DESb) {
Des des;
Des_SetKey(&des, decryptedKey, tmpIv, DES_DECRYPTION);
Des_CbcDecrypt(&des, encryptedContent, encryptedContent,
encryptedContentSz);
} else if (encOID == DES3b) {
Des3 des;
Des3_SetKey(&des, decryptedKey, tmpIv, DES_DECRYPTION);
Des3_CbcDecrypt(&des, encryptedContent, encryptedContent,
encryptedContentSz);
} else {
CYASSL_MSG("Unsupported content encryption OID type");
return ALGO_ID_E;
}
padLen = encryptedContent[encryptedContentSz-1];
/* copy plaintext to output */
XMEMCPY(output, encryptedContent, encryptedContentSz - padLen);
/* free memory, zero out keys */
XMEMSET(encryptedKey, 0, MAX_ENCRYPTED_KEY_SZ);
XMEMSET(encryptedContent, 0, encryptedContentSz);
XFREE(encryptedContent, NULL, DYNAMIC_TYPE_TMP_BUFFER);
return encryptedContentSz - padLen;
}
#else /* HAVE_PKCS7 */

View File

@ -4027,106 +4027,193 @@ int compress_test(void)
int pkcs7_test(void)
{
int ret = 0;
byte* cert;
byte out[2048];
char data[] = "Hello World";
word32 dataSz, outSz;
PKCS7 msg;
RNG rng;
word32 certSz;
FILE* file;
FILE* pkcs7File;
byte transIdOid[] =
{ 0x06, 0x0a, 0x60, 0x86, 0x48, 0x01, 0x86, 0xF8, 0x45, 0x01,
0x09, 0x07 };
byte messageTypeOid[] =
{ 0x06, 0x0a, 0x60, 0x86, 0x48, 0x01, 0x86, 0xF8, 0x45, 0x01,
0x09, 0x02 };
byte senderNonceOid[] =
{ 0x06, 0x0a, 0x60, 0x86, 0x48, 0x01, 0x86, 0xF8, 0x45, 0x01,
0x09, 0x05 };
byte pkiStatusOid[] =
{ 0x06, 0x0a, 0x60, 0x86, 0x48, 0x01, 0x86, 0xF8, 0x45, 0x01,
0x09, 0x03 };
byte transId[(SHA_DIGEST_SIZE + 1) * 2 + 1];
byte messageType[] = { 0x13, 2, '1', '9' };
byte senderNonce[34];
byte pkiStatus[] = { 0x13, 1, '0' };
PKCS7Attrib attribs[] =
/* Test the PKCS7 Signed-Data */
{
{ transIdOid, sizeof(transIdOid),
transId, sizeof(transId) - 1 }, /* take off the null */
{ messageTypeOid, sizeof(messageTypeOid),
messageType, sizeof(messageType) },
{ senderNonceOid, sizeof(senderNonceOid),
senderNonce, sizeof(senderNonce) },
{ pkiStatusOid, sizeof(pkiStatusOid),
pkiStatus, sizeof(pkiStatus) }
};
byte* cert;
byte out[2048];
char data[] = "Hello World";
word32 dataSz, outSz;
PKCS7 msg;
RNG rng;
dataSz = (word32) strlen(data);
outSz = sizeof(out);
word32 certSz;
FILE* file;
FILE* pkcs7File;
cert = (byte*)malloc(FOURK_BUF);
if (cert == NULL)
return -40;
byte transIdOid[] =
{ 0x06, 0x0a, 0x60, 0x86, 0x48, 0x01, 0x86, 0xF8, 0x45, 0x01,
0x09, 0x07 };
byte messageTypeOid[] =
{ 0x06, 0x0a, 0x60, 0x86, 0x48, 0x01, 0x86, 0xF8, 0x45, 0x01,
0x09, 0x02 };
byte senderNonceOid[] =
{ 0x06, 0x0a, 0x60, 0x86, 0x48, 0x01, 0x86, 0xF8, 0x45, 0x01,
0x09, 0x05 };
byte pkiStatusOid[] =
{ 0x06, 0x0a, 0x60, 0x86, 0x48, 0x01, 0x86, 0xF8, 0x45, 0x01,
0x09, 0x03 };
byte transId[(SHA_DIGEST_SIZE + 1) * 2 + 1];
byte messageType[] = { 0x13, 2, '1', '9' };
byte senderNonce[34];
byte pkiStatus[] = { 0x13, 1, '0' };
/* read in DER cert of recipient, into cert of size certSz */
file = fopen(clientCert, "rb");
PKCS7Attrib attribs[] =
{
{ transIdOid, sizeof(transIdOid),
transId, sizeof(transId) - 1 }, /* take off the null */
{ messageTypeOid, sizeof(messageTypeOid),
messageType, sizeof(messageType) },
{ senderNonceOid, sizeof(senderNonceOid),
senderNonce, sizeof(senderNonce) },
{ pkiStatusOid, sizeof(pkiStatusOid),
pkiStatus, sizeof(pkiStatus) }
};
if (!file)
err_sys("can't open ./certs/client-cert.der, "
"Please run from CyaSSL home dir", -40);
dataSz = (word32) strlen(data);
outSz = sizeof(out);
certSz = (word32)fread(cert, 1, FOURK_BUF, file);
fclose(file);
cert = (byte*)malloc(FOURK_BUF);
if (cert == NULL)
return -40;
ret = InitRng(&rng);
senderNonce[0] = 0x04;
senderNonce[1] = 0x20;
RNG_GenerateBlock(&rng, &senderNonce[2], 32);
/* read in DER cert of recipient, into cert of size certSz */
file = fopen(clientCert, "rb");
PKCS7_InitWithCert(&msg, cert, certSz);
msg.content = (byte*)data;
msg.contentSz = dataSz;
msg.hashOID = SHAh;
msg.encryptOID = RSAk;
msg.signedAttribs = attribs;
msg.signedAttribsSz = sizeof(attribs)/sizeof(PKCS7Attrib);
msg.rng = &rng;
{
Sha sha;
byte digest[SHA_DIGEST_SIZE];
int i,j;
if (!file)
err_sys("can't open ./certs/client-cert.der, "
"Please run from CyaSSL home dir", -40);
transId[0] = 0x13;
transId[1] = SHA_DIGEST_SIZE * 2;
certSz = (word32)fread(cert, 1, FOURK_BUF, file);
fclose(file);
InitSha(&sha);
ShaUpdate(&sha, msg.publicKey, msg.publicKeySz);
ShaFinal(&sha, digest);
ret = InitRng(&rng);
senderNonce[0] = 0x04;
senderNonce[1] = 0x20;
RNG_GenerateBlock(&rng, &senderNonce[2], 32);
for (i = 0, j = 2; i < SHA_DIGEST_SIZE; i++, j += 2) {
snprintf((char*)&transId[j], 3, "%02x", digest[i]);
PKCS7_InitWithCert(&msg, cert, certSz);
msg.content = (byte*)data;
msg.contentSz = dataSz;
msg.hashOID = SHAh;
msg.encryptOID = RSAk;
msg.signedAttribs = attribs;
msg.signedAttribsSz = sizeof(attribs)/sizeof(PKCS7Attrib);
msg.rng = &rng;
{
Sha sha;
byte digest[SHA_DIGEST_SIZE];
int i,j;
transId[0] = 0x13;
transId[1] = SHA_DIGEST_SIZE * 2;
InitSha(&sha);
ShaUpdate(&sha, msg.publicKey, msg.publicKeySz);
ShaFinal(&sha, digest);
for (i = 0, j = 2; i < SHA_DIGEST_SIZE; i++, j += 2) {
snprintf((char*)&transId[j], 3, "%02x", digest[i]);
}
}
}
ret = PKCS7_EncodeSignedData(&msg, out, outSz);
if (ret < 0) {
printf("Pkcs7_encrypt failed\n");
return -42;
}
else
outSz = ret;
ret = PKCS7_EncodeSignedData(&msg, out, outSz);
if (ret < 0) {
printf("Pkcs7_encrypt failed\n");
return -42;
}
else
outSz = ret;
/* write PKCS#7 to output file for more testing */
pkcs7File = fopen("./pkcs7test.der", "wb");
if (!pkcs7File)
return -43;
ret = (int)fwrite(out, outSz, 1, pkcs7File);
fclose(pkcs7File);
/* write PKCS#7 to output file for more testing */
pkcs7File = fopen("./pkcs7test.der", "wb");
if (!pkcs7File)
return -43;
ret = (int)fwrite(out, outSz, 1, pkcs7File);
fclose(pkcs7File);
}
/* Test the PKCS7 Enveloped-Data */
{
int cipher = DES3b;
int envelopedSz, decodedSz;
PKCS7 pkcs7;
byte* cert;
byte* privKey;
byte enveloped[2048];
byte decoded[2048];
size_t certSz;
size_t privKeySz;
FILE* certFile;
FILE* keyFile;
FILE* pkcs7File;
const char* pkcs7OutFile = "pkcs7envelopedData.der";
const byte data[] = { /* Hello World */
0x48,0x65,0x6c,0x6c,0x6f,0x20,0x57,0x6f,
0x72,0x6c,0x64
};
/* read client cert and key in DER format */
cert = (byte*)malloc(FOURK_BUF);
if (cert == NULL)
return -201;
privKey = (byte*)malloc(FOURK_BUF);
if (privKey == NULL)
return -202;
certFile = fopen(clientCert, "rb");
if (!certFile)
err_sys("can't open ./certs/client-cert.der, "
"Please run from CyaSSL home dir", -42);
certSz = fread(cert, 1, FOURK_BUF, certFile);
fclose(certFile);
keyFile = fopen(clientKey, "rb");
if (!keyFile)
err_sys("can't open ./certs/client-key.der, "
"Please run from CyaSSL home dir", -43);
privKeySz = fread(privKey, 1, FOURK_BUF, keyFile);
fclose(keyFile);
PKCS7_InitWithCert(&pkcs7, cert, (word32)certSz);
pkcs7.content = (byte*)data;
pkcs7.contentSz = (word32)sizeof(data);
pkcs7.contentOID = DATA;
pkcs7.encryptOID = cipher;
pkcs7.privateKey = privKey;
pkcs7.privKeySize = (word32)privKeySz;
/* encode envelopedData */
envelopedSz = PKCS7_EncodeEnvelopeData(&pkcs7, enveloped,
sizeof(enveloped));
if (envelopedSz <= 0)
return -203;
/* decode envelopedData */
decodedSz = PKCS7_DecodeEnvelopedData(&pkcs7, enveloped, envelopedSz,
decoded, sizeof(decoded));
if (decodedSz <= 0)
return -204;
/* test decode result */
if (memcmp(decoded, data, sizeof(data)) != 0) {
return -205;
}
/* output pkcs7 envelopedData for external testing */
pkcs7File = fopen(pkcs7OutFile, "wb");
if (!pkcs7File)
return -206;
ret = (int)fwrite(enveloped, envelopedSz, 1, pkcs7File);
fclose(pkcs7File);
free(cert);
free(privKey);
}
if (ret > 0)
return 0;

View File

@ -446,6 +446,16 @@ CYASSL_LOCAL int ValidateDate(const byte* date, byte format, int dateType);
/* ASN.1 helper functions */
CYASSL_LOCAL int GetLength(const byte* input, word32* inOutIdx, int* len,
word32 maxIdx);
CYASSL_LOCAL int GetSequence(const byte* input, word32* inOutIdx, int* len,
word32 maxIdx);
CYASSL_LOCAL int GetSet(const byte* input, word32* inOutIdx, int* len,
word32 maxIdx);
CYASSL_LOCAL int GetMyVersion(const byte* input, word32* inOutIdx,
int* version);
CYASSL_LOCAL int GetInt(mp_int* mpi, const byte* input, word32* inOutIdx,
word32 maxIdx);
CYASSL_LOCAL int GetAlgoId(const byte* input, word32* inOutIdx, word32* oid,
word32 maxIdx);
CYASSL_LOCAL word32 SetLength(word32 length, byte* output);
CYASSL_LOCAL word32 SetSequence(word32 len, byte* output);
CYASSL_LOCAL word32 SetOctetString(word32 len, byte* output);
@ -454,6 +464,8 @@ CYASSL_LOCAL word32 SetSet(word32 len, byte* output);
CYASSL_LOCAL word32 SetAlgoID(int algoOID, byte* output, int type, int curveSz);
CYASSL_LOCAL int SetMyVersion(word32 version, byte* output, int header);
CYASSL_LOCAL int SetSerialNumber(const byte* sn, word32 snSz, byte* output);
CYASSL_LOCAL int GetNameHash(const byte* source, word32* idx, byte* hash,
int maxIdx);
#ifdef HAVE_ECC
/* ASN sig helpers */

View File

@ -119,6 +119,9 @@ enum {
REQ_ATTRIBUTE_E = -194, /* setting cert request attributes error */
PKCS7_OID_E = -195, /* PKCS#7, mismatched OID error */
PKCS7_RECIP_E = -196, /* PKCS#7, recipient error */
MIN_CODE_E = -200 /* errors -101 - -199 */
};

View File

@ -63,19 +63,21 @@ typedef struct PKCS7Attrib {
typedef struct PKCS7 {
byte* content;
word32 contentSz;
int contentOID;
byte* content; /* inner content, not owner */
word32 contentSz; /* content size */
int contentOID; /* PKCS#7 content type OID sum */
RNG* rng;
int hashOID;
int encryptOID;
int encryptOID; /* key encryption algorithm OID */
byte* singleCert;
word32 singleCertSz;
byte* issuer;
byte* singleCert; /* recipient cert, DER, not owner */
word32 singleCertSz; /* size of recipient cert buffer, bytes */
byte* issuer;
word32 issuerSz;
byte* privateKey; /* recipient private key, DER, not owner */
word32 privKeySize; /* size of private key buffer, bytes */
byte issuerSn[MAX_SN_SZ];
word32 issuerSnSz;
byte publicKey[512];
@ -87,6 +89,8 @@ typedef struct PKCS7 {
CYASSL_LOCAL int SetContentType(int pkcs7TypeOID, byte* output);
CYASSL_LOCAL int GetContentType(const byte* input, word32* inOutIdx,
word32* oid, word32 maxIdx);
CYASSL_LOCAL int CreateRecipientInfo(const byte* cert, word32 certSz,
int keyEncAlgo, int blockKeySz,
RNG* rng, byte* contentKeyPlain,
@ -99,6 +103,9 @@ CYASSL_API int PKCS7_EncodeSignedData(PKCS7* pkcs7,
byte* output, word32 outputSz);
CYASSL_API int PKCS7_EncodeEnvelopeData(PKCS7* pkcs7,
byte* output, word32 outputSz);
CYASSL_API int PKCS7_DecodeEnvelopedData(PKCS7* pkcs7, byte* pkiMsg,
word32 pkiMsgSz, byte* output,
word32 outputSz);
#ifdef __cplusplus
} /* extern "C" */

View File

@ -973,6 +973,8 @@ CYASSL_API int CyaSSL_GetObjectSize(void); /* object size based on build */
CYASSL_API int CyaSSL_SetVersion(CYASSL* ssl, int version);
CYASSL_API int CyaSSL_KeyPemToDer(const unsigned char*, int sz, unsigned char*,
int, const char*);
CYASSL_API int CyaSSL_CertPemToDer(const unsigned char*, int sz, unsigned char*,
int, int);
typedef void (*CallbackCACache)(unsigned char* der, int sz, int type);
typedef void (*CbMissingCRL)(const char* url);

View File

@ -1059,6 +1059,54 @@ int CyaSSL_CertManagerUnloadCAs(CYASSL_CERT_MANAGER* cm)
}
/* Return bytes written to buff or < 0 for error */
int CyaSSL_CertPemToDer(const unsigned char* pem, int pemSz,
unsigned char* buff, int buffSz,
int type)
{
EncryptedInfo info;
int eccKey = 0;
int ret;
buffer der;
CYASSL_ENTER("CyaSSL_CertPemToDer");
if (pem == NULL || buff == NULL || buffSz <= 0) {
CYASSL_MSG("Bad pem der args");
return BAD_FUNC_ARG;
}
if (type != CERT_TYPE && type != CA_TYPE && type != CERTREQ_TYPE) {
CYASSL_MSG("Bad cert type");
return BAD_FUNC_ARG;
}
info.set = 0;
info.ctx = NULL;
info.consumed = 0;
der.buffer = NULL;
ret = PemToDer(pem, pemSz, type, &der, NULL, &info, &eccKey);
if (ret < 0) {
CYASSL_MSG("Bad Pem To Der");
}
else {
if (der.length <= (word32)buffSz) {
XMEMCPY(buff, der.buffer, der.length);
ret = der.length;
}
else {
CYASSL_MSG("Bad der length");
ret = BAD_FUNC_ARG;
}
}
XFREE(der.buffer, NULL, DYNAMIC_TYPE_KEY);
return ret;
}
/* our KeyPemToDer password callback, password in userData */
static INLINE int OurPasswordCb(char* passwd, int sz, int rw, void* userdata)
{
@ -1582,6 +1630,12 @@ int CyaSSL_Init(void)
XSTRNCPY(footer, "-----END CERTIFICATE-----", sizeof(footer));
dynamicType = (type == CA_TYPE) ? DYNAMIC_TYPE_CA :
DYNAMIC_TYPE_CERT;
} else if (type == CERTREQ_TYPE) {
XSTRNCPY(header, "-----BEGIN CERTIFICATE REQUEST-----",
sizeof(header));
XSTRNCPY(footer, "-----END CERTIFICATE REQUEST-----",
sizeof(footer));
dynamicType = DYNAMIC_TYPE_KEY;
} else if (type == DH_PARAM_TYPE) {
XSTRNCPY(header, "-----BEGIN DH PARAMETERS-----", sizeof(header));
XSTRNCPY(footer, "-----END DH PARAMETERS-----", sizeof(footer));

View File

@ -974,7 +974,7 @@ int TLSX_SNI_GetFromBuffer(const byte* clientHello, word32 helloSz,
if (sniType != type) {
offset += sniLen;
listLen -= MIN(ENUM_LEN + OPAQUE16_LEN + sniLen, listLen);
listLen -= min(ENUM_LEN + OPAQUE16_LEN + sniLen, listLen);
continue;
}
@ -985,7 +985,7 @@ int TLSX_SNI_GetFromBuffer(const byte* clientHello, word32 helloSz,
}
}
len16 -= MIN(2 * OPAQUE16_LEN + extLen, len16);
len16 -= min(2 * OPAQUE16_LEN + extLen, len16);
}
return len16 ? BUFFER_ERROR : SSL_SUCCESS;

View File

@ -440,6 +440,8 @@ void test_CyaSSL_UseSNI(void)
CyaSSL_free(ssl);
CyaSSL_CTX_free(ctx);
#if !defined(NO_FILESYSTEM) && !defined(NO_CERTS)
/* Testing success case at ctx */
client_callbacks.ctx_ready = server_callbacks.ctx_ready = use_SNI_at_ctx;
server_callbacks.on_result = verify_SNI_real_matching;
@ -473,6 +475,8 @@ void test_CyaSSL_UseSNI(void)
test_CyaSSL_client_server(&client_callbacks, &server_callbacks);
#endif
test_CyaSSL_SNI_GetFromBuffer();
}
#endif /* HAVE_SNI */