OLD | NEW |
---|---|
1 /* This Source Code Form is subject to the terms of the Mozilla Public | 1 /* This Source Code Form is subject to the terms of the Mozilla Public |
2 * License, v. 2.0. If a copy of the MPL was not distributed with this | 2 * License, v. 2.0. If a copy of the MPL was not distributed with this |
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ | 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
4 | 4 |
5 /* | 5 /* |
6 * PKCS7 decoding, verification. | 6 * PKCS7 decoding, verification. |
7 * | 7 * |
8 * $Id$ | 8 * $Id$ |
9 */ | 9 */ |
10 | 10 |
(...skipping 1228 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1239 * more complicated before I am finished, so... | 1239 * more complicated before I am finished, so... |
1240 */ | 1240 */ |
1241 if (signerinfos != NULL && signerinfos[0] != NULL) | 1241 if (signerinfos != NULL && signerinfos[0] != NULL) |
1242 return PR_TRUE; | 1242 return PR_TRUE; |
1243 else | 1243 else |
1244 return PR_FALSE; | 1244 return PR_FALSE; |
1245 } | 1245 } |
1246 | 1246 |
1247 | 1247 |
1248 /* | 1248 /* |
1249 * SEC_PKCS7ContentVerifySignature | 1249 * sec_pkcs7_verify_signature |
1250 * | |
1250 * Look at a PKCS7 contentInfo and check if the signature is good. | 1251 * Look at a PKCS7 contentInfo and check if the signature is good. |
1251 * The digest was either calculated earlier (and is stored in the | 1252 * The digest was either calculated earlier (and is stored in the |
1252 * contentInfo itself) or is passed in via "detached_digest". | 1253 * contentInfo itself) or is passed in via "detached_digest". |
1253 * | 1254 * |
1254 * The verification checks that the signing cert is valid and trusted | 1255 * The verification checks that the signing cert is valid and trusted |
1255 *» for the purpose specified by "certusage". | 1256 *» for the purpose specified by "certusage" at |
1257 * » - "*atTime" if "atTime" is not null, or | |
1258 * » - the signing time if the signing time is available in "cinfo", or | |
1259 *» - the current time (as returned by PR_Now). | |
1256 * | 1260 * |
1257 * In addition, if "keepcerts" is true, add any new certificates found | 1261 * In addition, if "keepcerts" is true, add any new certificates found |
1258 * into our local database. | 1262 * into our local database. |
1259 * | 1263 * |
1260 * XXX Each place which returns PR_FALSE should be sure to have a good | 1264 * XXX Each place which returns PR_FALSE should be sure to have a good |
1261 * error set for inspection by the caller. Alternatively, we could create | 1265 * error set for inspection by the caller. Alternatively, we could create |
1262 * an enumeration of success and each type of failure and return that | 1266 * an enumeration of success and each type of failure and return that |
1263 * instead of a boolean. For now, the default in a bad situation is to | 1267 * instead of a boolean. For now, the default in a bad situation is to |
1264 * set the error to SEC_ERROR_PKCS7_BAD_SIGNATURE. But this should be | 1268 * set the error to SEC_ERROR_PKCS7_BAD_SIGNATURE. But this should be |
1265 * reviewed; better (more specific) errors should be possible (to distinguish | 1269 * reviewed; better (more specific) errors should be possible (to distinguish |
1266 * a signature failure from a badly-formed pkcs7 signedData, for example). | 1270 * a signature failure from a badly-formed pkcs7 signedData, for example). |
1267 * Some of the errors should probably just be SEC_ERROR_BAD_SIGNATURE, | 1271 * Some of the errors should probably just be SEC_ERROR_BAD_SIGNATURE, |
1268 * but that has a less helpful error string associated with it right now; | 1272 * but that has a less helpful error string associated with it right now; |
1269 * if/when that changes, review and change these as needed. | 1273 * if/when that changes, review and change these as needed. |
1270 * | 1274 * |
1271 * XXX This is broken wrt signedAndEnvelopedData. In that case, the | 1275 * XXX This is broken wrt signedAndEnvelopedData. In that case, the |
1272 * message digest is doubly encrypted -- first encrypted with the signer | 1276 * message digest is doubly encrypted -- first encrypted with the signer |
1273 * private key but then again encrypted with the bulk encryption key used | 1277 * private key but then again encrypted with the bulk encryption key used |
1274 * to encrypt the content. So before we can pass the digest to VerifyDigest, | 1278 * to encrypt the content. So before we can pass the digest to VerifyDigest, |
1275 * we need to decrypt it with the bulk encryption key. Also, in this case, | 1279 * we need to decrypt it with the bulk encryption key. Also, in this case, |
1276 * there should be NO authenticatedAttributes (signerinfo->authAttr should | 1280 * there should be NO authenticatedAttributes (signerinfo->authAttr should |
1277 * be NULL). | 1281 * be NULL). |
1278 */ | 1282 */ |
1279 static PRBool | 1283 static PRBool |
1280 sec_pkcs7_verify_signature(SEC_PKCS7ContentInfo *cinfo, | 1284 sec_pkcs7_verify_signature(SEC_PKCS7ContentInfo *cinfo, |
1281 SECCertUsage certusage, | 1285 SECCertUsage certusage, |
1282 const SECItem *detached_digest, | 1286 const SECItem *detached_digest, |
1283 HASH_HashType digest_type, | 1287 HASH_HashType digest_type, |
1284 » » » PRBool keepcerts) | 1288 » » » PRBool keepcerts, |
1289 » » » const PRTime *atTime) | |
1285 { | 1290 { |
1286 SECAlgorithmID **digestalgs, *bulkid; | 1291 SECAlgorithmID **digestalgs, *bulkid; |
1287 const SECItem *digest; | 1292 const SECItem *digest; |
1288 SECItem **digests; | 1293 SECItem **digests; |
1289 SECItem **rawcerts; | 1294 SECItem **rawcerts; |
1290 CERTSignedCrl **crls; | 1295 CERTSignedCrl **crls; |
1291 SEC_PKCS7SignerInfo **signerinfos, *signerinfo; | 1296 SEC_PKCS7SignerInfo **signerinfos, *signerinfo; |
1292 CERTCertificate *cert, **certs; | 1297 CERTCertificate *cert, **certs; |
1293 PRBool goodsig; | 1298 PRBool goodsig; |
1294 CERTCertDBHandle *certdb, *defaultdb; | 1299 CERTCertDBHandle *certdb, *defaultdb; |
1295 SECOidTag encTag,digestTag; | 1300 SECOidTag encTag,digestTag; |
1296 HASH_HashType found_type; | 1301 HASH_HashType found_type; |
1297 int i, certcount; | 1302 int i, certcount; |
1298 SECKEYPublicKey *publickey; | 1303 SECKEYPublicKey *publickey; |
1299 SECItem *content_type; | 1304 SECItem *content_type; |
1300 PK11SymKey *sigkey; | 1305 PK11SymKey *sigkey; |
1301 SECItem *encoded_stime; | 1306 SECItem *encoded_stime; |
1302 int64 stime; | 1307 PRTime stime; |
1308 PRTime verificationTime; | |
1303 SECStatus rv; | 1309 SECStatus rv; |
1304 | 1310 |
1305 /* | 1311 /* |
1306 * Everything needed in order to "goto done" safely. | 1312 * Everything needed in order to "goto done" safely. |
1307 */ | 1313 */ |
1308 goodsig = PR_FALSE; | 1314 goodsig = PR_FALSE; |
1309 certcount = 0; | 1315 certcount = 0; |
1310 cert = NULL; | 1316 cert = NULL; |
1311 certs = NULL; | 1317 certs = NULL; |
1312 certdb = NULL; | 1318 certdb = NULL; |
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1429 } | 1435 } |
1430 | 1436 |
1431 /* | 1437 /* |
1432 * XXX This uses the signing time, if available. Additionally, we | 1438 * XXX This uses the signing time, if available. Additionally, we |
1433 * might want to, if there is no signing time, get the message time | 1439 * might want to, if there is no signing time, get the message time |
1434 * from the mail header itself, and use that. That would require | 1440 * from the mail header itself, and use that. That would require |
1435 * a change to our interface though, and for S/MIME callers to pass | 1441 * a change to our interface though, and for S/MIME callers to pass |
1436 * in a time (and for non-S/MIME callers to pass in nothing, or | 1442 * in a time (and for non-S/MIME callers to pass in nothing, or |
1437 * maybe make them pass in the current time, always?). | 1443 * maybe make them pass in the current time, always?). |
1438 */ | 1444 */ |
1439 if (CERT_VerifyCert (certdb, cert, PR_TRUE, certusage, | 1445 if (atTime) { |
1440 » » » encoded_stime != NULL ? stime : PR_Now(), | 1446 » verificationTime = *atTime; |
1447 } else if (encoded_stime != NULL) { | |
1448 » verificationTime = stime; | |
1449 } else { | |
1450 » verificationTime = PR_Now(); | |
1451 } | |
1452 if (CERT_VerifyCert (certdb, cert, PR_TRUE, certusage, verificationTime, | |
1441 cinfo->pwfn_arg, NULL) != SECSuccess) | 1453 cinfo->pwfn_arg, NULL) != SECSuccess) |
1442 { | 1454 { |
1443 /* | 1455 /* |
1444 * XXX Give the user an option to check the signature anyway? | 1456 * XXX Give the user an option to check the signature anyway? |
1445 * If we want to do this, need to give a way to leave and display | 1457 * If we want to do this, need to give a way to leave and display |
1446 * some dialog and get the answer and come back through (or do | 1458 * some dialog and get the answer and come back through (or do |
1447 * the rest of what we do below elsewhere, maybe by putting it | 1459 * the rest of what we do below elsewhere, maybe by putting it |
1448 * in a function that we call below and could call from a dialog | 1460 * in a function that we call below and could call from a dialog |
1449 * finish handler). | 1461 * finish handler). |
1450 */ | 1462 */ |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1511 | 1523 |
1512 digest = digests[i]; | 1524 digest = digests[i]; |
1513 } | 1525 } |
1514 | 1526 |
1515 encTag = SECOID_FindOIDTag(&(signerinfo->digestEncAlg.algorithm)); | 1527 encTag = SECOID_FindOIDTag(&(signerinfo->digestEncAlg.algorithm)); |
1516 if (encTag == SEC_OID_UNKNOWN) { | 1528 if (encTag == SEC_OID_UNKNOWN) { |
1517 PORT_SetError (SEC_ERROR_PKCS7_BAD_SIGNATURE); | 1529 PORT_SetError (SEC_ERROR_PKCS7_BAD_SIGNATURE); |
1518 goto done; | 1530 goto done; |
1519 } | 1531 } |
1520 | 1532 |
1521 #ifndef NSS_ECC_MORE_THAN_SUITE_B | |
1522 if (encTag == SEC_OID_ANSIX962_EC_PUBLIC_KEY) { | |
1523 PORT_SetError(SEC_ERROR_PKCS7_BAD_SIGNATURE); | |
1524 goto done; | |
1525 } | |
1526 #endif | |
1527 | |
1528 | |
1529 if (signerinfo->authAttr != NULL) { | 1533 if (signerinfo->authAttr != NULL) { |
1530 SEC_PKCS7Attribute *attr; | 1534 SEC_PKCS7Attribute *attr; |
1531 SECItem *value; | 1535 SECItem *value; |
1532 SECItem encoded_attrs; | 1536 SECItem encoded_attrs; |
1533 | 1537 |
1534 /* | 1538 /* |
1535 * We have a sigkey only for signedAndEnvelopedData, which is | 1539 * We have a sigkey only for signedAndEnvelopedData, which is |
1536 * not supposed to have any authenticated attributes. | 1540 * not supposed to have any authenticated attributes. |
1537 */ | 1541 */ |
1538 if (sigkey != NULL) { | 1542 if (sigkey != NULL) { |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1583 encoded_attrs.len = 0; | 1587 encoded_attrs.len = 0; |
1584 if (sec_PKCS7EncodeAttributes (NULL, &encoded_attrs, | 1588 if (sec_PKCS7EncodeAttributes (NULL, &encoded_attrs, |
1585 &(signerinfo->authAttr)) == NULL) | 1589 &(signerinfo->authAttr)) == NULL) |
1586 goto done; | 1590 goto done; |
1587 | 1591 |
1588 if (encoded_attrs.data == NULL || encoded_attrs.len == 0) { | 1592 if (encoded_attrs.data == NULL || encoded_attrs.len == 0) { |
1589 PORT_SetError (SEC_ERROR_PKCS7_BAD_SIGNATURE); | 1593 PORT_SetError (SEC_ERROR_PKCS7_BAD_SIGNATURE); |
1590 goto done; | 1594 goto done; |
1591 } | 1595 } |
1592 | 1596 |
1593 | |
1594 goodsig = (PRBool)(VFY_VerifyDataDirect(encoded_attrs.data, | 1597 goodsig = (PRBool)(VFY_VerifyDataDirect(encoded_attrs.data, |
1595 encoded_attrs.len, | 1598 encoded_attrs.len, |
1596 publickey, &(signerinfo->encDigest), | 1599 publickey, &(signerinfo->encDigest), |
1597 encTag, digestTag, NULL, | 1600 encTag, digestTag, NULL, |
1598 cinfo->pwfn_arg) == SECSuccess); | 1601 cinfo->pwfn_arg) == SECSuccess); |
1599 PORT_Free (encoded_attrs.data); | 1602 PORT_Free (encoded_attrs.data); |
1600 } else { | 1603 } else { |
1601 SECItem *sig; | 1604 SECItem *sig; |
1602 SECItem holder; | 1605 SECItem holder; |
1603 SECStatus rv; | 1606 SECStatus rv; |
(...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1750 * | 1753 * |
1751 * In addition, if "keepcerts" is true, add any new certificates found | 1754 * In addition, if "keepcerts" is true, add any new certificates found |
1752 * into our local database. | 1755 * into our local database. |
1753 */ | 1756 */ |
1754 PRBool | 1757 PRBool |
1755 SEC_PKCS7VerifySignature(SEC_PKCS7ContentInfo *cinfo, | 1758 SEC_PKCS7VerifySignature(SEC_PKCS7ContentInfo *cinfo, |
1756 SECCertUsage certusage, | 1759 SECCertUsage certusage, |
1757 PRBool keepcerts) | 1760 PRBool keepcerts) |
1758 { | 1761 { |
1759 return sec_pkcs7_verify_signature (cinfo, certusage, | 1762 return sec_pkcs7_verify_signature (cinfo, certusage, |
1760 » » » » NULL, HASH_AlgNULL, keepcerts); | 1763 » » » » NULL, HASH_AlgNULL, keepcerts, 0); |
wtc
2013/04/24 22:49:45
This 0 should be NULL.
| |
1761 } | 1764 } |
1762 | 1765 |
1763 /* | 1766 /* |
1764 * SEC_PKCS7VerifyDetachedSignature | 1767 * SEC_PKCS7VerifyDetachedSignature |
1765 * Look at a PKCS7 contentInfo and check if the signature matches | 1768 * Look at a PKCS7 contentInfo and check if the signature matches |
1766 * a passed-in digest (calculated, supposedly, from detached contents). | 1769 * a passed-in digest (calculated, supposedly, from detached contents). |
1767 * The verification checks that the signing cert is valid and trusted | 1770 * The verification checks that the signing cert is valid and trusted |
1768 * for the purpose specified by "certusage". | 1771 * for the purpose specified by "certusage". |
1769 * | 1772 * |
1770 * In addition, if "keepcerts" is true, add any new certificates found | 1773 * In addition, if "keepcerts" is true, add any new certificates found |
1771 * into our local database. | 1774 * into our local database. |
1772 */ | 1775 */ |
1773 PRBool | 1776 PRBool |
1774 SEC_PKCS7VerifyDetachedSignature(SEC_PKCS7ContentInfo *cinfo, | 1777 SEC_PKCS7VerifyDetachedSignature(SEC_PKCS7ContentInfo *cinfo, |
1775 SECCertUsage certusage, | 1778 SECCertUsage certusage, |
1776 const SECItem *detached_digest, | 1779 const SECItem *detached_digest, |
1777 HASH_HashType digest_type, | 1780 HASH_HashType digest_type, |
1778 PRBool keepcerts) | 1781 PRBool keepcerts) |
1779 { | 1782 { |
1780 return sec_pkcs7_verify_signature (cinfo, certusage, | 1783 return sec_pkcs7_verify_signature (cinfo, certusage, |
1781 detached_digest, digest_type, | 1784 detached_digest, digest_type, |
1782 » » » » keepcerts); | 1785 » » » » keepcerts, NULL); |
1783 } | 1786 } |
1784 | 1787 |
1788 /* | |
1789 * SEC_PKCS7VerifyDetachedSignatureAtTime | |
1790 * Look at a PKCS7 contentInfo and check if the signature matches | |
1791 * a passed-in digest (calculated, supposedly, from detached contents). | |
1792 * The verification checks that the signing cert is valid and trusted | |
1793 * for the purpose specified by "certusage" at time "atTime". | |
1794 * | |
1795 * In addition, if "keepcerts" is true, add any new certificates found | |
1796 * into our local database. | |
1797 */ | |
1798 PRBool | |
1799 SEC_PKCS7VerifyDetachedSignatureAtTime(SEC_PKCS7ContentInfo *cinfo, | |
1800 SECCertUsage certusage, | |
1801 const SECItem *detached_digest, | |
1802 HASH_HashType digest_type, | |
1803 PRBool keepcerts, | |
1804 PRTime atTime) | |
1805 { | |
1806 return sec_pkcs7_verify_signature (cinfo, certusage, | |
1807 detached_digest, digest_type, | |
1808 keepcerts, &atTime); | |
1809 } | |
1785 | 1810 |
1786 /* | 1811 /* |
1787 * Return the asked-for portion of the name of the signer of a PKCS7 | 1812 * Return the asked-for portion of the name of the signer of a PKCS7 |
1788 * signed object. | 1813 * signed object. |
1789 * | 1814 * |
1790 * Returns a pointer to allocated memory, which must be freed. | 1815 * Returns a pointer to allocated memory, which must be freed. |
1791 * A NULL return value is an error. | 1816 * A NULL return value is an error. |
1792 */ | 1817 */ |
1793 | 1818 |
1794 #define sec_common_name 1 | 1819 #define sec_common_name 1 |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1837 /* | 1862 /* |
1838 * No cert there; see if we can find one by calling verify ourselves. | 1863 * No cert there; see if we can find one by calling verify ourselves. |
1839 */ | 1864 */ |
1840 if (signercert == NULL) { | 1865 if (signercert == NULL) { |
1841 /* | 1866 /* |
1842 * The cert usage does not matter in this case, because we do not | 1867 * The cert usage does not matter in this case, because we do not |
1843 * actually care about the verification itself, but we have to pick | 1868 * actually care about the verification itself, but we have to pick |
1844 * some valid usage to pass in. | 1869 * some valid usage to pass in. |
1845 */ | 1870 */ |
1846 (void) sec_pkcs7_verify_signature (cinfo, certUsageEmailSigner, | 1871 (void) sec_pkcs7_verify_signature (cinfo, certUsageEmailSigner, |
1847 » » » » » NULL, HASH_AlgNULL, PR_FALSE); | 1872 » » » » » NULL, HASH_AlgNULL, PR_FALSE, 0); |
wtc
2013/04/24 22:49:45
This 0 should be NULL.
| |
1848 signercert = signerinfos[0]->cert; | 1873 signercert = signerinfos[0]->cert; |
1849 if (signercert == NULL) | 1874 if (signercert == NULL) |
1850 return NULL; | 1875 return NULL; |
1851 } | 1876 } |
1852 | 1877 |
1853 switch (selector) { | 1878 switch (selector) { |
1854 case sec_common_name: | 1879 case sec_common_name: |
1855 container = CERT_GetCommonName (&signercert->subject); | 1880 container = CERT_GetCommonName (&signercert->subject); |
1856 break; | 1881 break; |
1857 case sec_email_address: | 1882 case sec_email_address: |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1900 /* | 1925 /* |
1901 * No signature, or more than one, means no deal. | 1926 * No signature, or more than one, means no deal. |
1902 */ | 1927 */ |
1903 if (signerinfos == NULL || signerinfos[0] == NULL || signerinfos[1] != NULL) | 1928 if (signerinfos == NULL || signerinfos[0] == NULL || signerinfos[1] != NULL) |
1904 return NULL; | 1929 return NULL; |
1905 | 1930 |
1906 attr = sec_PKCS7FindAttribute (signerinfos[0]->authAttr, | 1931 attr = sec_PKCS7FindAttribute (signerinfos[0]->authAttr, |
1907 SEC_OID_PKCS9_SIGNING_TIME, PR_TRUE); | 1932 SEC_OID_PKCS9_SIGNING_TIME, PR_TRUE); |
1908 return sec_PKCS7AttributeValue (attr); | 1933 return sec_PKCS7AttributeValue (attr); |
1909 } | 1934 } |
OLD | NEW |