Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions scripts/infer.sh
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,7 @@ infer --fail-on-issue run -- javac \
src/main/java/com/wolfssl/provider/jce/WolfCryptMessageDigestSha512.java \
src/main/java/com/wolfssl/provider/jce/WolfCryptMessageDigestSha3.java \
src/main/java/com/wolfssl/provider/jce/WolfCryptMessageDigestShake.java \
src/main/java/com/wolfssl/provider/jce/WolfCryptOaepParameters.java \
src/main/java/com/wolfssl/provider/jce/WolfCryptPBEKey.java \
src/main/java/com/wolfssl/provider/jce/WolfCryptPKIXCertPathBuilder.java \
src/main/java/com/wolfssl/provider/jce/WolfCryptPKIXCertPathValidator.java \
Expand Down
15 changes: 15 additions & 0 deletions src/main/java/com/wolfssl/provider/jce/WolfCryptCipher.java
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,7 @@ private static final class DefaultIvRandom {
/* RSA-OAEP parameters */
private int oaepHashType = 0;
private int oaepMgf = 0;
private OAEPParameterSpec oaepSpec = null;

/* for debug logging */
private String algString;
Expand Down Expand Up @@ -374,6 +375,8 @@ private WolfCryptCipher(CipherType type, CipherMode mode, PaddingType pad,
private void initOaepParams() {
this.oaepHashType = WolfCrypt.WC_HASH_TYPE_SHA256;
this.oaepMgf = Rsa.WC_MGF1SHA1;
this.oaepSpec = new OAEPParameterSpec("SHA-256", "MGF1",
MGF1ParameterSpec.SHA1, PSource.PSpecified.DEFAULT);
}

/**
Expand All @@ -384,6 +387,8 @@ private void initOaepParams() {
private void initOaepParamsSha1() {
this.oaepHashType = WolfCrypt.WC_HASH_TYPE_SHA;
this.oaepMgf = Rsa.WC_MGF1SHA1;
this.oaepSpec = new OAEPParameterSpec("SHA-1", "MGF1",
MGF1ParameterSpec.SHA1, PSource.PSpecified.DEFAULT);
}

/**
Expand Down Expand Up @@ -509,6 +514,9 @@ private void setOaepParams(OAEPParameterSpec spec)
}
}

/* Store spec for AlgorithmParameters retrieval */
this.oaepSpec = spec;

/* Set OAEP hash type */
this.oaepHashType = hashNameToWolfCryptType(spec.getDigestAlgorithm());

Expand Down Expand Up @@ -1090,6 +1098,13 @@ else if (this.cipherType == CipherType.WC_DES3) {
break;
}

if (params == null && this.oaepSpec != null) {
params = AlgorithmParameters.getInstance("OAEP");
if (params != null) {
params.init(this.oaepSpec);
}
}

} catch (NoSuchAlgorithmException |
InvalidParameterSpecException e) {
/* Return null if parameter creation fails */
Expand Down
32 changes: 26 additions & 6 deletions src/main/java/com/wolfssl/provider/jce/WolfCryptECKeyFactory.java
Original file line number Diff line number Diff line change
Expand Up @@ -320,9 +320,19 @@ private PrivateKey generatePrivateFromECSpec(ECPrivateKeySpec keySpec)
"ECParameterSpec cannot be null");
}

/* Validate ECParameterSpec is supported by wolfCrypt,
* throws WolfCryptException if invalid */
WolfCryptECParameterSpec.validateParameters(keySpec.getParams());
/* Validate ECParameterSpec is supported by wolfCrypt.
* validateParameters throws IllegalArgumentException (unchecked)
* when the curve is not recognized; wrap it as
* InvalidKeySpecException so callers see a
* GeneralSecurityException. */
try {
WolfCryptECParameterSpec.validateParameters(
keySpec.getParams());
} catch (IllegalArgumentException e) {
throw new InvalidKeySpecException(
"Unsupported curve parameters: " +
e.getMessage(), e);
}

/* Get curve name from ECParameterSpec */
try {
Expand Down Expand Up @@ -577,9 +587,19 @@ private PublicKey generatePublicFromECSpec(ECPublicKeySpec keySpec)
"ECParameterSpec cannot be null");
}

/* Validate ECParameterSpec is supported by wolfCrypt,
* throws WolfCryptException if invalid */
WolfCryptECParameterSpec.validateParameters(keySpec.getParams());
/* Validate ECParameterSpec is supported by wolfCrypt.
* validateParameters throws IllegalArgumentException (unchecked)
* when the curve is not recognized; wrap it as
* InvalidKeySpecException so callers see a
* GeneralSecurityException. */
try {
WolfCryptECParameterSpec.validateParameters(
keySpec.getParams());
} catch (IllegalArgumentException e) {
throw new InvalidKeySpecException(
"Unsupported curve parameters: " +
e.getMessage(), e);
}

