Merge pull request #146 from cconlon/csrGen

Certificate Signing Request (CSR) support (WolfSSLCertRequest)
pull/148/head
JacobBarthelmeh 2023-09-05 06:47:42 -06:00 committed by GitHub
commit b9f858397c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
19 changed files with 2750 additions and 19 deletions

View File

@ -419,9 +419,10 @@ to run the ProviderTest:
examples\provider\ProviderTest.bat
```
Or to run the X509v3 certificate generation example:
Or to run the X509v3 certificate or CSR generation example:
```
examples\X509v3CertificateGeneration.bat
examples\X509CertRequest.bat
```

View File

@ -41,6 +41,7 @@
<ClCompile Include="..\..\native\com_wolfssl_WolfSSL.c" />
<ClCompile Include="..\..\native\com_wolfssl_WolfSSLCertificate.c" />
<ClCompile Include="..\..\native\com_wolfssl_WolfSSLCertManager.c" />
<ClCompile Include="..\..\native\com_wolfssl_WolfSSLCertRequest.c" />
<ClCompile Include="..\..\native\com_wolfssl_WolfSSLContext.c" />
<ClCompile Include="..\..\native\com_wolfssl_WolfSSLSession.c" />
<ClCompile Include="..\..\native\com_wolfssl_WolfSSLX509Name.c" />
@ -54,6 +55,7 @@
<ClInclude Include="..\..\native\com_wolfssl_WolfSSL.h" />
<ClInclude Include="..\..\native\com_wolfssl_WolfSSLCertificate.h" />
<ClInclude Include="..\..\native\com_wolfssl_WolfSSLCertManager.h" />
<ClInclude Include="..\..\native\com_wolfssl_WolfSSLCertRequest.h" />
<ClInclude Include="..\..\native\com_wolfssl_WolfSSLContext.h" />
<ClInclude Include="..\..\native\com_wolfssl_WolfSSLSession.h" />
<ClInclude Include="..\..\native\com_wolfssl_WolfSSLX509Name.h" />
@ -430,4 +432,4 @@ ant</Command>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>
</Project>

View File

@ -33,6 +33,9 @@
<ClCompile Include="..\..\native\com_wolfssl_WolfSSLCertManager.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\..\native\com_wolfssl_WolfSSLCertRequest.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\..\native\com_wolfssl_WolfSSLContext.c">
<Filter>Source Files</Filter>
</ClCompile>
@ -71,6 +74,9 @@
<ClInclude Include="..\..\native\com_wolfssl_WolfSSLCertManager.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\..\native\com_wolfssl_WolfSSLCertRequest.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\..\native\com_wolfssl_WolfSSLContext.h">
<Filter>Header Files</Filter>
</ClInclude>
@ -84,4 +90,4 @@
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
</Project>
</Project>

View File

@ -63,6 +63,27 @@ This will write out generated certificates to the following directory:
examples/certs/generated/
```
## Certificate Signing Request (CSR) Generation Example
An example is included which will generate Certificate Signing Requests (CSR)
using the wolfSSL JNI library `WolfSSLCertRequest` class.
**X509CertRequest.java** - CSR generation example
This example is compiled when the `ant examples` target is executed, and can
be run afterwards with the provided bash script:
```
$ cd <wolfssljni_root>
$ ./examples/X509CertRequest.sh
```
This will write out generated CSRs to the following directory:
```
examples/certs/generated/
```
## Support
Please contact the wolfSSL support team at support@wolfssl.com with any

View File

@ -0,0 +1,14 @@
cd %~dp0\build >NUL 2>NUL
SETLOCAL
:: Populate correct config for build
call ..\WindowsConfig.bat
:: Set PATH to include DLL for native wolfSSL and wolfSSL JNI (native library)
SET PATH="%WOLFSSLJNI_DLL_DIR%;%WOLFSSL_DLL_DIR%";%PATH%
java -cp ".;..\..\lib\wolfssl.jar;..\..\lib\wolfssl-jsse.jar" -Djava.library.path="%WOLFSSLJNI_DLL_DIR%;%WOLFSSL_DLL_DIR%" X509CertRequest
ENDLOCAL
cd %~dp0\..

View File

