add non-standard X509TrustManager.checkServerTrusted(X509Certificate[], String, String) for use on Android

pull/109/head
Chris Conlon 2022-11-04 12:34:56 -06:00
parent 097a707a12
commit be13b9bc9d
10 changed files with 1189 additions and 24 deletions

View File

@ -85,6 +85,7 @@ mkdir examples/certs
exit
adb push ./examples/provider/*.bks /sdcard/examples/provider/
adb push ./examples/certs/ /sdcard/examples/
adb push ./examples/certs/intermediate/* /sdcard/examples/certs/intermediate/
```
## 4. Import and Build the Example Project with Android Studio

View File

@ -12,7 +12,7 @@ add_definitions(-DHAVE_FFDHE_2048 -DWOLFSSL_TLS13 -DHAVE_TLS_EXTENSIONS -DHAVE_S
-DECC_SHAMIR -DWC_RSA_PSS -DWOLFSSL_BASE64_ENCODE -DNO_RC4
-DWOLFSSL_SHA224 -DWOLFSSL_SHA3 -DHAVE_POLY1305 -DHAVE_ONE_TIME_AUTH -DHAVE_CHACHA
-DHAVE_HASHDRBG -DHAVE_TLS_EXTENSIONS -DHAVE_SUPPORTED_CURVES -DHAVE_EXTENDED_MASTER
-DHAVE_SNI -DHAVE_ALPN -DWOLFSSL_JNI -DWOLFSSL_DTLS -DOPENSSL_EXTRA -DOPENSSL_ALL
-DHAVE_SNI -DHAVE_ALPN -DWOLFSSL_JNI -DOPENSSL_EXTRA -DOPENSSL_ALL
-DHAVE_EX_DATA -DHAVE_CRL -DHAVE_OCSP -DHAVE_CRL_MONITOR -DPERSIST_SESSION_CACHE
-DPERSIST_CERT_CACHE -DATOMIC_USER -DHAVE_PK_CALLBACKS -DWOLFSSL_CERT_EXT -DWOLFSSL_CERT_GEN
-DHAVE_ENCRYPT_THEN_MAC -DNO_MD4 -DWOLFSSL_ENCRYPTED_KEYS -DUSE_FAST_MATH -DNO_DES3
@ -104,6 +104,8 @@ add_library(wolfssl SHARED
${wolfssl_DIR}/wolfcrypt/src/wolfevent.c
${wolfssl_DIR}/wolfcrypt/src/wolfmath.c
${wolfssl_DIR}/src/crl.c
${wolfssl_DIR}/src/dtls13.c
${wolfssl_DIR}/src/dtls.c
${wolfssl_DIR}/src/internal.c
${wolfssl_DIR}/src/keys.c
${wolfssl_DIR}/src/ocsp.c

View File

@ -0,0 +1,24 @@
-----BEGIN CERTIFICATE-----
MIIEFzCCAv+gAwIBAgICEAAwDQYJKoZIhvcNAQELBQAwgZQxCzAJBgNVBAYTAlVT
MRAwDgYDVQQIDAdNb250YW5hMRAwDgYDVQQHDAdCb3plbWFuMREwDwYDVQQKDAhT
YXd0b290aDETMBEGA1UECwwKQ29uc3VsdGluZzEYMBYGA1UEAwwPd3d3LndvbGZz
c2wuY29tMR8wHQYJKoZIhvcNAQkBFhBpbmZvQHdvbGZzc2wuY29tMB4XDTIwMDYx
NjE5MTc1N1oXDTQwMDYxMTE5MTc1N1owgZ8xCzAJBgNVBAYTAlVTMRMwEQYDVQQI
DApXYXNoaW5ndG9uMRAwDgYDVQQHDAdTZWF0dGxlMRAwDgYDVQQKDAd3b2xmU1NM
MRQwEgYDVQQLDAtEZXZlbG9wbWVudDEgMB4GA1UEAwwXd29sZlNTTCBJbnRlcm1l
ZGlhdGUgQ0ExHzAdBgkqhkiG9w0BCQEWEGluZm9Ad29sZnNzbC5jb20wggEiMA0G
CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDyIyj3gUPwY7nyd34wGkBr4d1rQTbu
fVgj3Fbpu+g7EVjDw7frmFrpdhLN73cJJdNs5jpJaFCQ1zLgGNYF3/ee0o97tZFc
vz4Jgd157UTCk/WdpMsKa2O08O7R3WznxrfxMNS3VCgYEfwlrFvxsxkTR31+2UWX
PLu5QnAGlFUjFQuEygwVwW4aHPlUyebjuMFF5VqJ4fEbHYG3NAcXKFsQx6Yh612J
EaPQOWA06uF1+rh87sU/ZGoduNiksoKYMRHotSAtA+XRYTWkS7WtprdycT6GOA44
tl21q786uh4ydrpUTQXKTuKD3zBkEZ6Zkzum+zvffZAC9LTx6EExeAI/AgMBAAGj
ZjBkMB0GA1UdDgQWBBSDHPGYhexuBkU03lHAurcrZzJmTTAfBgNVHSMEGDAWgBQn
jmcRdMMmHT/tM2OzpNgdMOXo1TASBgNVHRMBAf8ECDAGAQH/AgEBMA4GA1UdDwEB
/wQEAwIBhjANBgkqhkiG9w0BAQsFAAOCAQEAfQ1cKhnn7l/KLdRZVLnKMxg64yIs
GHC7xVhF2YK8gF2Q2QI0bBpP8WtZTs3h6ieA5uLYfq8rrMFi4E3p5nSZ/sBQy9N9
5SuCDWcNFLUsaqJ6wt0Ip0Aqj6G/TVN1Xd3DguXkHwSwtqfMVWy01HSemjY38DJp
l0T70iIai5U0RDLMKql29xLHuZvx5afH1W0S7AAdIbIT8jPg6uDIY3zdBsc8uqS9
oJuNoRp9OtfJ8zVOxXZrbVDRlSPowH89P0UIEHdrKWjM3bYg+MEVTG/iq51hE928
xeeYzCMpuhy2IcCwtuneK0PXynsoavpMyTlN4UDt5sAWnWmy+b/bUCc8sw==
-----END CERTIFICATE-----

View File

@ -0,0 +1,16 @@
-----BEGIN CERTIFICATE-----
MIICkzCCAjigAwIBAgICEAQwCgYIKoZIzj0EAwIwgZcxCzAJBgNVBAYTAlVTMRMw
EQYDVQQIDApXYXNoaW5ndG9uMRAwDgYDVQQHDAdTZWF0dGxlMRAwDgYDVQQKDAd3
b2xmU1NMMRQwEgYDVQQLDAtEZXZlbG9wbWVudDEYMBYGA1UEAwwPd3d3LndvbGZz
c2wuY29tMR8wHQYJKoZIhvcNAQkBFhBpbmZvQHdvbGZzc2wuY29tMB4XDTIwMDYx
NjE5MTc1OFoXDTQwMDYxMTE5MTc1OFowgaMxCzAJBgNVBAYTAlVTMRMwEQYDVQQI
DApXYXNoaW5ndG9uMRAwDgYDVQQHDAdTZWF0dGxlMRAwDgYDVQQKDAd3b2xmU1NM
MRQwEgYDVQQLDAtEZXZlbG9wbWVudDEkMCIGA1UEAwwbd29sZlNTTCBJbnRlcm1l
ZGlhdGUgQ0EgRUNDMR8wHQYJKoZIhvcNAQkBFhBpbmZvQHdvbGZzc2wuY29tMFkw
EwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAExpzNj+XsW9iw/JEg4gs7UVNUS4lDjgDe
ka7TkPOF3Mw9EQgVdoLikjVK1EWOgzaCYrhNB4ULpVTgFOiT3n+S6KNmMGQwHQYD
VR0OBBYEFBO1eVkys7u0R7M0DoDAgx6qgshbMB8GA1UdIwQYMBaAFFaOmsPwQt4Y
uUVVbvmTz+rD86UhMBIGA1UdEwEB/wQIMAYBAf8CAQEwDgYDVR0PAQH/BAQDAgGG
MAoGCCqGSM49BAMCA0kAMEYCIQCKUZH2ksVKaWXbW5DDkGrAlucmeq8YkSxrZ1VA
GGzBpgIhAJbMnTet6nlSbk1Bk9tkf+dCufESkPSEXHOxIdj7Vf5v
-----END CERTIFICATE-----

View File

@ -0,0 +1,25 @@
-----BEGIN CERTIFICATE-----
MIIEIzCCAwugAwIBAgICEAEwDQYJKoZIhvcNAQELBQAwgZ8xCzAJBgNVBAYTAlVT
MRMwEQYDVQQIDApXYXNoaW5ndG9uMRAwDgYDVQQHDAdTZWF0dGxlMRAwDgYDVQQK
DAd3b2xmU1NMMRQwEgYDVQQLDAtEZXZlbG9wbWVudDEgMB4GA1UEAwwXd29sZlNT
TCBJbnRlcm1lZGlhdGUgQ0ExHzAdBgkqhkiG9w0BCQEWEGluZm9Ad29sZnNzbC5j
b20wHhcNMjAwNjE2MTkxNzU3WhcNNDAwNjExMTkxNzU3WjCBoDELMAkGA1UEBhMC
VVMxEzARBgNVBAgMCldhc2hpbmd0b24xEDAOBgNVBAcMB1NlYXR0bGUxEDAOBgNV
BAoMB3dvbGZTU0wxFDASBgNVBAsMC0RldmVsb3BtZW50MSEwHwYDVQQDDBh3b2xm
U1NMIEludGVybWVkaWF0ZTIgQ0ExHzAdBgkqhkiG9w0BCQEWEGluZm9Ad29sZnNz
bC5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCgL6ECMF0ZoY5E
htST9/FTuj/SJN//y6+Ppuf5h5ofAMyPQIZ4OhuaeA7jbtrz52xXdjHPAyGayHkp
YNvu2KkVtGdbd5qG+dtDzKIPkeZwTx5uFLGN8KHlOXehkpeISibxiJgkbP1G4nEH
Xa/UvKiMXe5DCNqn7AlR7a3NdYtYx6GYVucZeJNLU3e32nl9cIS7HemgPAK8p5b6
u5iQrjUZ0OdkHp0JoQbywv3LoykswHn46emTZ4w1LqFJoDRsOB1rTKW6x4SAlRcS
y92n9i4sxw/BVB+XbAE72i7H3FPJJuaaZqh/VfrNchhph06M5ALd9zEao27NiENw
tDRtpoZ1AgMBAAGjZjBkMB0GA1UdDgQWBBR6ix1Oo0DIzlhfjfz/Rix1QdkDXjAf
BgNVHSMEGDAWgBSDHPGYhexuBkU03lHAurcrZzJmTTASBgNVHRMBAf8ECDAGAQH/
AgEBMA4GA1UdDwEB/wQEAwIBhjANBgkqhkiG9w0BAQsFAAOCAQEADHKZ7ecDWMIr
iNKqQzGEGC/exV3gINhUPF4rhyqflrHvvtfHJ3ForHFhuG7Rqksv79Q357uHkGNI
OJsgFb28r4q0r1ORjoQRFOpvhfROugpJkbMZmSrR+aena/1/eIh7030ssZ9wFRrb
hpvOtwcl7DmMWaPS0cwYFRSghU1P+5pHL9xmx318EolIWNTLGhsSupztXIy/cg5f
jkI0S2w+BG/ZUOMok2sT/WvWLRvN+/4Lo4zfyOatnmmKk5bXhDG7yvLb4hjJ8ZGK
xwafwgrptF/jeyD8GhYcAlMSzWZFVW6xwJUtK9YZuJlOHxuc+7n+jH4yV/OA6fi+
JS8DRjyzCg==
-----END CERTIFICATE-----

View File

@ -0,0 +1,17 @@
-----BEGIN CERTIFICATE-----
MIICnzCCAkWgAwIBAgICEAUwCgYIKoZIzj0EAwIwgaMxCzAJBgNVBAYTAlVTMRMw
EQYDVQQIDApXYXNoaW5ndG9uMRAwDgYDVQQHDAdTZWF0dGxlMRAwDgYDVQQKDAd3
b2xmU1NMMRQwEgYDVQQLDAtEZXZlbG9wbWVudDEkMCIGA1UEAwwbd29sZlNTTCBJ
bnRlcm1lZGlhdGUgQ0EgRUNDMR8wHQYJKoZIhvcNAQkBFhBpbmZvQHdvbGZzc2wu
Y29tMB4XDTIwMDYxNjE5MTc1OFoXDTQwMDYxMTE5MTc1OFowgaQxCzAJBgNVBAYT
AlVTMRMwEQYDVQQIDApXYXNoaW5ndG9uMRAwDgYDVQQHDAdTZWF0dGxlMRAwDgYD
VQQKDAd3b2xmU1NMMRQwEgYDVQQLDAtEZXZlbG9wbWVudDElMCMGA1UEAwwcd29s
ZlNTTCBJbnRlcm1lZGlhdGUyIENBIEVDQzEfMB0GCSqGSIb3DQEJARYQaW5mb0B3
b2xmc3NsLmNvbTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABOoWKCwnXkGZBSiL
mfrFonQ8FU1S9EstgzSCjtW2P2HQh+v4TAZe7WYejMqk9ip2T9cmCUweibkYjtKj
ZjwbPcujZjBkMB0GA1UdDgQWBBQb9L2QKHRk4zNei2Sn/K+68rlV5TAfBgNVHSME
GDAWgBQTtXlZMrO7tEezNA6AwIMeqoLIWzASBgNVHRMBAf8ECDAGAQH/AgEBMA4G
A1UdDwEB/wQEAwIBhjAKBggqhkjOPQQDAgNIADBFAiBPG9Hh145ztYv3TQs9/BK8
b3ytuRJwMDdBJ+xrNQaORwIhAKFVkbdoHjJmN2gQCp827sOXK4W4PEc8Su0TxVtZ
vLUp
-----END CERTIFICATE-----

View File

@ -0,0 +1,29 @@
-----BEGIN CERTIFICATE-----
MIIE8jCCA9qgAwIBAgICEAIwDQYJKoZIhvcNAQELBQAwgaAxCzAJBgNVBAYTAlVT
MRMwEQYDVQQIDApXYXNoaW5ndG9uMRAwDgYDVQQHDAdTZWF0dGxlMRAwDgYDVQQK
DAd3b2xmU1NMMRQwEgYDVQQLDAtEZXZlbG9wbWVudDEhMB8GA1UEAwwYd29sZlNT
TCBJbnRlcm1lZGlhdGUyIENBMR8wHQYJKoZIhvcNAQkBFhBpbmZvQHdvbGZzc2wu
Y29tMB4XDTIwMDYxNjE5MTc1OFoXDTMwMDYxNDE5MTc1OFowgZwxCzAJBgNVBAYT
AlVTMRMwEQYDVQQIDApXYXNoaW5ndG9uMRAwDgYDVQQHDAdTZWF0dGxlMRAwDgYD
VQQKDAd3b2xmU1NMMRQwEgYDVQQLDAtEZXZlbG9wbWVudDEdMBsGA1UEAwwUd29s
ZlNTTCBTZXJ2ZXIgQ2hhaW4xHzAdBgkqhkiG9w0BCQEWEGluZm9Ad29sZnNzbC5j
b20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDAlQjhV0HycW230kVB
JwFlxkWu8rwkMLiVzi9O1vYciLx8n/uoZ3/+XJxRdfeKygfnNS+P4b17wC98q2So
F/zKXXu64CHlci5vLobYlXParBtTuV8/1xkNJU/hY2NRiwtkP61DuKUcXDSzrgCg
Y8X2fwtZaHhzpowYqQJtr8MZAS64EOPGzEC0aaNGM2mHbsS7F6bz6N2tc7x7LyG1
/WZRDL1Us+FtXxy8I3PRCQOJFNIQuWTDKtChlkq84dQaW8egwMFjeA9ENzAyloAy
I5Whd7oT0pdz4l0lyWoNwzlgpLSwaUJCCenYCLwzILNYIqeq68Th5mGDxdKW39nQ
T63XAgMBAAGjggE2MIIBMjAJBgNVHRMEAjAAMBEGCWCGSAGG+EIBAQQEAwIGQDAd
BgNVHQ4EFgQUsxEyyZKYhOLJ+NA7bgNCyh8Ojjwwgc0GA1UdIwSBxTCBwoAUeosd
TqNAyM5YX438/0YsdUHZA16hgaWkgaIwgZ8xCzAJBgNVBAYTAlVTMRMwEQYDVQQI
DApXYXNoaW5ndG9uMRAwDgYDVQQHDAdTZWF0dGxlMRAwDgYDVQQKDAd3b2xmU1NM
MRQwEgYDVQQLDAtEZXZlbG9wbWVudDEgMB4GA1UEAwwXd29sZlNTTCBJbnRlcm1l
ZGlhdGUgQ0ExHzAdBgkqhkiG9w0BCQEWEGluZm9Ad29sZnNzbC5jb22CAhABMA4G
A1UdDwEB/wQEAwIDqDATBgNVHSUEDDAKBggrBgEFBQcDATANBgkqhkiG9w0BAQsF
AAOCAQEAkpC/Vl2YIc7WCo18r7qbWdgzwSEPbzEcE8Wf3qh97+XFC4t+GMud2N7J
PTLu/9CJmDszaNvNZl6d7tpTNGUh40P2p7J5tXksLiM/PmFZgIj9w8UE6a1SqVh9
78WnhRpVYOENfhHIulnYxh02BGOOfa8o/RN6MvUp1wrvBjyFkLbGTzmxGO6+F6VE
F4ezlKE0Ykx3yAaTyAP18qpb/9CarfOyyluBVO8bOfjGd/GAUA8MbpQUYqP8mY7S
4za4JRttVdIbIZfThOaW7p+zAERwOp/8YuJCGpMe/J7sjRx6GrETRk7rDSi5TQjm
CTHAuy4H4MupWgaHxI66ay91VIU29Q==
-----END CERTIFICATE-----

View File

@ -0,0 +1,21 @@
-----BEGIN CERTIFICATE-----
MIIDczCCAxigAwIBAgICEAYwCgYIKoZIzj0EAwIwgaQxCzAJBgNVBAYTAlVTMRMw
EQYDVQQIDApXYXNoaW5ndG9uMRAwDgYDVQQHDAdTZWF0dGxlMRAwDgYDVQQKDAd3
b2xmU1NMMRQwEgYDVQQLDAtEZXZlbG9wbWVudDElMCMGA1UEAwwcd29sZlNTTCBJ
bnRlcm1lZGlhdGUyIENBIEVDQzEfMB0GCSqGSIb3DQEJARYQaW5mb0B3b2xmc3Ns
LmNvbTAeFw0yMDA2MTYxOTE3NThaFw0zMDA2MTQxOTE3NThaMIGgMQswCQYDVQQG
EwJVUzETMBEGA1UECAwKV2FzaGluZ3RvbjEQMA4GA1UEBwwHU2VhdHRsZTEQMA4G
A1UECgwHd29sZlNTTDEUMBIGA1UECwwLRGV2ZWxvcG1lbnQxITAfBgNVBAMMGHdv
bGZTU0wgU2VydmVyIENoYWluIEVDQzEfMB0GCSqGSIb3DQEJARYQaW5mb0B3b2xm
c3NsLmNvbTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABLszrEwnUErGSqUEwzze
nzbbci3OlOor+ssgCTksFuhhAumvTdMCk5oxW5eSIX/wzxjakRECNIboIFgzC4A0
idijggE6MIIBNjAJBgNVHRMEAjAAMBEGCWCGSAGG+EIBAQQEAwIGQDAdBgNVHQ4E
FgQUXV0m76x+NvmbdhUrSiUCI++yiTAwgdEGA1UdIwSByTCBxoAUG/S9kCh0ZOMz
Xotkp/yvuvK5VeWhgamkgaYwgaMxCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApXYXNo
aW5ndG9uMRAwDgYDVQQHDAdTZWF0dGxlMRAwDgYDVQQKDAd3b2xmU1NMMRQwEgYD
VQQLDAtEZXZlbG9wbWVudDEkMCIGA1UEAwwbd29sZlNTTCBJbnRlcm1lZGlhdGUg
Q0EgRUNDMR8wHQYJKoZIhvcNAQkBFhBpbmZvQHdvbGZzc2wuY29tggIQBTAOBgNV
HQ8BAf8EBAMCA6gwEwYDVR0lBAwwCgYIKwYBBQUHAwEwCgYIKoZIzj0EAwIDSQAw
RgIhAJjQ4vmJyrJ0NqczC/4UkBBFei1tQETbCOxFeYtOkeDVAiEA6hEbwbWVvL/Z
9Zk30dLmuKoZvZdCCbsKUWxOomFy6EQ=
-----END CERTIFICATE-----

View File

@ -27,6 +27,7 @@ import java.security.KeyStoreException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.List;
import java.util.Arrays;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.logging.Level;
@ -62,16 +63,233 @@ public class WolfSSLTrustX509 implements X509TrustManager {
}
/**
* Verify cert chain using WolfSSLCertManager, throw CertificateException
* on error/failure. Do all loading and verification in one function to
* avoid holding native resources at the object/class level. */
private void certManagerVerify(X509Certificate[] certs, String type)
* Sort provided certificate chain by subject and issuer.
* Begin with leaf cert, end with last most intermediate cert.
*
* @param certs Peer certificate chain, assuming leaf/peer is first
*
* @return List of X509Certifiates representing peer cert chain, sorted
* from leaf to last intermediate. Not including root CA.
* @throws CertificateException if error occurs while building chain.
*/
private X509Certificate[] sortCertChainBySubjectIssuer(
X509Certificate[] certs) throws CertificateException {
int i, curr, next;
boolean nextFound = false;
X509Certificate[] chain = null;
X509Certificate[] retChain = null;
if (certs == null) {
throw new CertificateException("Input cert chain null");
}
/* Make copy of peer cert chain, so we don't change original */
chain = certs.clone();
WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO,
"sorting peer chain (" + chain.length + " certs):");
for (i = 0; i < chain.length; i++) {
WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO,
"\t[" + i + "]: subject: " +
chain[i].getSubjectX500Principal().getName());
}
/* Assume peer/leaf cert is first in array */
for (curr = 0; curr < chain.length; curr++) {
nextFound = false;
for (next = curr + 1; next < chain.length; next++) {
/* check if next subject matches curr issuer */
if (chain[curr].getIssuerX500Principal().equals(
chain[next].getSubjectX500Principal())) {
/* if next not directly after curr, swap */
if (next != curr + 1) {
X509Certificate tmp = chain[next];
chain[next] = chain[curr + 1];
chain[curr + 1] = tmp;
}
nextFound = true;
break;
}
}
/* if next not found, stop building chain */
if (nextFound == false) {
break;
}
}
WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO,
"sorted peer chain (" + (curr + 1) + " certs):");
for (i = 0; i <= curr; i++) {
WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO,
"\t[" + i + "]: subject: " +
chain[i].getSubjectX500Principal().getName());
}
/* If chain is now shorter, return adjusted size array */
if (chain.length > (curr + 1)) {
retChain = Arrays.copyOf(chain, curr + 1);
} else {
retChain = chain;
}
return chain;
}
/**
* Finds and returns X509Certificate matching the root CA that will
* verify the given leaf/intermediate certificate.
*
* @param cert Certificate for which to find verifying root CA
* @param ks KeyStore to search in for root CA
*
* @return X509Certificate representing root CA which will verify cert
* @throws CertificateException on error/failure getting root CA.
*/
private X509Certificate findRootCAFromKeyStoreForCert(X509Certificate cert,
KeyStore ks) throws CertificateException {
int i = 0;
int ret = WolfSSL.SSL_FAILURE;
int verifiedRootIdx = -1;
WolfSSLCertManager cm = null;
List<X509Certificate> possibleCerts = new ArrayList<X509Certificate>();
byte[] encodedRoot = null;
byte[] encodedCert = null;
boolean rootFound = false;
if (cert == null || ks == null) {
throw new CertificateException("cert or keystore is null");
}
/* Issuer name we need to match */
X500Principal issuer = cert.getIssuerX500Principal();
WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO,
"Searching KeyStore for root CA matching: " + issuer.getName());
/* Find all issuers that match needed issuer name */
try {
Enumeration<String> aliases = ks.aliases();
while (aliases.hasMoreElements()) {
String name = aliases.nextElement();
X509Certificate root = null;
if (ks.isKeyEntry(name)) {
Certificate[] chain = ks.getCertificateChain(name);
if (chain != null) {
root = (X509Certificate) chain[0];
}
} else {
root = (X509Certificate) ks.getCertificate(name);
}
if (root != null && root.getBasicConstraints() >= 0) {
if (root.getSubjectX500Principal().equals(issuer)) {
/* Found correct CN, add to possible roots list */
possibleCerts.add(root);
}
}
}
} catch (KeyStoreException ex) {
throw new CertificateException(ex);
}
if (possibleCerts.size() == 0) {
WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO,
"No root CA found in KeyStore to validate certificate");
return null;
}
WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO,
"Found " + possibleCerts.size() + " possible root CAs, testing");
/* Use wolfSSL Cert Manager to make sure root verifies input cert */
try {
cm = new WolfSSLCertManager();
} catch (WolfSSLException e) {
throw new CertificateException(
"Failed to create native WolfSSLCertManager");
}
for (i = 0; i < possibleCerts.size(); i++) {
/* load candidate root CA as trusted */
encodedRoot = possibleCerts.get(i).getEncoded();
ret = cm.CertManagerLoadCABuffer(encodedRoot, encodedRoot.length,
WolfSSL.SSL_FILETYPE_ASN1);
if (ret != WolfSSL.SSL_SUCCESS) {
cm.free();
throw new CertificateException("Failed to load root CA DER" +
"into wolfSSL cert manager");
}
/* try to verify input cert */
encodedCert = cert.getEncoded();
ret = cm.CertManagerVerifyBuffer(encodedCert, encodedCert.length,
WolfSSL.SSL_FILETYPE_ASN1);
if (ret != WolfSSL.SSL_SUCCESS) {
WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO,
"Potential root " + i + " did not verify cert");
} else {
rootFound = true;
verifiedRootIdx = i;
WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO,
"Found valid root: " +
possibleCerts.get(i).getSubjectX500Principal().getName());
}
/* unload CAs from WolfSSLCertManager */
ret = cm.CertManagerUnloadCAs();
if (ret != WolfSSL.SSL_SUCCESS) {
WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO,
"Error unloading root CAs from WolfSSLCertManager");
cm.free();
throw new CertificateException("Failed to unload root CA " +
"from WolfSSLCertManager");
}
if (rootFound == true) {
break;
}
}
cm.free();
if (rootFound == true) {
return possibleCerts.get(verifiedRootIdx);
}
return null;
}
/**
* Verify cert chain using WolfSSLCertManager.
* Do all loading and verification in one function to avoid holding native
* resources at the object/class level.
*
* @param certs Certificate chain to validate
* @param type Authentication type
* @param returnChain Boolean (true/false), return validation chain or not
*
* @return Complete chain used for validation, including root CA, if
* returnChain is true. Otherwise, if returnChain is false return NULL
* @throws CertificateException on verification error/failure
*/
private List<X509Certificate> certManagerVerify(
X509Certificate[] certs, String type, boolean returnChain)
throws CertificateException {
int ret = WolfSSL.SSL_FAILURE;
WolfSSLCertManager cm = null;
X509Certificate[] sortedCerts = null;
if (certs == null || certs.length == 0 || type.length() == 0) {
X509Certificate rootCA = null;
List<X509Certificate> fullChain = null;
if (certs == null || certs.length == 0 ||
type == null || type.length() == 0) {
throw new CertificateException();
}
@ -92,24 +310,23 @@ public class WolfSSLTrustX509 implements X509TrustManager {
"Failed to load trusted certs into WolfSSLCertManager");
}
/* Here we assume certs chain starts with peer certificate (certs[0])
* and is followed incrementally by intermedaite certificates in the
* correct order. If the chain is out of order, this verification
* will fail and reorder logic will need to be implemented
*
* Walk backwards down list of intermediate CA certs, verify each one
* based on trusted certs we already have loaeded in the CertManager,
/* Sort cert chain in order from peer to last intermedate. We
* assume cert chain starts with peer certificate (certs[0]). */
sortedCerts = sortCertChainBySubjectIssuer(certs);
/* Walk backwards down list of intermediate CA certs, verify each one
* based on trusted certs we already have loaded in the CertManager,
* then once verified load the intermediate into the CertManager
* as a root that can be used to verify our peer cert. */
for (int i = certs.length-1; i > 0; i--) {
for (int i = sortedCerts.length-1; i > 0; i--) {
/* Verify chain cert */
WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO,
"Verifying intermediate chain cert: " +
certs[i].getSubjectX500Principal().getName());
sortedCerts[i].getSubjectX500Principal().getName());
byte[] encoded = certs[i].getEncoded();
byte[] encoded = sortedCerts[i].getEncoded();
ret = cm.CertManagerVerifyBuffer(encoded, encoded.length,
WolfSSL.SSL_FILETYPE_ASN1);
if (ret != WolfSSL.SSL_SUCCESS) {
@ -129,15 +346,15 @@ public class WolfSSLTrustX509 implements X509TrustManager {
WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO,
"Loaded intermediate CA: " +
certs[i].getSubjectX500Principal().getName());
sortedCerts[i].getSubjectX500Principal().getName());
}
/* Verify peer certificate */
WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO,
"Verifying peer certificate: " +
certs[0].getSubjectX500Principal().getName());
sortedCerts[0].getSubjectX500Principal().getName());
byte[] peer = certs[0].getEncoded();
byte[] peer = sortedCerts[0].getEncoded();
if (peer == null) {
cm.free();
throw new CertificateException("Failed to get encoded peer cert");
@ -154,9 +371,25 @@ public class WolfSSLTrustX509 implements X509TrustManager {
WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO,
"Verified peer certificate: " +
certs[0].getSubjectX500Principal().getName());
sortedCerts[0].getSubjectX500Principal().getName());
cm.free();
if (returnChain == true) {
/* Find root CA from KeyStore to append to chain */
rootCA = findRootCAFromKeyStoreForCert(
sortedCerts[sortedCerts.length - 1], this.store);
if (rootCA == null) {
throw new CertificateException("Unable to find root CA " +
"in KeyStore to append to chain list");
}
fullChain = new ArrayList<X509Certificate>();
fullChain.addAll(Arrays.asList(sortedCerts));
fullChain.add(rootCA);
}
return fullChain;
}
@Override
@ -166,7 +399,7 @@ public class WolfSSLTrustX509 implements X509TrustManager {
WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO,
"entered checkClientTrusted()");
certManagerVerify(certs, type);
certManagerVerify(certs, type, false);
}
@Override
@ -176,7 +409,31 @@ public class WolfSSLTrustX509 implements X509TrustManager {
WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO,
"entered checkServerTrusted()");
certManagerVerify(certs, type);
certManagerVerify(certs, type, false);
}
/**
* Verifies a specified certificate chain.
* Non standard API, this is called/needed on some versions of Android.
*
* @param certs Certificate chain to validate
* @param type Authentication type
* @param host Hostname of the server. Cert pinning at this level not
* currently supported by wolfJSSE. If supported, and host was
* non-null, would check if chain is pinned correctly for
* this host.
*
* @throws CertificateException if chain does not verify properly
* @return Certificate chain used for verification, ordered with leaf/peer
* cert first, root CA cert last
*/
public List<X509Certificate> checkServerTrusted(X509Certificate[] certs,
String type, String host) throws CertificateException {
WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO,
"entered checkServerTrusted()");
return certManagerVerify(certs, type, true);
}
@Override

