Crypto: Check for revocation when reading in certificates

This commit is contained in:
zzz
2016-02-19 01:37:41 +00:00
parent 910822ecf2
commit 238ebc23e2
3 changed files with 64 additions and 2 deletions

View File

@ -226,17 +226,24 @@ public final class CertUtil {
* Get the Java public key from a X.509 certificate file.
* Throws if the certificate is invalid (e.g. expired).
*
* This DOES check for revocation.
*
* @return non-null, throws on all errors including certificate invalid
* @since 0.9.24 moved from SU3File private method
*/
public static PublicKey loadKey(File kd) throws IOException, GeneralSecurityException {
return loadCert(kd).getPublicKey();
X509Certificate cert = loadCert(kd);
if (isRevoked(cert))
throw new CRLException("Certificate is revoked");
return cert.getPublicKey();
}
/**
* Get the certificate from a X.509 certificate file.
* Throws if the certificate is invalid (e.g. expired).
*
* This does NOT check for revocation.
*
* @return non-null, throws on all errors including certificate invalid
* @since 0.9.24 adapted from SU3File private method
*/
@ -314,6 +321,8 @@ public final class CertUtil {
* Throws if any certificate is invalid (e.g. expired).
* Does NOT close the stream.
*
* This does NOT check for revocation.
*
* @return non-null, non-empty, throws on all errors including certificate invalid
* @since 0.9.25
*/
@ -380,6 +389,19 @@ public final class CertUtil {
/**
* Is the certificate revoked?
* This loads the CRLs from disk.
* For efficiency, call loadCRLs() and then pass to isRevoked().
*
* @since 0.9.25
*/
public static boolean isRevoked(Certificate cert) {
return isRevoked(I2PAppContext.getGlobalContext(), cert);
}
/**
* Is the certificate revoked?
* This loads the CRLs from disk.
* For efficiency, call loadCRLs() and then pass to isRevoked().
*
* @since 0.9.25
*/
@ -403,6 +425,16 @@ public final class CertUtil {
return false;
}
/**
* Load CRLs from standard locations.
*
* @return non-null, possibly empty
* @since 0.9.25
*/
public static CertStore loadCRLs() {
return loadCRLs(I2PAppContext.getGlobalContext());
}
/**
* Load CRLs from standard locations.
*
@ -423,6 +455,7 @@ public final class CertUtil {
dir2 = new File(dir2, REVOCATION_DIR);
loadCRLs(crls, dir2);
}
//System.out.println("Loaded " + crls.size() + " CRLs");
CollectionCertStoreParameters ccsp = new CollectionCertStoreParameters(crls);
try {
CertStore store = CertStore.getInstance("Collection", ccsp);

View File

@ -12,6 +12,7 @@ import java.io.IOException;
import java.security.GeneralSecurityException;
import java.security.PublicKey;
import java.security.cert.CertificateFactory;
import java.security.cert.CRLException;
import java.security.cert.X509Certificate;
import net.i2p.util.SystemVersion;
@ -34,6 +35,8 @@ class DirKeyRing implements KeyRing {
* Cert must be in the file (escaped keyName).crt,
* and have a CN == keyName.
*
* This DOES do a revocation check.
*
* CN check unsupported on Android.
*
* @return null if file doesn't exist, throws on all other errors
@ -50,6 +53,8 @@ class DirKeyRing implements KeyRing {
if (!kd.exists())
return null;
X509Certificate cert = CertUtil.loadCert(kd);
if (CertUtil.isRevoked(cert))
throw new CRLException("Certificate is revoked");
if (!SystemVersion.isAndroid()) {
// getSubjectValue() unsupported on Android.
// Any cert problems will be caught in non-Android testing.

View File

@ -13,6 +13,7 @@ import java.security.PublicKey;
import java.security.cert.Certificate;
import java.security.cert.CertificateExpiredException;
import java.security.cert.CertificateNotYetValidException;
import java.security.cert.CertStore;
import java.security.cert.X509Certificate;
import java.security.cert.X509CRL;
import java.util.ArrayList;
@ -332,6 +333,8 @@ public final class KeyStoreUtil {
* Load all X509 Certs from a directory and add them to the
* trusted set of certificates in the key store
*
* This DOES check for revocation.
*
* @return number successfully added
* @since 0.8.2, moved from SSLEepGet in 0.9.9
*/
@ -341,6 +344,7 @@ public final class KeyStoreUtil {
if (dir.exists() && dir.isDirectory()) {
File[] files = dir.listFiles();
if (files != null) {
CertStore cs = CertUtil.loadCRLs();
for (int i = 0; i < files.length; i++) {
File f = files[i];
if (!f.isFile())
@ -354,7 +358,7 @@ public final class KeyStoreUtil {
alias.endsWith(".p7c") || alias.endsWith(".pfx") || alias.endsWith(".p12") ||
alias.endsWith(".cer"))
alias = alias.substring(0, alias.length() - 4);
boolean success = addCert(f, alias, ks);
boolean success = addCert(f, alias, ks, cs);
if (success)
added++;
}
@ -367,10 +371,26 @@ public final class KeyStoreUtil {
* Load an X509 Cert from a file and add it to the
* trusted set of certificates in the key store
*
* This does NOT check for revocation.
*
* @return success
* @since 0.8.2, moved from SSLEepGet in 0.9.9
*/
public static boolean addCert(File file, String alias, KeyStore ks) {
return addCert(file, alias, ks, null);
}
/**
* Load an X509 Cert from a file and add it to the
* trusted set of certificates in the key store
*
* This DOES check for revocation, IF cs is non-null.
*
* @param cs may be null; if non-null, check for revocation
* @return success
* @since 0.9.25
*/
public static boolean addCert(File file, String alias, KeyStore ks, CertStore cs) {
try {
X509Certificate cert = CertUtil.loadCert(file);
info("Read X509 Certificate from " + file.getAbsolutePath() +
@ -378,6 +398,10 @@ public final class KeyStoreUtil {
" Serial: " + cert.getSerialNumber().toString(16) +
"; Valid From: " + cert.getNotBefore() +
" To: " + cert.getNotAfter());
if (cs != null && CertUtil.isRevoked(cs, cert)) {
error("Certificate is revoked: " + file, new Exception());
return false;
}
ks.setCertificateEntry(alias, cert);
info("Now trusting X509 Certificate, Issuer: " + cert.getIssuerX500Principal());
} catch (CertificateExpiredException cee) {