@ -0,0 +1,366 @@
/* X509CertRequest.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.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.security.PublicKey;
import java.security.PrivateKey;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.cert.CertificateException;
import java.security.NoSuchAlgorithmException;
import com.wolfssl.WolfSSL;
import com.wolfssl.WolfSSLCertRequest;
import com.wolfssl.WolfSSLX509Name;
import com.wolfssl.WolfSSLException;
import com.wolfssl.WolfSSLJNIException;
/**
* Example application that demonstrates X509 Certificate Signing Request (CSR)
* generation including various combinations.
*
* CSR using files as input for certs/keys
* CSR using arrays as input for certs/keys
* CSR 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 X509CertRequest {
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 CSR gen example with files */
private static String clientKeyDer = CERT_DIR + "client-key.der";
private static String clientKeyPubDer = CERT_DIR + "client-keyPub.der";
/* Generated certificate signing request (CSR) locations. */
private static String csrUsingFilesDer =
GEN_DIR + "csr-using-files.der";
private static String csrUsingFilesPem =
GEN_DIR + "csr-using-files.pem";
private static String csrUsingArraysDer =
GEN_DIR + "csr-using-arrays.der";
private static String csrUsingArraysPem =
GEN_DIR + "csr-using-arrays.pem";
private static String csrUsingGeneratedKeysDer =
GEN_DIR + "csr-generated-keys.der";
private static String csrUsingGeneratedKeysPem =
GEN_DIR + "csr-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";
/* Example Attribute values */
private static String test_CHALLENGE_PASSWORD =
"12345!@#$%";
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 Signing Request (CSR) using the following
* files as input to the CSR generation process:
*
* clientKeyPubDer - Existing client public key in DER format
* clientKeyDer - Existing client private key in DER format
*
* Generates and writes CSR out to the following paths in
* both PEM and DER format (see variable values above):
* csrUsingFilesDer (DER format)
* csrUsingFilesPem (PEM format)
*
* @throws WolfSSLException if error occurs during CSR generation process.
* @throws WolfSSLJNIException if native JNI error occurs
* @throws IOException on error writing to output file locations
*/
public void generateCSRUsingFiles()
throws WolfSSLException, WolfSSLJNIException, IOException,
CertificateException {
System.out.print("\nGenerating CSR using files");
/* Create new CSR object */
WolfSSLCertRequest req = new WolfSSLCertRequest();
/* Set Subject Name */
WolfSSLX509Name subjectName = generateTestSubjectName();
req.setSubjectName(subjectName);
/* Set Public Key from existing public key DER file */
req.setPublicKey(clientKeyPubDer, WolfSSL.RSAk,
WolfSSL.SSL_FILETYPE_ASN1);
/* Add Attributes */
req.addAttribute(WolfSSL.NID_pkcs9_challengePassword,
test_CHALLENGE_PASSWORD.getBytes());
/* Add Extensions */
req.addExtension(WolfSSL.NID_key_usage, test_KEY_USAGE, false);
req.addExtension(WolfSSL.NID_ext_key_usage, test_EXT_KEY_USAGE, false);
req.addExtension(WolfSSL.NID_subject_alt_name, test_ALT_NAME, false);
req.addExtension(WolfSSL.NID_basic_constraints, true, true);
/* Sign CSR, using existing client key DER */
req.signRequest(clientKeyDer, WolfSSL.RSAk,
WolfSSL.SSL_FILETYPE_ASN1, "SHA256");
/* Output to DER and PEM files */
byte[] derCsr = req.getDer();
byte[] pemCsr = req.getPem();
/* Write out generated CSRs to files */
writeFile(csrUsingFilesDer, derCsr);
writeFile(csrUsingFilesPem, pemCsr);
System.out.println("... ");
System.out.println(" " + CERT_DIR_FROM_ROOT +
Paths.get(csrUsingFilesDer).getFileName());
System.out.println(" " + CERT_DIR_FROM_ROOT +
Paths.get(csrUsingFilesPem).getFileName());
/* Free native memory */
subjectName.free();
req.free();
}
/**
* Generate example Certificate Signing Request (CSR) using the following
* files in array format as input to the CSR generation process:
*
* clientKeyPubDer - Existing client public key in DER format
* clientKeyDer - Existing client private key in DER format
*
* Generates and writes CSR out to the following paths in
* both PEM and DER format (see variable values above):
* csrUsingArraysDer (DER format)
* csrUsingArraysPem (PEM format)
*
* @throws WolfSSLException if error occurs during CSR generation process.
* @throws WolfSSLJNIException if native JNI error occurs
* @throws IOException on error writing to output file locations
*/
public void generateCSRUsingArrays()
throws WolfSSLException, WolfSSLJNIException, IOException,
CertificateException {
System.out.print("\nGenerating CSR using arrays");
/* Create new CSR object */
WolfSSLCertRequest req = new WolfSSLCertRequest();
/* Set Subject Name */
WolfSSLX509Name subjectName = generateTestSubjectName();
req.setSubjectName(subjectName);
/* Set Public Key from existing public key DER file */
byte[] pubKey = Files.readAllBytes(Paths.get(clientKeyPubDer));
req.setPublicKey(pubKey, WolfSSL.RSAk, WolfSSL.SSL_FILETYPE_ASN1);
/* Add Attributes */
req.addAttribute(WolfSSL.NID_pkcs9_challengePassword,
test_CHALLENGE_PASSWORD.getBytes());
/* Add Extensions */
req.addExtension(WolfSSL.NID_key_usage, test_KEY_USAGE, false);
req.addExtension(WolfSSL.NID_ext_key_usage, test_EXT_KEY_USAGE, false);
req.addExtension(WolfSSL.NID_subject_alt_name, test_ALT_NAME, false);
req.addExtension(WolfSSL.NID_basic_constraints, true, true);
/* Sign CSR, using existing client key DER */
byte[] privKey = Files.readAllBytes(Paths.get(clientKeyDer));
req.signRequest(privKey, WolfSSL.RSAk,
WolfSSL.SSL_FILETYPE_ASN1, "SHA256");
/* Output to DER and PEM files */
byte[] derCsr = req.getDer();
byte[] pemCsr = req.getPem();
/* Write out generated CSRs to files */
writeFile(csrUsingArraysDer, derCsr);
writeFile(csrUsingArraysPem, pemCsr);
System.out.println("... ");
System.out.println(" " + CERT_DIR_FROM_ROOT +
Paths.get(csrUsingArraysDer).getFileName());
System.out.println(" " + CERT_DIR_FROM_ROOT +
Paths.get(csrUsingArraysPem).getFileName());
/* Free native memory */
subjectName.free();
req.free();
}
/**
* Generate example Certificate Signing Request (CSR) using generated keys
* for the CSR public and private signgin key, to be used in the CSR
* generation process.
*
* Generates and writes CSR out to the following paths in
* both PEM and DER format (see variable values above):
* csrUsingGeneratedKeysDer (DER format)
* csrUsingGeneratedKeysPem (PEM format)
*
* @throws WolfSSLException if error occurs during CSR generation process.
* @throws WolfSSLJNIException if native JNI error occurs
* @throws IOException on error writing to output file locations
*/
public void generateCSRUsingGeneratedKeys()
throws WolfSSLException, WolfSSLJNIException, IOException,
CertificateException, NoSuchAlgorithmException {
System.out.print("\nGenerating CSR with generated keys");
/* Create new CSR object */
WolfSSLCertRequest req = new WolfSSLCertRequest();
/* Set Subject Name */
WolfSSLX509Name subjectName = generateTestSubjectName();
req.setSubjectName(subjectName);
/* Set Public Key from generated java.security.PublicKey */
KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA");
kpg.initialize(2048);
KeyPair keyPair = kpg.generateKeyPair();
PublicKey pubKey = keyPair.getPublic();
req.setPublicKey(pubKey);
/* Add Attributes */
req.addAttribute(WolfSSL.NID_pkcs9_challengePassword,
test_CHALLENGE_PASSWORD.getBytes());
/* Add Extensions */
req.addExtension(WolfSSL.NID_key_usage, test_KEY_USAGE, false);
req.addExtension(WolfSSL.NID_ext_key_usage, test_EXT_KEY_USAGE, false);
req.addExtension(WolfSSL.NID_subject_alt_name, test_ALT_NAME, false);
req.addExtension(WolfSSL.NID_basic_constraints, true, true);
/* Sign CSR, with java.security.PrivateKey */
PrivateKey privKey = keyPair.getPrivate();
req.signRequest(privKey, "SHA256");
/* Output to DER and PEM files */
byte[] derCsr = req.getDer();
byte[] pemCsr = req.getPem();
/* Write out generated CSRs to files */
writeFile(csrUsingGeneratedKeysDer, derCsr);
writeFile(csrUsingGeneratedKeysPem, pemCsr);
System.out.println("... ");
System.out.println(" " + CERT_DIR_FROM_ROOT +
Paths.get(csrUsingGeneratedKeysDer).getFileName());
System.out.println(" " + CERT_DIR_FROM_ROOT +
Paths.get(csrUsingGeneratedKeysPem).getFileName());
/* Free native memory */
subjectName.free();
req.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 Certificate Signing Request Generation Example");
if (!WolfSSL.certReqEnabled()) {
System.out.println("ERROR: Native wolfSSL must be compiled " +
"with --enable-certreq or WOLFSSL_CERT_REQ to use this " +
"example");
/* exit with error */
System.exit(1);
}
/* Generate example Certificate Signing Request files */
generateCSRUsingFiles();
generateCSRUsingArrays();
generateCSRUsingGeneratedKeys();
} catch (WolfSSLException | WolfSSLJNIException |
IOException | CertificateException |
NoSuchAlgorithmException e) {
e.printStackTrace();
/* exit with error */
System.exit(1);
}
} /* end run() */
public static void main(String[] args) {
new X509CertRequest().run(args);
}
} /* end X509CertRequest */

View File

@ -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 X509CertRequest $@
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 CSRs with openssl...\n"
printf "Testing each can be opened with openssl req -text\n"
# Test reading each DER CSR
CERT_FILES="../certs/generated/csr*.der"
for f in $CERT_FILES
do
$OPENSSL req -inform DER -in $f -text -noout > /dev/null
if [ $? != 0 ]; then
printf "File not readable with openssl req: $f\n"
exit -1
fi
done
# Test reading each PEM CSR
CERT_FILES="../certs/generated/csr*.pem"
for f in $CERT_FILES
do
$OPENSSL req -inform PEM -in $f -text -noout > /dev/null
if [ $? != 0 ]; then
printf "File not readable with openssl req: $f\n"
exit -1
fi
done
printf "Verification successful\n"

Binary file not shown.

View File

