Merge pull request #32 from cconlon/systemcerts

Improve system CA cert loading, PKIX TrustManager, Android improvements
pull/33/head
JacobBarthelmeh 2020-02-26 15:01:58 -07:00 committed by GitHub
commit b3301d3479
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 722 additions and 158 deletions

4
README
View File

@ -24,6 +24,10 @@ wolfSSL JNI Release X.X.X (TBD)
Release X.X.X has bug fixes and new features including:
- Support for custom TrustManager checkClientTrusted(), checkServerTrusted()
- wolfJSSE TrustManager registered as PKIX provider
- Improved support for auto-loading system CA certificates
- Improved Android TrustManager support
- Support for X509Certificate.getSubjectAlternativeNames()
The wolfSSL JNI Manual is available at:
http://www.wolfssl.com/documentation/wolfSSL-JNI-Manual.pdf. For build

Binary file not shown.

View File

@ -64,6 +64,84 @@ JNIEXPORT jlong JNICALL Java_com_wolfssl_WolfSSLCertificate_d2i_1X509
return (jlong)(intptr_t)wolfSSL_d2i_X509(NULL, &pt, sz);
}
JNIEXPORT jbyteArray JNICALL Java_com_wolfssl_WolfSSLCertificate_certPemToDer
(JNIEnv* jenv, jclass jcl, jbyteArray pem, jint pemSz)
{
unsigned char* der = NULL;
unsigned char* tmpPem = NULL;
int derSz = 0;
jbyteArray ret;
if (!jenv || !pem || (pemSz < 0))
return NULL;
/* find exception class */
jclass excClass = (*jenv)->FindClass(jenv,
"com/wolfssl/WolfSSLJNIException");
if ((*jenv)->ExceptionOccurred(jenv)) {
(*jenv)->ExceptionDescribe(jenv);
(*jenv)->ExceptionClear(jenv);
return NULL;
}
/* allocate space for DER, using PEM sz. DER will be smaller than PEM */
derSz = pemSz;
der = (unsigned char*)XMALLOC(derSz, NULL, DYNAMIC_TYPE_TMP_BUFFER);
if (der == NULL) {
return NULL;
}
XMEMSET(der, 0, derSz);
/* allocate space for converted jbyteArray */
tmpPem = (unsigned char*)XMALLOC(pemSz, NULL, DYNAMIC_TYPE_TMP_BUFFER);
if (tmpPem == NULL) {
XFREE(der, NULL, DYNAMIC_TYPE_TMP_BUFFER);
return NULL;
}
(*jenv)->GetByteArrayRegion(jenv, pem, 0, pemSz, (jbyte*)tmpPem);
if ((*jenv)->ExceptionOccurred(jenv)) {
(*jenv)->ExceptionDescribe(jenv);
(*jenv)->ExceptionClear(jenv);
XFREE(tmpPem, NULL, DYNAMIC_TYPE_TMP_BUFFER);
XFREE(der, NULL, DYNAMIC_TYPE_TMP_BUFFER);
(*jenv)->ThrowNew(jenv, excClass,
"Failed to get byte region in native certPemToDer");
return NULL;
}
derSz = wc_CertPemToDer(tmpPem, pemSz, der, derSz, CERT_TYPE);
if (derSz < 0) {
XFREE(tmpPem, NULL, DYNAMIC_TYPE_TMP_BUFFER);
XFREE(der, NULL, DYNAMIC_TYPE_TMP_BUFFER);
(*jenv)->ThrowNew(jenv, excClass,
"wc_CertPemToDer() failed in native certPemToDer");
return NULL;
}
XFREE(tmpPem, NULL, DYNAMIC_TYPE_TMP_BUFFER);
ret = (*jenv)->NewByteArray(jenv, derSz);
if (!ret) {
XFREE(der, NULL, DYNAMIC_TYPE_TMP_BUFFER);
(*jenv)->ThrowNew(jenv, jcl,
"Failed to create Java byte array in native certPemToDer");
return NULL;
}
(*jenv)->SetByteArrayRegion(jenv, ret, 0, derSz, (jbyte*)der);
if ((*jenv)->ExceptionOccurred(jenv)) {
(*jenv)->ExceptionDescribe(jenv);
(*jenv)->ExceptionClear(jenv);
XFREE(der, NULL, DYNAMIC_TYPE_TMP_BUFFER);
(*jenv)->ThrowNew(jenv, excClass,
"Failed to set byte region in native certPemToDer");
return NULL;
}
XFREE(der, NULL, DYNAMIC_TYPE_TMP_BUFFER);
return ret;
}
JNIEXPORT jbyteArray JNICALL Java_com_wolfssl_WolfSSLCertificate_X509_1get_1der
(JNIEnv* jenv, jclass jcl, jlong x509)
{
@ -688,3 +766,29 @@ JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLCertificate_X509_1is_1extension_1
return 0;
}
JNIEXPORT jstring JNICALL Java_com_wolfssl_WolfSSLCertificate_X509_1get_1next_1altname
(JNIEnv* jenv, jclass jcl, jlong x509)
{
#if defined(KEEP_PEER_CERT) || defined(SESSION_CERTS)
char* altname;
jstring retString;
(void)jcl;
if (!jenv || !x509)
return NULL;
altname = wolfSSL_X509_get_next_altname((WOLFSSL_X509*)(intptr_t)x509);
if (altname == NULL) {
return NULL;
}
retString = (*jenv)->NewStringUTF(jenv, altname);
return retString;
#else
(void)jenv;
(void)jcl;
(void)x509;
return NULL;
#endif
}

