diff --git a/.gitignore b/.gitignore index d5d705070..ee2053048 100644 --- a/.gitignore +++ b/.gitignore @@ -54,6 +54,7 @@ key.der key.pem certreq.der certreq.pem +pkcs7cert.der pkcs7signedData.der pkcs7envelopedData.der diff diff --git a/ctaocrypt/src/pkcs7.c b/ctaocrypt/src/pkcs7.c index d7fe5eee9..67db28ad4 100644 --- a/ctaocrypt/src/pkcs7.c +++ b/ctaocrypt/src/pkcs7.c @@ -548,6 +548,99 @@ int PKCS7_EncodeSignedData(PKCS7* pkcs7, byte* output, word32 outputSz) } +/* Finds the certificates in the message and saves it. */ +int PKCS7_VerifySignedData(PKCS7* pkcs7, byte* pkiMsg, word32 pkiMsgSz) +{ + word32 idx, contentType; + int length, version; + byte b; + + if (pkcs7 == NULL || pkiMsg == NULL || pkiMsgSz == 0) + return BAD_FUNC_ARG; + + idx = 0; + + /* Get the contentInfo sequence */ + if (GetSequence(pkiMsg, &idx, &length, pkiMsgSz) < 0) + return ASN_PARSE_E; + + /* Get the contentInfo contentType */ + if (GetContentType(pkiMsg, &idx, &contentType, pkiMsgSz) < 0) + return ASN_PARSE_E; + + if (contentType != SIGNED_DATA) { + CYASSL_MSG("PKCS#7 input not of type SignedData"); + return PKCS7_OID_E; + } + + /* get the ContentInfo content */ + if (pkiMsg[idx++] != (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0)) + return ASN_PARSE_E; + + if (GetLength(pkiMsg, &idx, &length, pkiMsgSz) < 0) + return ASN_PARSE_E; + + /* Get the signedData sequence */ + 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 signedData needs to be of version 1"); + return ASN_VERSION_E; + } + + /* Get the set of DigestAlgorithmIdentifiers */ + if (GetSet(pkiMsg, &idx, &length, pkiMsgSz) < 0) + return ASN_PARSE_E; + + /* Skip the set. */ + idx += length; + + /* Get the inner ContentInfo sequence */ + if (GetSequence(pkiMsg, &idx, &length, pkiMsgSz) < 0) + return ASN_PARSE_E; + + /* Skip the seqeunce. */ + idx += length; + + b = pkiMsg[idx]; + /* Get the implicit[0] set of certificates */ + if (b == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0)) { + idx++; + if (GetLength(pkiMsg, &idx, &length, pkiMsgSz) < 0) + return ASN_PARSE_E; + + if (length > 0) { + /* At this point, idx is at the first certificate in + * a set of certificates. There may be more than one, + * or none, or they may be a PKCS 6 extended + * certificate. We want to save the first cert if it + * is X.509. */ + + word32 certIdx = idx; + + b = pkiMsg[certIdx++]; + if (b == (ASN_CONSTRUCTED | ASN_SEQUENCE)) { + int certSz; + + if (GetLength(pkiMsg, &certIdx, &certSz, pkiMsgSz) < 0) + return ASN_PARSE_E; + + pkcs7->singleCert = &pkiMsg[idx]; + pkcs7->singleCertSz = certSz + (certIdx - idx); + return 1; + } + } + } + + return 0; +} + + /* create ASN.1 fomatted RecipientInfo structure, returns sequence size */ CYASSL_LOCAL int CreateRecipientInfo(const byte* cert, word32 certSz, int keyEncAlgo, int blockKeySz, diff --git a/ctaocrypt/test/test.c b/ctaocrypt/test/test.c index b1fbaa6b5..9bd1ffa2b 100644 --- a/ctaocrypt/test/test.c +++ b/ctaocrypt/test/test.c @@ -4252,7 +4252,38 @@ int pkcs7signed_test(void) PKCS7_Free(&msg); return -211; } - ret = (int)fwrite(out, outSz, 1, file); + ret = (int)fwrite(out, 1, outSz, file); + fclose(file); + + PKCS7_Free(&msg); + PKCS7_InitWithCert(&msg, NULL, 0); + + ret = PKCS7_VerifySignedData(&msg, out, outSz); + if (ret < 0) { + free(certDer); + free(keyDer); + free(out); + PKCS7_Free(&msg); + return -212; + } + + if (msg.singleCert == NULL || msg.singleCertSz == 0) { + free(certDer); + free(keyDer); + free(out); + PKCS7_Free(&msg); + return -213; + } + + file = fopen("./pkcs7cert.der", "wb"); + if (!file) { + free(certDer); + free(keyDer); + free(out); + PKCS7_Free(&msg); + return -214; + } + ret = (int)fwrite(msg.singleCert, 1, msg.singleCertSz, file); fclose(file); free(certDer); diff --git a/cyassl/ctaocrypt/pkcs7.h b/cyassl/ctaocrypt/pkcs7.h index 0ea781774..5d5d801d6 100644 --- a/cyassl/ctaocrypt/pkcs7.h +++ b/cyassl/ctaocrypt/pkcs7.h @@ -103,6 +103,8 @@ CYASSL_API void PKCS7_Free(PKCS7* pkcs7); CYASSL_API int PKCS7_EncodeData(PKCS7* pkcs7, byte* output, word32 outputSz); CYASSL_API int PKCS7_EncodeSignedData(PKCS7* pkcs7, byte* output, word32 outputSz); +CYASSL_API int PKCS7_VerifySignedData(PKCS7* pkcs7, + byte* pkiMsg, word32 pkiMsgSz); CYASSL_API int PKCS7_EncodeEnvelopedData(PKCS7* pkcs7, byte* output, word32 outputSz); CYASSL_API int PKCS7_DecodeEnvelopedData(PKCS7* pkcs7, byte* pkiMsg,