mirror of
https://github.com/wolfSSL/wolfssl.git
synced 2025-08-03 12:44:45 +02:00
PKCS7_VerifySignedMessage() decodes more of the
message and performs an RSA verify on it.
This commit is contained in:
@@ -228,7 +228,7 @@ typedef struct EncodedAttrib {
|
|||||||
typedef struct ESD {
|
typedef struct ESD {
|
||||||
Sha sha;
|
Sha sha;
|
||||||
byte contentDigest[SHA_DIGEST_SIZE + 2]; /* content only + ASN.1 heading */
|
byte contentDigest[SHA_DIGEST_SIZE + 2]; /* content only + ASN.1 heading */
|
||||||
byte contentAttribsDigest[SHA_DIGEST_SIZE]; /* content + attribs */
|
byte contentAttribsDigest[SHA_DIGEST_SIZE];
|
||||||
byte encContentDigest[512];
|
byte encContentDigest[512];
|
||||||
|
|
||||||
byte outerSeq[MAX_SEQ_SZ];
|
byte outerSeq[MAX_SEQ_SZ];
|
||||||
@@ -417,17 +417,40 @@ int PKCS7_EncodeSignedData(PKCS7* pkcs7, byte* output, word32 outputSz)
|
|||||||
int result;
|
int result;
|
||||||
word32 scratch = 0;
|
word32 scratch = 0;
|
||||||
|
|
||||||
|
byte digestInfo[MAX_SEQ_SZ + MAX_ALGO_SZ +
|
||||||
|
MAX_OCTET_STR_SZ + SHA_DIGEST_SIZE];
|
||||||
|
byte digestInfoSeq[MAX_SEQ_SZ];
|
||||||
|
byte digestStr[MAX_OCTET_STR_SZ];
|
||||||
|
word32 digestInfoSeqSz, digestStrSz;
|
||||||
|
int digIdx = 0;
|
||||||
|
|
||||||
if (pkcs7->signedAttribsSz != 0) {
|
if (pkcs7->signedAttribsSz != 0) {
|
||||||
byte attribSet[MAX_SET_SZ];
|
byte attribSet[MAX_SET_SZ];
|
||||||
word32 attribSetSz;
|
word32 attribSetSz;
|
||||||
|
|
||||||
attribSetSz = SetSet(flatSignedAttribsSz, attribSet);
|
attribSetSz = SetSet(flatSignedAttribsSz, attribSet);
|
||||||
|
|
||||||
|
InitSha(&esd.sha);
|
||||||
ShaUpdate(&esd.sha, attribSet, attribSetSz);
|
ShaUpdate(&esd.sha, attribSet, attribSetSz);
|
||||||
ShaUpdate(&esd.sha, flatSignedAttribs, flatSignedAttribsSz);
|
ShaUpdate(&esd.sha, flatSignedAttribs, flatSignedAttribsSz);
|
||||||
}
|
}
|
||||||
ShaFinal(&esd.sha, esd.contentAttribsDigest);
|
ShaFinal(&esd.sha, esd.contentAttribsDigest);
|
||||||
|
|
||||||
|
digestStrSz = SetOctetString(SHA_DIGEST_SIZE, digestStr);
|
||||||
|
digestInfoSeqSz = SetSequence(esd.signerDigAlgoIdSz +
|
||||||
|
digestStrSz + SHA_DIGEST_SIZE,
|
||||||
|
digestInfoSeq);
|
||||||
|
|
||||||
|
XMEMCPY(digestInfo + digIdx, digestInfoSeq, digestInfoSeqSz);
|
||||||
|
digIdx += digestInfoSeqSz;
|
||||||
|
XMEMCPY(digestInfo + digIdx,
|
||||||
|
esd.signerDigAlgoId, esd.signerDigAlgoIdSz);
|
||||||
|
digIdx += esd.signerDigAlgoIdSz;
|
||||||
|
XMEMCPY(digestInfo + digIdx, digestStr, digestStrSz);
|
||||||
|
digIdx += digestStrSz;
|
||||||
|
XMEMCPY(digestInfo + digIdx, esd.contentAttribsDigest, SHA_DIGEST_SIZE);
|
||||||
|
digIdx += SHA_DIGEST_SIZE;
|
||||||
|
|
||||||
InitRsaKey(&privKey, NULL);
|
InitRsaKey(&privKey, NULL);
|
||||||
result = RsaPrivateKeyDecode(pkcs7->privateKey, &scratch, &privKey,
|
result = RsaPrivateKeyDecode(pkcs7->privateKey, &scratch, &privKey,
|
||||||
pkcs7->privateKeySz);
|
pkcs7->privateKeySz);
|
||||||
@@ -435,11 +458,9 @@ int PKCS7_EncodeSignedData(PKCS7* pkcs7, byte* output, word32 outputSz)
|
|||||||
XFREE(flatSignedAttribs, 0, NULL);
|
XFREE(flatSignedAttribs, 0, NULL);
|
||||||
return PUBLIC_KEY_E;
|
return PUBLIC_KEY_E;
|
||||||
}
|
}
|
||||||
result = RsaSSL_Sign(esd.contentAttribsDigest,
|
result = RsaSSL_Sign(digestInfo, digIdx,
|
||||||
sizeof(esd.contentAttribsDigest),
|
esd.encContentDigest, sizeof(esd.encContentDigest),
|
||||||
esd.encContentDigest,
|
&privKey, pkcs7->rng);
|
||||||
sizeof(esd.encContentDigest), &privKey,
|
|
||||||
pkcs7->rng);
|
|
||||||
FreeRsaKey(&privKey);
|
FreeRsaKey(&privKey);
|
||||||
if (result < 0) {
|
if (result < 0) {
|
||||||
XFREE(flatSignedAttribs, 0, NULL);
|
XFREE(flatSignedAttribs, 0, NULL);
|
||||||
@@ -553,7 +574,11 @@ int PKCS7_VerifySignedData(PKCS7* pkcs7, byte* pkiMsg, word32 pkiMsgSz)
|
|||||||
{
|
{
|
||||||
word32 idx, contentType;
|
word32 idx, contentType;
|
||||||
int length, version;
|
int length, version;
|
||||||
byte b;
|
byte* content = NULL;
|
||||||
|
byte* sig = NULL;
|
||||||
|
byte* cert = NULL;
|
||||||
|
byte* signedAttr = NULL;
|
||||||
|
int contentSz = 0, sigSz = 0, certSz = 0, signedAttrSz = 0;
|
||||||
|
|
||||||
if (pkcs7 == NULL || pkiMsg == NULL || pkiMsgSz == 0)
|
if (pkcs7 == NULL || pkiMsg == NULL || pkiMsgSz == 0)
|
||||||
return BAD_FUNC_ARG;
|
return BAD_FUNC_ARG;
|
||||||
@@ -613,27 +638,27 @@ int PKCS7_VerifySignedData(PKCS7* pkcs7, byte* pkiMsg, word32 pkiMsgSz)
|
|||||||
return PKCS7_OID_E;
|
return PKCS7_OID_E;
|
||||||
}
|
}
|
||||||
|
|
||||||
b = pkiMsg[idx++];
|
if (pkiMsg[idx++] != (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0))
|
||||||
if (b != (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0))
|
|
||||||
return ASN_PARSE_E;
|
return ASN_PARSE_E;
|
||||||
|
|
||||||
if (GetLength(pkiMsg, &idx, &length, pkiMsgSz) < 0)
|
if (GetLength(pkiMsg, &idx, &length, pkiMsgSz) < 0)
|
||||||
return ASN_PARSE_E;
|
return ASN_PARSE_E;
|
||||||
|
|
||||||
b = pkiMsg[idx++];
|
if (pkiMsg[idx++] != ASN_OCTET_STRING)
|
||||||
|
return ASN_PARSE_E;
|
||||||
|
|
||||||
if (GetLength(pkiMsg, &idx, &length, pkiMsgSz) < 0)
|
if (GetLength(pkiMsg, &idx, &length, pkiMsgSz) < 0)
|
||||||
return ASN_PARSE_E;
|
return ASN_PARSE_E;
|
||||||
|
|
||||||
/* Save the inner data as the content. */
|
/* Save the inner data as the content. */
|
||||||
if (length > 0) {
|
if (length > 0) {
|
||||||
pkcs7->content = &pkiMsg[idx];
|
content = &pkiMsg[idx];
|
||||||
pkcs7->contentSz = length;
|
contentSz = length;
|
||||||
idx += length;
|
idx += length;
|
||||||
}
|
}
|
||||||
|
|
||||||
b = pkiMsg[idx];
|
|
||||||
/* Get the implicit[0] set of certificates */
|
/* Get the implicit[0] set of certificates */
|
||||||
if (b == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0)) {
|
if (pkiMsg[idx] == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0)) {
|
||||||
idx++;
|
idx++;
|
||||||
if (GetLength(pkiMsg, &idx, &length, pkiMsgSz) < 0)
|
if (GetLength(pkiMsg, &idx, &length, pkiMsgSz) < 0)
|
||||||
return ASN_PARSE_E;
|
return ASN_PARSE_E;
|
||||||
@@ -647,18 +672,114 @@ int PKCS7_VerifySignedData(PKCS7* pkcs7, byte* pkiMsg, word32 pkiMsgSz)
|
|||||||
|
|
||||||
word32 certIdx = idx;
|
word32 certIdx = idx;
|
||||||
|
|
||||||
b = pkiMsg[certIdx++];
|
if (pkiMsg[certIdx++] == (ASN_CONSTRUCTED | ASN_SEQUENCE)) {
|
||||||
if (b == (ASN_CONSTRUCTED | ASN_SEQUENCE)) {
|
|
||||||
int certSz;
|
|
||||||
|
|
||||||
if (GetLength(pkiMsg, &certIdx, &certSz, pkiMsgSz) < 0)
|
if (GetLength(pkiMsg, &certIdx, &certSz, pkiMsgSz) < 0)
|
||||||
return ASN_PARSE_E;
|
return ASN_PARSE_E;
|
||||||
|
|
||||||
pkcs7->singleCert = &pkiMsg[idx];
|
cert = &pkiMsg[idx];
|
||||||
pkcs7->singleCertSz = certSz + (certIdx - idx);
|
certSz += (certIdx - idx);
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
idx += length;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Get the implicit[1] set of crls */
|
||||||
|
if (pkiMsg[idx] == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 1)) {
|
||||||
|
idx++;
|
||||||
|
if (GetLength(pkiMsg, &idx, &length, pkiMsgSz) < 0)
|
||||||
|
return ASN_PARSE_E;
|
||||||
|
|
||||||
|
/* Skip the set */
|
||||||
|
idx += length;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Get the set of signerInfos */
|
||||||
|
if (GetSet(pkiMsg, &idx, &length, pkiMsgSz) < 0)
|
||||||
|
return ASN_PARSE_E;
|
||||||
|
|
||||||
|
/* Get the sequence of the first signerInfo */
|
||||||
|
if (GetSequence(pkiMsg, &idx, &length, pkiMsgSz) < 0)
|
||||||
|
return ASN_PARSE_E;
|
||||||
|
|
||||||
|
/* Get the version */
|
||||||
|
if (GetMyVersion(pkiMsg, &idx, &version) < 0)
|
||||||
|
return ASN_PARSE_E;
|
||||||
|
|
||||||
|
if (version != 1) {
|
||||||
|
CYASSL_MSG("PKCS#7 signerInfo needs to be of version 1");
|
||||||
|
return ASN_VERSION_E;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Get the sequence of IssuerAndSerialNumber */
|
||||||
|
if (GetSequence(pkiMsg, &idx, &length, pkiMsgSz) < 0)
|
||||||
|
return ASN_PARSE_E;
|
||||||
|
|
||||||
|
/* Skip it */
|
||||||
|
idx += length;
|
||||||
|
|
||||||
|
/* Get the sequence of digestAlgorithm */
|
||||||
|
if (GetSequence(pkiMsg, &idx, &length, pkiMsgSz) < 0)
|
||||||
|
return ASN_PARSE_E;
|
||||||
|
|
||||||
|
/* Skip it */
|
||||||
|
idx += length;
|
||||||
|
|
||||||
|
/* Get the IMPLICIT[0] SET OF signedAttributes */
|
||||||
|
if (pkiMsg[idx] == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0)) {
|
||||||
|
idx++;
|
||||||
|
|
||||||
|
if (GetLength(pkiMsg, &idx, &length, pkiMsgSz) < 0)
|
||||||
|
return ASN_PARSE_E;
|
||||||
|
|
||||||
|
/* save pointer and length */
|
||||||
|
signedAttr = &pkiMsg[idx];
|
||||||
|
signedAttrSz = length;
|
||||||
|
|
||||||
|
idx += length;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Get the sequence of digestEncryptionAlgorithm */
|
||||||
|
if (GetSequence(pkiMsg, &idx, &length, pkiMsgSz) < 0)
|
||||||
|
return ASN_PARSE_E;
|
||||||
|
|
||||||
|
/* Skip it */
|
||||||
|
idx += length;
|
||||||
|
|
||||||
|
/* Get the signature */
|
||||||
|
if (pkiMsg[idx] == ASN_OCTET_STRING) {
|
||||||
|
idx++;
|
||||||
|
|
||||||
|
if (GetLength(pkiMsg, &idx, &length, pkiMsgSz) < 0)
|
||||||
|
return ASN_PARSE_E;
|
||||||
|
|
||||||
|
/* save pointer and length */
|
||||||
|
sig = &pkiMsg[idx];
|
||||||
|
sigSz = length;
|
||||||
|
|
||||||
|
idx += length;
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
RsaKey key;
|
||||||
|
word32 scratch = 0;
|
||||||
|
int plainSz = 0;
|
||||||
|
byte digest[MAX_SEQ_SZ+MAX_ALGO_SZ+MAX_OCTET_STR_SZ+SHA_DIGEST_SIZE];
|
||||||
|
|
||||||
|
XMEMSET(digest, 0, sizeof(digest));
|
||||||
|
PKCS7_InitWithCert(pkcs7, cert, certSz);
|
||||||
|
pkcs7->content = content;
|
||||||
|
pkcs7->contentSz = contentSz;
|
||||||
|
|
||||||
|
InitRsaKey(&key, NULL);
|
||||||
|
if (RsaPublicKeyDecode(pkcs7->publicKey, &scratch, &key,
|
||||||
|
pkcs7->publicKeySz) < 0) {
|
||||||
|
CYASSL_MSG("ASN RSA key decode error");
|
||||||
|
return PUBLIC_KEY_E;
|
||||||
|
}
|
||||||
|
plainSz = RsaSSL_Verify(sig, sigSz, digest, sizeof(digest), &key);
|
||||||
|
FreeRsaKey(&key);
|
||||||
|
if (plainSz < 0)
|
||||||
|
return plainSz;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
Reference in New Issue
Block a user