View File

@ -15,6 +15,14 @@ extern "C" {
JNIEXPORT jlong JNICALL Java_com_wolfssl_WolfSSLCertificate_d2i_1X509
(JNIEnv *, jclass, jbyteArray, jint);
/*
* Class: com_wolfssl_WolfSSLCertificate
* Method: certPemToDer
* Signature: ([BI)[B
*/
JNIEXPORT jbyteArray JNICALL Java_com_wolfssl_WolfSSLCertificate_certPemToDer
(JNIEnv *, jclass, jbyteArray, jint);
/*
* Class: com_wolfssl_WolfSSLCertificate
* Method: X509_get_der
@ -183,6 +191,14 @@ JNIEXPORT jbyteArray JNICALL Java_com_wolfssl_WolfSSLCertificate_X509_1get_1exte
JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLCertificate_X509_1is_1extension_1set
(JNIEnv *, jclass, jlong, jstring);
/*
* Class: com_wolfssl_WolfSSLCertificate
* Method: X509_get_next_altname
* Signature: (J)Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_com_wolfssl_WolfSSLCertificate_X509_1get_1next_1altname
(JNIEnv *, jclass, jlong);
#ifdef __cplusplus
}
#endif

View File

@ -30,6 +30,10 @@ import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.logging.Level;
import java.util.logging.Logger;
@ -42,7 +46,11 @@ public class WolfSSLCertificate {
private boolean active = false;
private long x509Ptr = 0;
/* cache alt names once retrieved once */
private Collection<List<?>> altNames = null;
static native long d2i_X509(byte[] der, int len);
static native byte[] certPemToDer(byte[] pem, int len);
static native byte[] X509_get_der(long x509);
static native byte[] X509_get_tbs(long x509);
static native void X509_free(long x509);
@ -64,11 +72,43 @@ public class WolfSSLCertificate {
static native boolean[] X509_get_key_usage(long x509);
static native byte[] X509_get_extension(long x509, String oid);
static native int X509_is_extension_set(long x509, String oid);
static native String X509_get_next_altname(long x509);
public WolfSSLCertificate(byte[] der) throws WolfSSLException {
x509Ptr = d2i_X509(der, der.length);
if (x509Ptr == 0) {
throw new WolfSSLException("Failed to create SSL Context");
throw new WolfSSLException("Failed to create WolfSSLCertificate");
}
this.active = true;
}
public WolfSSLCertificate(byte[] in, int format) throws WolfSSLException {
byte[] input = in;
if (in == null || in.length == 0) {
throw new WolfSSLException(
"Input array must not be null or zero length");
}
if (format != WolfSSL.SSL_FILETYPE_ASN1 &&
format != WolfSSL.SSL_FILETYPE_PEM) {
throw new WolfSSLException(
"Input format must be WolfSSL.SSL_FILETYPE_ASN1 or " +
"WolfSSL.SSL_FILETYPE_PEM");
}
if (format == WolfSSL.SSL_FILETYPE_PEM) {
/* convert PEM to DER */
input = certPemToDer(in, in.length);
if (input == null) {
throw new WolfSSLException("Failed to convert PEM to DER");
}
}
/* create from DER array */
x509Ptr = d2i_X509(input, input.length);
if (x509Ptr == 0) {
throw new WolfSSLException("Failed to create WolfSSLCertificate");
}
this.active = true;
}
@ -88,6 +128,51 @@ public class WolfSSLCertificate {
"Failed to create WolfSSLCertificate", ex);
}
x509Ptr = d2i_X509(der, der.length);
if (x509Ptr == 0) {
throw new WolfSSLException(
"Failed to create WolfSSLCertificate, d2i_X509() returned 0");
}
this.active = true;
}
public WolfSSLCertificate(String fileName, int format)
throws WolfSSLException {
InputStream stream = null;
byte[] bytes = null;
byte[] der = null;
if (fileName == null) {
throw new WolfSSLException("Input file must not be null");
}
if (format != WolfSSL.SSL_FILETYPE_ASN1 &&
format != WolfSSL.SSL_FILETYPE_PEM) {
throw new WolfSSLException(
"Input format must be WolfSSL.SSL_FILETYPE_ASN1 or " +
"WolfSSL.SSL_FILETYPE_PEM");
}
File f = new File(fileName);
try {
bytes = new byte[(int) f.length()];
stream = new FileInputStream(f);
stream.read(bytes, 0, bytes.length);
stream.close();
} catch (IOException ex) {
throw new WolfSSLException(
"Failed to create WolfSSLCertificate", ex);
}
if (format == WolfSSL.SSL_FILETYPE_PEM) {
/* convert PEM to DER */
der = certPemToDer(bytes, bytes.length);
if (der == null) {
throw new WolfSSLException("Failed to convert PEM to DER");
}
} else {
der = bytes;
}
x509Ptr = d2i_X509(der, der.length);
if (x509Ptr == 0) {
@ -225,6 +310,49 @@ public class WolfSSLCertificate {
return X509_is_extension_set(this.x509Ptr, oid);
}
/**
* Returns an immutable Collection of subject alternative names from this
* certificate's SubjectAltName extension.
*
* Each collection item is a List containing two objects:
* [0] = Integer representing type of name, 0-8 (ex: 2 == dNSName)
* [1] = String representing altname entry.
*
* Note: this currently returns all altNames as dNSName types, with the
* second list element being a String.
*
* @return immutable Collection of subject alternative names, or null
*/
public Collection<List<?>> getSubjectAltNames() {
if (this.active == false) {
throw new IllegalStateException("Object has been freed");
}
if (this.altNames != null) {
/* already gathered, return cached version */
return this.altNames;
}
Collection<List<?>> names = new ArrayList<List<?>>();
String nextAltName = X509_get_next_altname(this.x509Ptr);
while (nextAltName != null) {
Object[] entry = new Object[2];
entry[0] = 2; // Only return dNSName type for now
entry[1] = nextAltName;
List<?> entryList = Arrays.asList(entry);
names.add(Collections.unmodifiableList(entryList));
nextAltName = X509_get_next_altname(this.x509Ptr);
}
/* cache altNames collection for later use */
this.altNames = Collections.unmodifiableCollection(names);
return this.altNames;
}
/**
* Returns X509Certificate object based on this certificate.
*

View File

@ -141,6 +141,9 @@ public class WolfSSLContext extends SSLContextSpi {
return;
}
WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO,
"Using X509TrustManager: " + tm.toString());
X509Certificate[] caList = tm.getAcceptedIssuers();
if (caList == null) {
WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO,

View File

@ -77,6 +77,8 @@ public final class WolfSSLProvider extends Provider {
"com.wolfssl.provider.jsse.WolfSSLContext$DEFAULT_Context");
/* Trust Factory */
put("TrustManagerFactory.PKIX",
"com.wolfssl.provider.jsse.WolfSSLTrustManager");
put("TrustManagerFactory.X509",
"com.wolfssl.provider.jsse.WolfSSLTrustManager");
put("TrustManagerFactory.SunX509",

View File

@ -26,16 +26,22 @@ import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.ByteArrayInputStream;
import java.security.InvalidAlgorithmParameterException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import java.security.cert.Certificate;
import java.security.cert.CertificateFactory;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.net.ssl.ManagerFactoryParameters;
import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactorySpi;
import com.wolfssl.WolfSSL;
import com.wolfssl.WolfSSLCertificate;
import com.wolfssl.WolfSSLException;
/**
* wolfSSL implemenation of TrustManagerFactorySpi
@ -51,47 +57,177 @@ public class WolfSSLTrustManager extends TrustManagerFactorySpi {
if (in == null) {
String pass = System.getProperty("javax.net.ssl.trustStorePassword");
String file = System.getProperty("javax.net.ssl.trustStore");
String type = System.getProperty("javax.net.ssl.trustStoreType");
String vmVendor = System.getProperty("java.vm.vendor");
char passAr[] = null;
InputStream stream = null;
boolean systemCertsFound = false;
int aliasCnt = 0;
String[] cafiles = null;
try {
if (pass != null) {
passAr = pass.toCharArray();
}
certs = KeyStore.getInstance("JKS");
/* default to JKS KeyStore type if not set at system level */
try {
if (type != null && type != "") {
certs = KeyStore.getInstance(type);
} else {
if (vmVendor.equals("The Android Project")) {
WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO,
"Detected Android VM, using BKS KeyStore type");
certs = KeyStore.getInstance("BKS");
} else {
certs = KeyStore.getInstance("JKS");
}
}
} catch (KeyStoreException kse) {
WolfSSLDebug.log(getClass(), WolfSSLDebug.ERROR,
"Unsupported KeyStore type: " + type);
throw kse;
}
try {
/* initialize KeyStore, loading certs below will
* overwrite if needed, otherwise Android needs
* this to be initialized here */
certs.load(null, null);
} catch (Exception e) {
WolfSSLDebug.log(getClass(), WolfSSLDebug.ERROR,
"Error initializing KeyStore with load(null, null)");
throw e;
}
if (file == null) {
/* try to load trusted system certs if possible */
String home = System.getenv("JAVA_HOME");
if (home != null) {
if (!home.endsWith("/") && !home.endsWith("\\")) {
/* add trailing slash if not there already */
home = home.concat("/");
}
WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO,
"$JAVA_HOME = " + home);
/* trying: "lib/security/jssecacerts" */
File f = new File(home.concat(
"lib/security/jssecacerts"));
"jre/lib/security/jssecacerts"));
if (f.exists()) {
WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO,
"Loading certs from " +
home.concat("lib/security/jssecacerts"));
stream = new FileInputStream(f);
certs.load(stream, passAr);
stream.close();
systemCertsFound = true;
}
else {
f = new File(home.concat("lib/security/cacerts"));
if (f.exists()) {
WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO,
"Loading certs from " +
home.concat("lib/security/cacerts"));
stream = new FileInputStream(f);
certs.load(stream, passAr);
}
else {
WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO,
"Using Anonymous cipher suite");
}
/* trying: "lib/security/cacerts" */
f = new File(home.concat("jre/lib/security/cacerts"));
if (f.exists()) {
WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO,
"Loading certs from " +
home.concat("lib/security/cacerts"));
stream = new FileInputStream(f);
certs.load(stream, passAr);
stream.close();
systemCertsFound = true;
}
}
/* ANDROID, detect based on ANDROID_ROOT */
home = System.getenv("ANDROID_ROOT");
if (home != null) {
/* try: "/system/security/cacerts/*"
* this is a directory of individual PEM files */
if (!home.endsWith("/") && !home.endsWith("\\")) {
/* add trailing slash if not there already */
home = home.concat("/");
}
String caStoreDir = home.concat("etc/security/cacerts");
File cadir = new File(caStoreDir);
try {
cafiles = cadir.list();
} catch (Exception e) {
/* denied access reading cacerts directory */
WolfSSLDebug.log(getClass(), WolfSSLDebug.ERROR,
"Permission error when trying to read " +
"system CA certificates");
throw e;
}
WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO,
"Found " + cafiles.length + " CA files to load " +
"into KeyStore");
/* get factory for cert creation */
CertificateFactory cfactory =
CertificateFactory.getInstance("X.509");
/* loop over all PEM certs */
for (String cafile : cafiles) {
WolfSSLCertificate certPem;
String fullCertPath = caStoreDir.concat("/");
fullCertPath = fullCertPath.concat(cafile);
try {
certPem = new WolfSSLCertificate(
fullCertPath, WolfSSL.SSL_FILETYPE_PEM);
} catch (WolfSSLException we) {
/* skip, error parsing PEM */
WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO,
"Skipped loading cert: " + fullCertPath);
continue;
}
byte[] derArray = certPem.getDer();
ByteArrayInputStream bis =
new ByteArrayInputStream(derArray);
Certificate tmpCert = null;
try {
tmpCert = cfactory.generateCertificate(bis);
} catch (CertificateException ce) {
WolfSSLDebug.log(getClass(), WolfSSLDebug.ERROR,
"Error generating certificate from " +
"ByteArrayInputStream");
throw ce;
}
String aliasString = "alias" + aliasCnt;
try {
certs.setCertificateEntry(aliasString, tmpCert);
} catch (KeyStoreException kse) {
WolfSSLDebug.log(getClass(), WolfSSLDebug.ERROR,
"Error setting certificate entry in " +
"KeyStore, skipping loading cert");
continue;
}
/* increment alias counter for unique aliases */
aliasCnt++;
}
systemCertsFound = true;
}
if (systemCertsFound == false) {
WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO,
"No trusted system certs found, " +
"using Anonymous cipher suite");
}
}
else {
WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO,
"Loading certs from " + file);
stream = new FileInputStream(file);
certs.load(stream, passAr);
stream.close();
}
} catch (FileNotFoundException ex) {
Logger.getLogger(
@ -110,14 +246,6 @@ public class WolfSSLTrustManager extends TrustManagerFactorySpi {
WolfSSLTrustManager.class.getName()).log(
Level.SEVERE, null, ex);
}
if (stream != null) {
try {
stream.close();
} catch (IOException e) {
throw new KeyStoreException("Unable to close stream");
}
}
}
this.store = certs;
}

