wolfssljni/native/com_wolfssl_WolfSSLCRL.c

1107 lines
29 KiB
C

/* com_wolfssl_WolfSSLCRL.c
*
* 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 3 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/openssl/evp.h>
#include <wolfssl/openssl/x509.h>
#include <wolfssl/error-ssl.h>
#include "com_wolfssl_globals.h"
#include "com_wolfssl_WolfSSLCRL.h"
#if ((LIBWOLFSSL_VERSION_HEX > 0x05008004) || \
defined(WOLFSSL_PR9631_PATCH_APPLIED)) && \
defined(HAVE_CRL) && defined(OPENSSL_EXTRA) && \
defined(WOLFSSL_CERT_GEN)
#define WOLFSSL_JNI_CRL_GEN_ENABLED
#endif
JNIEXPORT jlong JNICALL Java_com_wolfssl_WolfSSLCRL_X509_1CRL_1new
(JNIEnv* jenv, jclass jcl)
{
#if defined(WOLFSSL_JNI_CRL_GEN_ENABLED)
WOLFSSL_X509_CRL* crl = NULL;
(void)jcl;
if (jenv == NULL) {
return 0;
}
crl = wolfSSL_X509_CRL_new();
if (crl == NULL) {
return 0;
}
return (jlong)(uintptr_t)crl;
#else
(void)jenv;
(void)jcl;
return 0;
#endif
}
JNIEXPORT void JNICALL Java_com_wolfssl_WolfSSLCRL_X509_1CRL_1free
(JNIEnv* jenv, jclass jcl, jlong crlPtr)
{
#if defined(WOLFSSL_JNI_CRL_GEN_ENABLED)
WOLFSSL_X509_CRL* crl = (WOLFSSL_X509_CRL*)(uintptr_t)crlPtr;
(void)jcl;
if (jenv == NULL || crl == NULL) {
return;
}
wolfSSL_X509_CRL_free(crl);
#else
(void)jenv;
(void)jcl;
(void)crlPtr;
#endif
}
JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLCRL_X509_1CRL_1set_1version
(JNIEnv* jenv, jclass jcl, jlong crlPtr, jint version)
{
#if defined(WOLFSSL_JNI_CRL_GEN_ENABLED)
WOLFSSL_X509_CRL* crl = (WOLFSSL_X509_CRL*)(uintptr_t)crlPtr;
(void)jcl;
if (jenv == NULL || crl == NULL) {
return WOLFSSL_FAILURE;
}
return wolfSSL_X509_CRL_set_version(crl, version);
#else
(void)jenv;
(void)jcl;
(void)crlPtr;
(void)version;
return (jint)NOT_COMPILED_IN;
#endif
}
JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLCRL_X509_1CRL_1set_1issuer_1name
(JNIEnv* jenv, jclass jcl, jlong crlPtr, jlong x509NamePtr)
{
#if defined(WOLFSSL_JNI_CRL_GEN_ENABLED)
WOLFSSL_X509_CRL* crl = (WOLFSSL_X509_CRL*)(uintptr_t)crlPtr;
WOLFSSL_X509_NAME* name = (WOLFSSL_X509_NAME*)(uintptr_t)x509NamePtr;
(void)jcl;
if (jenv == NULL || crl == NULL || name == NULL) {
return WOLFSSL_FAILURE;
}
return wolfSSL_X509_CRL_set_issuer_name(crl, name);
#else
(void)jenv;
(void)jcl;
(void)crlPtr;
(void)x509NamePtr;
return (jint)NOT_COMPILED_IN;
#endif
}
JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLCRL_X509_1CRL_1set_1lastUpdate
(JNIEnv* jenv, jclass jcl, jlong crlPtr, jbyteArray time)
{
#if defined(WOLFSSL_JNI_CRL_GEN_ENABLED)
WOLFSSL_X509_CRL* crl = (WOLFSSL_X509_CRL*)(uintptr_t)crlPtr;
byte* timeBuf = NULL;
int timeSz = 0;
int ret = 0;
WOLFSSL_ASN1_TIME asnTime;
char timeStr[CTC_DATE_SIZE + 1];
int timeLen = 0;
(void)jcl;
if (jenv == NULL || crl == NULL || time == NULL) {
return 0;
}
timeBuf = (byte*)(*jenv)->GetByteArrayElements(jenv, time, NULL);
timeSz = (*jenv)->GetArrayLength(jenv, time);
/* Ensure there is enough room for date string (32 bytes)
plus 4 bytes of length and 4 bytes for type. */
if (timeBuf == NULL || timeSz < (CTC_DATE_SIZE + 8)) {
ret = 0;
}
else {
/* Extract length from bytes 32-35 (assuming native byte order) */
XMEMCPY(&timeLen, timeBuf + CTC_DATE_SIZE, sizeof(timeLen));
if (timeLen <= 0 || timeLen > CTC_DATE_SIZE) {
ret = 0;
}
else {
/* Copy time string and null-terminate */
XMEMCPY(timeStr, timeBuf, timeLen);
timeStr[timeLen] = '\0';
/* Create ASN1_TIME object and set string */
XMEMSET(&asnTime, 0, sizeof(asnTime));
if (wolfSSL_ASN1_TIME_set_string(&asnTime, timeStr) == 1) {
ret = wolfSSL_X509_CRL_set_lastUpdate(crl, &asnTime);
}
else {
ret = 0;
}
}
}
if (timeBuf != NULL) {
(*jenv)->ReleaseByteArrayElements(jenv, time,
(jbyte*)timeBuf, JNI_ABORT);
}
return (jint)ret;
#else
(void)jenv;
(void)jcl;
(void)crlPtr;
(void)time;
return 0;
#endif
}
JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLCRL_X509_1CRL_1set_1nextUpdate
(JNIEnv* jenv, jclass jcl, jlong crlPtr, jbyteArray time)
{
#if defined(WOLFSSL_JNI_CRL_GEN_ENABLED)
WOLFSSL_X509_CRL* crl = (WOLFSSL_X509_CRL*)(uintptr_t)crlPtr;
byte* timeBuf = NULL;
int timeSz = 0;
int ret = 0;
WOLFSSL_ASN1_TIME asnTime;
char timeStr[CTC_DATE_SIZE + 1];
int timeLen = 0;
(void)jcl;
if (jenv == NULL || crl == NULL || time == NULL) {
return 0;
}
timeBuf = (byte*)(*jenv)->GetByteArrayElements(jenv, time, NULL);
timeSz = (*jenv)->GetArrayLength(jenv, time);
/* Ensure there is enough room for date string (32 bytes)
plus 4 bytes of length and 4 bytes for type. */
if (timeBuf == NULL || timeSz < (CTC_DATE_SIZE + 8)) {
ret = 0;
}
else {
/* Extract length from bytes 32-35 (assuming native byte order) */
XMEMCPY(&timeLen, timeBuf + CTC_DATE_SIZE, sizeof(timeLen));
if (timeLen <= 0 || timeLen > CTC_DATE_SIZE) {
ret = 0;
}
else {
/* Copy time string and null-terminate */
XMEMCPY(timeStr, timeBuf, timeLen);
timeStr[timeLen] = '\0';
/* Create ASN1_TIME object and set string */
XMEMSET(&asnTime, 0, sizeof(asnTime));
if (wolfSSL_ASN1_TIME_set_string(&asnTime, timeStr) == 1) {
ret = wolfSSL_X509_CRL_set_nextUpdate(crl, &asnTime);
}
else {
ret = 0;
}
}
}
if (timeBuf != NULL) {
(*jenv)->ReleaseByteArrayElements(jenv, time,
(jbyte*)timeBuf, JNI_ABORT);
}
return (jint)ret;
#else
(void)jenv;
(void)jcl;
(void)crlPtr;
(void)time;
return 0;
#endif
}
JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLCRL_X509_1CRL_1add_1revoked
(JNIEnv* jenv, jclass jcl, jlong crlPtr, jbyteArray serial,
jbyteArray revDate, jint dateFmt)
{
#if defined(WOLFSSL_JNI_CRL_GEN_ENABLED)
WOLFSSL_X509_CRL* crl = (WOLFSSL_X509_CRL*)(uintptr_t)crlPtr;
WOLFSSL_X509_REVOKED revoked;
WOLFSSL_ASN1_INTEGER* serialInt = NULL;
byte* serialBuf = NULL;
int serialSz = 0;
int ret = WOLFSSL_SUCCESS;
(void)jcl;
/* Note: date is not currently used until WOLFSSL_X509_REVOKED adds it. */
(void)revDate;
(void)dateFmt;
if (jenv == NULL || crl == NULL || serial == NULL) {
return WOLFSSL_FAILURE;
}
serialBuf = (byte*)(*jenv)->GetByteArrayElements(jenv, serial, NULL);
serialSz = (*jenv)->GetArrayLength(jenv, serial);
if (serialBuf == NULL || serialSz == 0) {
ret = WOLFSSL_FAILURE;
}
else {
XMEMSET(&revoked, 0, sizeof(revoked));
serialInt = wolfSSL_ASN1_INTEGER_new();
if (serialInt == NULL) {
ret = MEMORY_E;
}
else {
serialInt->data = (unsigned char*)serialBuf;
serialInt->dataMax = (unsigned int)serialSz;
serialInt->length = serialSz;
serialInt->isDynamic = 0;
serialInt->type = 0;
revoked.serialNumber = serialInt;
ret = wolfSSL_X509_CRL_add_revoked(crl, &revoked);
}
}
if (serialBuf != NULL) {
(*jenv)->ReleaseByteArrayElements(jenv, serial,
(jbyte*)serialBuf, JNI_ABORT);
}
if (serialInt != NULL) {
wolfSSL_ASN1_INTEGER_free(serialInt);
}
return ret;
#else
(void)jenv;
(void)jcl;
(void)crlPtr;
(void)serial;
(void)revDate;
(void)dateFmt;
return (jint)NOT_COMPILED_IN;
#endif
}
JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLCRL_X509_1CRL_1add_1revoked_1cert
(JNIEnv* jenv, jclass jcl, jlong crlPtr, jbyteArray certDer,
jbyteArray revDate, jint dateFmt)
{
#if defined(WOLFSSL_JNI_CRL_GEN_ENABLED)
WOLFSSL_X509_CRL* crl = (WOLFSSL_X509_CRL*)(uintptr_t)crlPtr;
byte* certBuf = NULL;
int certSz = 0;
int ret = WOLFSSL_SUCCESS;
(void)jcl;
(void)revDate;
(void)dateFmt;
if (jenv == NULL || crl == NULL || certDer == NULL) {
return WOLFSSL_FAILURE;
}
certBuf = (byte*)(*jenv)->GetByteArrayElements(jenv, certDer, NULL);
certSz = (*jenv)->GetArrayLength(jenv, certDer);
if (certBuf == NULL || certSz == 0) {
ret = WOLFSSL_FAILURE;
}
else {
ret = wolfSSL_X509_CRL_add_revoked_cert(crl, certBuf, certSz);
}
if (certBuf != NULL) {
(*jenv)->ReleaseByteArrayElements(jenv, certDer,
(jbyte*)certBuf, JNI_ABORT);
}
return ret;
#else
(void)jenv;
(void)jcl;
(void)crlPtr;
(void)certDer;
(void)revDate;
(void)dateFmt;
return (jint)NOT_COMPILED_IN;
#endif
}
JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLCRL_X509_1CRL_1sign
(JNIEnv* jenv, jclass jcl, jlong crlPtr, jint keyType, jbyteArray keyBytes,
jint format, jstring digestAlg)
{
#if defined(WOLFSSL_JNI_CRL_GEN_ENABLED)
WOLFSSL_X509_CRL* crl = (WOLFSSL_X509_CRL*)(uintptr_t)crlPtr;
byte* keyBuf = NULL;
int keySz = 0;
byte* derBuf = NULL;
int derSz = 0;
WOLFSSL_EVP_PKEY* priv = NULL;
const WOLFSSL_EVP_MD* md = NULL;
unsigned char* rsaPrivBuf = NULL;
const char* mdName = NULL;
jboolean isCopy = JNI_FALSE;
int ret = WOLFSSL_SUCCESS;
(void)jcl;
if (jenv == NULL || crl == NULL || keyBytes == NULL) {
return WOLFSSL_FAILURE;
}
keyBuf = (byte*)(*jenv)->GetByteArrayElements(jenv, keyBytes, &isCopy);
if ((*jenv)->ExceptionOccurred(jenv)) {
(*jenv)->ExceptionClear(jenv);
return WOLFSSL_FAILURE;
}
keySz = (*jenv)->GetArrayLength(jenv, keyBytes);
if (keyBuf == NULL || keySz == 0) {
ret = WOLFSSL_FAILURE;
}
if (ret == WOLFSSL_SUCCESS) {
if (digestAlg != NULL) {
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)format == 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 {
XMEMSET(derBuf, 0, derSz);
ret = WOLFSSL_SUCCESS;
}
}
/* convert PEM to DER */
if (derBuf != NULL && 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) {
/* Use temp pointer since d2i_PrivateKey() modifies the buffer */
rsaPrivBuf = derBuf;
priv = wolfSSL_d2i_PrivateKey((int)keyType, NULL,
(const unsigned char**)&rsaPrivBuf, derSz);
if (priv == NULL) {
ret = WOLFSSL_FAILURE;
}
}
/* sign WOLFSSL_X509_CRL with WOLFSSL_EVP_PKEY, wolfSSL_X509_CRL_sign()
* returns WOLFSSL_SUCCESS on success, WOLFSSL_FAILURE (0) or negative
* code on error */
if (ret == WOLFSSL_SUCCESS) {
ret = wolfSSL_X509_CRL_sign(crl, priv, md);
if (ret > 0) {
ret = WOLFSSL_SUCCESS;
}
}
if (priv != NULL) {
wolfSSL_EVP_PKEY_free(priv);
}
if (derBuf != NULL && derBuf != keyBuf) {
XMEMSET(derBuf, 0, derSz);
XFREE(derBuf, NULL, DYNAMIC_TYPE_TMP_BUFFER);
derBuf = NULL;
}
if (mdName != NULL) {
(*jenv)->ReleaseStringUTFChars(jenv, digestAlg, mdName);
}
if (keyBuf != NULL) {
/* Only zero if JVM made a copy */
if (isCopy == JNI_TRUE) {
#if (LIBWOLFSSL_VERSION_HEX >= 0x05008004) && \
!defined(WOLFSSL_NO_FORCE_ZERO)
wc_ForceZero(keyBuf, keySz);
#else
XMEMSET(keyBuf, 0, keySz);
#endif
}
(*jenv)->ReleaseByteArrayElements(jenv, keyBytes, (jbyte*)keyBuf,
JNI_ABORT);
}
return ret;
#else
(void)jenv;
(void)jcl;
(void)crlPtr;
(void)keyType;
(void)keyBytes;
(void)format;
(void)digestAlg;
return (jint)NOT_COMPILED_IN;
#endif
}
JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLCRL_write_1X509_1CRL
(JNIEnv* jenv, jclass jcl, jlong crlPtr, jstring path, jint format)
{
#if defined(WOLFSSL_JNI_CRL_GEN_ENABLED)
WOLFSSL_X509_CRL* crl = (WOLFSSL_X509_CRL*)(uintptr_t)crlPtr;
const char* cPath = NULL;
int ret = WOLFSSL_FAILURE;
(void)jcl;
if (jenv == NULL || crl == NULL || path == NULL) {
return WOLFSSL_FAILURE;
}
cPath = (*jenv)->GetStringUTFChars(jenv, path, NULL);
if (cPath == NULL) {
return WOLFSSL_FAILURE;
}
ret = wolfSSL_write_X509_CRL(crl, cPath, format);
(*jenv)->ReleaseStringUTFChars(jenv, path, cPath);
return ret;
#else
(void)jenv;
(void)jcl;
(void)crlPtr;
(void)path;
(void)format;
return (jint)NOT_COMPILED_IN;
#endif
}
JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLCRL_X509_1CRL_1version
(JNIEnv* jenv, jclass jcl, jlong crlPtr)
{
#if defined(WOLFSSL_JNI_CRL_GEN_ENABLED)
WOLFSSL_X509_CRL* crl = (WOLFSSL_X509_CRL*)(uintptr_t)crlPtr;
(void)jcl;
if (jenv == NULL || crl == NULL) {
return 0;
}
return (jint)wolfSSL_X509_CRL_version(crl);
#else
(void)jenv;
(void)jcl;
(void)crlPtr;
return 0;
#endif
}
JNIEXPORT jstring JNICALL Java_com_wolfssl_WolfSSLCRL_X509_1CRL_1get_1lastUpdate
(JNIEnv* jenv, jclass jcl, jlong crlPtr)
{
#if defined(WOLFSSL_JNI_CRL_GEN_ENABLED) && !defined(NO_ASN_TIME)
WOLFSSL_X509_CRL* crl = (WOLFSSL_X509_CRL*)(uintptr_t)crlPtr;
WOLFSSL_ASN1_TIME* date = NULL;
char timeStr[CTC_DATE_SIZE];
char* dateStr = NULL;
(void)jcl;
if (jenv == NULL || crl == NULL) {
return NULL;
}
date = wolfSSL_X509_CRL_get_lastUpdate(crl);
if (date != NULL) {
dateStr = wolfSSL_ASN1_TIME_to_string(date, timeStr, sizeof(timeStr));
if (dateStr != NULL) {
return (*jenv)->NewStringUTF(jenv, dateStr);
}
}
return NULL;
#else
(void)jenv;
(void)jcl;
(void)crlPtr;
return NULL;
#endif
}
JNIEXPORT jstring JNICALL Java_com_wolfssl_WolfSSLCRL_X509_1CRL_1get_1nextUpdate
(JNIEnv* jenv, jclass jcl, jlong crlPtr)
{
#if defined(WOLFSSL_JNI_CRL_GEN_ENABLED) && !defined(NO_ASN_TIME)
WOLFSSL_X509_CRL* crl = (WOLFSSL_X509_CRL*)(uintptr_t)crlPtr;
WOLFSSL_ASN1_TIME* date = NULL;
char timeStr[CTC_DATE_SIZE];
char* dateStr = NULL;
(void)jcl;
if (jenv == NULL || crl == NULL) {
return NULL;
}
date = wolfSSL_X509_CRL_get_nextUpdate(crl);
if (date != NULL) {
dateStr = wolfSSL_ASN1_TIME_to_string(date, timeStr, sizeof(timeStr));
if (dateStr != NULL) {
return (*jenv)->NewStringUTF(jenv, dateStr);
}
}
return NULL;
#else
(void)jenv;
(void)jcl;
(void)crlPtr;
return NULL;
#endif
}
JNIEXPORT jbyteArray JNICALL Java_com_wolfssl_WolfSSLCRL_X509_1CRL_1print
(JNIEnv* jenv, jclass jcl, jlong crlPtr)
{
#if defined(WOLFSSL_JNI_CRL_GEN_ENABLED)
WOLFSSL_BIO* bio;
int sz = 0;
char* mem = NULL;
jbyteArray memArr = NULL;
WOLFSSL_X509_CRL* crl = (WOLFSSL_X509_CRL*)(uintptr_t)crlPtr;
(void)jcl;
if (jenv == NULL || crl == NULL) {
return NULL;
}
bio = wolfSSL_BIO_new(wolfSSL_BIO_s_mem());
if (bio == NULL) {
return NULL;
}
if (wolfSSL_X509_CRL_print(bio, crl) != 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)) {
(*jenv)->DeleteLocalRef(jenv, memArr);
wolfSSL_BIO_free(bio);
return NULL;
}
}
wolfSSL_BIO_free(bio);
return memArr;
#else
(void)jenv;
(void)jcl;
(void)crlPtr;
return NULL;
#endif
}
JNIEXPORT jbyteArray JNICALL Java_com_wolfssl_WolfSSLCRL_X509_1CRL_1get_1der
(JNIEnv* jenv, jclass jcl, jlong crlPtr)
{
#if defined(WOLFSSL_JNI_CRL_GEN_ENABLED)
WOLFSSL_X509_CRL* crl = (WOLFSSL_X509_CRL*)(uintptr_t)crlPtr;
unsigned char* der = NULL;
jbyteArray derArr = NULL;
jclass excClass = NULL;
int sz = 0;
(void)jcl;
if (jenv == NULL || crl == NULL) {
return NULL;
}
sz = wolfSSL_i2d_X509_CRL(crl, &der);
if (sz <= 0) {
return NULL;
}
derArr = (*jenv)->NewByteArray(jenv, sz);
if (derArr == NULL) {
throwWolfSSLJNIException(jenv,
"Failed to create byte array in native X509_CRL_get_der");
XFREE(der, NULL, DYNAMIC_TYPE_OPENSSL);
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_CRL_get_der");
return NULL;
}
XFREE(der, NULL, DYNAMIC_TYPE_OPENSSL);
return derArr;
#else
(void)jenv;
(void)jcl;
(void)crlPtr;
return NULL;
#endif
}
JNIEXPORT jbyteArray JNICALL Java_com_wolfssl_WolfSSLCRL_X509_1CRL_1get_1pem
(JNIEnv* jenv, jclass jcl, jlong crlPtr)
{
#if defined(WOLFSSL_JNI_CRL_GEN_ENABLED)
WOLFSSL_X509_CRL* crl = (WOLFSSL_X509_CRL*)(uintptr_t)crlPtr;
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 || crl == NULL) {
return NULL;
}
sz = wolfSSL_i2d_X509_CRL(crl, &der);
if (sz <= 0) {
return NULL;
}
pemSz = wc_DerToPem(der, sz, NULL, 0, CRL_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, CRL_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) {
throwWolfSSLJNIException(jenv,
"Failed to create byte array in native X509_CRL_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_CRL_get_pem");
return NULL;
}
XFREE(pem, NULL, DYNAMIC_TYPE_TMP_BUFFER);
return pemArr;
#else
(void)jenv;
(void)jcl;
(void)crlPtr;
return NULL;
#endif
}
JNIEXPORT jbyteArray JNICALL Java_com_wolfssl_WolfSSLCRL_X509_1CRL_1get_1signature
(JNIEnv* jenv, jclass jcl, jlong crlPtr)
{
#if defined(WOLFSSL_JNI_CRL_GEN_ENABLED)
WOLFSSL_X509_CRL* crl = (WOLFSSL_X509_CRL*)(uintptr_t)crlPtr;
int sigSz = 0;
unsigned char* sigBuf = NULL;
jbyteArray sigArr = NULL;
jclass excClass = NULL;
(void)jcl;
if (jenv == NULL || crl == NULL) {
return NULL;
}
if (wolfSSL_X509_CRL_get_signature(crl, NULL, &sigSz) != WOLFSSL_SUCCESS ||
sigSz <= 0) {
return NULL;
}
sigArr = (*jenv)->NewByteArray(jenv, sigSz);
if (sigArr == NULL) {
throwWolfSSLJNIException(jenv,
"Failed to create byte array in native X509_CRL_get_signature");
return NULL;
}
sigBuf = (unsigned char*)XMALLOC(sigSz, NULL, DYNAMIC_TYPE_TMP_BUFFER);
if (sigBuf == NULL) {
(*jenv)->DeleteLocalRef(jenv, sigArr);
return NULL;
}
if (wolfSSL_X509_CRL_get_signature(crl, sigBuf, &sigSz)
!= WOLFSSL_SUCCESS) {
(*jenv)->DeleteLocalRef(jenv, sigArr);
XFREE(sigBuf, 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, sigArr);
XFREE(sigBuf, NULL, DYNAMIC_TYPE_TMP_BUFFER);
return NULL;
}
(*jenv)->SetByteArrayRegion(jenv, sigArr, 0, sigSz,
(const jbyte*)sigBuf);
XFREE(sigBuf, NULL, DYNAMIC_TYPE_TMP_BUFFER);
if ((*jenv)->ExceptionOccurred(jenv)) {
(*jenv)->ExceptionDescribe(jenv);
(*jenv)->ExceptionClear(jenv);
(*jenv)->DeleteLocalRef(jenv, sigArr);
(*jenv)->ThrowNew(jenv, excClass,
"Failed to set byte region in native X509_CRL_get_signature");
return NULL;
}
return sigArr;
#else
(void)jenv;
(void)jcl;
(void)crlPtr;
return NULL;
#endif
}
JNIEXPORT jlong JNICALL Java_com_wolfssl_WolfSSLCRL_X509_1CRL_1load_1buffer
(JNIEnv* jenv, jclass jcl, jbyteArray buf, jint format)
{
#if defined(HAVE_CRL) && defined(OPENSSL_EXTRA)
WOLFSSL_X509_CRL* crl = NULL;
byte* bufPtr = NULL;
int bufSz = 0;
(void)jcl;
if (jenv == NULL || buf == NULL) {
return 0;
}
bufPtr = (byte*)(*jenv)->GetByteArrayElements(jenv, buf, NULL);
bufSz = (*jenv)->GetArrayLength(jenv, buf);
if (bufPtr == NULL || bufSz <= 0) {
if (bufPtr != NULL) {
(*jenv)->ReleaseByteArrayElements(
jenv, buf, (jbyte*)bufPtr, JNI_ABORT);
}
return 0;
}
if ((int)format == WOLFSSL_FILETYPE_PEM) {
/* PEM format: use BIO to decode */
WOLFSSL_BIO* bio = wolfSSL_BIO_new_mem_buf(bufPtr, bufSz);
if (bio != NULL) {
crl = wolfSSL_PEM_read_bio_X509_CRL(bio, NULL, NULL, NULL);
wolfSSL_BIO_free(bio);
}
}
else {
/* DER format: decode directly */
crl = wolfSSL_d2i_X509_CRL(NULL, (const unsigned char*)bufPtr, bufSz);
}
(*jenv)->ReleaseByteArrayElements(jenv, buf, (jbyte*)bufPtr, JNI_ABORT);
return (jlong)(uintptr_t)crl;
#else
(void)jenv;
(void)jcl;
(void)buf;
(void)format;
return 0;
#endif
}
JNIEXPORT jlong JNICALL Java_com_wolfssl_WolfSSLCRL_X509_1CRL_1load_1file
(JNIEnv* jenv, jclass jcl, jstring path, jint format)
{
#if defined(HAVE_CRL) && defined(OPENSSL_EXTRA) && \
!defined(NO_FILESYSTEM)
WOLFSSL_X509_CRL* crl = NULL;
const char* cPath = NULL;
XFILE fp = XBADFILE;
(void)jcl;
if (jenv == NULL || path == NULL) {
return 0;
}
cPath = (*jenv)->GetStringUTFChars(jenv, path, NULL);
if (cPath == NULL) {
return 0;
}
fp = XFOPEN(cPath, "rb");
if (fp == XBADFILE) {
(*jenv)->ReleaseStringUTFChars(jenv, path, cPath);
return 0;
}
if ((int)format == WOLFSSL_FILETYPE_PEM) {
crl = wolfSSL_PEM_read_X509_CRL(fp, NULL, NULL, NULL);
}
else {
crl = wolfSSL_d2i_X509_CRL_fp(fp, NULL);
}
XFCLOSE(fp);
(*jenv)->ReleaseStringUTFChars(jenv, path, cPath);
return (jlong)(uintptr_t)crl;
#else
(void)jenv;
(void)jcl;
(void)path;
(void)format;
return 0;
#endif
}
JNIEXPORT jstring JNICALL Java_com_wolfssl_WolfSSLCRL_X509_1CRL_1get_1issuer_1name_1string
(JNIEnv* jenv, jclass jcl, jlong crlPtr)
{
#if defined(HAVE_CRL) && defined(OPENSSL_EXTRA)
WOLFSSL_X509_CRL* crl = (WOLFSSL_X509_CRL*)(uintptr_t)crlPtr;
WOLFSSL_X509_NAME* name = NULL;
char* nameStr = NULL;
jstring ret = NULL;
(void)jcl;
if (jenv == NULL || crl == NULL) {
return NULL;
}
name = wolfSSL_X509_CRL_get_issuer_name(crl);
if (name != NULL) {
nameStr = wolfSSL_X509_NAME_oneline(name, NULL, 0);
if (nameStr == NULL) {
return NULL;
}
ret = (*jenv)->NewStringUTF(jenv, nameStr);
XFREE(nameStr, NULL, DYNAMIC_TYPE_OPENSSL);
return ret;
}
return NULL;
#else
(void)jenv;
(void)jcl;
(void)crlPtr;
return NULL;
#endif
}
JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLCRL_X509_1CRL_1get_1signature_1type
(JNIEnv* jenv, jclass jcl, jlong crlPtr)
{
#if defined(HAVE_CRL) && defined(OPENSSL_EXTRA)
WOLFSSL_X509_CRL* crl = (WOLFSSL_X509_CRL*)(uintptr_t)crlPtr;
(void)jcl;
if (jenv == NULL || crl == NULL) {
return 0;
}
return (jint)wolfSSL_X509_CRL_get_signature_type(crl);
#else
(void)jenv;
(void)jcl;
(void)crlPtr;
return 0;
#endif
}
JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLCRL_X509_1CRL_1get_1signature_1nid
(JNIEnv* jenv, jclass jcl, jlong crlPtr)
{
#if defined(HAVE_CRL) && defined(OPENSSL_EXTRA)
WOLFSSL_X509_CRL* crl = (WOLFSSL_X509_CRL*)(uintptr_t)crlPtr;
(void)jcl;
if (jenv == NULL || crl == NULL) {
return 0;
}
return (jint)wolfSSL_X509_CRL_get_signature_nid(crl);
#else
(void)jenv;
(void)jcl;
(void)crlPtr;
return 0;
#endif
}
/* TODO: wolfSSL_X509_CRL_verify() is currently a stub in wolfSSL
* (src/x509.c, guarded by NO_WOLFSSL_STUB) and always returns 0.
* This JNI wrapper is provided for API completeness and will work
* correctly once the native implementation is completed. */
JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLCRL_X509_1CRL_1verify
(JNIEnv* jenv, jclass jcl, jlong crlPtr, jbyteArray pubKey)
{
#if defined(HAVE_CRL) && defined(OPENSSL_EXTRA)
WOLFSSL_X509_CRL* crl = (WOLFSSL_X509_CRL*)(uintptr_t)crlPtr;
WOLFSSL_EVP_PKEY* pkey = NULL;
unsigned char* buf = NULL;
#if LIBWOLFSSL_VERSION_HEX >= 0x04004000
const unsigned char* ptr = NULL;
#else
unsigned char* ptr = NULL;
#endif
int pubKeySz;
int ret;
(void)jcl;
if (jenv == NULL || crl == NULL || pubKey == NULL) {
return BAD_FUNC_ARG;
}
pubKeySz = (*jenv)->GetArrayLength(jenv, pubKey);
if (pubKeySz <= 0) {
return BAD_FUNC_ARG;
}
buf = (unsigned char*)(*jenv)->GetByteArrayElements(jenv, pubKey, NULL);
if (buf == NULL) {
return MEMORY_E;
}
ptr = buf;
/* Note thatwolfSSL_d2i_PUBKEY advances ptr */
pkey = wolfSSL_d2i_PUBKEY(NULL, &ptr, pubKeySz);
(*jenv)->ReleaseByteArrayElements(jenv, pubKey, (jbyte*)buf, JNI_ABORT);
if (pkey == NULL) {
return WOLFSSL_FAILURE;
}
ret = wolfSSL_X509_CRL_verify(crl, pkey);
wolfSSL_EVP_PKEY_free(pkey);
return ret;
#else
(void)jenv;
(void)jcl;
(void)crlPtr;
(void)pubKey;
return 0;
#endif
}