Skip to content

Commit 4c2c36f

Browse files
committed
Add CRL decode
1 parent 194db83 commit 4c2c36f

10 files changed

Lines changed: 1015 additions & 7 deletions

File tree

examples/certs/test/crl-decode.der

474 Bytes
Binary file not shown.

examples/certs/test/crl-decode.pem

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
-----BEGIN X509 CRL-----
2+
MIIB1jCBvwIBATANBgkqhkiG9w0BAQsFADB9MQswCQYDVQQGEwJVUzEQMA4GA1UE
3+
CAwHTW9udGFuYTEQMA4GA1UEBwwHQm96ZW1hbjEVMBMGA1UECgwMd29sZlNTTCBJ
4+
bmMuMRkwFwYDVQQLDBBEZXZlbG9wbWVudCBUZXN0MRgwFgYDVQQDDA93b2xmU1NM
5+
IFRlc3QgQ0EXDTI2MDIxOTAwMzYyMloXDTM2MDIxNzAwMzYyMlqgDjAMMAoGA1Ud
6+
FAQDAgEBMA0GCSqGSIb3DQEBCwUAA4IBAQCvwOGtRd31ztiKj6SPIe3Oo0bW0MC+
7+
bBqd5oCpupUR9qEdV391PNT2F/h6P61asKJbj5ItPoFAKjOKmCFm6UvJp24ypxmr
8+
n3pbvjFH+ki77+3fyzvZmkbyQC5vrdb8X9dEvwk3/z98x9QB47d2zVyQLMG9ZEHT
9+
uTQXL9liz8V1q2BHy3V8/wwsPJhZTm3sViayixQA80YOtp1+7K08GnOhvAr78Vqd
10+
CvN4lY3GUkzgjt6n4gFSrsahIAyGb7hZ9opSQBAO/SMg1P6J85bYshTWSiD6aLCY
11+
uUxLGPkJSEKdqQph/vAr4JifZQIaIHY9oP4HmDHw8ChFlvz571YHyDLV
12+
-----END X509 CRL-----

examples/certs/update-certs.sh

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,62 @@ rm intermediate/ca-int-ecc-cert.pem.bak
148148
rm intermediate/server-int-cert.pem.bak
149149
rm intermediate/server-int-ecc-cert.pem.bak
150150

151+
# Generate test CRL (PEM and DER) for WolfSSLCRL decode testing.
152+
# Creates a self-signed CA, revokes a dummy serial, produces CRL in
153+
# both PEM and DER formats under test/.
154+
printf "\nGenerating test CRL for CRL decode testing...\n"
155+
TMP_DIR="$(mktemp -d)"
156+
157+
# CA key + self-signed cert
158+
openssl genrsa -out "${TMP_DIR}/crl-test-ca-key.pem" 2048 2>/dev/null
159+
openssl req -x509 -new -nodes \
160+
-key "${TMP_DIR}/crl-test-ca-key.pem" \
161+
-sha256 -days 3650 \
162+
-subj "/C=US/ST=Montana/L=Bozeman/O=wolfSSL Inc./OU=Development Test/CN=wolfSSL Test CA" \
163+
-out "${TMP_DIR}/crl-test-ca-cert.pem" 2>/dev/null
164+
165+
# CRL index / database files required by openssl ca
166+
touch "${TMP_DIR}/index.txt"
167+
echo "01" > "${TMP_DIR}/crlnumber"
168+
169+
cat > "${TMP_DIR}/openssl-ca.cnf" <<EOF
170+
[ ca ]
171+
default_ca = CA_default
172+
173+
[ CA_default ]
174+
database = ${TMP_DIR}/index.txt
175+
crlnumber = ${TMP_DIR}/crlnumber
176+
default_md = sha256
177+
default_crl_days = 3650
178+
179+
[ crl_ext ]
180+
authorityKeyIdentifier = keyid:always
181+
EOF
182+
183+
# Generate CRL with empty revocation list. Decode tests only need to parse
184+
# the CRL structure (issuer, signature, dates, etc.), not iterate entries.
185+
openssl ca -gencrl \
186+
-keyfile "${TMP_DIR}/crl-test-ca-key.pem" \
187+
-cert "${TMP_DIR}/crl-test-ca-cert.pem" \
188+
-config "${TMP_DIR}/openssl-ca.cnf" \
189+
-out test/crl-decode.pem 2>/dev/null
190+
if [ $? -ne 0 ]; then
191+
printf "Failed to generate test/crl-decode.pem\n"
192+
rm -rf "${TMP_DIR}"
193+
exit 1
194+
fi
195+
196+
# Convert PEM CRL to DER
197+
openssl crl -in test/crl-decode.pem -outform DER \
198+
-out test/crl-decode.der 2>/dev/null
199+
if [ $? -ne 0 ]; then
200+
printf "Failed to generate test/crl-decode.der\n"
201+
rm -rf "${TMP_DIR}"
202+
exit 1
203+
fi
204+
rm -rf "${TMP_DIR}"
205+
printf "Generated test/crl-decode.pem and test/crl-decode.der\n"
206+
151207
# Generate SAN test certificates for WolfSSLAltName testing
152208
printf "\nGenerating SAN test certificates...\n"
153209
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"