View File

@ -23,8 +23,12 @@ package com.wolfssl.provider.jsse.test;
import com.wolfssl.WolfSSL;
import com.wolfssl.WolfSSLException;
import com.wolfssl.provider.jsse.WolfSSLProvider;
import com.wolfssl.provider.jsse.WolfSSLTrustX509;
import java.util.List;
import java.io.File;
import java.io.FileInputStream;
import java.io.BufferedInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
@ -34,10 +38,13 @@ import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.Provider;
import java.security.Security;
import java.security.cert.Certificate;
import java.security.cert.CertificateFactory;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.fail;
import org.junit.BeforeClass;
@ -72,6 +79,7 @@ public class WolfSSLTrustX509Test {
}
/* Testing WolfSSLTrustX509.getAcceptedIssuers() with all.jks */
@Test
public void testCAParsing()
throws NoSuchProviderException, NoSuchAlgorithmException {
@ -138,6 +146,7 @@ public class WolfSSLTrustX509Test {
pass("\t\t... passed");
}
/* Testing WolfSSLTrustX509.getAcceptedIssuers() with server.jks */
@Test
public void testServerParsing()
throws NoSuchProviderException, NoSuchAlgorithmException {
@ -201,6 +210,7 @@ public class WolfSSLTrustX509Test {
}
/* Testing WolfSSLTrustX509.getAcceptedIssuers() with all_mixed.jks */
@Test
public void testCAParsingMixed()
throws NoSuchProviderException, NoSuchAlgorithmException {
@ -317,8 +327,9 @@ public class WolfSSLTrustX509Test {
@Test
public void testVerify()
throws NoSuchProviderException, NoSuchAlgorithmException, KeyStoreException,
FileNotFoundException, IOException, CertificateException {
throws NoSuchProviderException, NoSuchAlgorithmException,
KeyStoreException, FileNotFoundException, IOException,
CertificateException {
TrustManager[] tm;
X509TrustManager x509tm;
X509Certificate cas[];
@ -386,6 +397,768 @@ public class WolfSSLTrustX509Test {
pass("\t\t\t... passed");
}
@Test
public void testCheckServerTrustedWithChain()
throws NoSuchProviderException, NoSuchAlgorithmException,
KeyStoreException, FileNotFoundException, IOException,
CertificateException {
TrustManager[] tm;
X509TrustManager x509tm;
Certificate cert = null;
X509Certificate[] certArray = null;
FileInputStream fis = null;
BufferedInputStream bis = null;
CertificateFactory cf = CertificateFactory.getInstance("X.509");
System.out.print("\tcheckServerTrusted() chain");
String rsaServerCert =
"examples/certs/intermediate/server-int-cert.pem";
String rsaInt1Cert = "examples/certs/intermediate/ca-int-cert.pem";
String rsaInt2Cert = "examples/certs/intermediate/ca-int2-cert.pem";
String eccServerCert =
"examples/certs/intermediate/server-int-ecc-cert.pem";
String eccInt1Cert = "examples/certs/intermediate/ca-int-ecc-cert.pem";
String eccInt2Cert = "examples/certs/intermediate/ca-int2-ecc-cert.pem";
if (tf.isAndroid()) {
rsaServerCert = "/sdcard/" + rsaServerCert;
rsaInt1Cert = "/sdcard/" + rsaInt1Cert;
rsaInt2Cert = "/sdcard/" + rsaInt2Cert;
eccServerCert = "/sdcard/" + eccServerCert;
eccInt1Cert = "/sdcard/" + eccInt1Cert;
eccInt2Cert = "/sdcard/" + eccInt2Cert;
}
tm = tf.createTrustManager("SunX509", tf.caJKS, provider);
if (tm == null) {
error("\t... failed");
fail("failed to create trustmanager");
return;
}
x509tm = (X509TrustManager) tm[0];
/* ---------- RSA Based Chain ---------- */
/* build up X509Certificate[] chain */
certArray = new X509Certificate[3];
/* certArray[0]: server/peer cert */
fis = new FileInputStream(rsaServerCert);
bis = new BufferedInputStream(fis);
cert = cf.generateCertificate(bis);
certArray[0] = (X509Certificate)cert;
bis.close();
fis.close();
/* certArray[1]: intermediate CA 1 */
fis = new FileInputStream(rsaInt1Cert);
bis = new BufferedInputStream(fis);
cert = cf.generateCertificate(bis);
certArray[1] = (X509Certificate)cert;
bis.close();
fis.close();
/* certArray[2]: intermediate CA 2 */
fis = new FileInputStream(rsaInt2Cert);
bis = new BufferedInputStream(fis);
cert = cf.generateCertificate(bis);
certArray[2] = (X509Certificate)cert;
bis.close();
fis.close();
/* verify chain, root (certs/ca-cert.pem) should be in caJKS */
try {
x509tm.checkServerTrusted(certArray, "RSA");
} catch (CertificateException e) {
error("\t... failed");
fail("Failed verify of RSA chain with intermediates");
}
/* ---------- ECC Based Chain ---------- */
/* build up X509Certificate[] chain */
certArray = new X509Certificate[3];
/* certArray[0]: server/peer cert */
fis = new FileInputStream(eccServerCert);
bis = new BufferedInputStream(fis);
cert = cf.generateCertificate(bis);
certArray[0] = (X509Certificate)cert;
bis.close();
fis.close();
/* certArray[1]: intermediate CA 1 */
fis = new FileInputStream(eccInt1Cert);
bis = new BufferedInputStream(fis);
cert = cf.generateCertificate(bis);
certArray[1] = (X509Certificate)cert;
bis.close();
fis.close();
/* certArray[2]: intermediate CA 2 */
fis = new FileInputStream(eccInt2Cert);
bis = new BufferedInputStream(fis);
cert = cf.generateCertificate(bis);
certArray[2] = (X509Certificate)cert;
bis.close();
fis.close();
/* verify chain, root (certs/ca-ecc-cert.pem) should be in caJKS */
try {
x509tm.checkServerTrusted(certArray, "ECC");
} catch (CertificateException e) {
error("\t... failed");
fail("Failed verify of ECC chain with intermediates");
}
pass("\t... passed");
}
@Test
public void testCheckServerTrustedWithBadChainCert()
throws NoSuchProviderException, NoSuchAlgorithmException,
KeyStoreException, FileNotFoundException, IOException,
CertificateException {
TrustManager[] tm;
X509TrustManager x509tm;
Certificate cert = null;
X509Certificate[] certArray = null;
FileInputStream fis = null;
BufferedInputStream bis = null;
CertificateFactory cf = CertificateFactory.getInstance("X.509");
System.out.print("\tcheckServerTrusted() bad int");
String rsaServerCert = "examples/certs/intermediate/server-int-cert.pem";
/* wrong/bad CA as intermediate, should not verify. Using int CA
* from ECC chain but correct one is from RSA chain. */
String rsaInt1CertWrong =
"examples/certs/intermediate/ca-int2-ecc-cert.pem";
String rsaInt2Cert = "examples/certs/intermediate/ca-int2-cert.pem";
String eccServerCert =
"examples/certs/intermediate/server-int-ecc-cert.pem";
/* wrong/bad CA as intermediate, should not verify. Using int CA
* from RSA chain but correct one is from ECC chain. */
String eccInt1CertWrong =
"examples/certs/intermediate/ca-int-cert.pem";
String eccInt2Cert = "examples/certs/intermediate/ca-int2-ecc-cert.pem";
if (tf.isAndroid()) {
rsaServerCert = "/sdcard/" + rsaServerCert;
rsaInt1CertWrong = "/sdcard/" + rsaInt1CertWrong;
rsaInt2Cert = "/sdcard/" + rsaInt2Cert;
eccServerCert = "/sdcard/" + eccServerCert;
eccInt1CertWrong = "/sdcard/" + eccInt1CertWrong;
eccInt2Cert = "/sdcard/" + eccInt2Cert;
}
tm = tf.createTrustManager("SunX509", tf.caJKS, provider);
if (tm == null) {
error("\t... failed");
fail("failed to create trustmanager");
return;
}
x509tm = (X509TrustManager) tm[0];
/* ---------- RSA Based Chain ---------- */
/* build up X509Certificate[] chain */
certArray = new X509Certificate[3];
/* certArray[0]: server/peer cert */
fis = new FileInputStream(rsaServerCert);
bis = new BufferedInputStream(fis);
cert = cf.generateCertificate(bis);
certArray[0] = (X509Certificate)cert;
bis.close();
fis.close();
/* certArray[1]: intermediate CA 1 (wrong one, should cause error) */
fis = new FileInputStream(rsaInt1CertWrong);
bis = new BufferedInputStream(fis);
cert = cf.generateCertificate(bis);
certArray[1] = (X509Certificate)cert;
bis.close();
fis.close();
/* certArray[2]: intermediate CA 2 */
fis = new FileInputStream(rsaInt2Cert);
bis = new BufferedInputStream(fis);
cert = cf.generateCertificate(bis);
certArray[2] = (X509Certificate)cert;
bis.close();
fis.close();
/* verify chain, root (certs/ca-cert.pem) should be in caJKS */
try {
x509tm.checkServerTrusted(certArray, "RSA");
error("\t... failed");
fail("Verified RSA chain with bad CA, but shouldn't have");
} catch (CertificateException e) {
/* expected, should fail with wrong intermediate chain CA */
}
/* ---------- ECC Based Chain ---------- */
/* build up X509Certificate[] chain */
certArray = new X509Certificate[3];
/* certArray[0]: server/peer cert */
fis = new FileInputStream(eccServerCert);
bis = new BufferedInputStream(fis);
cert = cf.generateCertificate(bis);
certArray[0] = (X509Certificate)cert;
bis.close();
fis.close();
/* certArray[1]: intermediate CA 1 (wrong one, should cause error) */
fis = new FileInputStream(eccInt1CertWrong);
bis = new BufferedInputStream(fis);
cert = cf.generateCertificate(bis);
certArray[1] = (X509Certificate)cert;
bis.close();
fis.close();
/* certArray[2]: intermediate CA 2 */
fis = new FileInputStream(eccInt2Cert);
bis = new BufferedInputStream(fis);
cert = cf.generateCertificate(bis);
certArray[2] = (X509Certificate)cert;
bis.close();
fis.close();
/* verify chain, root (certs/ca-ecc-cert.pem) should be in caJKS */
try {
x509tm.checkServerTrusted(certArray, "ECC");
error("\t... failed");
fail("Verified RSA chain with bad CA, but shouldn't have");
} catch (CertificateException e) {
/* expected, should fail with wrong intermediate chain CA */
}
pass("\t... passed");
}
@Test
public void testCheckServerTrustedWithWrongChain()
throws NoSuchProviderException, NoSuchAlgorithmException,
KeyStoreException, FileNotFoundException, IOException,
CertificateException {
TrustManager[] tm;
X509TrustManager x509tm;
Certificate cert = null;
X509Certificate[] certArray = null;
FileInputStream fis = null;
BufferedInputStream bis = null;
CertificateFactory cf = CertificateFactory.getInstance("X.509");
System.out.print("\tcheckServerTrusted() bad chain");
/* server/peer cert is ECC, but is using RSA example chain. Should
* not verify correctly */
String rsaServerCert =
"examples/certs/intermediate/server-int-ecc-cert.pem";
String rsaInt1Cert = "examples/certs/intermediate/ca-int-cert.pem";
String rsaInt2Cert = "examples/certs/intermediate/ca-int2-cert.pem";
/* server/peer cert is RSA, but is using ECC example chain. Should
* not verify correctly */
String eccServerCert =
"examples/certs/intermediate/server-int-cert.pem";
String eccInt1Cert = "examples/certs/intermediate/ca-int-ecc-cert.pem";
String eccInt2Cert = "examples/certs/intermediate/ca-int2-ecc-cert.pem";
if (tf.isAndroid()) {
rsaServerCert = "/sdcard/" + rsaServerCert;
rsaInt1Cert = "/sdcard/" + rsaInt1Cert;
rsaInt2Cert = "/sdcard/" + rsaInt2Cert;
eccServerCert = "/sdcard/" + eccServerCert;
eccInt1Cert = "/sdcard/" + eccInt1Cert;
eccInt2Cert = "/sdcard/" + eccInt2Cert;
}
tm = tf.createTrustManager("SunX509", tf.caJKS, provider);
if (tm == null) {
error("\t... failed");
fail("failed to create trustmanager");
return;
}
x509tm = (X509TrustManager) tm[0];
/* ---------- ECC Peer Cert, RSA chain ---------- */
/* build up X509Certificate[] chain */
certArray = new X509Certificate[3];
/* certArray[0]: server/peer cert */
fis = new FileInputStream(rsaServerCert);
bis = new BufferedInputStream(fis);
cert = cf.generateCertificate(bis);
certArray[0] = (X509Certificate)cert;
bis.close();
fis.close();
/* certArray[1]: intermediate CA 1 (wrong one, should cause error) */
fis = new FileInputStream(rsaInt1Cert);
bis = new BufferedInputStream(fis);
cert = cf.generateCertificate(bis);
certArray[1] = (X509Certificate)cert;
bis.close();
fis.close();
/* certArray[2]: intermediate CA 2 */
fis = new FileInputStream(rsaInt2Cert);
bis = new BufferedInputStream(fis);
cert = cf.generateCertificate(bis);
certArray[2] = (X509Certificate)cert;
bis.close();
fis.close();
/* verify chain, root (certs/ca-ecc-cert.pem) should be in caJKS */
try {
x509tm.checkServerTrusted(certArray, "ECC");
error("\t... failed");
fail("Verified cert with wrong chain, should not happen");
} catch (CertificateException e) {
/* expected, should fail with wrong intermediate chain CA */
}
/* ---------- RSA Peer Cert, ECC chain ---------- */
/* build up X509Certificate[] chain */
certArray = new X509Certificate[3];
/* certArray[0]: server/peer cert */
fis = new FileInputStream(eccServerCert);
bis = new BufferedInputStream(fis);
cert = cf.generateCertificate(bis);
certArray[0] = (X509Certificate)cert;
bis.close();
fis.close();
/* certArray[1]: intermediate CA 1 (wrong one, should cause error) */
fis = new FileInputStream(eccInt1Cert);
bis = new BufferedInputStream(fis);
cert = cf.generateCertificate(bis);
certArray[1] = (X509Certificate)cert;
bis.close();
fis.close();
/* certArray[2]: intermediate CA 2 */
fis = new FileInputStream(eccInt2Cert);
bis = new BufferedInputStream(fis);
cert = cf.generateCertificate(bis);
certArray[2] = (X509Certificate)cert;
bis.close();
fis.close();
/* verify chain, root (certs/ca-cert.pem) should be in caJKS */
try {
x509tm.checkServerTrusted(certArray, "RSA");
error("\t... failed");
fail("Verified cert with wrong chain, should not happen");
} catch (CertificateException e) {
/* expected, should fail with wrong intermediate chain CA */
}
pass("\t... passed");
}
@Test
public void testCheckServerTrustedMissingChain()
throws NoSuchProviderException, NoSuchAlgorithmException,
KeyStoreException, FileNotFoundException, IOException,
CertificateException {
TrustManager[] tm;
X509TrustManager x509tm;
Certificate cert = null;
X509Certificate[] certArray = null;
FileInputStream fis = null;
BufferedInputStream bis = null;
CertificateFactory cf = CertificateFactory.getInstance("X.509");
System.out.print("\tcheckServerTrusted() miss chain");
/* RSA chain, missing intermediate CA 1 */
String rsaServerCert = "examples/certs/intermediate/server-int-cert.pem";
String rsaInt2Cert = "examples/certs/intermediate/ca-int2-cert.pem";
/* ECC chain, missing intermediate CA 1 */
String eccServerCert =
"examples/certs/intermediate/server-int-ecc-cert.pem";
String eccInt2Cert = "examples/certs/intermediate/ca-int2-ecc-cert.pem";
if (tf.isAndroid()) {
rsaServerCert = "/sdcard/" + rsaServerCert;
rsaInt2Cert = "/sdcard/" + rsaInt2Cert;
eccServerCert = "/sdcard/" + eccServerCert;
eccInt2Cert = "/sdcard/" + eccInt2Cert;
}
tm = tf.createTrustManager("SunX509", tf.caJKS, provider);
if (tm == null) {
error("\t... failed");
fail("failed to create trustmanager");
return;
}
x509tm = (X509TrustManager) tm[0];
/* ---------- RSA Cert Chain ---------- */
/* build up X509Certificate[] chain, missing intermediate 1 */
certArray = new X509Certificate[2];
/* certArray[0]: server/peer cert */
fis = new FileInputStream(rsaServerCert);
bis = new BufferedInputStream(fis);
cert = cf.generateCertificate(bis);
certArray[0] = (X509Certificate)cert;
bis.close();
fis.close();
/* certArray[1]: intermediate CA 2 */
fis = new FileInputStream(rsaInt2Cert);
bis = new BufferedInputStream(fis);
cert = cf.generateCertificate(bis);
certArray[1] = (X509Certificate)cert;
bis.close();
fis.close();
/* try to verify chain, root (certs/ca-cert.pem) should be in caJKS */
try {
x509tm.checkServerTrusted(certArray, "RSA");
error("\t... failed");
fail("Did not fail verify like expected when missing intermediate");
} catch (CertificateException e) {
/* Expected, missing intermediate 1 from chain */
}
/* ---------- ECC Cert Chain ---------- */
/* build up X509Certificate[] chain, missing intermediate 1 */
certArray = new X509Certificate[2];
/* certArray[0]: server/peer cert */
fis = new FileInputStream(eccServerCert);
bis = new BufferedInputStream(fis);
cert = cf.generateCertificate(bis);
certArray[0] = (X509Certificate)cert;
bis.close();
fis.close();
/* certArray[1]: intermediate CA 2 */
fis = new FileInputStream(eccInt2Cert);
bis = new BufferedInputStream(fis);
cert = cf.generateCertificate(bis);
certArray[1] = (X509Certificate)cert;
bis.close();
fis.close();
/* try to verify chain, root (certs/ca-cert.pem) should be in caJKS */
try {
x509tm.checkServerTrusted(certArray, "ECC");
error("\t... failed");
fail("Did not fail verify like expected when missing intermediate");
} catch (CertificateException e) {
/* Expected, missing intermediate 1 from chain */
}
pass("\t... passed");
}
@Test
public void testCheckServerTrustedWithChainWrongOrder()
throws NoSuchProviderException, NoSuchAlgorithmException,
KeyStoreException, FileNotFoundException, IOException,
CertificateException {
TrustManager[] tm;
X509TrustManager x509tm;
Certificate cert = null;
X509Certificate[] certArray = null;
FileInputStream fis = null;
BufferedInputStream bis = null;
CertificateFactory cf = CertificateFactory.getInstance("X.509");
System.out.print("\tcheckServerTrusted() ooo chain");
/* RSA chain, out of order intermediate CAs */
String rsaServerCert = "examples/certs/intermediate/server-int-cert.pem";
String rsaInt1Cert = "examples/certs/intermediate/ca-int-cert.pem";
String rsaInt2Cert = "examples/certs/intermediate/ca-int2-cert.pem";
/* ECC chain, out of order intermediate CAs */
String eccServerCert = "examples/certs/intermediate/server-int-ecc-cert.pem";
String eccInt1Cert = "examples/certs/intermediate/ca-int-ecc-cert.pem";
String eccInt2Cert = "examples/certs/intermediate/ca-int2-ecc-cert.pem";
if (tf.isAndroid()) {
rsaServerCert = "/sdcard/" + rsaServerCert;
rsaInt1Cert = "/sdcard/" + rsaInt1Cert;
rsaInt2Cert = "/sdcard/" + rsaInt2Cert;
eccServerCert = "/sdcard/" + eccServerCert;
eccInt1Cert = "/sdcard/" + eccInt1Cert;
eccInt2Cert = "/sdcard/" + eccInt2Cert;
}
tm = tf.createTrustManager("SunX509", tf.caJKS, provider);
if (tm == null) {
error("\t... failed");
fail("failed to create trustmanager");
return;
}
x509tm = (X509TrustManager) tm[0];
/* ---------- RSA Cert Chain ---------- */
/* build up X509Certificate[] chain, out of order intermediates */
certArray = new X509Certificate[3];
/* certArray[0]: server/peer cert */
fis = new FileInputStream(rsaServerCert);
bis = new BufferedInputStream(fis);
cert = cf.generateCertificate(bis);
certArray[0] = (X509Certificate)cert;
bis.close();
fis.close();
/* certArray[1]: intermediate CA 2 */
fis = new FileInputStream(rsaInt2Cert);
bis = new BufferedInputStream(fis);
cert = cf.generateCertificate(bis);
certArray[1] = (X509Certificate)cert;
bis.close();
fis.close();
/* certArray[2]: intermediate CA 1 */
fis = new FileInputStream(rsaInt1Cert);
bis = new BufferedInputStream(fis);
cert = cf.generateCertificate(bis);
certArray[2] = (X509Certificate)cert;
bis.close();
fis.close();
/* verify chain, root (certs/ca-cert.pem) should be in caJKS */
try {
x509tm.checkServerTrusted(certArray, "RSA");
} catch (CertificateException e) {
error("\t... failed");
fail("Failed verify of RSA chain with intermediates");
}
/* ---------- ECC Cert Chain ---------- */
/* build up X509Certificate[] chain, out of order intermediates */
certArray = new X509Certificate[3];
/* certArray[0]: server/peer cert */
fis = new FileInputStream(eccServerCert);
bis = new BufferedInputStream(fis);
cert = cf.generateCertificate(bis);
certArray[0] = (X509Certificate)cert;
bis.close();
fis.close();
/* certArray[1]: intermediate CA 2 */
fis = new FileInputStream(eccInt2Cert);
bis = new BufferedInputStream(fis);
cert = cf.generateCertificate(bis);
certArray[1] = (X509Certificate)cert;
bis.close();
fis.close();
/* certArray[2]: intermediate CA 1 */
fis = new FileInputStream(eccInt1Cert);
bis = new BufferedInputStream(fis);
cert = cf.generateCertificate(bis);
certArray[2] = (X509Certificate)cert;
bis.close();
fis.close();
/* verify chain, root (certs/ca-ecc-cert.pem) should be in caJKS */
try {
x509tm.checkServerTrusted(certArray, "ECC");
} catch (CertificateException e) {
error("\t... failed");
fail("Failed verify of ECC chain with intermediates");
}
pass("\t... passed");
}
@Test
public void testCheckServerTrustedWithChainReturnsChain()
throws NoSuchProviderException, NoSuchAlgorithmException,
KeyStoreException, FileNotFoundException, IOException,
CertificateException {
TrustManager[] tm;
X509TrustManager x509tm;
WolfSSLTrustX509 wolfX509tm;
Certificate cert = null;
X509Certificate[] certArray = null;
FileInputStream fis = null;
BufferedInputStream bis = null;
CertificateFactory cf = CertificateFactory.getInstance("X.509");
List<X509Certificate> retChain = null;
System.out.print("\tcheckServerTrusted() ret chain");
/* RSA chain */
String rsaServerCert =
"examples/certs/intermediate/server-int-cert.pem";
String rsaInt1Cert = "examples/certs/intermediate/ca-int-cert.pem";
String rsaInt2Cert = "examples/certs/intermediate/ca-int2-cert.pem";
/* ECC chain */
String eccServerCert =
"examples/certs/intermediate/server-int-ecc-cert.pem";
String eccInt1Cert = "examples/certs/intermediate/ca-int-ecc-cert.pem";
String eccInt2Cert = "examples/certs/intermediate/ca-int2-ecc-cert.pem";
if (tf.isAndroid()) {
rsaServerCert = "/sdcard/" + rsaServerCert;
rsaInt1Cert = "/sdcard/" + rsaInt1Cert;
rsaInt2Cert = "/sdcard/" + rsaInt2Cert;
eccServerCert = "/sdcard/" + eccServerCert;
eccInt1Cert = "/sdcard/" + eccInt1Cert;
eccInt2Cert = "/sdcard/" + eccInt2Cert;
}
tm = tf.createTrustManager("SunX509", tf.caJKS, provider);
if (tm == null) {
error("\t... failed");
fail("failed to create trustmanager");
return;
}
x509tm = (X509TrustManager) tm[0];
/* checkServerTrusted() that returns List<X509Certificate> is non
* standard, must call directly from WolfSSLTrustX509. Called by
* okhttp on Android. */
wolfX509tm = (WolfSSLTrustX509)x509tm;
/* ---------- RSA Cert Chain ---------- */
/* build up X509Certificate[] chain, out of order intermediates */
certArray = new X509Certificate[3];
/* certArray[0]: server/peer cert */
fis = new FileInputStream(rsaServerCert);
bis = new BufferedInputStream(fis);
cert = cf.generateCertificate(bis);
certArray[0] = (X509Certificate)cert;
bis.close();
fis.close();
/* certArray[1]: intermediate CA 1 */
fis = new FileInputStream(rsaInt1Cert);
bis = new BufferedInputStream(fis);
cert = cf.generateCertificate(bis);
certArray[1] = (X509Certificate)cert;
bis.close();
fis.close();
/* certArray[2]: intermediate CA 2 */
fis = new FileInputStream(rsaInt2Cert);
bis = new BufferedInputStream(fis);
cert = cf.generateCertificate(bis);
certArray[2] = (X509Certificate)cert;
bis.close();
fis.close();
/* verify chain, root (certs/ca-cert.pem) should be in caJKS */
try {
/* hostname cert pinning not supported yet by wolfJSSE */
retChain = wolfX509tm.checkServerTrusted(certArray,
"RSA", "localhost");
} catch (CertificateException e) {
error("\t... failed");
fail("Failed verify of RSA chain with intermediates");
}
if (retChain == null) {
error("\t... failed");
fail("checkServerTrusted() did not return expected List of certs");
}
/* cert chain returned should include peer, ints, and root */
if (retChain.size() != 4) {
error("\t... failed");
fail("checkServerTrusted() didn't return expected number of certs");
}
/* ---------- ECC Cert Chain ---------- */
/* build up X509Certificate[] chain, out of order intermediates */
certArray = new X509Certificate[3];
/* certArray[0]: server/peer cert */
fis = new FileInputStream(eccServerCert);
bis = new BufferedInputStream(fis);
cert = cf.generateCertificate(bis);
certArray[0] = (X509Certificate)cert;
bis.close();
fis.close();
/* certArray[1]: intermediate CA 1 */
fis = new FileInputStream(eccInt1Cert);
bis = new BufferedInputStream(fis);
cert = cf.generateCertificate(bis);
certArray[1] = (X509Certificate)cert;
bis.close();
fis.close();
/* certArray[2]: intermediate CA 2 */
fis = new FileInputStream(eccInt2Cert);
bis = new BufferedInputStream(fis);
cert = cf.generateCertificate(bis);
certArray[2] = (X509Certificate)cert;
bis.close();
fis.close();
/* verify chain, root (certs/ca-ecc-cert.pem) should be in caJKS */
try {
/* hostname cert pinning not supported yet by wolfJSSE */
retChain = wolfX509tm.checkServerTrusted(certArray,
"ECC", "localhost");
} catch (CertificateException e) {
error("\t... failed");
fail("Failed verify of ECC chain with intermediates");
}
if (retChain == null) {
error("\t... failed");
fail("checkServerTrusted() did not return expected List of certs");
}
/* cert chain returned should include peer, ints, and root */
if (retChain.size() != 4) {
error("\t... failed");
fail("checkServerTrusted() didn't return expected number of certs");
}
pass("\t... passed");
}
private void pass(String msg) {
WolfSSLTestFactory.pass(msg);