@ -41,6 +41,7 @@ certList=(
"client-key.der"
"client-keyPub.der"
"dh2048.pem"
"ecc-client-key.der"
"ecc-client-key.pem"
"ecc-key.pem"
"server-cert.pem"

View File

@ -115,10 +115,11 @@ gcc -Wall -c $fpic $cflags ./native/com_wolfssl_wolfcrypt_RSA.c -o ./native/com_
gcc -Wall -c $fpic $cflags ./native/com_wolfssl_wolfcrypt_ECC.c -o ./native/com_wolfssl_wolfcrypt_ECC.o $javaIncludes
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_WolfSSLCertRequest.c -o ./native/com_wolfssl_WolfSSLCertRequest.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_WolfSSLX509Name.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_WolfSSLCertRequest.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

View File

@ -386,6 +386,19 @@ JNIEXPORT jboolean JNICALL Java_com_wolfssl_WolfSSL_FileSystemEnabled
#endif
}
JNIEXPORT jboolean JNICALL Java_com_wolfssl_WolfSSL_certReqEnabled
(JNIEnv* jenv, jclass jcl)
{
(void)jenv;
(void)jcl;
#ifdef WOLFSSL_CERT_REQ
return JNI_TRUE;
#else
return JNI_FALSE;
#endif
}
JNIEXPORT jlong JNICALL Java_com_wolfssl_WolfSSL_SSLv3_1ServerMethod
(JNIEnv* jenv, jclass jcl)
{

View File

@ -211,6 +211,20 @@ extern "C" {
#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_surname
#define com_wolfssl_WolfSSL_NID_surname 4L
#undef com_wolfssl_WolfSSL_NID_serialNumber
#define com_wolfssl_WolfSSL_NID_serialNumber 5L
#undef com_wolfssl_WolfSSL_NID_pkcs9_unstructuredName
#define com_wolfssl_WolfSSL_NID_pkcs9_unstructuredName 49L
#undef com_wolfssl_WolfSSL_NID_pkcs9_contentType
#define com_wolfssl_WolfSSL_NID_pkcs9_contentType 50L
#undef com_wolfssl_WolfSSL_NID_pkcs9_challengePassword
#define com_wolfssl_WolfSSL_NID_pkcs9_challengePassword 54L
#undef com_wolfssl_WolfSSL_NID_givenName
#define com_wolfssl_WolfSSL_NID_givenName 100L
#undef com_wolfssl_WolfSSL_NID_initials
#define com_wolfssl_WolfSSL_NID_initials 101L
#undef com_wolfssl_WolfSSL_NID_key_usage
#define com_wolfssl_WolfSSL_NID_key_usage 129L
#undef com_wolfssl_WolfSSL_NID_subject_alt_name
@ -219,6 +233,8 @@ extern "C" {
#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_NID_dnQualifier
#define com_wolfssl_WolfSSL_NID_dnQualifier 174L
#undef com_wolfssl_WolfSSL_WOLFSSL_NAMED_GROUP_INVALID
#define com_wolfssl_WolfSSL_WOLFSSL_NAMED_GROUP_INVALID 0L
#undef com_wolfssl_WolfSSL_WOLFSSL_ECC_SECT163K1
@ -477,6 +493,14 @@ JNIEXPORT jboolean JNICALL Java_com_wolfssl_WolfSSL_RsaEnabled
JNIEXPORT jboolean JNICALL Java_com_wolfssl_WolfSSL_FileSystemEnabled
(JNIEnv *, jclass);
/*
* Class: com_wolfssl_WolfSSL
* Method: certReqEnabled
* Signature: ()Z
*/
JNIEXPORT jboolean JNICALL Java_com_wolfssl_WolfSSL_certReqEnabled
(JNIEnv *, jclass);
/*
* Class: com_wolfssl_WolfSSL
* Method: SSLv3_ServerMethod

View File

@ -0,0 +1,728 @@
/* com_wolfssl_WolfSSLCertRequest.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 <stdio.h>
#include <stdint.h>
#ifdef WOLFSSL_USER_SETTINGS
#include <wolfssl/wolfcrypt/settings.h>
#else
#include <wolfssl/options.h>
#endif
#include <wolfssl/version.h>
#include <wolfssl/ssl.h>
#include <wolfssl/wolfcrypt/asn.h>
#include <wolfssl/wolfcrypt/asn_public.h>
#include <wolfssl/openssl/evp.h> /* for EVP_PKEY functions */
#include <wolfssl/openssl/x509v3.h> /* for WOLFSSL_X509_EXTENSION */
#include <wolfssl/error-ssl.h>
#include "com_wolfssl_globals.h"
#include "com_wolfssl_WolfSSLCertRequest.h"
JNIEXPORT jlong JNICALL Java_com_wolfssl_WolfSSLCertRequest_X509_1REQ_1new
(JNIEnv* jenv, jclass jcl)
{
#if !defined(WOLFCRYPT_ONLY) && !defined(NO_CERTS) && defined(OPENSSL_ALL) && \
defined(WOLFSSL_CERT_GEN) && defined(WOLFSSL_CERT_REQ)
WOLFSSL_X509* x509 = NULL;
(void)jcl;
if (jenv == NULL) {
return (jlong)0;
}
x509 = wolfSSL_X509_REQ_new();
if (x509 == NULL) {
return (jlong)0;
}
return (jlong)(uintptr_t)x509;
#else
(void)jenv;
(void)jcl;
return (jlong)0;
#endif
}
JNIEXPORT void JNICALL Java_com_wolfssl_WolfSSLCertRequest_X509_1REQ_1free
(JNIEnv* jenv, jclass jcl, jlong x509ReqPtr)
{
#if !defined(WOLFCRYPT_ONLY) && !defined(NO_CERTS) && defined(OPENSSL_ALL) && \
defined(WOLFSSL_CERT_GEN) && defined(WOLFSSL_CERT_REQ)
WOLFSSL_X509* x509 = (WOLFSSL_X509*)(uintptr_t)x509ReqPtr;
(void)jcl;
if (jenv == NULL || x509 == NULL) {
return;
}
wolfSSL_X509_REQ_free(x509);
#else
(void)jenv;
(void)jcl;
return;
#endif
}
JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLCertRequest_X509_1REQ_1set_1subject_1name
(JNIEnv* jenv, jclass jcl, jlong x509ReqPtr, jlong x509NamePtr)
{
#if !defined(WOLFCRYPT_ONLY) && !defined(NO_CERTS) && defined(OPENSSL_ALL) && \
defined(WOLFSSL_CERT_GEN) && defined(WOLFSSL_CERT_REQ)
WOLFSSL_X509* x509 = (WOLFSSL_X509*)(uintptr_t)x509ReqPtr;
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_REQ_set_subject_name(x509, x509Name);
return ret;
#else
(void)jenv;
(void)jcl;
(void)x509ReqPtr;
(void)x509NamePtr;
return (jint)NOT_COMPILED_IN;
#endif
}
JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLCertRequest_X509_1REQ_1add1_1attr_1by_1NID
(JNIEnv* jenv, jclass jcl, jlong x509ReqPtr, jint nid, jint type, jbyteArray attrBytes)
{
#if !defined(WOLFCRYPT_ONLY) && !defined(NO_CERTS) && defined(OPENSSL_ALL) && \
defined(WOLFSSL_CERT_GEN) && defined(WOLFSSL_CERT_REQ)
WOLFSSL_X509* x509 = (WOLFSSL_X509*)(uintptr_t)x509ReqPtr;
int ret = WOLFSSL_SUCCESS;
unsigned char* attr = NULL;
int attrSz = 0;
(void)jcl;
if (jenv == NULL || x509 == NULL || attrBytes == NULL) {
return WOLFSSL_FAILURE;
}
attr = (byte*)(*jenv)->GetByteArrayElements(jenv, attrBytes, NULL);
attrSz = (*jenv)->GetArrayLength(jenv, attrBytes);
if (attr == NULL || attrSz <= 0) {
ret = WOLFSSL_FAILURE;
}
if (ret == WOLFSSL_SUCCESS) {
ret = X509_REQ_add1_attr_by_NID(x509, (int)nid, (int)type,
attr, attrSz);
}
(*jenv)->ReleaseByteArrayElements(jenv, attrBytes, (jbyte*)attr, JNI_ABORT);
return (jint)ret;
#else
(void)jenv;
(void)jcl;
(void)x509ReqPtr;
(void)nid;
(void)type;
(void)attrBytes;
return (jint)NOT_COMPILED_IN;
#endif
}
JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLCertRequest_X509_1REQ_1set_1version
(JNIEnv* jenv, jclass jcl, jlong x509ReqPtr, jlong version)
{
#if !defined(WOLFCRYPT_ONLY) && !defined(NO_CERTS) && \
(defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL))
WOLFSSL_X509* x509 = (WOLFSSL_X509*)(uintptr_t)x509ReqPtr;
int ret = WOLFSSL_SUCCESS;
(void)jcl;
if (jenv == NULL || x509 == NULL) {
return WOLFSSL_FAILURE;
}
ret = X509_REQ_set_version(x509, (long)version);
return (jint)ret;
#else
(void)jenv;
(void)jcl;
(void)x509ReqPtr;
(void)version;
return (jint)NOT_COMPILED_IN;
#endif
}
JNIEXPORT jbyteArray JNICALL Java_com_wolfssl_WolfSSLCertRequest_X509_1REQ_1print
(JNIEnv* jenv, jclass jcl, jlong x509ReqPtr)
{
#if !defined(WOLFCRYPT_ONLY) && !defined(NO_CERTS) && \
defined(OPENSSL_EXTRA) && !defined(NO_BIO) && defined(XSNPRINTF) && \
defined(WOLFSSL_CERT_REQ)
WOLFSSL_X509* x509 = (WOLFSSL_X509*)(uintptr_t)x509ReqPtr;
WOLFSSL_BIO* bio = NULL;
char* mem = NULL;
int sz = 0;
jbyteArray memArr = NULL;
(void)jcl;
if (jenv == NULL || x509 == NULL) {
return NULL;
}
bio = wolfSSL_BIO_new(wolfSSL_BIO_s_mem());
if (bio == NULL) {
return NULL;
}
if (wolfSSL_X509_REQ_print(bio, x509) != WOLFSSL_SUCCESS) {
wolfSSL_BIO_free(bio);
return NULL;
}
sz = wolfSSL_BIO_get_mem_data(bio, &mem);
if (sz > 0 && mem != NULL) {
memArr = (*jenv)->NewByteArray(jenv, sz);
if (memArr == NULL) {
wolfSSL_BIO_free(bio);
return NULL;
}
(*jenv)->SetByteArrayRegion(jenv, memArr, 0, sz, (jbyte*)mem);
if ((*jenv)->ExceptionOccurred(jenv)) {
/* failed to set byte region */
(*jenv)->DeleteLocalRef(jenv, memArr);
wolfSSL_BIO_free(bio);
return NULL;
}
}
wolfSSL_BIO_free(bio);
return memArr;
#else
(void)jenv;
(void)jcl;
(void)x509ReqPtr;
return NULL;
#endif
}
JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLCertRequest_X509_1REQ_1sign
(JNIEnv* jenv, jclass jcl, jlong x509ReqPtr, jint keyType, jbyteArray keyBytes, jint fileFormat, jstring digestAlg)
{
#if !defined(WOLFCRYPT_ONLY) && !defined(NO_CERTS) && defined(OPENSSL_ALL) && \
defined(WOLFSSL_CERT_GEN) && defined(WOLFSSL_CERT_REQ)
WOLFSSL_X509* x509 = (WOLFSSL_X509*)(uintptr_t)x509ReqPtr;
byte* keyBuf = NULL;
byte* derBuf = NULL;
int keySz = 0;
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;
}
keyBuf = (byte*)(*jenv)->GetByteArrayElements(jenv, keyBytes, NULL);
keySz = (*jenv)->GetArrayLength(jenv, keyBytes);
if (keyBuf == NULL || keySz == 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 = keyBuf;
derSz = keySz;
}
else {
/* get needed buffer size */
ret = wc_KeyPemToDer(keyBuf, keySz, 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(keyBuf, keySz, 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;
}
}
/* sign WOLFSSL_X509 with WOLFSSL_EVP_PKEY, returns size of signature
* on success or negative on error */
if (ret == WOLFSSL_SUCCESS) {
ret = wolfSSL_X509_REQ_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, keyBytes, (jbyte*)keyBuf,
JNI_ABORT);
(*jenv)->ReleaseStringUTFChars(jenv, digestAlg, mdName);
return (jint)ret;
#else
(void)jenv;
(void)jcl;
(void)x509ReqPtr;
(void)keyType;
(void)keyBytes;
(void)fileFormat;
(void)digestAlg;
return (jint)NOT_COMPILED_IN;
#endif
}
JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLCertRequest_X509_1REQ_1set_1pubkey_1native_1open
(JNIEnv* jenv, jclass jcl, jlong x509ReqPtr, 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)x509ReqPtr;
byte* fileBuf = NULL;
byte* derBuf = NULL;
int fileSz = 0;
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)x509ReqPtr;
(void)keyType;
(void)fileBytes;
(void)fileFormat;
return (jint)NOT_COMPILED_IN;
#endif
}
JNIEXPORT jbyteArray JNICALL Java_com_wolfssl_WolfSSLCertRequest_X509_1REQ_1get_1der
(JNIEnv* jenv, jclass jcl, jlong x509ReqPtr)
{
#if !defined(WOLFCRYPT_ONLY) && !defined(NO_CERTS) && defined(OPENSSL_ALL) && \
defined(WOLFSSL_CERT_GEN) && defined(WOLFSSL_CERT_REQ) && \
!defined(NO_BIO)
WOLFSSL_X509* x509 = (WOLFSSL_X509*)(uintptr_t)x509ReqPtr;
unsigned char* der = NULL;
jbyteArray derArr = NULL;
jclass excClass = NULL;
int sz = 0;
(void)jcl;
if (jenv == NULL || x509 == NULL) {
return NULL;
}
sz = wolfSSL_i2d_X509_REQ(x509, &der);
if (sz <= 0) {
return NULL;
}
derArr = (*jenv)->NewByteArray(jenv, sz);
if (derArr == NULL) {
(*jenv)->ThrowNew(jenv, jcl,
"Failed to create byte array in native X509_REQ_get_der");
return NULL;
}
excClass = (*jenv)->FindClass(jenv, "com/wolfssl/WolfSSLJNIException");
if ((*jenv)->ExceptionOccurred(jenv)) {
(*jenv)->ExceptionDescribe(jenv);
(*jenv)->ExceptionClear(jenv);
(*jenv)->DeleteLocalRef(jenv, derArr);
XFREE(der, NULL, DYNAMIC_TYPE_OPENSSL);
return NULL;
}
(*jenv)->SetByteArrayRegion(jenv, derArr, 0, sz, (jbyte*)der);
if ((*jenv)->ExceptionOccurred(jenv)) {
(*jenv)->ExceptionDescribe(jenv);
(*jenv)->ExceptionClear(jenv);
(*jenv)->DeleteLocalRef(jenv, derArr);
XFREE(der, NULL, DYNAMIC_TYPE_OPENSSL);
(*jenv)->ThrowNew(jenv, excClass,
"Failed to set byte region in native X509_REQ_get_der");
return NULL;
}
XFREE(der, NULL, DYNAMIC_TYPE_OPENSSL);
return derArr;
#else
(void)jenv;
(void)jcl;
(void)x509ReqPtr;
return NULL;
#endif
}
JNIEXPORT jbyteArray JNICALL Java_com_wolfssl_WolfSSLCertRequest_X509_1REQ_1get_1pem
(JNIEnv* jenv, jclass jcl, jlong x509ReqPtr)
{
#if !defined(WOLFCRYPT_ONLY) && !defined(NO_CERTS) && defined(OPENSSL_ALL) && \
defined(WOLFSSL_CERT_GEN) && defined(WOLFSSL_CERT_REQ) && \
!defined(NO_BIO)
WOLFSSL_X509* x509 = (WOLFSSL_X509*)(uintptr_t)x509ReqPtr;
unsigned char* der = NULL;
unsigned char* pem = NULL;
int sz = 0;
int pemSz = 0;
jbyteArray pemArr = NULL;
jclass excClass = NULL;
(void)jcl;
if (jenv == NULL || x509 == NULL) {
return NULL;
}
sz = wolfSSL_i2d_X509_REQ(x509, &der);
if (sz <= 0) {
return NULL;
}
pemSz = wc_DerToPem(der, sz, NULL, 0, CERTREQ_TYPE);
if (pemSz < 0) {
XFREE(der, NULL, DYNAMIC_TYPE_OPENSSL);
return NULL;
}
pem = (byte*)XMALLOC(pemSz, NULL, DYNAMIC_TYPE_TMP_BUFFER);
if (pem == NULL) {
XFREE(der, NULL, DYNAMIC_TYPE_OPENSSL);
return NULL;
}
XMEMSET(pem, 0, pemSz);
pemSz = wc_DerToPem(der, sz, pem, pemSz, CERTREQ_TYPE);
if (pemSz < 0) {
XFREE(der, NULL, DYNAMIC_TYPE_OPENSSL);
XFREE(pem, NULL, DYNAMIC_TYPE_TMP_BUFFER);
return NULL;
}
XFREE(der, NULL, DYNAMIC_TYPE_OPENSSL);
pemArr = (*jenv)->NewByteArray(jenv, pemSz);
if (pemArr == NULL) {
(*jenv)->ThrowNew(jenv, jcl,
"Failed to create byte array in native X509_REQ_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);
XFREE(pem, NULL, DYNAMIC_TYPE_TMP_BUFFER);
(*jenv)->ThrowNew(jenv, excClass,
"Failed to set byte region in native X509_get_pem");
return NULL;
}
XFREE(pem, NULL, DYNAMIC_TYPE_TMP_BUFFER);
return pemArr;
#else
(void)jenv;
(void)jcl;
(void)x509ReqPtr;
return NULL;
#endif
}
JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLCertRequest_X509_1add_1ext_1via_1nconf_1nid
(JNIEnv* jenv, jclass jcl, jlong x509ReqPtr, jint nid, jstring extValue, jboolean isCritical)
{
#if !defined(WOLFCRYPT_ONLY) && !defined(NO_CERTS) && defined(OPENSSL_EXTRA)
WOLFSSL_X509* x509 = (WOLFSSL_X509*)(uintptr_t)x509ReqPtr;
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)x509ReqPtr;
(void)nid;
(void)extValue;
(void)isCritical;
return (jint)NOT_COMPILED_IN;
#endif
}
JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLCertRequest_X509_1add_1ext_1via_1set_1object_1boolean
(JNIEnv* jenv, jclass jcl, jlong x509ReqPtr, jint nid, jboolean extValue, jboolean isCritical)
{
#if !defined(WOLFCRYPT_ONLY) && !defined(NO_CERTS) && defined(OPENSSL_EXTRA)
WOLFSSL_X509* x509 = (WOLFSSL_X509*)(uintptr_t)x509ReqPtr;
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)x509ReqPtr;
(void)nid;
(void)extValue;
(void)isCritical;
return (jint)NOT_COMPILED_IN;
#endif
}