View File

@ -129,8 +129,13 @@ public class WolfSSLTrustX509 implements X509TrustManager {
@Override
public X509Certificate[] getAcceptedIssuers() {
if (CAs != null)
if (CAs != null) {
WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO,
"accepted issuer array size = " + CAs.size());
return CAs.toArray(new X509Certificate[CAs.size()]);
}
WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO,
"accepted issuer array is null");
return null;
}
}

View File

@ -34,11 +34,14 @@ import java.security.cert.CertificateEncodingException;
import java.security.cert.CertificateException;
import java.security.cert.CertificateExpiredException;
import java.security.cert.CertificateNotYetValidException;
import java.security.cert.CertificateParsingException;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.Date;
import java.util.Set;
import java.util.TreeSet;
import java.util.List;
import java.util.Collection;
import com.wolfssl.WolfSSLCertificate;
import com.wolfssl.WolfSSLException;
@ -187,6 +190,12 @@ public class WolfSSLX509 extends X509Certificate {
return ret;
}
@Override
public Collection<List<?>> getSubjectAlternativeNames()
throws CertificateParsingException {
return this.cert.getSubjectAltNames();
}
@Override
public void verify(PublicKey key)
throws CertificateException, NoSuchAlgorithmException,

View File

@ -65,6 +65,7 @@ class WolfSSLTestFactory {
protected String caJKS;
protected String rsaJKS;
protected String googleCACert;
protected String exampleComCert;
protected final static char[] jksPass = "wolfSSL test".toCharArray();
protected String keyStoreType = "JKS";
private boolean extraDebug = false;
@ -77,6 +78,7 @@ class WolfSSLTestFactory {
caJKS = "examples/provider/cacerts.jks";
rsaJKS = "examples/provider/rsa.jks";
googleCACert = "examples/certs/ca-google-root.der";
exampleComCert = "examples/certs/example-com.der";
/* test if running from IDE directory */
File f = new File(serverJKS);
@ -104,6 +106,7 @@ class WolfSSLTestFactory {
caJKS = in.concat(caJKS);
rsaJKS = in.concat(rsaJKS);
googleCACert = in.concat(googleCACert);
exampleComCert = in.concat(exampleComCert);
}
private boolean isIDEFile() {

View File

@ -43,6 +43,9 @@ import java.security.cert.CertificateNotYetValidException;
import java.security.cert.X509Certificate;
import java.util.Date;
import java.util.Set;
import java.util.List;
import java.util.ArrayList;
import java.util.Collection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLEngine;
@ -545,6 +548,79 @@ public class WolfSSLX509Test {
pass("\t\t... passed");
}
@Test
public void testSubjectAlternativeNames() {
X509Certificate x509;
int ALT_DNS_NAME = 2; /* dNSName type */
System.out.print("\tTesting getting alt names");
/* populate known alt name list for example.com cert, for comparison */
List<String> expected = new ArrayList<>();
expected.add("www.example.net");
expected.add("www.example.edu");
expected.add("www.example.com");
expected.add("example.org");
expected.add("example.net");
expected.add("example.edu");
expected.add("example.com");
expected.add("www.example.org");
/* list to hold found altNames */
List<String> found = new ArrayList<>();
try {
x509 = new WolfSSLX509(tf.exampleComCert);
Collection<?> subjectAltNames = x509.getSubjectAlternativeNames();
if (subjectAltNames == null) {
error("\t... failed");
fail("subjectAltNames Collection was null");
}
for (Object subjectAltName : subjectAltNames) {
List<?> entry = (List<?>)subjectAltName;
if (entry == null || entry.size() < 2) {
error("\t... failed");
fail("subjectAltName List<?> null or length < 2");
}
Integer altNameType = (Integer)entry.get(0);
if (altNameType == null) {
error("\t... failed");
fail("subjectAltName List[0] was null, should be Integer");
}
if (altNameType != ALT_DNS_NAME) {
error("\t... failed");
fail("subjectAltName type is not ALT_DNS_NAME (2)");
}
String altName = (String)entry.get(1);
if (altName == null) {
error("\t... failed");
fail("Individual altName was null, should not be");
}
found.add(altName);
}
if (found.size() != expected.size()) {
error("\r... failed");
fail("altName list size differs from expected size");
}
for (int i = 0; i < found.size(); i++) {
if (!found.get(i).equals(expected.get(i))) {
error("\r... failed");
fail("altName entry does not match expected: found: " +
found.get(i) + ", expected: " + expected.get(i));
}
}
} catch (Exception ex) {
error("\t... failed");
fail("unexpected exception found");
}
pass("\t... passed");
}
private void pass(String msg) {
WolfSSLTestFactory.pass(msg);

View File

@ -33,6 +33,7 @@ import java.util.logging.Logger;
import static org.junit.Assert.fail;
import org.junit.Test;
import com.wolfssl.WolfSSL;
import com.wolfssl.WolfSSLCertificate;
import com.wolfssl.WolfSSLException;
@ -44,7 +45,8 @@ public class WolfSSLCertificateTest {
public final static int TEST_FAIL = -1;
public final static int TEST_SUCCESS = 0;
public static String cliCert = "examples/certs/client-cert.der";
public static String cliCertDer = "examples/certs/client-cert.der";
public static String cliCertPem = "examples/certs/client-cert.pem";
public static String external = "examples/certs/ca-google-root.der";
public static String bogusFile = "/dev/null";
private WolfSSLCertificate cert;
@ -54,10 +56,29 @@ public class WolfSSLCertificateTest {
System.out.println("WolfSSLCertificate Class");
cliCert = WolfSSLTestCommon.getPath(cliCert);
external = WolfSSLTestCommon.getPath(external);
test_WolfSSLCertificate_new();
cliCertDer = WolfSSLTestCommon.getPath(cliCertDer);
cliCertPem = WolfSSLTestCommon.getPath(cliCertPem);
external = WolfSSLTestCommon.getPath(external);
/* WolfSSLCertificate(byte[] der) */
test_WolfSSLCertificate_new_derArray();
test_runCertTestsAfterConstructor();
/* WolfSSLCertificate(String der) */
test_WolfSSLCertificate_new_pemArray();
test_runCertTestsAfterConstructor();
/* WolfSSLCertificate(byte[] pem) */
test_WolfSSLCertificate_new_derFile();
test_runCertTestsAfterConstructor();
/* WolfSSLCertificate(String pem) */
test_WolfSSLCertificate_new_pemFile();
test_runCertTestsAfterConstructor();
}
public void test_runCertTestsAfterConstructor() {
test_getSerial();
test_notBefore();
test_notAfter();
@ -77,89 +98,154 @@ public class WolfSSLCertificateTest {
test_toString();
test_free();
}
public void test_WolfSSLCertificate_new() {
File f = new File(cliCert);
public void test_WolfSSLCertificate_new_derArray() {
File f = new File(cliCertDer);
byte[] der = null;
System.out.print("\tWolfSSLCertificate_new");
System.out.print("\tnew(byte[] der)");
try {
InputStream stream = new FileInputStream(f);
der = new byte[(int) f.length()];
stream.read(der, 0, der.length);
stream.close();
} catch (IOException ex) {
System.out.println("\t\t... failed");
fail("Unable to read file " + cliCert);
Logger.getLogger(WolfSSLCertificateTest.class.getName()).log(Level.SEVERE, null, ex);
System.out.println("\t\t\t... failed");
fail("Unable to read file " + cliCertDer);
Logger.getLogger(WolfSSLCertificateTest.class.getName()).log(
Level.SEVERE, null, ex);
}
try {
this.cert = new WolfSSLCertificate(der);
} catch (WolfSSLException ex) {
System.out.println("\t\t... failed");
System.out.println("\t\t\t... failed");
fail("Unable to initialize class");
Logger.getLogger(WolfSSLCertificateTest.class.getName()).log(Level.SEVERE, null, ex);
Logger.getLogger(WolfSSLCertificateTest.class.getName()).log(
Level.SEVERE, null, ex);
}
System.out.println("\t\t... passed");
System.out.println("\t\t\t... passed");
}
public void test_WolfSSLCertificate_new_derFile() {
System.out.print("\tnew(String der, int format)");
try {
this.cert = new WolfSSLCertificate(cliCertDer,
WolfSSL.SSL_FILETYPE_ASN1);
} catch (WolfSSLException ex) {
System.out.println("\t... failed");
fail("Unable to initialize class");
Logger.getLogger(WolfSSLCertificateTest.class.getName()).log(
Level.SEVERE, null, ex);
}
System.out.println("\t... passed");
}
public void test_WolfSSLCertificate_new_pemArray() {
File f = new File(cliCertPem);
byte[] pem = null;
System.out.print("\tnew(byte[] in, int format)");
try {
InputStream stream = new FileInputStream(f);
pem = new byte[(int) f.length()];
stream.read(pem, 0, pem.length);
stream.close();
} catch (IOException ex) {
System.out.println("\t... failed");
fail("Unable to read file " + cliCertPem);
Logger.getLogger(WolfSSLCertificateTest.class.getName()).log(
Level.SEVERE, null, ex);
}
try {
this.cert = new WolfSSLCertificate(pem, WolfSSL.SSL_FILETYPE_PEM);
} catch (WolfSSLException ex) {
System.out.println("\t... failed");
fail("Unable to initialize class");
Logger.getLogger(WolfSSLCertificateTest.class.getName()).log(
Level.SEVERE, null, ex);
}
System.out.println("\t... passed");
}
public void test_WolfSSLCertificate_new_pemFile() {
System.out.print("\tnew(String pem, int format)");
try {
this.cert = new WolfSSLCertificate(cliCertPem,
WolfSSL.SSL_FILETYPE_PEM);
} catch (WolfSSLException ex) {
System.out.println("\t... failed");
fail("Unable to initialize class");
Logger.getLogger(WolfSSLCertificateTest.class.getName()).log(
Level.SEVERE, null, ex);
}
System.out.println("\t... passed");
}
public void test_getSerial() {
byte[] expected = new byte[]{(byte)0xaa, (byte)0xc4, (byte)0xbf,
(byte)0x4c, (byte)0x50, (byte)0xbd, (byte)0x55, (byte)0x77};
byte[] serial;
int i;
BigInteger bigi = cert.getSerial();
System.out.print("\tgetSerial");
System.out.print("\t\tgetSerial");
serial = bigi.toByteArray();
for (i = 0; i < serial.length && i < expected.length; i++) {
if (serial[i] != expected[i]) {
System.out.println("\t\t\t... failed");
System.out.println("\t\t... failed");
fail("Unexpected serial number");
}
}
System.out.println("\t\t\t... passed");
System.out.println("\t\t... passed");
}
@SuppressWarnings("deprecation")
public void test_notBefore() {
Date date = cert.notBefore();
Date expected = new Date("Fri Apr 13 09:23:09 MDT 2018");
System.out.print("\tnotBefore");
System.out.print("\t\tnotBefore");
if (date.compareTo(expected) != 0) {
System.out.println("\t\t\t... failed");
System.out.println("\t\t... failed");
fail("Unexpected not before date");
}
System.out.println("\t\t\t... passed");
System.out.println("\t\t... passed");
}
@SuppressWarnings("deprecation")
public void test_notAfter() {
Date date = cert.notAfter();
Date expected = new Date("Thu Jan 07 08:23:09 MST 2021");
System.out.print("\tnotAfter");
System.out.print("\t\tnotAfter");
if (date.compareTo(expected) != 0) {
System.out.println("\t\t\t... failed");
System.out.println("\t\t... failed");
fail("Unexpected not after date");
}
System.out.println("\t\t\t... passed");
System.out.println("\t\t... passed");
}
public void test_getVersion() {
int version = cert.getVersion();
System.out.print("\tgetVersion");
System.out.print("\t\tgetVersion");
if (version != 3) {
System.out.println("\t\t\t... failed");
System.out.println("\t\t... failed");
fail("Unexpected version number");
}
System.out.println("\t\t\t... passed");
System.out.println("\t\t... passed");
}
public void test_getSignature() {
byte[] sig = cert.getSignature();
byte[] expected = new byte[] {
@ -217,47 +303,47 @@ public class WolfSSLCertificateTest {
(byte)0xB4
};
int i;
System.out.print("\tgetSignature");
System.out.print("\t\tgetSignature");
for (i = 0; i < sig.length && i < expected.length; i++) {
if (sig[i] != expected[i]) {
System.out.println("\t\t\t... failed");
fail("Unexpected signature");
System.out.println("\t\t... failed");
fail("Unexpected signature");
}
}
System.out.println("\t\t... passed");
}
public void test_isCA() {
System.out.print("\t\tisCA");
if (this.cert.isCA() != 1) {
System.out.println("\t\t\t... failed");
fail("Expected isCA to be set");
}
System.out.println("\t\t\t... passed");
}
public void test_isCA() {
System.out.print("\tisCA");
if (this.cert.isCA() != 1) {
System.out.println("\t\t\t\t... failed");
fail("Expected isCA to be set");
}
System.out.println("\t\t\t\t... passed");
}
public void test_getSubject() {
String expected = "/C=US/ST=Montana/L=Bozeman/O=wolfSSL_2048/OU=Programming-2048/CN=www.wolfssl.com/emailAddress=info@wolfssl.com";
System.out.print("\tgetSubject");
System.out.print("\t\tgetSubject");
if (!cert.getSubject().equals(expected)) {
System.out.println("\t\t\t... failed");
fail("Unexpected subject");
System.out.println("\t\t... failed");
fail("Unexpected subject");
}
System.out.println("\t\t\t... passed");
System.out.println("\t\t... passed");
}
public void test_getIssuer() {
String expected = "/C=US/ST=Montana/L=Bozeman/O=wolfSSL_2048/OU=Programming-2048/CN=www.wolfssl.com/emailAddress=info@wolfssl.com";
System.out.print("\tgetIssuer");
System.out.print("\t\tgetIssuer");
if (!cert.getIssuer().equals(expected)) {
System.out.println("\t\t\t... failed");
fail("Unexpected issuer");
System.out.println("\t\t... failed");
fail("Unexpected issuer");
}
System.out.println("\t\t\t... passed");
System.out.println("\t\t... passed");
}
public void test_getPubkey() {
byte[] expected = new byte[] {
(byte)0x30, (byte)0x82, (byte)0x01, (byte)0x22,
@ -331,147 +417,147 @@ public class WolfSSLCertificateTest {
};
int i;
byte[] pub;
System.out.print("\tgetPubkey");
System.out.print("\t\tgetPubkey");
pub = cert.getPubkey();
for (i = 0; i < pub.length && i < expected.length; i++) {
if (pub[i] != expected[i]) {
System.out.println("\t\t\t... failed");
System.out.println("\t\t... failed");
fail("Unexpected public key value");
}
}
System.out.println("\t\t\t... passed");
System.out.println("\t\t... passed");
}
public void test_getPubkeyType() {
String expected = "RSA";
System.out.print("\tgetPubkeyType");
System.out.print("\t\tgetPubkeyType");
if (!expected.equals(this.cert.getPubkeyType())) {
System.out.println("\t\t\t... failed");
fail("Unexpected public key type value");
}
System.out.println("\t\t\t... passed");
}
public void test_getPathLen() {
int expected = -1;
System.out.print("\tgetPathLen");
if (this.cert.getPathLen() != expected) {
System.out.println("\t\t\t... failed");
fail("Unexpected path length value");
}
System.out.println("\t\t\t... passed");
}
public void test_getSignatureType() {
String expected = "SHA256withRSA";
System.out.print("\tgetSignatureType");
if (!expected.equals(this.cert.getSignatureType())) {
System.out.println("\t\t... failed");
fail("Unexpected signature type");
fail("Unexpected public key type value");
}
System.out.println("\t\t... passed");
}
public void test_getPathLen() {
int expected = -1;
System.out.print("\t\tgetPathLen");
if (this.cert.getPathLen() != expected) {
System.out.println("\t\t... failed");
fail("Unexpected path length value");
}
System.out.println("\t\t... passed");
}
public void test_getSignatureType() {
String expected = "SHA256withRSA";
System.out.print("\t\tgetSignatureType");
if (!expected.equals(this.cert.getSignatureType())) {
System.out.println("\t... failed");
fail("Unexpected signature type");
}
System.out.println("\t... passed");
}
public void test_verify() {
byte[] pubkey;
System.out.print("\tverify");
System.out.print("\t\tverify");
pubkey = this.cert.getPubkey();
if (pubkey == null) {
System.out.println("\t\t\t\t... failed");
System.out.println("\t\t\t... failed");
fail("Could not get public key");
return;
}
if (this.cert.verify(pubkey, pubkey.length) != true) {
System.out.println("\t\t\t\t... failed");
fail("Verify signature failed");
System.out.println("\t\t\t... failed");
fail("Verify signature failed");
}
System.out.println("\t\t\t\t... passed");
System.out.println("\t\t\t... passed");
}
public void test_getSignatureOID() {
System.out.print("\tgetSignatureOID");
System.out.print("\t\tgetSignatureOID");
/* make sure is sha256WithRSAEncryption OID */
if (!this.cert.getSignatureOID().equals("1.2.840.113549.1.1.11")) {
System.out.println("\t\t\t... failed");
fail("Could not get public key");
System.out.println("\t\t... failed");
fail("Could not get public key");
}
System.out.println("\t\t\t... passed");
System.out.println("\t\t... passed");
}
public void test_getKeyUsage() {
WolfSSLCertificate ext;
boolean[] expected = {
false, false, false, false, false, true, true, false, false
};
System.out.print("\tgetKeyUsage");
System.out.print("\t\tgetKeyUsage");
if (this.cert.getKeyUsage() != null) {
System.out.println("\t\t\t... failed");
fail("Found key usage extension when not expecting any");
System.out.println("\t\t... failed");
fail("Found key usage extension when not expecting any");
}
/* test with certificate that has key usage extension */
try {
int i;
boolean[] kuse;
ext = new WolfSSLCertificate(this.external);
kuse = ext.getKeyUsage();
if (kuse == null) {
System.out.println("\t\t\t... failed");
System.out.println("\t\t... failed");
fail("Did not find key usage extension");
return;
}
for (i = 0; i < kuse.length; i++) {
if (kuse[i] != expected[i]) {
System.out.println("\t\t\t... failed");
fail("Found wrong key usage extension");
System.out.println("\t\t... failed");
fail("Found wrong key usage extension");
}
}
ext.free();
} catch (WolfSSLException ex) {
Logger.getLogger(WolfSSLCertificateTest.class.getName()).log(Level.SEVERE, null, ex);
System.out.println("\t\t\t... failed");
fail("Error loading external certificate");
System.out.println("\t\t... failed");
fail("Error loading external certificate");
}
System.out.println("\t\t\t... passed");
System.out.println("\t\t... passed");
}
public void test_getExtensionSet() {
System.out.print("\tgetExtensionSet");
System.out.print("\t\tgetExtensionSet");
if (this.cert.getExtensionSet("2.5.29.19") != 1) {
System.out.println("\t\t\t... failed");
System.out.println("\t\t... failed");
fail("Error with basic constraint extension");
}
if (this.cert.getExtensionSet("2.5.29.14") != 1) {
System.out.println("\t\t\t... failed");
System.out.println("\t\t... failed");
fail("Error with subject key ID extension");
}
System.out.println("\t\t\t... passed");
System.out.println("\t\t... passed");
}
public void test_toString() {
String s;
System.out.print("\ttoString");
System.out.print("\t\ttoString");
s = cert.toString();
if (s == null) {
System.out.println("\t\t\t... failed");
System.out.println("\t\t... failed");
fail("Error getting certificate string");
}
System.out.println("\t\t... passed");
}
public void test_free() {
System.out.print("\t\tfree");
this.cert.free();
System.out.println("\t\t\t... passed");
}
public void test_free() {
System.out.print("\tfree");
this.cert.free();
System.out.println("\t\t\t\t... passed");
}
}