Merge pull request #265 from cconlon/fenrirAug24
Fenrir fixes across AES, ECC, RSA, SLH-DSA, DH, and PKIX revocationpull/266/merge
commit
b8392ced50
|
|
@ -888,6 +888,10 @@ revoked, validation will fail. The difference only affects behavior when one
|
|||
method succeeds and the other would have failed (e.g., OCSP unreachable but
|
||||
CRL available).
|
||||
|
||||
A `PKIXRevocationChecker` added with `addCertPathChecker()` applies
|
||||
irregardless of if `setRevocationEnabled()` is set, so `PREFER_CRLS` with CRLs
|
||||
in the `CertStore` list performs CRL checking even when revocation is disabled.
|
||||
|
||||
#### Indirect CRL Not Supported
|
||||
|
||||
Native wolfSSL does not support indirect CRLs. An indirect CRL is a CRL signed
|
||||
|
|
|
|||
|
|
@ -64,17 +64,19 @@ JNIEXPORT void JNICALL Java_com_wolfssl_wolfcrypt_AesGmac_native_1init(
|
|||
JNIEnv* env, jobject this)
|
||||
{
|
||||
#ifdef HAVE_AESGCM
|
||||
int ret = 0;
|
||||
Gmac* gmac = (Gmac*) getNativeStruct(env, this);
|
||||
if ((*env)->ExceptionOccurred(env)) {
|
||||
/* getNativeStruct may throw exception, prevent throwing another */
|
||||
return;
|
||||
}
|
||||
|
||||
/* GMAC struct is already zero-initialized in mallocNativeStruct_internal */
|
||||
/* Actual initialization happens in wc_GmacSetKey when we have the key */
|
||||
ret = wc_AesInit(&gmac->aes, NULL, INVALID_DEVID);
|
||||
if (ret != 0) {
|
||||
throwWolfCryptExceptionFromError(env, ret);
|
||||
}
|
||||
|
||||
LogStr("native_init(gmac=%p)\n", gmac);
|
||||
(void)gmac; /* suppress unused variable warning */
|
||||
#else
|
||||
throwNotCompiledInException(env);
|
||||
#endif
|
||||
|
|
@ -93,9 +95,9 @@ JNIEXPORT void JNICALL Java_com_wolfssl_wolfcrypt_AesGmac_native_1free(
|
|||
LogStr("free Gmac %p\n", gmac);
|
||||
|
||||
if (gmac) {
|
||||
/* Only clear the GMAC struct - do NOT free the memory here.
|
||||
* The base class NativeStruct.xfree() will handle the actual
|
||||
* memory deallocation to avoid double-free. */
|
||||
/* Free AES backend resources, then clear the struct.
|
||||
* NativeStruct.xfree() frees Gmac struct. */
|
||||
wc_AesFree(&gmac->aes);
|
||||
XMEMSET(gmac, 0, sizeof(Gmac));
|
||||
}
|
||||
#else
|
||||
|
|
@ -242,8 +244,10 @@ JNIEXPORT jint JNICALL Java_com_wolfssl_wolfcrypt_AesGmac_wc_1Gmac(
|
|||
authInSz = getByteArrayLength(env, authIn_object);
|
||||
authTagSz = getByteArrayLength(env, authTag_object);
|
||||
|
||||
/* Set the key */
|
||||
ret = wc_GmacSetKey(&gmac, key, keySz);
|
||||
ret = wc_AesInit(&gmac.aes, NULL, INVALID_DEVID);
|
||||
if (ret == 0) {
|
||||
ret = wc_GmacSetKey(&gmac, key, keySz);
|
||||
}
|
||||
|
||||
if (ret == 0) {
|
||||
/* Use a local buffer for the auth tag result to avoid
|
||||
|
|
@ -319,8 +323,10 @@ JNIEXPORT jint JNICALL Java_com_wolfssl_wolfcrypt_AesGmac_wc_1GmacVerify(
|
|||
authInSz = getByteArrayLength(env, authIn_object);
|
||||
authTagSz = getByteArrayLength(env, authTag_object);
|
||||
|
||||
/* Set the key */
|
||||
ret = wc_GmacSetKey(&gmac, key, keySz);
|
||||
ret = wc_AesInit(&gmac.aes, NULL, INVALID_DEVID);
|
||||
if (ret == 0) {
|
||||
ret = wc_GmacSetKey(&gmac, key, keySz);
|
||||
}
|
||||
|
||||
if (ret == 0) {
|
||||
/* Generate the expected tag and compare */
|
||||
|
|
|
|||
|
|
@ -71,6 +71,7 @@ Java_com_wolfssl_wolfcrypt_AesOfb_native_1set_1key_1internal(
|
|||
byte* key = NULL;
|
||||
byte* iv = NULL;
|
||||
word32 keySz = 0;
|
||||
(void)opmode;
|
||||
|
||||
aes = (Aes*) getNativeStruct(env, this);
|
||||
if ((*env)->ExceptionOccurred(env)) {
|
||||
|
|
@ -87,7 +88,7 @@ Java_com_wolfssl_wolfcrypt_AesOfb_native_1set_1key_1internal(
|
|||
}
|
||||
|
||||
if (ret == 0) {
|
||||
ret = wc_AesSetKey(aes, key, keySz, iv, opmode);
|
||||
ret = wc_AesSetKey(aes, key, keySz, iv, AES_ENCRYPTION);
|
||||
}
|
||||
|
||||
if (ret != 0) {
|
||||
|
|
|
|||
|
|
@ -320,7 +320,6 @@ Java_com_wolfssl_wolfcrypt_Dh_wc_1DhGenerateKeyPair(
|
|||
LogStr("wc_DhGenerateKeyPair(key, rng, priv, privSz, pub, pubSz) = %d\n",
|
||||
ret);
|
||||
LogStr("private[%u]: [%p]\n", privSz, priv);
|
||||
LogHex(priv, 0, privSz);
|
||||
LogStr("public[%u]: [%p]\n", pubSz, pub);
|
||||
LogHex(pub, 0, pubSz);
|
||||
|
||||
|
|
@ -455,7 +454,6 @@ Java_com_wolfssl_wolfcrypt_Dh_wc_1DhAgree(
|
|||
LogStr("wc_DhAgree(key, secret, secretSz, priv, privSz, pub, pubSz) = %d\n",
|
||||
ret);
|
||||
LogStr("secret[%u]: [%p]\n", secretSz, secret);
|
||||
LogHex(secret, 0, secretSz);
|
||||
|
||||
if (secret != NULL) {
|
||||
#if (LIBWOLFSSL_VERSION_HEX >= 0x05008004) && \
|
||||
|
|
|
|||
|
|
@ -164,6 +164,7 @@ JNIEXPORT void JNICALL Java_com_wolfssl_wolfcrypt_Ecc_wc_1ecc_1make_1key_1ex
|
|||
{
|
||||
#ifdef HAVE_ECC
|
||||
int ret = 0;
|
||||
int curveId = 0;
|
||||
ecc_key* ecc = NULL;
|
||||
RNG* rng = NULL;
|
||||
const char* name = NULL;
|
||||
|
|
@ -188,29 +189,26 @@ JNIEXPORT void JNICALL Java_com_wolfssl_wolfcrypt_Ecc_wc_1ecc_1make_1key_1ex
|
|||
if (ret == 0) {
|
||||
name = (*env)->GetStringUTFChars(env, curveName, 0);
|
||||
if (name == NULL) {
|
||||
ret = BAD_FUNC_ARG;
|
||||
/* GetStringUTFChars failed with an exception already pending */
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (ret == 0) {
|
||||
ret = wc_ecc_get_curve_id_from_name(name);
|
||||
curveId = wc_ecc_get_curve_id_from_name(name);
|
||||
(*env)->ReleaseStringUTFChars(env, curveName, name);
|
||||
|
||||
if (curveId < 0) {
|
||||
throwWolfCryptException(env,
|
||||
"ECC curve unsupported or not enabled");
|
||||
return;
|
||||
}
|
||||
|
||||
/* Pass keysize 0 so the curve_id sets the key size, required for
|
||||
* FIPS where approved curves need keysize 0 */
|
||||
ret = wc_ecc_make_key_ex(rng, 0, ecc, curveId);
|
||||
}
|
||||
|
||||
if (ret < 0) {
|
||||
throwWolfCryptException(env, "ECC curve unsupported or not enabled");
|
||||
|
||||
} else {
|
||||
/* When using a specific curve_id, pass keysize as 0 to let the
|
||||
* curve_id determine the key size. This is required for FIPS mode
|
||||
* compatibility where keysize must be 0 when using approved curves.
|
||||
* The 'size' parameter from Java is ignored here since curve_id
|
||||
* (stored in ret) defines the actual key size. */
|
||||
ret = wc_ecc_make_key_ex(rng, 0, ecc, ret);
|
||||
|
||||
if (ret < 0) {
|
||||
throwWolfCryptExceptionFromError(env, ret);
|
||||
}
|
||||
if (ret != 0) {
|
||||
throwWolfCryptExceptionFromError(env, ret);
|
||||
}
|
||||
|
||||
LogStr("ecc_make_key_ex(rng, size, ecc=%p) = %d\n", ecc, ret);
|
||||
|
|
|
|||
|
|
@ -527,7 +527,11 @@ JNIEXPORT jboolean JNICALL Java_com_wolfssl_wolfcrypt_FeatureDetect_RsaPssLongSa
|
|||
{
|
||||
(void)env;
|
||||
(void)jcl;
|
||||
#if !defined(NO_RSA) && defined(WC_RSA_PSS) && defined(WOLFSSL_PSS_LONG_SALT)
|
||||
/* FIPS v7 and later cap the PSS salt at the digest length, even when
|
||||
* WOLFSSL_PSS_LONG_SALT is defined */
|
||||
#if !defined(NO_RSA) && defined(WC_RSA_PSS) && \
|
||||
defined(WOLFSSL_PSS_LONG_SALT) && \
|
||||
!(defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 7))
|
||||
return JNI_TRUE;
|
||||
#else
|
||||
return JNI_FALSE;
|
||||
|
|
|
|||
|
|
@ -561,23 +561,6 @@ JNIEXPORT jbyteArray JNICALL Java_com_wolfssl_wolfcrypt_Rsa_wc_1RsaPrivateKeyToP
|
|||
}
|
||||
}
|
||||
|
||||
/* Get PKCS#8 output size, into pkcs8Sz */
|
||||
if (ret == 0) {
|
||||
ret = wc_CreatePKCS8Key(NULL, &pkcs8Sz, derKey, derKeySz, algoID,
|
||||
curveOID, oidSz);
|
||||
if (ret == LENGTH_ONLY_E) {
|
||||
pkcs8 = (byte*)XMALLOC(pkcs8Sz, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
||||
if (pkcs8 == NULL) {
|
||||
ret = MEMORY_E;
|
||||
}
|
||||
else {
|
||||
XMEMSET(pkcs8, 0, pkcs8Sz);
|
||||
pkcs8BufSz = pkcs8Sz;
|
||||
ret = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (ret == 0) {
|
||||
/* Allocate temp buffer to hold DER encoded key */
|
||||
derKey = (byte*)XMALLOC(derKeySz, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
||||
|
|
@ -599,6 +582,23 @@ JNIEXPORT jbyteArray JNICALL Java_com_wolfssl_wolfcrypt_Rsa_wc_1RsaPrivateKeyToP
|
|||
}
|
||||
}
|
||||
|
||||
/* Get PKCS#8 output size, into pkcs8Sz. */
|
||||
if (ret == 0) {
|
||||
ret = wc_CreatePKCS8Key(NULL, &pkcs8Sz, derKey, derKeySz, algoID,
|
||||
curveOID, oidSz);
|
||||
if (ret == LENGTH_ONLY_E) {
|
||||
pkcs8 = (byte*)XMALLOC(pkcs8Sz, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
||||
if (pkcs8 == NULL) {
|
||||
ret = MEMORY_E;
|
||||
}
|
||||
else {
|
||||
XMEMSET(pkcs8, 0, pkcs8Sz);
|
||||
pkcs8BufSz = pkcs8Sz;
|
||||
ret = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Create PKCS#8 from DER key */
|
||||
if (ret == 0) {
|
||||
ret = wc_CreatePKCS8Key(pkcs8, &pkcs8Sz, derKey, derKeySz,
|
||||
|
|
|
|||
|
|
@ -50,6 +50,12 @@
|
|||
/* #define WOLFCRYPT_JNI_DEBUG_ON */
|
||||
#include <wolfcrypt_jni_debug.h>
|
||||
|
||||
#if (LIBWOLFSSL_VERSION_HEX >= 0x05008004) && !defined(WOLFSSL_NO_FORCE_ZERO)
|
||||
#define SLHDSA_FORCE_ZERO(p, len) wc_ForceZero((p), (len))
|
||||
#else
|
||||
#define SLHDSA_FORCE_ZERO(p, len) XMEMSET((p), 0, (len))
|
||||
#endif
|
||||
|
||||
/* A WOLFSSL_SLHDSA_VERIFY_ONLY build provides only public-key verify. DER
|
||||
* encode (KeyToDer / PublicKeyToDer) additionally needs
|
||||
* WC_ENABLE_ASYM_KEY_EXPORT. */
|
||||
|
|
@ -1258,7 +1264,7 @@ JNIEXPORT jbyteArray JNICALL Java_com_wolfssl_wolfcrypt_SlhDsa_wc_1SlhDsaKey_1ex
|
|||
|
||||
LogStr("wc_SlhDsaKey_ExportPrivate(key=%p) = %d\n", key, ret);
|
||||
|
||||
wc_ForceZero(output, outputBufSz);
|
||||
SLHDSA_FORCE_ZERO(output, outputBufSz);
|
||||
XFREE(output, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
||||
#else
|
||||
(void)env;
|
||||
|
|
@ -1463,7 +1469,7 @@ JNIEXPORT jbyteArray JNICALL Java_com_wolfssl_wolfcrypt_SlhDsa_wc_1SlhDsaKey_1Ke
|
|||
|
||||
LogStr("wc_SlhDsaKey_KeyToDer(key=%p) = %d\n", key, ret);
|
||||
|
||||
wc_ForceZero(output, outputBufSz);
|
||||
SLHDSA_FORCE_ZERO(output, outputBufSz);
|
||||
XFREE(output, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
||||
#else
|
||||
(void)env;
|
||||
|
|
@ -1558,7 +1564,7 @@ JNIEXPORT void JNICALL Java_com_wolfssl_wolfcrypt_SlhDsa_wc_1SlhDsaKey_1PrivateK
|
|||
LogStr("wc_SlhDsaKey_PrivateKeyDecode(key=%p) = %d\n", key, ret);
|
||||
|
||||
if (derCopy != NULL) {
|
||||
wc_ForceZero(derCopy, derLen);
|
||||
SLHDSA_FORCE_ZERO(derCopy, derLen);
|
||||
XFREE(derCopy, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
||||
}
|
||||
releaseByteArray(env, der_object, der, JNI_ABORT);
|
||||
|
|
|
|||
|
|
@ -523,6 +523,9 @@ JNIEXPORT jint JNICALL Java_com_wolfssl_wolfcrypt_WolfSSLCertManager_CertManager
|
|||
}
|
||||
|
||||
buff = (byte*)(*env)->GetByteArrayElements(env, in, NULL);
|
||||
if (buff == NULL) {
|
||||
return MEMORY_E;
|
||||
}
|
||||
buffSz = (word32)sz;
|
||||
|
||||
ret = wolfSSL_CertManagerLoadCABuffer(cm, buff, buffSz, format);
|
||||
|
|
@ -547,6 +550,9 @@ JNIEXPORT jint JNICALL Java_com_wolfssl_wolfcrypt_WolfSSLCertManager_CertManager
|
|||
}
|
||||
|
||||
buff = (byte*)(*env)->GetByteArrayElements(env, in, NULL);
|
||||
if (buff == NULL) {
|
||||
return MEMORY_E;
|
||||
}
|
||||
buffSz = (word32)sz;
|
||||
|
||||
ret = wolfSSL_CertManagerLoadCABuffer_ex(cm, buff, buffSz, format, 0,
|
||||
|
|
@ -588,6 +594,9 @@ JNIEXPORT jint JNICALL Java_com_wolfssl_wolfcrypt_WolfSSLCertManager_CertManager
|
|||
}
|
||||
|
||||
buff = (byte*)(*env)->GetByteArrayElements(env, in, NULL);
|
||||
if (buff == NULL) {
|
||||
return MEMORY_E;
|
||||
}
|
||||
buffSz = (word32)sz;
|
||||
|
||||
ret = wolfSSL_CertManagerVerifyBuffer(cm, buff, buffSz, format);
|
||||
|
|
@ -656,6 +665,9 @@ JNIEXPORT jint JNICALL Java_com_wolfssl_wolfcrypt_WolfSSLCertManager_CertManager
|
|||
}
|
||||
|
||||
buff = (byte*)(*env)->GetByteArrayElements(env, in, NULL);
|
||||
if (buff == NULL) {
|
||||
return MEMORY_E;
|
||||
}
|
||||
buffSz = (word32)sz;
|
||||
|
||||
ret = wolfSSL_CertManagerLoadCRLBuffer(cm, buff, buffSz, type);
|
||||
|
|
|
|||
|
|
@ -73,7 +73,8 @@ import java.security.cert.CertificateException;
|
|||
* validation will not return PolicyNode in CertPathValidatorResult
|
||||
*
|
||||
* Revocation checking is supported via:
|
||||
* - CRL: If PKIXParameters.isRevocationEnabled() is true and appropriate
|
||||
* - CRL: If PKIXParameters.isRevocationEnabled() is true, or a
|
||||
* PKIXRevocationChecker with PREFER_CRLS is registered, and appropriate
|
||||
* CRLs have been loaded into CertStore Set
|
||||
* - OCSP: via getRevocationChecker() which returns a
|
||||
* WolfCryptPKIXRevocationChecker supporting OCSP and options
|
||||
|
|
@ -839,25 +840,71 @@ public class WolfCryptPKIXCertPathValidator extends CertPathValidatorSpi {
|
|||
CertPath certPath, List<X509Certificate> certs)
|
||||
throws CertPathValidatorException {
|
||||
|
||||
/* Report index of last cert in path (closest to trust anchor)
|
||||
* to match SunJCE behavior. */
|
||||
int failIndex = 0;
|
||||
if (certs != null && certs.size() > 1) {
|
||||
failIndex = certs.size() - 1;
|
||||
}
|
||||
throw new CertPathValidatorException(message, null, certPath,
|
||||
failIndex, BasicReason.UNDETERMINED_REVOCATION_STATUS);
|
||||
lastCertIndex(certs), BasicReason.UNDETERMINED_REVOCATION_STATUS);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if revocation has been enabled in PKIXParameters, and if so
|
||||
* find and load any CRLs in params.getCertStores().
|
||||
* Index of cert closest to the trust anchor.
|
||||
*
|
||||
* When a PKIXRevocationChecker is registered via addCertPathChecker(),
|
||||
* that checker handles revocation checking. CRL checking in the native
|
||||
* CertManager is only enabled if:
|
||||
* - No PKIXRevocationChecker is present (default CRL behavior), or
|
||||
* - PKIXRevocationChecker has PREFER_CRLS option set
|
||||
* @param certs certificate list from the CertPath
|
||||
*
|
||||
* @return index of the last cert, or 0 for a single-cert path
|
||||
*/
|
||||
private static int lastCertIndex(List<X509Certificate> certs) {
|
||||
|
||||
if (certs != null && certs.size() > 1) {
|
||||
return certs.size() - 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Disable native CRL checking after a PREFER_CRLS checker found no CRL
|
||||
* to load, so wolfSSL doesn't fail chain validation on a missing CRL. With
|
||||
* NO_FALLBACK set, revocation is undetermined, which fails validation
|
||||
* unless SOFT_FAIL is set. Without NO_FALLBACK, the OCSP result the
|
||||
* checker already produced in check() propogates.
|
||||
*
|
||||
* @param revChecker the registered PREFER_CRLS checker
|
||||
* @param noFallback true if the checker has NO_FALLBACK set
|
||||
* @param cm WolfSSLCertManager with CRL checking enabled
|
||||
* @param certPath the CertPath being validated, for exception reporting
|
||||
* @param failIndex index of the cert to report
|
||||
*
|
||||
* @throws CertPathValidatorException if revocation is undetermined and
|
||||
* SOFT_FAIL is not set, or native CRL checking cannot be disabled
|
||||
*/
|
||||
private void handleMissingCrl(WolfCryptPKIXRevocationChecker revChecker,
|
||||
boolean noFallback, WolfSSLCertManager cm, CertPath certPath,
|
||||
int failIndex) throws CertPathValidatorException {
|
||||
|
||||
if (noFallback) {
|
||||
revChecker.handleMissingCrlRevocation(certPath, failIndex);
|
||||
}
|
||||
else {
|
||||
log("no CRL loaded, PREFER_CRLS checker falls back to OCSP");
|
||||
}
|
||||
|
||||
try {
|
||||
cm.CertManagerDisableCRL();
|
||||
}
|
||||
catch (WolfCryptException e) {
|
||||
throw new CertPathValidatorException("Failed to disable CRL " +
|
||||
"checking in native WolfSSLCertManager", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if CRL checking is wanted and, if so, find and load any CRLs in
|
||||
* params.getCertStores().
|
||||
*
|
||||
* CRL checking in the native CertManager is enabled when
|
||||
* PKIXParameters.isRevocationEnabled() is true, or when a
|
||||
* PKIXRevocationChecker with PREFER_CRLS is registered, which applies
|
||||
* irregardless of the revocation flag. A registered checker without
|
||||
* PREFER_CRLS handles revocation itself via OCSP.
|
||||
*
|
||||
* @param params parameters used to check if revocation is enabled and,
|
||||
* if so load any CRLs available
|
||||
|
|
@ -877,10 +924,13 @@ public class WolfCryptPKIXCertPathValidator extends CertPathValidatorSpi {
|
|||
int i = 0;
|
||||
int loadedCount = 0;
|
||||
int certCount = 0;
|
||||
int failIndex = lastCertIndex(certs);
|
||||
List<CertStore> stores = null;
|
||||
Collection<? extends CRL> crls = null;
|
||||
boolean hasRevocationChecker = false;
|
||||
boolean preferCrls = false;
|
||||
boolean noFallback = false;
|
||||
WolfCryptPKIXRevocationChecker revChecker = null;
|
||||
|
||||
if (params == null || cm == null) {
|
||||
throw new CertPathValidatorException(
|
||||
|
|
@ -894,13 +944,14 @@ public class WolfCryptPKIXCertPathValidator extends CertPathValidatorSpi {
|
|||
for (PKIXCertPathChecker checker : pathCheckers) {
|
||||
if (checker instanceof WolfCryptPKIXRevocationChecker) {
|
||||
hasRevocationChecker = true;
|
||||
WolfCryptPKIXRevocationChecker revChecker =
|
||||
(WolfCryptPKIXRevocationChecker)checker;
|
||||
revChecker = (WolfCryptPKIXRevocationChecker)checker;
|
||||
Set<PKIXRevocationChecker.Option> options =
|
||||
revChecker.getOptions();
|
||||
if (options != null && options.contains(
|
||||
PKIXRevocationChecker.Option.PREFER_CRLS)) {
|
||||
preferCrls = true;
|
||||
if (options != null) {
|
||||
preferCrls = options.contains(
|
||||
PKIXRevocationChecker.Option.PREFER_CRLS);
|
||||
noFallback = options.contains(
|
||||
PKIXRevocationChecker.Option.NO_FALLBACK);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
|
@ -913,18 +964,24 @@ public class WolfCryptPKIXCertPathValidator extends CertPathValidatorSpi {
|
|||
return;
|
||||
}
|
||||
|
||||
if (params.isRevocationEnabled()) {
|
||||
log("revocation enabled in PKIXParameters, checking for CRLs " +
|
||||
"to load");
|
||||
if (params.isRevocationEnabled() || preferCrls) {
|
||||
log("revocation enabled or PREFER_CRLS checker registered, " +
|
||||
"checking for CRLs to load");
|
||||
|
||||
if (!WolfCrypt.CrlEnabled()) {
|
||||
throw new CertPathValidatorException(
|
||||
"Revocation enabled in PKIXParameters but native " +
|
||||
"wolfCrypt CRL not compiled in");
|
||||
"CRL checking requested but native wolfCrypt CRL not " +
|
||||
"compiled in");
|
||||
}
|
||||
|
||||
/* Enable CRL in native WolfSSLCertManager */
|
||||
cm.CertManagerEnableCRL(WolfCrypt.WOLFSSL_CRL_CHECK);
|
||||
try {
|
||||
cm.CertManagerEnableCRL(WolfCrypt.WOLFSSL_CRL_CHECK);
|
||||
}
|
||||
catch (WolfCryptException e) {
|
||||
throw new CertPathValidatorException("Failed to enable CRL " +
|
||||
"checking in native WolfSSLCertManager", e);
|
||||
}
|
||||
log("CRL support enabled in native WolfSSLCertManager");
|
||||
|
||||
stores = params.getCertStores();
|
||||
|
|
@ -940,6 +997,10 @@ public class WolfCryptPKIXCertPathValidator extends CertPathValidatorSpi {
|
|||
"and no PKIXRevocationChecker configured for OCSP",
|
||||
certPath, certs);
|
||||
}
|
||||
else {
|
||||
handleMissingCrl(revChecker, noFallback, cm, certPath,
|
||||
failIndex);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
|
@ -990,22 +1051,32 @@ public class WolfCryptPKIXCertPathValidator extends CertPathValidatorSpi {
|
|||
}
|
||||
} catch (CertStoreException e) {
|
||||
throw new CertPathValidatorException(e);
|
||||
} catch (WolfCryptException e) {
|
||||
throw new CertPathValidatorException(
|
||||
"Failed to load CRL into native WolfSSLCertManager", e);
|
||||
}
|
||||
|
||||
log("loaded " + loadedCount + " CRLs into WolfSSLCertManager");
|
||||
|
||||
/* If no CRLs were loaded and no PKIXRevocationChecker is handling
|
||||
* OCSP, we cannot determine revocation status. */
|
||||
if (loadedCount == 0 && !hasRevocationChecker) {
|
||||
throwUndeterminedRevocationStatus(
|
||||
"Revocation checking enabled but no CRLs found in " +
|
||||
"CertStores and no PKIXRevocationChecker configured " +
|
||||
"for OCSP",
|
||||
certPath, certs);
|
||||
if (loadedCount == 0) {
|
||||
if (!hasRevocationChecker) {
|
||||
throwUndeterminedRevocationStatus(
|
||||
"Revocation checking enabled but no CRLs found in " +
|
||||
"CertStores and no PKIXRevocationChecker configured " +
|
||||
"for OCSP",
|
||||
certPath, certs);
|
||||
}
|
||||
else {
|
||||
handleMissingCrl(revChecker, noFallback, cm, certPath,
|
||||
failIndex);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
log("revocation not enabled in PKIXParameters");
|
||||
log("revocation not enabled in PKIXParameters and no PREFER_CRLS" +
|
||||
"checker registered");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@ package com.wolfssl.provider.jce;
|
|||
import java.net.URI;
|
||||
import java.security.cert.Certificate;
|
||||
import java.security.cert.CertificateEncodingException;
|
||||
import java.security.cert.CertPath;
|
||||
import java.security.cert.CertPathValidatorException;
|
||||
import java.security.cert.CertPathValidatorException.BasicReason;
|
||||
import java.security.cert.Extension;
|
||||
|
|
@ -543,6 +544,27 @@ public class WolfCryptPKIXRevocationChecker extends PKIXRevocationChecker {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Fail closed when a PREFER_CRLS/NO_FALLBACK checker has no CRL source.
|
||||
*
|
||||
* check() runs before CRLs are loaded and cannot see whether a CRL source
|
||||
* is configured, so the validator calls this after CRL setup. With OCSP
|
||||
* suppressed by NO_FALLBACK and no CRL to check, revocation status is
|
||||
* undetermined. Honors SOFT_FAIL via handleException().
|
||||
*
|
||||
* @param certPath the CertPath being validated, for exception reporting
|
||||
* @param index index of the cert whose revocation status is undetermined
|
||||
*
|
||||
* @throws CertPathValidatorException if SOFT_FAIL is not set
|
||||
*/
|
||||
void handleMissingCrlRevocation(CertPath certPath, int index)
|
||||
throws CertPathValidatorException {
|
||||
handleException(new CertPathValidatorException(
|
||||
"PREFER_CRLS with NO_FALLBACK selected but no CRL source is " +
|
||||
"available, revocation status cannot be determined", null,
|
||||
certPath, index, BasicReason.UNDETERMINED_REVOCATION_STATUS));
|
||||
}
|
||||
|
||||
/**
|
||||
* Set OCSP responder URI override.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -904,11 +904,10 @@ public class WolfCryptUtil {
|
|||
* Get minimum key size limit from disabled algorithms security property
|
||||
* for specified algorithm.
|
||||
*
|
||||
* Parses constraints like "RSA keySize < 1024" from the security
|
||||
* property and returns the minimum allowed key size. Entries are
|
||||
* matched on their leading algorithm name, any algorithm name may be
|
||||
* used. Only the "<" and "<=" operators are supported, entries
|
||||
* using other operators are ignored.
|
||||
* Parses constraints (ex: {@code RSA keySize < 1024}) from the security
|
||||
* property and returns the minimum allowed key size. Match entries on their
|
||||
* leading algorithm name. Only {@code <} and {@code <=} operators are
|
||||
* supported, entries using other operators are ignored.
|
||||
*
|
||||
* @param algo Algorithm to search for key size limitation for
|
||||
* (ex: "RSA", "DH", "DSA", "EC")
|
||||
|
|
@ -920,30 +919,38 @@ public class WolfCryptUtil {
|
|||
public static int getDisabledAlgorithmsKeySizeLimit(String algo,
|
||||
String propertyName) {
|
||||
|
||||
return getDisabledAlgorithmsKeySizeLimit(algo, propertyName, false);
|
||||
return getDisabledAlgorithmsKeySizeLimit(algo, propertyName, false, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Internal implementation of getDisabledAlgorithmsKeySizeLimit().
|
||||
*
|
||||
* Matches entries on their leading algorithm name so that, for
|
||||
* Matches entries on leading algorithm name so that, for
|
||||
* example, an "ECDH keySize" entry does not set the "DH" limit.
|
||||
*
|
||||
* With a known keySize, an entry disables the key only when all of its
|
||||
* keySize constraints match. denyAfter and jdkCA qualifiers are treated as
|
||||
* satisfied rather than evaluated, so an entry using them fails closed.
|
||||
* With keySize 0, only the floor from the first {@code <} or {@code <=}
|
||||
* constraint is returned.
|
||||
*
|
||||
* @param algo Algorithm to search for key size limitation for
|
||||
* (ex: "RSA", "DH", "DSA", "EC")
|
||||
* @param propertyName Security property name to check
|
||||
* @param certPathContext true when checking for CertPath validation,
|
||||
* skips entries scoped to usage contexts that can never apply
|
||||
* there
|
||||
* @param keySize actual key size in bits, or 0 to compute the floor only
|
||||
*
|
||||
* @return minimum key size allowed, or 0 if not set in property
|
||||
* @return -1 if keySize is disabled, the min-size floor when keySize is
|
||||
* 0, or 0 when no constraint applies
|
||||
*/
|
||||
private static int getDisabledAlgorithmsKeySizeLimit(String algo,
|
||||
String propertyName, boolean certPathContext) {
|
||||
String propertyName, boolean certPathContext, int keySize) {
|
||||
|
||||
int ret = 0;
|
||||
List<String> disabledList = null;
|
||||
Pattern p = Pattern.compile("keySize\\s*<(=?)\\s*(\\d+)",
|
||||
Pattern p = Pattern.compile("keySize\\s*(>=|<=|==|!=|>|<)\\s*(\\d+)",
|
||||
Pattern.CASE_INSENSITIVE);
|
||||
Matcher match = null;
|
||||
|
||||
|
|
@ -959,8 +966,7 @@ public class WolfCryptUtil {
|
|||
disabledList = getExpandedDisabledEntries(propertyName);
|
||||
|
||||
for (String s : disabledList) {
|
||||
/* Match on the leading algorithm name only, so "ECDH keySize"
|
||||
* does not match algo "DH" */
|
||||
/* Match on leading algorithm name only */
|
||||
String disabledName = extractDisabledAlgorithmName(s);
|
||||
if (disabledName == null || !disabledName.equalsIgnoreCase(algo)) {
|
||||
continue;
|
||||
|
|
@ -973,20 +979,54 @@ public class WolfCryptUtil {
|
|||
}
|
||||
|
||||
match = p.matcher(s);
|
||||
if (match.find()) {
|
||||
try {
|
||||
int limit = Integer.parseInt(match.group(2));
|
||||
if (match.group(1).equals("=") &&
|
||||
limit < Integer.MAX_VALUE) {
|
||||
/* "keySize <= N" disables through N, minimum allowed
|
||||
* size is N + 1 */
|
||||
limit = limit + 1;
|
||||
|
||||
if (keySize > 0) {
|
||||
boolean anyConstraint = false;
|
||||
boolean allMatch = true;
|
||||
while (match.find()) {
|
||||
String op = match.group(1);
|
||||
int limit;
|
||||
try {
|
||||
limit = Integer.parseInt(match.group(2));
|
||||
} catch (NumberFormatException e) {
|
||||
/* Exceeds Integer.MAX_VALUE, ignore this constraint */
|
||||
continue;
|
||||
}
|
||||
/* Keep the strictest of multiple matching entries */
|
||||
ret = Math.max(ret, limit);
|
||||
} catch (NumberFormatException e) {
|
||||
/* Number exceeds Integer.MAX_VALUE, ignore malformed
|
||||
* number and leave ret unchanged. */
|
||||
anyConstraint = true;
|
||||
boolean matches =
|
||||
(op.equals("<") && keySize < limit) ||
|
||||
(op.equals("<=") && keySize <= limit) ||
|
||||
(op.equals(">") && keySize > limit) ||
|
||||
(op.equals(">=") && keySize >= limit) ||
|
||||
(op.equals("==") && keySize == limit) ||
|
||||
(op.equals("!=") && keySize != limit);
|
||||
if (!matches) {
|
||||
allMatch = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (anyConstraint && allMatch) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* keySize unknown, derive floor from first < or <= */
|
||||
while (match.find()) {
|
||||
String op = match.group(1);
|
||||
if (!op.equals("<") && !op.equals("<=")) {
|
||||
continue;
|
||||
}
|
||||
try {
|
||||
int limit = Integer.parseInt(match.group(2));
|
||||
if (op.equals("<=") && limit < Integer.MAX_VALUE) {
|
||||
/* "keySize <= N" disables N, min allowed N + 1 */
|
||||
limit = limit + 1;
|
||||
}
|
||||
ret = Math.max(ret, limit);
|
||||
} catch (NumberFormatException e) {
|
||||
/* Number exceeds Integer.MAX_VALUE, ignore */
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1049,7 +1089,7 @@ public class WolfCryptUtil {
|
|||
boolean certPathContext) {
|
||||
|
||||
int keySize = 0;
|
||||
int minSize = 0;
|
||||
int sizeLimit = 0;
|
||||
String algorithm = null;
|
||||
|
||||
if (key == null) {
|
||||
|
|
@ -1067,8 +1107,8 @@ public class WolfCryptUtil {
|
|||
if (key instanceof RSAPublicKey) {
|
||||
RSAPublicKey rsaKey = (RSAPublicKey)key;
|
||||
keySize = rsaKey.getModulus().bitLength();
|
||||
minSize = getDisabledAlgorithmsKeySizeLimit("RSA", propertyName,
|
||||
certPathContext);
|
||||
sizeLimit = getDisabledAlgorithmsKeySizeLimit("RSA", propertyName,
|
||||
certPathContext, keySize);
|
||||
}
|
||||
else if (key instanceof ECPublicKey) {
|
||||
ECPublicKey ecKey = (ECPublicKey)key;
|
||||
|
|
@ -1097,24 +1137,24 @@ public class WolfCryptUtil {
|
|||
}
|
||||
}
|
||||
|
||||
minSize = getDisabledAlgorithmsKeySizeLimit("EC", propertyName,
|
||||
certPathContext);
|
||||
sizeLimit = getDisabledAlgorithmsKeySizeLimit("EC", propertyName,
|
||||
certPathContext, keySize);
|
||||
}
|
||||
else if (key instanceof DSAPublicKey) {
|
||||
DSAPublicKey dsaKey = (DSAPublicKey)key;
|
||||
if (dsaKey.getParams() != null) {
|
||||
keySize = dsaKey.getParams().getP().bitLength();
|
||||
}
|
||||
minSize = getDisabledAlgorithmsKeySizeLimit("DSA", propertyName,
|
||||
certPathContext);
|
||||
sizeLimit = getDisabledAlgorithmsKeySizeLimit("DSA", propertyName,
|
||||
certPathContext, keySize);
|
||||
}
|
||||
else if (key instanceof DHPublicKey) {
|
||||
DHPublicKey dhKey = (DHPublicKey)key;
|
||||
if (dhKey.getParams() != null) {
|
||||
keySize = dhKey.getParams().getP().bitLength();
|
||||
}
|
||||
minSize = getDisabledAlgorithmsKeySizeLimit("DH", propertyName,
|
||||
certPathContext);
|
||||
sizeLimit = getDisabledAlgorithmsKeySizeLimit("DH", propertyName,
|
||||
certPathContext, keySize);
|
||||
}
|
||||
else if (key instanceof WolfCryptMlDsaPublicKey) {
|
||||
/* ML-DSA uses fixed parameter sets, no key size constraints */
|
||||
|
|
@ -1136,8 +1176,13 @@ public class WolfCryptUtil {
|
|||
certPathContext);
|
||||
}
|
||||
|
||||
/* If minimum size constraint exists and key is smaller, reject */
|
||||
if (minSize > 0 && keySize < minSize) {
|
||||
/* Negative limit means a >/>=/==/!= disabled this size. */
|
||||
if (sizeLimit < 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Reject a key below the min size floor */
|
||||
if (sizeLimit > 0 && keySize < sizeLimit) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -66,10 +66,18 @@ public class AesGmac extends NativeStruct {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void releaseNativeStruct() {
|
||||
public synchronized void releaseNativeStruct() {
|
||||
synchronized (stateLock) {
|
||||
native_free();
|
||||
super.releaseNativeStruct();
|
||||
if (state == WolfCryptState.RELEASED) {
|
||||
return;
|
||||
}
|
||||
synchronized (pointerLock) {
|
||||
if (state != WolfCryptState.UNINITIALIZED) {
|
||||
native_free();
|
||||
}
|
||||
super.releaseNativeStruct();
|
||||
}
|
||||
state = WolfCryptState.RELEASED;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -225,8 +233,10 @@ public class AesGmac extends NativeStruct {
|
|||
}
|
||||
|
||||
private void throwIfKeyNotLoaded() throws IllegalStateException {
|
||||
if (state != WolfCryptState.READY) {
|
||||
throw new IllegalStateException("No key available");
|
||||
synchronized (stateLock) {
|
||||
if (state != WolfCryptState.READY) {
|
||||
throw new IllegalStateException("No key available");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -326,10 +326,10 @@ public class FeatureDetect {
|
|||
public static native boolean RsaPssEnabled();
|
||||
|
||||
/**
|
||||
* Tests if RSA-PSS salt lengths longer than the digest are compiled into
|
||||
* the native wolfSSL library (WOLFSSL_PSS_LONG_SALT).
|
||||
* Tests if RSA-PSS salt lengths longer than the digest are supported by
|
||||
* the native wolfSSL library.
|
||||
*
|
||||
* @return true if enabled, otherwise false if not compiled in.
|
||||
* @return true if supported, otherwise false.
|
||||
*/
|
||||
public static native boolean RsaPssLongSaltEnabled();
|
||||
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@ import org.junit.BeforeClass;
|
|||
|
||||
import java.util.List;
|
||||
import java.util.ArrayList;
|
||||
import java.util.EnumSet;
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
|
@ -41,6 +42,10 @@ import java.io.File;
|
|||
import java.io.InputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.FileInputStream;
|
||||
import java.util.Arrays;
|
||||
import java.nio.file.Paths;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.security.Security;
|
||||
import java.security.Provider;
|
||||
|
|
@ -57,6 +62,7 @@ import java.security.cert.CertPath;
|
|||
import java.security.cert.CertPathValidator;
|
||||
import java.security.cert.CertPathValidatorResult;
|
||||
import java.security.cert.PKIXParameters;
|
||||
import java.security.cert.PKIXRevocationChecker;
|
||||
import java.security.cert.PKIXCertPathChecker;
|
||||
import java.security.cert.PKIXCertPathValidatorResult;
|
||||
import java.security.cert.CertificateException;
|
||||
|
|
@ -97,6 +103,7 @@ public class WolfCryptPKIXCertPathValidatorTest {
|
|||
protected static String caCertDer = null; /* ca-cert.der */
|
||||
protected static String caEccCertDer = null; /* ca-ecc-cert.der */
|
||||
protected static String crlDer = null; /* crl.der */
|
||||
protected static String crlRevoked = null; /* crl.revoked */
|
||||
|
||||
/* RSA-based cert chain with intermediates:
|
||||
* server/peer: server-int-cert.pem/der
|
||||
|
|
@ -208,6 +215,8 @@ public class WolfCryptPKIXCertPathValidatorTest {
|
|||
|
||||
crlDer =
|
||||
certPre.concat("examples/certs/crl/crl.der");
|
||||
crlRevoked =
|
||||
certPre.concat("examples/certs/crl/crl.revoked");
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -314,6 +323,312 @@ public class WolfCryptPKIXCertPathValidatorTest {
|
|||
checkPKIXCertPathValidatorResult(result, caCert, certPubKey);
|
||||
}
|
||||
|
||||
/* Build a single server-cert path validated against the RSA CA anchor. */
|
||||
private CertPath singleServerCertPath(CertificateFactory certFactory)
|
||||
throws Exception {
|
||||
|
||||
List<Certificate> certList = new ArrayList<>();
|
||||
InputStream fis = new FileInputStream(serverCertDer);
|
||||
certList.add(certFactory.generateCertificate(fis));
|
||||
fis.close();
|
||||
return certFactory.generateCertPath(certList);
|
||||
}
|
||||
|
||||
/**
|
||||
* PREFER_CRLS with NO_FALLBACK and no CRL source must fail closed with
|
||||
* UNDETERMINED_REVOCATION_STATUS.
|
||||
*/
|
||||
@Test
|
||||
public void testPreferCrlsNoFallbackWithoutCrlFailsClosed()
|
||||
throws Exception {
|
||||
|
||||
KeyStore store = createKeyStoreFromFile(jksCaServerRSA2048,
|
||||
keyStorePass);
|
||||
if (store == null || store.size() != 1) {
|
||||
throw new Exception("Error creating KeyStore");
|
||||
}
|
||||
|
||||
CertificateFactory certFactory =
|
||||
CertificateFactory.getInstance("X.509");
|
||||
CertPath path = singleServerCertPath(certFactory);
|
||||
CertPathValidator cpv = CertPathValidator.getInstance("PKIX", provider);
|
||||
|
||||
PKIXRevocationChecker rc =
|
||||
(PKIXRevocationChecker) cpv.getRevocationChecker();
|
||||
rc.setOptions(EnumSet.of(PKIXRevocationChecker.Option.PREFER_CRLS,
|
||||
PKIXRevocationChecker.Option.NO_FALLBACK));
|
||||
|
||||
PKIXParameters params = new PKIXParameters(store);
|
||||
params.setRevocationEnabled(false);
|
||||
params.addCertPathChecker(rc);
|
||||
|
||||
try {
|
||||
cpv.validate(path, params);
|
||||
fail("Validation should fail closed with no CRL source");
|
||||
} catch (CertPathValidatorException e) {
|
||||
assertEquals(BasicReason.UNDETERMINED_REVOCATION_STATUS,
|
||||
e.getReason());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* With SOFT_FAIL, the missing-CRL determination is soft, so validation
|
||||
* completes instead of failing closed. The soft-fail exception is not
|
||||
* asserted here because addCertPathChecker() clones rc, so it lands on
|
||||
* the clone rather than rc.
|
||||
*/
|
||||
@Test
|
||||
public void testPreferCrlsNoFallbackWithoutCrlSoftFailPasses()
|
||||
throws Exception {
|
||||
|
||||
KeyStore store = createKeyStoreFromFile(jksCaServerRSA2048,
|
||||
keyStorePass);
|
||||
if (store == null || store.size() != 1) {
|
||||
throw new Exception("Error creating KeyStore");
|
||||
}
|
||||
|
||||
CertificateFactory certFactory =
|
||||
CertificateFactory.getInstance("X.509");
|
||||
CertPath path = singleServerCertPath(certFactory);
|
||||
CertPathValidator cpv =
|
||||
CertPathValidator.getInstance("PKIX", provider);
|
||||
|
||||
PKIXRevocationChecker rc =
|
||||
(PKIXRevocationChecker) cpv.getRevocationChecker();
|
||||
rc.setOptions(EnumSet.of(PKIXRevocationChecker.Option.PREFER_CRLS,
|
||||
PKIXRevocationChecker.Option.NO_FALLBACK,
|
||||
PKIXRevocationChecker.Option.SOFT_FAIL));
|
||||
|
||||
PKIXParameters params = new PKIXParameters(store);
|
||||
params.setRevocationEnabled(false);
|
||||
params.addCertPathChecker(rc);
|
||||
|
||||
cpv.validate(path, params);
|
||||
}
|
||||
|
||||
/**
|
||||
* SOFT_FAIL with revocation enabled but no CRL source must also complete.
|
||||
* Revocation turns on the native CRL check, so the missing-CRL path must
|
||||
* disable it under SOFT_FAIL to avoid a hard CRL_MISSING failure.
|
||||
*/
|
||||
@Test
|
||||
public void testPreferCrlsNoFallbackRevocationEnabledSoftFailPasses()
|
||||
throws Exception {
|
||||
|
||||
if (!WolfCrypt.CrlEnabled()) {
|
||||
System.out.println("CertPathValidator revocation status test " +
|
||||
"skipped, CRL not compiled in");
|
||||
return;
|
||||
}
|
||||
|
||||
KeyStore store = createKeyStoreFromFile(jksCaServerRSA2048,
|
||||
keyStorePass);
|
||||
if (store == null || store.size() != 1) {
|
||||
throw new Exception("Error creating KeyStore");
|
||||
}
|
||||
|
||||
CertificateFactory certFactory =
|
||||
CertificateFactory.getInstance("X.509");
|
||||
CertPath path = singleServerCertPath(certFactory);
|
||||
CertPathValidator cpv = CertPathValidator.getInstance("PKIX", provider);
|
||||
|
||||
PKIXRevocationChecker rc =
|
||||
(PKIXRevocationChecker) cpv.getRevocationChecker();
|
||||
rc.setOptions(EnumSet.of(PKIXRevocationChecker.Option.PREFER_CRLS,
|
||||
PKIXRevocationChecker.Option.NO_FALLBACK,
|
||||
PKIXRevocationChecker.Option.SOFT_FAIL));
|
||||
|
||||
PKIXParameters params = new PKIXParameters(store);
|
||||
params.setRevocationEnabled(true);
|
||||
params.addCertPathChecker(rc);
|
||||
|
||||
cpv.validate(path, params);
|
||||
}
|
||||
|
||||
/**
|
||||
* Load a CRL from a file. Some CRL files carry a PEM text dump ahead
|
||||
* of the PEM block, which not every CertificateFactory skips, so start
|
||||
* at the PEM header when one is present.
|
||||
*/
|
||||
private CRL crlFromFile(CertificateFactory certFactory, String path)
|
||||
throws Exception {
|
||||
|
||||
byte[] data = Files.readAllBytes(Paths.get(path));
|
||||
int begin = new String(data, StandardCharsets.US_ASCII)
|
||||
.indexOf("-----BEGIN X509 CRL-----");
|
||||
|
||||
if (begin > 0) {
|
||||
data = Arrays.copyOfRange(data, begin, data.length);
|
||||
}
|
||||
return certFactory.generateCRL(new ByteArrayInputStream(data));
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate the single server cert with a PREFER_CRLS/NO_FALLBACK checker
|
||||
* and the given CRL supplied through a CertStore.
|
||||
*/
|
||||
private void validatePreferCrlsNoFallbackWithCrl(String crlPath,
|
||||
boolean revocationEnabled) throws Exception {
|
||||
|
||||
KeyStore store = createKeyStoreFromFile(jksCaServerRSA2048,
|
||||
keyStorePass);
|
||||
if (store == null || store.size() != 1) {
|
||||
throw new Exception("Error creating KeyStore");
|
||||
}
|
||||
|
||||
CertificateFactory certFactory =
|
||||
CertificateFactory.getInstance("X.509");
|
||||
CertPath path = singleServerCertPath(certFactory);
|
||||
CertPathValidator cpv = CertPathValidator.getInstance("PKIX", provider);
|
||||
|
||||
PKIXRevocationChecker rc =
|
||||
(PKIXRevocationChecker) cpv.getRevocationChecker();
|
||||
rc.setOptions(EnumSet.of(PKIXRevocationChecker.Option.PREFER_CRLS,
|
||||
PKIXRevocationChecker.Option.NO_FALLBACK));
|
||||
|
||||
/* CRL files are issued by ca-cert.der, the root for server-cert */
|
||||
Collection<CRL> crls = new HashSet<>();
|
||||
crls.add(crlFromFile(certFactory, crlPath));
|
||||
List<CertStore> certStores = new ArrayList<>();
|
||||
certStores.add(CertStore.getInstance("Collection",
|
||||
new CollectionCertStoreParameters(crls)));
|
||||
|
||||
PKIXParameters params = new PKIXParameters(store);
|
||||
params.setCertStores(certStores);
|
||||
params.setRevocationEnabled(revocationEnabled);
|
||||
params.addCertPathChecker(rc);
|
||||
|
||||
cpv.validate(path, params);
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate a server cert with a PREFER_CRLS checker that allows OCSP
|
||||
* fallback, SOFT_FAIL set, and no CRL source.
|
||||
*/
|
||||
private void validatePreferCrlsFallbackSoftFailWithoutCrl(
|
||||
boolean revocationEnabled) throws Exception {
|
||||
|
||||
KeyStore store = createKeyStoreFromFile(jksCaServerRSA2048,
|
||||
keyStorePass);
|
||||
if (store == null || store.size() != 1) {
|
||||
throw new Exception("Error creating KeyStore");
|
||||
}
|
||||
|
||||
CertificateFactory certFactory =
|
||||
CertificateFactory.getInstance("X.509");
|
||||
CertPath path = singleServerCertPath(certFactory);
|
||||
CertPathValidator cpv = CertPathValidator.getInstance("PKIX", provider);
|
||||
|
||||
PKIXRevocationChecker rc =
|
||||
(PKIXRevocationChecker) cpv.getRevocationChecker();
|
||||
rc.setOptions(EnumSet.of(PKIXRevocationChecker.Option.PREFER_CRLS,
|
||||
PKIXRevocationChecker.Option.SOFT_FAIL));
|
||||
|
||||
PKIXParameters params = new PKIXParameters(store);
|
||||
params.setRevocationEnabled(revocationEnabled);
|
||||
params.addCertPathChecker(rc);
|
||||
|
||||
cpv.validate(path, params);
|
||||
}
|
||||
|
||||
/**
|
||||
* PREFER_CRLS with fallback allowed and no CRL source must not fail on
|
||||
* a missing CRL, revocation is then determined by OCSP alone. With
|
||||
* SOFT_FAIL an unreachable OCSP responder is not fatal, so validation
|
||||
* should complete successfully.
|
||||
*/
|
||||
@Test
|
||||
public void testPreferCrlsFallbackWithoutCrlSoftFailPasses()
|
||||
throws Exception {
|
||||
|
||||
if (!WolfCrypt.CrlEnabled()) {
|
||||
System.out.println(
|
||||
"PREFER_CRLS fallback test skipped, CRL not compiled in");
|
||||
return;
|
||||
}
|
||||
|
||||
validatePreferCrlsFallbackSoftFailWithoutCrl(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* PREFER_CRLS with fallback allowed, SOFT_FAIL, no CRL source, and
|
||||
* revocation enabled must not fail on the missing CRL, revocation is
|
||||
* then determined only by OCSP.
|
||||
*/
|
||||
@Test
|
||||
public void testPreferCrlsFallbackEnabledWithoutCrlSoftFailPasses()
|
||||
throws Exception {
|
||||
|
||||
if (!WolfCrypt.CrlEnabled()) {
|
||||
System.out.println(
|
||||
"PREFER_CRLS fallback test skipped, CRL not compiled in");
|
||||
return;
|
||||
}
|
||||
|
||||
validatePreferCrlsFallbackSoftFailWithoutCrl(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* A PREFER_CRLS/NO_FALLBACK checker with CRLs actually loaded must still
|
||||
* validate a non-revoked cert. The missing-CRL fail-closed path must not
|
||||
* fire when a CRL source is present.
|
||||
*/
|
||||
@Test
|
||||
public void testPreferCrlsNoFallbackWithCrlValidates()
|
||||
throws Exception {
|
||||
|
||||
if (!WolfCrypt.CrlEnabled()) {
|
||||
System.out.println(
|
||||
"PREFER_CRLS with CRL test skipped, CRL not compiled in");
|
||||
return;
|
||||
}
|
||||
|
||||
validatePreferCrlsNoFallbackWithCrl(crlDer, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* A checker added with addCertPathChecker() applies irrespective of
|
||||
* setRevocationEnabled(), so PREFER_CRLS with a CRL in the CertStores is
|
||||
* a supported CRL-only setup even with revocation disabled.
|
||||
*/
|
||||
@Test
|
||||
public void testPreferCrlsNoFallbackRevocationDisabledWithCrlValidates()
|
||||
throws Exception {
|
||||
|
||||
if (!WolfCrypt.CrlEnabled()) {
|
||||
System.out.println(
|
||||
"PREFER_CRLS with CRL test skipped, CRL not compiled in");
|
||||
return;
|
||||
}
|
||||
|
||||
validatePreferCrlsNoFallbackWithCrl(crlDer, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* PREFER_CRLS with NO_FALLBACK, revocation disabled, and a CRL in the
|
||||
* CertStores that revokes the server cert must fail validation, proving
|
||||
* the supplied CRL is checked and not just ignored.
|
||||
*/
|
||||
@Test
|
||||
public void testPreferCrlsNoFallbackRevocationDisabledRevokedFails()
|
||||
throws Exception {
|
||||
|
||||
if (!WolfCrypt.CrlEnabled()) {
|
||||
System.out.println(
|
||||
"PREFER_CRLS with CRL test skipped, CRL not compiled in");
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
validatePreferCrlsNoFallbackWithCrl(crlRevoked, false);
|
||||
fail("Revoked cert should fail with revocation disabled and " +
|
||||
"PREFER_CRLS");
|
||||
|
||||
} catch (CertPathValidatorException e) {
|
||||
/* expected */
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that setting the target cert constraints with
|
||||
* PKIXParameters.setTargetCertConstraints() passes with correct cert
|
||||
|
|
@ -2049,6 +2364,96 @@ public class WolfCryptPKIXCertPathValidatorTest {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* PREFER_CRLS/NO_FALLBACK with revocation enabled and a CertStore that
|
||||
* loads no matching CRL (loadedCount == 0) must fail closed.
|
||||
*/
|
||||
@Test
|
||||
public void testPreferCrlsNoFallbackEmptyCertStoreFailsClosed()
|
||||
throws Exception {
|
||||
|
||||
if (!WolfCrypt.CrlEnabled()) {
|
||||
System.out.println("CertPathValidator revocation status test " +
|
||||
"skipped, CRL not compiled in");
|
||||
return;
|
||||
}
|
||||
|
||||
KeyStore store = createKeyStoreFromFile(jksCaServerRSA2048,
|
||||
keyStorePass);
|
||||
if (store == null || store.size() != 1) {
|
||||
throw new Exception("Error creating KeyStore");
|
||||
}
|
||||
|
||||
CertificateFactory certFactory =
|
||||
CertificateFactory.getInstance("X.509");
|
||||
CertPath path = singleServerCertPath(certFactory);
|
||||
CertPathValidator cpv = CertPathValidator.getInstance("PKIX", provider);
|
||||
|
||||
PKIXRevocationChecker rc =
|
||||
(PKIXRevocationChecker) cpv.getRevocationChecker();
|
||||
rc.setOptions(EnumSet.of(PKIXRevocationChecker.Option.PREFER_CRLS,
|
||||
PKIXRevocationChecker.Option.NO_FALLBACK));
|
||||
|
||||
PKIXParameters params = new PKIXParameters(store);
|
||||
params.setRevocationEnabled(true);
|
||||
params.addCertPathChecker(rc);
|
||||
/* Non-empty store list holding no matching CRL drives loadedCount 0 */
|
||||
List<CertStore> certStores = new ArrayList<>();
|
||||
certStores.add(CertStore.getInstance("Collection",
|
||||
new CollectionCertStoreParameters(new HashSet<CRL>())));
|
||||
params.setCertStores(certStores);
|
||||
|
||||
try {
|
||||
cpv.validate(path, params);
|
||||
fail("Expected UNDETERMINED_REVOCATION_STATUS");
|
||||
} catch (CertPathValidatorException e) {
|
||||
assertEquals(BasicReason.UNDETERMINED_REVOCATION_STATUS,
|
||||
e.getReason());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Same as above with SOFT_FAIL, validation must complete because the
|
||||
* missing-CRL path disables the native CRL check.
|
||||
*/
|
||||
@Test
|
||||
public void testPreferCrlsNoFallbackEmptyCertStoreSoftFailPasses()
|
||||
throws Exception {
|
||||
|
||||
if (!WolfCrypt.CrlEnabled()) {
|
||||
System.out.println("CertPathValidator revocation status test " +
|
||||
"skipped, CRL not compiled in");
|
||||
return;
|
||||
}
|
||||
|
||||
KeyStore store = createKeyStoreFromFile(jksCaServerRSA2048,
|
||||
keyStorePass);
|
||||
if (store == null || store.size() != 1) {
|
||||
throw new Exception("Error creating KeyStore");
|
||||
}
|
||||
|
||||
CertificateFactory certFactory =
|
||||
CertificateFactory.getInstance("X.509");
|
||||
CertPath path = singleServerCertPath(certFactory);
|
||||
CertPathValidator cpv = CertPathValidator.getInstance("PKIX", provider);
|
||||
|
||||
PKIXRevocationChecker rc =
|
||||
(PKIXRevocationChecker) cpv.getRevocationChecker();
|
||||
rc.setOptions(EnumSet.of(PKIXRevocationChecker.Option.PREFER_CRLS,
|
||||
PKIXRevocationChecker.Option.NO_FALLBACK,
|
||||
PKIXRevocationChecker.Option.SOFT_FAIL));
|
||||
|
||||
PKIXParameters params = new PKIXParameters(store);
|
||||
params.setRevocationEnabled(true);
|
||||
params.addCertPathChecker(rc);
|
||||
List<CertStore> certStores = new ArrayList<>();
|
||||
certStores.add(CertStore.getInstance("Collection",
|
||||
new CollectionCertStoreParameters(new HashSet<CRL>())));
|
||||
params.setCertStores(certStores);
|
||||
|
||||
cpv.validate(path, params);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that zero-length cert paths are valid per RFC 5280. This occurs
|
||||
* when CertPathBuilder determines the trust anchor itself is the target.
|
||||
|
|
|
|||
|
|
@ -1821,7 +1821,7 @@ public class WolfCryptSignatureTest {
|
|||
|
||||
if (!FeatureDetect.RsaPssLongSaltEnabled()) {
|
||||
System.out.println("\tSkipping max salt lengths, " +
|
||||
"WOLFSSL_PSS_LONG_SALT not compiled in");
|
||||
"long PSS salts not supported by native wolfSSL");
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -2218,7 +2218,7 @@ public class WolfCryptSignatureTest {
|
|||
/* Uses the maximum salt length for each digest */
|
||||
if (!FeatureDetect.RsaPssLongSaltEnabled()) {
|
||||
System.out.println(
|
||||
"\tSkipping, WOLFSSL_PSS_LONG_SALT not compiled in");
|
||||
"\tSkipping, long PSS salts not supported by native wolfSSL");
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1196,10 +1196,17 @@ public class WolfCryptUtilTest {
|
|||
WolfCryptUtil.getDisabledAlgorithmsKeySizeLimit(
|
||||
"RSA", "jdk.certpath.disabledAlgorithms"));
|
||||
|
||||
/* Unsupported operators are ignored */
|
||||
/* The floor overload returns 0 for non-floor operators */
|
||||
Security.setProperty("jdk.certpath.disabledAlgorithms",
|
||||
"RSA keySize >= 8192");
|
||||
assertEquals("Unsupported operator should be ignored", 0,
|
||||
assertEquals("keySize >= sets no minimum-size floor", 0,
|
||||
WolfCryptUtil.getDisabledAlgorithmsKeySizeLimit(
|
||||
"RSA", "jdk.certpath.disabledAlgorithms"));
|
||||
|
||||
/* An & chain still yields the floor from its < constraint */
|
||||
Security.setProperty("jdk.certpath.disabledAlgorithms",
|
||||
"RSA keySize >= 1024 & keySize < 2048");
|
||||
assertEquals("floor comes from the < half of an & chain", 2048,
|
||||
WolfCryptUtil.getDisabledAlgorithmsKeySizeLimit(
|
||||
"RSA", "jdk.certpath.disabledAlgorithms"));
|
||||
|
||||
|
|
@ -1290,6 +1297,126 @@ public class WolfCryptUtilTest {
|
|||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsKeyAllowedKeySizeOperators() throws Exception {
|
||||
|
||||
String origProperty = Security.getProperty(
|
||||
"jdk.certpath.disabledAlgorithms");
|
||||
PublicKey rsaPub = null;
|
||||
|
||||
try {
|
||||
KeyPairGenerator kpg =
|
||||
KeyPairGenerator.getInstance("RSA", "wolfJCE");
|
||||
kpg.initialize(2048);
|
||||
rsaPub = kpg.generateKeyPair().getPublic();
|
||||
} catch (Exception e) {
|
||||
/* skip, RSA key generation not available */
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
Security.setProperty("jdk.certpath.disabledAlgorithms",
|
||||
"RSA keySize == 2048");
|
||||
assertFalse("keySize == N must reject a key of size N",
|
||||
WolfCryptUtil.isKeyAllowed(rsaPub,
|
||||
"jdk.certpath.disabledAlgorithms"));
|
||||
Security.setProperty("jdk.certpath.disabledAlgorithms",
|
||||
"RSA keySize == 4096");
|
||||
assertTrue("keySize == N must allow a key of a different size",
|
||||
WolfCryptUtil.isKeyAllowed(rsaPub,
|
||||
"jdk.certpath.disabledAlgorithms"));
|
||||
|
||||
Security.setProperty("jdk.certpath.disabledAlgorithms",
|
||||
"RSA keySize >= 2048");
|
||||
assertFalse("keySize >= N must reject a key of size N",
|
||||
WolfCryptUtil.isKeyAllowed(rsaPub,
|
||||
"jdk.certpath.disabledAlgorithms"));
|
||||
Security.setProperty("jdk.certpath.disabledAlgorithms",
|
||||
"RSA keySize >= 4096");
|
||||
assertTrue("keySize >= N must allow a key below N",
|
||||
WolfCryptUtil.isKeyAllowed(rsaPub,
|
||||
"jdk.certpath.disabledAlgorithms"));
|
||||
|
||||
Security.setProperty("jdk.certpath.disabledAlgorithms",
|
||||
"RSA keySize > 1024");
|
||||
assertFalse("keySize > N must reject a key above N",
|
||||
WolfCryptUtil.isKeyAllowed(rsaPub,
|
||||
"jdk.certpath.disabledAlgorithms"));
|
||||
Security.setProperty("jdk.certpath.disabledAlgorithms",
|
||||
"RSA keySize > 2048");
|
||||
assertTrue("keySize > N must allow a key of size N",
|
||||
WolfCryptUtil.isKeyAllowed(rsaPub,
|
||||
"jdk.certpath.disabledAlgorithms"));
|
||||
|
||||
Security.setProperty("jdk.certpath.disabledAlgorithms",
|
||||
"RSA keySize != 4096");
|
||||
assertFalse("keySize != N must reject a key of a different size",
|
||||
WolfCryptUtil.isKeyAllowed(rsaPub,
|
||||
"jdk.certpath.disabledAlgorithms"));
|
||||
Security.setProperty("jdk.certpath.disabledAlgorithms",
|
||||
"RSA keySize != 2048");
|
||||
assertTrue("keySize != N must allow a key of size N",
|
||||
WolfCryptUtil.isKeyAllowed(rsaPub,
|
||||
"jdk.certpath.disabledAlgorithms"));
|
||||
|
||||
/* < and <= remain handled by the minimum-size floor */
|
||||
Security.setProperty("jdk.certpath.disabledAlgorithms",
|
||||
"RSA keySize < 4096");
|
||||
assertFalse("keySize < N must reject a key below N",
|
||||
WolfCryptUtil.isKeyAllowed(rsaPub,
|
||||
"jdk.certpath.disabledAlgorithms"));
|
||||
Security.setProperty("jdk.certpath.disabledAlgorithms",
|
||||
"RSA keySize < 2048");
|
||||
assertTrue("keySize < N must allow a key of size N",
|
||||
WolfCryptUtil.isKeyAllowed(rsaPub,
|
||||
"jdk.certpath.disabledAlgorithms"));
|
||||
|
||||
Security.setProperty("jdk.certpath.disabledAlgorithms",
|
||||
"RSA keySize < 1024, RSA keySize > 4096");
|
||||
assertTrue("floor plus a non-matching range must allow the key",
|
||||
WolfCryptUtil.isKeyAllowed(rsaPub,
|
||||
"jdk.certpath.disabledAlgorithms"));
|
||||
Security.setProperty("jdk.certpath.disabledAlgorithms",
|
||||
"RSA keySize < 1024, RSA keySize >= 2048");
|
||||
assertFalse("floor plus a matching range must reject the key",
|
||||
WolfCryptUtil.isKeyAllowed(rsaPub,
|
||||
"jdk.certpath.disabledAlgorithms"));
|
||||
|
||||
Security.setProperty("jdk.certpath.disabledAlgorithms",
|
||||
"RSA keySize >= 2048");
|
||||
assertFalse("keySize >= N rejects via CertPath overload",
|
||||
WolfCryptUtil.isKeyAllowedForCertPath(rsaPub,
|
||||
"jdk.certpath.disabledAlgorithms"));
|
||||
|
||||
/* & chains AND their keySize constraints, an entry disables the
|
||||
* key only when every constraint holds */
|
||||
Security.setProperty("jdk.certpath.disabledAlgorithms",
|
||||
"RSA keySize >= 1024 & keySize < 2048");
|
||||
assertTrue("key outside an AND range must be allowed",
|
||||
WolfCryptUtil.isKeyAllowed(rsaPub,
|
||||
"jdk.certpath.disabledAlgorithms"));
|
||||
Security.setProperty("jdk.certpath.disabledAlgorithms",
|
||||
"RSA keySize >= 1024 & keySize <= 2048");
|
||||
assertFalse("key inside an AND range must be rejected",
|
||||
WolfCryptUtil.isKeyAllowed(rsaPub,
|
||||
"jdk.certpath.disabledAlgorithms"));
|
||||
|
||||
/* denyAfter is not evaluated, the entry fails closed on keySize */
|
||||
Security.setProperty("jdk.certpath.disabledAlgorithms",
|
||||
"RSA keySize == 2048 & denyAfter 2999-01-01");
|
||||
assertFalse("denyAfter entry applies unconditionally on keySize",
|
||||
WolfCryptUtil.isKeyAllowed(rsaPub,
|
||||
"jdk.certpath.disabledAlgorithms"));
|
||||
} finally {
|
||||
if (origProperty != null) {
|
||||
Security.setProperty("jdk.certpath.disabledAlgorithms",
|
||||
origProperty);
|
||||
} else {
|
||||
Security.setProperty("jdk.certpath.disabledAlgorithms", "");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsKeyAllowedECNamedCurve() throws Exception {
|
||||
|
||||
|
|
|
|||
|
|
@ -2104,6 +2104,10 @@ public class WolfSSLKeyStoreTest {
|
|||
WolfCryptProvider prov = null;
|
||||
KeyStore store = null;
|
||||
|
||||
/* The Android platform PKCS12 provider cannot read the PBES2/PBKDF2
|
||||
* client.p12, matching testLoadWKSasJKSFromFile which also skips. */
|
||||
Assume.assumeTrue(!isAndroid());
|
||||
|
||||
/* Use client.wks (clientWKS) to test. Any WKS KeyStore could be used,
|
||||
* this was just picked since was first used/tested in test above. */
|
||||
|
||||
|
|
|
|||
|
|
@ -377,6 +377,46 @@ public class AesGmacTest {
|
|||
gmac.releaseNativeStruct();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAesGmacSetKeyAfterReleaseThrows() {
|
||||
if (!FeatureDetect.AesGmacEnabled()) {
|
||||
/* skip test if AES-GMAC is not compiled in native wolfCrypt */
|
||||
return;
|
||||
}
|
||||
|
||||
AesGmac gmac = new AesGmac();
|
||||
gmac.setKey(new byte[16]);
|
||||
gmac.releaseNativeStruct();
|
||||
|
||||
/* Re-keying a released object must throw, its AES was freed */
|
||||
try {
|
||||
gmac.setKey(new byte[16]);
|
||||
fail("Expected IllegalStateException");
|
||||
} catch (IllegalStateException e) {
|
||||
/* Expected */
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAesGmacReleaseBeforeSetKey() {
|
||||
if (!FeatureDetect.AesGmacEnabled()) {
|
||||
/* skip test if AES-GMAC is not compiled in native wolfCrypt */
|
||||
return;
|
||||
}
|
||||
|
||||
/* Release with no key set must free quietly, twice is harmless */
|
||||
AesGmac gmac = new AesGmac();
|
||||
gmac.releaseNativeStruct();
|
||||
gmac.releaseNativeStruct();
|
||||
|
||||
try {
|
||||
gmac.setKey(new byte[16]);
|
||||
fail("Expected IllegalStateException");
|
||||
} catch (IllegalStateException e) {
|
||||
/* Expected */
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAesGmacInvalidInputs() {
|
||||
if (!FeatureDetect.AesGmacEnabled()) {
|
||||
|
|
|
|||
|
|
@ -207,6 +207,25 @@ public class AesOfbTest {
|
|||
aesOfb.releaseNativeStruct();
|
||||
}
|
||||
|
||||
/**
|
||||
* A DECRYPT_MODE key schedule must still recover ciphertext produced
|
||||
* under ENCRYPT_MODE.
|
||||
*/
|
||||
@Test
|
||||
public void aes128OfbDecryptModeSetKeyRoundTrip() {
|
||||
AesOfb enc = new AesOfb();
|
||||
enc.setKey(KEY_128, IV_128, AesOfb.ENCRYPT_MODE);
|
||||
byte[] ciphertext = enc.encrypt(PLAINTEXT_128);
|
||||
assertArrayEquals(CIPHERTEXT_128, ciphertext);
|
||||
enc.releaseNativeStruct();
|
||||
|
||||
AesOfb dec = new AesOfb();
|
||||
dec.setKey(KEY_128, IV_128, AesOfb.DECRYPT_MODE);
|
||||
byte[] decrypted = dec.decrypt(ciphertext);
|
||||
assertArrayEquals(PLAINTEXT_128, decrypted);
|
||||
dec.releaseNativeStruct();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void aes128OfbLongDataTest() {
|
||||
AesOfb aesOfb = new AesOfb();
|
||||
|
|
|
|||
|
|
@ -297,6 +297,19 @@ public class EccTest {
|
|||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void eccMakeKeyOnCurveNullRngReportsBadFuncArg() {
|
||||
Ecc alice = new Ecc();
|
||||
try {
|
||||
/* A null Rng is an argument error, not a curve problem, so it
|
||||
* must be reported as BAD_FUNC_ARG */
|
||||
alice.makeKeyOnCurve(null, 32, "secp256r1");
|
||||
fail("null Rng should fail with exception");
|
||||
} catch (WolfCryptException e) {
|
||||
assertEquals(WolfCryptError.BAD_FUNC_ARG, e.getError());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void eccPrivateToPkcs8() {
|
||||
Ecc alice = new Ecc();
|
||||
|
|
|
|||
|
|
@ -423,6 +423,21 @@ public class RsaTest {
|
|||
pub.releaseNativeStruct();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void rsaPrivateKeyToPkcs8RoundTrip() {
|
||||
Rsa key = makeKeyWithRetry(2048, 65537, rng);
|
||||
|
||||
byte[] pkcs8 = key.privateKeyEncodePKCS8();
|
||||
assertNotNull(pkcs8);
|
||||
assertTrue(pkcs8.length > 0);
|
||||
key.releaseNativeStruct();
|
||||
|
||||
/* PKCS8 output must decode back into a usable private key */
|
||||
Rsa decoded = new Rsa();
|
||||
decoded.decodePrivateKeyPKCS8(pkcs8);
|
||||
decoded.releaseNativeStruct();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void publicKeyDecodeAndEncodeWithByteBuffer() {
|
||||
Rsa key = new Rsa();
|
||||
|
|
|
|||
|
|
@ -36,6 +36,7 @@ import com.wolfssl.wolfcrypt.FeatureDetect;
|
|||
import com.wolfssl.wolfcrypt.SlhDsa;
|
||||
import com.wolfssl.wolfcrypt.Rng;
|
||||
import com.wolfssl.wolfcrypt.Sha256;
|
||||
import com.wolfssl.wolfcrypt.Sha384;
|
||||
import com.wolfssl.wolfcrypt.Sha512;
|
||||
import com.wolfssl.wolfcrypt.WolfCrypt;
|
||||
import com.wolfssl.wolfcrypt.WolfCryptError;
|
||||
|
|
@ -766,20 +767,17 @@ public class SlhDsaTest {
|
|||
|
||||
byte[] msg = "pre-hash pairing check".getBytes();
|
||||
|
||||
/* Independently validate the FIPS 205 Section 10.2.2 pre-hash pairing
|
||||
* for the SHA2 sets. signPreHash() chooses the hash in native C. Here
|
||||
* we reconstruct the expected digest and hashType in Java and confirm
|
||||
* the signature verifies through the explicit-digest verifyHash()
|
||||
* path, then that the other SHA-2 hash does NOT verify. Sign and verify
|
||||
* do not share the digest helper, so a wrong-but-consistent pairing is
|
||||
* caught (128-bit sets use SHA-256, 192/256-bit sets use SHA-512). The
|
||||
* SHAKE sets cannot be cross-checked here (no Java SHAKE digest). */
|
||||
/* Confirm the pre-hash signPreHash() picks natively (SHA-256 for
|
||||
* 128-bit sets, SHA-512 for 192/256-bit) by verifying with the
|
||||
* expected digest, then with a mismatched one. The mismatch must be
|
||||
* at least as strong as the set, weaker hashes are rejected with
|
||||
* BAD_FUNC_ARG. SHAKE sets are not checked (no Java SHAKE digest). */
|
||||
checkSha2Pairing(SlhDsa.SLH_DSA_SHA2_128F, msg,
|
||||
sha256(msg), WolfCrypt.WC_HASH_TYPE_SHA256,
|
||||
sha512(msg), WolfCrypt.WC_HASH_TYPE_SHA512);
|
||||
checkSha2Pairing(SlhDsa.SLH_DSA_SHA2_192F, msg,
|
||||
sha512(msg), WolfCrypt.WC_HASH_TYPE_SHA512,
|
||||
sha256(msg), WolfCrypt.WC_HASH_TYPE_SHA256);
|
||||
sha384(msg), WolfCrypt.WC_HASH_TYPE_SHA384);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
@ -888,6 +886,12 @@ public class SlhDsaTest {
|
|||
return sha.digest();
|
||||
}
|
||||
|
||||
private static byte[] sha384(byte[] in) {
|
||||
Sha384 sha = new Sha384();
|
||||
sha.update(in);
|
||||
return sha.digest();
|
||||
}
|
||||
|
||||
private static byte[] sha512(byte[] in) {
|
||||
Sha512 sha = new Sha512();
|
||||
sha.update(in);
|
||||
|
|
|
|||
Loading…
Reference in New Issue