View File

@ -0,0 +1,115 @@
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_wolfssl_WolfSSLCertRequest */
#ifndef _Included_com_wolfssl_WolfSSLCertRequest
#define _Included_com_wolfssl_WolfSSLCertRequest
#ifdef __cplusplus
extern "C" {
#endif
#undef com_wolfssl_WolfSSLCertRequest_EVP_PKEY_RSA
#define com_wolfssl_WolfSSLCertRequest_EVP_PKEY_RSA 16L
#undef com_wolfssl_WolfSSLCertRequest_EVP_PKEY_EC
#define com_wolfssl_WolfSSLCertRequest_EVP_PKEY_EC 18L
#undef com_wolfssl_WolfSSLCertRequest_MBSTRING_ASC
#define com_wolfssl_WolfSSLCertRequest_MBSTRING_ASC 4097L
/*
* Class: com_wolfssl_WolfSSLCertRequest
* Method: X509_REQ_new
* Signature: ()J
*/
JNIEXPORT jlong JNICALL Java_com_wolfssl_WolfSSLCertRequest_X509_1REQ_1new
(JNIEnv *, jclass);
/*
* Class: com_wolfssl_WolfSSLCertRequest
* Method: X509_REQ_free
* Signature: (J)V
*/
JNIEXPORT void JNICALL Java_com_wolfssl_WolfSSLCertRequest_X509_1REQ_1free
(JNIEnv *, jclass, jlong);
/*
* Class: com_wolfssl_WolfSSLCertRequest
* Method: X509_REQ_set_subject_name
* Signature: (JJ)I
*/
JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLCertRequest_X509_1REQ_1set_1subject_1name
(JNIEnv *, jclass, jlong, jlong);
/*
* Class: com_wolfssl_WolfSSLCertRequest
* Method: X509_REQ_add1_attr_by_NID
* Signature: (JII[B)I
*/
JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLCertRequest_X509_1REQ_1add1_1attr_1by_1NID
(JNIEnv *, jclass, jlong, jint, jint, jbyteArray);
/*
* Class: com_wolfssl_WolfSSLCertRequest
* Method: X509_REQ_set_version
* Signature: (JJ)I
*/
JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLCertRequest_X509_1REQ_1set_1version
(JNIEnv *, jclass, jlong, jlong);
/*
* Class: com_wolfssl_WolfSSLCertRequest
* Method: X509_REQ_print
* Signature: (J)[B
*/
JNIEXPORT jbyteArray JNICALL Java_com_wolfssl_WolfSSLCertRequest_X509_1REQ_1print
(JNIEnv *, jclass, jlong);
/*
* Class: com_wolfssl_WolfSSLCertRequest
* Method: X509_REQ_sign
* Signature: (JI[BILjava/lang/String;)I
*/
JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLCertRequest_X509_1REQ_1sign
(JNIEnv *, jclass, jlong, jint, jbyteArray, jint, jstring);
/*
* Class: com_wolfssl_WolfSSLCertRequest
* Method: X509_REQ_set_pubkey_native_open
* Signature: (JI[BI)I
*/
JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLCertRequest_X509_1REQ_1set_1pubkey_1native_1open
(JNIEnv *, jclass, jlong, jint, jbyteArray, jint);
/*
* Class: com_wolfssl_WolfSSLCertRequest
* Method: X509_REQ_get_der
* Signature: (J)[B
*/
JNIEXPORT jbyteArray JNICALL Java_com_wolfssl_WolfSSLCertRequest_X509_1REQ_1get_1der
(JNIEnv *, jclass, jlong);
/*
* Class: com_wolfssl_WolfSSLCertRequest
* Method: X509_REQ_get_pem
* Signature: (J)[B
*/
JNIEXPORT jbyteArray JNICALL Java_com_wolfssl_WolfSSLCertRequest_X509_1REQ_1get_1pem
(JNIEnv *, jclass, jlong);
/*
* Class: com_wolfssl_WolfSSLCertRequest
* Method: X509_add_ext_via_nconf_nid
* Signature: (JILjava/lang/String;Z)I
*/
JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLCertRequest_X509_1add_1ext_1via_1nconf_1nid
(JNIEnv *, jclass, jlong, jint, jstring, jboolean);
/*
* Class: com_wolfssl_WolfSSLCertRequest
* Method: X509_add_ext_via_set_object_boolean
* Signature: (JIZZ)I
*/
JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLCertRequest_X509_1add_1ext_1via_1set_1object_1boolean
(JNIEnv *, jclass, jlong, jint, jboolean, jboolean);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -361,14 +361,30 @@ public class WolfSSL {
public static final int ASN_IP_TYPE = 0x07;
/* NIDs, from native asn.h */
/** Surname NID */
public static final int NID_surname = 4;
/** Serial number NID */
public static final int NID_serialNumber = 5;
/** PKCS9 Unstructured name NID */
public static final int NID_pkcs9_unstructuredName = 49;
/** PKCS9 contentType NID */
public static final int NID_pkcs9_contentType = 50;
/** PKCS9 challenge password NID */
public static final int NID_pkcs9_challengePassword = 54;
/** Given name NID */
public static final int NID_givenName = 100;
/** Initials NID */
public static final int NID_initials = 101;
/** Key Usage NID */
public static final int NID_key_usage = 129;
public static final int NID_key_usage = 129;
/** Subject Alternative Name NID */
public static final int NID_subject_alt_name = 131;
public static final int NID_subject_alt_name = 131;
/** Basic Constraints NID */
public static final int NID_basic_constraints = 133;
public static final int NID_basic_constraints = 133;
/** Extended Key Usage NID */
public static final int NID_ext_key_usage = 151;
public static final int NID_ext_key_usage = 151;
/** Domain name qualifier NID */
public static final int NID_dnQualifier = 174;
/* is this object active, or has it been cleaned up? */
private boolean active = false;
@ -590,52 +606,61 @@ public class WolfSSL {
* TLS 1.0 is disabled by default in native wolfSSL, unless the user
* has configured wolfSSL with "--enable-tls10".
*
* @return 1 if enabled, otherwise 0 if not compiled in.
* @return true if enabled, otherwise false if not compiled in.
*/
public static native boolean TLSv1Enabled();
/**
* Tests if TLS 1.1 has been compiled into the native wolfSSL library.
*
* @return 1 if enabled, otherwise 0 if not compiled in.
* @return true if enabled, otherwise false if not compiled in.
*/
public static native boolean TLSv11Enabled();
/**
* Tests if TLS 1.2 has been compiled into the native wolfSSL library.
*
* @return 1 if enabled, otherwise 0 if not compiled in.
* @return true if enabled, otherwise false if not compiled in.
*/
public static native boolean TLSv12Enabled();
/**
* Tests if TLS 1.3 has been compiled into the native wolfSSL library.
*
* @return 1 if enabled, otherwise 0 if not compiled in.
* @return true if enabled, otherwise false if not compiled in.
*/
public static native boolean TLSv13Enabled();
/**
* Tests if ECC support has been compiled into the native wolfSSL library.
*
* @return 1 if enabled, otherwise 0 if not compiled in.
* @return true if enabled, otherwise false if not compiled in.
*/
public static native boolean EccEnabled();
/**
* Tests if RSA support has been compiled into the native wolfSSL library.
*
* @return 1 if enabled, otherwise 0 if not compiled in.
* @return true if enabled, otherwise false if not compiled in.
*/
public static native boolean RsaEnabled();
/**
* Tests if filesystem support has been compiled into the wolfSSL library.
*
* @return 1 if enabled, otherwise 0 if NO_FILESYSTEM has been defined.
* @return true if enabled, otherwise false if NO_FILESYSTEM has been
* defined.
*/
public static native boolean FileSystemEnabled();
/**
* Tests if Certificate Signing Request (CSR) support has been compiled
* into the native wolfSSL library.
*
* @return true if enabled, otherwise false if WOLFSSL_CERT_EXT not defined.
*/
public static native boolean certReqEnabled();
/* ---------------- native SSL/TLS version functions ---------------- */
/**

View File

@ -0,0 +1,730 @@
/* WolfSSLCertRequest.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;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.charset.Charset;
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;
/**
* WolfSSLCertRequest class, wraps native X509_REQ functionality.
*/
public class WolfSSLCertRequest {
private boolean active = false;
/* native X509_REQ pointer */
private long x509ReqPtr = 0;
/* lock around active state */
private final Object stateLock = new Object();
/* lock around native X509_REQ pointer use */
private final Object x509ReqLock = new Object();
/* Public key types used for CSR, 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;
/* Define from <wolfssl/openssl/asn1.h> */
private static final int MBSTRING_ASC = 0x1001;
/* Native JNI methods */
static native long X509_REQ_new();
static native void X509_REQ_free(long x509ReqPtr);
static native int X509_REQ_set_subject_name(long x509ReqPtr,
long x509NamePtr);
static native int X509_REQ_add1_attr_by_NID(long x509ReqPtr, int nid,
int type, byte[] bytes);
static native int X509_REQ_set_version(long x509ReqPtr, long ver);
static native byte[] X509_REQ_print(long x509ReqPtr);
static native int X509_REQ_sign(long x509ReqPtr, int evpKeyType,
byte[] keyBytes, int format, String digestAlg);
static native int X509_REQ_set_pubkey_native_open(long x509ReqPtr,
int keyType, byte[] fileBytes, int format);
static native byte[] X509_REQ_get_der(long x509);
static native byte[] X509_REQ_get_pem(long x509);
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);
/**
* Create new empty WolfSSLCertRequest object, for use with CSR generation
*
* @throws WolfSSLException if native API call fails.
*/
public WolfSSLCertRequest() throws WolfSSLException {
x509ReqPtr = X509_REQ_new();
if (x509ReqPtr == 0) {
throw new WolfSSLException("Failed to create WolfSSLCertRequest");
}
synchronized (stateLock) {
this.active = true;
}
}
/**
* Verifies that the current WolfSSLCertRequest object is active.
*
* @throws IllegalStateException if object has been freed
*/
private void confirmObjectIsActive()
throws IllegalStateException {
synchronized (stateLock) {
if (this.active == false) {
throw new IllegalStateException(
"WolfSSLCertRequest object has been freed");
}
}
}
/**
* Set the Subject Name to be used with this WolfSSLCertRequest.
* 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 WolfSSLCertRequest for cert generation.
*
* @throws IllegalStateException if WolfSSLCertRequest has been freed.
* @throws WolfSSLException if native JNI error occurs.
*/
public void setSubjectName(WolfSSLX509Name name)
throws IllegalStateException, WolfSSLException {
int ret;
confirmObjectIsActive();
synchronized (x509ReqLock) {
/* TODO somehow lock WolfSSLX509Name object while using pointer? */
ret = X509_REQ_set_subject_name(this.x509ReqPtr,
name.getNativeX509NamePtr());
}
if (ret != WolfSSL.SSL_SUCCESS) {
throw new WolfSSLException("Error setting subject name " +
"(ret: " + ret + ")");
}
}
/**
* Add a CSR attribute to this WolfSSLCertRequest
*
* @param nid NID of an attribute to add. Must be one of:
* WolfSSL.NID_pkcs9_challengePassword
* WolfSSL.NID_serialNumber
* WolfSSL.NID_pkcs9_unstructuredName
* WolfSSL.NID_pkcs9_contentType
* WolfSSL.NID_surname
* WolfSSL.NID_initials
* WolfSSL.NID_givenName
* WolfSSL.NID_dnQualifier
* @param value value of attribute to set, if passing in String, use
* String.getBytes()
*
* @throws IllegalStateException if WolfSSLCertRequest has been freed.
* @throws WolfSSLException if native JNI error occurs.
*/
public void addAttribute(int nid, byte[] value)
throws IllegalStateException, WolfSSLException {
int ret;
confirmObjectIsActive();
if (nid != WolfSSL.NID_pkcs9_challengePassword &&
nid != WolfSSL.NID_serialNumber &&
nid != WolfSSL.NID_pkcs9_unstructuredName &&
nid != WolfSSL.NID_pkcs9_contentType &&
nid != WolfSSL.NID_surname &&
nid != WolfSSL.NID_initials &&
nid != WolfSSL.NID_givenName &&
nid != WolfSSL.NID_dnQualifier) {
throw new WolfSSLException(
"Unsupported CSR attribute NID: " + nid);
}
if (value == null || value.length == 0) {
throw new WolfSSLException(
"CSR attribute value may not be null or zero length");
}
synchronized (x509ReqLock) {
ret = X509_REQ_add1_attr_by_NID(this.x509ReqPtr, nid,
MBSTRING_ASC, value);
}
if (ret != WolfSSL.SSL_SUCCESS) {
throw new WolfSSLException("Error setting CSR attribute " +
"(ret: " + ret + ")");
}
}
/**
* Set CSR version for this WolfSSLCertRequest object.
*
* Calling this method is optional when generating a CSR. By default,
* a value of 0 (zero) is used for the CSR version. This is currently
* the version used by all CSR RFCs/specs.
*
* @param version version to set for CSR
*
* @throws IllegalStateException if WolfSSLCertRequest has been freed.
* @throws WolfSSLException if native JNI error occurs.
*/
public void setVersion(long version)
throws IllegalStateException, WolfSSLException {
int ret;
confirmObjectIsActive();
synchronized (x509ReqLock) {
ret = X509_REQ_set_version(this.x509ReqPtr, version);
}
if (ret != WolfSSL.SSL_SUCCESS) {
throw new WolfSSLException("Error setting CSR version " +
"(ret: " + ret + ")");
}
}
/**
* Set public key for this WolfSSLCertRequest, used when generating
* Certificate Signing Requests
*
* @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 WolfSSLCertRequest 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 WolfSSLCertRequest, used when generating
* Certificate Signing Requests
*
* @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 WolfSSLCertRequest 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 (x509ReqLock) {
ret = X509_REQ_set_pubkey_native_open(this.x509ReqPtr, evpKeyType,
key, format);
}
if (ret != WolfSSL.SSL_SUCCESS) {
throw new WolfSSLException(
"Error setting public key into native WOLFSSL_X509_REQ " +
"(ret: " + ret + ")");
}
}
/**
* Set public key for this WolfSSLCertRequest, used when generating
* Certificate Signing Requests
*
* @param key PublicKey object containing public key to be used when
* generating CSR.
*
* @throws IllegalStateException if WolfSSLCertRequest 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);
}
/**
* Add an extension to a WolfSSLCertRequest 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_ext_key_usage
* WolfSSL.NID_subject_alt_name
* @param value String value of extension to set. For keyUsage and
* extKeyUsage this should be a comma-delimited list.
* For subjectAltName, this is a single value. Possible
* values for keyUsage and extKeyUsage are:
*
* NID_key_usage:
* digitalSignature
* nonRepudiation
* contentCommitment
* keyEncipherment
* dataEncipherment
* keyAgreement
* keyCertSign
* cRLSign
* encipherOnly
* decipherOnly
*
* NID_ext_key_usage:
* serverAuth
* clientAuth
* codeSigning
* emailProtection
* timeStamping
* OCSPSigning
*
* @param isCritical Boolean flag indicating if this extension is
* critical
*
* @throws IllegalStateException if WolfSSLCertRequest 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 (x509ReqLock) {
ret = X509_add_ext_via_nconf_nid(this.x509ReqPtr, 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 WolfSSLCertRequest 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_basic_constraints
* @param value Boolean value of extension (true/false)
* @param isCritical Boolean flag indicating if this extension is
* critical
*
* @throws IllegalStateException if WolfSSLCertRequest 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 (x509ReqLock) {
ret = X509_add_ext_via_set_object_boolean(
this.x509ReqPtr, nid, value, isCritical);
}
if (ret != WolfSSL.SSL_SUCCESS) {
throw new WolfSSLException(
"Error setting extension into native WOLFSSL_X509 " +
"(ret: " + ret + ")");
}
}
/**
* Sign certificate request 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 WolfSSLCertRequest has been freed.
* @throws IOException on error opening input file
* @throws WolfSSLException if invalid arguments or native JNI error occurs.
*/
public void signRequest(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);
}
signRequest(Files.readAllBytes(keyFile.toPath()), keyType,
format, digestAlg);
}
/**
* Sign certificate request 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 WolfSSLCertRequest has been freed.
* @throws WolfSSLException if invalid arguments or native JNI error occurs.
*/
public void signRequest(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 (x509ReqLock) {
ret = X509_REQ_sign(this.x509ReqPtr, evpKeyType, key, format,
digestAlg);
}
if (ret != WolfSSL.SSL_SUCCESS) {
throw new WolfSSLException(
"Error signing native X509_REQ " +
"(ret: " + ret + ")");
}
}
/**
* Sign certificate request 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 WolfSSLCertRequest has been freed.
* @throws WolfSSLException if invalid arguments or native JNI error occurs.
*/
public void signRequest(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 (x509ReqLock) {
ret = X509_REQ_sign(this.x509ReqPtr, evpKeyType, encodedKey,
WolfSSL.SSL_FILETYPE_ASN1, digestAlg);
}
if (ret != WolfSSL.SSL_SUCCESS) {
throw new WolfSSLException(
"Error signing native X509_REQ " +
"(ret: " + ret + ")");
}
}
/**
* Get ASN.1/DER encoding of this CSR, after signRequest() has been called.
*
* @return DER encoded array of CSR or null if not available.
*
* @throws IllegalStateException if WolfSSLCertRequest has been freed.
* @throws WolfSSLJNIException if native JNI operation fails
*/
public byte[] getDer() throws IllegalStateException, WolfSSLJNIException {
confirmObjectIsActive();
synchronized (x509ReqLock) {
return X509_REQ_get_der(this.x509ReqPtr);
}
}
/**
* Get PEM encoding of this CSR, after signRequest() has been called.
*
* @return PEM encoded array of CSR or null if not available.
*
* @throws IllegalStateException if WolfSSLCertRequest has been freed.
* @throws WolfSSLJNIException if native JNI operation fails
*/
public byte[] getPem() throws IllegalStateException, WolfSSLJNIException {
confirmObjectIsActive();
synchronized (x509ReqLock) {
return X509_REQ_get_pem(this.x509ReqPtr);
}
}
@Override
public String toString() {
byte[] x509ReqText = null;
synchronized (stateLock) {
if (this.active == false) {
return super.toString();
}
synchronized (x509ReqLock) {
x509ReqText = X509_REQ_print(this.x509ReqPtr);
}
if (x509ReqText != null) {
/* let Java do the modified UTF-8 conversion */
return new String(x509ReqText, Charset.forName("UTF-8"));
} else {
System.out.println("toString: x509ReqTest == null");
}
}
return super.toString();
}
/**
* Frees WolfSSLCertRequest native resources.
*/
public synchronized void free() {
synchronized (stateLock) {
if (this.active == false) {
/* already freed, just return */
return;
}
synchronized (x509ReqLock) {
/* free native resources */
X509_REQ_free(this.x509ReqPtr);
/* free Java resources */
this.active = false;
this.x509ReqPtr = 0;
}
}
}
@SuppressWarnings("deprecation")
@Override
protected void finalize() throws Throwable
{
this.free();
super.finalize();
}
}