/* Get curve name from ECParameterSpec */
try {
Expand Down
71 changes: 68 additions & 3 deletions src/main/java/com/wolfssl/provider/jce/WolfCryptKeyAgreement.java
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,8 @@ enum EngineState {
private Ecc ecPrivate = null;

private int primeLen = 0;
private byte[] dhParamP = null;
private byte[] dhParamG = null;
private int curveSize = 0;
private String curveName = null;

Expand Down Expand Up @@ -128,12 +130,36 @@ protected Key engineDoPhase(Key key, boolean lastPhase)
"Key must be of type DHPublicKey");
}

pubKey = ((DHPublicKey)key).getY().toByteArray();
DHPublicKey dhPubKey = (DHPublicKey)key;

pubKey = dhPubKey.getY().toByteArray();
if (pubKey == null) {
throw new InvalidKeyException(
"Failed to get DH public key from Key object");
}

if (this.dhParamP == null || this.dhParamG == null) {
throw new InvalidKeyException(
"DH private key not initialized with parameters");
}

if (dhPubKey.getParams() == null) {
throw new InvalidKeyException(
"DH public key has no parameters");
}

BigInteger privP = new BigInteger(this.dhParamP);
BigInteger privG = new BigInteger(this.dhParamG);
BigInteger pubPBig = dhPubKey.getParams().getP();
BigInteger pubGBig = dhPubKey.getParams().getG();

if (!privP.equals(pubPBig) || !privG.equals(pubGBig)) {
throw new InvalidKeyException(
"DH public key parameters do not match " +
"private key parameters, cannot generate " +
"shared secret");
}

/* Validate peer public key (SP 800-56A) before use */
try {
this.dh.checkPublicKey(pubKey);
Expand Down Expand Up @@ -168,6 +194,25 @@ protected Key engineDoPhase(Key key, boolean lastPhase)
"ECC public key failed validation", e);
}

/* Verify the public key curve matches the private key curve.
* A curve mismatch (e.g. secp224r1 public against secp256r1
* private) is caught here so the caller sees
* InvalidKeyException
* rather than a WolfCryptException from makeSharedSecret. */
try {
int pubCurveId = this.ecPublic.getCurveId();
int privCurveId = this.ecPrivate.getCurveId();
if (pubCurveId != privCurveId) {
throw new InvalidKeyException(
"EC public key curve does not match private key " +
"curve (public curveId=" + pubCurveId +
", private curveId=" + privCurveId + ")");
}
} catch (WolfCryptException e) {
throw new InvalidKeyException(
"Failed to validate EC key curve compatibility", e);
}

break;
};

Expand Down Expand Up @@ -328,7 +373,13 @@ protected int engineGenerateSecret(byte[] sharedSecret, int offset)

case WC_ECDH:

tmp = this.ecPrivate.makeSharedSecret(this.ecPublic);
try {
tmp = this.ecPrivate.makeSharedSecret(this.ecPublic);
} catch (WolfCryptException e) {
throw new IllegalStateException(
"Native ECDH shared secret generation failed: " +
e.getMessage(), e);
}
if (tmp == null) {
throw new RuntimeException("Error when creating " +
"ECDH shared secret");
Expand Down Expand Up @@ -505,6 +556,9 @@ private void wcInitDHParams(Key key, AlgorithmParameterSpec params)

this.dh.setParams(paramP, paramG);

this.dhParamP = paramP;
this.dhParamG = paramG;

primeLen = paramP.length;

/* prime may have leading zero */
Expand Down Expand Up @@ -603,11 +657,22 @@ private void wcInitECDHParams(Key key, AlgorithmParameterSpec params)
"ECC curve is null, please check algorithm parameters");
}

/* Release and recreate native structs to support re-initialization.
* JCE requires KeyAgreement.init() to be callable multiple times. */
if (this.ecPrivate != null) {
this.ecPrivate.releaseNativeStruct();
}
this.ecPrivate = new Ecc();
if (this.ecPublic != null) {
this.ecPublic.releaseNativeStruct();
}
this.ecPublic = new Ecc();

privKeyBytes = ecKey.getS().toByteArray();

try {
this.ecPrivate.importPrivateOnCurve(privKeyBytes,
null, this.curveName);
null, this.curveName);
} finally {
zeroArray(privKeyBytes);
}
Expand Down
154 changes: 154 additions & 0 deletions src/main/java/com/wolfssl/provider/jce/WolfCryptOaepParameters.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
/* WolfCryptOaepParameters.java
*
* Copyright (C) 2006-2026 wolfSSL Inc.
*
* This file is part of wolfSSL.
*
* wolfSSL is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* wolfSSL is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
*/

