diff --git a/.gitignore b/.gitignore index 0f7b6e2..9e43ca8 100644 --- a/.gitignore +++ b/.gitignore @@ -25,6 +25,7 @@ IDE/WIN/DLL Debug IDE/WIN/DLL Debug FIPS IDE/WIN/DLL Release IDE/WIN/DLL Release FIPS +examples/certs/generated # RPM package files rpm/spec diff --git a/IDE/WIN/wolfssljni.vcxproj b/IDE/WIN/wolfssljni.vcxproj index 8d91e01..68285ef 100644 --- a/IDE/WIN/wolfssljni.vcxproj +++ b/IDE/WIN/wolfssljni.vcxproj @@ -43,6 +43,7 @@ + @@ -55,6 +56,7 @@ + diff --git a/IDE/WIN/wolfssljni.vcxproj.filters b/IDE/WIN/wolfssljni.vcxproj.filters index e911186..c330006 100644 --- a/IDE/WIN/wolfssljni.vcxproj.filters +++ b/IDE/WIN/wolfssljni.vcxproj.filters @@ -42,6 +42,9 @@ Source Files + + Source Files + @@ -77,5 +80,8 @@ Header Files + + Header Files + \ No newline at end of file diff --git a/examples/README.md b/examples/README.md index cf48f3c..6ab988d 100644 --- a/examples/README.md +++ b/examples/README.md @@ -41,6 +41,28 @@ argument: $ ./examples/server.sh --help ``` +## X509v3 Certificate Generation Example + +An example is included which will generate self-signed and CA-signed +X.509v3 certificates using the wolfSSL JNI library `WolfSSLCertificate` +class. + +**X509v3CertificateGeneration.java** - Certificate generation example + +This example is compiled when the `ant examples` target is executed, and can +be run afterwards with the provided bash script: + +``` +$ cd +$ ./examples/X509v3CertificateGeneration.sh +``` + +This will write out generated certificates to the following directory: + +``` +examples/certs/generated/ +``` + ## Support Please contact the wolfSSL support team at support@wolfssl.com with any diff --git a/examples/X509v3CertificateGeneration.java b/examples/X509v3CertificateGeneration.java new file mode 100644 index 0000000..d365c66 --- /dev/null +++ b/examples/X509v3CertificateGeneration.java @@ -0,0 +1,690 @@ +/* X509v3CertificateGeneration.java + * + * Copyright (C) 2006-2023 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + +import java.io.*; +import java.net.*; +import java.nio.*; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.time.Instant; +import java.time.Duration; +import java.util.Date; +import java.math.BigInteger; + +import java.io.FileInputStream; +import java.security.KeyFactory; +import java.security.KeyPairGenerator; +import java.security.KeyPair; +import java.security.PublicKey; +import java.security.PrivateKey; +import java.security.spec.PKCS8EncodedKeySpec; +import java.security.spec.InvalidKeySpecException; +import java.security.interfaces.RSAPrivateKey; +import java.security.NoSuchAlgorithmException; +import java.security.cert.CertificateFactory; +import java.security.cert.X509Certificate; +import java.security.cert.CertificateException; + +import com.wolfssl.WolfSSL; +import com.wolfssl.WolfSSLCertificate; +import com.wolfssl.WolfSSLX509Name; +import com.wolfssl.WolfSSLException; +import com.wolfssl.WolfSSLJNIException; + +/** + * Example application that demonstrates X509v3 certifiate generation + * including various combinations: + * + * Self-signed certificate using files as input for certs/keys + * Self-signed certificate using arrays as input for certs/keys + * Self-signed certificate using generated certs and keys + * + * CA-signed certificate using files as input for certs/keys + * CA-signed certificate using arrays as input for certs/keys + * CA-signed certificate using generated certs and keys + * + * Each sub-example is contained in a separate method. + * + * When run, generated certificates are written out to PEM and DER files, + * with location specified by variables at the top of this class. + */ +public class X509v3CertificateGeneration { + + private static String CERT_DIR = "../certs/"; + private static String GEN_DIR = CERT_DIR + "generated/"; + private static String CERT_DIR_FROM_ROOT = "./exammples/certs/generated/"; + + /* Existing certs/keys used for cert gen example with files */ + private static String caCertPem = CERT_DIR + "ca-cert.pem"; + private static String caKeyDer = CERT_DIR + "ca-key.der"; + private static String caKeyPkcs8Der = CERT_DIR + "ca-keyPkcs8.der"; + private static String clientKeyDer = CERT_DIR + "client-key.der"; + private static String clientKeyPubDer = CERT_DIR + "client-keyPub.der"; + + /* Generated self-signed certificate locations. + * Generated self-signed certs have isCA Basic Constraint set true + * in these examples. */ + private static String selfSignedUsingFilesDer = + GEN_DIR + "self-signed-using-files.der"; + private static String selfSignedUsingFilesPem = + GEN_DIR + "self-signed-using-files.pem"; + private static String selfSignedUsingArraysDer = + GEN_DIR + "self-signed-using-arrays.der"; + private static String selfSignedUsingArraysPem = + GEN_DIR + "self-signed-using-arrays.pem"; + private static String selfSignedUsingGeneratedKeysDer = + GEN_DIR + "self-signed-generated-keys.der"; + private static String selfSignedUsingGeneratedKeysPem = + GEN_DIR + "self-signed-generated-keys.pem"; + + /* Generated CA-signed certificate locations. + * Generated CA-signed certs have isCA Basic Constraint set false + * in these examples. */ + private static String caSignedUsingFilesDer = + GEN_DIR + "ca-signed-using-files.der"; + private static String caSignedUsingFilesPem = + GEN_DIR + "ca-signed-using-files.pem"; + private static String caSignedUsingArraysDer = + GEN_DIR + "ca-signed-using-arrays.der"; + private static String caSignedUsingArraysPem = + GEN_DIR + "ca-signed-using-arrays.pem"; + private static String caSignedUsingGeneratedKeysDer = + GEN_DIR + "ca-signed-generated-keys.der"; + private static String caSignedUsingGeneratedKeysPem = + GEN_DIR + "ca-signed-generated-keys.pem"; + + /* Example Extension values */ + private static String test_KEY_USAGE = + "digitalSignature,keyEncipherment,dataEncipherment"; + private static String test_EXT_KEY_USAGE = + "clientAuth,serverAuth"; + private static String test_ALT_NAME = + "alt.example.com"; + + private void writeFile(String path, byte[] bytes) + throws IOException { + + File genDir = new File(GEN_DIR); + if (!genDir.exists()) { + genDir.mkdir(); + } + Files.write(new File(path).toPath(), bytes); + } + + private WolfSSLX509Name generateTestSubjectName() + throws WolfSSLException { + + WolfSSLX509Name subjectName = new WolfSSLX509Name(); + subjectName.setCountryName("US"); + subjectName.setStateOrProvinceName("Montana"); + subjectName.setStreetAddress("12345 Test Address"); + subjectName.setLocalityName("Bozeman"); + subjectName.setSurname("Test Surname"); + subjectName.setCommonName("example.com"); + subjectName.setEmailAddress("support@example.com"); + subjectName.setOrganizationName("wolfSSL Inc."); + subjectName.setOrganizationalUnitName("Test and Development"); + subjectName.setPostalCode("59715"); + subjectName.setUserId("TestUserID"); + + return subjectName; + } + + /** + * Generate example certificate using the following files as input + * to the certificate generation process: + * + * clientKeyPubDer - Existing client public key in DER format + * clientKeyDer - Existing client private key in DER format + * + * Generates and writes certificate out to the following paths in + * both PEM and DER format (see variable values above): + * selfSignedUsingFilesDer (DER format) + * selfSignedUsingFilesPem (PEM format) + * + * @throws WolfSSLException if error occurs during certificate generation + * process. + * @throws WolfSSLJNIException if native JNI error occurs + * @throws IOException on error writing to output file locations + */ + public void generateSelfSignedUsingFiles() + throws WolfSSLException, WolfSSLJNIException, IOException, + CertificateException { + + System.out.print("\nGenerating self-signed cert using files"); + + /* Create new certificate object */ + WolfSSLCertificate x509 = new WolfSSLCertificate(); + + /* Set notBefore/notAfter validity dates */ + Instant now = Instant.now(); + final Date notBefore = Date.from(now); + final Date notAfter = Date.from(now.plus(Duration.ofDays(365))); + x509.setNotBefore(notBefore); + x509.setNotAfter(notAfter); + + /* Set serial number */ + x509.setSerialNumber(BigInteger.valueOf(12345)); + + /* Set Subject Name */ + WolfSSLX509Name subjectName = generateTestSubjectName(); + x509.setSubjectName(subjectName); + + /* Not setting Issuer, since generating self-signed cert */ + + /* Set Public Key from existing public key DER file */ + x509.setPublicKey(clientKeyPubDer, WolfSSL.RSAk, + WolfSSL.SSL_FILETYPE_ASN1); + + /* Add Extensions */ + x509.addExtension(WolfSSL.NID_key_usage, test_KEY_USAGE, false); + x509.addExtension(WolfSSL.NID_ext_key_usage, test_EXT_KEY_USAGE, false); + x509.addExtension(WolfSSL.NID_subject_alt_name, test_ALT_NAME, false); + x509.addExtension(WolfSSL.NID_basic_constraints, true, true); + + /* Sign certificate, self-signed using existing client key DER */ + x509.signCert(clientKeyDer, WolfSSL.RSAk, + WolfSSL.SSL_FILETYPE_ASN1, "SHA256"); + + /* Output to DER and PEM files */ + byte[] derCert = x509.getDer(); + byte[] pemCert = x509.getPem(); + + /* Write out generated certs to files */ + writeFile(selfSignedUsingFilesDer, derCert); + writeFile(selfSignedUsingFilesPem, pemCert); + + /* Test converting to X509Certificate */ + X509Certificate tmpX509 = x509.getX509Certificate(); + + System.out.println("... "); + System.out.println(" " + CERT_DIR_FROM_ROOT + + Paths.get(selfSignedUsingFilesDer).getFileName()); + System.out.println(" " + CERT_DIR_FROM_ROOT + + Paths.get(selfSignedUsingFilesPem).getFileName()); + + /* Free native memory */ + subjectName.free(); + x509.free(); + } + + /** + * Generate example certificate using the following files in array format + * as input to the certificate generation process: + * + * clientKeyPubDer - Existing client public key in DER format + * clientKeyDer - Existing client private key in DER format + * + * Generates and writes certificate out to the following paths in + * both PEM and DER format (see variable values above): + * selfSignedUsingArraysDer (DER format) + * selfSignedUsingArraysPem (PEM format) + * + * @throws WolfSSLException if error occurs during certificate generation + * process. + * @throws WolfSSLJNIException if native JNI error occurs + * @throws IOException on error writing to output file locations + */ + public void generateSelfSignedUsingArrays() + throws WolfSSLException, WolfSSLJNIException, IOException, + CertificateException { + + System.out.print("\nGenerating self-signed cert using arrays"); + + /* Create new certificate object */ + WolfSSLCertificate x509 = new WolfSSLCertificate(); + + /* Set notBefore/notAfter validity dates */ + Instant now = Instant.now(); + final Date notBefore = Date.from(now); + final Date notAfter = Date.from(now.plus(Duration.ofDays(365))); + x509.setNotBefore(notBefore); + x509.setNotAfter(notAfter); + + /* Set serial number */ + x509.setSerialNumber(BigInteger.valueOf(12345)); + + /* Set Subject Name */ + WolfSSLX509Name subjectName = generateTestSubjectName(); + x509.setSubjectName(subjectName); + + /* Not setting Issuer, since generating self-signed cert */ + + /* Set Public Key from existing public key DER file */ + byte[] pubKey = Files.readAllBytes(Paths.get(clientKeyPubDer)); + x509.setPublicKey(pubKey, WolfSSL.RSAk, WolfSSL.SSL_FILETYPE_ASN1); + + /* Add Extensions */ + x509.addExtension(WolfSSL.NID_key_usage, test_KEY_USAGE, false); + x509.addExtension(WolfSSL.NID_ext_key_usage, test_EXT_KEY_USAGE, false); + x509.addExtension(WolfSSL.NID_subject_alt_name, test_ALT_NAME, false); + x509.addExtension(WolfSSL.NID_basic_constraints, true, true); + + /* Sign certificate, self-signed using existing client key DER */ + byte[] privKey = Files.readAllBytes(Paths.get(clientKeyDer)); + x509.signCert(privKey, WolfSSL.RSAk, + WolfSSL.SSL_FILETYPE_ASN1, "SHA256"); + + /* Output to DER and PEM files */ + byte[] derCert = x509.getDer(); + byte[] pemCert = x509.getPem(); + + /* Write out generated certs to files */ + writeFile(selfSignedUsingArraysDer, derCert); + writeFile(selfSignedUsingArraysPem, pemCert); + + /* Test converting to X509Certificate */ + X509Certificate tmpX509 = x509.getX509Certificate(); + + System.out.println("... "); + System.out.println(" " + CERT_DIR_FROM_ROOT + + Paths.get(selfSignedUsingArraysDer).getFileName()); + System.out.println(" " + CERT_DIR_FROM_ROOT + + Paths.get(selfSignedUsingArraysPem).getFileName()); + + /* Free native memory */ + subjectName.free(); + x509.free(); + } + + /** + * Generate example certificate using generated keys for the certificate + * public and private key, to be used in the certificate generation + * process. + * + * Generates and writes certificate out to the following paths in + * both PEM and DER format (see variable values above): + * selfSignedUsingGeneratedKeysDer (DER format) + * selfSignedUsingGeneratedKeysPem (PEM format) + * + * @throws WolfSSLException if error occurs during certificate generation + * process. + * @throws WolfSSLJNIException if native JNI error occurs + * @throws IOException on error writing to output file locations + */ + public void generateSelfSignedUsingGeneratedKeys() + throws WolfSSLException, WolfSSLJNIException, IOException, + CertificateException, NoSuchAlgorithmException { + + System.out.print("\nGenerating self-signed cert with generated keys"); + + /* Create new certificate object */ + WolfSSLCertificate x509 = new WolfSSLCertificate(); + + /* Set notBefore/notAfter validity dates */ + Instant now = Instant.now(); + final Date notBefore = Date.from(now); + final Date notAfter = Date.from(now.plus(Duration.ofDays(365))); + x509.setNotBefore(notBefore); + x509.setNotAfter(notAfter); + + /* Set serial number */ + x509.setSerialNumber(BigInteger.valueOf(12345)); + + /* Set Subject Name */ + WolfSSLX509Name subjectName = generateTestSubjectName(); + x509.setSubjectName(subjectName); + + /* Not setting Issuer, since generating self-signed cert */ + + /* Set Public Key from generated java.security.PublicKey */ + KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA"); + kpg.initialize(2048); + KeyPair keyPair = kpg.generateKeyPair(); + PublicKey pubKey = keyPair.getPublic(); + x509.setPublicKey(pubKey); + + /* Add Extensions */ + x509.addExtension(WolfSSL.NID_key_usage, test_KEY_USAGE, false); + x509.addExtension(WolfSSL.NID_ext_key_usage, test_EXT_KEY_USAGE, false); + x509.addExtension(WolfSSL.NID_subject_alt_name, test_ALT_NAME, false); + x509.addExtension(WolfSSL.NID_basic_constraints, true, true); + + /* Sign certificate, self-signed with java.security.PrivateKey */ + PrivateKey privKey = keyPair.getPrivate(); + x509.signCert(privKey, "SHA256"); + + /* Output to DER and PEM files */ + byte[] derCert = x509.getDer(); + byte[] pemCert = x509.getPem(); + + /* Write out generated certs to files */ + writeFile(selfSignedUsingGeneratedKeysDer, derCert); + writeFile(selfSignedUsingGeneratedKeysPem, pemCert); + + /* Test converting to X509Certificate */ + X509Certificate tmpX509 = x509.getX509Certificate(); + + System.out.println("... "); + System.out.println(" " + CERT_DIR_FROM_ROOT + + Paths.get(selfSignedUsingGeneratedKeysDer).getFileName()); + System.out.println(" " + CERT_DIR_FROM_ROOT + + Paths.get(selfSignedUsingGeneratedKeysPem).getFileName()); + + /* Free native memory */ + subjectName.free(); + x509.free(); + } + + /** + * ----------------------------------------------------------------------- + * Below are examples of CA-signed certificate generation + * ----------------------------------------------------------------------- + */ + + /** + * Generate example CA-signed certificate using the following files as + * input to the certificate generation process: + * + * caCertPem - Existing CA certificate in PEM format + * clientKeyPubDer - Existing client public key in DER format + * clientKeyDer - Existing client private key in DER format + * + * Generates and writes certificate out to the following paths in + * both PEM and DER format (see variable values above): + * caSignedUsingFilesDer (DER format) + * caSignedUsingFilesPem (PEM format) + * + * @throws WolfSSLException if error occurs during certificate generation + * process. + * @throws WolfSSLJNIException if native JNI error occurs + * @throws IOException on error writing to output file locations + */ + public void generateCASignedUsingFiles() + throws WolfSSLException, WolfSSLJNIException, IOException, + CertificateException { + + System.out.print("\nGenerating CA-signed cert using files"); + + /* Create new certificate object */ + WolfSSLCertificate x509 = new WolfSSLCertificate(); + + /* Set notBefore/notAfter validity dates */ + Instant now = Instant.now(); + final Date notBefore = Date.from(now); + final Date notAfter = Date.from(now.plus(Duration.ofDays(365))); + x509.setNotBefore(notBefore); + x509.setNotAfter(notAfter); + + /* Set serial number */ + x509.setSerialNumber(BigInteger.valueOf(12345)); + + /* Set Subject Name */ + WolfSSLX509Name subjectName = generateTestSubjectName(); + x509.setSubjectName(subjectName); + + /* Set Issuer Name from existing cert file wrapped in + * WolfSSLCertificate object */ + WolfSSLCertificate issuer = new WolfSSLCertificate(caCertPem, + WolfSSL.SSL_FILETYPE_PEM); + x509.setIssuerName(issuer); + + /* Set Public Key from existing public key DER file */ + x509.setPublicKey(clientKeyPubDer, WolfSSL.RSAk, + WolfSSL.SSL_FILETYPE_ASN1); + + /* Add Extensions */ + x509.addExtension(WolfSSL.NID_key_usage, test_KEY_USAGE, false); + x509.addExtension(WolfSSL.NID_ext_key_usage, test_EXT_KEY_USAGE, false); + x509.addExtension(WolfSSL.NID_subject_alt_name, test_ALT_NAME, false); + x509.addExtension(WolfSSL.NID_basic_constraints, true, true); + + /* Sign certificate, CA-signed using existing CA key DER */ + x509.signCert(caKeyDer, WolfSSL.RSAk, + WolfSSL.SSL_FILETYPE_ASN1, "SHA256"); + + /* Output to DER and PEM files */ + byte[] derCert = x509.getDer(); + byte[] pemCert = x509.getPem(); + + /* Write out generated certs to files */ + writeFile(caSignedUsingFilesDer, derCert); + writeFile(caSignedUsingFilesPem, pemCert); + + /* Test converting to X509Certificate */ + X509Certificate tmpX509 = x509.getX509Certificate(); + + System.out.println("... "); + System.out.println(" " + CERT_DIR_FROM_ROOT + + Paths.get(caSignedUsingFilesDer).getFileName()); + System.out.println(" " + CERT_DIR_FROM_ROOT + + Paths.get(caSignedUsingFilesPem).getFileName()); + + /* Free native memory */ + subjectName.free(); + x509.free(); + } + + /** + * Generate example CA-signed certificate using the following files in + * array format as input to the certificate generation process: + * + * caCertPem - Existing CA certificate in PEM format + * clientKeyPubDer - Existing client public key in DER format + * clientKeyDer - Existing client private key in DER format + * + * Generates and writes certificate out to the following paths in + * both PEM and DER format (see variable values above): + * caSignedUsingArraysDer (DER format) + * caSignedUsingArraysPem (PEM format) + * + * @throws WolfSSLException if error occurs during certificate generation + * process. + * @throws WolfSSLJNIException if native JNI error occurs + * @throws IOException on error writing to output file locations + */ + public void generateCASignedUsingArrays() + throws WolfSSLException, WolfSSLJNIException, IOException, + CertificateException { + + System.out.print("\nGenerating CA-signed cert using arrays"); + + /* Create new certificate object */ + WolfSSLCertificate x509 = new WolfSSLCertificate(); + + /* Set notBefore/notAfter validity dates */ + Instant now = Instant.now(); + final Date notBefore = Date.from(now); + final Date notAfter = Date.from(now.plus(Duration.ofDays(365))); + x509.setNotBefore(notBefore); + x509.setNotAfter(notAfter); + + /* Set serial number */ + x509.setSerialNumber(BigInteger.valueOf(12345)); + + /* Set Subject Name */ + WolfSSLX509Name subjectName = generateTestSubjectName(); + x509.setSubjectName(subjectName); + + /* Set Issuer Name from existing cert file ready into a byte array and + * wrapped in WolfSSLCertificate object */ + WolfSSLCertificate issuer = new WolfSSLCertificate( + Files.readAllBytes(Paths.get(caCertPem)), + WolfSSL.SSL_FILETYPE_PEM); + x509.setIssuerName(issuer); + + /* Set Public Key from existing public key DER file */ + byte[] pubKey = Files.readAllBytes(Paths.get(clientKeyPubDer)); + x509.setPublicKey(pubKey, WolfSSL.RSAk, WolfSSL.SSL_FILETYPE_ASN1); + + /* Add Extensions */ + x509.addExtension(WolfSSL.NID_key_usage, test_KEY_USAGE, false); + x509.addExtension(WolfSSL.NID_ext_key_usage, test_EXT_KEY_USAGE, false); + x509.addExtension(WolfSSL.NID_subject_alt_name, test_ALT_NAME, false); + x509.addExtension(WolfSSL.NID_basic_constraints, true, true); + + /* Sign certificate, self-signed using existing client key DER */ + byte[] privKey = Files.readAllBytes(Paths.get(caKeyDer)); + x509.signCert(privKey, WolfSSL.RSAk, + WolfSSL.SSL_FILETYPE_ASN1, "SHA256"); + + /* Output to DER and PEM files */ + byte[] derCert = x509.getDer(); + byte[] pemCert = x509.getPem(); + + /* Write out generated certs to files */ + writeFile(caSignedUsingArraysDer, derCert); + writeFile(caSignedUsingArraysPem, pemCert); + + /* Test converting to X509Certificate */ + X509Certificate tmpX509 = x509.getX509Certificate(); + + System.out.println("... "); + System.out.println(" " + CERT_DIR_FROM_ROOT + + Paths.get(caSignedUsingArraysDer).getFileName()); + System.out.println(" " + CERT_DIR_FROM_ROOT + + Paths.get(caSignedUsingArraysPem).getFileName()); + + /* Free native memory */ + subjectName.free(); + x509.free(); + } + + /** + * Generate example CA-signed certificate using generated keys for the + * certificate public and private key, to be used in the certificate + * generation process. + * + * Generates and writes certificate out to the following paths in + * both PEM and DER format (see variable values above): + * caSignedUsingGeneratedKeysDer (DER format) + * caSignedUsingGeneratedKeysPem (PEM format) + * + * @throws WolfSSLException if error occurs during certificate generation + * process. + * @throws WolfSSLJNIException if native JNI error occurs + * @throws IOException on error writing to output file locations + */ + public void generateCASignedUsingGeneratedKeys() + throws WolfSSLException, WolfSSLJNIException, IOException, + CertificateException, NoSuchAlgorithmException, + InvalidKeySpecException { + + System.out.print("\nGenerating CA-signed cert with generated keys"); + + /* Create new certificate object */ + WolfSSLCertificate x509 = new WolfSSLCertificate(); + + /* Set notBefore/notAfter validity dates */ + Instant now = Instant.now(); + final Date notBefore = Date.from(now); + final Date notAfter = Date.from(now.plus(Duration.ofDays(365))); + x509.setNotBefore(notBefore); + x509.setNotAfter(notAfter); + + /* Set serial number */ + x509.setSerialNumber(BigInteger.valueOf(12345)); + + /* Set Subject Name */ + WolfSSLX509Name subjectName = generateTestSubjectName(); + x509.setSubjectName(subjectName); + + /* Set Issuer Name from existing cert file wrapped in + * WolfSSLCertificate object */ + WolfSSLCertificate issuer = new WolfSSLCertificate(caCertPem, + WolfSSL.SSL_FILETYPE_PEM); + X509Certificate issuerX509 = issuer.getX509Certificate(); + x509.setIssuerName(issuerX509); + + /* Set Public Key from generated java.security.PublicKey */ + KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA"); + kpg.initialize(2048); + KeyPair keyPair = kpg.generateKeyPair(); + PublicKey pubKey = keyPair.getPublic(); + x509.setPublicKey(pubKey); + + /* Add Extensions */ + x509.addExtension(WolfSSL.NID_key_usage, test_KEY_USAGE, false); + x509.addExtension(WolfSSL.NID_ext_key_usage, test_EXT_KEY_USAGE, false); + x509.addExtension(WolfSSL.NID_subject_alt_name, test_ALT_NAME, false); + x509.addExtension(WolfSSL.NID_basic_constraints, true, true); + + /* Sign certificate, using CA's private key */ + byte[] privBytes = Files.readAllBytes(Paths.get(caKeyPkcs8Der)); + KeyFactory kf = KeyFactory.getInstance("RSA"); + PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(privBytes); + RSAPrivateKey rsaPriv = (RSAPrivateKey)kf.generatePrivate(spec); + x509.signCert((PrivateKey)rsaPriv, "SHA256"); + + /* Output to DER and PEM files */ + byte[] derCert = x509.getDer(); + byte[] pemCert = x509.getPem(); + + /* Write out generated certs to files */ + writeFile(caSignedUsingGeneratedKeysDer, derCert); + writeFile(caSignedUsingGeneratedKeysPem, pemCert); + + /* Test converting to X509Certificate */ + X509Certificate tmpX509 = x509.getX509Certificate(); + + System.out.println("... "); + System.out.println(" " + CERT_DIR_FROM_ROOT + + Paths.get(caSignedUsingGeneratedKeysDer).getFileName()); + System.out.println(" " + CERT_DIR_FROM_ROOT + + Paths.get(caSignedUsingGeneratedKeysPem).getFileName()); + + /* Free native memory */ + subjectName.free(); + x509.free(); + } + + public void run(String[] args) { + + int ret = 0; + + try { + /* Initialize and load native wolfSSL library, enable debugging */ + WolfSSL.loadLibrary(); + WolfSSL sslLib = new WolfSSL(); + + /* Enable debugging if desired */ + //sslLib.debuggingON(); + + System.out.println( + "wolfSSL JNI X509v3 Certificate Generation Example"); + + /* Generate self-signed example certificates */ + generateSelfSignedUsingFiles(); + generateSelfSignedUsingArrays(); + generateSelfSignedUsingGeneratedKeys(); + + /* Generate CA-signed example certificates */ + generateCASignedUsingFiles(); + generateCASignedUsingArrays(); + generateCASignedUsingGeneratedKeys(); + + } catch (WolfSSLException | WolfSSLJNIException | + IOException | CertificateException | + NoSuchAlgorithmException | InvalidKeySpecException e) { + e.printStackTrace(); + + /* exit with error */ + System.exit(1); + } + + } /* end run() */ + + public static void main(String[] args) { + new X509v3CertificateGeneration().run(args); + } + +} /* end X509v3CertificateGeneration */ + diff --git a/examples/X509v3CertificateGeneration.sh b/examples/X509v3CertificateGeneration.sh new file mode 100755 index 0000000..dfeb0af --- /dev/null +++ b/examples/X509v3CertificateGeneration.sh @@ -0,0 +1,51 @@ +#!/bin/bash + +# Allow user to override which openssl binary is used to verify certs +if [ -z "${OPENSSL}" ]; then + OPENSSL=openssl +fi + +cd ./examples/build +export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:../../lib/:/usr/local/lib +java -classpath ../../lib/wolfssl.jar:./ -Dsun.boot.library.path=../../lib/ -Xcheck:jni X509v3CertificateGeneration $@ + +if [ $? != 0 ]; then + printf "\nExample failed\n" + exit -1 +else + printf "\nExample passed\n" +fi + +which $OPENSSL > /dev/null +if [ $? != 0 ]; then + printf "openssl not detected, skipping cert verification\n" + exit -1 +fi + +printf "\nVerifying certs with openssl...\n" + +printf "Testing each can be opened with openssl x509 -text\n" + +# Test reading each DER cert +CERT_FILES="../certs/generated/*.der" +for f in $CERT_FILES +do + $OPENSSL x509 -inform DER -in $f -text -noout > /dev/null + if [ $? != 0 ]; then + printf "File not readable with openssl x509: $f\n" + exit -1 + fi +done + +# Test reading each PEM cert +CERT_FILES="../certs/generated/*.pem" +for f in $CERT_FILES +do + $OPENSSL x509 -inform PEM -in $f -text -noout > /dev/null + if [ $? != 0 ]; then + printf "File not readable with openssl x509: $f\n" + exit -1 + fi +done + +printf "Verification successful\n" diff --git a/examples/certs/ca-cert.pem b/examples/certs/ca-cert.pem index 2c7fc17..58688a0 100644 --- a/examples/certs/ca-cert.pem +++ b/examples/certs/ca-cert.pem @@ -2,12 +2,12 @@ Certificate: Data: Version: 3 (0x2) Serial Number: - 26:8c:93:f9:f9:f4:1e:b3:01:72:94:55:67:6d:e2:f8:3d:da:e9:f4 + 2c:80:ce:db:47:9d:07:66:92:3d:68:d7:ca:ac:90:4f:ca:69:41:4b Signature Algorithm: sha256WithRSAEncryption Issuer: C = US, ST = Montana, L = Bozeman, O = Sawtooth, OU = Consulting, CN = www.wolfssl.com, emailAddress = info@wolfssl.com Validity - Not Before: Feb 15 12:50:24 2022 GMT - Not After : Nov 11 12:50:24 2024 GMT + Not Before: Dec 16 21:17:49 2022 GMT + Not After : Sep 11 21:17:49 2025 GMT Subject: C = US, ST = Montana, L = Bozeman, O = Sawtooth, OU = Consulting, CN = www.wolfssl.com, emailAddress = info@wolfssl.com Subject Public Key Info: Public Key Algorithm: rsaEncryption @@ -38,7 +38,7 @@ Certificate: X509v3 Authority Key Identifier: keyid:27:8E:67:11:74:C3:26:1D:3F:ED:33:63:B3:A4:D8:1D:30:E5:E8:D5 DirName:/C=US/ST=Montana/L=Bozeman/O=Sawtooth/OU=Consulting/CN=www.wolfssl.com/emailAddress=info@wolfssl.com - serial:26:8C:93:F9:F9:F4:1E:B3:01:72:94:55:67:6D:E2:F8:3D:DA:E9:F4 + serial:2C:80:CE:DB:47:9D:07:66:92:3D:68:D7:CA:AC:90:4F:CA:69:41:4B X509v3 Basic Constraints: CA:TRUE @@ -47,27 +47,27 @@ Certificate: X509v3 Extended Key Usage: TLS Web Server Authentication, TLS Web Client Authentication Signature Algorithm: sha256WithRSAEncryption - 62:e4:1b:28:3c:9d:d2:60:a9:55:be:6a:f6:20:f2:da:e8:a1: - 1a:97:b1:90:77:82:ed:c7:77:29:53:33:18:10:62:e0:bd:93: - 1b:d2:d6:a1:80:43:1d:64:f1:42:92:ec:b7:b8:f0:6b:da:59: - 83:f4:b8:87:e6:fc:70:21:ea:62:32:70:68:14:0e:dc:b4:f1: - 66:e2:6e:ab:d2:72:6f:da:df:71:f6:3d:27:97:7d:be:e1:d1: - ac:16:ad:d7:4f:aa:9d:0c:1e:6e:a9:5e:7d:57:5b:3c:c7:6d: - d2:f2:5c:c3:dc:3d:36:99:8e:ab:c0:7f:13:a5:f4:67:8b:e2: - a6:51:31:f1:03:91:00:a8:c4:c5:1d:7f:35:62:b8:1d:a0:a5: - ab:ec:32:68:ee:f3:ca:48:16:9f:f4:1e:7e:ea:fa:b0:86:15: - 52:36:6c:4b:58:44:a7:eb:20:78:6e:7e:e8:00:40:ac:98:d8: - 53:f3:13:4b:b8:98:66:50:63:ed:af:e5:a4:f6:c9:90:1c:84: - 0a:09:45:2f:a1:e1:37:63:b5:43:8c:a0:2e:7f:c4:d4:e1:ae: - b7:b9:45:13:f8:70:d5:79:06:4f:82:83:4b:98:d7:56:47:64: - 9a:6a:6d:8e:7a:9d:ef:83:0f:6b:75:0e:47:22:92:f3:b4:b2: - 84:61:1f:1c + ae:b0:a4:35:8e:8a:1b:a6:eb:b3:a2:57:cf:3a:1f:dc:6e:bc: + d2:d0:a6:4a:8f:88:0a:6e:74:d5:d1:7c:d1:44:b1:d4:3b:17: + 03:09:5a:46:ed:08:08:cf:f1:fd:20:07:67:c0:97:ec:35:f3: + 75:ca:20:61:98:3e:f5:4d:be:e6:9d:75:1e:e4:03:ad:8c:a6: + 1e:3d:ec:e4:1a:92:5b:f9:a3:ad:83:ca:4f:cd:aa:38:bb:6e: + ae:ad:fa:a7:46:f1:8b:73:ec:09:23:bc:f2:18:e5:b7:92:86: + 3e:a4:75:60:c7:3d:0f:3f:83:00:c3:06:08:9c:d1:54:d6:ba: + 6d:95:3d:34:a1:be:24:91:cc:20:03:11:5b:72:1c:d4:65:d0: + 11:88:75:26:04:26:ef:66:70:e6:3b:38:87:9c:53:71:1b:09: + 51:70:50:99:4c:31:0c:62:44:57:30:60:04:fc:12:2c:a3:24: + b4:f7:11:d5:0e:b5:21:0b:ed:86:11:67:4d:36:fa:57:a0:59: + 55:21:b3:6d:e4:77:5e:ec:7e:f0:09:13:8e:99:98:b2:e1:82: + b6:4b:3e:0f:41:a6:0c:cd:49:99:7e:e4:8a:cb:37:ed:53:cf: + 86:5d:a9:26:a8:e5:01:25:5a:b4:bc:25:35:f1:fa:5a:5c:ce: + d4:b8:9a:2c -----BEGIN CERTIFICATE----- -MIIE/zCCA+egAwIBAgIUJoyT+fn0HrMBcpRVZ23i+D3a6fQwDQYJKoZIhvcNAQEL +MIIE/zCCA+egAwIBAgIULIDO20edB2aSPWjXyqyQT8ppQUswDQYJKoZIhvcNAQEL BQAwgZQxCzAJBgNVBAYTAlVTMRAwDgYDVQQIDAdNb250YW5hMRAwDgYDVQQHDAdC b3plbWFuMREwDwYDVQQKDAhTYXd0b290aDETMBEGA1UECwwKQ29uc3VsdGluZzEY MBYGA1UEAwwPd3d3LndvbGZzc2wuY29tMR8wHQYJKoZIhvcNAQkBFhBpbmZvQHdv -bGZzc2wuY29tMB4XDTIyMDIxNTEyNTAyNFoXDTI0MTExMTEyNTAyNFowgZQxCzAJ +bGZzc2wuY29tMB4XDTIyMTIxNjIxMTc0OVoXDTI1MDkxMTIxMTc0OVowgZQxCzAJ BgNVBAYTAlVTMRAwDgYDVQQIDAdNb250YW5hMRAwDgYDVQQHDAdCb3plbWFuMREw DwYDVQQKDAhTYXd0b290aDETMBEGA1UECwwKQ29uc3VsdGluZzEYMBYGA1UEAwwP d3d3LndvbGZzc2wuY29tMR8wHQYJKoZIhvcNAQkBFhBpbmZvQHdvbGZzc2wuY29t @@ -82,12 +82,12 @@ BgNVHSMEgcwwgcmAFCeOZxF0wyYdP+0zY7Ok2B0w5ejVoYGapIGXMIGUMQswCQYD VQQGEwJVUzEQMA4GA1UECAwHTW9udGFuYTEQMA4GA1UEBwwHQm96ZW1hbjERMA8G A1UECgwIU2F3dG9vdGgxEzARBgNVBAsMCkNvbnN1bHRpbmcxGDAWBgNVBAMMD3d3 dy53b2xmc3NsLmNvbTEfMB0GCSqGSIb3DQEJARYQaW5mb0B3b2xmc3NsLmNvbYIU -JoyT+fn0HrMBcpRVZ23i+D3a6fQwDAYDVR0TBAUwAwEB/zAcBgNVHREEFTATggtl +LIDO20edB2aSPWjXyqyQT8ppQUswDAYDVR0TBAUwAwEB/zAcBgNVHREEFTATggtl eGFtcGxlLmNvbYcEfwAAATAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIw -DQYJKoZIhvcNAQELBQADggEBAGLkGyg8ndJgqVW+avYg8trooRqXsZB3gu3HdylT -MxgQYuC9kxvS1qGAQx1k8UKS7Le48GvaWYP0uIfm/HAh6mIycGgUDty08WbibqvS -cm/a33H2PSeXfb7h0awWrddPqp0MHm6pXn1XWzzHbdLyXMPcPTaZjqvAfxOl9GeL -4qZRMfEDkQCoxMUdfzViuB2gpavsMmju88pIFp/0Hn7q+rCGFVI2bEtYRKfrIHhu -fugAQKyY2FPzE0u4mGZQY+2v5aT2yZAchAoJRS+h4TdjtUOMoC5/xNThrre5RRP4 -cNV5Bk+Cg0uY11ZHZJpqbY56ne+DD2t1DkcikvO0soRhHxw= +DQYJKoZIhvcNAQELBQADggEBAK6wpDWOihum67OiV886H9xuvNLQpkqPiApudNXR +fNFEsdQ7FwMJWkbtCAjP8f0gB2fAl+w183XKIGGYPvVNvuaddR7kA62Mph497OQa +klv5o62Dyk/Nqji7bq6t+qdG8Ytz7AkjvPIY5beShj6kdWDHPQ8/gwDDBgic0VTW +um2VPTShviSRzCADEVtyHNRl0BGIdSYEJu9mcOY7OIecU3EbCVFwUJlMMQxiRFcw +YAT8EiyjJLT3EdUOtSEL7YYRZ002+legWVUhs23kd17sfvAJE46ZmLLhgrZLPg9B +pgzNSZl+5IrLN+1Tz4ZdqSao5QElWrS8JTXx+lpcztS4miw= -----END CERTIFICATE----- diff --git a/examples/certs/ca-ecc-cert.pem b/examples/certs/ca-ecc-cert.pem index 1d0148d..e4e4c7c 100644 --- a/examples/certs/ca-ecc-cert.pem +++ b/examples/certs/ca-ecc-cert.pem @@ -2,12 +2,12 @@ Certificate: Data: Version: 3 (0x2) Serial Number: - 29:bf:2b:cd:bf:55:54:49:85:b3:69:4e:e1:85:37:79:1e:81:f9:c2 + 65:67:42:4c:06:e7:e4:c3:68:01:a9:94:a9:07:e6:fe:bd:2c:d6:3d Signature Algorithm: ecdsa-with-SHA256 Issuer: C = US, ST = Washington, L = Seattle, O = wolfSSL, OU = Development, CN = www.wolfssl.com, emailAddress = info@wolfssl.com Validity - Not Before: Feb 15 12:50:24 2022 GMT - Not After : Nov 11 12:50:24 2024 GMT + Not Before: Dec 16 21:17:49 2022 GMT + Not After : Sep 11 21:17:49 2025 GMT Subject: C = US, ST = Washington, L = Seattle, O = wolfSSL, OU = Development, CN = www.wolfssl.com, emailAddress = info@wolfssl.com Subject Public Key Info: Public Key Algorithm: id-ecPublicKey @@ -31,16 +31,16 @@ Certificate: X509v3 Key Usage: critical Digital Signature, Certificate Sign, CRL Sign Signature Algorithm: ecdsa-with-SHA256 - 30:44:02:20:78:ed:4c:1c:a7:2d:b3:35:0b:1d:46:a3:37:31: - 0b:8a:05:39:c8:28:31:58:35:f1:98:f7:4b:72:c0:4f:e6:7f: - 02:20:02:f2:09:2b:3a:e1:36:92:bf:58:6a:03:12:2d:79:e6: - bd:06:45:61:b9:0e:39:e1:9c:f0:a8:2e:0b:1e:8c:b2 + 30:46:02:21:00:b0:12:16:03:26:79:d4:6b:94:d9:7e:ca:e1: + 2d:24:64:ef:11:6e:f2:12:81:e4:ce:1d:77:7d:ca:5c:47:50: + 62:02:21:00:80:bf:46:3c:5d:d8:e5:ab:47:ce:a2:19:bd:21: + de:85:6f:ab:c9:8f:01:f3:ab:1b:b9:e1:53:d6:24:77:a6:4d -----BEGIN CERTIFICATE----- -MIIClDCCAjugAwIBAgIUKb8rzb9VVEmFs2lO4YU3eR6B+cIwCgYIKoZIzj0EAwIw +MIICljCCAjugAwIBAgIUZWdCTAbn5MNoAamUqQfm/r0s1j0wCgYIKoZIzj0EAwIw gZcxCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApXYXNoaW5ndG9uMRAwDgYDVQQHDAdT ZWF0dGxlMRAwDgYDVQQKDAd3b2xmU1NMMRQwEgYDVQQLDAtEZXZlbG9wbWVudDEY MBYGA1UEAwwPd3d3LndvbGZzc2wuY29tMR8wHQYJKoZIhvcNAQkBFhBpbmZvQHdv -bGZzc2wuY29tMB4XDTIyMDIxNTEyNTAyNFoXDTI0MTExMTEyNTAyNFowgZcxCzAJ +bGZzc2wuY29tMB4XDTIyMTIxNjIxMTc0OVoXDTI1MDkxMTIxMTc0OVowgZcxCzAJ BgNVBAYTAlVTMRMwEQYDVQQIDApXYXNoaW5ndG9uMRAwDgYDVQQHDAdTZWF0dGxl MRAwDgYDVQQKDAd3b2xmU1NMMRQwEgYDVQQLDAtEZXZlbG9wbWVudDEYMBYGA1UE AwwPd3d3LndvbGZzc2wuY29tMR8wHQYJKoZIhvcNAQkBFhBpbmZvQHdvbGZzc2wu @@ -48,6 +48,6 @@ Y29tMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEAtPZbtYBjkXIuZAx5cBM456t KTiYuhDW6QkqgKkuFyq5ir8zg0bjlQvkd0C1O0NFMw9hU3w3RMHL/IDK6EPqp6Nj MGEwHQYDVR0OBBYEFFaOmsPwQt4YuUVVbvmTz+rD86UhMB8GA1UdIwQYMBaAFFaO msPwQt4YuUVVbvmTz+rD86UhMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQD -AgGGMAoGCCqGSM49BAMCA0cAMEQCIHjtTBynLbM1Cx1GozcxC4oFOcgoMVg18Zj3 -S3LAT+Z/AiAC8gkrOuE2kr9YagMSLXnmvQZFYbkOOeGc8KguCx6Msg== +AgGGMAoGCCqGSM49BAMCA0kAMEYCIQCwEhYDJnnUa5TZfsrhLSRk7xFu8hKB5M4d +d33KXEdQYgIhAIC/Rjxd2OWrR86iGb0h3oVvq8mPAfOrG7nhU9Ykd6ZN -----END CERTIFICATE----- diff --git a/examples/certs/ca-key.der b/examples/certs/ca-key.der new file mode 100644 index 0000000..14456f3 Binary files /dev/null and b/examples/certs/ca-key.der differ diff --git a/examples/certs/ca-keyPkcs8.der b/examples/certs/ca-keyPkcs8.der new file mode 100644 index 0000000..58ac8d4 Binary files /dev/null and b/examples/certs/ca-keyPkcs8.der differ diff --git a/examples/certs/client-cert.der b/examples/certs/client-cert.der index 321f5c1..aa7e268 100644 Binary files a/examples/certs/client-cert.der and b/examples/certs/client-cert.der differ diff --git a/examples/certs/client-cert.pem b/examples/certs/client-cert.pem index 26c7384..4bf36d3 100644 --- a/examples/certs/client-cert.pem +++ b/examples/certs/client-cert.pem @@ -2,12 +2,12 @@ Certificate: Data: Version: 3 (0x2) Serial Number: - 01:1a:eb:56:ab:dc:8b:f3:a6:1e:f4:93:60:89:b7:05:07:29:01:2c + 73:fb:54:d6:03:7d:4c:07:84:e2:00:11:8c:dd:90:dc:48:8d:ea:53 Signature Algorithm: sha256WithRSAEncryption Issuer: C = US, ST = Montana, L = Bozeman, O = wolfSSL_2048, OU = Programming-2048, CN = www.wolfssl.com, emailAddress = info@wolfssl.com Validity - Not Before: Feb 15 12:50:24 2022 GMT - Not After : Nov 11 12:50:24 2024 GMT + Not Before: Dec 16 21:17:49 2022 GMT + Not After : Sep 11 21:17:49 2025 GMT Subject: C = US, ST = Montana, L = Bozeman, O = wolfSSL_2048, OU = Programming-2048, CN = www.wolfssl.com, emailAddress = info@wolfssl.com Subject Public Key Info: Public Key Algorithm: rsaEncryption @@ -38,7 +38,7 @@ Certificate: X509v3 Authority Key Identifier: keyid:33:D8:45:66:D7:68:87:18:7E:54:0D:70:27:91:C7:26:D7:85:65:C0 DirName:/C=US/ST=Montana/L=Bozeman/O=wolfSSL_2048/OU=Programming-2048/CN=www.wolfssl.com/emailAddress=info@wolfssl.com - serial:01:1A:EB:56:AB:DC:8B:F3:A6:1E:F4:93:60:89:B7:05:07:29:01:2C + serial:73:FB:54:D6:03:7D:4C:07:84:E2:00:11:8C:DD:90:DC:48:8D:EA:53 X509v3 Basic Constraints: CA:TRUE @@ -47,28 +47,28 @@ Certificate: X509v3 Extended Key Usage: TLS Web Server Authentication, TLS Web Client Authentication Signature Algorithm: sha256WithRSAEncryption - 64:6d:a6:4a:a8:9f:a7:e9:75:2c:f3:85:3d:3e:af:38:fb:6c: - c7:eb:c7:d0:2b:a2:45:b5:65:be:d0:13:2c:f7:a3:c1:eb:3c: - b1:f8:b8:3d:63:8f:ca:08:4e:65:1d:2c:ce:34:6e:35:96:87: - 93:30:5d:aa:c8:e9:a0:9c:9b:84:78:3a:52:a1:33:48:6e:84: - 66:71:9c:cf:d1:c7:7b:02:4c:e1:49:7c:69:47:fc:b7:01:f9: - a0:39:3b:ab:b9:c6:d9:ca:27:85:f0:5c:b6:a4:e6:dc:f2:52: - fe:44:00:b6:f0:47:f2:6f:3f:d5:0f:ff:31:93:53:88:8c:c7: - fb:56:10:4b:3b:43:e6:8a:9c:b7:b4:9a:dd:5c:e3:cd:9c:bd: - a7:0c:c1:d9:96:f0:93:f3:ab:bd:d2:1e:77:8a:42:cd:0f:fe: - 48:da:57:34:61:46:a3:89:2e:31:d2:4a:d4:43:2f:56:85:44: - 75:ca:6b:36:e2:e8:3a:b2:95:95:3a:28:90:8d:c0:23:fb:3c: - d2:1a:73:6b:ef:fd:d6:1b:eb:6d:67:2a:e1:eb:2a:83:22:ad: - e3:95:19:e5:93:ee:14:dc:b5:7d:e7:cf:89:8c:d7:8f:d2:3f: - 68:7e:a9:74:7c:1b:38:65:f9:28:4d:ff:50:c8:ee:51:3a:8f: - 1d:9e:55:5e + 36:cb:bc:c5:52:9a:66:cd:91:4d:8f:27:9f:b3:64:80:0e:64: + b4:cb:1a:cd:75:9e:82:7c:55:67:d8:9f:90:a3:34:96:99:43: + f7:49:53:a2:58:85:a0:b3:83:4f:af:b8:15:8a:88:1e:f3:60: + f4:7c:94:b5:58:68:f1:2a:13:80:34:c2:6f:a5:f8:7e:76:16: + 81:4f:36:8b:c3:59:bd:51:dd:60:87:d7:1d:96:44:69:07:3c: + 8f:28:56:b1:11:5c:4e:81:3f:57:25:fd:65:dd:07:cf:17:0a: + 01:7e:4e:3f:8e:73:db:fe:f4:f2:c5:ff:a3:76:a8:74:46:2e: + 47:0d:b0:ed:0a:c0:c5:0a:65:d3:dc:62:b2:e0:1e:8e:bd:f3: + bd:af:af:66:84:36:92:e2:3b:80:d0:57:a6:41:a3:62:d1:a6: + 6d:14:6c:cd:82:b1:c1:c1:35:55:ae:59:49:a8:26:52:bd:ef: + 1b:2c:1f:9d:39:04:d2:82:a0:6b:39:71:59:33:82:ba:55:6c: + 97:f2:1b:5b:e0:4d:e2:cf:89:e7:26:b8:2c:6c:9f:83:d6:ed: + 4e:2f:75:a9:30:4e:01:95:0d:4f:83:5e:c8:af:7f:67:ea:53: + bf:ca:9b:1f:d4:ff:36:97:02:71:8e:33:de:e2:58:27:aa:70: + 0c:5b:de:0e -----BEGIN CERTIFICATE----- -MIIFHTCCBAWgAwIBAgIUARrrVqvci/OmHvSTYIm3BQcpASwwDQYJKoZIhvcNAQEL +MIIFHTCCBAWgAwIBAgIUc/tU1gN9TAeE4gARjN2Q3EiN6lMwDQYJKoZIhvcNAQEL BQAwgZ4xCzAJBgNVBAYTAlVTMRAwDgYDVQQIDAdNb250YW5hMRAwDgYDVQQHDAdC b3plbWFuMRUwEwYDVQQKDAx3b2xmU1NMXzIwNDgxGTAXBgNVBAsMEFByb2dyYW1t aW5nLTIwNDgxGDAWBgNVBAMMD3d3dy53b2xmc3NsLmNvbTEfMB0GCSqGSIb3DQEJ -ARYQaW5mb0B3b2xmc3NsLmNvbTAeFw0yMjAyMTUxMjUwMjRaFw0yNDExMTExMjUw -MjRaMIGeMQswCQYDVQQGEwJVUzEQMA4GA1UECAwHTW9udGFuYTEQMA4GA1UEBwwH +ARYQaW5mb0B3b2xmc3NsLmNvbTAeFw0yMjEyMTYyMTE3NDlaFw0yNTA5MTEyMTE3 +NDlaMIGeMQswCQYDVQQGEwJVUzEQMA4GA1UECAwHTW9udGFuYTEQMA4GA1UEBwwH Qm96ZW1hbjEVMBMGA1UECgwMd29sZlNTTF8yMDQ4MRkwFwYDVQQLDBBQcm9ncmFt bWluZy0yMDQ4MRgwFgYDVQQDDA93d3cud29sZnNzbC5jb20xHzAdBgkqhkiG9w0B CQEWEGluZm9Ad29sZnNzbC5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK @@ -82,13 +82,13 @@ Ztdohxh+VA1wJ5HHJteFZcAwgd4GA1UdIwSB1jCB04AUM9hFZtdohxh+VA1wJ5HH JteFZcChgaSkgaEwgZ4xCzAJBgNVBAYTAlVTMRAwDgYDVQQIDAdNb250YW5hMRAw DgYDVQQHDAdCb3plbWFuMRUwEwYDVQQKDAx3b2xmU1NMXzIwNDgxGTAXBgNVBAsM EFByb2dyYW1taW5nLTIwNDgxGDAWBgNVBAMMD3d3dy53b2xmc3NsLmNvbTEfMB0G -CSqGSIb3DQEJARYQaW5mb0B3b2xmc3NsLmNvbYIUARrrVqvci/OmHvSTYIm3BQcp -ASwwDAYDVR0TBAUwAwEB/zAcBgNVHREEFTATggtleGFtcGxlLmNvbYcEfwAAATAd +CSqGSIb3DQEJARYQaW5mb0B3b2xmc3NsLmNvbYIUc/tU1gN9TAeE4gARjN2Q3EiN +6lMwDAYDVR0TBAUwAwEB/zAcBgNVHREEFTATggtleGFtcGxlLmNvbYcEfwAAATAd BgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEB -AGRtpkqon6fpdSzzhT0+rzj7bMfrx9ArokW1Zb7QEyz3o8HrPLH4uD1jj8oITmUd -LM40bjWWh5MwXarI6aCcm4R4OlKhM0huhGZxnM/Rx3sCTOFJfGlH/LcB+aA5O6u5 -xtnKJ4XwXLak5tzyUv5EALbwR/JvP9UP/zGTU4iMx/tWEEs7Q+aKnLe0mt1c482c -vacMwdmW8JPzq73SHneKQs0P/kjaVzRhRqOJLjHSStRDL1aFRHXKazbi6DqylZU6 -KJCNwCP7PNIac2vv/dYb621nKuHrKoMireOVGeWT7hTctX3nz4mM14/SP2h+qXR8 -Gzhl+ShN/1DI7lE6jx2eVV4= +ADbLvMVSmmbNkU2PJ5+zZIAOZLTLGs11noJ8VWfYn5CjNJaZQ/dJU6JYhaCzg0+v +uBWKiB7zYPR8lLVYaPEqE4A0wm+l+H52FoFPNovDWb1R3WCH1x2WRGkHPI8oVrER +XE6BP1cl/WXdB88XCgF+Tj+Oc9v+9PLF/6N2qHRGLkcNsO0KwMUKZdPcYrLgHo69 +872vr2aENpLiO4DQV6ZBo2LRpm0UbM2CscHBNVWuWUmoJlK97xssH505BNKCoGs5 +cVkzgrpVbJfyG1vgTeLPiecmuCxsn4PW7U4vdakwTgGVDU+DXsivf2fqU7/Kmx/U +/zaXAnGOM97iWCeqcAxb3g4= -----END CERTIFICATE----- diff --git a/examples/certs/client-key.der b/examples/certs/client-key.der new file mode 100644 index 0000000..94dc253 Binary files /dev/null and b/examples/certs/client-key.der differ diff --git a/examples/certs/client-keyPub.der b/examples/certs/client-keyPub.der new file mode 100644 index 0000000..b27f0e9 Binary files /dev/null and b/examples/certs/client-keyPub.der differ diff --git a/examples/certs/crl/cliCrl.pem b/examples/certs/crl/cliCrl.pem index 603da9a..10fe581 100644 --- a/examples/certs/crl/cliCrl.pem +++ b/examples/certs/crl/cliCrl.pem @@ -2,41 +2,41 @@ Certificate Revocation List (CRL): Version 2 (0x1) Signature Algorithm: sha256WithRSAEncryption Issuer: C = US, ST = Montana, L = Bozeman, O = wolfSSL_2048, OU = Programming-2048, CN = www.wolfssl.com, emailAddress = info@wolfssl.com - Last Update: Feb 15 12:50:27 2022 GMT - Next Update: Nov 11 12:50:27 2024 GMT + Last Update: Dec 16 21:17:50 2022 GMT + Next Update: Sep 11 21:17:50 2025 GMT CRL extensions: X509v3 CRL Number: 6 Revoked Certificates: Serial Number: 02 - Revocation Date: Feb 15 12:50:27 2022 GMT + Revocation Date: Dec 16 21:17:50 2022 GMT Signature Algorithm: sha256WithRSAEncryption - 7e:92:50:e4:30:78:22:ed:6f:79:a5:cb:65:3c:de:7a:83:88: - 1e:66:8a:e5:2e:42:c6:9f:66:31:94:22:89:30:18:a2:b4:28: - 76:b1:bc:8b:4a:0d:aa:ee:92:b6:4e:b5:11:87:6b:57:18:4d: - fd:3c:b1:75:d7:b3:16:0e:7a:42:76:c5:b8:7c:22:15:11:c0: - 9b:0d:a6:fe:42:86:ef:cb:79:60:4d:35:20:4c:a3:a2:37:07: - de:dd:94:fe:49:86:ae:7c:86:71:e2:86:9a:2b:e2:a2:80:6c: - 96:3c:8b:13:4f:f6:52:63:6d:1c:7c:af:3f:22:c1:53:97:6b: - d0:2f:84:88:68:23:e1:8c:2d:bd:57:e3:c7:eb:6f:20:13:a7: - 13:86:2f:2e:d5:3b:87:bb:08:3b:24:cb:dd:10:17:48:d9:97: - 67:28:6e:40:6a:70:45:04:6f:93:52:77:a3:21:7e:58:29:95: - 96:a6:3f:a2:73:83:2f:3e:d8:85:0a:f4:7d:39:04:9b:5d:cb: - 7e:d4:6a:33:63:b4:67:6f:b8:e3:3a:6a:7b:57:ed:f6:bd:98: - 11:fb:f1:0e:c8:29:73:fd:dd:55:93:d4:00:05:5c:be:d6:e7: - 24:ec:9d:d0:41:d3:1c:dc:4b:de:df:64:e1:00:39:dc:7d:04: - 75:fd:94:7c + bf:d3:f7:5b:70:94:5a:11:50:b2:7d:7b:f9:c8:0f:aa:1b:82: + f9:24:5f:79:a6:ab:9d:71:53:83:a2:29:93:a4:91:9d:70:0e: + b7:b7:e2:67:b8:ee:1c:fb:81:be:f7:e6:a7:d7:c0:df:5d:d3: + 4b:df:50:1c:08:c3:95:20:bd:6c:0e:f8:c9:70:66:cd:42:19: + d8:a5:75:bf:cc:b4:fb:f4:fc:85:58:06:95:07:fd:a5:c2:a8: + ac:a3:e9:eb:0c:99:98:f8:62:a8:59:22:d5:72:71:05:8a:ca: + 6a:5a:96:c1:a3:29:b2:ea:78:30:1d:8c:c5:17:26:b5:d4:87: + 79:c9:f6:51:2e:c9:e9:b5:f4:17:2a:8e:ba:3d:e9:8d:e0:66: + 87:7b:8f:36:8c:62:45:7a:07:2b:b2:da:02:ba:27:b9:e6:18: + d8:84:5f:4d:8f:cd:03:91:e8:53:c8:10:c8:d9:51:af:3d:e3: + 35:25:cd:3e:44:7e:fd:8f:74:46:4a:b9:03:da:41:2b:b1:4d: + 4c:39:af:14:fa:9c:4f:54:4c:4b:9f:a8:4a:b6:99:24:95:54: + 37:05:ab:45:7b:7b:25:20:d1:99:b1:5e:aa:98:a0:1e:b9:b1: + a3:fe:e5:2c:f8:49:d8:94:07:05:79:b5:9b:19:0e:53:c8:b3: + ce:60:d0:bc -----BEGIN X509 CRL----- MIICDjCB9wIBATANBgkqhkiG9w0BAQsFADCBnjELMAkGA1UEBhMCVVMxEDAOBgNV BAgMB01vbnRhbmExEDAOBgNVBAcMB0JvemVtYW4xFTATBgNVBAoMDHdvbGZTU0xf MjA0ODEZMBcGA1UECwwQUHJvZ3JhbW1pbmctMjA0ODEYMBYGA1UEAwwPd3d3Lndv -bGZzc2wuY29tMR8wHQYJKoZIhvcNAQkBFhBpbmZvQHdvbGZzc2wuY29tFw0yMjAy -MTUxMjUwMjdaFw0yNDExMTExMjUwMjdaMBQwEgIBAhcNMjIwMjE1MTI1MDI3WqAO -MAwwCgYDVR0UBAMCAQYwDQYJKoZIhvcNAQELBQADggEBAH6SUOQweCLtb3mly2U8 -3nqDiB5miuUuQsafZjGUIokwGKK0KHaxvItKDarukrZOtRGHa1cYTf08sXXXsxYO -ekJ2xbh8IhURwJsNpv5Chu/LeWBNNSBMo6I3B97dlP5Jhq58hnHihpor4qKAbJY8 -ixNP9lJjbRx8rz8iwVOXa9AvhIhoI+GMLb1X48frbyATpxOGLy7VO4e7CDsky90Q -F0jZl2cobkBqcEUEb5NSd6MhflgplZamP6Jzgy8+2IUK9H05BJtdy37UajNjtGdv -uOM6antX7fa9mBH78Q7IKXP93VWT1AAFXL7W5yTsndBB0xzcS97fZOEAOdx9BHX9 -lHw= +bGZzc2wuY29tMR8wHQYJKoZIhvcNAQkBFhBpbmZvQHdvbGZzc2wuY29tFw0yMjEy +MTYyMTE3NTBaFw0yNTA5MTEyMTE3NTBaMBQwEgIBAhcNMjIxMjE2MjExNzUwWqAO +MAwwCgYDVR0UBAMCAQYwDQYJKoZIhvcNAQELBQADggEBAL/T91twlFoRULJ9e/nI +D6obgvkkX3mmq51xU4OiKZOkkZ1wDre34me47hz7gb735qfXwN9d00vfUBwIw5Ug +vWwO+MlwZs1CGdildb/MtPv0/IVYBpUH/aXCqKyj6esMmZj4YqhZItVycQWKympa +lsGjKbLqeDAdjMUXJrXUh3nJ9lEuyem19Bcqjro96Y3gZod7jzaMYkV6Byuy2gK6 +J7nmGNiEX02PzQOR6FPIEMjZUa894zUlzT5Efv2PdEZKuQPaQSuxTUw5rxT6nE9U +TEufqEq2mSSVVDcFq0V7eyUg0ZmxXqqYoB65saP+5Sz4SdiUBwV5tZsZDlPIs85g +0Lw= -----END X509 CRL----- diff --git a/examples/certs/crl/crl.pem b/examples/certs/crl/crl.pem index 8f96121..9da22d8 100644 --- a/examples/certs/crl/crl.pem +++ b/examples/certs/crl/crl.pem @@ -2,40 +2,40 @@ Certificate Revocation List (CRL): Version 2 (0x1) Signature Algorithm: sha256WithRSAEncryption Issuer: C = US, ST = Montana, L = Bozeman, O = Sawtooth, OU = Consulting, CN = www.wolfssl.com, emailAddress = info@wolfssl.com - Last Update: Feb 15 12:50:27 2022 GMT - Next Update: Nov 11 12:50:27 2024 GMT + Last Update: Dec 16 21:17:50 2022 GMT + Next Update: Sep 11 21:17:50 2025 GMT CRL extensions: X509v3 CRL Number: 2 Revoked Certificates: Serial Number: 02 - Revocation Date: Feb 15 12:50:27 2022 GMT + Revocation Date: Dec 16 21:17:50 2022 GMT Signature Algorithm: sha256WithRSAEncryption - 43:e6:3b:30:0e:32:53:32:a4:08:3c:e5:d5:2e:f1:ce:e9:95: - ff:ba:d6:fe:2e:59:80:f8:0a:2f:cf:1e:e0:37:fe:ca:cc:33: - 66:8b:ed:65:50:7d:44:92:d3:5c:52:9a:95:a5:9d:a5:4e:77: - 8b:b4:7f:59:c8:7a:e0:eb:34:32:ae:a1:03:99:d2:3c:c0:f4: - 7e:1c:87:4c:6c:5a:ba:0a:95:e8:a1:44:01:7b:8f:3e:a4:e3: - e8:1e:07:19:f0:09:7a:85:8f:f3:82:62:f8:1e:08:51:a3:60: - 30:5b:06:c8:a2:b3:ff:aa:28:66:ad:fe:4b:81:49:30:ef:5f: - 5d:ac:d9:ad:17:9f:2a:b6:22:d6:35:cc:9f:d9:11:26:dd:7a: - 06:35:d0:d5:c7:41:6c:52:97:8c:aa:82:5a:e5:a8:58:d4:b7: - 2b:31:84:34:15:bd:08:e4:9e:71:9e:c5:40:f8:02:a3:a0:1e: - 4f:98:72:2b:eb:9e:8a:4e:01:83:88:e5:cb:6e:3b:52:e3:a9: - 34:a1:7c:e4:79:2c:d1:e0:0b:74:22:ba:6d:cb:c3:a1:56:f9: - c9:f4:20:bf:00:49:df:6b:59:49:18:c7:75:27:8e:a1:5a:a6: - ff:f2:be:34:4a:c9:6d:6e:24:a3:1f:15:7e:34:90:b6:81:bf: - 15:80:c3:ac + 39:44:ff:39:f4:04:45:79:7e:73:e2:42:48:db:85:66:fd:99: + 76:94:7c:b5:79:5d:15:71:36:a9:87:f0:73:05:50:08:6b:1c: + 6e:de:96:45:31:c3:c0:ba:ba:f5:08:1d:05:4a:52:39:e9:03: + ef:59:c8:1d:4a:f2:86:05:99:7b:4b:74:f6:d3:75:8d:b2:57: + ba:ac:a7:11:14:d6:6c:71:c4:4c:1c:68:bc:49:78:f0:c9:52: + 8a:e7:8b:54:e6:20:58:20:60:66:f5:14:d8:cb:ff:e0:a0:45: + bc:b4:81:ad:1d:bc:cf:f8:8e:a8:87:24:55:99:d9:ce:47:f7: + 5b:4a:33:6d:db:bf:93:64:1a:a6:46:5f:27:dc:d8:d4:f9:c2: + 42:2a:7e:b2:7c:dd:98:77:f5:88:7d:15:25:08:bc:e0:d0:8d: + f4:c3:c3:04:41:a4:d1:b1:39:4a:6b:2c:b5:2e:9a:65:43:0d: + 0e:73:f4:06:e1:b3:49:34:94:b0:b7:ff:c0:27:c1:b5:ea:06: + f7:71:71:97:bb:bc:c7:1a:9f:eb:f6:3d:a5:7b:55:a7:bf:dd: + d7:ee:97:b8:9d:dc:cd:e3:06:db:9a:2c:60:bf:70:84:fa:6b: + 8d:70:7d:de:e8:b7:ab:b0:38:68:6c:c0:b1:e1:ba:45:e0:d7: + 12:3d:71:5b -----BEGIN X509 CRL----- MIICBDCB7QIBATANBgkqhkiG9w0BAQsFADCBlDELMAkGA1UEBhMCVVMxEDAOBgNV BAgMB01vbnRhbmExEDAOBgNVBAcMB0JvemVtYW4xETAPBgNVBAoMCFNhd3Rvb3Ro MRMwEQYDVQQLDApDb25zdWx0aW5nMRgwFgYDVQQDDA93d3cud29sZnNzbC5jb20x -HzAdBgkqhkiG9w0BCQEWEGluZm9Ad29sZnNzbC5jb20XDTIyMDIxNTEyNTAyN1oX -DTI0MTExMTEyNTAyN1owFDASAgECFw0yMjAyMTUxMjUwMjdaoA4wDDAKBgNVHRQE -AwIBAjANBgkqhkiG9w0BAQsFAAOCAQEAQ+Y7MA4yUzKkCDzl1S7xzumV/7rW/i5Z -gPgKL88e4Df+yswzZovtZVB9RJLTXFKalaWdpU53i7R/Wch64Os0Mq6hA5nSPMD0 -fhyHTGxaugqV6KFEAXuPPqTj6B4HGfAJeoWP84Ji+B4IUaNgMFsGyKKz/6ooZq3+ -S4FJMO9fXazZrRefKrYi1jXMn9kRJt16BjXQ1cdBbFKXjKqCWuWoWNS3KzGENBW9 -COSecZ7FQPgCo6AeT5hyK+ueik4Bg4jly247UuOpNKF85Hks0eALdCK6bcvDoVb5 -yfQgvwBJ32tZSRjHdSeOoVqm//K+NErJbW4kox8VfjSQtoG/FYDDrA== +HzAdBgkqhkiG9w0BCQEWEGluZm9Ad29sZnNzbC5jb20XDTIyMTIxNjIxMTc1MFoX +DTI1MDkxMTIxMTc1MFowFDASAgECFw0yMjEyMTYyMTE3NTBaoA4wDDAKBgNVHRQE +AwIBAjANBgkqhkiG9w0BAQsFAAOCAQEAOUT/OfQERXl+c+JCSNuFZv2ZdpR8tXld +FXE2qYfwcwVQCGscbt6WRTHDwLq69QgdBUpSOekD71nIHUryhgWZe0t09tN1jbJX +uqynERTWbHHETBxovEl48MlSiueLVOYgWCBgZvUU2Mv/4KBFvLSBrR28z/iOqIck +VZnZzkf3W0ozbdu/k2QapkZfJ9zY1PnCQip+snzdmHf1iH0VJQi84NCN9MPDBEGk +0bE5SmsstS6aZUMNDnP0BuGzSTSUsLf/wCfBteoG93Fxl7u8xxqf6/Y9pXtVp7/d +1+6XuJ3czeMG25osYL9whPprjXB93ui3q7A4aGzAseG6ReDXEj1xWw== -----END X509 CRL----- diff --git a/examples/certs/crl/crl.revoked b/examples/certs/crl/crl.revoked index 81e8021..b85ca36 100644 --- a/examples/certs/crl/crl.revoked +++ b/examples/certs/crl/crl.revoked @@ -2,43 +2,43 @@ Certificate Revocation List (CRL): Version 2 (0x1) Signature Algorithm: sha256WithRSAEncryption Issuer: C = US, ST = Montana, L = Bozeman, O = Sawtooth, OU = Consulting, CN = www.wolfssl.com, emailAddress = info@wolfssl.com - Last Update: Feb 15 12:50:27 2022 GMT - Next Update: Nov 11 12:50:27 2024 GMT + Last Update: Dec 16 21:17:50 2022 GMT + Next Update: Sep 11 21:17:50 2025 GMT CRL extensions: X509v3 CRL Number: 3 Revoked Certificates: Serial Number: 01 - Revocation Date: Feb 15 12:50:27 2022 GMT + Revocation Date: Dec 16 21:17:50 2022 GMT Serial Number: 02 - Revocation Date: Feb 15 12:50:27 2022 GMT + Revocation Date: Dec 16 21:17:50 2022 GMT Signature Algorithm: sha256WithRSAEncryption - 0f:69:fc:a3:54:d7:9c:94:db:71:a8:6c:b6:af:3c:df:0d:bb: - bb:cb:2e:45:6f:6d:a5:27:dc:ee:67:39:36:d4:33:22:02:5e: - fe:4f:27:00:4a:ba:b0:51:7c:3e:98:ee:a2:d3:58:31:6c:60: - 02:34:f0:ec:67:ec:fa:66:44:8d:27:f7:70:57:4b:a1:10:e3: - a1:fb:f4:3a:ac:ec:ca:cb:d8:d7:d8:ca:45:41:d4:17:18:30: - f1:4e:f6:a4:8b:17:0c:4f:b0:b6:79:17:f3:a8:57:8f:8d:89: - ad:73:b9:d4:95:c1:e2:19:0e:f6:ca:dd:bd:dc:d1:0b:eb:a7: - c7:85:c6:49:8f:7d:e4:9b:fb:1a:a9:da:92:0a:52:7a:87:f3: - 32:dc:a8:9f:cf:a3:3b:47:ee:66:f4:61:48:a0:60:4c:50:66: - 87:07:33:55:11:ed:8b:5d:df:d8:10:de:ce:ea:4a:98:41:ca: - 6a:90:7c:35:0d:df:ac:4d:19:d6:5f:37:a5:a7:48:40:31:59: - 62:84:a8:21:a6:b5:8d:63:54:e0:2e:b9:83:92:b0:20:bc:66: - b2:bf:4d:5a:0b:00:a7:c0:cb:29:c3:54:be:92:91:1d:b0:d0: - ec:b4:5d:fe:a4:90:ed:08:21:71:18:91:4b:97:3d:75:4f:f0: - bc:56:8e:db + 1f:6c:1c:50:42:8a:55:bc:41:f6:a9:15:b6:ad:90:53:0a:b8: + 73:71:8b:dd:0e:8f:95:0f:97:6d:82:24:09:6d:d5:9f:57:47: + ab:c2:10:ad:df:27:0b:6c:d4:1f:c2:d5:4b:56:4b:44:01:3e: + 5f:d3:08:6c:da:5b:94:40:00:47:e2:c9:f5:93:3d:c6:b0:28: + b6:48:ff:32:9e:7b:d9:2d:71:5c:c4:53:13:50:8d:c7:e8:d0: + 6f:28:ee:71:a0:8a:3e:da:9a:c4:e1:ad:a7:36:ce:87:ff:1f: + 32:f1:32:ca:ff:81:d9:b8:d1:ca:39:7f:08:90:77:da:45:23: + 56:49:ad:08:99:ef:75:23:5f:92:9a:b4:34:ef:5c:b1:68:71: + 0d:06:31:28:5e:b1:34:56:a3:d6:47:8a:ba:2b:e2:be:28:29: + d0:6a:12:60:5e:5c:93:7d:0d:54:bf:ee:72:7f:31:e6:9a:ab: + 56:fc:34:45:06:e9:bd:fc:39:1d:37:91:77:d2:da:96:01:a0: + 0d:9f:cf:b6:26:98:6b:fb:d9:ef:51:1d:df:41:6c:3c:61:5c: + 38:83:e4:71:51:1d:62:57:53:8b:0b:0a:b1:ac:df:5c:22:26: + b6:67:51:62:06:5b:97:ed:94:f4:40:7e:48:4e:3b:fd:b7:75: + 40:17:ec:48 -----BEGIN X509 CRL----- MIICGTCCAQECAQEwDQYJKoZIhvcNAQELBQAwgZQxCzAJBgNVBAYTAlVTMRAwDgYD VQQIDAdNb250YW5hMRAwDgYDVQQHDAdCb3plbWFuMREwDwYDVQQKDAhTYXd0b290 aDETMBEGA1UECwwKQ29uc3VsdGluZzEYMBYGA1UEAwwPd3d3LndvbGZzc2wuY29t -MR8wHQYJKoZIhvcNAQkBFhBpbmZvQHdvbGZzc2wuY29tFw0yMjAyMTUxMjUwMjda -Fw0yNDExMTExMjUwMjdaMCgwEgIBARcNMjIwMjE1MTI1MDI3WjASAgECFw0yMjAy -MTUxMjUwMjdaoA4wDDAKBgNVHRQEAwIBAzANBgkqhkiG9w0BAQsFAAOCAQEAD2n8 -o1TXnJTbcahstq883w27u8suRW9tpSfc7mc5NtQzIgJe/k8nAEq6sFF8PpjuotNY -MWxgAjTw7Gfs+mZEjSf3cFdLoRDjofv0OqzsysvY19jKRUHUFxgw8U72pIsXDE+w -tnkX86hXj42JrXO51JXB4hkO9srdvdzRC+unx4XGSY995Jv7GqnakgpSeofzMtyo -n8+jO0fuZvRhSKBgTFBmhwczVRHti13f2BDezupKmEHKapB8NQ3frE0Z1l83padI -QDFZYoSoIaa1jWNU4C65g5KwILxmsr9NWgsAp8DLKcNUvpKRHbDQ7LRd/qSQ7Qgh -cRiRS5c9dU/wvFaO2w== +MR8wHQYJKoZIhvcNAQkBFhBpbmZvQHdvbGZzc2wuY29tFw0yMjEyMTYyMTE3NTBa +Fw0yNTA5MTEyMTE3NTBaMCgwEgIBARcNMjIxMjE2MjExNzUwWjASAgECFw0yMjEy +MTYyMTE3NTBaoA4wDDAKBgNVHRQEAwIBAzANBgkqhkiG9w0BAQsFAAOCAQEAH2wc +UEKKVbxB9qkVtq2QUwq4c3GL3Q6PlQ+XbYIkCW3Vn1dHq8IQrd8nC2zUH8LVS1ZL +RAE+X9MIbNpblEAAR+LJ9ZM9xrAotkj/Mp572S1xXMRTE1CNx+jQbyjucaCKPtqa +xOGtpzbOh/8fMvEyyv+B2bjRyjl/CJB32kUjVkmtCJnvdSNfkpq0NO9csWhxDQYx +KF6xNFaj1keKuivivigp0GoSYF5ck30NVL/ucn8x5pqrVvw0RQbpvfw5HTeRd9La +lgGgDZ/PtiaYa/vZ71Ed30FsPGFcOIPkcVEdYldTiwsKsazfXCImtmdRYgZbl+2U +9EB+SE47/bd1QBfsSA== -----END X509 CRL----- diff --git a/examples/certs/crl/eccCliCRL.pem b/examples/certs/crl/eccCliCRL.pem index 0399310..0b51168 100644 --- a/examples/certs/crl/eccCliCRL.pem +++ b/examples/certs/crl/eccCliCRL.pem @@ -2,25 +2,25 @@ Certificate Revocation List (CRL): Version 2 (0x1) Signature Algorithm: ecdsa-with-SHA256 Issuer: C = US, ST = Oregon, L = Salem, O = Client ECC, OU = Fast, CN = www.wolfssl.com, emailAddress = info@wolfssl.com - Last Update: Feb 15 12:50:27 2022 GMT - Next Update: Nov 11 12:50:27 2024 GMT + Last Update: Dec 16 21:17:50 2022 GMT + Next Update: Sep 11 21:17:50 2025 GMT CRL extensions: X509v3 CRL Number: 7 Revoked Certificates: Serial Number: 02 - Revocation Date: Feb 15 12:50:27 2022 GMT + Revocation Date: Dec 16 21:17:50 2022 GMT Signature Algorithm: ecdsa-with-SHA256 - 30:46:02:21:00:c3:8c:e6:ec:41:6c:c8:c7:eb:97:dd:f0:5b: - be:bf:38:68:fe:0a:62:ff:c2:f9:23:db:98:41:0e:b1:64:b8: - 46:02:21:00:d7:d8:77:8c:e7:c7:8a:45:9f:fe:c0:4c:bd:f4: - 4c:aa:06:ea:5f:82:b6:8b:93:09:57:60:85:d4:82:09:7d:f8 + 30:46:02:21:00:de:52:96:3d:ab:bf:56:6f:1b:a5:61:f2:43: + 38:09:61:35:be:c3:8a:7b:17:77:2c:6a:a2:94:be:db:eb:c9: + 54:02:21:00:8f:38:ad:28:29:42:e6:5c:65:73:d8:2e:2c:b1: + ba:ec:15:d9:c6:fe:48:07:bd:d9:46:1a:24:0c:0a:da:e7:8c -----BEGIN X509 CRL----- MIIBPTCB4wIBATAKBggqhkjOPQQDAjCBjTELMAkGA1UEBhMCVVMxDzANBgNVBAgM Bk9yZWdvbjEOMAwGA1UEBwwFU2FsZW0xEzARBgNVBAoMCkNsaWVudCBFQ0MxDTAL BgNVBAsMBEZhc3QxGDAWBgNVBAMMD3d3dy53b2xmc3NsLmNvbTEfMB0GCSqGSIb3 -DQEJARYQaW5mb0B3b2xmc3NsLmNvbRcNMjIwMjE1MTI1MDI3WhcNMjQxMTExMTI1 -MDI3WjAUMBICAQIXDTIyMDIxNTEyNTAyN1qgDjAMMAoGA1UdFAQDAgEHMAoGCCqG -SM49BAMCA0kAMEYCIQDDjObsQWzIx+uX3fBbvr84aP4KYv/C+SPbmEEOsWS4RgIh -ANfYd4znx4pFn/7ATL30TKoG6l+CtouTCVdghdSCCX34 +DQEJARYQaW5mb0B3b2xmc3NsLmNvbRcNMjIxMjE2MjExNzUwWhcNMjUwOTExMjEx +NzUwWjAUMBICAQIXDTIyMTIxNjIxMTc1MFqgDjAMMAoGA1UdFAQDAgEHMAoGCCqG +SM49BAMCA0kAMEYCIQDeUpY9q79WbxulYfJDOAlhNb7DinsXdyxqopS+2+vJVAIh +AI84rSgpQuZcZXPYLiyxuuwV2cb+SAe92UYaJAwK2ueM -----END X509 CRL----- diff --git a/examples/certs/crl/eccSrvCRL.pem b/examples/certs/crl/eccSrvCRL.pem index 9d5ce3d..cf3b068 100644 --- a/examples/certs/crl/eccSrvCRL.pem +++ b/examples/certs/crl/eccSrvCRL.pem @@ -2,25 +2,25 @@ Certificate Revocation List (CRL): Version 2 (0x1) Signature Algorithm: ecdsa-with-SHA256 Issuer: C = US, ST = Washington, L = Seattle, O = Eliptic, OU = ECC, CN = www.wolfssl.com, emailAddress = info@wolfssl.com - Last Update: Feb 15 12:50:27 2022 GMT - Next Update: Nov 11 12:50:27 2024 GMT + Last Update: Dec 16 21:17:50 2022 GMT + Next Update: Sep 11 21:17:50 2025 GMT CRL extensions: X509v3 CRL Number: 8 Revoked Certificates: Serial Number: 02 - Revocation Date: Feb 15 12:50:27 2022 GMT + Revocation Date: Dec 16 21:17:50 2022 GMT Signature Algorithm: ecdsa-with-SHA256 - 30:46:02:21:00:df:77:ba:80:37:b2:31:55:06:a9:96:02:6f: - 53:1c:8f:a7:ab:69:43:37:e8:23:35:5a:42:db:71:cd:b7:7c: - a2:02:21:00:f1:cf:b2:64:30:18:a3:52:0d:04:ad:89:ae:a2: - 43:35:60:b4:90:0f:12:63:c7:87:7f:24:6e:c8:33:af:39:1e + 30:46:02:21:00:df:3b:2d:3e:14:df:73:4d:43:71:47:aa:5b: + a3:2f:19:8f:26:8c:e7:20:60:20:75:d7:4b:68:9e:d6:a9:f4: + 44:02:21:00:ec:32:6d:22:c4:bd:98:85:1b:66:9c:00:2b:5e: + c3:0f:cd:cc:54:a4:0a:2c:e9:bb:32:18:8f:27:d3:a3:d4:84 -----BEGIN X509 CRL----- MIIBPzCB5QIBATAKBggqhkjOPQQDAjCBjzELMAkGA1UEBhMCVVMxEzARBgNVBAgM Cldhc2hpbmd0b24xEDAOBgNVBAcMB1NlYXR0bGUxEDAOBgNVBAoMB0VsaXB0aWMx DDAKBgNVBAsMA0VDQzEYMBYGA1UEAwwPd3d3LndvbGZzc2wuY29tMR8wHQYJKoZI -hvcNAQkBFhBpbmZvQHdvbGZzc2wuY29tFw0yMjAyMTUxMjUwMjdaFw0yNDExMTEx -MjUwMjdaMBQwEgIBAhcNMjIwMjE1MTI1MDI3WqAOMAwwCgYDVR0UBAMCAQgwCgYI -KoZIzj0EAwIDSQAwRgIhAN93uoA3sjFVBqmWAm9THI+nq2lDN+gjNVpC23HNt3yi -AiEA8c+yZDAYo1INBK2JrqJDNWC0kA8SY8eHfyRuyDOvOR4= +hvcNAQkBFhBpbmZvQHdvbGZzc2wuY29tFw0yMjEyMTYyMTE3NTBaFw0yNTA5MTEy +MTE3NTBaMBQwEgIBAhcNMjIxMjE2MjExNzUwWqAOMAwwCgYDVR0UBAMCAQgwCgYI +KoZIzj0EAwIDSQAwRgIhAN87LT4U33NNQ3FHqlujLxmPJoznIGAgdddLaJ7WqfRE +AiEA7DJtIsS9mIUbZpwAK17DD83MVKQKLOm7MhiPJ9Oj1IQ= -----END X509 CRL----- diff --git a/examples/certs/server-cert.pem b/examples/certs/server-cert.pem index 75c6f83..de754a2 100644 --- a/examples/certs/server-cert.pem +++ b/examples/certs/server-cert.pem @@ -5,8 +5,8 @@ Certificate: Signature Algorithm: sha256WithRSAEncryption Issuer: C = US, ST = Montana, L = Bozeman, O = Sawtooth, OU = Consulting, CN = www.wolfssl.com, emailAddress = info@wolfssl.com Validity - Not Before: Feb 15 12:50:24 2022 GMT - Not After : Nov 11 12:50:24 2024 GMT + Not Before: Dec 16 21:17:49 2022 GMT + Not After : Sep 11 21:17:49 2025 GMT Subject: C = US, ST = Montana, L = Bozeman, O = wolfSSL, OU = Support, CN = www.wolfssl.com, emailAddress = info@wolfssl.com Subject Public Key Info: Public Key Algorithm: rsaEncryption @@ -37,7 +37,7 @@ Certificate: X509v3 Authority Key Identifier: keyid:27:8E:67:11:74:C3:26:1D:3F:ED:33:63:B3:A4:D8:1D:30:E5:E8:D5 DirName:/C=US/ST=Montana/L=Bozeman/O=Sawtooth/OU=Consulting/CN=www.wolfssl.com/emailAddress=info@wolfssl.com - serial:26:8C:93:F9:F9:F4:1E:B3:01:72:94:55:67:6D:E2:F8:3D:DA:E9:F4 + serial:2C:80:CE:DB:47:9D:07:66:92:3D:68:D7:CA:AC:90:4F:CA:69:41:4B X509v3 Basic Constraints: CA:TRUE @@ -46,27 +46,27 @@ Certificate: X509v3 Extended Key Usage: TLS Web Server Authentication, TLS Web Client Authentication Signature Algorithm: sha256WithRSAEncryption - 4b:88:54:a8:57:f0:62:4d:b3:c5:8c:d2:02:0a:89:19:45:63: - 8e:37:5c:a9:f7:8c:c5:7c:9d:19:b4:5d:b6:a4:29:4d:97:da: - 6e:3c:27:ec:02:5c:fb:e2:93:6f:b6:1a:dc:5e:25:1f:be:ab: - 6f:37:ff:d6:98:67:7c:f7:53:84:3b:e6:f7:22:ef:52:b0:8f: - 9d:4e:2f:41:2a:7d:2f:f8:02:1e:f5:cd:9a:b2:68:68:d6:ef: - ed:6a:96:a0:84:6f:0c:5e:7b:44:f9:6f:d0:00:6f:dd:83:6a: - d9:d9:17:9d:32:9a:ea:4b:87:f9:12:45:3e:b8:de:20:fe:f4: - b8:3f:f4:99:61:a6:2b:97:1b:7c:a0:90:cf:e9:3b:cd:94:ce: - 85:df:fb:6a:2b:67:5b:8c:28:de:e6:0b:4b:68:5b:b3:4a:3e: - 10:3b:0c:d8:c8:f1:3e:3d:cc:2f:16:76:24:43:b6:3b:fd:cf: - 2f:07:0f:15:31:59:5e:cd:84:a9:82:05:1f:0c:97:56:5d:90: - 49:bd:84:47:ec:07:b9:cf:fa:a0:56:9b:ae:e2:a9:96:b2:62: - 02:4a:fa:42:d5:23:dc:1c:6b:5c:41:3d:f2:73:e8:ed:32:93: - cc:f7:02:5a:b4:be:84:ca:73:26:9f:03:2c:b3:74:96:20:7e: - 12:ea:e5:ef + b9:10:f0:be:fe:c8:67:5e:7d:0f:36:33:c7:17:2a:01:c4:bb: + 74:83:4c:bc:bb:e2:ba:92:82:3a:d9:2d:8c:0e:e3:75:1b:c0: + 14:aa:40:1e:a8:11:7d:94:9c:3d:74:7a:3b:16:7b:d8:9d:f0: + e8:7d:1d:fa:3b:14:42:20:e3:05:a3:fd:b1:0c:f1:2a:c4:00: + 50:8d:1e:97:93:6a:de:82:13:24:9e:2b:fa:08:85:e3:4f:40: + fd:63:c7:3d:e9:bd:6f:7c:03:98:85:fe:b4:51:5d:7f:8c:83: + b3:ad:4a:88:e9:f3:4c:33:84:77:d3:02:35:59:e3:4e:64:a1: + b7:bb:fb:f8:fb:14:2a:ae:36:bf:d9:82:e7:cb:98:48:16:c8: + 81:d6:a0:f1:74:14:e3:74:4a:72:4a:f1:6f:dd:be:86:1e:20: + f3:05:16:83:1f:aa:7c:59:35:97:24:b8:27:b7:56:9f:30:2e: + 90:e0:19:e0:21:ca:9d:3f:da:99:07:94:79:49:53:14:5c:a2: + 2c:56:5b:b2:55:68:5c:1f:91:58:9a:cd:53:b5:ea:63:5a:72: + 49:41:cc:76:9f:88:35:86:0d:60:5d:e5:91:bd:ac:6f:cf:d5: + 92:27:72:4a:21:f4:58:98:8e:3b:d2:29:e6:ee:fa:e6:b0:6c: + 8b:1e:e0:54 -----BEGIN CERTIFICATE----- MIIE6DCCA9CgAwIBAgIBATANBgkqhkiG9w0BAQsFADCBlDELMAkGA1UEBhMCVVMx EDAOBgNVBAgMB01vbnRhbmExEDAOBgNVBAcMB0JvemVtYW4xETAPBgNVBAoMCFNh d3Rvb3RoMRMwEQYDVQQLDApDb25zdWx0aW5nMRgwFgYDVQQDDA93d3cud29sZnNz -bC5jb20xHzAdBgkqhkiG9w0BCQEWEGluZm9Ad29sZnNzbC5jb20wHhcNMjIwMjE1 -MTI1MDI0WhcNMjQxMTExMTI1MDI0WjCBkDELMAkGA1UEBhMCVVMxEDAOBgNVBAgM +bC5jb20xHzAdBgkqhkiG9w0BCQEWEGluZm9Ad29sZnNzbC5jb20wHhcNMjIxMjE2 +MjExNzQ5WhcNMjUwOTExMjExNzQ5WjCBkDELMAkGA1UEBhMCVVMxEDAOBgNVBAgM B01vbnRhbmExEDAOBgNVBAcMB0JvemVtYW4xEDAOBgNVBAoMB3dvbGZTU0wxEDAO BgNVBAsMB1N1cHBvcnQxGDAWBgNVBAMMD3d3dy53b2xmc3NsLmNvbTEfMB0GCSqG SIb3DQEJARYQaW5mb0B3b2xmc3NsLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEP @@ -80,26 +80,26 @@ BBSzETLJkpiE4sn40DtuA0LKHw6OPDCB1AYDVR0jBIHMMIHJgBQnjmcRdMMmHT/t M2OzpNgdMOXo1aGBmqSBlzCBlDELMAkGA1UEBhMCVVMxEDAOBgNVBAgMB01vbnRh bmExEDAOBgNVBAcMB0JvemVtYW4xETAPBgNVBAoMCFNhd3Rvb3RoMRMwEQYDVQQL DApDb25zdWx0aW5nMRgwFgYDVQQDDA93d3cud29sZnNzbC5jb20xHzAdBgkqhkiG -9w0BCQEWEGluZm9Ad29sZnNzbC5jb22CFCaMk/n59B6zAXKUVWdt4vg92un0MAwG +9w0BCQEWEGluZm9Ad29sZnNzbC5jb22CFCyAzttHnQdmkj1o18qskE/KaUFLMAwG A1UdEwQFMAMBAf8wHAYDVR0RBBUwE4ILZXhhbXBsZS5jb22HBH8AAAEwHQYDVR0l -BBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCMA0GCSqGSIb3DQEBCwUAA4IBAQBLiFSo -V/BiTbPFjNICCokZRWOON1yp94zFfJ0ZtF22pClNl9puPCfsAlz74pNvthrcXiUf -vqtvN//WmGd891OEO+b3Iu9SsI+dTi9BKn0v+AIe9c2asmho1u/tapaghG8MXntE -+W/QAG/dg2rZ2RedMprqS4f5EkU+uN4g/vS4P/SZYaYrlxt8oJDP6TvNlM6F3/tq -K2dbjCje5gtLaFuzSj4QOwzYyPE+PcwvFnYkQ7Y7/c8vBw8VMVlezYSpggUfDJdW -XZBJvYRH7Ae5z/qgVpuu4qmWsmICSvpC1SPcHGtcQT3yc+jtMpPM9wJatL6EynMm -nwMss3SWIH4S6uXv +BBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCMA0GCSqGSIb3DQEBCwUAA4IBAQC5EPC+ +/shnXn0PNjPHFyoBxLt0g0y8u+K6koI62S2MDuN1G8AUqkAeqBF9lJw9dHo7FnvY +nfDofR36OxRCIOMFo/2xDPEqxABQjR6Xk2reghMkniv6CIXjT0D9Y8c96b1vfAOY +hf60UV1/jIOzrUqI6fNMM4R30wI1WeNOZKG3u/v4+xQqrja/2YLny5hIFsiB1qDx +dBTjdEpySvFv3b6GHiDzBRaDH6p8WTWXJLgnt1afMC6Q4BngIcqdP9qZB5R5SVMU +XKIsVluyVWhcH5FYms1TtepjWnJJQcx2n4g1hg1gXeWRvaxvz9WSJ3JKIfRYmI47 +0inm7vrmsGyLHuBU -----END CERTIFICATE----- Certificate: Data: Version: 3 (0x2) Serial Number: - 26:8c:93:f9:f9:f4:1e:b3:01:72:94:55:67:6d:e2:f8:3d:da:e9:f4 + 2c:80:ce:db:47:9d:07:66:92:3d:68:d7:ca:ac:90:4f:ca:69:41:4b Signature Algorithm: sha256WithRSAEncryption Issuer: C = US, ST = Montana, L = Bozeman, O = Sawtooth, OU = Consulting, CN = www.wolfssl.com, emailAddress = info@wolfssl.com Validity - Not Before: Feb 15 12:50:24 2022 GMT - Not After : Nov 11 12:50:24 2024 GMT + Not Before: Dec 16 21:17:49 2022 GMT + Not After : Sep 11 21:17:49 2025 GMT Subject: C = US, ST = Montana, L = Bozeman, O = Sawtooth, OU = Consulting, CN = www.wolfssl.com, emailAddress = info@wolfssl.com Subject Public Key Info: Public Key Algorithm: rsaEncryption @@ -130,7 +130,7 @@ Certificate: X509v3 Authority Key Identifier: keyid:27:8E:67:11:74:C3:26:1D:3F:ED:33:63:B3:A4:D8:1D:30:E5:E8:D5 DirName:/C=US/ST=Montana/L=Bozeman/O=Sawtooth/OU=Consulting/CN=www.wolfssl.com/emailAddress=info@wolfssl.com - serial:26:8C:93:F9:F9:F4:1E:B3:01:72:94:55:67:6D:E2:F8:3D:DA:E9:F4 + serial:2C:80:CE:DB:47:9D:07:66:92:3D:68:D7:CA:AC:90:4F:CA:69:41:4B X509v3 Basic Constraints: CA:TRUE @@ -139,27 +139,27 @@ Certificate: X509v3 Extended Key Usage: TLS Web Server Authentication, TLS Web Client Authentication Signature Algorithm: sha256WithRSAEncryption - 62:e4:1b:28:3c:9d:d2:60:a9:55:be:6a:f6:20:f2:da:e8:a1: - 1a:97:b1:90:77:82:ed:c7:77:29:53:33:18:10:62:e0:bd:93: - 1b:d2:d6:a1:80:43:1d:64:f1:42:92:ec:b7:b8:f0:6b:da:59: - 83:f4:b8:87:e6:fc:70:21:ea:62:32:70:68:14:0e:dc:b4:f1: - 66:e2:6e:ab:d2:72:6f:da:df:71:f6:3d:27:97:7d:be:e1:d1: - ac:16:ad:d7:4f:aa:9d:0c:1e:6e:a9:5e:7d:57:5b:3c:c7:6d: - d2:f2:5c:c3:dc:3d:36:99:8e:ab:c0:7f:13:a5:f4:67:8b:e2: - a6:51:31:f1:03:91:00:a8:c4:c5:1d:7f:35:62:b8:1d:a0:a5: - ab:ec:32:68:ee:f3:ca:48:16:9f:f4:1e:7e:ea:fa:b0:86:15: - 52:36:6c:4b:58:44:a7:eb:20:78:6e:7e:e8:00:40:ac:98:d8: - 53:f3:13:4b:b8:98:66:50:63:ed:af:e5:a4:f6:c9:90:1c:84: - 0a:09:45:2f:a1:e1:37:63:b5:43:8c:a0:2e:7f:c4:d4:e1:ae: - b7:b9:45:13:f8:70:d5:79:06:4f:82:83:4b:98:d7:56:47:64: - 9a:6a:6d:8e:7a:9d:ef:83:0f:6b:75:0e:47:22:92:f3:b4:b2: - 84:61:1f:1c + ae:b0:a4:35:8e:8a:1b:a6:eb:b3:a2:57:cf:3a:1f:dc:6e:bc: + d2:d0:a6:4a:8f:88:0a:6e:74:d5:d1:7c:d1:44:b1:d4:3b:17: + 03:09:5a:46:ed:08:08:cf:f1:fd:20:07:67:c0:97:ec:35:f3: + 75:ca:20:61:98:3e:f5:4d:be:e6:9d:75:1e:e4:03:ad:8c:a6: + 1e:3d:ec:e4:1a:92:5b:f9:a3:ad:83:ca:4f:cd:aa:38:bb:6e: + ae:ad:fa:a7:46:f1:8b:73:ec:09:23:bc:f2:18:e5:b7:92:86: + 3e:a4:75:60:c7:3d:0f:3f:83:00:c3:06:08:9c:d1:54:d6:ba: + 6d:95:3d:34:a1:be:24:91:cc:20:03:11:5b:72:1c:d4:65:d0: + 11:88:75:26:04:26:ef:66:70:e6:3b:38:87:9c:53:71:1b:09: + 51:70:50:99:4c:31:0c:62:44:57:30:60:04:fc:12:2c:a3:24: + b4:f7:11:d5:0e:b5:21:0b:ed:86:11:67:4d:36:fa:57:a0:59: + 55:21:b3:6d:e4:77:5e:ec:7e:f0:09:13:8e:99:98:b2:e1:82: + b6:4b:3e:0f:41:a6:0c:cd:49:99:7e:e4:8a:cb:37:ed:53:cf: + 86:5d:a9:26:a8:e5:01:25:5a:b4:bc:25:35:f1:fa:5a:5c:ce: + d4:b8:9a:2c -----BEGIN CERTIFICATE----- -MIIE/zCCA+egAwIBAgIUJoyT+fn0HrMBcpRVZ23i+D3a6fQwDQYJKoZIhvcNAQEL +MIIE/zCCA+egAwIBAgIULIDO20edB2aSPWjXyqyQT8ppQUswDQYJKoZIhvcNAQEL BQAwgZQxCzAJBgNVBAYTAlVTMRAwDgYDVQQIDAdNb250YW5hMRAwDgYDVQQHDAdC b3plbWFuMREwDwYDVQQKDAhTYXd0b290aDETMBEGA1UECwwKQ29uc3VsdGluZzEY MBYGA1UEAwwPd3d3LndvbGZzc2wuY29tMR8wHQYJKoZIhvcNAQkBFhBpbmZvQHdv -bGZzc2wuY29tMB4XDTIyMDIxNTEyNTAyNFoXDTI0MTExMTEyNTAyNFowgZQxCzAJ +bGZzc2wuY29tMB4XDTIyMTIxNjIxMTc0OVoXDTI1MDkxMTIxMTc0OVowgZQxCzAJ BgNVBAYTAlVTMRAwDgYDVQQIDAdNb250YW5hMRAwDgYDVQQHDAdCb3plbWFuMREw DwYDVQQKDAhTYXd0b290aDETMBEGA1UECwwKQ29uc3VsdGluZzEYMBYGA1UEAwwP d3d3LndvbGZzc2wuY29tMR8wHQYJKoZIhvcNAQkBFhBpbmZvQHdvbGZzc2wuY29t @@ -174,12 +174,12 @@ BgNVHSMEgcwwgcmAFCeOZxF0wyYdP+0zY7Ok2B0w5ejVoYGapIGXMIGUMQswCQYD VQQGEwJVUzEQMA4GA1UECAwHTW9udGFuYTEQMA4GA1UEBwwHQm96ZW1hbjERMA8G A1UECgwIU2F3dG9vdGgxEzARBgNVBAsMCkNvbnN1bHRpbmcxGDAWBgNVBAMMD3d3 dy53b2xmc3NsLmNvbTEfMB0GCSqGSIb3DQEJARYQaW5mb0B3b2xmc3NsLmNvbYIU -JoyT+fn0HrMBcpRVZ23i+D3a6fQwDAYDVR0TBAUwAwEB/zAcBgNVHREEFTATggtl +LIDO20edB2aSPWjXyqyQT8ppQUswDAYDVR0TBAUwAwEB/zAcBgNVHREEFTATggtl eGFtcGxlLmNvbYcEfwAAATAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIw -DQYJKoZIhvcNAQELBQADggEBAGLkGyg8ndJgqVW+avYg8trooRqXsZB3gu3HdylT -MxgQYuC9kxvS1qGAQx1k8UKS7Le48GvaWYP0uIfm/HAh6mIycGgUDty08WbibqvS -cm/a33H2PSeXfb7h0awWrddPqp0MHm6pXn1XWzzHbdLyXMPcPTaZjqvAfxOl9GeL -4qZRMfEDkQCoxMUdfzViuB2gpavsMmju88pIFp/0Hn7q+rCGFVI2bEtYRKfrIHhu -fugAQKyY2FPzE0u4mGZQY+2v5aT2yZAchAoJRS+h4TdjtUOMoC5/xNThrre5RRP4 -cNV5Bk+Cg0uY11ZHZJpqbY56ne+DD2t1DkcikvO0soRhHxw= +DQYJKoZIhvcNAQELBQADggEBAK6wpDWOihum67OiV886H9xuvNLQpkqPiApudNXR +fNFEsdQ7FwMJWkbtCAjP8f0gB2fAl+w183XKIGGYPvVNvuaddR7kA62Mph497OQa +klv5o62Dyk/Nqji7bq6t+qdG8Ytz7AkjvPIY5beShj6kdWDHPQ8/gwDDBgic0VTW +um2VPTShviSRzCADEVtyHNRl0BGIdSYEJu9mcOY7OIecU3EbCVFwUJlMMQxiRFcw +YAT8EiyjJLT3EdUOtSEL7YYRZ002+legWVUhs23kd17sfvAJE46ZmLLhgrZLPg9B +pgzNSZl+5IrLN+1Tz4ZdqSao5QElWrS8JTXx+lpcztS4miw= -----END CERTIFICATE----- diff --git a/examples/certs/server-ecc.pem b/examples/certs/server-ecc.pem index 24d3d40..d2f48f9 100644 --- a/examples/certs/server-ecc.pem +++ b/examples/certs/server-ecc.pem @@ -5,8 +5,8 @@ Certificate: Signature Algorithm: ecdsa-with-SHA256 Issuer: C = US, ST = Washington, L = Seattle, O = wolfSSL, OU = Development, CN = www.wolfssl.com, emailAddress = info@wolfssl.com Validity - Not Before: Feb 15 12:50:24 2022 GMT - Not After : Nov 11 12:50:24 2024 GMT + Not Before: Dec 16 21:17:49 2022 GMT + Not After : Sep 11 21:17:49 2025 GMT Subject: C = US, ST = Washington, L = Seattle, O = Eliptic, OU = ECC, CN = www.wolfssl.com, emailAddress = info@wolfssl.com Subject Public Key Info: Public Key Algorithm: id-ecPublicKey @@ -34,16 +34,16 @@ Certificate: Netscape Cert Type: SSL Server Signature Algorithm: ecdsa-with-SHA256 - 30:45:02:20:5b:9d:f4:69:17:88:c0:13:34:3d:81:81:dc:fb: - 27:7c:a0:63:00:87:d5:48:e1:9c:57:c9:01:c1:d2:5f:30:58: - 02:21:00:89:93:a5:b6:04:de:4d:3d:98:ed:0b:ce:3a:74:3e: - 6c:f1:80:1f:28:d8:ee:78:af:da:8a:3b:b4:27:38:e2:b1 + 30:45:02:21:00:cf:3a:17:97:d4:be:7c:50:e1:be:1b:53:95: + 7b:a3:b8:c6:73:c4:34:e0:73:5a:db:3e:cb:3a:b6:a8:f1:cd: + bf:02:20:2b:e6:f9:65:b2:ab:0f:bb:2b:36:5c:cc:2e:19:a9: + 59:1c:6f:6f:ce:9b:7a:e6:5b:65:31:33:80:05:cb:7c:96 -----BEGIN CERTIFICATE----- MIICoTCCAkegAwIBAgIBAzAKBggqhkjOPQQDAjCBlzELMAkGA1UEBhMCVVMxEzAR BgNVBAgMCldhc2hpbmd0b24xEDAOBgNVBAcMB1NlYXR0bGUxEDAOBgNVBAoMB3dv bGZTU0wxFDASBgNVBAsMC0RldmVsb3BtZW50MRgwFgYDVQQDDA93d3cud29sZnNz -bC5jb20xHzAdBgkqhkiG9w0BCQEWEGluZm9Ad29sZnNzbC5jb20wHhcNMjIwMjE1 -MTI1MDI0WhcNMjQxMTExMTI1MDI0WjCBjzELMAkGA1UEBhMCVVMxEzARBgNVBAgM +bC5jb20xHzAdBgkqhkiG9w0BCQEWEGluZm9Ad29sZnNzbC5jb20wHhcNMjIxMjE2 +MjExNzQ5WhcNMjUwOTExMjExNzQ5WjCBjzELMAkGA1UEBhMCVVMxEzARBgNVBAgM Cldhc2hpbmd0b24xEDAOBgNVBAcMB1NlYXR0bGUxEDAOBgNVBAoMB0VsaXB0aWMx DDAKBgNVBAsMA0VDQzEYMBYGA1UEAwwPd3d3LndvbGZzc2wuY29tMR8wHQYJKoZI hvcNAQkBFhBpbmZvQHdvbGZzc2wuY29tMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcD @@ -51,7 +51,7 @@ QgAEuzOsTCdQSsZKpQTDPN6fNttyLc6U6iv6yyAJOSwW6GEC6a9N0wKTmjFbl5Ih f/DPGNqREQI0huggWDMLgDSJ2KOBiTCBhjAdBgNVHQ4EFgQUXV0m76x+NvmbdhUr SiUCI++yiTAwHwYDVR0jBBgwFoAUVo6aw/BC3hi5RVVu+ZPP6sPzpSEwDAYDVR0T AQH/BAIwADAOBgNVHQ8BAf8EBAMCA6gwEwYDVR0lBAwwCgYIKwYBBQUHAwEwEQYJ -YIZIAYb4QgEBBAQDAgZAMAoGCCqGSM49BAMCA0gAMEUCIFud9GkXiMATND2Bgdz7 -J3ygYwCH1UjhnFfJAcHSXzBYAiEAiZOltgTeTT2Y7QvOOnQ+bPGAHyjY7niv2oo7 -tCc44rE= +YIZIAYb4QgEBBAQDAgZAMAoGCCqGSM49BAMCA0gAMEUCIQDPOheX1L58UOG+G1OV +e6O4xnPENOBzWts+yzq2qPHNvwIgK+b5ZbKrD7srNlzMLhmpWRxvb86beuZbZTEz +gAXLfJY= -----END CERTIFICATE----- diff --git a/examples/certs/update-certs.sh b/examples/certs/update-certs.sh index 2e1ac4a..c113aeb 100755 --- a/examples/certs/update-certs.sh +++ b/examples/certs/update-certs.sh @@ -34,9 +34,12 @@ certList=( "ca-ecc-cert.pem" "ca-ecc-key.pem" "ca-key.pem" + "ca-key.der" "client-cert.der" "client-cert.pem" "client-key.pem" + "client-key.der" + "client-keyPub.der" "dh2048.pem" "ecc-client-key.pem" "ecc-key.pem" @@ -66,14 +69,30 @@ do fi done +# Generate ca-keyPkcs8.der, used by examples/X509CertificateGeneration.java +openssl pkcs8 -topk8 -inform DER -outform DER -in ca-key.der -out ca-keyPkcs8.der -nocrypt +if [ $? -ne 0 ]; then + printf "Failed to generate ca-keyPkcs8.der" + exit 1 +fi +printf "Generated ca-keyPkcs8.der\n" + # Remove text info from intermediate certs, causes issues on Android (WRONG TAG) printf "Removing text info from intermediate certs\n" -sed -i -n '/-----BEGIN CERTIFICATE-----/,$p' intermediate/ca-int2-cert.pem -sed -i -n '/-----BEGIN CERTIFICATE-----/,$p' intermediate/ca-int2-ecc-cert.pem -sed -i -n '/-----BEGIN CERTIFICATE-----/,$p' intermediate/ca-int-cert.pem -sed -i -n '/-----BEGIN CERTIFICATE-----/,$p' intermediate/ca-int-ecc-cert.pem -sed -i -n '/-----BEGIN CERTIFICATE-----/,$p' intermediate/server-int-cert.pem -sed -i -n '/-----BEGIN CERTIFICATE-----/,$p' intermediate/server-int-ecc-cert.pem +sed -i.bak -n '/-----BEGIN CERTIFICATE-----/,$p' intermediate/ca-int2-cert.pem +sed -i.bak -n '/-----BEGIN CERTIFICATE-----/,$p' intermediate/ca-int2-ecc-cert.pem +sed -i.bak -n '/-----BEGIN CERTIFICATE-----/,$p' intermediate/ca-int-cert.pem +sed -i.bak -n '/-----BEGIN CERTIFICATE-----/,$p' intermediate/ca-int-ecc-cert.pem +sed -i.bak -n '/-----BEGIN CERTIFICATE-----/,$p' intermediate/server-int-cert.pem +sed -i.bak -n '/-----BEGIN CERTIFICATE-----/,$p' intermediate/server-int-ecc-cert.pem + +# Remvoe sed .bak files +rm intermediate/ca-int2-cert.pem.bak +rm intermediate/ca-int2-ecc-cert.pem.bak +rm intermediate/ca-int-cert.pem.bak +rm intermediate/ca-int-ecc-cert.pem.bak +rm intermediate/server-int-cert.pem.bak +rm intermediate/server-int-ecc-cert.pem.bak printf "Finished successfully\n" diff --git a/examples/provider/all.jks b/examples/provider/all.jks index 8773fb8..46376f2 100644 Binary files a/examples/provider/all.jks and b/examples/provider/all.jks differ diff --git a/examples/provider/all_mixed.jks b/examples/provider/all_mixed.jks index 706db39..bec480a 100644 Binary files a/examples/provider/all_mixed.jks and b/examples/provider/all_mixed.jks differ diff --git a/examples/provider/ca-client.jks b/examples/provider/ca-client.jks index 7f86494..7fb9c55 100644 Binary files a/examples/provider/ca-client.jks and b/examples/provider/ca-client.jks differ diff --git a/examples/provider/ca-server.jks b/examples/provider/ca-server.jks index e4673d7..ccfc2be 100644 Binary files a/examples/provider/ca-server.jks and b/examples/provider/ca-server.jks differ diff --git a/examples/provider/cacerts.jks b/examples/provider/cacerts.jks index bc32113..d05f055 100644 Binary files a/examples/provider/cacerts.jks and b/examples/provider/cacerts.jks differ diff --git a/examples/provider/client-ecc.jks b/examples/provider/client-ecc.jks index 8419abb..df96030 100644 Binary files a/examples/provider/client-ecc.jks and b/examples/provider/client-ecc.jks differ diff --git a/examples/provider/client-rsa-1024.jks b/examples/provider/client-rsa-1024.jks index b9a3447..da53582 100644 Binary files a/examples/provider/client-rsa-1024.jks and b/examples/provider/client-rsa-1024.jks differ diff --git a/examples/provider/client-rsa.jks b/examples/provider/client-rsa.jks index 14328f2..dff623f 100644 Binary files a/examples/provider/client-rsa.jks and b/examples/provider/client-rsa.jks differ diff --git a/examples/provider/client.jks b/examples/provider/client.jks index d047734..5ef402c 100644 Binary files a/examples/provider/client.jks and b/examples/provider/client.jks differ diff --git a/examples/provider/server-ecc.jks b/examples/provider/server-ecc.jks index 77cda05..118ffb8 100644 Binary files a/examples/provider/server-ecc.jks and b/examples/provider/server-ecc.jks differ diff --git a/examples/provider/server-rsa-1024.jks b/examples/provider/server-rsa-1024.jks index 316805c..f674bea 100644 Binary files a/examples/provider/server-rsa-1024.jks and b/examples/provider/server-rsa-1024.jks differ diff --git a/examples/provider/server-rsa.jks b/examples/provider/server-rsa.jks index fdae9ff..f2b99fc 100644 Binary files a/examples/provider/server-rsa.jks and b/examples/provider/server-rsa.jks differ diff --git a/examples/provider/server.jks b/examples/provider/server.jks index b5f1268..23d05ee 100644 Binary files a/examples/provider/server.jks and b/examples/provider/server.jks differ diff --git a/java.sh b/java.sh index b5fa16e..cfbc258 100755 --- a/java.sh +++ b/java.sh @@ -116,8 +116,9 @@ gcc -Wall -c $fpic $cflags ./native/com_wolfssl_wolfcrypt_ECC.c -o ./native/com_ gcc -Wall -c $fpic $cflags ./native/com_wolfssl_wolfcrypt_EccKey.c -o ./native/com_wolfssl_wolfcrypt_EccKey.o $javaIncludes gcc -Wall -c $fpic $cflags ./native/com_wolfssl_WolfSSLCertManager.c -o ./native/com_wolfssl_WolfSSLCertManager.o $javaIncludes gcc -Wall -c $fpic $cflags ./native/com_wolfssl_WolfSSLCertificate.c -o ./native/com_wolfssl_WolfSSLCertificate.o $javaIncludes +gcc -Wall -c $fpic $cflags ./native/com_wolfssl_WolfSSLX509Name.c -o ./native/com_wolfssl_WolfSSLX509Name.o $javaIncludes gcc -Wall -c $fpic $cflags ./native/com_wolfssl_WolfSSLX509StoreCtx.c -o ./native/com_wolfssl_WolfSSLX509StoreCtx.o $javaIncludes -gcc -Wall $javaLibs $cflags -o ./lib/$jniLibName ./native/com_wolfssl_WolfSSL.o ./native/com_wolfssl_WolfSSLSession.o ./native/com_wolfssl_WolfSSLContext.o ./native/com_wolfssl_wolfcrypt_RSA.o ./native/com_wolfssl_wolfcrypt_ECC.o ./native/com_wolfssl_wolfcrypt_EccKey.o ./native/com_wolfssl_WolfSSLCertManager.o ./native/com_wolfssl_WolfSSLCertificate.o ./native/com_wolfssl_WolfSSLX509StoreCtx.o -L$WOLFSSL_INSTALL_DIR/lib -L$WOLFSSL_INSTALL_DIR/lib64 -l$WOLFSSL_LIBNAME +gcc -Wall $javaLibs $cflags -o ./lib/$jniLibName ./native/com_wolfssl_WolfSSL.o ./native/com_wolfssl_WolfSSLSession.o ./native/com_wolfssl_WolfSSLContext.o ./native/com_wolfssl_wolfcrypt_RSA.o ./native/com_wolfssl_wolfcrypt_ECC.o ./native/com_wolfssl_wolfcrypt_EccKey.o ./native/com_wolfssl_WolfSSLCertManager.o ./native/com_wolfssl_WolfSSLCertificate.o ./native/com_wolfssl_WolfSSLX509Name.o ./native/com_wolfssl_WolfSSLX509StoreCtx.o -L$WOLFSSL_INSTALL_DIR/lib -L$WOLFSSL_INSTALL_DIR/lib64 -l$WOLFSSL_LIBNAME if [ $? != 0 ]; then echo "Error creating native JNI library" exit 1 diff --git a/native/com_wolfssl_WolfSSL.c b/native/com_wolfssl_WolfSSL.c index f46e740..3d315a2 100644 --- a/native/com_wolfssl_WolfSSL.c +++ b/native/com_wolfssl_WolfSSL.c @@ -1147,6 +1147,12 @@ JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSL_getHmacMaxSize return WC_MAX_DIGEST_SIZE; } +JNIEXPORT jlong JNICALL Java_com_wolfssl_WolfSSL_getLibVersionHex + (JNIEnv* jenv, jclass jcl) +{ + return (jlong)wolfSSL_lib_version_hex(); +} + JNIEXPORT jstring JNICALL Java_com_wolfssl_WolfSSL_getEnabledCipherSuites (JNIEnv* jenv, jclass jcl) { diff --git a/native/com_wolfssl_WolfSSL.h b/native/com_wolfssl_WolfSSL.h index a6589d4..c4b71e3 100644 --- a/native/com_wolfssl_WolfSSL.h +++ b/native/com_wolfssl_WolfSSL.h @@ -199,6 +199,26 @@ extern "C" { #define com_wolfssl_WolfSSL_ECDSAk 518L #undef com_wolfssl_WolfSSL_ED25519k #define com_wolfssl_WolfSSL_ED25519k 256L +#undef com_wolfssl_WolfSSL_ASN_OTHER_TYPE +#define com_wolfssl_WolfSSL_ASN_OTHER_TYPE 0L +#undef com_wolfssl_WolfSSL_ASN_RFC822_TYPE +#define com_wolfssl_WolfSSL_ASN_RFC822_TYPE 1L +#undef com_wolfssl_WolfSSL_ASN_DNS_TYPE +#define com_wolfssl_WolfSSL_ASN_DNS_TYPE 2L +#undef com_wolfssl_WolfSSL_ASN_DIR_TYPE +#define com_wolfssl_WolfSSL_ASN_DIR_TYPE 4L +#undef com_wolfssl_WolfSSL_ASN_URI_TYPE +#define com_wolfssl_WolfSSL_ASN_URI_TYPE 6L +#undef com_wolfssl_WolfSSL_ASN_IP_TYPE +#define com_wolfssl_WolfSSL_ASN_IP_TYPE 7L +#undef com_wolfssl_WolfSSL_NID_key_usage +#define com_wolfssl_WolfSSL_NID_key_usage 129L +#undef com_wolfssl_WolfSSL_NID_subject_alt_name +#define com_wolfssl_WolfSSL_NID_subject_alt_name 131L +#undef com_wolfssl_WolfSSL_NID_basic_constraints +#define com_wolfssl_WolfSSL_NID_basic_constraints 133L +#undef com_wolfssl_WolfSSL_NID_ext_key_usage +#define com_wolfssl_WolfSSL_NID_ext_key_usage 151L #undef com_wolfssl_WolfSSL_WOLFSSL_NAMED_GROUP_INVALID #define com_wolfssl_WolfSSL_WOLFSSL_NAMED_GROUP_INVALID 0L #undef com_wolfssl_WolfSSL_WOLFSSL_ECC_SECT163K1 @@ -729,6 +749,14 @@ JNIEXPORT jbyteArray JNICALL Java_com_wolfssl_WolfSSL_x509_1getDer JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSL_getHmacMaxSize (JNIEnv *, jclass); +/* + * Class: com_wolfssl_WolfSSL + * Method: getLibVersionHex + * Signature: ()J + */ +JNIEXPORT jlong JNICALL Java_com_wolfssl_WolfSSL_getLibVersionHex + (JNIEnv *, jclass); + /* * Class: com_wolfssl_WolfSSL * Method: isEnabledCRL diff --git a/native/com_wolfssl_WolfSSLCertificate.c b/native/com_wolfssl_WolfSSLCertificate.c index fa410cb..d9863b7 100644 --- a/native/com_wolfssl_WolfSSLCertificate.c +++ b/native/com_wolfssl_WolfSSLCertificate.c @@ -38,6 +38,672 @@ #include "com_wolfssl_globals.h" #include "com_wolfssl_WolfSSLCertificate.h" +JNIEXPORT jlong JNICALL Java_com_wolfssl_WolfSSLCertificate_X509_1new + (JNIEnv* jenv, jclass jcl) +{ + WOLFSSL_X509* x509 = NULL; + (void)jcl; + + if (jenv == NULL) { + return 0; + } + + x509 = wolfSSL_X509_new(); + if (x509 == NULL) { + return 0; + } + + return (jlong)(uintptr_t)x509; +} + +JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLCertificate_X509_1set_1subject_1name + (JNIEnv* jenv, jclass jcl, jlong x509Ptr, jlong x509NamePtr) +{ +#if !defined(WOLFCRYPT_ONLY) && !defined(NO_CERTS) && \ + (defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)) + WOLFSSL_X509* x509 = (WOLFSSL_X509*)(uintptr_t)x509Ptr; + WOLFSSL_X509_NAME* x509Name = (WOLFSSL_X509_NAME*)(uintptr_t)x509NamePtr; + int ret = WOLFSSL_FAILURE; + (void)jcl; + + if (jenv == NULL || x509 == NULL || x509Name == NULL) { + return ret; + } + + ret = wolfSSL_X509_set_subject_name(x509, x509Name); + + return ret; +#else + (void)jenv; + (void)jcl; + (void)x509Ptr; + (void)x509NamePtr; + return (jint)NOT_COMPILED_IN; +#endif +} + +JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLCertificate_X509_1set_1issuer_1name + (JNIEnv* jenv, jclass jcl, jlong x509Ptr, jlong x509NamePtr) +{ +#if !defined(WOLFCRYPT_ONLY) && !defined(NO_CERTS) && \ + (defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)) + WOLFSSL_X509* x509 = (WOLFSSL_X509*)(uintptr_t)x509Ptr; + WOLFSSL_X509_NAME* x509Name = (WOLFSSL_X509_NAME*)(uintptr_t)x509NamePtr; + int ret = WOLFSSL_FAILURE; + (void)jcl; + + if (jenv == NULL || x509 == NULL || x509Name == NULL) { + return ret; + } + + ret = wolfSSL_X509_set_issuer_name(x509, x509Name); + + return ret; +#else + (void)jenv; + (void)jcl; + (void)x509Ptr; + (void)x509NamePtr; + return (jint)NOT_COMPILED_IN; +#endif +} + +JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLCertificate_X509_1set_1issuer_1name_1from_1der + (JNIEnv* jenv, jclass jcl, jlong x509Ptr, jbyteArray certDer) +{ +#if !defined(WOLFCRYPT_ONLY) && !defined(NO_CERTS) && \ + (defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)) + WOLFSSL_X509* x509 = (WOLFSSL_X509*)(uintptr_t)x509Ptr; + WOLFSSL_X509* x509In = NULL; + WOLFSSL_X509_NAME* name = NULL; + byte* der = NULL; + int derSz = 0; + int ret = WOLFSSL_SUCCESS; + (void)jcl; + + if (jenv == NULL || x509 == NULL || certDer == NULL) { + return WOLFSSL_FAILURE; + } + + der = (byte*)(*jenv)->GetByteArrayElements(jenv, certDer, NULL); + derSz = (*jenv)->GetArrayLength(jenv, certDer); + + if (der == NULL || derSz <= 0) { + ret = WOLFSSL_FAILURE; + } + + if (ret == WOLFSSL_SUCCESS) { + x509In = wolfSSL_X509_load_certificate_buffer(der, derSz, + SSL_FILETYPE_ASN1); + if (x509In == NULL) { + ret = WOLFSSL_FAILURE; + } + } + + if (ret == WOLFSSL_SUCCESS) { + /* Returns pointer into WOLFSSL_X509, no free needed on name */ + name = wolfSSL_X509_get_issuer_name(x509In); + if (name == NULL) { + ret = WOLFSSL_FAILURE; + } + } + + if (ret == WOLFSSL_SUCCESS) { + ret = wolfSSL_X509_set_issuer_name(x509, name); + } + + if (x509In != NULL) { + wolfSSL_X509_free(x509In); + } + + (*jenv)->ReleaseByteArrayElements(jenv, certDer, (jbyte*)der, JNI_ABORT); + + return ret; +#else + (void)jenv; + (void)jcl; + (void)x509Ptr; + (void)certDer; + return (jint)NOT_COMPILED_IN; +#endif +} + +JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLCertificate_X509_1set_1pubkey_1native_1open + (JNIEnv* jenv, jclass jcl, jlong x509Ptr, jint keyType, jbyteArray fileBytes, jint fileFormat) +{ +#if !defined(WOLFCRYPT_ONLY) && !defined(NO_CERTS) && \ + (defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)) + WOLFSSL_X509* x509 = (WOLFSSL_X509*)(uintptr_t)x509Ptr; + + byte* fileBuf = NULL; + int fileSz = 0; + byte* derBuf = NULL; + int derSz = 0; + byte derAllocated = 0; + WOLFSSL_EVP_PKEY* pub = NULL; + unsigned char* rsaPubBuf = NULL; + + int ret = WOLFSSL_SUCCESS; + (void)jcl; + + if (jenv == NULL || x509 == NULL) { + return WOLFSSL_FAILURE; + } + + fileBuf = (byte*)(*jenv)->GetByteArrayElements(jenv, fileBytes, NULL); + fileSz = (*jenv)->GetArrayLength(jenv, fileBytes); + + if (fileBuf == NULL || fileSz == 0) { + ret = WOLFSSL_FAILURE; + } + + /* convert PEM to DER if needed */ + if (ret == WOLFSSL_SUCCESS) { + if ((int)fileFormat == WOLFSSL_FILETYPE_ASN1) { + /* already in DER */ + derBuf = fileBuf; + derSz = fileSz; + } + else { + /* get needed buffer size */ + ret = wc_KeyPemToDer(fileBuf, fileSz, NULL, 0, NULL); + if (ret <= 0) { + ret = WOLFSSL_FAILURE; + } + else { + derSz = ret; + derBuf = (byte*)XMALLOC(derSz, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (derBuf == NULL) { + ret = WOLFSSL_FAILURE; + } + else { + ret = WOLFSSL_SUCCESS; + derAllocated = 1; + XMEMSET(derBuf, 0, derSz); + } + } + } + } + + /* convert PEM to DER if derBuf has been allocated */ + if (derAllocated == 1 && ret == WOLFSSL_SUCCESS) { + ret = wc_KeyPemToDer(fileBuf, fileSz, derBuf, derSz, NULL); + if (ret <= 0 || ret != derSz) { + ret = WOLFSSL_FAILURE; + } + else { + ret = WOLFSSL_SUCCESS; + } + } + + /* convert buffer into WOLFSSL_EVP_PKEY */ + if (ret == WOLFSSL_SUCCESS) { + rsaPubBuf = derBuf; + + pub = wolfSSL_d2i_PUBKEY(NULL, (const unsigned char**)&rsaPubBuf, derSz); + if (pub == NULL) { + ret = WOLFSSL_FAILURE; + } + } + + /* set WOLFSSL_EVP_PKEY into WOLFSSL_X509 */ + if (ret == WOLFSSL_SUCCESS) { + ret = wolfSSL_X509_set_pubkey(x509, pub); + } + + if (pub != NULL) { + /* free WOLFSSL_EVP_PKEY, since X509_set_pubkey() makes copy */ + wolfSSL_EVP_PKEY_free(pub); + } + if (derAllocated == 1 && derBuf != NULL) { + XMEMSET(derBuf, 0, derSz); + XFREE(derBuf, NULL, DYNAMIC_TYPE_TMP_BUFFER); + } + (*jenv)->ReleaseByteArrayElements(jenv, fileBytes, (jbyte*)fileBuf, + JNI_ABORT); + + return (jint)ret; +#else + (void)jenv; + (void)jcl; + (void)x509Ptr; + (void)keyType; + (void)filePath; + (void)fileFormat; + return (jint)NOT_COMPILED_IN; +#endif +} + +JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLCertificate_X509_1add_1altname + (JNIEnv* jenv, jclass jcl, jlong x509Ptr, jstring altName, jint type) +{ +#if !defined(WOLFCRYPT_ONLY) && !defined(NO_CERTS) && defined(OPENSSL_EXTRA) + WOLFSSL_X509* x509 = (WOLFSSL_X509*)(uintptr_t)x509Ptr; + const char* name = NULL; + int ret = WOLFSSL_SUCCESS; + (void)jcl; + + if (jenv == NULL || x509 == NULL) { + return WOLFSSL_FAILURE; + } + + name = (*jenv)->GetStringUTFChars(jenv, altName, 0); + + if (name == NULL) { + ret = WOLFSSL_FAILURE; + } + else { + ret = wolfSSL_X509_add_altname(x509, name, (int)type); + } + + (*jenv)->ReleaseStringUTFChars(jenv, altName, name); + + return (jint)ret; +#else + (void)jenv; + (void)jcl; + (void)x509Ptr; + (void)altName; + (void)type; + return (jint)NOT_COMPILED_IN; +#endif +} + +JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLCertificate_X509_1add_1ext_1via_1nconf_1nid + (JNIEnv* jenv, jclass jcl, jlong x509Ptr, jint nid, jstring extValue, jboolean isCritical) +{ +#if !defined(WOLFCRYPT_ONLY) && !defined(NO_CERTS) && defined(OPENSSL_EXTRA) + WOLFSSL_X509* x509 = (WOLFSSL_X509*)(uintptr_t)x509Ptr; + WOLFSSL_X509_EXTENSION* ext = NULL; + const char* value = NULL; + int ret = WOLFSSL_SUCCESS; + (void)jcl; + + if (jenv == NULL || x509 == NULL) { + return WOLFSSL_FAILURE; + } + + value = (*jenv)->GetStringUTFChars(jenv, extValue, 0); + if (value == NULL) { + ret = WOLFSSL_FAILURE; + } + + if (ret == WOLFSSL_SUCCESS) { + ext = wolfSSL_X509V3_EXT_nconf_nid(NULL, NULL, (int)nid, value); + if (ext == NULL) { + ret = WOLFSSL_FAILURE; + } + } + + if (ret == WOLFSSL_SUCCESS) { + if (isCritical == JNI_TRUE) { + ret = wolfSSL_X509_EXTENSION_set_critical(ext, 1); + } + } + + if (ret == WOLFSSL_SUCCESS) { + ret = wolfSSL_X509_add_ext(x509, ext, -1); + } + + if (ext != NULL) { + wolfSSL_X509_EXTENSION_free(ext); + } + + (*jenv)->ReleaseStringUTFChars(jenv, extValue, value); + + return (jint)ret; +#else + (void)jenv; + (void)jcl; + (void)x509Ptr; + (void)nid; + (void)extValue; + (void)isCritical; + return (jint)NOT_COMPILED_IN; +#endif +} + +JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLCertificate_X509_1add_1ext_1via_1set_1object_1boolean + (JNIEnv* jenv, jclass jcl, jlong x509Ptr, jint nid, jboolean extValue, jboolean isCritical) +{ +#if !defined(WOLFCRYPT_ONLY) && !defined(NO_CERTS) && defined(OPENSSL_EXTRA) + WOLFSSL_X509* x509 = (WOLFSSL_X509*)(uintptr_t)x509Ptr; + WOLFSSL_X509_EXTENSION* ext = NULL; + WOLFSSL_ASN1_OBJECT* obj = NULL; + int ret = WOLFSSL_SUCCESS; + (void)jcl; + + if (jenv == NULL || x509 == NULL) { + return WOLFSSL_FAILURE; + } + + ext = wolfSSL_X509_EXTENSION_new(); + if (ext == NULL) { + ret = WOLFSSL_FAILURE; + } + + if (ret == WOLFSSL_SUCCESS) { + if (isCritical == JNI_TRUE) { + ret = wolfSSL_X509_EXTENSION_set_critical(ext, 1); + } + } + + if (ret == WOLFSSL_SUCCESS) { + obj = wolfSSL_OBJ_nid2obj((int)nid); + if (obj == NULL) { + ret = WOLFSSL_FAILURE; + } + } + + if (ret == WOLFSSL_SUCCESS) { + if (extValue == JNI_TRUE) { + obj->ca = 1; + } + else { + obj->ca = 0; + } + } + + if (ret == WOLFSSL_SUCCESS) { + ret = wolfSSL_X509_EXTENSION_set_object(ext, obj); + } + + if (ret == WOLFSSL_SUCCESS) { + ret = wolfSSL_X509_add_ext(x509, ext, -1); + } + + + if (obj != NULL) { + wolfSSL_ASN1_OBJECT_free(obj); + } + if (ext != NULL) { + wolfSSL_X509_EXTENSION_free(ext); + } + + return (jint)ret; +#else + (void)jenv; + (void)jcl; + (void)x509Ptr; + (void)nid; + (void)extValue; + (void)isCritical; + return (jint)NOT_COMPILED_IN; +#endif +} + +JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLCertificate_X509_1set_1notBefore + (JNIEnv* jenv, jclass jcl, jlong x509Ptr, jlong notBefore) +{ +#if !defined(WOLFCRYPT_ONLY) && !defined(NO_CERTS) && \ + (defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)) + + WOLFSSL_X509* x509 = (WOLFSSL_X509*)(uintptr_t)x509Ptr; + WOLFSSL_ASN1_TIME* asnBefore = NULL; + int ret = WOLFSSL_SUCCESS; + time_t notBeforeTime = (time_t)(long)notBefore; + (void)jcl; + + if (jenv == NULL || x509 == NULL) { + return WOLFSSL_FAILURE; + } + + /* set time_t value into WOLFSSL_ASN1_TIME struct, no adjustment */ + asnBefore = wolfSSL_ASN1_TIME_adj(NULL, notBeforeTime, 0, 0); + if (asnBefore == NULL) { + ret = WOLFSSL_FAILURE; + } + + if (ret == WOLFSSL_SUCCESS) { + ret = wolfSSL_X509_set_notBefore(x509, asnBefore); + } + + if (asnBefore != NULL) { + wolfSSL_ASN1_TIME_free(asnBefore); + } + + return ret; +#else + (void)jenv; + (void)jcl; + (void)x509Ptr; + (void)notBefore; + return (jint)NOT_COMPILED_IN; +#endif +} + +JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLCertificate_X509_1set_1notAfter + (JNIEnv* jenv, jclass jcl, jlong x509Ptr, jlong notAfter) +{ +#if !defined(WOLFCRYPT_ONLY) && !defined(NO_CERTS) && \ + (defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)) + + WOLFSSL_X509* x509 = (WOLFSSL_X509*)(uintptr_t)x509Ptr; + WOLFSSL_ASN1_TIME* asnAfter = NULL; + int ret = WOLFSSL_SUCCESS; + time_t notAfterTime = (time_t)(long)notAfter; + (void)jcl; + + if (jenv == NULL || x509 == NULL) { + return WOLFSSL_FAILURE; + } + + /* set time_t value into WOLFSSL_ASN1_TIME struct, no adjustment */ + asnAfter = wolfSSL_ASN1_TIME_adj(NULL, notAfterTime, 0, 0); + if (asnAfter == NULL) { + ret = WOLFSSL_FAILURE; + } + + if (ret == WOLFSSL_SUCCESS) { + ret = wolfSSL_X509_set_notAfter(x509, asnAfter); + } + + if (asnAfter != NULL) { + wolfSSL_ASN1_TIME_free(asnAfter); + } + + return ret; +#else + (void)jenv; + (void)jcl; + (void)x509Ptr; + (void)notAfter; + return (jint)NOT_COMPILED_IN; +#endif +} + +JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLCertificate_X509_1set_1serialNumber + (JNIEnv* jenv, jclass jcl, jlong x509Ptr, jbyteArray serialBytes) +{ +#if !defined(WOLFCRYPT_ONLY) && !defined(NO_CERTS) && \ + (defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)) + WOLFSSL_X509* x509 = (WOLFSSL_X509*)(uintptr_t)x509Ptr; + WOLFSSL_ASN1_INTEGER* serial = NULL; + byte* serialBuf = NULL; + int serialSz = 0; + int ret = WOLFSSL_SUCCESS; + (void)jcl; + + if (jenv == NULL || x509 == NULL) { + return WOLFSSL_FAILURE; + } + + serialBuf = (byte*)(*jenv)->GetByteArrayElements(jenv, serialBytes, NULL); + serialSz = (*jenv)->GetArrayLength(jenv, serialBytes); + + if (serialBuf == NULL || serialSz == 0) { + ret = WOLFSSL_FAILURE; + } + + if (ret == WOLFSSL_SUCCESS) { + serial = wolfSSL_ASN1_INTEGER_new(); + if (serial == NULL) { + ret = WOLFSSL_FAILURE; + } + else { + serial->data[0] = ASN_INTEGER; + serial->data[1] = serialSz; + XMEMCPY(&serial->data[2], serialBuf, serialSz); + serial->length = serialSz + 2; + } + } + + if (ret == WOLFSSL_SUCCESS) { + /* copies contents of ASN1_INTEGER, we can free below */ + ret = wolfSSL_X509_set_serialNumber(x509, serial); + } + + if (serial != NULL) { + wolfSSL_ASN1_INTEGER_free(serial); + } + + (*jenv)->ReleaseByteArrayElements(jenv, serialBytes, (jbyte*)serialBuf, + JNI_ABORT); + + return ret; +#else + (void)jenv; + (void)jcl; + (void)x509Ptr; + (void)serialBytes; + return (jint)NOT_COMPILED_IN; +#endif +} + +JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLCertificate_X509_1sign + (JNIEnv* jenv, jclass jcl, jlong x509Ptr, jint keyType, jbyteArray fileBytes, jint fileFormat, jstring digestAlg) +{ +#if !defined(WOLFCRYPT_ONLY) && !defined(NO_CERTS) && \ + (defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)) && \ + defined(WOLFSSL_CERT_GEN) + WOLFSSL_X509* x509 = (WOLFSSL_X509*)(uintptr_t)x509Ptr; + + byte* fileBuf = NULL; + int fileSz = 0; + byte* derBuf = NULL; + int derSz = 0; + byte derAllocated = 0; + WOLFSSL_EVP_PKEY* priv = NULL; + const WOLFSSL_EVP_MD* md = NULL; + unsigned char* rsaPrivBuf = NULL; + const char* mdName = NULL; + + int ret = WOLFSSL_SUCCESS; + (void)jcl; + + if (jenv == NULL || x509 == NULL) { + return WOLFSSL_FAILURE; + } + + fileBuf = (byte*)(*jenv)->GetByteArrayElements(jenv, fileBytes, NULL); + fileSz = (*jenv)->GetArrayLength(jenv, fileBytes); + + if (fileBuf == NULL || fileSz == 0) { + ret = WOLFSSL_FAILURE; + } + + /* Set correct WOLFSSL_EVP_MD, does not need to be freed */ + if (ret == WOLFSSL_SUCCESS) { + mdName = (*jenv)->GetStringUTFChars(jenv, digestAlg, 0); + if (mdName == NULL) { + ret = WOLFSSL_FAILURE; + } + else { + md = wolfSSL_EVP_get_digestbyname(mdName); + if (md == NULL) { + ret = WOLFSSL_FAILURE; + } + } + } + + /* convert PEM to DER if needed */ + if (ret == WOLFSSL_SUCCESS) { + if ((int)fileFormat == WOLFSSL_FILETYPE_ASN1) { + /* already in DER */ + derBuf = fileBuf; + derSz = fileSz; + } + else { + /* get needed buffer size */ + ret = wc_KeyPemToDer(fileBuf, fileSz, NULL, 0, NULL); + if (ret <= 0) { + ret = WOLFSSL_FAILURE; + } + else { + derSz = ret; + derBuf = (byte*)XMALLOC(derSz, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (derBuf == NULL) { + ret = WOLFSSL_FAILURE; + } + else { + ret = WOLFSSL_SUCCESS; + derAllocated = 1; + XMEMSET(derBuf, 0, derSz); + } + } + } + } + + /* convert PEM to DER if derBuf has been allocated */ + if (derAllocated == 1 && ret == WOLFSSL_SUCCESS) { + ret = wc_KeyPemToDer(fileBuf, fileSz, derBuf, derSz, NULL); + if (ret <= 0 || ret != derSz) { + ret = WOLFSSL_FAILURE; + } + else { + ret = WOLFSSL_SUCCESS; + } + } + + /* convert buffer into WOLFSSL_EVP_PKEY */ + if (ret == WOLFSSL_SUCCESS) { + rsaPrivBuf = derBuf; + + priv = wolfSSL_d2i_PrivateKey((int)keyType, NULL, + (const unsigned char**)&rsaPrivBuf, derSz); + if (priv == NULL) { + ret = WOLFSSL_FAILURE; + } + } + + /* set version to v3 (only supported currently */ + if (ret == WOLFSSL_SUCCESS) { + ret = wolfSSL_X509_set_version(x509, 2L); + } + + /* sign WOLFSSL_X509 with WOLFSSL_EVP_PKEY, returns size of signature + * on success or negative on error */ + if (ret == WOLFSSL_SUCCESS) { + ret = wolfSSL_X509_sign(x509, priv, md); + if (ret >= 0) { + ret = WOLFSSL_SUCCESS; + } + } + + if (priv != NULL) { + wolfSSL_EVP_PKEY_free(priv); + } + if (derAllocated == 1 && derBuf != NULL) { + XMEMSET(derBuf, 0, derSz); + XFREE(derBuf, NULL, DYNAMIC_TYPE_TMP_BUFFER); + } + (*jenv)->ReleaseByteArrayElements(jenv, fileBytes, (jbyte*)fileBuf, + JNI_ABORT); + (*jenv)->ReleaseStringUTFChars(jenv, digestAlg, mdName); + + return (jint)ret; +#else + (void)jenv; + (void)jcl; + (void)x509Ptr; + (void)keyType; + (void)fileBytes; + (void)fileFormat; + (void)digestAlg; + return (jint)NOT_COMPILED_IN; +#endif +} + JNIEXPORT jlong JNICALL Java_com_wolfssl_WolfSSLCertificate_X509_1load_1certificate_1buffer (JNIEnv* jenv, jclass jcl, jbyteArray in, jint format) { @@ -139,6 +805,83 @@ JNIEXPORT jbyteArray JNICALL Java_com_wolfssl_WolfSSLCertificate_X509_1get_1der return derArr; } +JNIEXPORT jbyteArray JNICALL Java_com_wolfssl_WolfSSLCertificate_X509_1get_1pem + (JNIEnv* jenv, jclass jcl, jlong x509Ptr) +{ +#ifdef WOLFSSL_DER_TO_PEM + int sz = 0; + const byte* der = NULL; + byte* pem = NULL; + int pemSz = 0; + jbyteArray pemArr = NULL; + jclass excClass = NULL; + WOLFSSL_X509* x509 = (WOLFSSL_X509*)(uintptr_t)x509Ptr; + + if (jenv == NULL || x509 == NULL) { + return NULL; + } + + der = wolfSSL_X509_get_der(x509, &sz); + if (der == NULL || sz == 0) { + return NULL; + } + + pemSz = wc_DerToPem(der, sz, NULL, 0, CERT_TYPE); + if (pemSz < 0) { + return NULL; + } + + pem = (byte*)XMALLOC(pemSz, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (pem == NULL) { + return NULL; + } + XMEMSET(pem, 0, pemSz); + + pemSz = wc_DerToPem(der, sz, pem, pemSz, CERT_TYPE); + if (pemSz < 0) { + XFREE(pem, NULL, DYNAMIC_TYPE_TMP_BUFFER); + return NULL; + } + + pemArr = (*jenv)->NewByteArray(jenv, pemSz); + if (pemArr == NULL) { + (*jenv)->ThrowNew(jenv, jcl, + "Failed to create byte array in native X509_get_pem"); + XFREE(pem, NULL, DYNAMIC_TYPE_TMP_BUFFER); + return NULL; + } + + excClass = (*jenv)->FindClass(jenv, "com/wolfssl/WolfSSLJNIException"); + if ((*jenv)->ExceptionOccurred(jenv)) { + (*jenv)->ExceptionDescribe(jenv); + (*jenv)->ExceptionClear(jenv); + (*jenv)->DeleteLocalRef(jenv, pemArr); + XFREE(pem, NULL, DYNAMIC_TYPE_TMP_BUFFER); + return NULL; + } + + (*jenv)->SetByteArrayRegion(jenv, pemArr, 0, pemSz, (jbyte*)pem); + if ((*jenv)->ExceptionOccurred(jenv)) { + (*jenv)->ExceptionDescribe(jenv); + (*jenv)->ExceptionClear(jenv); + (*jenv)->DeleteLocalRef(jenv, pemArr); + (*jenv)->ThrowNew(jenv, excClass, + "Failed to set byte region in native X509_get_pem"); + XFREE(pem, NULL, DYNAMIC_TYPE_TMP_BUFFER); + return NULL; + } + + XFREE(pem, NULL, DYNAMIC_TYPE_TMP_BUFFER); + + return pemArr; +#else + (void)jenv; + (void)jcl; + (void)x509Ptr; + return NULL; +#endif +} + JNIEXPORT jbyteArray JNICALL Java_com_wolfssl_WolfSSLCertificate_X509_1get_1tbs (JNIEnv* jenv, jclass jcl, jlong x509Ptr) { @@ -541,6 +1284,33 @@ JNIEXPORT jstring JNICALL Java_com_wolfssl_WolfSSLCertificate_X509_1get_1issuer_ return NULL; } +JNIEXPORT jlong JNICALL Java_com_wolfssl_WolfSSLCertificate_X509_1get_1issuer_1name_1ptr + (JNIEnv* jenv, jclass jcl, jlong x509Ptr) +{ +#if !defined(WOLFCRYPT_ONLY) && !defined(NO_CERTS) && \ + (defined(OPENSSL_EXTRA_X509_SMALL) || defined(KEEP_PEER_CERT) || \ + defined(SESSION_CERTS)) + WOLFSSL_X509* x509 = (WOLFSSL_X509*)(uintptr_t)x509Ptr; + WOLFSSL_X509_NAME* name = NULL; + + if (jenv == NULL || x509 == NULL) { + return 0; + } + + name = wolfSSL_X509_get_issuer_name(x509); + if (name == NULL) { + return 0; + } + + return (jlong)(uintptr_t)name; +#else + (void)jenv; + (void)jcl; + (void)x509Ptr; + return (jlong)0; +#endif +} + JNIEXPORT jbyteArray JNICALL Java_com_wolfssl_WolfSSLCertificate_X509_1get_1pubkey (JNIEnv* jenv, jclass jcl, jlong x509Ptr) { diff --git a/native/com_wolfssl_WolfSSLCertificate.h b/native/com_wolfssl_WolfSSLCertificate.h index ac0ffe3..494c911 100644 --- a/native/com_wolfssl_WolfSSLCertificate.h +++ b/native/com_wolfssl_WolfSSLCertificate.h @@ -7,6 +7,10 @@ #ifdef __cplusplus extern "C" { #endif +#undef com_wolfssl_WolfSSLCertificate_EVP_PKEY_RSA +#define com_wolfssl_WolfSSLCertificate_EVP_PKEY_RSA 16L +#undef com_wolfssl_WolfSSLCertificate_EVP_PKEY_EC +#define com_wolfssl_WolfSSLCertificate_EVP_PKEY_EC 18L /* * Class: com_wolfssl_WolfSSLCertificate * Method: X509_get_der @@ -15,6 +19,14 @@ extern "C" { JNIEXPORT jbyteArray JNICALL Java_com_wolfssl_WolfSSLCertificate_X509_1get_1der (JNIEnv *, jclass, jlong); +/* + * Class: com_wolfssl_WolfSSLCertificate + * Method: X509_get_pem + * Signature: (J)[B + */ +JNIEXPORT jbyteArray JNICALL Java_com_wolfssl_WolfSSLCertificate_X509_1get_1pem + (JNIEnv *, jclass, jlong); + /* * Class: com_wolfssl_WolfSSLCertificate * Method: X509_get_tbs @@ -119,6 +131,14 @@ JNIEXPORT jstring JNICALL Java_com_wolfssl_WolfSSLCertificate_X509_1get_1subject JNIEXPORT jstring JNICALL Java_com_wolfssl_WolfSSLCertificate_X509_1get_1issuer_1name (JNIEnv *, jclass, jlong); +/* + * Class: com_wolfssl_WolfSSLCertificate + * Method: X509_get_issuer_name_ptr + * Signature: (J)J + */ +JNIEXPORT jlong JNICALL Java_com_wolfssl_WolfSSLCertificate_X509_1get_1issuer_1name_1ptr + (JNIEnv *, jclass, jlong); + /* * Class: com_wolfssl_WolfSSLCertificate * Method: X509_get_pubkey @@ -199,6 +219,102 @@ JNIEXPORT jlong JNICALL Java_com_wolfssl_WolfSSLCertificate_X509_1load_1certific JNIEXPORT jlong JNICALL Java_com_wolfssl_WolfSSLCertificate_X509_1load_1certificate_1file (JNIEnv *, jclass, jstring, jint); +/* + * Class: com_wolfssl_WolfSSLCertificate + * Method: X509_new + * Signature: ()J + */ +JNIEXPORT jlong JNICALL Java_com_wolfssl_WolfSSLCertificate_X509_1new + (JNIEnv *, jclass); + +/* + * Class: com_wolfssl_WolfSSLCertificate + * Method: X509_set_subject_name + * Signature: (JJ)I + */ +JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLCertificate_X509_1set_1subject_1name + (JNIEnv *, jclass, jlong, jlong); + +/* + * Class: com_wolfssl_WolfSSLCertificate + * Method: X509_set_issuer_name + * Signature: (JJ)I + */ +JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLCertificate_X509_1set_1issuer_1name + (JNIEnv *, jclass, jlong, jlong); + +/* + * Class: com_wolfssl_WolfSSLCertificate + * Method: X509_set_issuer_name_from_der + * Signature: (J[B)I + */ +JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLCertificate_X509_1set_1issuer_1name_1from_1der + (JNIEnv *, jclass, jlong, jbyteArray); + +/* + * Class: com_wolfssl_WolfSSLCertificate + * Method: X509_set_pubkey_native_open + * Signature: (JI[BI)I + */ +JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLCertificate_X509_1set_1pubkey_1native_1open + (JNIEnv *, jclass, jlong, jint, jbyteArray, jint); + +/* + * Class: com_wolfssl_WolfSSLCertificate + * Method: X509_add_altname + * Signature: (JLjava/lang/String;I)I + */ +JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLCertificate_X509_1add_1altname + (JNIEnv *, jclass, jlong, jstring, jint); + +/* + * Class: com_wolfssl_WolfSSLCertificate + * Method: X509_add_ext_via_nconf_nid + * Signature: (JILjava/lang/String;Z)I + */ +JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLCertificate_X509_1add_1ext_1via_1nconf_1nid + (JNIEnv *, jclass, jlong, jint, jstring, jboolean); + +/* + * Class: com_wolfssl_WolfSSLCertificate + * Method: X509_add_ext_via_set_object_boolean + * Signature: (JIZZ)I + */ +JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLCertificate_X509_1add_1ext_1via_1set_1object_1boolean + (JNIEnv *, jclass, jlong, jint, jboolean, jboolean); + +/* + * Class: com_wolfssl_WolfSSLCertificate + * Method: X509_set_notBefore + * Signature: (JJ)I + */ +JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLCertificate_X509_1set_1notBefore + (JNIEnv *, jclass, jlong, jlong); + +/* + * Class: com_wolfssl_WolfSSLCertificate + * Method: X509_set_notAfter + * Signature: (JJ)I + */ +JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLCertificate_X509_1set_1notAfter + (JNIEnv *, jclass, jlong, jlong); + +/* + * Class: com_wolfssl_WolfSSLCertificate + * Method: X509_set_serialNumber + * Signature: (J[B)I + */ +JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLCertificate_X509_1set_1serialNumber + (JNIEnv *, jclass, jlong, jbyteArray); + +/* + * Class: com_wolfssl_WolfSSLCertificate + * Method: X509_sign + * Signature: (JI[BILjava/lang/String;)I + */ +JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLCertificate_X509_1sign + (JNIEnv *, jclass, jlong, jint, jbyteArray, jint, jstring); + #ifdef __cplusplus } #endif diff --git a/native/com_wolfssl_WolfSSLX509Name.c b/native/com_wolfssl_WolfSSLX509Name.c new file mode 100644 index 0000000..4d4906c --- /dev/null +++ b/native/com_wolfssl_WolfSSLX509Name.c @@ -0,0 +1,126 @@ +/* com_wolfssl_WolfSSLX509Name.c + * + * Copyright (C) 2006-2023 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + +#include +#include + +#ifdef WOLFSSL_USER_SETTINGS + #include +#else + #include +#endif + +#include + +#include "com_wolfssl_globals.h" +#include "com_wolfssl_WolfSSLX509Name.h" + +JNIEXPORT jlong JNICALL Java_com_wolfssl_WolfSSLX509Name_X509_1NAME_1new + (JNIEnv* jenv, jclass jcl) +{ +#if !defined(WOLFCRYPT_ONLY) && !defined(NO_CERTS) && \ + (defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)) + WOLFSSL_X509_NAME* x509Name = NULL; + (void)jcl; + + if (jenv == NULL) { + return 0; + } + + x509Name = wolfSSL_X509_NAME_new(); + if (x509Name == NULL) { + return 0; + } + + return (jlong)(uintptr_t)x509Name; +#else + (void)jenv; + (void)jcl; + return 0; +#endif +} + +JNIEXPORT void JNICALL Java_com_wolfssl_WolfSSLX509Name_X509_1NAME_1free + (JNIEnv* jenv, jclass jcl, jlong x509NamePtr) +{ +#if !defined(WOLFCRYPT_ONLY) && !defined(NO_CERTS) && \ + (defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)) + WOLFSSL_X509_NAME* ptr = (WOLFSSL_X509_NAME*)(uintptr_t)x509NamePtr; + (void)jcl; + + if (jenv == NULL || ptr == NULL) { + return; + } + + wolfSSL_X509_NAME_free(ptr); +#else + (void)jenv; + (void)jcl; + (void)x509NamePtr; +#endif +} + +JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLX509Name_X509_1NAME_1add_1entry_1by_1txt + (JNIEnv* jenv, jclass jcl, jlong x509NamePtr, jstring fieldStr, jint type, + jbyteArray entryArr, jint entryLen, jint loc, jint set) +{ +#if !defined(WOLFCRYPT_ONLY) && !defined(NO_CERTS) && \ + (defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)) + WOLFSSL_X509_NAME* ptr = (WOLFSSL_X509_NAME*)(uintptr_t)x509NamePtr; + const char* field = NULL; + unsigned char* entry = NULL; + int ret = WOLFSSL_FAILURE; + int len = 0; + (void)jcl; + (void)entryLen; + + if (jenv == NULL) { + return ret; + } + + field = (*jenv)->GetStringUTFChars(jenv, fieldStr, 0); + entry = (unsigned char*)(*jenv)->GetByteArrayElements(jenv, entryArr, NULL); + len = (*jenv)->GetArrayLength(jenv, entryArr); + + if (entry != NULL && len > 0 && field != NULL) { + + ret = wolfSSL_X509_NAME_add_entry_by_txt(ptr, field, (int)type, + entry, len, (int)loc, (int)set); + } + + (*jenv)->ReleaseByteArrayElements(jenv, entryArr, (jbyte*)entry, JNI_ABORT); + (*jenv)->ReleaseStringUTFChars(jenv, fieldStr, field); + + return (jint)ret; +#else + (void)jenv; + (void)jcl; + (void)x509NamePtr; + (void)fieldStr; + (void)type; + (void)entryArr; + (void)entryLen; + (void)loc; + (void)set; + return (jint)NOT_COMPILED_IN; +#endif +} + diff --git a/native/com_wolfssl_WolfSSLX509Name.h b/native/com_wolfssl_WolfSSLX509Name.h new file mode 100644 index 0000000..0fde184 --- /dev/null +++ b/native/com_wolfssl_WolfSSLX509Name.h @@ -0,0 +1,39 @@ +/* DO NOT EDIT THIS FILE - it is machine generated */ +#include +/* Header for class com_wolfssl_WolfSSLX509Name */ + +#ifndef _Included_com_wolfssl_WolfSSLX509Name +#define _Included_com_wolfssl_WolfSSLX509Name +#ifdef __cplusplus +extern "C" { +#endif +#undef com_wolfssl_WolfSSLX509Name_MBSTRING_UTF8 +#define com_wolfssl_WolfSSLX509Name_MBSTRING_UTF8 256L +/* + * Class: com_wolfssl_WolfSSLX509Name + * Method: X509_NAME_new + * Signature: ()J + */ +JNIEXPORT jlong JNICALL Java_com_wolfssl_WolfSSLX509Name_X509_1NAME_1new + (JNIEnv *, jclass); + +/* + * Class: com_wolfssl_WolfSSLX509Name + * Method: X509_NAME_free + * Signature: (J)V + */ +JNIEXPORT void JNICALL Java_com_wolfssl_WolfSSLX509Name_X509_1NAME_1free + (JNIEnv *, jclass, jlong); + +/* + * Class: com_wolfssl_WolfSSLX509Name + * Method: X509_NAME_add_entry_by_txt + * Signature: (JLjava/lang/String;I[BIII)I + */ +JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLX509Name_X509_1NAME_1add_1entry_1by_1txt + (JNIEnv *, jclass, jlong, jstring, jint, jbyteArray, jint, jint, jint); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/src/java/com/wolfssl/WolfSSL.java b/src/java/com/wolfssl/WolfSSL.java index 9099c41..e3ba852 100644 --- a/src/java/com/wolfssl/WolfSSL.java +++ b/src/java/com/wolfssl/WolfSSL.java @@ -346,6 +346,20 @@ public class WolfSSL { /** Ed25519 key type */ public static final int ED25519k = 256; + /* GeneralName types. Match native values in asn.h */ + public static final int ASN_OTHER_TYPE = 0x00; + public static final int ASN_RFC822_TYPE = 0x01; + public static final int ASN_DNS_TYPE = 0x02; + public static final int ASN_DIR_TYPE = 0x04; + public static final int ASN_URI_TYPE = 0x06; + public static final int ASN_IP_TYPE = 0x07; + + /* NIDs, from native asn.h */ + public static final int NID_key_usage = 129; + public static final int NID_subject_alt_name = 131; + public static final int NID_basic_constraints = 133; + public static final int NID_ext_key_usage = 151; + /* is this object active, or has it been cleaned up? */ private boolean active = false; @@ -1048,6 +1062,15 @@ public class WolfSSL { */ public static native int getHmacMaxSize(); + /** + * Return the wolfSSL library vesrion number in hex. + * + * Wrapper around native wolfSSL_lib_version_hex() + * + * @return wolfSSL native library version hex value + */ + public static native long getLibVersionHex(); + /** * Returns the enabled cipher suites for native wolfSSL. * diff --git a/src/java/com/wolfssl/WolfSSLCertificate.java b/src/java/com/wolfssl/WolfSSLCertificate.java index fa9efab..e0aab09 100644 --- a/src/java/com/wolfssl/WolfSSLCertificate.java +++ b/src/java/com/wolfssl/WolfSSLCertificate.java @@ -23,7 +23,9 @@ package com.wolfssl; import java.io.IOException; import java.io.InputStream; import java.io.ByteArrayInputStream; +import java.io.File; import java.nio.charset.Charset; +import java.nio.file.Files; import java.math.BigInteger; import java.text.ParseException; import java.text.SimpleDateFormat; @@ -33,9 +35,16 @@ import java.util.List; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; +import java.security.PublicKey; +import java.security.PrivateKey; +import java.security.interfaces.RSAPublicKey; +import java.security.interfaces.RSAPrivateKey; +import java.security.interfaces.ECPublicKey; +import java.security.interfaces.ECPrivateKey; import java.security.cert.CertificateFactory; import java.security.cert.X509Certificate; import java.security.cert.CertificateException; +import java.security.cert.CertificateEncodingException; /** * WolfSSLCertificate class, wraps native wolfSSL WOLFSSL_X509 functionality. @@ -52,10 +61,19 @@ public class WolfSSLCertificate { /* lock around active state */ private final Object stateLock = new Object(); + /* lock around native WOLFSSL_X509 pointer use */ + private final Object x509Lock = new Object(); + /* cache alt names once retrieved once */ private Collection> altNames = null; + /* Public key types used for certificate generation, mirrored from + * native enum in wolfssl/openssl/evp.h */ + private static final int EVP_PKEY_RSA = 16; + private static final int EVP_PKEY_EC = 18; + static native byte[] X509_get_der(long x509); + static native byte[] X509_get_pem(long x509); static native byte[] X509_get_tbs(long x509); static native void X509_free(long x509); static native int X509_get_serial_number(long x509, byte[] out); @@ -69,6 +87,7 @@ public class WolfSSLCertificate { static native int X509_get_isCA(long x509); static native String X509_get_subject_name(long x509); static native String X509_get_issuer_name(long x509); + static native long X509_get_issuer_name_ptr(long x509); static native byte[] X509_get_pubkey(long x509); static native String X509_get_pubkey_type(long x509); static native int X509_get_pathLength(long x509); @@ -80,6 +99,45 @@ public class WolfSSLCertificate { static native long X509_load_certificate_buffer(byte[] buf, int format); static native long X509_load_certificate_file(String path, int format); + /* native functions used for X509v3 certificate generation */ + static native long X509_new(); + static native int X509_set_subject_name(long x509Ptr, long x509NamePtr); + static native int X509_set_issuer_name(long x509Ptr, long x509NamePtr); + static native int X509_set_issuer_name_from_der(long x509Ptr, byte[] certDer); + static native int X509_set_pubkey_native_open(long x509Ptr, int keyType, + byte[] fileBytes, int format); + static native int X509_add_altname(long x509Ptr, String name, int type); + static native int X509_add_ext_via_nconf_nid(long x509Ptr, int nid, + String extValue, boolean isCritical); + static native int X509_add_ext_via_set_object_boolean(long x509Ptr, + int nid, boolean extValue, boolean isCritical); + static native int X509_set_notBefore(long x509Ptr, long timeSecs); + static native int X509_set_notAfter(long x509Ptr, long timeSecs); + static native int X509_set_serialNumber(long x509Ptr, byte[] serialBytes); + static native int X509_sign(long x509Ptr, int evpKeyType, byte[] keyBytes, + int format, String digestAlg); + + /** + * Create new empty WolfSSLCertificate object, for use with X509v3 + * certificate generation. + * + * @throws WolfSSLException if native API call fails. + */ + public WolfSSLCertificate() throws WolfSSLException { + + x509Ptr = X509_new(); + if (x509Ptr == 0) { + throw new WolfSSLException("Failed to create WolfSSLCertificate"); + } + + /* x509Ptr has been allocated natively, mark as owned */ + this.weOwnX509Ptr = true; + + synchronized (stateLock) { + this.active = true; + } + } + /** * Create new WolfSSLCertificate from DER-encoded byte array. * @@ -236,60 +294,761 @@ public class WolfSSLCertificate { } } + /** + * Verifies that the current WolfSSLCertificate object is active. + * + * @throws IllegalStateException if object has been freed + */ + private void confirmObjectIsActive() + throws IllegalStateException { + + synchronized (stateLock) { + if (this.active == false) { + throw new IllegalStateException( + "WolfSSLCertificate object has been freed"); + } + } + } + + /** + * Protected method to be used by objects of this class to get + * internal WOLFSSL_X509 pointer. + * + * @return internal WOLFSSL_X509 pointer value + * @throws IllegalStateException if object has been freed + */ + protected long getX509Ptr() throws IllegalStateException { + + confirmObjectIsActive(); + + return this.x509Ptr; + } + + /** + * Set the Subject Name to be used with this WolfSSLCertificate. + * Note that the WolfSSLX509Name object should be completely set up + * before calling this method. This method copies/duplicates the contents + * of the WOLFSSL_X509_NAME (WolfSSLX509Name) into the native + * WOLFSSL_X509 structure. + * + * @param name Initialized and populated WolfSSLX509 name to be set into + * Subject Name of WolfSSLCertificate for cert generation. + * + * @throws IllegalStateException if WolfSSLCertificate has been freed. + * @throws WolfSSLException if native JNI error occurs. + */ + public void setSubjectName(WolfSSLX509Name name) + throws IllegalStateException, WolfSSLException { + + int ret; + + confirmObjectIsActive(); + + synchronized (x509Lock) { + /* TODO somehow lock WolfSSLX509Name object while using pointer? */ + ret = X509_set_subject_name(this.x509Ptr, + name.getNativeX509NamePtr()); + } + + if (ret != WolfSSL.SSL_SUCCESS) { + throw new WolfSSLException("Error setting subject name " + + "(ret: " + ret + ")"); + } + } + + /** + * Set the Issuer Name to be used with this WolfSSLCertificate. + * Note that the WolfSSLX509Name object should be completely set up + * before calling this method. This method copies/duplicates the contents + * of the WOLFSSL_X509_NAME (WolfSSLX509Name) into the native + * WOLFSSL_X509 structure. + * + * @param name Initialized and populated WolfSSLX509 name to be set into + * Issuer Name of WolfSSLCertificate for cert generation. + * + * @throws IllegalStateException if WolfSSLCertificate has been freed. + * @throws WolfSSLException if native JNI error occurs. + */ + public void setIssuerName(WolfSSLX509Name name) + throws IllegalStateException, WolfSSLException { + + int ret; + + confirmObjectIsActive(); + + synchronized (x509Lock) { + /* TODO somehow lock WolfSSLX509Name object while using pointer? */ + ret = X509_set_issuer_name(this.x509Ptr, + name.getNativeX509NamePtr()); + } + + if (ret != WolfSSL.SSL_SUCCESS) { + throw new WolfSSLException("Error setting issuer name " + + "(ret: " + ret + ")"); + } + } + + /** + * Set the Issuer Name to be used with this WolfSSLCertificate. + * This method copies the issuer name from the existing populated + * WolfSSLCertificate object, which would commonly be initialized + * from a CA certificate file or byte array. + * + * @param cert Initialized and populated WolfSSLCertificate to be set into + * Issuer Name of this WolfSSLCertificate for cert generation. + * + * @throws IllegalStateException if WolfSSLCertificate has been freed. + * @throws WolfSSLException if native JNI error occurs. + */ + public void setIssuerName(WolfSSLCertificate cert) + throws IllegalStateException, WolfSSLException { + + int ret; + long x509CertPtr = 0; + long x509NamePtr = 0; + + confirmObjectIsActive(); + + x509NamePtr = X509_get_issuer_name_ptr(cert.getX509Ptr()); + if (x509NamePtr == 0) { + throw new WolfSSLException("Error getting issuer name from " + + "WolfSSLCertificate"); + } + + synchronized (x509Lock) { + /* TODO somehow lock WolfSSLX509Name object while using pointer? */ + ret = X509_set_issuer_name(this.x509Ptr, x509NamePtr); + } + + if (ret != WolfSSL.SSL_SUCCESS) { + throw new WolfSSLException("Error setting issuer name " + + "(ret: " + ret + ")"); + } + } + + /** + * Set the Issuer Name to be used with this WolfSSLCertificate. + * This method copies the issuer name from the existing populated + * X509Certificate object. + * + * @param cert Initialized and populated X509Certificate to be used to set + * Issuer Name of this WolfSSLCertificate for cert generation. + * + * @throws IllegalStateException if WolfSSLCertificate has been freed. + * @throws WolfSSLException if native JNI error occurs. + * @throws CertificateEncodingException if error occurs while parsing + * X509Certificate + */ + public void setIssuerName(X509Certificate cert) + throws IllegalStateException, WolfSSLException, + CertificateEncodingException { + + int ret; + byte[] certDer = null; + + confirmObjectIsActive(); + + /* Get DER encoding of certificate */ + certDer = cert.getEncoded(); + + synchronized (x509Lock) { + ret = X509_set_issuer_name_from_der(this.x509Ptr, certDer); + } + + if (ret != WolfSSL.SSL_SUCCESS) { + throw new WolfSSLException("Error setting issuer name " + + "(ret: " + ret + ")"); + } + } + + /** + * Set public key for this WolfSSLCertificate, used when generating + * X509v3 certificates. + * + * @param filePath Path to public key file + * @param keyType Type of public key algorithm, options are: + * WolfSSL.RSAk + * WolfSSL.ECDSAk + * @param format Format of public key file, options are: + * WolfSSL.SSL_FILETYPE_ASN1 (DER formatted) + * WolfSSL.SSL_FILETYPE_PEM (PEM formatted) + * + * @throws IllegalStateException if WolfSSLCertificate has been freed. + * @throws IOException on error opening input file + * @throws WolfSSLException if invalid arguments or native JNI error occurs. + */ + public void setPublicKey(String filePath, int keyType, int format) + throws IllegalStateException, IOException, WolfSSLException { + + int ret = 0; + File keyFile = null; + + confirmObjectIsActive(); + + if (filePath == null || filePath.isEmpty()) { + throw new WolfSSLException("File path is null or empty"); + } + + keyFile = new File(filePath); + if (!keyFile.exists()) { + throw new WolfSSLException("Input file does not exist: " + + filePath); + } + + setPublicKey(Files.readAllBytes(keyFile.toPath()), keyType, format); + } + + /** + * Set public key for this WolfSSLCertificate, used when generating + * X509v3 certificates. + * + * @param key Byte array containing public key + * @param keyType Type of public key algorithm, options are: + * WolfSSL.RSAk + * WolfSSL.ECDSAk + * @param format Format of public key file, options are: + * WolfSSL.SSL_FILETYPE_ASN1 (DER formatted) + * WolfSSL.SSL_FILETYPE_PEM (PEM formatted) + * + * @throws IllegalStateException if WolfSSLCertificate has been freed. + * @throws IOException on error opening input file + * @throws WolfSSLException if invalid arguments or native JNI error occurs. + */ + public void setPublicKey(byte[] key, int keyType, int format) + throws IllegalStateException, IOException, WolfSSLException { + + int ret = 0; + int evpKeyType; + + confirmObjectIsActive(); + + if (key == null || key.length == 0) { + throw new WolfSSLException("Key array is null or empty"); + } + + if (format != WolfSSL.SSL_FILETYPE_ASN1 && + format != WolfSSL.SSL_FILETYPE_PEM) { + throw new WolfSSLException( + "Invalid key format, must be PEM or DER"); + } + + switch (keyType) { + case WolfSSL.RSAk: + evpKeyType = EVP_PKEY_RSA; + break; + case WolfSSL.ECDSAk: + evpKeyType = EVP_PKEY_EC; + break; + default: + throw new WolfSSLException("Unsupported public key type"); + } + + synchronized (x509Lock) { + ret = X509_set_pubkey_native_open(this.x509Ptr, evpKeyType, + key, format); + } + + if (ret != WolfSSL.SSL_SUCCESS) { + throw new WolfSSLException( + "Error setting public key into native WOLFSSL_X509 " + + "(ret: " + ret + ")"); + } + } + + /** + * Set public key for this WolfSSLCertificate, used when generating + * X509v3 certificates. + * + * @param key PublicKey object containing public key to be used when + * generating X509v3 certificate. + * + * @throws IllegalStateException if WolfSSLCertificate has been freed. + * @throws WolfSSLException if invalid arguments or native JNI error occurs. + * @throws IOException on error opening/reading public key + */ + public void setPublicKey(PublicKey key) + throws IllegalStateException, IOException, WolfSSLException { + + int keyType; + byte[] encodedKey = null; + + confirmObjectIsActive(); + + if (key instanceof RSAPublicKey) { + keyType = WolfSSL.RSAk; + } + else if (key instanceof ECPublicKey) { + keyType = WolfSSL.ECDSAk; + } + else { + throw new WolfSSLException( + "PublicKey must be of type RSAPublicKey or ECPublicKey"); + } + + /* Get DER encoded key */ + encodedKey = key.getEncoded(); + if (encodedKey == null) { + throw new WolfSSLException( + "Error getting encoded (DER) format of PublicKey"); + } + + setPublicKey(encodedKey, keyType, WolfSSL.SSL_FILETYPE_ASN1); + } + + /** + * Sets the serial number for this WolfSSLCertificate, used when + * generating X509v3 certificates. + * + * @param serial BigInteger holding serial number for generated cert + * + * @throws IllegalStateException if WolfSSLCertificate has been freed. + * @throws WolfSSLException if invalid arguments or native JNI error occurs. + */ + public void setSerialNumber(BigInteger serial) + throws IllegalStateException, WolfSSLException { + + int ret = 0; + byte[] serialBytes = null; + + confirmObjectIsActive(); + + if (serial == null) { + throw new WolfSSLException("Input BigInteger is null"); + } + + serialBytes = serial.toByteArray(); + if (serialBytes == null || serialBytes.length == 0) { + throw new WolfSSLException("BigInteger.toByteArray() " + + "is null or 0 length"); + } + + synchronized (x509Lock) { + ret = X509_set_serialNumber(this.x509Ptr, serialBytes); + } + + if (ret != WolfSSL.SSL_SUCCESS) { + throw new WolfSSLException( + "Error setting serial number into native WOLFSSL_X509 " + + "(ret: " + ret + ")"); + } + } + + /** + * Sets the notBefore date for this WolfSSLCertificate, used when + * generating X509v3 certificates. + * + * @param notBefore Date object representing notBefore date/time to set + * + * @throws IllegalStateException if WolfSSLCertificate has been freed. + * @throws WolfSSLException if invalid arguments or native JNI error occurs. + */ + public void setNotBefore(Date notBefore) + throws IllegalStateException, WolfSSLException { + + int ret = 0; + + confirmObjectIsActive(); + + synchronized (x509Lock) { + ret = X509_set_notBefore(this.x509Ptr, notBefore.getTime() / 1000); + } + + if (ret != WolfSSL.SSL_SUCCESS) { + throw new WolfSSLException( + "Error setting notBefore date into native WOLFSSL_X509 " + + "(ret: " + ret + ")"); + } + } + + /** + * Sets the notAfter date for this WolfSSLCertificate, used when + * generating X509v3 certificates. + * + * @param notAfter Date object representing notAfter date/time to set + * + * @throws IllegalStateException if WolfSSLCertificate has been freed. + * @throws WolfSSLException if invalid arguments or native JNI error occurs. + */ + public void setNotAfter(Date notAfter) + throws IllegalStateException, WolfSSLException { + + int ret = 0; + + confirmObjectIsActive(); + + synchronized (x509Lock) { + ret = X509_set_notAfter(this.x509Ptr, notAfter.getTime() / 1000); + } + + if (ret != WolfSSL.SSL_SUCCESS) { + throw new WolfSSLException( + "Error setting notAfter date into native WOLFSSL_X509 " + + "(ret: " + ret + ")"); + } + } + + /** + * Add subject alternative name for this WolfSSLCertificate, used when + * generating X509v3 certificates. + * + * @param name String value of subject alternative name to set + * @param type Type of subject alt name entry, must be one of: + * WolfSSL.ASN_OTHER_TYPE, WolfSSL.ASN_RFC822_TYPE, + * WolfSSL.ASN_DNS_TYPE, WolfSSL.ASN_DIR_TYPE, WolfSSL.ASN_URI_TYPE, + * WolfSSL.ASN_IP_TYPE + * + * @throws IllegalStateException if WolfSSLCertificate has been freed. + * @throws WolfSSLException if invalid arguments or native JNI error occurs. + */ + public void addAltName(String name, int type) + throws IllegalStateException, WolfSSLException { + + int ret = 0; + + confirmObjectIsActive(); + + synchronized (x509Lock) { + ret = X509_add_altname(this.x509Ptr, name, type); + } + + if (ret != WolfSSL.SSL_SUCCESS) { + throw new WolfSSLException( + "Error setting altName into native WOLFSSL_X509 " + + "(ret: " + ret + ")"); + } + } + + /** + * Add an extension to a WOLFSSL_X509 given the NID and extension + * value String. + * + * This method supports the following extensions: + * - Key Usage (WolfSSL.NID_key_usage) + * - Extended Key Usage (WolfSSL.NID_ext_key_usage) + * - Subject Alt Name (WolfSSL.NED_subject_alt_name) + * + * @param nid NID of extension to add. Must be one of: + * WolfSSL.NID_key_usage + * WolfSSL.NID_subject_alt_name + * @param value String value of extension to set + * @param isCritical Boolean flag indicating if this extension is + * critical + * + * @throws IllegalStateException if WolfSSLCertificate has been freed. + * @throws WolfSSLException if invalid arguments or native JNI error occurs. + */ + public void addExtension(int nid, String value, boolean isCritical) + throws IllegalStateException, WolfSSLException { + + int ret = 0; + + confirmObjectIsActive(); + + if (nid != WolfSSL.NID_key_usage && + nid != WolfSSL.NID_subject_alt_name && + nid != WolfSSL.NID_ext_key_usage) { + throw new WolfSSLException( + "Unsupported X509v3 extension NID: " + nid); + } + + synchronized (x509Lock) { + ret = X509_add_ext_via_nconf_nid(this.x509Ptr, nid, value, + isCritical); + } + + if (ret != WolfSSL.SSL_SUCCESS) { + if ((WolfSSL.getLibVersionHex() <= 0x05006003) && + (nid == WolfSSL.NID_key_usage || + nid == WolfSSL.NID_ext_key_usage)) { + + /* wolfSSL versions 5.6.3 and earlier did not include code + * fixes to native wolfSSL allowing this extension support to + * work. Use a version > 5.6.3 or apply patch from wolfSSL + * PR 6585 for correct support */ + throw new WolfSSLException( + "Error setting extension into native WOLFSSL_X509 " + + "(ret: " + ret + ").\nNeed to use wolfSSL version " + + "greater than 5.6.3 for extension support (PR 6585)."); + } + + throw new WolfSSLException( + "Error setting extension into native WOLFSSL_X509 " + + "(ret: " + ret + ")"); + } + } + + /** + * Add an extension to a WOLFSSL_X509 given the NID and extension + * value true/false value. + * + * This method supports the following extensions: + * - Basic Constraints (WolfSSL.NID_basic_constraints) + * + * @param nid NID of extension to add. Must be one of: + * WolfSSL.NID_key_usage + * WolfSSL.NID_subject_alt_name + * @param value Boolean value of extension (true/false) + * @param isCritical Boolean flag indicating if this extension is + * critical + * + * @throws IllegalStateException if WolfSSLCertificate has been freed. + * @throws WolfSSLException if invalid arguments or native JNI error occurs. + */ + public void addExtension(int nid, boolean value, boolean isCritical) + throws IllegalStateException, WolfSSLException { + + int ret = 0; + + confirmObjectIsActive(); + + if (nid != WolfSSL.NID_basic_constraints) { + throw new WolfSSLException( + "Unsupported X509v3 extension NID: " + nid); + } + + synchronized (x509Lock) { + ret = X509_add_ext_via_set_object_boolean( + this.x509Ptr, nid, value, isCritical); + } + + if (ret != WolfSSL.SSL_SUCCESS) { + throw new WolfSSLException( + "Error setting extension into native WOLFSSL_X509 " + + "(ret: " + ret + ")"); + } + } + + /** + * Sign certificate with private key from file. + * + * @param filePath Path to private key file + * @param keyType Type of public key algorithm, options are: + * WolfSSL.RSAk + * WolfSSL.ECDSAk + * @param format Format of private key file, options are: + * WolfSSL.SSL_FILETYPE_ASN1 (DER formatted) + * WolfSSL.SSL_FILETYPE_PEM (PEM formatted) + * @param digestAlg Message digest algorithm to use for signature + * generation. Options include the following, but native algorithm + * must be compiled into wolfSSL to be available: + * "MD4", "MD5", "SHA1", "SHA224", "SHA256", "SHA384", + * "SHA512", "SHA3_224", "SHA3_256", "SHA3_384", "SHA3_512" + * + * @throws IllegalStateException if WolfSSLCertificate has been freed. + * @throws IOException on error opening input file + * @throws WolfSSLException if invalid arguments or native JNI error occurs. + */ + public void signCert(String filePath, int keyType, int format, + String digestAlg) throws IllegalStateException, IOException, + WolfSSLException { + + int ret = 0; + File keyFile = null; + + confirmObjectIsActive(); + + if (filePath == null || filePath.isEmpty()) { + throw new WolfSSLException("File path is null or empty"); + } + + keyFile = new File(filePath); + if (!keyFile.exists()) { + throw new WolfSSLException("Input file does not exist: " + + filePath); + } + + signCert(Files.readAllBytes(keyFile.toPath()), keyType, format, + digestAlg); + } + + /** + * Sign certificate with private key from buffer. + * + * @param key Byte array containing private key + * @param keyType Type of public key algorithm, options are: + * WolfSSL.RSAk + * WolfSSL.ECDSAk + * @param format Format of private key file, options are: + * WolfSSL.SSL_FILETYPE_ASN1 (DER formatted) + * WolfSSL.SSL_FILETYPE_PEM (PEM formatted) + * @param digestAlg Message digest algorithm to use for signature + * generation. Options include the following, but native algorithm + * must be compiled into wolfSSL to be available: + * "MD4", "MD5", "SHA1", "SHA224", "SHA256", "SHA384", + * "SHA512", "SHA3_224", "SHA3_256", "SHA3_384", "SHA3_512" + * + * @throws IllegalStateException if WolfSSLCertificate has been freed. + * @throws WolfSSLException if invalid arguments or native JNI error occurs. + */ + public void signCert(byte[] key, int keyType, int format, + String digestAlg) throws IllegalStateException, WolfSSLException { + + int ret = 0; + int evpKeyType; + + confirmObjectIsActive(); + + if (key == null || key.length == 0) { + throw new WolfSSLException("Key array is null or empty"); + } + + if (format != WolfSSL.SSL_FILETYPE_ASN1 && + format != WolfSSL.SSL_FILETYPE_PEM) { + throw new WolfSSLException( + "Invalid key format, must be PEM or DER"); + } + + switch (keyType) { + case WolfSSL.RSAk: + evpKeyType = EVP_PKEY_RSA; + break; + case WolfSSL.ECDSAk: + evpKeyType = EVP_PKEY_EC; + break; + default: + throw new WolfSSLException("Unsupported private key type"); + } + + synchronized (x509Lock) { + ret = X509_sign(this.x509Ptr, evpKeyType, key, format, digestAlg); + } + + if (ret != WolfSSL.SSL_SUCCESS) { + throw new WolfSSLException( + "Error signing native WOLFSSL_X509 " + + "(ret: " + ret + ")"); + } + } + + /** + * Sign certificate with private key from PrivateKey object. + * + * @param key java.security.PrivateKey object containing private key, + * must be of type RSAPrivateKey or ECPrivateKey + * @param digestAlg Message digest algorithm to use for signature + * generation. Options include the following, but native algorithm + * must be compiled into wolfSSL to be available: + * "MD4", "MD5", "SHA1", "SHA224", "SHA256", "SHA384", + * "SHA512", "SHA3_224", "SHA3_256", "SHA3_384", "SHA3_512" + * + * @throws IllegalStateException if WolfSSLCertificate has been freed. + * @throws WolfSSLException if invalid arguments or native JNI error occurs. + */ + public void signCert(PrivateKey key, String digestAlg) + throws IllegalStateException, WolfSSLException { + + int ret = 0; + int evpKeyType; + byte[] encodedKey = null; + + confirmObjectIsActive(); + + if (key == null) { + throw new WolfSSLException("Key object is null"); + } + + if (key instanceof RSAPrivateKey) { + evpKeyType = EVP_PKEY_RSA; + } + else if (key instanceof ECPrivateKey) { + evpKeyType = EVP_PKEY_EC; + } + else { + throw new WolfSSLException( + "PrivateKey must be of type RSAPrivateKey or ECPrivateKey"); + } + + /* Get DER encoded key */ + encodedKey = key.getEncoded(); + if (encodedKey == null) { + throw new WolfSSLException("PrivateKey does not support encoding"); + } + + synchronized (x509Lock) { + ret = X509_sign(this.x509Ptr, evpKeyType, encodedKey, + WolfSSL.SSL_FILETYPE_ASN1, digestAlg); + } + + if (ret != WolfSSL.SSL_SUCCESS) { + throw new WolfSSLException( + "Error signing native WOLFSSL_X509 " + + "(ret: " + ret + ")"); + } + } + /** * Get ASN.1/DER encoding of this X.509 certificate * * @return DER encoded array of certificate or null if not available. + * + * @throws IllegalStateException if WolfSSLCertificate has been freed. + * @throws WolfSSLJNIException if native JNI operation fails */ - public byte[] getDer() { + public byte[] getDer() throws IllegalStateException, WolfSSLJNIException { - synchronized (stateLock) { - if (this.active == true) { - return X509_get_der(this.x509Ptr); - } + confirmObjectIsActive(); + + synchronized (x509Lock) { + return X509_get_der(this.x509Ptr); } + } - return null; + /** + * Get PEM encoding of this X.509 certificate + * + * @return PEM encoded array of certificate or null if not available. + * + * @throws IllegalStateException if WolfSSLCertificate has been freed. + * @throws WolfSSLJNIException if native JNI operation fails + */ + public byte[] getPem() throws IllegalStateException, WolfSSLJNIException { + + confirmObjectIsActive(); + + synchronized (x509Lock) { + return X509_get_pem(this.x509Ptr); + } } /** * Get buffer that is To Be Signed (Tbs) * * @return byte array to be signed + * + * @throws IllegalStateException if WolfSSLCertificate has been freed. */ - public byte[] getTbs() { + public byte[] getTbs() throws IllegalStateException { - synchronized (stateLock) { - if (this.active == true) { - return X509_get_tbs(this.x509Ptr); - } + confirmObjectIsActive(); + + synchronized (x509Lock) { + return X509_get_tbs(this.x509Ptr); } - - return null; } /** * Get X.509 serial number as BigInteger * * @return serial number as BigInteger, or null if not available + * + * @throws IllegalStateException if WolfSSLCertificate has been freed. */ - public BigInteger getSerial() { + public BigInteger getSerial() throws IllegalStateException { + byte[] out = new byte[32]; int sz; - synchronized (stateLock) { - if (this.active == false) { - return null; - } + confirmObjectIsActive(); - sz = X509_get_serial_number(this.x509Ptr, out); - if (sz <= 0) { - return null; - } - else { - byte[] serial = Arrays.copyOf(out, sz); - return new BigInteger(serial); - } + synchronized (x509Lock) { + sz = X509_get_serial_number(this.x509Ptr, out); + } + if (sz <= 0) { + return null; + } + else { + byte[] serial = Arrays.copyOf(out, sz); + return new BigInteger(serial); } } @@ -297,26 +1056,28 @@ public class WolfSSLCertificate { * Get X.509 validity notBefore date * * @return notBefore date as Date object, or null if not available + * + * @throws IllegalStateException if WolfSSLCertificate has been freed. */ - public Date notBefore() { + public Date notBefore() throws IllegalStateException { + String nb; - synchronized (stateLock) { - if (this.active == false) { - return null; - } + confirmObjectIsActive(); + synchronized (x509Lock) { nb = X509_notBefore(this.x509Ptr); - if (nb != null) { - SimpleDateFormat format = - new SimpleDateFormat("MMM dd HH:mm:ss yyyy zzz"); - try { - return format.parse(nb); - } catch (ParseException ex) { - /* error case parsing date */ - } + } + if (nb != null) { + SimpleDateFormat format = + new SimpleDateFormat("MMM dd HH:mm:ss yyyy zzz"); + try { + return format.parse(nb); + } catch (ParseException ex) { + /* error case parsing date */ } } + return null; } @@ -324,26 +1085,28 @@ public class WolfSSLCertificate { * Get X.509 validity notAfter date * * @return notAfter date as Date object, or null if not available + * + * @throws IllegalStateException if WolfSSLCertificate has been freed. */ - public Date notAfter() { + public Date notAfter() throws IllegalStateException { + String nb; - synchronized (stateLock) { - if (this.active == false) { - return null; - } + confirmObjectIsActive(); + synchronized (x509Lock) { nb = X509_notAfter(this.x509Ptr); - if (nb != null) { - SimpleDateFormat format = - new SimpleDateFormat("MMM dd HH:mm:ss yyyy zzz"); - try { - return format.parse(nb); - } catch (ParseException ex) { - /* error case parsing date */ - } + } + if (nb != null) { + SimpleDateFormat format = + new SimpleDateFormat("MMM dd HH:mm:ss yyyy zzz"); + try { + return format.parse(nb); + } catch (ParseException ex) { + /* error case parsing date */ } } + return null; } @@ -351,160 +1114,160 @@ public class WolfSSLCertificate { * Get X.509 version * * @return version of X.509 certificate + * + * @throws IllegalStateException if WolfSSLCertificate has been freed. */ - public int getVersion() { + public int getVersion() throws IllegalStateException { - synchronized (stateLock) { - if (this.active == true) { - return X509_version(this.x509Ptr); - } + confirmObjectIsActive(); + + synchronized (x509Lock) { + return X509_version(this.x509Ptr); } - - return 0; } /** * Get signature from X.509 certificate * * @return byte array with signature from X.509 certificate, or null + * + * @throws IllegalStateException if WolfSSLCertificate has been freed. */ - public byte[] getSignature() { + public byte[] getSignature() throws IllegalStateException { - synchronized (stateLock) { - if (this.active == true) { - return X509_get_signature(this.x509Ptr); - } + confirmObjectIsActive(); + + synchronized (x509Lock) { + return X509_get_signature(this.x509Ptr); } - - return null; } /** * Get signature type from X.509 certificate * * @return signature type String, or null + * + * @throws IllegalStateException if WolfSSLCertificate has been freed. */ - public String getSignatureType() { + public String getSignatureType() throws IllegalStateException { - synchronized (stateLock) { - if (this.active == true) { - return X509_get_signature_type(this.x509Ptr); - } + confirmObjectIsActive(); + + synchronized (x509Lock) { + return X509_get_signature_type(this.x509Ptr); } - - return null; } /** * Get X.509 signature algorithm OID * * @return algorithm OID of signature, or null + * + * @throws IllegalStateException if WolfSSLCertificate has been freed. */ - public String getSignatureOID() { + public String getSignatureOID() throws IllegalStateException { - synchronized (stateLock) { - if (this.active == true) { - return X509_get_signature_OID(this.x509Ptr); - } + confirmObjectIsActive(); + + synchronized (x509Lock) { + return X509_get_signature_OID(this.x509Ptr); } - - return null; } /** * Get public key from X.509 certificate * * @return certificate public key, byte array. Or null. + * + * @throws IllegalStateException if WolfSSLCertificate has been freed. */ - public byte[] getPubkey() { + public byte[] getPubkey() throws IllegalStateException { - synchronized (stateLock) { - if (this.active == true) { - return X509_get_pubkey(this.x509Ptr); - } + confirmObjectIsActive(); + + synchronized (x509Lock) { + return X509_get_pubkey(this.x509Ptr); } - - return null; } /** * Get public key type of certificate * * @return public key type String, or null + * + * @throws IllegalStateException if WolfSSLCertificate has been freed. */ - public String getPubkeyType() { + public String getPubkeyType() throws IllegalStateException { - synchronized (stateLock) { - if (this.active == true) { - return X509_get_pubkey_type(this.x509Ptr); - } + confirmObjectIsActive(); + + synchronized (x509Lock) { + return X509_get_pubkey_type(this.x509Ptr); } - - return null; } /** * Get certificate isCA value * * @return X.509 isCA value + * + * @throws IllegalStateException if WolfSSLCertificate has been freed. */ - public int isCA() { + public int isCA() throws IllegalStateException { - synchronized (stateLock) { - if (this.active == true) { - return X509_get_isCA(this.x509Ptr); - } + confirmObjectIsActive(); + + synchronized (x509Lock) { + return X509_get_isCA(this.x509Ptr); } - - return 0; } /** * Get certificate path length * * @return path length, or -1 if not set + * + * @throws IllegalStateException if WolfSSLCertificate has been freed. */ - public int getPathLen() { + public int getPathLen() throws IllegalStateException { - synchronized (stateLock) { - if (this.active == true) { - return X509_get_pathLength(this.x509Ptr); - } + confirmObjectIsActive(); + + synchronized (x509Lock) { + return X509_get_pathLength(this.x509Ptr); } - - return 0; } /** * Get certificate Subject * * @return X.509 Subject String, or null + * + * @throws IllegalStateException if WolfSSLCertificate has been freed. */ - public String getSubject() { + public String getSubject() throws IllegalStateException { - synchronized (stateLock) { - if (this.active == true) { - return X509_get_subject_name(this.x509Ptr); - } + confirmObjectIsActive(); + + synchronized (x509Lock) { + return X509_get_subject_name(this.x509Ptr); } - - return null; } /** * Get certificate Issuer * * @return X.509 Issuer String, or null + * + * @throws IllegalStateException if WolfSSLCertificate has been freed. */ - public String getIssuer() { + public String getIssuer() throws IllegalStateException { - synchronized (stateLock) { - if (this.active == true) { - return X509_get_issuer_name(this.x509Ptr); - } + confirmObjectIsActive(); + + synchronized (x509Lock) { + return X509_get_issuer_name(this.x509Ptr); } - - return null; } /** @@ -514,19 +1277,21 @@ public class WolfSSLCertificate { * @param pubKeySz size of public key array, bytes * * @return true if verified, otherwise false + * + * @throws IllegalStateException if WolfSSLCertificate has been freed. */ - public boolean verify(byte[] pubKey, int pubKeySz) { + public boolean verify(byte[] pubKey, int pubKeySz) + throws IllegalStateException { + int ret; - synchronized (stateLock) { - if (this.active == false) { - return false; - } + confirmObjectIsActive(); + synchronized (x509Lock) { ret = X509_verify(this.x509Ptr, pubKey, pubKeySz); - if (ret == WolfSSL.SSL_SUCCESS) { - return true; - } + } + if (ret == WolfSSL.SSL_SUCCESS) { + return true; } return false; @@ -547,16 +1312,16 @@ public class WolfSSLCertificate { * [8] = KEYUSE_DECIPHER_ONLY * * @return arrray of key usages set for certificate, or null + * + * @throws IllegalStateException if WolfSSLCertificate has been freed. */ - public boolean[] getKeyUsage() { + public boolean[] getKeyUsage() throws IllegalStateException { - synchronized (stateLock) { - if (this.active == true) { - return X509_get_key_usage(this.x509Ptr); - } + confirmObjectIsActive(); + + synchronized (x509Lock) { + return X509_get_key_usage(this.x509Ptr); } - - return null; } /** @@ -565,13 +1330,18 @@ public class WolfSSLCertificate { * @param oid OID value of extension to retreive value for * * @return DER encoded extension value, or null + * + * @throws IllegalStateException if WolfSSLCertificate has been freed. */ - public byte[] getExtension(String oid) { + public byte[] getExtension(String oid) throws IllegalStateException { - synchronized (stateLock) { - if (oid == null || this.active == false) { - return null; - } + confirmObjectIsActive(); + + if (oid == null) { + return null; + } + + synchronized (x509Lock) { return X509_get_extension(this.x509Ptr, oid); } } @@ -585,13 +1355,14 @@ public class WolfSSLCertificate { * 2 if extension OID is set and is critical, * 0 if not set, * otherwise negative value on error + * + * @throws IllegalStateException if WolfSSLCertificate has been freed. */ - public int getExtensionSet(String oid) { + public int getExtensionSet(String oid) throws IllegalStateException { - synchronized (stateLock) { - if (this.active == false) { - return 0; - } + confirmObjectIsActive(); + + synchronized (x509Lock) { return X509_is_extension_set(this.x509Ptr, oid); } } @@ -608,21 +1379,22 @@ public class WolfSSLCertificate { * second list element being a String. * * @return immutable Collection of subject alternative names, or null + * + * @throws IllegalStateException if WolfSSLCertificate has been freed. */ - public Collection> getSubjectAltNames() { + public Collection> getSubjectAltNames() + throws IllegalStateException { - synchronized (stateLock) { - if (this.active == false) { - throw new IllegalStateException("Object has been freed"); - } + confirmObjectIsActive(); - if (this.altNames != null) { - /* already gathered, return cached version */ - return this.altNames; - } + if (this.altNames != null) { + /* already gathered, return cached version */ + return this.altNames; + } - Collection> names = new ArrayList>(); + Collection> names = new ArrayList>(); + synchronized (x509Lock) { String nextAltName = X509_get_next_altname(this.x509Ptr); while (nextAltName != null) { Object[] entry = new Object[2]; @@ -633,44 +1405,43 @@ public class WolfSSLCertificate { 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; } + + /* cache altNames collection for later use */ + this.altNames = Collections.unmodifiableCollection(names); + + return this.altNames; } /** * Returns X509Certificate object based on this certificate. * * @return X509Certificate object + * + * @throws IllegalStateException if WolfSSLCertificate has been freed. * @throws CertificateException on error * @throws IOException on error closing ByteArrayInputStream + * @throws WolfSSLJNIException if native JNI error occurs */ public X509Certificate getX509Certificate() - throws CertificateException, IOException { + throws IllegalStateException, CertificateException, IOException, + WolfSSLJNIException { X509Certificate cert = null; InputStream in = null; - CertificateFactory cf = CertificateFactory.getInstance("X.509"); - synchronized (stateLock) { - if (this.active == false) { - throw new CertificateException("Object has been freed"); - } + confirmObjectIsActive(); - try { - in = new ByteArrayInputStream(this.getDer()); - cert = (X509Certificate)cf.generateCertificate(in); + try { + in = new ByteArrayInputStream(this.getDer()); + cert = (X509Certificate)cf.generateCertificate(in); + in.close(); + + } catch (Exception e) { + if (in != null) { in.close(); - - } catch (Exception e) { - if (in != null) { - in.close(); - throw e; - } + throw e; } } @@ -687,7 +1458,9 @@ public class WolfSSLCertificate { return super.toString(); } - x509Text = X509_print(this.x509Ptr); + synchronized (x509Lock) { + x509Text = X509_print(this.x509Ptr); + } if (x509Text != null) { /* let Java do the modified UTF-8 conversion */ return new String(x509Text, Charset.forName("UTF-8")); @@ -698,11 +1471,9 @@ public class WolfSSLCertificate { } /** - * Frees an X509. - * - * @throws IllegalStateException WolfSSLCertificate has been freed + * Frees WolfSSLCertificate native resources. */ - public synchronized void free() throws IllegalStateException { + public synchronized void free() { synchronized (stateLock) { if (this.active == false) { @@ -713,15 +1484,17 @@ public class WolfSSLCertificate { /* set this.altNames to null so GC can free */ this.altNames = null; - /* only free native resources if we own pointer */ - if (this.weOwnX509Ptr == true) { - /* free native resources */ - X509_free(this.x509Ptr); - } + synchronized (x509Lock) { + /* only free native resources if we own pointer */ + if (this.weOwnX509Ptr == true) { + /* free native resources */ + X509_free(this.x509Ptr); + } - /* free Java resources */ - this.active = false; - this.x509Ptr = 0; + /* free Java resources */ + this.active = false; + this.x509Ptr = 0; + } } } @@ -733,3 +1506,4 @@ public class WolfSSLCertificate { super.finalize(); } } + diff --git a/src/java/com/wolfssl/WolfSSLX509Name.java b/src/java/com/wolfssl/WolfSSLX509Name.java new file mode 100644 index 0000000..316add3 --- /dev/null +++ b/src/java/com/wolfssl/WolfSSLX509Name.java @@ -0,0 +1,527 @@ +/* WolfSSLX509Name.java + * + * Copyright (C) 2006-2023 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ +package com.wolfssl; + +/** + * WolfSSLX509Name class, wraps native WOLFSSL_X509_NAME functionality. + */ +public class WolfSSLX509Name { + + private boolean active = false; + private long x509NamePtr = 0; + + /* Lock around active state */ + private final Object stateLock = new Object(); + + /* Cache name elements in Java before pushing through JNI, for easier + * retrieval from getXXX() methods */ + private String countryName = null; + private String stateOrProvinceName = null; + private String streetAddress = null; + private String localityName = null; + private String surname = null; + private String commonName = null; + private String emailAddress = null; + private String organizationName = null; + private String organizationalUnitName = null; + private String postalCode = null; + private String userId = null; + + /* Encoding types, matched to native define values */ + private static final int MBSTRING_UTF8 = 0x100; + + /* Native JNI methods */ + static native long X509_NAME_new(); + static native void X509_NAME_free(long x509Name); + static native int X509_NAME_add_entry_by_txt(long x509Name, String field, + int type, byte[] entry, int len, int loc, int set); + + /** + * Create new empty WolfSSLX509Name object. + * + * @throws WolfSSLException if native API call fails. + */ + public WolfSSLX509Name() throws WolfSSLException { + + x509NamePtr = X509_NAME_new(); + if (x509NamePtr == 0) { + throw new WolfSSLException("Failed to create WolfSSLX509Name"); + } + + synchronized (stateLock) { + this.active = true; + } + } + + /** + * Verifies that the current WolfSSLX509Name object is active. + * + * @throws IllegalStateException if object has been freed + */ + private void confirmObjectIsActive() + throws IllegalStateException { + + synchronized (stateLock) { + if (this.active == false) { + throw new IllegalStateException( + "WolfSSLX509Name object has been freed"); + } + } + } + + /** + * For package use only, return native WOLFSSL_X509_NAME pointer. + * + * @return native WOLFSSL_X509_POINTER value + * @throws IllegalStateException if WolfSSLX509Name has been freed. + */ + protected long getNativeX509NamePtr() throws IllegalStateException { + + confirmObjectIsActive(); + + /* TODO lock around x509NamePtr */ + return this.x509NamePtr; + } + + /** + * Private helper function to call native JNI function + * X509_NAME_add_entry_by_txt(). + * + * @param field String containing field name to set, for example + * "countryName" + * @param entry String value to store into field + * + * @throws WolfSSLException if arguments are invalid or error occurs + * with native JNI call. + */ + private synchronized void addEntryByTxt(String field, String entry) + throws WolfSSLException { + + int ret = 0; + + if (field == null || entry == null) { + throw new WolfSSLException("field or entry is null in " + + "addEntryByTxt()"); + } + + ret = X509_NAME_add_entry_by_txt(this.x509NamePtr, field, + MBSTRING_UTF8, entry.getBytes(), + entry.getBytes().length, -1, 0); + + if (ret != WolfSSL.SSL_SUCCESS) { + throw new WolfSSLException("Error setting " + field + " into " + + "WolfSSLX509Name (error: " + ret + ")"); + } + } + + /** + * Set country name for this name object. + * + * @param countryName String containing country name to be set + * + * @throws IllegalStateException if WolfSSLX509Name has been freed. + * @throws WolfSSLException if native JNI error has occurred, or input + * argument is invalid. + */ + public synchronized void setCountryName(String countryName) + throws IllegalStateException, WolfSSLException { + + confirmObjectIsActive(); + + addEntryByTxt("countryName", countryName); + this.countryName = countryName; + } + + /** + * Set state or province name for this name object. + * + * @param name String containing state or province name to be set + * + * @throws IllegalStateException if WolfSSLX509Name has been freed. + * @throws WolfSSLException if native JNI error has occurred, or input + * argument is invalid. + */ + public synchronized void setStateOrProvinceName(String name) + throws IllegalStateException, WolfSSLException { + + confirmObjectIsActive(); + + addEntryByTxt("stateOrProvinceName", name); + this.stateOrProvinceName = name; + } + + /** + * Set street address for this name object. + * + * @param address String containing street address to be set + * + * @throws IllegalStateException if WolfSSLX509Name has been freed. + * @throws WolfSSLException if native JNI error has occurred, or input + * argument is invalid. + */ + public synchronized void setStreetAddress(String address) + throws IllegalStateException, WolfSSLException { + + confirmObjectIsActive(); + + addEntryByTxt("streetAddress", address); + this.streetAddress = address; + } + + /** + * Set locality name / city for this name object. + * + * @param name String containing locality name to be set + * + * @throws IllegalStateException if WolfSSLX509Name has been freed. + * @throws WolfSSLException if native JNI error has occurred, or input + * argument is invalid. + */ + public synchronized void setLocalityName(String name) + throws IllegalStateException, WolfSSLException { + + confirmObjectIsActive(); + + addEntryByTxt("localityName", name); + this.localityName = name; + } + + /** + * Set surname for this name object. + * + * @param name String containing surname to be set + * + * @throws IllegalStateException if WolfSSLX509Name has been freed. + * @throws WolfSSLException if native JNI error has occurred, or input + * argument is invalid. + */ + public synchronized void setSurname(String name) + throws IllegalStateException, WolfSSLException { + + confirmObjectIsActive(); + + addEntryByTxt("surname", name); + this.surname = name; + } + + /** + * Set common name for this name object. + * + * @param name String containing common name to be set + * + * @throws IllegalStateException if WolfSSLX509Name has been freed. + * @throws WolfSSLException if native JNI error has occurred, or input + * argument is invalid. + */ + public synchronized void setCommonName(String name) + throws IllegalStateException, WolfSSLException { + + confirmObjectIsActive(); + + addEntryByTxt("commonName", name); + this.commonName = name; + } + + /** + * Set email address for this name object. + * + * @param email String containing email address to be set + * + * @throws IllegalStateException if WolfSSLX509Name has been freed. + * @throws WolfSSLException if native JNI error has occurred, or input + * argument is invalid. + */ + public synchronized void setEmailAddress(String email) + throws IllegalStateException, WolfSSLException { + + confirmObjectIsActive(); + + addEntryByTxt("emailAddress", email); + this.emailAddress = email; + } + + /** + * Set organization name for this name object. + * + * @param name String containing organization name to be set + * + * @throws IllegalStateException if WolfSSLX509Name has been freed. + * @throws WolfSSLException if native JNI error has occurred, or input + * argument is invalid. + */ + public synchronized void setOrganizationName(String name) + throws IllegalStateException, WolfSSLException { + + confirmObjectIsActive(); + + addEntryByTxt("organizationName", name); + this.organizationName = name; + } + + /** + * Set organizational unit name for this name object. + * + * @param name String containing organizational unit name to be set + * + * @throws IllegalStateException if WolfSSLX509Name has been freed. + * @throws WolfSSLException if native JNI error has occurred, or input + * argument is invalid. + */ + public synchronized void setOrganizationalUnitName(String name) + throws IllegalStateException, WolfSSLException { + + confirmObjectIsActive(); + + addEntryByTxt("organizationalUnitName", name); + this.organizationalUnitName = name; + } + + /** + * Set postal code for this name object. + * + * @param code String containing postal code to be set + * + * @throws IllegalStateException if WolfSSLX509Name has been freed. + * @throws WolfSSLException if native JNI error has occurred, or input + * argument is invalid. + */ + public synchronized void setPostalCode(String code) + throws IllegalStateException, WolfSSLException { + + confirmObjectIsActive(); + + addEntryByTxt("postalCode", code); + this.postalCode = code; + } + + /** + * Set user ID for this name object. + * + * @param id String containing user ID to be set + * + * @throws IllegalStateException if WolfSSLX509Name has been freed. + * @throws WolfSSLException if native JNI error has occurred, or input + * argument is invalid. + */ + public synchronized void setUserId(String id) + throws IllegalStateException, WolfSSLException { + + confirmObjectIsActive(); + + addEntryByTxt("userId", id); + this.userId = id; + } + + /** + * Get country name set in this object. + * + * @return country name string, or null if not yet set + * + * @throws IllegalStateException if WolfSSLX509Name has been freed. + */ + public synchronized String getCountryName() { + + confirmObjectIsActive(); + + return this.countryName; + } + + /** + * Get state or province name set in this object. + * + * @return state or province name string, or null if not yet set + * + * @throws IllegalStateException if WolfSSLX509Name has been freed. + */ + public synchronized String getStateOrProvinceName() { + + confirmObjectIsActive(); + + return this.stateOrProvinceName; + } + + /** + * Get street address set in this object. + * + * @return street address string, or null if not yet set + * + * @throws IllegalStateException if WolfSSLX509Name has been freed. + */ + public synchronized String getStreetAddress() { + + confirmObjectIsActive(); + + return this.streetAddress; + } + + /** + * Get locality name set in this object. + * + * @return locality name string, or null if not yet set + * + * @throws IllegalStateException if WolfSSLX509Name has been freed. + */ + public synchronized String getLocalityName() { + + confirmObjectIsActive(); + + return this.localityName; + } + + /** + * Get surname set in this object. + * + * @return surname string, or null if not yet set + * + * @throws IllegalStateException if WolfSSLX509Name has been freed. + */ + public synchronized String getSurname() { + + confirmObjectIsActive(); + + return this.surname; + } + + /** + * Get common name set in this object. + * + * @return common name string, or null if not yet set + * + * @throws IllegalStateException if WolfSSLX509Name has been freed. + */ + public synchronized String getCommonName() { + + confirmObjectIsActive(); + + return this.commonName; + } + + /** + * Get email address set in this object. + * + * @return email address string, or null if not yet set + * + * @throws IllegalStateException if WolfSSLX509Name has been freed. + */ + public synchronized String getEmailAddress() { + + confirmObjectIsActive(); + + return this.emailAddress; + } + + /** + * Get organization name set in this object. + * + * @return organization name string, or null if not yet set + * + * @throws IllegalStateException if WolfSSLX509Name has been freed. + */ + public synchronized String getOrganizationName() { + + confirmObjectIsActive(); + + return this.organizationName; + } + + /** + * Get organizational unit name set in this object. + * + * @return organizational unit name string, or null if not yet set + * + * @throws IllegalStateException if WolfSSLX509Name has been freed. + */ + public synchronized String getOrganizationalUnitName() { + + confirmObjectIsActive(); + + return this.organizationalUnitName; + } + + /** + * Get postal code set in this object. + * + * @return postal code string, or null if not yet set + * + * @throws IllegalStateException if WolfSSLX509Name has been freed. + */ + public synchronized String getPostalCode() { + + confirmObjectIsActive(); + + return this.postalCode; + } + + /** + * Get user ID set in this object. + * + * @return user ID string, or null if not yet set + * + * @throws IllegalStateException if WolfSSLX509Name has been freed. + */ + public synchronized String getUserId() { + + confirmObjectIsActive(); + + return this.userId; + } + + @Override + public String toString() { + + synchronized (stateLock) { + if (this.active == false) { + return ""; + } + } + + /* TODO: wrap wolfSSL_X509_NAME_oneline() */ + return null; + } + + /** + * Free native resources of WolfSSLX509Name. + */ + public synchronized void free() { + + synchronized (stateLock) { + if (this.active == false) { + /* already freed, just return */ + return; + } + + /* free native resources */ + X509_NAME_free(this.x509NamePtr); + + this.active = false; + this.x509NamePtr = 0; + } + } + + @SuppressWarnings("deprecation") + @Override + protected void finalize() throws Throwable + { + this.free(); + super.finalize(); + } +} + diff --git a/src/java/com/wolfssl/provider/jsse/WolfSSLInternalVerifyCb.java b/src/java/com/wolfssl/provider/jsse/WolfSSLInternalVerifyCb.java index d24fb93..9b69883 100644 --- a/src/java/com/wolfssl/provider/jsse/WolfSSLInternalVerifyCb.java +++ b/src/java/com/wolfssl/provider/jsse/WolfSSLInternalVerifyCb.java @@ -22,6 +22,7 @@ package com.wolfssl.provider.jsse; import com.wolfssl.WolfSSLVerifyCallback; import com.wolfssl.WolfSSLException; +import com.wolfssl.WolfSSLJNIException; import com.wolfssl.WolfSSLCertificate; import com.wolfssl.WolfSSLX509StoreCtx; import com.wolfssl.provider.jsse.WolfSSLInternalVerifyCb; @@ -103,7 +104,8 @@ public class WolfSSLInternalVerifyCb implements WolfSSLVerifyCallback { WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO, "Peer cert: " + x509certs[i].getSubjectDN().getName()); } - } catch (CertificateException | IOException ce) { + } catch (CertificateException | IOException | + WolfSSLJNIException ce) { /* failed to get cert array, give app null array */ WolfSSLDebug.log(getClass(), WolfSSLDebug.INFO, "Failed to get X509Certificate[] array, set to null"); diff --git a/src/java/com/wolfssl/provider/jsse/WolfSSLTrustManager.java b/src/java/com/wolfssl/provider/jsse/WolfSSLTrustManager.java index 8bbe3db..535819b 100644 --- a/src/java/com/wolfssl/provider/jsse/WolfSSLTrustManager.java +++ b/src/java/com/wolfssl/provider/jsse/WolfSSLTrustManager.java @@ -40,6 +40,7 @@ import javax.net.ssl.TrustManagerFactorySpi; import com.wolfssl.WolfSSL; import com.wolfssl.WolfSSLCertificate; import com.wolfssl.WolfSSLException; +import com.wolfssl.WolfSSLJNIException; /** * wolfSSL implemenation of TrustManagerFactorySpi @@ -346,6 +347,8 @@ public class WolfSSLTrustManager extends TrustManagerFactorySpi { throw new KeyStoreException(ex); } catch (CertificateException ex) { throw new KeyStoreException(ex); + } catch (WolfSSLJNIException ex) { + throw new KeyStoreException(ex); } } this.store = certs; diff --git a/src/java/com/wolfssl/provider/jsse/WolfSSLX509.java b/src/java/com/wolfssl/provider/jsse/WolfSSLX509.java index 8f5fb34..dd021b0 100644 --- a/src/java/com/wolfssl/provider/jsse/WolfSSLX509.java +++ b/src/java/com/wolfssl/provider/jsse/WolfSSLX509.java @@ -45,6 +45,7 @@ import java.util.Collection; import com.wolfssl.WolfSSLCertificate; import com.wolfssl.WolfSSLException; +import com.wolfssl.WolfSSLJNIException; /** * wolfSSL implementation of X509Certificate @@ -334,11 +335,17 @@ public class WolfSSLX509 extends X509Certificate { if (this.cert == null) { return null; } - byte[] ret = this.cert.getDer(); - if (ret == null) { - throw new CertificateEncodingException(); + + try { + byte[] ret = this.cert.getDer(); + if (ret == null) { + throw new CertificateEncodingException(); + } + return ret; + + } catch (WolfSSLJNIException e) { + throw new CertificateEncodingException(e); } - return ret; } @Override diff --git a/src/test/com/wolfssl/test/WolfSSLCertificateTest.java b/src/test/com/wolfssl/test/WolfSSLCertificateTest.java index ff7d837..b6c401b 100644 --- a/src/test/com/wolfssl/test/WolfSSLCertificateTest.java +++ b/src/test/com/wolfssl/test/WolfSSLCertificateTest.java @@ -27,15 +27,37 @@ import java.io.IOException; import java.io.InputStream; import java.math.BigInteger; import java.nio.file.Files; +import java.nio.file.Paths; import java.util.Date; import java.util.logging.Level; import java.util.logging.Logger; -import static org.junit.Assert.fail; +import java.time.Instant; +import java.time.Duration; +import java.security.cert.CertificateException; +import java.security.cert.CertificateFactory; +import java.security.cert.X509Certificate; +import java.security.spec.PKCS8EncodedKeySpec; +import java.security.spec.InvalidKeySpecException; +import java.security.interfaces.RSAPrivateKey; +import java.security.KeyPairGenerator; +import java.security.KeyFactory; +import java.security.KeyPair; +import java.security.PublicKey; +import java.security.PrivateKey; +import java.security.NoSuchAlgorithmException; + import org.junit.Test; +import org.junit.BeforeClass; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; +import static org.junit.Assert.*; import com.wolfssl.WolfSSL; +import com.wolfssl.WolfSSLX509Name; import com.wolfssl.WolfSSLCertificate; +import com.wolfssl.WolfSSLCertManager; import com.wolfssl.WolfSSLException; +import com.wolfssl.WolfSSLJNIException; /** * @@ -47,19 +69,39 @@ public class WolfSSLCertificateTest { public static String cliCertDer = "examples/certs/client-cert.der"; public static String cliCertPem = "examples/certs/client-cert.pem"; + public static String cliKeyDer = "examples/certs/client-key.der"; + public static String cliKeyPubDer = "examples/certs/client-keyPub.der"; + public static String caCertPem = "examples/certs/ca-cert.pem"; + public static String caKeyDer = "examples/certs/ca-key.der"; + public static String caKeyPkcs8Der = "examples/certs/ca-keyPkcs8.der"; + public static String serverCertPem = "examples/certs/server-cert.pem"; public static String external = "examples/certs/ca-google-root.der"; public static String bogusFile = "/dev/null"; private WolfSSLCertificate cert; + @BeforeClass + public static void setCertPaths() throws WolfSSLException { + + try { + WolfSSL.loadLibrary(); + } catch (UnsatisfiedLinkError ule) { + fail("failed to load native JNI library"); + } + + cliCertDer = WolfSSLTestCommon.getPath(cliCertDer); + cliCertPem = WolfSSLTestCommon.getPath(cliCertPem); + cliKeyPubDer = WolfSSLTestCommon.getPath(cliKeyPubDer); + caCertPem = WolfSSLTestCommon.getPath(caCertPem); + caKeyDer = WolfSSLTestCommon.getPath(caKeyDer); + external = WolfSSLTestCommon.getPath(external); + } + + @Test public void testWolfSSLCertificate() throws WolfSSLException { System.out.println("WolfSSLCertificate Class"); - cliCertDer = WolfSSLTestCommon.getPath(cliCertDer); - cliCertPem = WolfSSLTestCommon.getPath(cliCertPem); - external = WolfSSLTestCommon.getPath(external); - /* WolfSSLCertificate(byte[] der) */ test_WolfSSLCertificate_new_derArray(); test_runCertTestsAfterConstructor(); @@ -79,7 +121,6 @@ public class WolfSSLCertificateTest { } } - public void test_runCertTestsAfterConstructor() { test_getSerial(); test_notBefore(); @@ -95,7 +136,11 @@ public class WolfSSLCertificateTest { test_getSignatureType(); test_verify(); test_getSignatureOID(); - test_getKeyUsage(); + if (WolfSSL.getLibVersionHex() > 0x05006003) { + /* Key Usage and Extended Key Usage only work with wolfSSL + * later than 5.6.3 */ + test_getKeyUsage(); + } test_getExtensionSet(); test_toString(); test_free(); @@ -208,11 +253,11 @@ public class WolfSSLCertificateTest { public void test_getSerial() { - byte[] expected = new byte[]{ - (byte)0x01, (byte)0x1a, (byte)0xeb, (byte)0x56, (byte)0xab, - (byte)0xdc, (byte)0x8b, (byte)0xf3, (byte)0xa6, (byte)0x1e, - (byte)0xf4, (byte)0x93, (byte)0x60, (byte)0x89, (byte)0xb7, - (byte)0x05, (byte)0x07, (byte)0x29, (byte)0x01, (byte)0x2c + byte[] expected = new byte[] { + (byte)0x73, (byte)0xfb, (byte)0x54, (byte)0xd6, (byte)0x03, + (byte)0x7d, (byte)0x4c, (byte)0x07, (byte)0x84, (byte)0xe2, + (byte)0x00, (byte)0x11, (byte)0x8c, (byte)0xdd, (byte)0x90, + (byte)0xdc, (byte)0x48, (byte)0x8d, (byte)0xea, (byte)0x53 }; byte[] serial; int i; @@ -232,7 +277,7 @@ public class WolfSSLCertificateTest { @SuppressWarnings("deprecation") public void test_notBefore() { Date date = cert.notBefore(); - Date expected = new Date("Feb 15 12:50:24 2022 GMT"); + Date expected = new Date("Dec 16 21:17:49 2022 GMT"); System.out.print("\t\tnotBefore"); if (date.compareTo(expected) != 0) { System.out.println("\t\t... failed"); @@ -245,7 +290,7 @@ public class WolfSSLCertificateTest { @SuppressWarnings("deprecation") public void test_notAfter() { Date date = cert.notAfter(); - Date expected = new Date("Nov 11 12:50:24 2024 GMT"); + Date expected = new Date("Sep 11 21:17:49 2025 GMT"); System.out.print("\t\tnotAfter"); if (date.compareTo(expected) != 0) { System.out.println("\t\t... failed"); @@ -268,49 +313,58 @@ public class WolfSSLCertificateTest { public void test_getSignature() { byte[] sig = cert.getSignature(); byte[] expected = new byte[] { - (byte)0x64, (byte)0x6d, (byte)0xa6, (byte)0x4a, (byte)0xa8, (byte)0x9f, - (byte)0xa7, (byte)0xe9, (byte)0x75, (byte)0x2c, (byte)0xf3, (byte)0x85, - (byte)0x3d, (byte)0x3e, (byte)0xaf, (byte)0x38, (byte)0xfb, (byte)0x6c, - (byte)0xc7, (byte)0xeb, (byte)0xc7, (byte)0xd0, (byte)0x2b, (byte)0xa2, - (byte)0x45, (byte)0xb5, (byte)0x65, (byte)0xbe, (byte)0xd0, (byte)0x13, - (byte)0x2c, (byte)0xf7, (byte)0xa3, (byte)0xc1, (byte)0xeb, (byte)0x3c, - (byte)0xb1, (byte)0xf8, (byte)0xb8, (byte)0x3d, (byte)0x63, (byte)0x8f, - (byte)0xca, (byte)0x08, (byte)0x4e, (byte)0x65, (byte)0x1d, (byte)0x2c, - (byte)0xce, (byte)0x34, (byte)0x6e, (byte)0x35, (byte)0x96, (byte)0x87, - (byte)0x93, (byte)0x30, (byte)0x5d, (byte)0xaa, (byte)0xc8, (byte)0xe9, - (byte)0xa0, (byte)0x9c, (byte)0x9b, (byte)0x84, (byte)0x78, (byte)0x3a, - (byte)0x52, (byte)0xa1, (byte)0x33, (byte)0x48, (byte)0x6e, (byte)0x84, - (byte)0x66, (byte)0x71, (byte)0x9c, (byte)0xcf, (byte)0xd1, (byte)0xc7, - (byte)0x7b, (byte)0x02, (byte)0x4c, (byte)0xe1, (byte)0x49, (byte)0x7c, - (byte)0x69, (byte)0x47, (byte)0xfc, (byte)0xb7, (byte)0x01, (byte)0xf9, - (byte)0xa0, (byte)0x39, (byte)0x3b, (byte)0xab, (byte)0xb9, (byte)0xc6, - (byte)0xd9, (byte)0xca, (byte)0x27, (byte)0x85, (byte)0xf0, (byte)0x5c, - (byte)0xb6, (byte)0xa4, (byte)0xe6, (byte)0xdc, (byte)0xf2, (byte)0x52, - (byte)0xfe, (byte)0x44, (byte)0x00, (byte)0xb6, (byte)0xf0, (byte)0x47, - (byte)0xf2, (byte)0x6f, (byte)0x3f, (byte)0xd5, (byte)0x0f, (byte)0xff, - (byte)0x31, (byte)0x93, (byte)0x53, (byte)0x88, (byte)0x8c, (byte)0xc7, - (byte)0xfb, (byte)0x56, (byte)0x10, (byte)0x4b, (byte)0x3b, (byte)0x43, - (byte)0xe6, (byte)0x8a, (byte)0x9c, (byte)0xb7, (byte)0xb4, (byte)0x9a, - (byte)0xdd, (byte)0x5c, (byte)0xe3, (byte)0xcd, (byte)0x9c, (byte)0xbd, - (byte)0xa7, (byte)0x0c, (byte)0xc1, (byte)0xd9, (byte)0x96, (byte)0xf0, - (byte)0x93, (byte)0xf3, (byte)0xab, (byte)0xbd, (byte)0xd2, (byte)0x1e, - (byte)0x77, (byte)0x8a, (byte)0x42, (byte)0xcd, (byte)0x0f, (byte)0xfe, - (byte)0x48, (byte)0xda, (byte)0x57, (byte)0x34, (byte)0x61, (byte)0x46, - (byte)0xa3, (byte)0x89, (byte)0x2e, (byte)0x31, (byte)0xd2, (byte)0x4a, - (byte)0xd4, (byte)0x43, (byte)0x2f, (byte)0x56, (byte)0x85, (byte)0x44, - (byte)0x75, (byte)0xca, (byte)0x6b, (byte)0x36, (byte)0xe2, (byte)0xe8, - (byte)0x3a, (byte)0xb2, (byte)0x95, (byte)0x95, (byte)0x3a, (byte)0x28, - (byte)0x90, (byte)0x8d, (byte)0xc0, (byte)0x23, (byte)0xfb, (byte)0x3c, - (byte)0xd2, (byte)0x1a, (byte)0x73, (byte)0x6b, (byte)0xef, (byte)0xfd, - (byte)0xd6, (byte)0x1b, (byte)0xeb, (byte)0x6d, (byte)0x67, (byte)0x2a, - (byte)0xe1, (byte)0xeb, (byte)0x2a, (byte)0x83, (byte)0x22, (byte)0xad, - (byte)0xe3, (byte)0x95, (byte)0x19, (byte)0xe5, (byte)0x93, (byte)0xee, - (byte)0x14, (byte)0xdc, (byte)0xb5, (byte)0x7d, (byte)0xe7, (byte)0xcf, - (byte)0x89, (byte)0x8c, (byte)0xd7, (byte)0x8f, (byte)0xd2, (byte)0x3f, - (byte)0x68, (byte)0x7e, (byte)0xa9, (byte)0x74, (byte)0x7c, (byte)0x1b, - (byte)0x38, (byte)0x65, (byte)0xf9, (byte)0x28, (byte)0x4d, (byte)0xff, - (byte)0x50, (byte)0xc8, (byte)0xee, (byte)0x51, (byte)0x3a, (byte)0x8f, - (byte)0x1d, (byte)0x9e, (byte)0x55, (byte)0x5e + (byte)0x36, (byte)0xcb, (byte)0xbc, (byte)0xc5, (byte)0x52, + (byte)0x9a, (byte)0x66, (byte)0xcd, (byte)0x91, (byte)0x4d, + (byte)0x8f, (byte)0x27, (byte)0x9f, (byte)0xb3, (byte)0x64, + (byte)0x80, (byte)0x0e, (byte)0x64, (byte)0xb4, (byte)0xcb, + (byte)0x1a, (byte)0xcd, (byte)0x75, (byte)0x9e, (byte)0x82, + (byte)0x7c, (byte)0x55, (byte)0x67, (byte)0xd8, (byte)0x9f, + (byte)0x90, (byte)0xa3, (byte)0x34, (byte)0x96, (byte)0x99, + (byte)0x43, (byte)0xf7, (byte)0x49, (byte)0x53, (byte)0xa2, + (byte)0x58, (byte)0x85, (byte)0xa0, (byte)0xb3, (byte)0x83, + (byte)0x4f, (byte)0xaf, (byte)0xb8, (byte)0x15, (byte)0x8a, + (byte)0x88, (byte)0x1e, (byte)0xf3, (byte)0x60, (byte)0xf4, + (byte)0x7c, (byte)0x94, (byte)0xb5, (byte)0x58, (byte)0x68, + (byte)0xf1, (byte)0x2a, (byte)0x13, (byte)0x80, (byte)0x34, + (byte)0xc2, (byte)0x6f, (byte)0xa5, (byte)0xf8, (byte)0x7e, + (byte)0x76, (byte)0x16, (byte)0x81, (byte)0x4f, (byte)0x36, + (byte)0x8b, (byte)0xc3, (byte)0x59, (byte)0xbd, (byte)0x51, + (byte)0xdd, (byte)0x60, (byte)0x87, (byte)0xd7, (byte)0x1d, + (byte)0x96, (byte)0x44, (byte)0x69, (byte)0x07, (byte)0x3c, + (byte)0x8f, (byte)0x28, (byte)0x56, (byte)0xb1, (byte)0x11, + (byte)0x5c, (byte)0x4e, (byte)0x81, (byte)0x3f, (byte)0x57, + (byte)0x25, (byte)0xfd, (byte)0x65, (byte)0xdd, (byte)0x07, + (byte)0xcf, (byte)0x17, (byte)0x0a, (byte)0x01, (byte)0x7e, + (byte)0x4e, (byte)0x3f, (byte)0x8e, (byte)0x73, (byte)0xdb, + (byte)0xfe, (byte)0xf4, (byte)0xf2, (byte)0xc5, (byte)0xff, + (byte)0xa3, (byte)0x76, (byte)0xa8, (byte)0x74, (byte)0x46, + (byte)0x2e, (byte)0x47, (byte)0x0d, (byte)0xb0, (byte)0xed, + (byte)0x0a, (byte)0xc0, (byte)0xc5, (byte)0x0a, (byte)0x65, + (byte)0xd3, (byte)0xdc, (byte)0x62, (byte)0xb2, (byte)0xe0, + (byte)0x1e, (byte)0x8e, (byte)0xbd, (byte)0xf3, (byte)0xbd, + (byte)0xaf, (byte)0xaf, (byte)0x66, (byte)0x84, (byte)0x36, + (byte)0x92, (byte)0xe2, (byte)0x3b, (byte)0x80, (byte)0xd0, + (byte)0x57, (byte)0xa6, (byte)0x41, (byte)0xa3, (byte)0x62, + (byte)0xd1, (byte)0xa6, (byte)0x6d, (byte)0x14, (byte)0x6c, + (byte)0xcd, (byte)0x82, (byte)0xb1, (byte)0xc1, (byte)0xc1, + (byte)0x35, (byte)0x55, (byte)0xae, (byte)0x59, (byte)0x49, + (byte)0xa8, (byte)0x26, (byte)0x52, (byte)0xbd, (byte)0xef, + (byte)0x1b, (byte)0x2c, (byte)0x1f, (byte)0x9d, (byte)0x39, + (byte)0x04, (byte)0xd2, (byte)0x82, (byte)0xa0, (byte)0x6b, + (byte)0x39, (byte)0x71, (byte)0x59, (byte)0x33, (byte)0x82, + (byte)0xba, (byte)0x55, (byte)0x6c, (byte)0x97, (byte)0xf2, + (byte)0x1b, (byte)0x5b, (byte)0xe0, (byte)0x4d, (byte)0xe2, + (byte)0xcf, (byte)0x89, (byte)0xe7, (byte)0x26, (byte)0xb8, + (byte)0x2c, (byte)0x6c, (byte)0x9f, (byte)0x83, (byte)0xd6, + (byte)0xed, (byte)0x4e, (byte)0x2f, (byte)0x75, (byte)0xa9, + (byte)0x30, (byte)0x4e, (byte)0x01, (byte)0x95, (byte)0x0d, + (byte)0x4f, (byte)0x83, (byte)0x5e, (byte)0xc8, (byte)0xaf, + (byte)0x7f, (byte)0x67, (byte)0xea, (byte)0x53, (byte)0xbf, + (byte)0xca, (byte)0x9b, (byte)0x1f, (byte)0xd4, (byte)0xff, + (byte)0x36, (byte)0x97, (byte)0x02, (byte)0x71, (byte)0x8e, + (byte)0x33, (byte)0xde, (byte)0xe2, (byte)0x58, (byte)0x27, + (byte)0xaa, (byte)0x70, (byte)0x0c, (byte)0x5b, (byte)0xde, + (byte)0x0e }; int i; System.out.print("\t\tgetSignature"); @@ -577,4 +631,616 @@ public class WolfSSLCertificateTest { this.cert.free(); System.out.println("\t\t\t... passed"); } + + @Test + public void testWolfSSLCertificateGeneration() + throws WolfSSLException, WolfSSLJNIException, IOException, + CertificateException, NoSuchAlgorithmException, + InvalidKeySpecException { + + System.out.println("WolfSSLCertificate Generation"); + + if (WolfSSL.FileSystemEnabled() == true) { + testCertGen_SelfSigned_UsingFiles(); + testCertGen_SelfSigned_UsingBuffers(); + testCertGen_SelfSigned_UsingJavaClasses(); + testCertGen_CASigned_UsingFiles(); + testCertGen_CASigned_UsingBuffers(); + testCertGen_CASigned_UsingJavaClasses(); + } + } + + /* Quick sanity check on certificate bytes. Loads cert into new + * WolfSSLCertificate object, tries to get various elements and + * simply verify if not null / etc. */ + private void sanityCheckCertFileBytes(byte[] certBytes, int type) + throws WolfSSLException, WolfSSLJNIException, IOException, + CertificateException { + + if (certBytes == null || + (type != WolfSSL.SSL_FILETYPE_ASN1 && + type != WolfSSL.SSL_FILETYPE_PEM)) { + throw new WolfSSLException("certBytes is null or bad type"); + } + + WolfSSLCertificate tmp = new WolfSSLCertificate(certBytes, type); + assertNotNull(tmp); + assertNotNull(tmp.getDer()); + assertNotNull(tmp.getPem()); + assertNotNull(tmp.getTbs()); + assertNotNull(tmp.getSerial()); + assertNotNull(tmp.notBefore()); + assertNotNull(tmp.notAfter()); + assertTrue(tmp.getVersion() >= 0); + assertNotNull(tmp.getSignature()); + assertNotNull(tmp.getSignatureType()); + assertNotNull(tmp.getSignatureOID()); + assertNotNull(tmp.getPubkey()); + assertNotNull(tmp.getPubkeyType()); + int isCA = tmp.isCA(); + assertTrue(isCA == 0 || isCA == 1); + assertTrue(tmp.getPathLen() >= -1); + assertNotNull(tmp.getSubject()); + assertNotNull(tmp.getIssuer()); + if (WolfSSL.getLibVersionHex() > 0x05006003) { + /* Key Usage and Extended Key Usage only work with wolfSSL + * later than 5.6.3 */ + assertNotNull(tmp.getKeyUsage()); + } + assertNotNull(tmp.getSubjectAltNames()); + assertNotNull(tmp.getX509Certificate()); + assertNotNull(tmp.toString()); + } + + /* Make sure peer cert can be verified using CertManager and provided + * CA cert (and optional intermediate CA cert if needed). Supports PEM and + * DER. Throws WolfSSLException if not valid. */ + private void verifyCertSignatureIsCorrect( + byte[] peerCert, int peerCertType, + byte[] intCaCert, int intCaCertType, + byte[] rootCaCert, int rootCaCertType) throws WolfSSLException { + + int ret = WolfSSL.SSL_FAILURE; + WolfSSLCertManager cm = new WolfSSLCertManager(); + + if (peerCert == null || rootCaCert == null || + (peerCertType != WolfSSL.SSL_FILETYPE_ASN1 && + peerCertType != WolfSSL.SSL_FILETYPE_PEM) || + (rootCaCertType != WolfSSL.SSL_FILETYPE_ASN1 && + rootCaCertType != WolfSSL.SSL_FILETYPE_PEM)) { + throw new WolfSSLException("cert or CA cert is null or bad type"); + } + + /* Load root CA as trusted */ + ret = cm.CertManagerLoadCABuffer(rootCaCert, rootCaCert.length, + rootCaCertType); + if (ret != WolfSSL.SSL_SUCCESS) { + throw new WolfSSLException("Failed to load CA for verifying"); + } + + /* Load intermediate CA as trusted if needed */ + if (intCaCert != null) { + if (intCaCertType != WolfSSL.SSL_FILETYPE_ASN1 && + intCaCertType != WolfSSL.SSL_FILETYPE_PEM) { + throw new WolfSSLException("intermediate cert is bad type"); + } + + ret = cm.CertManagerLoadCABuffer(intCaCert, intCaCert.length, + intCaCertType); + if (ret != WolfSSL.SSL_SUCCESS) { + throw new WolfSSLException( + "Failed to load intermediate CA for verifying"); + } + } + + ret = cm.CertManagerVerifyBuffer(peerCert, peerCert.length, + peerCertType); + if (ret != WolfSSL.SSL_SUCCESS) { + throw new WolfSSLException("Failed to verify peer cert against CA"); + } + } + + + /* Internal helper method, generate test SubjectName for cert generation */ + private WolfSSLX509Name GenerateTestSubjectName() throws WolfSSLException { + + WolfSSLX509Name name = new WolfSSLX509Name(); + + name.setCountryName("US"); + name.setStateOrProvinceName("Montana"); + name.setStreetAddress("12345 Test Address"); + name.setLocalityName("Bozeman"); + name.setSurname("Test Surname"); + name.setCommonName("wolfssl.com"); + name.setEmailAddress("support@wolfssl.com"); + name.setOrganizationName("wolfSSL Inc."); + name.setOrganizationalUnitName("Development Test"); + name.setUserId("TestUserID"); + + return name; + } + + /* Test self-signed certificate generation using files for public key, + * issuer name, and issuer private key */ + private void testCertGen_SelfSigned_UsingFiles() + throws WolfSSLException, WolfSSLJNIException, IOException, + CertificateException { + + System.out.print("\tself signed (files)"); + + WolfSSLCertificate x509 = new WolfSSLCertificate(); + assertNotNull(x509); + + /* Set notBefore/notAfter dates */ + Instant now = Instant.now(); + final Date notBefore = Date.from(now); + final Date notAfter = Date.from(now.plus(Duration.ofDays(365))); + x509.setNotBefore(notBefore); + x509.setNotAfter(notAfter); + + /* Set serial number */ + x509.setSerialNumber(BigInteger.valueOf(12345)); + + /* Set Subject Name */ + WolfSSLX509Name subjectName = GenerateTestSubjectName(); + assertNotNull(subjectName); + x509.setSubjectName(subjectName); + + /* Not setting Issuer, since generating self-signed cert */ + + /* Set Public Key from file */ + x509.setPublicKey(cliKeyPubDer, WolfSSL.RSAk, + WolfSSL.SSL_FILETYPE_ASN1); + + /* Set Extensions */ + if (WolfSSL.getLibVersionHex() > 0x05006003) { + /* Key Usage and Extended Key Usage only work with wolfSSL + * later than 5.6.3 */ + x509.addExtension(WolfSSL.NID_key_usage, + "digitalSignature,keyEncipherment,dataEncipherment", false); + + x509.addExtension(WolfSSL.NID_ext_key_usage, + "clientAuth,serverAuth", false); + } + x509.addExtension(WolfSSL.NID_subject_alt_name, + "test.wolfssl.com", false); + x509.addExtension(WolfSSL.NID_basic_constraints, true, true); + + /* Sign cert, self-signed */ + x509.signCert(cliKeyDer, WolfSSL.RSAk, + WolfSSL.SSL_FILETYPE_ASN1, "SHA256"); + + /* Output to DER and PEM */ + byte[] derCert = x509.getDer(); + byte[] pemCert = x509.getPem(); + + assertNotNull(derCert); + assertTrue(derCert.length > 0); + assertNotNull(pemCert); + assertTrue(pemCert.length > 0); + + /* Sanity check generated cert buffers */ + sanityCheckCertFileBytes(derCert, WolfSSL.SSL_FILETYPE_ASN1); + sanityCheckCertFileBytes(pemCert, WolfSSL.SSL_FILETYPE_PEM); + + /* Sanity check CertManager can verify signature using expected CA */ + verifyCertSignatureIsCorrect(derCert, WolfSSL.SSL_FILETYPE_ASN1, + null, 0, derCert, WolfSSL.SSL_FILETYPE_ASN1); + verifyCertSignatureIsCorrect(pemCert, WolfSSL.SSL_FILETYPE_PEM, + null, 0, derCert, WolfSSL.SSL_FILETYPE_ASN1); + + /* Free native memory */ + subjectName.free(); + x509.free(); + + System.out.println("\t\t... passed"); + } + + /* Test CA-signed certificate generation using files for public key, + * issuer name, and issuer private key */ + private void testCertGen_CASigned_UsingFiles() + throws WolfSSLException, WolfSSLJNIException, IOException, + CertificateException { + + System.out.print("\tCA signed (files)"); + + WolfSSLCertificate x509 = new WolfSSLCertificate(); + assertNotNull(x509); + + /* Set notBefore/notAfter dates */ + Instant now = Instant.now(); + final Date notBefore = Date.from(now); + final Date notAfter = Date.from(now.plus(Duration.ofDays(365))); + x509.setNotBefore(notBefore); + x509.setNotAfter(notAfter); + + /* Set serial number */ + x509.setSerialNumber(BigInteger.valueOf(12345)); + + /* Set Subject Name */ + WolfSSLX509Name subjectName = GenerateTestSubjectName(); + assertNotNull(subjectName); + x509.setSubjectName(subjectName); + + /* Set Issuer Name from existing PEM file */ + WolfSSLCertificate issuer = + new WolfSSLCertificate(caCertPem, WolfSSL.SSL_FILETYPE_PEM); + x509.setIssuerName(issuer); + + /* Set Public Key from file */ + x509.setPublicKey(cliKeyPubDer, WolfSSL.RSAk, + WolfSSL.SSL_FILETYPE_ASN1); + + /* Set Extensions */ + if (WolfSSL.getLibVersionHex() > 0x05006003) { + /* Key Usage and Extended Key Usage only work with wolfSSL + * later than 5.6.3 */ + x509.addExtension(WolfSSL.NID_key_usage, + "digitalSignature,keyEncipherment,dataEncipherment", false); + x509.addExtension(WolfSSL.NID_ext_key_usage, + "clientAuth,serverAuth", false); + } + x509.addExtension(WolfSSL.NID_subject_alt_name, + "test.wolfssl.com", false); + x509.addExtension(WolfSSL.NID_basic_constraints, false, true); + + /* Sign cert, CA-signed */ + x509.signCert(caKeyDer, WolfSSL.RSAk, + WolfSSL.SSL_FILETYPE_ASN1, "SHA256"); + + /* Output to DER and PEM */ + byte[] derCert = x509.getDer(); + byte[] pemCert = x509.getPem(); + + assertNotNull(derCert); + assertTrue(derCert.length > 0); + assertNotNull(pemCert); + assertTrue(pemCert.length > 0); + + /* Sanity check generated cert buffers */ + sanityCheckCertFileBytes(derCert, WolfSSL.SSL_FILETYPE_ASN1); + sanityCheckCertFileBytes(pemCert, WolfSSL.SSL_FILETYPE_PEM); + + /* Sanity check CertManager can verify signature using expected CA */ + verifyCertSignatureIsCorrect(derCert, WolfSSL.SSL_FILETYPE_ASN1, + null, 0, issuer.getDer(), WolfSSL.SSL_FILETYPE_ASN1); + verifyCertSignatureIsCorrect(pemCert, WolfSSL.SSL_FILETYPE_PEM, + null, 0, issuer.getDer(), WolfSSL.SSL_FILETYPE_ASN1); + + /* Free native memory */ + subjectName.free(); + x509.free(); + + System.out.println("\t\t... passed"); + } + + /* Test self-signed certificate generation using buffers for public key, + * issuer name, and issuer private key */ + private void testCertGen_SelfSigned_UsingBuffers() + throws WolfSSLException, WolfSSLJNIException, IOException, + CertificateException { + + System.out.print("\tself signed (buffers)"); + + WolfSSLCertificate x509 = new WolfSSLCertificate(); + assertNotNull(x509); + + /* Set notBefore/notAfter dates */ + Instant now = Instant.now(); + final Date notBefore = Date.from(now); + final Date notAfter = Date.from(now.plus(Duration.ofDays(365))); + x509.setNotBefore(notBefore); + x509.setNotAfter(notAfter); + + /* Set serial number */ + x509.setSerialNumber(BigInteger.valueOf(12345)); + + /* Set Subject Name */ + WolfSSLX509Name subjectName = GenerateTestSubjectName(); + assertNotNull(subjectName); + x509.setSubjectName(subjectName); + + /* Not setting Issuer, since generating self-signed cert */ + + /* Set Public Key from file */ + byte[] pubKey = Files.readAllBytes(Paths.get(cliKeyPubDer)); + x509.setPublicKey(pubKey, WolfSSL.RSAk, WolfSSL.SSL_FILETYPE_ASN1); + + /* Set Extensions */ + if (WolfSSL.getLibVersionHex() > 0x05006003) { + /* Key Usage and Extended Key Usage only work with wolfSSL + * later than 5.6.3 */ + x509.addExtension(WolfSSL.NID_key_usage, + "digitalSignature,keyEncipherment,dataEncipherment", false); + x509.addExtension(WolfSSL.NID_ext_key_usage, + "clientAuth,serverAuth", false); + } + x509.addExtension(WolfSSL.NID_subject_alt_name, + "test.wolfssl.com", false); + x509.addExtension(WolfSSL.NID_basic_constraints, true, true); + + /* Sign cert, self-signed */ + byte[] privKey = Files.readAllBytes(Paths.get(cliKeyDer)); + x509.signCert(privKey, WolfSSL.RSAk, + WolfSSL.SSL_FILETYPE_ASN1, "SHA256"); + + /* Output to DER and PEM */ + byte[] derCert = x509.getDer(); + byte[] pemCert = x509.getPem(); + + assertNotNull(derCert); + assertTrue(derCert.length > 0); + assertNotNull(pemCert); + assertTrue(pemCert.length > 0); + + /* Sanity check generated cert buffers */ + sanityCheckCertFileBytes(derCert, WolfSSL.SSL_FILETYPE_ASN1); + sanityCheckCertFileBytes(pemCert, WolfSSL.SSL_FILETYPE_PEM); + + /* Sanity check CertManager can verify signature using expected CA */ + verifyCertSignatureIsCorrect(derCert, WolfSSL.SSL_FILETYPE_ASN1, + null, 0, derCert, WolfSSL.SSL_FILETYPE_ASN1); + verifyCertSignatureIsCorrect(pemCert, WolfSSL.SSL_FILETYPE_PEM, + null, 0, derCert, WolfSSL.SSL_FILETYPE_ASN1); + + /* Free native memory */ + subjectName.free(); + x509.free(); + + System.out.println("\t\t... passed"); + } + + /* Test CA-signed certificate generation using buffers for public key, + * issuer name, and issuer private key */ + private void testCertGen_CASigned_UsingBuffers() + throws WolfSSLException, WolfSSLJNIException, IOException, + CertificateException { + + System.out.print("\tCA signed (buffers)"); + + WolfSSLCertificate x509 = new WolfSSLCertificate(); + assertNotNull(x509); + + /* Set notBefore/notAfter dates */ + Instant now = Instant.now(); + final Date notBefore = Date.from(now); + final Date notAfter = Date.from(now.plus(Duration.ofDays(365))); + x509.setNotBefore(notBefore); + x509.setNotAfter(notAfter); + + /* Set serial number */ + x509.setSerialNumber(BigInteger.valueOf(12345)); + + /* Set Subject Name */ + WolfSSLX509Name subjectName = GenerateTestSubjectName(); + assertNotNull(subjectName); + x509.setSubjectName(subjectName); + + /* Set Issuer Name from existing PEM file */ + WolfSSLCertificate issuer = + new WolfSSLCertificate(Files.readAllBytes(Paths.get(caCertPem)), + WolfSSL.SSL_FILETYPE_PEM); + x509.setIssuerName(issuer); + + /* Set Public Key from file */ + byte[] pubKey = Files.readAllBytes(Paths.get(cliKeyPubDer)); + x509.setPublicKey(pubKey, WolfSSL.RSAk, WolfSSL.SSL_FILETYPE_ASN1); + + /* Set Extensions */ + if (WolfSSL.getLibVersionHex() > 0x05006003) { + /* Key Usage and Extended Key Usage only work with wolfSSL + * later than 5.6.3 */ + x509.addExtension(WolfSSL.NID_key_usage, + "digitalSignature,keyEncipherment,dataEncipherment", false); + x509.addExtension(WolfSSL.NID_ext_key_usage, + "clientAuth,serverAuth", false); + } + x509.addExtension(WolfSSL.NID_subject_alt_name, + "test.wolfssl.com", false); + x509.addExtension(WolfSSL.NID_basic_constraints, false, true); + + /* Sign cert, CA-signed */ + byte[] privKey = Files.readAllBytes(Paths.get(caKeyDer)); + x509.signCert(privKey, WolfSSL.RSAk, + WolfSSL.SSL_FILETYPE_ASN1, "SHA256"); + + /* Output to DER and PEM */ + byte[] derCert = x509.getDer(); + byte[] pemCert = x509.getPem(); + + assertNotNull(derCert); + assertTrue(derCert.length > 0); + assertNotNull(pemCert); + assertTrue(pemCert.length > 0); + + /* Sanity check generated cert buffers */ + sanityCheckCertFileBytes(derCert, WolfSSL.SSL_FILETYPE_ASN1); + sanityCheckCertFileBytes(pemCert, WolfSSL.SSL_FILETYPE_PEM); + + /* Sanity check CertManager can verify signature using expected CA */ + verifyCertSignatureIsCorrect(derCert, WolfSSL.SSL_FILETYPE_ASN1, + null, 0, issuer.getDer(), WolfSSL.SSL_FILETYPE_ASN1); + verifyCertSignatureIsCorrect(pemCert, WolfSSL.SSL_FILETYPE_PEM, + null, 0, issuer.getDer(), WolfSSL.SSL_FILETYPE_ASN1); + + /* Free native memory */ + subjectName.free(); + x509.free(); + + System.out.println("\t\t... passed"); + } + + /* Test self-signed certificate generation using higher-level Java classes + * for public key, issuer name, and issuer private key */ + private void testCertGen_SelfSigned_UsingJavaClasses() + throws WolfSSLException, WolfSSLJNIException, IOException, + CertificateException, NoSuchAlgorithmException { + + System.out.print("\tself signed (Java classes)"); + + WolfSSLCertificate x509 = new WolfSSLCertificate(); + assertNotNull(x509); + + /* Set notBefore/notAfter dates */ + Instant now = Instant.now(); + final Date notBefore = Date.from(now); + final Date notAfter = Date.from(now.plus(Duration.ofDays(365))); + x509.setNotBefore(notBefore); + x509.setNotAfter(notAfter); + + /* Set serial number */ + x509.setSerialNumber(BigInteger.valueOf(12345)); + + /* Set Subject Name */ + WolfSSLX509Name subjectName = GenerateTestSubjectName(); + assertNotNull(subjectName); + x509.setSubjectName(subjectName); + + /* Not setting Issuer, since generating self-signed cert */ + + /* Set Public Key from generated java.security.PublicKey */ + KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA"); + kpg.initialize(2048); + KeyPair keyPair = kpg.generateKeyPair(); + PublicKey pubKey = keyPair.getPublic(); + x509.setPublicKey(pubKey); + + /* Set Extensions */ + if (WolfSSL.getLibVersionHex() > 0x05006003) { + /* Key Usage and Extended Key Usage only work with wolfSSL + * later than 5.6.3 */ + x509.addExtension(WolfSSL.NID_key_usage, + "digitalSignature,keyEncipherment,dataEncipherment", false); + x509.addExtension(WolfSSL.NID_ext_key_usage, + "clientAuth,serverAuth", false); + } + x509.addExtension(WolfSSL.NID_subject_alt_name, + "test.wolfssl.com", false); + x509.addExtension(WolfSSL.NID_basic_constraints, true, true); + + /* Sign cert, self-signed with java.security.PrivateKey */ + PrivateKey privKey = keyPair.getPrivate(); + x509.signCert(privKey, "SHA256"); + + /* Output to DER and PEM */ + byte[] derCert = x509.getDer(); + byte[] pemCert = x509.getPem(); + + assertNotNull(derCert); + assertTrue(derCert.length > 0); + assertNotNull(pemCert); + assertTrue(pemCert.length > 0); + + /* Sanity check generated cert buffers */ + sanityCheckCertFileBytes(derCert, WolfSSL.SSL_FILETYPE_ASN1); + sanityCheckCertFileBytes(pemCert, WolfSSL.SSL_FILETYPE_PEM); + + /* Sanity check CertManager can verify signature using expected CA */ + verifyCertSignatureIsCorrect(derCert, WolfSSL.SSL_FILETYPE_ASN1, + null, 0, derCert, WolfSSL.SSL_FILETYPE_ASN1); + verifyCertSignatureIsCorrect(pemCert, WolfSSL.SSL_FILETYPE_PEM, + null, 0, derCert, WolfSSL.SSL_FILETYPE_ASN1); + + /* Free native memory */ + subjectName.free(); + x509.free(); + + System.out.println("\t... passed"); + } + + /* Test CA-signed certificate generation using higher-level Java classes + * for public key, issuer name, and issuer private key */ + private void testCertGen_CASigned_UsingJavaClasses() + throws WolfSSLException, WolfSSLJNIException, IOException, + CertificateException, NoSuchAlgorithmException, + InvalidKeySpecException { + + System.out.print("\tCA signed (Java classes)"); + + WolfSSLCertificate x509 = new WolfSSLCertificate(); + assertNotNull(x509); + + /* Set notBefore/notAfter dates */ + Instant now = Instant.now(); + final Date notBefore = Date.from(now); + final Date notAfter = Date.from(now.plus(Duration.ofDays(365))); + x509.setNotBefore(notBefore); + x509.setNotAfter(notAfter); + + /* Set serial number */ + x509.setSerialNumber(BigInteger.valueOf(12345)); + + /* Set Subject Name */ + WolfSSLX509Name subjectName = GenerateTestSubjectName(); + assertNotNull(subjectName); + x509.setSubjectName(subjectName); + + /* Set Issuer Name from existing PEM file, using server cert since it + * is a CA, and wolfSSL proper ships a PKCS#8 encoded DER private key + * needed below */ + WolfSSLCertificate issuer = + new WolfSSLCertificate(Files.readAllBytes(Paths.get(caCertPem)), + WolfSSL.SSL_FILETYPE_PEM); + X509Certificate issuerX509 = issuer.getX509Certificate(); + x509.setIssuerName(issuerX509); + + /* Set Public Key from generated java.security.PublicKey */ + KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA"); + kpg.initialize(2048); + KeyPair keyPair = kpg.generateKeyPair(); + PublicKey pubKey = keyPair.getPublic(); + x509.setPublicKey(pubKey); + + /* Set Extensions */ + if (WolfSSL.getLibVersionHex() > 0x05006003) { + /* Key Usage and Extended Key Usage only work with wolfSSL + * later than 5.6.3 */ + x509.addExtension(WolfSSL.NID_key_usage, + "digitalSignature,keyEncipherment,dataEncipherment", false); + x509.addExtension(WolfSSL.NID_ext_key_usage, + "clientAuth,serverAuth", false); + } + x509.addExtension(WolfSSL.NID_subject_alt_name, + "test.wolfssl.com", false); + x509.addExtension(WolfSSL.NID_basic_constraints, false, true); + + /* Sign cert, with CA's private key */ + byte[] privBytes = Files.readAllBytes(Paths.get(caKeyPkcs8Der)); + KeyFactory kf = KeyFactory.getInstance("RSA"); + PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(privBytes); + RSAPrivateKey rsaPriv = (RSAPrivateKey)kf.generatePrivate(spec); + x509.signCert((PrivateKey)rsaPriv, "SHA256"); + + /* Output to DER and PEM */ + byte[] derCert = x509.getDer(); + byte[] pemCert = x509.getPem(); + + assertNotNull(derCert); + assertTrue(derCert.length > 0); + assertNotNull(pemCert); + assertTrue(pemCert.length > 0); + + /* Sanity check generated cert buffers */ + sanityCheckCertFileBytes(derCert, WolfSSL.SSL_FILETYPE_ASN1); + sanityCheckCertFileBytes(pemCert, WolfSSL.SSL_FILETYPE_PEM); + + /* Sanity check CertManager can verify signature using expected CA */ + verifyCertSignatureIsCorrect(derCert, WolfSSL.SSL_FILETYPE_ASN1, + null, 0, issuer.getDer(), WolfSSL.SSL_FILETYPE_ASN1); + verifyCertSignatureIsCorrect(pemCert, WolfSSL.SSL_FILETYPE_PEM, + null, 0, issuer.getDer(), WolfSSL.SSL_FILETYPE_ASN1); + + /* Free native memory */ + subjectName.free(); + x509.free(); + + System.out.println("\t... passed"); + } + + /* Utility method if needed for testing, print out cert array to file */ + private void writeOutCertFile(byte[] cert, String path) + throws IOException { + Files.write(new File(path).toPath(), cert); + } } + diff --git a/src/test/com/wolfssl/test/WolfSSLTest.java b/src/test/com/wolfssl/test/WolfSSLTest.java index 353a006..cb183c3 100644 --- a/src/test/com/wolfssl/test/WolfSSLTest.java +++ b/src/test/com/wolfssl/test/WolfSSLTest.java @@ -52,6 +52,7 @@ public class WolfSSLTest { test_WolfSSL_new(lib); test_WolfSSL_protocol(); test_WolfSSL_Method_Allocators(lib); + test_WolfSSL_getLibVersionHex(); testGetCiphersAvailableIana(); } @@ -128,5 +129,17 @@ public class WolfSSLTest { System.out.println("\t... passed"); } + + public void test_WolfSSL_getLibVersionHex() { + System.out.print("\tgetLibVersionHex()"); + + long verHex = WolfSSL.getLibVersionHex(); + if (verHex == 0 || verHex < 0) { + System.out.println("\t\t... failed"); + fail("getting library version hex failed"); + } + + System.out.println("\t\t... passed"); + } }