wolfssljni/src/java/com/wolfssl/WolfSSLCertRequest.java

865 lines
31 KiB
Java

/* WolfSSLCertRequest.java
*
* Copyright (C) 2006-2026 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.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, int pathLen);
/**
* 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");
}
WolfSSLDebug.log(getClass(), WolfSSLDebug.Component.JNI,
WolfSSLDebug.INFO, x509ReqPtr,
() -> "creating new 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) {
WolfSSLDebug.log(getClass(), WolfSSLDebug.Component.JNI,
WolfSSLDebug.INFO, this.x509ReqPtr,
() -> "entered setSubjectName(" + name + ")");
/* 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();
synchronized (x509ReqLock) {
WolfSSLDebug.log(getClass(), WolfSSLDebug.Component.JNI,
WolfSSLDebug.INFO, this.x509ReqPtr,
() -> "entered addAttribute(nid: " + nid + ", byte[])");
}
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) {
WolfSSLDebug.log(getClass(), WolfSSLDebug.Component.JNI,
WolfSSLDebug.INFO, this.x509ReqPtr,
() -> "entered setVersion(" + version + ")");
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 {
File keyFile = null;
byte[] fileBytes = null;
confirmObjectIsActive();
synchronized (x509ReqLock) {
WolfSSLDebug.log(getClass(), WolfSSLDebug.Component.JNI,
WolfSSLDebug.INFO, this.x509ReqPtr,
() -> "entered setPublicKey(" + filePath + ", type: " +
keyType + ", format: " + format + ")");
}
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);
}
fileBytes = WolfSSL.fileToBytes(keyFile);
if (fileBytes == null) {
throw new WolfSSLException(
"Failed to read bytes from file: " + filePath);
}
setPublicKey(fileBytes, 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();
synchronized (x509ReqLock) {
WolfSSLDebug.log(getClass(), WolfSSLDebug.Component.JNI,
WolfSSLDebug.INFO, this.x509ReqPtr,
() -> "entered setPublicKey(byte[], type: " + keyType +
", format: " + format + ")");
}
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");
}
if (keyType == WolfSSL.RSAk) {
evpKeyType = EVP_PKEY_RSA;
} else if (keyType == WolfSSL.ECDSAk) {
evpKeyType = EVP_PKEY_EC;
} else {
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();
synchronized (x509ReqLock) {
WolfSSLDebug.log(getClass(), WolfSSLDebug.Component.JNI,
WolfSSLDebug.INFO, this.x509ReqPtr,
() -> "entered setPublicKey(" + key + ")");
}
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();
synchronized (x509ReqLock) {
WolfSSLDebug.log(getClass(), WolfSSLDebug.Component.JNI,
WolfSSLDebug.INFO, this.x509ReqPtr,
() -> "entered addExtension(nid: " + nid + ", value: " + value +
", isCritical: " + isCritical + ")");
}
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 {
addExtension(nid, value, -1, isCritical);
}
/**
* Add Basic Constraints extension with CA flag and path length constraint
* to a WolfSSLCertRequest.
*
* This method allows setting the Basic Constraints extension with both the
* CA boolean and an optional path length constraint. The path length limits
* the number of intermediate CA certificates that may follow this
* certificate in a valid certification path.
*
* To set Basic Constraints without a path length constraint, use
* {@link #addExtension(int, boolean, boolean)} with
* {@code WolfSSL.NID_basic_constraints} instead.
*
* @param nid NID of extension to add. Must be:
* WolfSSL.NID_basic_constraints
* @param value Boolean value of CA flag (true for CA, false for end entity)
* @param pathLen Maximum number of intermediate CA certificates allowed
* below this CA. Must be &gt;= 0, or -1 to not set a path length
* constraint. Only meaningful when value is true.
* @param isCritical Boolean flag indicating if this extension is critical
*
* @throws IllegalStateException if WolfSSLCertRequest has been freed
* @throws WolfSSLException if invalid arguments or on native JNI error
*/
public void addExtension(int nid, boolean value, int pathLen,
boolean isCritical) throws IllegalStateException, WolfSSLException {
int ret = 0;
confirmObjectIsActive();
synchronized (x509ReqLock) {
WolfSSLDebug.log(getClass(), WolfSSLDebug.Component.JNI,
WolfSSLDebug.INFO, this.x509ReqPtr,
() -> "entered addExtension(nid: " + nid + ", value: " + value +
", pathLen: " + pathLen + ", isCritical: " + isCritical + ")");
}
if (nid != WolfSSL.NID_basic_constraints) {
throw new WolfSSLException(
"Unsupported X509v3 extension NID: " + nid);
}
if (pathLen < -1) {
throw new WolfSSLException(
"Path length must be >= 0 or -1, got: " + pathLen);
}
if (!value && pathLen >= 0) {
throw new WolfSSLException(
"pathLen must not be set when isCA is FALSE (RFC 5280), " +
"got pathLen: " + pathLen);
}
synchronized (x509ReqLock) {
ret = X509_add_ext_via_set_object_boolean(this.x509ReqPtr, nid,
value, isCritical, pathLen);
}
if (ret == WolfSSL.NOT_COMPILED_IN) {
throw new WolfSSLException(
"addExtension NOT_COMPILED_IN, pathLen " +
"support requires wolfSSL > 5.8.4 or " +
"PR 9940 patch (ret: " + ret + ")");
}
else 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 {
File keyFile = null;
byte[] fileBytes = null;
confirmObjectIsActive();
synchronized (x509ReqLock) {
WolfSSLDebug.log(getClass(), WolfSSLDebug.Component.JNI,
WolfSSLDebug.INFO, this.x509ReqPtr,
() -> "entered signRequest(" + filePath + ", keyType: " +
keyType + ", format: " + format + ", digestAlg: " +
digestAlg + ")");
}
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);
}
fileBytes = WolfSSL.fileToBytes(keyFile);
if (fileBytes == null) {
throw new WolfSSLException(
"Failed to read bytes from file: " + filePath);
}
signRequest(fileBytes, 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();
synchronized (x509ReqLock) {
WolfSSLDebug.log(getClass(), WolfSSLDebug.Component.JNI,
WolfSSLDebug.INFO, this.x509ReqPtr,
() -> "entered signRequest(byte[], keyType: " + keyType +
", format: " + format + ", digestAlg: " + digestAlg + ")");
}
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");
}
if (keyType == WolfSSL.RSAk) {
evpKeyType = EVP_PKEY_RSA;
} else if (keyType == WolfSSL.ECDSAk) {
evpKeyType = EVP_PKEY_EC;
} else {
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();
synchronized (x509ReqLock) {
WolfSSLDebug.log(getClass(), WolfSSLDebug.Component.JNI,
WolfSSLDebug.INFO, this.x509ReqPtr,
() -> "entered signRequest(key: " + key + ", digestAlg: " +
digestAlg + ")");
}
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) {
WolfSSLDebug.log(getClass(), WolfSSLDebug.Component.JNI,
WolfSSLDebug.INFO, this.x509ReqPtr, () -> "entered getDer()");
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) {
WolfSSLDebug.log(getClass(), WolfSSLDebug.Component.JNI,
WolfSSLDebug.INFO, this.x509ReqPtr, () -> "entered getPem()");
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) {
WolfSSLDebug.log(getClass(), WolfSSLDebug.Component.JNI,
WolfSSLDebug.INFO, this.x509ReqPtr, () -> "entered free()");
/* 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();
}
}