native/com_wolfssl_WolfSSL.c

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1093,6 +1093,19 @@ JNIEXPORT jboolean JNICALL Java_com_wolfssl_WolfSSL_CrlGenerationEnabled
10931093
#endif
10941094
}
10951095

1096+
JNIEXPORT jboolean JNICALL Java_com_wolfssl_WolfSSL_CrlDecodeEnabled
1097+
(JNIEnv* jenv, jclass jcl)
1098+
{
1099+
(void)jenv;
1100+
(void)jcl;
1101+
1102+
#if defined(HAVE_CRL) && defined(OPENSSL_EXTRA)
1103+
return JNI_TRUE;
1104+
#else
1105+
return JNI_FALSE;
1106+
#endif
1107+
}
1108+
10961109
JNIEXPORT jboolean JNICALL Java_com_wolfssl_WolfSSL_certReqEnabled
10971110
(JNIEnv* jenv, jclass jcl)
10981111
{

native/com_wolfssl_WolfSSL.h

Lines changed: 8 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

native/com_wolfssl_WolfSSLCRL.c

Lines changed: 274 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,10 @@
4444
#define WOLFSSL_JNI_CRL_GEN_ENABLED
4545
#endif
4646

47+
#if defined(HAVE_CRL) && defined(OPENSSL_EXTRA)
48+
#define WOLFSSL_JNI_CRL_DECODE_ENABLED
49+
#endif
50+
4751
JNIEXPORT jlong JNICALL Java_com_wolfssl_WolfSSLCRL_X509_1CRL_1new
4852
(JNIEnv* jenv, jclass jcl)
4953
{
@@ -847,3 +851,273 @@ JNIEXPORT jbyteArray JNICALL Java_com_wolfssl_WolfSSLCRL_X509_1CRL_1get_1signatu
847851
return NULL;
848852
#endif
849853
}
854+
855+
JNIEXPORT jlong JNICALL Java_com_wolfssl_WolfSSLCRL_X509_1CRL_1load_1buffer
856+
(JNIEnv* jenv, jclass jcl, jbyteArray buf, jint format)
857+
{
858+
#if defined(WOLFSSL_JNI_CRL_DECODE_ENABLED)
859+
WOLFSSL_X509_CRL* crl = NULL;
860+
byte* bufPtr = NULL;
861+
int bufSz = 0;
862+
(void)jcl;
863+
864+
if (jenv == NULL || buf == NULL) {
865+
return 0;
866+
}
867+
868+
bufPtr = (byte*)(*jenv)->GetByteArrayElements(
869+
jenv, buf, NULL);
870+
bufSz = (*jenv)->GetArrayLength(jenv, buf);
871+
872+
if (bufPtr == NULL || bufSz <= 0) {
873+
if (bufPtr != NULL) {
874+
(*jenv)->ReleaseByteArrayElements(
875+
jenv, buf, (jbyte*)bufPtr, JNI_ABORT);
876+
}
877+
return 0;
878+
}
879+
880+
if ((int)format == WOLFSSL_FILETYPE_PEM) {
881+
/* PEM format: use BIO to decode */
882+
WOLFSSL_BIO* bio = wolfSSL_BIO_new_mem_buf(
883+
bufPtr, bufSz);
884+
if (bio != NULL) {
885+
crl = wolfSSL_PEM_read_bio_X509_CRL(
886+
bio, NULL, NULL, NULL);
887+
wolfSSL_BIO_free(bio);
888+
}
889+
}
890+
else {
891+
/* DER format: decode directly */
892+
crl = wolfSSL_d2i_X509_CRL(
893+
NULL, (const unsigned char*)bufPtr, bufSz);
894+
}
895+
896+
(*jenv)->ReleaseByteArrayElements(
897+
jenv, buf, (jbyte*)bufPtr, JNI_ABORT);
898+
899+
return (jlong)(uintptr_t)crl;
900+
#else
901+
(void)jenv;
902+
(void)jcl;
903+
(void)buf;
904+
(void)format;
905+
return 0;
906+
#endif
907+
}
908+
909+
JNIEXPORT jlong JNICALL Java_com_wolfssl_WolfSSLCRL_X509_1CRL_1load_1file
910+
(JNIEnv* jenv, jclass jcl, jstring path, jint format)
911+
{
912+
#if defined(WOLFSSL_JNI_CRL_DECODE_ENABLED) && \
913+
!defined(NO_FILESYSTEM)
914+
WOLFSSL_X509_CRL* crl = NULL;
915+
const char* cPath = NULL;
916+
XFILE fp = XBADFILE;
917+
(void)jcl;
918+
919+
if (jenv == NULL || path == NULL) {
920+
return 0;
921+
}
922+
923+
cPath = (*jenv)->GetStringUTFChars(jenv, path, NULL);
924+
if (cPath == NULL) {
925+
return 0;
926+
}
927+
928+
fp = XFOPEN(cPath, "rb");
929+
if (fp == XBADFILE) {
930+
(*jenv)->ReleaseStringUTFChars(jenv, path, cPath);
931+
return 0;
932+
}
933+
934+
if ((int)format == WOLFSSL_FILETYPE_PEM) {
935+
crl = wolfSSL_PEM_read_X509_CRL(
936+
fp, NULL, NULL, NULL);
937+
}
938+
else {
939+
crl = wolfSSL_d2i_X509_CRL_fp(fp, NULL);
940+
}
941+
942+
XFCLOSE(fp);
943+
(*jenv)->ReleaseStringUTFChars(jenv, path, cPath);
944+
945+
return (jlong)(uintptr_t)crl;
946+
#else
947+
(void)jenv;
948+
(void)jcl;
949+
(void)path;
950+
(void)format;
951+
return 0;
952+
#endif
953+
}
954+
955+
JNIEXPORT jstring JNICALL Java_com_wolfssl_WolfSSLCRL_X509_1CRL_1get_1issuer_1name_1string
956+
(JNIEnv* jenv, jclass jcl, jlong crlPtr)
957+
{
958+
#if defined(WOLFSSL_JNI_CRL_DECODE_ENABLED)
959+
WOLFSSL_X509_CRL* crl =
960+
(WOLFSSL_X509_CRL*)(uintptr_t)crlPtr;
961+
WOLFSSL_X509_NAME* name = NULL;
962+
char* nameStr = NULL;
963+
jstring ret = NULL;
964+
(void)jcl;
965+
966+
if (jenv == NULL || crl == NULL) {
967+
return NULL;
968+
}
969+
970+
name = wolfSSL_X509_CRL_get_issuer_name(crl);
971+
if (name != NULL) {
972+
nameStr = wolfSSL_X509_NAME_oneline(name, NULL, 0);
973+
if (nameStr == NULL) {
974+
return NULL;
975+
}
976+
ret = (*jenv)->NewStringUTF(jenv, nameStr);
977+
XFREE(nameStr, NULL, DYNAMIC_TYPE_OPENSSL);
978+
return ret;
979+
}
980+
return NULL;
981+
#else
982+
(void)jenv;
983+
(void)jcl;
984+
(void)crlPtr;
985+
return NULL;
986+
#endif
987+
}
988+
989+
JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLCRL_X509_1CRL_1get_1signature_1type
990+
(JNIEnv* jenv, jclass jcl, jlong crlPtr)
991+
{
992+
#if defined(WOLFSSL_JNI_CRL_DECODE_ENABLED)
993+
WOLFSSL_X509_CRL* crl =
994+
(WOLFSSL_X509_CRL*)(uintptr_t)crlPtr;
995+
(void)jcl;
996+
997+
if (jenv == NULL || crl == NULL) {
998+
return 0;
999+
}
1000+
1001+
return (jint)wolfSSL_X509_CRL_get_signature_type(crl);
1002+
#else
1003+
(void)jenv;
1004+
(void)jcl;
1005+
(void)crlPtr;
1006+
return 0;
1007+
#endif
1008+
}
1009+
1010+
JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLCRL_X509_1CRL_1get_1signature_1nid
1011+
(JNIEnv* jenv, jclass jcl, jlong crlPtr)
1012+
{
1013+
#if defined(WOLFSSL_JNI_CRL_DECODE_ENABLED)
1014+
WOLFSSL_X509_CRL* crl =
1015+
(WOLFSSL_X509_CRL*)(uintptr_t)crlPtr;
1016+
(void)jcl;
1017+
1018+
if (jenv == NULL || crl == NULL) {
1019+
return 0;
1020+
}
1021+
1022+
return (jint)wolfSSL_X509_CRL_get_signature_nid(crl);
1023+
#else
1024+
(void)jenv;
1025+
(void)jcl;
1026+
(void)crlPtr;
1027+
return 0;
1028+
#endif
1029+
}
1030+
1031+
/* TODO: wolfSSL_X509_CRL_verify() is currently a stub in wolfSSL
1032+
* (src/x509.c, guarded by NO_WOLFSSL_STUB) and always returns 0.
1033+
* This JNI wrapper is provided for API completeness and will work
1034+
* correctly once the native implementation is completed. */
1035+
JNIEXPORT jint JNICALL Java_com_wolfssl_WolfSSLCRL_X509_1CRL_1verify
1036+
(JNIEnv* jenv, jclass jcl, jlong crlPtr, jbyteArray pubKey,
1037+
jint pubKeySz)
1038+
{
1039+
#if defined(WOLFSSL_JNI_CRL_DECODE_ENABLED)
1040+
WOLFSSL_X509_CRL* crl =
1041+
(WOLFSSL_X509_CRL*)(uintptr_t)crlPtr;
1042+
WOLFSSL_EVP_PKEY* pkey = NULL;
1043+
unsigned char* buf = NULL;
1044+
#if LIBWOLFSSL_VERSION_HEX >= 0x04004000
1045+
const unsigned char* ptr = NULL;
1046+
#else
1047+
unsigned char* ptr = NULL;
1048+
#endif
1049+
int ret;
1050+
(void)jcl;
1051+
1052+
if (jenv == NULL || crl == NULL ||
1053+
pubKey == NULL || (int)pubKeySz < 0) {
1054+
return BAD_FUNC_ARG;
1055+
}
1056+
1057+
buf = (unsigned char*)XMALLOC(pubKeySz, NULL,
1058+
DYNAMIC_TYPE_TMP_BUFFER);
1059+
if (buf == NULL) {
1060+
return MEMORY_E;
1061+
}
1062+
XMEMSET(buf, 0, pubKeySz);
1063+
1064+
(*jenv)->GetByteArrayRegion(jenv, pubKey, 0,
1065+
pubKeySz, (jbyte*)buf);
1066+
if ((*jenv)->ExceptionOccurred(jenv)) {
1067+
(*jenv)->ExceptionDescribe(jenv);
1068+
(*jenv)->ExceptionClear(jenv);
1069+
XFREE(buf, NULL, DYNAMIC_TYPE_TMP_BUFFER);
1070+
return WOLFSSL_FAILURE;
1071+
}
1072+
ptr = buf;
1073+
1074+
pkey = wolfSSL_d2i_PUBKEY(NULL, &ptr,
1075+
(int)pubKeySz);
1076+
if (pkey == NULL) {
1077+
XFREE(buf, NULL, DYNAMIC_TYPE_TMP_BUFFER);
1078+
return WOLFSSL_FAILURE;
1079+
}
1080+
1081+
ret = wolfSSL_X509_CRL_verify(crl, pkey);
1082+
1083+
wolfSSL_EVP_PKEY_free(pkey);
1084+
XFREE(buf, NULL, DYNAMIC_TYPE_TMP_BUFFER);
1085+
1086+
return ret;
1087+
#else
1088+
(void)jenv;
1089+
(void)jcl;
1090+
(void)crlPtr;
1091+
(void)pubKey;
1092+
(void)pubKeySz;
1093+
return 0;
1094+
#endif
1095+
}
1096+
1097+
/* TODO: wolfSSL_X509_CRL_get_REVOKED() is currently a stub in wolfSSL
1098+
* (src/x509.c, guarded by NO_WOLFSSL_STUB) and always returns NULL.
1099+
* This JNI wrapper is provided for API completeness and will work
1100+
* correctly once the native implementation is completed. */
1101+
JNIEXPORT jlong JNICALL Java_com_wolfssl_WolfSSLCRL_X509_1CRL_1get_1REVOKED
1102+
(JNIEnv* jenv, jclass jcl, jlong crlPtr)
1103+
{
1104+
#if defined(WOLFSSL_JNI_CRL_DECODE_ENABLED)
1105+
WOLFSSL_X509_CRL* crl =
1106+
(WOLFSSL_X509_CRL*)(uintptr_t)crlPtr;
1107+
WOLFSSL_X509_REVOKED* revoked = NULL;
1108+
(void)jcl;
1109+
1110+
if (jenv == NULL || crl == NULL) {
1111+
return 0;
1112+
}
1113+
1114+
revoked = wolfSSL_X509_CRL_get_REVOKED(crl);
1115+
1116+
return (jlong)(uintptr_t)revoked;
1117+
#else
1118+
(void)jenv;
1119+
(void)jcl;
1120+
(void)crlPtr;
1121+
return 0;
1122+
#endif
1123+
}

0 commit comments

Comments
 (0)