View File

@ -730,7 +730,32 @@ public class WolfSSLCertificate {
* @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
* WolfSSL.NID_subject_alt_name
* @param value String value of extension to set. For keyUsage and
* extKeyUsage this should be a comma-delimited list.
* For subjectAltName, this is a single value. Possible
* values for keyUsage and extKeyUsage are:
*
* NID_key_usage:
* digitalSignature
* nonRepudiation
* contentCommitment
* keyEncipherment
* dataEncipherment
* keyAgreement
* keyCertSign
* cRLSign
* encipherOnly
* decipherOnly
*
* NID_ext_key_usage:
* serverAuth
* clientAuth
* codeSigning
* emailProtection
* timeStamping
* OCSPSigning
*
* @param isCritical Boolean flag indicating if this extension is
* critical
*
@ -785,8 +810,7 @@ public class WolfSSLCertificate {
* - 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
* WolfSSL.NID_basic_constraints
* @param value Boolean value of extension (true/false)
* @param isCritical Boolean flag indicating if this extension is
* critical

View File

@ -0,0 +1,608 @@
/* WolfSSLCertRequestTest.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.test;
import org.junit.Test;
import org.junit.BeforeClass;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
import static org.junit.Assert.*;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.security.PublicKey;
import java.security.PrivateKey;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import com.wolfssl.WolfSSL;
import com.wolfssl.WolfSSLX509Name;
import com.wolfssl.WolfSSLCertRequest;
import com.wolfssl.WolfSSLException;
import com.wolfssl.WolfSSLJNIException;
/**
* @author wolfSSL
*/
public class WolfSSLCertRequestTest {
public final static int TEST_FAIL = -1;
public final static int TEST_SUCCESS = 0;
public static String cliKeyDer = "examples/certs/client-key.der";
public static String cliKeyPem = "examples/certs/client-key.pem";
public static String cliKeyPubDer = "examples/certs/client-keyPub.der";
public static String cliEccKeyDer = "examples/certs/ecc-client-key.der";
public static String cliEccKeyPem = "examples/certs/ecc-client-key.pem";
@BeforeClass
public static void setCertPaths() throws WolfSSLException {
System.out.println("WolfSSLCertRequest Class");
try {
WolfSSL.loadLibrary();
} catch (UnsatisfiedLinkError ule) {
fail("failed to load native JNI library");
}
cliKeyDer = WolfSSLTestCommon.getPath(cliKeyDer);
cliKeyPubDer = WolfSSLTestCommon.getPath(cliKeyPubDer);
}
/* 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
public void testAddAttribute()
throws WolfSSLException, WolfSSLJNIException, IOException,
CertificateException {
System.out.print("\taddAttribute()");
if (!WolfSSL.certReqEnabled()) {
/* WOLFSSL_CERT_REQ / --enable-certreq not enabled in wolfSSL */
System.out.println("\t\t\t... skipped");
return;
}
WolfSSLCertRequest req = new WolfSSLCertRequest();
assertNotNull(req);
/* Test adding supported attributes by NID */
req.addAttribute(WolfSSL.NID_pkcs9_challengePassword,
"12345".getBytes());
req.addAttribute(WolfSSL.NID_serialNumber,
"12345".getBytes());
req.addAttribute(WolfSSL.NID_pkcs9_unstructuredName,
"12345".getBytes());
req.addAttribute(WolfSSL.NID_pkcs9_contentType,
"12345".getBytes());
req.addAttribute(WolfSSL.NID_surname,
"12345".getBytes());
req.addAttribute(WolfSSL.NID_initials,
"12345".getBytes());
req.addAttribute(WolfSSL.NID_givenName,
"12345".getBytes());
req.addAttribute(WolfSSL.NID_dnQualifier,
"12345".getBytes());
/* Adding unsupported NID should throw exception */
try {
req.addAttribute(123456,
"12345".getBytes());
System.out.println("\t\t\t... failed");
fail("Unsupported NID did not throw exception");
} catch (WolfSSLException e) {
/* expected */
}
req.free();
System.out.println("\t\t\t... passed");
}
@Test
public void testAddExtension()
throws WolfSSLException, WolfSSLJNIException, IOException,
CertificateException {
System.out.print("\taddExtension()");
if (!WolfSSL.certReqEnabled()) {
/* WOLFSSL_CERT_REQ / --enable-certreq not enabled in wolfSSL */
System.out.println("\t\t\t... skipped");
return;
}
WolfSSLCertRequest req = new WolfSSLCertRequest();
assertNotNull(req);
/* Test adding supported extensions by NID */
/* 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 */
if (WolfSSL.getLibVersionHex() <= 0x05006003) {
req.addExtension(WolfSSL.NID_key_usage,
"digitalSignature,keyAgreement", false);
req.addExtension(WolfSSL.NID_ext_key_usage,
"serverAuth,clientAuth", false);
}
req.addExtension(WolfSSL.NID_subject_alt_name,
"my test altName", false);
/* Adding unsupported NID should throw exception */
try {
req.addExtension(123456, "12345", false);
System.out.println("\t\t\t... failed");
fail("Unsupported extension NID did not throw exception");
} catch (WolfSSLException e) {
/* expected */
}
/* Test boolean extension setting */
req.addExtension(WolfSSL.NID_basic_constraints, true, true);
req.addExtension(WolfSSL.NID_basic_constraints, false, true);
/* Adding unsupported NID should throw exception */
try {
req.addExtension(123456, true, false);
System.out.println("\t\t\t... failed");
fail("Unsupported extension NID did not throw exception");
} catch (WolfSSLException e) {
/* expected */
}
req.free();
System.out.println("\t\t\t... passed");
}
@Test
public void testSetVersion()
throws WolfSSLException, WolfSSLJNIException, IOException,
CertificateException {
System.out.print("\tsetVersion()");
if (!WolfSSL.certReqEnabled()) {
/* WOLFSSL_CERT_REQ / --enable-certreq not enabled in wolfSSL */
System.out.println("\t\t\t... skipped");
return;
}
WolfSSLCertRequest req = new WolfSSLCertRequest();
assertNotNull(req);
req.setVersion(0);
req.setVersion(1);
/* Negative versions should throw exception */
try {
req.setVersion(-100);
System.out.println("\t\t\t... failed");
fail("Negative version should throw exception");
} catch (WolfSSLException e) {
/* expected */
}
req.free();
System.out.println("\t\t\t... passed");
}
@Test
public void testSetPublicKeyFile()
throws WolfSSLException, WolfSSLJNIException, IOException,
CertificateException {
System.out.print("\tsetPublicKey(file)");
if (!WolfSSL.certReqEnabled()) {
/* WOLFSSL_CERT_REQ / --enable-certreq not enabled in wolfSSL */
System.out.println("\t\t... skipped");
return;
}
WolfSSLCertRequest req = new WolfSSLCertRequest();
assertNotNull(req);
/* RSA */
req.setPublicKey(cliKeyPubDer, WolfSSL.RSAk,
WolfSSL.SSL_FILETYPE_ASN1);
req.setPublicKey(cliKeyPem, WolfSSL.RSAk,
WolfSSL.SSL_FILETYPE_PEM);
/* ECC */
req.setPublicKey(cliEccKeyDer, WolfSSL.ECDSAk,
WolfSSL.SSL_FILETYPE_ASN1);
req.setPublicKey(cliEccKeyPem, WolfSSL.ECDSAk,
WolfSSL.SSL_FILETYPE_PEM);
/* Test bad key type */
try {
req.setPublicKey(cliKeyPubDer, 12345,
WolfSSL.SSL_FILETYPE_ASN1);
System.out.println("\t\t... failed");
fail("bad key type should throw exception");
} catch (WolfSSLException e) {
/* expected */
}
/* Test bad file type */
try {
req.setPublicKey(cliKeyPubDer, WolfSSL.RSAk, 12345);
System.out.println("\t\t... failed");
fail("bad file type should throw exception");
} catch (WolfSSLException e) {
/* expected */
}
/* Test null file String */
try {
req.setPublicKey((String)null, WolfSSL.RSAk,
WolfSSL.SSL_FILETYPE_ASN1);
System.out.println("\t\t... failed");
fail("null PublicKey should throw exception");
} catch (WolfSSLException e) {
/* expected */
}
/* Test file that does not exist */
try {
req.setPublicKey("badfile", WolfSSL.RSAk,
WolfSSL.SSL_FILETYPE_ASN1);
System.out.println("\t\t... failed");
fail("Bad path to PublicKey should throw exception");
} catch (WolfSSLException e) {
/* expected */
}
req.free();
System.out.println("\t\t... passed");
}
@Test
public void testSetPublicKeyArray()
throws WolfSSLException, WolfSSLJNIException, IOException,
CertificateException {
System.out.print("\tsetPublicKey(array)");
if (!WolfSSL.certReqEnabled()) {
/* WOLFSSL_CERT_REQ / --enable-certreq not enabled in wolfSSL */
System.out.println("\t\t... skipped");
return;
}
WolfSSLCertRequest req = new WolfSSLCertRequest();
assertNotNull(req);
byte[] cliKeyRSADer = Files.readAllBytes(Paths.get(cliKeyDer));
byte[] cliKeyRSAPem = Files.readAllBytes(Paths.get(cliKeyPem));
byte[] cliKeyECCDer = Files.readAllBytes(Paths.get(cliEccKeyDer));
byte[] cliKeyECCPem = Files.readAllBytes(Paths.get(cliEccKeyPem));
/* RSA */
req.setPublicKey(cliKeyRSADer, WolfSSL.RSAk,
WolfSSL.SSL_FILETYPE_ASN1);
req.setPublicKey(cliKeyRSAPem, WolfSSL.RSAk,
WolfSSL.SSL_FILETYPE_PEM);
/* ECC */
req.setPublicKey(cliKeyECCDer, WolfSSL.ECDSAk,
WolfSSL.SSL_FILETYPE_ASN1);
req.setPublicKey(cliKeyECCPem, WolfSSL.ECDSAk,
WolfSSL.SSL_FILETYPE_PEM);
/* Test bad key type */
try {
req.setPublicKey(cliKeyRSADer, 12345,
WolfSSL.SSL_FILETYPE_ASN1);
System.out.println("\t\t... failed");
fail("bad key type should throw exception");
} catch (WolfSSLException e) {
/* expected */
}
/* Test bad file type */
try {
req.setPublicKey(cliKeyRSADer, WolfSSL.RSAk, 12345);
System.out.println("\t\t... failed");
fail("bad file type should throw exception");
} catch (WolfSSLException e) {
/* expected */
}
/* Test null file String */
try {
req.setPublicKey((byte[])null, WolfSSL.RSAk,
WolfSSL.SSL_FILETYPE_ASN1);
System.out.println("\t\t... failed");
fail("null key array should throw exception");
} catch (WolfSSLException e) {
/* expected */
}
/* Test zero-length byte array */
byte[] zeroArr = new byte[0];
try {
req.setPublicKey(zeroArr, WolfSSL.RSAk,
WolfSSL.SSL_FILETYPE_ASN1);
System.out.println("\t\t... failed");
fail("Zero length pub key array should throw exception");
} catch (WolfSSLException e) {
/* expected */
}
req.free();
System.out.println("\t\t... passed");
}
@Test
public void testSetPublicKeyObject()
throws WolfSSLException, WolfSSLJNIException, IOException,
CertificateException, NoSuchAlgorithmException {
System.out.print("\tsetPublicKey(PublicKey)");
if (!WolfSSL.certReqEnabled()) {
/* WOLFSSL_CERT_REQ / --enable-certreq not enabled in wolfSSL */
System.out.println("\t\t... skipped");
return;
}
WolfSSLCertRequest req = new WolfSSLCertRequest();
assertNotNull(req);
/* RSA: Set Public Key from generated java.security.PublicKey */
KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA");
kpg.initialize(2048);
KeyPair keyPair = kpg.generateKeyPair();
PublicKey pubKey = keyPair.getPublic();
req.setPublicKey(pubKey);
/* ECC: Set Public Key from generated java.security.PublicKey */
KeyPairGenerator kpgEcc = KeyPairGenerator.getInstance("EC");
kpgEcc.initialize(256);
KeyPair keyPairEcc = kpgEcc.generateKeyPair();
PublicKey pubKeyEcc = keyPairEcc.getPublic();
req.setPublicKey(pubKeyEcc);
/* Test null PublicKey object */
try {
req.setPublicKey((PublicKey)null);
System.out.println("\t\t... failed");
fail("null PublicKey should throw exception");
} catch (WolfSSLException e) {
/* expected */
}
req.free();
System.out.println("\t\t... passed");
}
@Test
public void testGenCSR_UsingFiles()
throws WolfSSLException, WolfSSLJNIException, IOException,
CertificateException {
System.out.print("\tgen CSR using files");
if (!WolfSSL.certReqEnabled()) {
/* WOLFSSL_CERT_REQ / --enable-certreq not enabled in wolfSSL */
System.out.println("\t\t... skipped");
return;
}
WolfSSLCertRequest req = new WolfSSLCertRequest();
assertNotNull(req);
/* Set Subject Name */
WolfSSLX509Name subjectName = GenerateTestSubjectName();
assertNotNull(subjectName);
req.setSubjectName(subjectName);
/* Set Public Key from file */
req.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 */
req.addExtension(WolfSSL.NID_key_usage,
"digitalSignature,keyEncipherment,dataEncipherment", false);
req.addExtension(WolfSSL.NID_ext_key_usage,
"clientAuth,serverAuth", false);
}
req.addExtension(WolfSSL.NID_subject_alt_name,
"test.wolfssl.com", false);
req.addExtension(WolfSSL.NID_basic_constraints, true, true);
/* Sign CSR */
req.signRequest(cliKeyDer, WolfSSL.RSAk,
WolfSSL.SSL_FILETYPE_ASN1, "SHA256");
/* Output to DER and PEM */
byte[] derCsr = req.getDer();
byte[] pemCsr = req.getPem();
assertNotNull(derCsr);
assertTrue(derCsr.length > 0);
assertNotNull(pemCsr);
assertTrue(pemCsr.length > 0);
/* Free native memory */
subjectName.free();
req.free();
System.out.println("\t\t... passed");
}
@Test
public void testGenCSR_UsingBuffers()
throws WolfSSLException, WolfSSLJNIException, IOException,
CertificateException {
System.out.print("\tgen CSR using buffers");
if (!WolfSSL.certReqEnabled()) {
/* WOLFSSL_CERT_REQ / --enable-certreq not enabled in wolfSSL */
System.out.println("\t\t... skipped");
return;
}
WolfSSLCertRequest req = new WolfSSLCertRequest();
assertNotNull(req);
/* Set Subject Name */
WolfSSLX509Name subjectName = GenerateTestSubjectName();
assertNotNull(subjectName);
req.setSubjectName(subjectName);
/* Set Public Key from file */
byte[] pubKey = Files.readAllBytes(Paths.get(cliKeyPubDer));
req.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 */
req.addExtension(WolfSSL.NID_key_usage,
"digitalSignature,keyEncipherment,dataEncipherment", false);
req.addExtension(WolfSSL.NID_ext_key_usage,
"clientAuth,serverAuth", false);
}
req.addExtension(WolfSSL.NID_subject_alt_name,
"test.wolfssl.com", false);
req.addExtension(WolfSSL.NID_basic_constraints, true, true);
/* Sign CSR */
byte[] privKey = Files.readAllBytes(Paths.get(cliKeyDer));
req.signRequest(privKey, WolfSSL.RSAk,
WolfSSL.SSL_FILETYPE_ASN1, "SHA256");
/* Output to DER and PEM */
byte[] derCsr = req.getDer();
byte[] pemCsr = req.getPem();
assertNotNull(derCsr);
assertTrue(derCsr.length > 0);
assertNotNull(pemCsr);
assertTrue(pemCsr.length > 0);
/* Free native memory */
subjectName.free();
req.free();
System.out.println("\t\t... passed");
}
@Test
public void testGenCSR_UsingJavaClasses()
throws WolfSSLException, WolfSSLJNIException, IOException,
CertificateException, NoSuchAlgorithmException {
System.out.print("\tgen CSR using Java classes");
if (!WolfSSL.certReqEnabled()) {
/* WOLFSSL_CERT_REQ / --enable-certreq not enabled in wolfSSL */
System.out.println("\t... skipped");
return;
}
WolfSSLCertRequest req = new WolfSSLCertRequest();
assertNotNull(req);
/* Set Subject Name */
WolfSSLX509Name subjectName = GenerateTestSubjectName();
assertNotNull(subjectName);
req.setSubjectName(subjectName);
/* Set Public Key from generated java.security.PublicKey */
KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA");
kpg.initialize(2048);
KeyPair keyPair = kpg.generateKeyPair();
PublicKey pubKey = keyPair.getPublic();
req.setPublicKey(pubKey);
/* Set Extensions */
if (WolfSSL.getLibVersionHex() > 0x05006003) {
/* Key Usage and Extended Key Usage only work with wolfSSL
* later than 5.6.3 */
req.addExtension(WolfSSL.NID_key_usage,
"digitalSignature,keyEncipherment,dataEncipherment", false);
req.addExtension(WolfSSL.NID_ext_key_usage,
"clientAuth,serverAuth", false);
}
req.addExtension(WolfSSL.NID_subject_alt_name,
"test.wolfssl.com", false);
req.addExtension(WolfSSL.NID_basic_constraints, true, true);
/* Sign CSR, with java.security.PrivateKey */
PrivateKey privKey = keyPair.getPrivate();
req.signRequest(privKey, "SHA256");
/* Output to DER and PEM */
byte[] derCsr = req.getDer();
byte[] pemCsr = req.getPem();
assertNotNull(derCsr);
assertTrue(derCsr.length > 0);
assertNotNull(pemCsr);
assertTrue(pemCsr.length > 0);
/* Free native memory */
subjectName.free();
req.free();
System.out.println("\t... passed");
}
/* Utility method if needed for testing, print out CSR array to file */
private void writeOutCsrFile(byte[] csr, String path)
throws IOException {
Files.write(new File(path).toPath(), csr);
}
}

View File

@ -31,7 +31,8 @@ import org.junit.runners.Suite;
WolfSSLSessionTest.class,
WolfCryptRSATest.class,
WolfCryptECCTest.class,
WolfSSLCertificateTest.class
WolfSSLCertificateTest.class,
WolfSSLCertRequestTest.class
})