forked from wolfSSL/wolfssl
Added encoding PKCS#7 signed data messages.
This commit is contained in:
2
.gitignore
vendored
2
.gitignore
vendored
@ -54,6 +54,8 @@ key.der
|
|||||||
key.pem
|
key.pem
|
||||||
certreq.der
|
certreq.der
|
||||||
certreq.pem
|
certreq.pem
|
||||||
|
pkcs7test.der
|
||||||
|
pkcs7test.pem
|
||||||
diff
|
diff
|
||||||
sslSniffer/sslSnifferTest/tracefile.txt
|
sslSniffer/sslSnifferTest/tracefile.txt
|
||||||
*.gz
|
*.gz
|
||||||
|
@ -2278,6 +2278,12 @@ CYASSL_LOCAL word32 SetSet(word32 len, byte* output)
|
|||||||
return SetLength(len, output + 1) + 1;
|
return SetLength(len, output + 1) + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CYASSL_LOCAL word32 SetTagged(byte tag, word32 len, byte* output)
|
||||||
|
{
|
||||||
|
output[0] = ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | tag;
|
||||||
|
return SetLength(len, output + 1) + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#if defined(HAVE_ECC) && defined(CYASSL_CERT_GEN)
|
#if defined(HAVE_ECC) && defined(CYASSL_CERT_GEN)
|
||||||
|
|
||||||
|
@ -30,6 +30,14 @@
|
|||||||
#include <cyassl/ctaocrypt/pkcs7.h>
|
#include <cyassl/ctaocrypt/pkcs7.h>
|
||||||
#include <cyassl/ctaocrypt/error.h>
|
#include <cyassl/ctaocrypt/error.h>
|
||||||
#include <cyassl/ctaocrypt/logging.h>
|
#include <cyassl/ctaocrypt/logging.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#ifndef min
|
||||||
|
static INLINE word32 min(word32 a, word32 b)
|
||||||
|
{
|
||||||
|
return a > b ? b : a;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
CYASSL_LOCAL int SetContentType(int pkcs7TypeOID, byte* output)
|
CYASSL_LOCAL int SetContentType(int pkcs7TypeOID, byte* output)
|
||||||
{
|
{
|
||||||
@ -109,11 +117,31 @@ CYASSL_LOCAL int SetContentType(int pkcs7TypeOID, byte* output)
|
|||||||
|
|
||||||
int PKCS7_InitWithCert(PKCS7* pkcs7, byte* cert, word32 certSz)
|
int PKCS7_InitWithCert(PKCS7* pkcs7, byte* cert, word32 certSz)
|
||||||
{
|
{
|
||||||
XMEMSET(pkcs7, 0, sizeof(PKCS7));
|
int ret = 0;
|
||||||
pkcs7->singleCert = cert;
|
|
||||||
pkcs7->singleCertSz = certSz;
|
|
||||||
|
|
||||||
return 0;
|
XMEMSET(pkcs7, 0, sizeof(PKCS7));
|
||||||
|
if (cert != NULL && certSz > 0) {
|
||||||
|
DecodedCert dCert;
|
||||||
|
|
||||||
|
pkcs7->singleCert = cert;
|
||||||
|
pkcs7->singleCertSz = certSz;
|
||||||
|
InitDecodedCert(&dCert, cert, certSz, 0);
|
||||||
|
|
||||||
|
ret = ParseCert(&dCert, CA_TYPE, NO_VERIFY, 0);
|
||||||
|
if (ret < 0) {
|
||||||
|
FreeDecodedCert(&dCert);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
XMEMCPY(pkcs7->publicKey, dCert.publicKey, dCert.pubKeySize);
|
||||||
|
pkcs7->publicKeySz = dCert.pubKeySize;
|
||||||
|
pkcs7->issuer = dCert.issuerRaw;
|
||||||
|
pkcs7->issuerSz = dCert.issuerRawLen;
|
||||||
|
XMEMCPY(pkcs7->issuerSn, dCert.serial, dCert.serialSz);
|
||||||
|
pkcs7->issuerSnSz = dCert.serialSz;
|
||||||
|
FreeDecodedCert(&dCert);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -126,18 +154,19 @@ int PKCS7_EncodeData(PKCS7* pkcs7, byte* output, word32 outputSz)
|
|||||||
byte octetStr[MAX_OCTET_STR_SZ];
|
byte octetStr[MAX_OCTET_STR_SZ];
|
||||||
word32 seqSz;
|
word32 seqSz;
|
||||||
word32 octetStrSz;
|
word32 octetStrSz;
|
||||||
|
word32 oidSz = (word32)sizeof(oid);
|
||||||
int idx = 0;
|
int idx = 0;
|
||||||
|
|
||||||
octetStrSz = SetOctetString(pkcs7->contentSz, octetStr);
|
octetStrSz = SetOctetString(pkcs7->contentSz, octetStr);
|
||||||
seqSz = SetSequence(pkcs7->contentSz + octetStrSz + sizeof(oid), seq);
|
seqSz = SetSequence(pkcs7->contentSz + octetStrSz + oidSz, seq);
|
||||||
|
|
||||||
if (outputSz < pkcs7->contentSz + octetStrSz + sizeof(oid) + seqSz)
|
if (outputSz < pkcs7->contentSz + octetStrSz + oidSz + seqSz)
|
||||||
return BUFFER_E;
|
return BUFFER_E;
|
||||||
|
|
||||||
XMEMCPY(output, seq, seqSz);
|
XMEMCPY(output, seq, seqSz);
|
||||||
idx += seqSz;
|
idx += seqSz;
|
||||||
XMEMCPY(output + idx, oid, sizeof(oid));
|
XMEMCPY(output + idx, oid, oidSz);
|
||||||
idx += sizeof(oid);
|
idx += oidSz;
|
||||||
XMEMCPY(output + idx, octetStr, octetStrSz);
|
XMEMCPY(output + idx, octetStr, octetStrSz);
|
||||||
idx += octetStrSz;
|
idx += octetStrSz;
|
||||||
XMEMCPY(output + idx, pkcs7->content, pkcs7->contentSz);
|
XMEMCPY(output + idx, pkcs7->content, pkcs7->contentSz);
|
||||||
@ -147,12 +176,325 @@ int PKCS7_EncodeData(PKCS7* pkcs7, byte* output, word32 outputSz)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct EncodedAttrib {
|
||||||
|
byte valueSeq[MAX_SEQ_SZ];
|
||||||
|
const byte* oid;
|
||||||
|
byte valueSet[MAX_SET_SZ];
|
||||||
|
const byte* value;
|
||||||
|
word32 valueSeqSz, oidSz, idSz, valueSetSz, valueSz, totalSz;
|
||||||
|
} EncodedAttrib;
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct ESD {
|
||||||
|
Sha sha;
|
||||||
|
byte contentDigest[SHA_DIGEST_SIZE + 2]; /* content only + ASN.1 heading */
|
||||||
|
byte contentAttribsDigest[SHA_DIGEST_SIZE]; /* content + attribs */
|
||||||
|
byte encContentDigest[512];
|
||||||
|
|
||||||
|
byte outerSeq[MAX_SEQ_SZ];
|
||||||
|
byte outerContent[MAX_EXP_SZ];
|
||||||
|
byte innerSeq[MAX_SEQ_SZ];
|
||||||
|
byte version[MAX_VERSION_SZ];
|
||||||
|
byte digAlgoIdSet[MAX_SET_SZ];
|
||||||
|
byte singleDigAlgoId[MAX_ALGO_SZ];
|
||||||
|
|
||||||
|
byte contentInfoSeq[MAX_SEQ_SZ];
|
||||||
|
byte innerContSeq[MAX_EXP_SZ];
|
||||||
|
byte innerOctets[MAX_OCTET_STR_SZ];
|
||||||
|
|
||||||
|
byte certsSet[MAX_SET_SZ];
|
||||||
|
|
||||||
|
byte signerInfoSet[MAX_SET_SZ];
|
||||||
|
byte signerInfoSeq[MAX_SEQ_SZ];
|
||||||
|
byte signerVersion[MAX_VERSION_SZ];
|
||||||
|
byte issuerSnSeq[MAX_SEQ_SZ];
|
||||||
|
byte issuerName[MAX_SEQ_SZ];
|
||||||
|
byte issuerSn[MAX_SN_SZ];
|
||||||
|
byte signerDigAlgoId[MAX_ALGO_SZ];
|
||||||
|
byte digEncAlgoId[MAX_ALGO_SZ];
|
||||||
|
byte signedAttribSet[MAX_SET_SZ];
|
||||||
|
EncodedAttrib signedAttribs[6];
|
||||||
|
byte signerDigest[MAX_OCTET_STR_SZ];
|
||||||
|
word32 innerOctetsSz, innerContSeqSz, contentInfoSeqSz;
|
||||||
|
word32 outerSeqSz, outerContentSz, innerSeqSz, versionSz, digAlgoIdSetSz,
|
||||||
|
singleDigAlgoIdSz, certsSetSz;
|
||||||
|
word32 signerInfoSetSz, signerInfoSeqSz, signerVersionSz,
|
||||||
|
issuerSnSeqSz, issuerNameSz, issuerSnSz,
|
||||||
|
signerDigAlgoIdSz, digEncAlgoIdSz, signerDigestSz;
|
||||||
|
word32 encContentDigestSz, signedAttribsSz, signedAttribsCount,
|
||||||
|
signedAttribSetSz;
|
||||||
|
} ESD;
|
||||||
|
|
||||||
|
|
||||||
|
static int EncodeAttributes(EncodedAttrib* ea, int eaSz,
|
||||||
|
PKCS7Attrib* attribs, int attribsSz)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
int maxSz = min(eaSz, attribsSz);
|
||||||
|
int allAttribsSz = 0;
|
||||||
|
|
||||||
|
for (i = 0; i < maxSz; i++)
|
||||||
|
{
|
||||||
|
int attribSz = 0;
|
||||||
|
|
||||||
|
ea[i].value = attribs[i].value;
|
||||||
|
ea[i].valueSz = attribs[i].valueSz;
|
||||||
|
attribSz += ea[i].valueSz;
|
||||||
|
ea[i].valueSetSz = SetSet(attribSz, ea[i].valueSet);
|
||||||
|
attribSz += ea[i].valueSetSz;
|
||||||
|
ea[i].oid = attribs[i].oid;
|
||||||
|
ea[i].oidSz = attribs[i].oidSz;
|
||||||
|
attribSz += ea[i].oidSz;
|
||||||
|
ea[i].valueSeqSz = SetSequence(attribSz, ea[i].valueSeq);
|
||||||
|
attribSz += ea[i].valueSeqSz;
|
||||||
|
ea[i].totalSz = attribSz;
|
||||||
|
|
||||||
|
allAttribsSz += attribSz;
|
||||||
|
}
|
||||||
|
return allAttribsSz;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int FlattenAttributes(byte* output, EncodedAttrib* ea, int eaSz)
|
||||||
|
{
|
||||||
|
int i, idx;
|
||||||
|
|
||||||
|
idx = 0;
|
||||||
|
for (i = 0; i < eaSz; i++) {
|
||||||
|
XMEMCPY(output + idx, ea[i].valueSeq, ea[i].valueSeqSz);
|
||||||
|
idx += ea[i].valueSeqSz;
|
||||||
|
XMEMCPY(output + idx, ea[i].oid, ea[i].oidSz);
|
||||||
|
idx += ea[i].oidSz;
|
||||||
|
XMEMCPY(output + idx, ea[i].valueSet, ea[i].valueSetSz);
|
||||||
|
idx += ea[i].valueSetSz;
|
||||||
|
XMEMCPY(output + idx, ea[i].value, ea[i].valueSz);
|
||||||
|
idx += ea[i].valueSz;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int PKCS7_EncodeSignedData(PKCS7* pkcs7, byte* output, word32 outputSz)
|
int PKCS7_EncodeSignedData(PKCS7* pkcs7, byte* output, word32 outputSz)
|
||||||
{
|
{
|
||||||
(void)pkcs7;
|
static const byte outerOid[] =
|
||||||
(void)output;
|
{ ASN_OBJECT_ID, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01,
|
||||||
(void)outputSz;
|
0x07, 0x02 };
|
||||||
return 0;
|
static const byte innerOid[] =
|
||||||
|
{ ASN_OBJECT_ID, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01,
|
||||||
|
0x07, 0x01 };
|
||||||
|
|
||||||
|
ESD esd;
|
||||||
|
word32 signerInfoSz = 0;
|
||||||
|
word32 totalSz = 0;
|
||||||
|
int idx = 0;
|
||||||
|
byte* flatSignedAttribs = NULL;
|
||||||
|
word32 flatSignedAttribsSz = 0;
|
||||||
|
|
||||||
|
XMEMSET(&esd, 0, sizeof(esd));
|
||||||
|
InitSha(&esd.sha);
|
||||||
|
|
||||||
|
if (pkcs7->contentSz != 0)
|
||||||
|
{
|
||||||
|
ShaUpdate(&esd.sha, pkcs7->content, pkcs7->contentSz);
|
||||||
|
esd.contentDigest[0] = ASN_OCTET_STRING;
|
||||||
|
esd.contentDigest[1] = SHA_DIGEST_SIZE;
|
||||||
|
ShaFinal(&esd.sha, &esd.contentDigest[2]);
|
||||||
|
}
|
||||||
|
|
||||||
|
esd.innerOctetsSz = SetOctetString(pkcs7->contentSz, esd.innerOctets);
|
||||||
|
esd.innerContSeqSz = SetTagged(0, esd.innerOctetsSz + pkcs7->contentSz,
|
||||||
|
esd.innerContSeq);
|
||||||
|
esd.contentInfoSeqSz = SetSequence(pkcs7->contentSz + esd.innerOctetsSz +
|
||||||
|
sizeof(innerOid) + esd.innerContSeqSz,
|
||||||
|
esd.contentInfoSeq);
|
||||||
|
|
||||||
|
esd.issuerSnSz = SetSerialNumber(pkcs7->issuerSn, pkcs7->issuerSnSz,
|
||||||
|
esd.issuerSn);
|
||||||
|
signerInfoSz += esd.issuerSnSz;
|
||||||
|
esd.issuerNameSz = SetSequence(pkcs7->issuerSz, esd.issuerName);
|
||||||
|
signerInfoSz += esd.issuerNameSz + pkcs7->issuerSz;
|
||||||
|
esd.issuerSnSeqSz = SetSequence(signerInfoSz, esd.issuerSnSeq);
|
||||||
|
signerInfoSz += esd.issuerSnSeqSz;
|
||||||
|
esd.signerVersionSz = SetMyVersion(1, esd.signerVersion, 0);
|
||||||
|
signerInfoSz += esd.signerVersionSz;
|
||||||
|
esd.signerDigAlgoIdSz = SetAlgoID(pkcs7->hashOID, esd.signerDigAlgoId,
|
||||||
|
hashType, 0);
|
||||||
|
signerInfoSz += esd.signerDigAlgoIdSz;
|
||||||
|
esd.digEncAlgoIdSz = SetAlgoID(pkcs7->encryptOID, esd.digEncAlgoId,
|
||||||
|
keyType, 0);
|
||||||
|
signerInfoSz += esd.digEncAlgoIdSz;
|
||||||
|
|
||||||
|
if (pkcs7->signedAttribsSz != 0) {
|
||||||
|
byte contentTypeOid[] =
|
||||||
|
{ ASN_OBJECT_ID, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xF7, 0x0d, 0x01,
|
||||||
|
0x09, 0x03 };
|
||||||
|
byte contentType[] =
|
||||||
|
{ ASN_OBJECT_ID, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01,
|
||||||
|
0x07, 0x01 };
|
||||||
|
byte messageDigestOid[] =
|
||||||
|
{ ASN_OBJECT_ID, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01,
|
||||||
|
0x09, 0x04 };
|
||||||
|
|
||||||
|
PKCS7Attrib cannedAttribs[2] =
|
||||||
|
{
|
||||||
|
{ contentTypeOid, sizeof(contentTypeOid),
|
||||||
|
contentType, sizeof(contentType) },
|
||||||
|
{ messageDigestOid, sizeof(messageDigestOid),
|
||||||
|
esd.contentDigest, sizeof(esd.contentDigest) }
|
||||||
|
};
|
||||||
|
word32 cannedAttribsCount = sizeof(cannedAttribs)/sizeof(PKCS7Attrib);
|
||||||
|
|
||||||
|
esd.signedAttribsCount += cannedAttribsCount;
|
||||||
|
esd.signedAttribsSz += EncodeAttributes(&esd.signedAttribs[0], 2,
|
||||||
|
cannedAttribs, cannedAttribsCount);
|
||||||
|
|
||||||
|
esd.signedAttribsCount += pkcs7->signedAttribsSz;
|
||||||
|
esd.signedAttribsSz += EncodeAttributes(&esd.signedAttribs[2], 4,
|
||||||
|
pkcs7->signedAttribs, pkcs7->signedAttribsSz);
|
||||||
|
|
||||||
|
flatSignedAttribs = (byte*)XMALLOC(esd.signedAttribsSz, 0, NULL);
|
||||||
|
flatSignedAttribsSz = esd.signedAttribsSz;
|
||||||
|
if (flatSignedAttribs == NULL)
|
||||||
|
return MEMORY_E;
|
||||||
|
FlattenAttributes(flatSignedAttribs,
|
||||||
|
esd.signedAttribs, esd.signedAttribsCount);
|
||||||
|
esd.signedAttribSetSz = SetTagged(0, esd.signedAttribsSz,
|
||||||
|
esd.signedAttribSet);
|
||||||
|
}
|
||||||
|
/* Calculate the final hash and encrypt it. */
|
||||||
|
{
|
||||||
|
RsaKey pubKey;
|
||||||
|
int result;
|
||||||
|
word32 scratch = 0;
|
||||||
|
|
||||||
|
if (pkcs7->signedAttribsSz != 0) {
|
||||||
|
byte attribSet[MAX_SET_SZ];
|
||||||
|
word32 attribSetSz;
|
||||||
|
|
||||||
|
attribSetSz = SetSet(flatSignedAttribsSz, attribSet);
|
||||||
|
|
||||||
|
ShaUpdate(&esd.sha, attribSet, attribSetSz);
|
||||||
|
ShaUpdate(&esd.sha, flatSignedAttribs, flatSignedAttribsSz);
|
||||||
|
}
|
||||||
|
ShaFinal(&esd.sha, esd.contentAttribsDigest);
|
||||||
|
|
||||||
|
InitRsaKey(&pubKey, NULL);
|
||||||
|
result = RsaPublicKeyDecode(pkcs7->publicKey, &scratch, &pubKey,
|
||||||
|
pkcs7->publicKeySz);
|
||||||
|
if (result < 0) {
|
||||||
|
XFREE(flatSignedAttribs, 0, NULL);
|
||||||
|
return PUBLIC_KEY_E;
|
||||||
|
}
|
||||||
|
result = RsaPublicEncrypt(esd.contentAttribsDigest,
|
||||||
|
sizeof(esd.contentAttribsDigest),
|
||||||
|
esd.encContentDigest,
|
||||||
|
sizeof(esd.encContentDigest), &pubKey,
|
||||||
|
pkcs7->rng);
|
||||||
|
FreeRsaKey(&pubKey);
|
||||||
|
if (result < 0) {
|
||||||
|
XFREE(flatSignedAttribs, 0, NULL);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
esd.encContentDigestSz = (word32)result;
|
||||||
|
}
|
||||||
|
signerInfoSz += flatSignedAttribsSz + esd.signedAttribSetSz;
|
||||||
|
|
||||||
|
esd.signerDigestSz = SetOctetString(esd.encContentDigestSz,
|
||||||
|
esd.signerDigest);
|
||||||
|
signerInfoSz += esd.signerDigestSz + esd.encContentDigestSz;
|
||||||
|
|
||||||
|
esd.signerInfoSeqSz = SetSequence(signerInfoSz, esd.signerInfoSeq);
|
||||||
|
signerInfoSz += esd.signerInfoSeqSz;
|
||||||
|
esd.signerInfoSetSz = SetSet(signerInfoSz, esd.signerInfoSet);
|
||||||
|
signerInfoSz += esd.signerInfoSetSz;
|
||||||
|
|
||||||
|
esd.certsSetSz = SetTagged(0, pkcs7->singleCertSz, esd.certsSet);
|
||||||
|
|
||||||
|
esd.singleDigAlgoIdSz = SetAlgoID(pkcs7->hashOID, esd.singleDigAlgoId,
|
||||||
|
hashType, 0);
|
||||||
|
esd.digAlgoIdSetSz = SetSet(esd.singleDigAlgoIdSz, esd.digAlgoIdSet);
|
||||||
|
|
||||||
|
|
||||||
|
esd.versionSz = SetMyVersion(1, esd.version, 0);
|
||||||
|
|
||||||
|
totalSz = esd.versionSz + esd.singleDigAlgoIdSz + esd.digAlgoIdSetSz +
|
||||||
|
esd.contentInfoSeqSz + esd.certsSetSz + pkcs7->singleCertSz +
|
||||||
|
esd.innerOctetsSz + esd.innerContSeqSz +
|
||||||
|
sizeof(innerOid) + pkcs7->contentSz +
|
||||||
|
signerInfoSz;
|
||||||
|
esd.innerSeqSz = SetSequence(totalSz, esd.innerSeq);
|
||||||
|
totalSz += esd.innerSeqSz;
|
||||||
|
esd.outerContentSz = SetTagged(0, totalSz, esd.outerContent);
|
||||||
|
totalSz += esd.outerContentSz + sizeof(outerOid);
|
||||||
|
esd.outerSeqSz = SetSequence(totalSz, esd.outerSeq);
|
||||||
|
totalSz += esd.outerSeqSz;
|
||||||
|
|
||||||
|
if (outputSz < totalSz)
|
||||||
|
return BUFFER_E;
|
||||||
|
|
||||||
|
idx = 0;
|
||||||
|
XMEMCPY(output + idx, esd.outerSeq, esd.outerSeqSz);
|
||||||
|
idx += esd.outerSeqSz;
|
||||||
|
XMEMCPY(output + idx, outerOid, sizeof(outerOid));
|
||||||
|
idx += sizeof(outerOid);
|
||||||
|
XMEMCPY(output + idx, esd.outerContent, esd.outerContentSz);
|
||||||
|
idx += esd.outerContentSz;
|
||||||
|
XMEMCPY(output + idx, esd.innerSeq, esd.innerSeqSz);
|
||||||
|
idx += esd.innerSeqSz;
|
||||||
|
XMEMCPY(output + idx, esd.version, esd.versionSz);
|
||||||
|
idx += esd.versionSz;
|
||||||
|
XMEMCPY(output + idx, esd.digAlgoIdSet, esd.digAlgoIdSetSz);
|
||||||
|
idx += esd.digAlgoIdSetSz;
|
||||||
|
XMEMCPY(output + idx, esd.singleDigAlgoId, esd.singleDigAlgoIdSz);
|
||||||
|
idx += esd.singleDigAlgoIdSz;
|
||||||
|
XMEMCPY(output + idx, esd.contentInfoSeq, esd.contentInfoSeqSz);
|
||||||
|
idx += esd.contentInfoSeqSz;
|
||||||
|
XMEMCPY(output + idx, innerOid, sizeof(innerOid));
|
||||||
|
idx += sizeof(innerOid);
|
||||||
|
XMEMCPY(output + idx, esd.innerContSeq, esd.innerContSeqSz);
|
||||||
|
idx += esd.innerContSeqSz;
|
||||||
|
XMEMCPY(output + idx, esd.innerOctets, esd.innerOctetsSz);
|
||||||
|
idx += esd.innerOctetsSz;
|
||||||
|
XMEMCPY(output + idx, pkcs7->content, pkcs7->contentSz);
|
||||||
|
idx += pkcs7->contentSz;
|
||||||
|
XMEMCPY(output + idx, esd.certsSet, esd.certsSetSz);
|
||||||
|
idx += esd.certsSetSz;
|
||||||
|
XMEMCPY(output + idx, pkcs7->singleCert, pkcs7->singleCertSz);
|
||||||
|
idx += pkcs7->singleCertSz;
|
||||||
|
XMEMCPY(output + idx, esd.signerInfoSet, esd.signerInfoSetSz);
|
||||||
|
idx += esd.signerInfoSetSz;
|
||||||
|
XMEMCPY(output + idx, esd.signerInfoSeq, esd.signerInfoSeqSz);
|
||||||
|
idx += esd.signerInfoSeqSz;
|
||||||
|
XMEMCPY(output + idx, esd.signerVersion, esd.signerVersionSz);
|
||||||
|
idx += esd.signerVersionSz;
|
||||||
|
XMEMCPY(output + idx, esd.issuerSnSeq, esd.issuerSnSeqSz);
|
||||||
|
idx += esd.issuerSnSeqSz;
|
||||||
|
XMEMCPY(output + idx, esd.issuerName, esd.issuerNameSz);
|
||||||
|
idx += esd.issuerNameSz;
|
||||||
|
XMEMCPY(output + idx, pkcs7->issuer, pkcs7->issuerSz);
|
||||||
|
idx += pkcs7->issuerSz;
|
||||||
|
XMEMCPY(output + idx, esd.issuerSn, esd.issuerSnSz);
|
||||||
|
idx += esd.issuerSnSz;
|
||||||
|
XMEMCPY(output + idx, esd.signerDigAlgoId, esd.signerDigAlgoIdSz);
|
||||||
|
idx += esd.signerDigAlgoIdSz;
|
||||||
|
|
||||||
|
/* SignerInfo:Attributes */
|
||||||
|
if (pkcs7->signedAttribsSz != 0) {
|
||||||
|
XMEMCPY(output + idx, esd.signedAttribSet, esd.signedAttribSetSz);
|
||||||
|
idx += esd.signedAttribSetSz;
|
||||||
|
XMEMCPY(output + idx, flatSignedAttribs, flatSignedAttribsSz);
|
||||||
|
idx += flatSignedAttribsSz;
|
||||||
|
XFREE(flatSignedAttribs, 0, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
XMEMCPY(output + idx, esd.digEncAlgoId, esd.digEncAlgoIdSz);
|
||||||
|
idx += esd.digEncAlgoIdSz;
|
||||||
|
XMEMCPY(output + idx, esd.signerDigest, esd.signerDigestSz);
|
||||||
|
idx += esd.signerDigestSz;
|
||||||
|
XMEMCPY(output + idx, esd.encContentDigest, esd.encContentDigestSz);
|
||||||
|
idx += esd.encContentDigestSz;
|
||||||
|
|
||||||
|
return idx;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -61,6 +61,9 @@
|
|||||||
#ifdef HAVE_LIBZ
|
#ifdef HAVE_LIBZ
|
||||||
#include <cyassl/ctaocrypt/compress.h>
|
#include <cyassl/ctaocrypt/compress.h>
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef HAVE_PKCS7
|
||||||
|
#include <cyassl/ctaocrypt/pkcs7.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
/* 4996 warning to use MS extensions e.g., strcpy_s instead of strncpy */
|
/* 4996 warning to use MS extensions e.g., strcpy_s instead of strncpy */
|
||||||
@ -174,6 +177,9 @@ int pbkdf2_test(void);
|
|||||||
#ifdef HAVE_LIBZ
|
#ifdef HAVE_LIBZ
|
||||||
int compress_test(void);
|
int compress_test(void);
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef HAVE_PKCS7
|
||||||
|
int pkcs7_test(void);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -458,6 +464,13 @@ void ctaocrypt_test(void* args)
|
|||||||
printf( "COMPRESS test passed!\n");
|
printf( "COMPRESS test passed!\n");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAVE_PKCS7
|
||||||
|
if ( (ret = pkcs7_test()) != 0)
|
||||||
|
err_sys("PKCS7 test failed!\n", ret);
|
||||||
|
else
|
||||||
|
printf( "PKCS7 test passed!\n");
|
||||||
|
#endif
|
||||||
|
|
||||||
((func_args*)args)->return_code = ret;
|
((func_args*)args)->return_code = ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4009,4 +4022,118 @@ int compress_test(void)
|
|||||||
|
|
||||||
#endif /* HAVE_LIBZ */
|
#endif /* HAVE_LIBZ */
|
||||||
|
|
||||||
|
#ifdef HAVE_PKCS7
|
||||||
|
|
||||||
|
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[] =
|
||||||
|
{
|
||||||
|
{ 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) }
|
||||||
|
};
|
||||||
|
|
||||||
|
dataSz = (word32) strlen(data);
|
||||||
|
outSz = sizeof(out);
|
||||||
|
|
||||||
|
cert = (byte*)malloc(FOURK_BUF);
|
||||||
|
if (cert == NULL)
|
||||||
|
return -40;
|
||||||
|
|
||||||
|
/* read in DER cert of recipient, into cert of size certSz */
|
||||||
|
file = fopen(clientCert, "rb");
|
||||||
|
|
||||||
|
if (!file)
|
||||||
|
err_sys("can't open ./certs/client-cert.der, "
|
||||||
|
"Please run from CyaSSL home dir", -40);
|
||||||
|
|
||||||
|
certSz = (word32)fread(cert, 1, FOURK_BUF, file);
|
||||||
|
fclose(file);
|
||||||
|
|
||||||
|
ret = InitRng(&rng);
|
||||||
|
senderNonce[0] = 0x04;
|
||||||
|
senderNonce[1] = 0x20;
|
||||||
|
RNG_GenerateBlock(&rng, &senderNonce[2], 32);
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
/* 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);
|
||||||
|
|
||||||
|
if (ret > 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* HAVE_PKCS7 */
|
||||||
|
|
||||||
#endif /* NO_CRYPT_TEST */
|
#endif /* NO_CRYPT_TEST */
|
||||||
|
@ -127,6 +127,7 @@ enum Misc_ASN {
|
|||||||
MAX_SEQ_SZ = 5, /* enum(seq | con) + length(4) */
|
MAX_SEQ_SZ = 5, /* enum(seq | con) + length(4) */
|
||||||
MAX_SET_SZ = 5, /* enum(set | con) + length(4) */
|
MAX_SET_SZ = 5, /* enum(set | con) + length(4) */
|
||||||
MAX_OCTET_STR_SZ = 5, /* enum(set | con) + length(4) */
|
MAX_OCTET_STR_SZ = 5, /* enum(set | con) + length(4) */
|
||||||
|
MAX_EXP_SZ = 5, /* enum(contextspec|con|exp) + length(4) */
|
||||||
MAX_PRSTR_SZ = 5, /* enum(prstr) + length(4) */
|
MAX_PRSTR_SZ = 5, /* enum(prstr) + length(4) */
|
||||||
MAX_VERSION_SZ = 5, /* enum + id + version(byte) + (header(2))*/
|
MAX_VERSION_SZ = 5, /* enum + id + version(byte) + (header(2))*/
|
||||||
MAX_ENCODED_DIG_SZ = 73, /* sha512 + enum(bit or octet) + legnth(4) */
|
MAX_ENCODED_DIG_SZ = 73, /* sha512 + enum(bit or octet) + legnth(4) */
|
||||||
@ -448,6 +449,7 @@ CYASSL_LOCAL int GetLength(const byte* input, word32* inOutIdx, int* len,
|
|||||||
CYASSL_LOCAL word32 SetLength(word32 length, byte* output);
|
CYASSL_LOCAL word32 SetLength(word32 length, byte* output);
|
||||||
CYASSL_LOCAL word32 SetSequence(word32 len, byte* output);
|
CYASSL_LOCAL word32 SetSequence(word32 len, byte* output);
|
||||||
CYASSL_LOCAL word32 SetOctetString(word32 len, byte* output);
|
CYASSL_LOCAL word32 SetOctetString(word32 len, byte* output);
|
||||||
|
CYASSL_LOCAL word32 SetTagged(byte tag, word32 len, byte* output);
|
||||||
CYASSL_LOCAL word32 SetSet(word32 len, byte* output);
|
CYASSL_LOCAL word32 SetSet(word32 len, byte* output);
|
||||||
CYASSL_LOCAL word32 SetAlgoID(int algoOID, byte* output, int type, int curveSz);
|
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 SetMyVersion(word32 version, byte* output, int header);
|
||||||
|
@ -67,6 +67,8 @@ typedef struct PKCS7 {
|
|||||||
word32 contentSz;
|
word32 contentSz;
|
||||||
int contentOID;
|
int contentOID;
|
||||||
|
|
||||||
|
RNG* rng;
|
||||||
|
|
||||||
int hashOID;
|
int hashOID;
|
||||||
int encryptOID;
|
int encryptOID;
|
||||||
|
|
||||||
@ -74,9 +76,13 @@ typedef struct PKCS7 {
|
|||||||
word32 singleCertSz;
|
word32 singleCertSz;
|
||||||
byte* issuer;
|
byte* issuer;
|
||||||
word32 issuerSz;
|
word32 issuerSz;
|
||||||
|
byte issuerSn[MAX_SN_SZ];
|
||||||
|
word32 issuerSnSz;
|
||||||
|
byte publicKey[512];
|
||||||
|
word32 publicKeySz;
|
||||||
|
|
||||||
PKCS7Attrib** signedAttribs;
|
PKCS7Attrib* signedAttribs;
|
||||||
word32 signedAttribsSz; /* Number of attribs in list */
|
word32 signedAttribsSz;
|
||||||
} PKCS7;
|
} PKCS7;
|
||||||
|
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user