From 0972fbbf9d384c0e4651849fa595364961a32288 Mon Sep 17 00:00:00 2001 From: John Safranek Date: Thu, 23 Jan 2014 11:24:50 -0800 Subject: [PATCH] PKCS7_VerifySignedMessage() decodes more of the message and performs an RSA verify on it. --- ctaocrypt/src/pkcs7.c | 163 ++++++++++++++++++++++++++++++++++++------ 1 file changed, 142 insertions(+), 21 deletions(-) diff --git a/ctaocrypt/src/pkcs7.c b/ctaocrypt/src/pkcs7.c index edf986c30..e9a797491 100644 --- a/ctaocrypt/src/pkcs7.c +++ b/ctaocrypt/src/pkcs7.c @@ -228,7 +228,7 @@ typedef struct 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 contentAttribsDigest[SHA_DIGEST_SIZE]; byte encContentDigest[512]; byte outerSeq[MAX_SEQ_SZ]; @@ -417,17 +417,40 @@ int PKCS7_EncodeSignedData(PKCS7* pkcs7, byte* output, word32 outputSz) int result; 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) { byte attribSet[MAX_SET_SZ]; word32 attribSetSz; attribSetSz = SetSet(flatSignedAttribsSz, attribSet); + InitSha(&esd.sha); ShaUpdate(&esd.sha, attribSet, attribSetSz); ShaUpdate(&esd.sha, flatSignedAttribs, flatSignedAttribsSz); } 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); result = RsaPrivateKeyDecode(pkcs7->privateKey, &scratch, &privKey, pkcs7->privateKeySz); @@ -435,11 +458,9 @@ int PKCS7_EncodeSignedData(PKCS7* pkcs7, byte* output, word32 outputSz) XFREE(flatSignedAttribs, 0, NULL); return PUBLIC_KEY_E; } - result = RsaSSL_Sign(esd.contentAttribsDigest, - sizeof(esd.contentAttribsDigest), - esd.encContentDigest, - sizeof(esd.encContentDigest), &privKey, - pkcs7->rng); + result = RsaSSL_Sign(digestInfo, digIdx, + esd.encContentDigest, sizeof(esd.encContentDigest), + &privKey, pkcs7->rng); FreeRsaKey(&privKey); if (result < 0) { XFREE(flatSignedAttribs, 0, NULL); @@ -553,7 +574,11 @@ int PKCS7_VerifySignedData(PKCS7* pkcs7, byte* pkiMsg, word32 pkiMsgSz) { word32 idx, contentType; 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) return BAD_FUNC_ARG; @@ -613,27 +638,27 @@ int PKCS7_VerifySignedData(PKCS7* pkcs7, byte* pkiMsg, word32 pkiMsgSz) return PKCS7_OID_E; } - b = pkiMsg[idx++]; - if (b != (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0)) + if (pkiMsg[idx++] != (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0)) return ASN_PARSE_E; if (GetLength(pkiMsg, &idx, &length, pkiMsgSz) < 0) return ASN_PARSE_E; - b = pkiMsg[idx++]; + if (pkiMsg[idx++] != ASN_OCTET_STRING) + return ASN_PARSE_E; + if (GetLength(pkiMsg, &idx, &length, pkiMsgSz) < 0) return ASN_PARSE_E; /* Save the inner data as the content. */ if (length > 0) { - pkcs7->content = &pkiMsg[idx]; - pkcs7->contentSz = length; + content = &pkiMsg[idx]; + contentSz = length; idx += length; } - b = pkiMsg[idx]; /* 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++; if (GetLength(pkiMsg, &idx, &length, pkiMsgSz) < 0) return ASN_PARSE_E; @@ -647,18 +672,114 @@ int PKCS7_VerifySignedData(PKCS7* pkcs7, byte* pkiMsg, word32 pkiMsgSz) word32 certIdx = idx; - b = pkiMsg[certIdx++]; - if (b == (ASN_CONSTRUCTED | ASN_SEQUENCE)) { - int certSz; - + if (pkiMsg[certIdx++] == (ASN_CONSTRUCTED | ASN_SEQUENCE)) { if (GetLength(pkiMsg, &certIdx, &certSz, pkiMsgSz) < 0) return ASN_PARSE_E; - pkcs7->singleCert = &pkiMsg[idx]; - pkcs7->singleCertSz = certSz + (certIdx - idx); - return 1; + cert = &pkiMsg[idx]; + certSz += (certIdx - idx); } } + 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;