Chromium Code Reviews| 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 |