package com.wolfssl.provider.jce;

import java.io.IOException;
import java.security.AlgorithmParametersSpi;
import java.security.spec.AlgorithmParameterSpec;
import java.security.spec.InvalidParameterSpecException;
import java.security.spec.MGF1ParameterSpec;
import javax.crypto.spec.OAEPParameterSpec;
import javax.crypto.spec.PSource;

/**
* wolfCrypt JCE AlgorithmParametersSpi implementation for RSA-OAEP parameters
*/
public class WolfCryptOaepParameters extends AlgorithmParametersSpi {

private OAEPParameterSpec oaepSpec;

public WolfCryptOaepParameters() {
this.oaepSpec = OAEPParameterSpec.DEFAULT;
}

@Override
protected void engineInit(AlgorithmParameterSpec paramSpec)
throws InvalidParameterSpecException {

if (!(paramSpec instanceof OAEPParameterSpec)) {
throw new InvalidParameterSpecException(
"Only OAEPParameterSpec supported");
}

OAEPParameterSpec spec = (OAEPParameterSpec) paramSpec;

if (!"MGF1".equals(spec.getMGFAlgorithm())) {
throw new InvalidParameterSpecException(
"Only MGF1 supported for OAEP, got: " +
spec.getMGFAlgorithm());
}

AlgorithmParameterSpec mgfParams = spec.getMGFParameters();
if (!(mgfParams instanceof MGF1ParameterSpec)) {
throw new InvalidParameterSpecException(
"MGF parameters must be MGF1ParameterSpec");
}

String mgfDigest = ((MGF1ParameterSpec) mgfParams).getDigestAlgorithm();
if (!isDigestSupported(mgfDigest)) {
throw new InvalidParameterSpecException(
"Unsupported MGF digest: " + mgfDigest);
}

PSource pSource = spec.getPSource();
if (pSource != null && pSource instanceof PSource.PSpecified) {
byte[] label = ((PSource.PSpecified) pSource).getValue();
if (label != null && label.length > 0) {
throw new InvalidParameterSpecException(
"OAEP label (PSource) must be empty");
}
}

this.oaepSpec = spec;
}

@Override
protected void engineInit(byte[] params) throws IOException {
throw new IOException("Encoded OAEP parameters not supported");
}

@Override
protected void engineInit(byte[] params, String format)
throws IOException {
throw new IOException("Encoded OAEP parameters not supported");
}

@Override
@SuppressWarnings("unchecked")
protected <T extends AlgorithmParameterSpec> T engineGetParameterSpec(
Class<T> paramSpec) throws InvalidParameterSpecException {

if (this.oaepSpec == null) {
throw new InvalidParameterSpecException(
"OAEP parameters not initialized");
}

if (paramSpec == null) {
throw new InvalidParameterSpecException(
"Parameter spec class cannot be null");
}

if (paramSpec == OAEPParameterSpec.class ||
paramSpec == AlgorithmParameterSpec.class) {
return (T) this.oaepSpec;
}

throw new InvalidParameterSpecException(
"Unsupported parameter spec: " + paramSpec.getName());
}

@Override
protected byte[] engineGetEncoded() throws IOException {
throw new IOException("Encoded OAEP parameters not supported");
}

@Override
protected byte[] engineGetEncoded(String format) throws IOException {
throw new IOException("Encoded OAEP parameters not supported");
}

@Override
protected String engineToString() {
if (this.oaepSpec == null) {
return "WolfCryptOaepParameters[uninitialized]";
}

return "WolfCryptOaepParameters[" +
"digest=" + this.oaepSpec.getDigestAlgorithm() +
", mgf=" + this.oaepSpec.getMGFAlgorithm() + "]";
}

private boolean isDigestSupported(String digestAlg) {
switch (digestAlg.toUpperCase()) {
case "SHA-1":
case "SHA-224":
case "SHA-256":
case "SHA-384":
case "SHA-512":
case "SHA-512/224":
case "SHA-512/256":
return true;
default:
return false;
}
}
}
6 changes: 6 additions & 0 deletions src/main/java/com/wolfssl/provider/jce/WolfCryptProvider.java
Original file line number Diff line number Diff line change
Expand Up @@ -859,6 +859,12 @@ private void registerServices() {
put("Alg.Alias.Cipher.RSA/ECB/OAEPWithSHA1AndMGF1Padding",
"RSA/ECB/OAEPWithSHA-1AndMGF1Padding");
}

/* OAEP AlgorithmParameters */
if (FeatureDetect.RsaOaepEnabled()) {
put("AlgorithmParameters.OAEP",
"com.wolfssl.provider.jce.WolfCryptOaepParameters");
}
}

/* KeyAgreement */
Expand Down
Loading
Loading