Skip to content

Commit 6ee6da6

Browse files
committed
JNI/JCE: add AES and DESede SecretKeyFactory and SecretKey support to wolfJCE
1 parent 87c7bfb commit 6ee6da6

File tree

7 files changed

+1178
-6
lines changed

7 files changed

+1178
-6
lines changed

scripts/infer.sh

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,7 @@ infer --fail-on-issue run -- javac \
100100
src/main/java/com/wolfssl/provider/jce/WolfCryptProvider.java \
101101
src/main/java/com/wolfssl/provider/jce/WolfCryptPssParameters.java \
102102
src/main/java/com/wolfssl/provider/jce/WolfCryptRandom.java \
103+
src/main/java/com/wolfssl/provider/jce/WolfCryptSecretKey.java \
103104
src/main/java/com/wolfssl/provider/jce/WolfCryptSecretKeyFactory.java \
104105
src/main/java/com/wolfssl/provider/jce/WolfCryptSignature.java \
105106
src/main/java/com/wolfssl/provider/jce/WolfCryptUtil.java \

src/main/java/com/wolfssl/provider/jce/WolfCryptProvider.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -484,6 +484,14 @@ private void registerServices() {
484484
"com.wolfssl.provider.jce.WolfCryptSecretKeyFactory$wcPBKDF2WithHmacSHA3_512");
485485
}
486486
}
487+
if (FeatureDetect.AesEnabled()) {
488+
put("SecretKeyFactory.AES",
489+
"com.wolfssl.provider.jce.WolfCryptSecretKeyFactory$wcAES");
490+
}
491+
if (FeatureDetect.Des3Enabled() && !Fips.enabled) {
492+
put("SecretKeyFactory.DESede",
493+
"com.wolfssl.provider.jce.WolfCryptSecretKeyFactory$wcDESede");
494+
}
487495

488496
/* KeyFactory */
489497
if (FeatureDetect.EccEnabled()) {
Lines changed: 234 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,234 @@
1+
/* WolfCryptSecretKey.java
2+
*
3+
* Copyright (C) 2006-2025 wolfSSL Inc.
4+
*
5+
* This file is part of wolfSSL.
6+
*
7+
* wolfSSL is free software; you can redistribute it and/or modify
8+
* it under the terms of the GNU General Public License as published by
9+
* the Free Software Foundation; either version 2 of the License, or
10+
* (at your option) any later version.
11+
*
12+
* wolfSSL is distributed in the hope that it will be useful,
13+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
14+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15+
* GNU General Public License for more details.
16+
*
17+
* You should have received a copy of the GNU General Public License
18+
* along with this program; if not, write to the Free Software
19+
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
20+
*/
21+
22+
package com.wolfssl.provider.jce;
23+
24+
import java.util.Arrays;
25+
import java.security.InvalidKeyException;
26+
import javax.crypto.SecretKey;
27+
28+
import com.wolfssl.wolfcrypt.Aes;
29+
import com.wolfssl.wolfcrypt.Des3;
30+
31+
/**
32+
* wolfCrypt SecretKey implementation for symmetric algorithms.
33+
*
34+
* Supports AES and 3DES/DESede algorithms with key size validation.
35+
*/
36+
public class WolfCryptSecretKey implements SecretKey {
37+
38+
private static final long serialVersionUID = 1L;
39+
40+
/** Encoded key byte array */
41+
private byte[] encoded = null;
42+
43+
/** Key algorithm name */
44+
private String algorithm = null;
45+
46+
/** Has object been destroyed or not */
47+
private boolean destroyed = false;
48+
49+
/* Lock around destroyed */
50+
private transient final Object destroyedLock = new Object();
51+
52+
/**
53+
* Create new WolfCryptSecretKey object.
54+
*
55+
* @param algorithm key algorithm name ("AES", "DESede")
56+
* @param encoded encoded key byte array
57+
*
58+
* @throws InvalidKeyException if algorithm is null/empty,
59+
* encoded is null/zero length, or key size is invalid
60+
*/
61+
public WolfCryptSecretKey(String algorithm, byte[] encoded)
62+
throws InvalidKeyException {
63+
64+
if (algorithm == null || algorithm.isEmpty()) {
65+
throw new InvalidKeyException(
66+
"Algorithm String cannot be null or empty");
67+
}
68+
69+
if (encoded == null || encoded.length == 0) {
70+
throw new InvalidKeyException(
71+
"Encoded key cannot be null or zero length");
72+
}
73+
74+
/* Validate key size based on algorithm. Sanitize maching wolfCrypt
75+
* aes.c and des3.c input sizes. */
76+
if (algorithm.equalsIgnoreCase("AES")) {
77+
if (encoded.length != Aes.KEY_SIZE_128 &&
78+
encoded.length != Aes.KEY_SIZE_192 &&
79+
encoded.length != Aes.KEY_SIZE_256) {
80+
throw new InvalidKeyException(
81+
"AES key must be 16, 24, or 32 bytes, got: " +
82+
encoded.length);
83+
}
84+
}
85+
else if (algorithm.equalsIgnoreCase("DESede") ||
86+
algorithm.equalsIgnoreCase("TripleDES")) {
87+
if (encoded.length != Des3.KEY_SIZE) {
88+
throw new InvalidKeyException(
89+
"DESede key must be 24 bytes, got: " + encoded.length);
90+
}
91+
}
92+
else {
93+
throw new InvalidKeyException(
94+
"Unsupported algorithm: " + algorithm);
95+
}
96+
97+
this.algorithm = algorithm;
98+
this.encoded = encoded.clone();
99+
}
100+
101+
/**
102+
* Check if this object has been destroyed with destroy().
103+
*
104+
* @throws IllegalStateException if object has been destroyed
105+
*/
106+
private synchronized void checkDestroyed()
107+
throws IllegalStateException {
108+
109+
synchronized (destroyedLock) {
110+
if (this.destroyed == true) {
111+
throw new IllegalStateException(
112+
"SecretKey has been destroyed");
113+
}
114+
}
115+
}
116+
117+
/**
118+
* Return algorithm String representing this SecretKey.
119+
*
120+
* @return algorithm string matching this object
121+
*
122+
* @throws IllegalStateException if object has been destroyed
123+
*/
124+
@Override
125+
public synchronized String getAlgorithm() {
126+
127+
checkDestroyed();
128+
129+
return this.algorithm;
130+
}
131+
132+
/**
133+
* Return encoding format for this SecretKey.
134+
*
135+
* @return encoding format string, will be "RAW" for this object
136+
*
137+
* @throws IllegalStateException if object has been destroyed
138+
*/
139+
@Override
140+
public synchronized String getFormat() {
141+
142+
checkDestroyed();
143+
144+
return "RAW";
145+
}
146+
147+
/**
148+
* Return encoded byte array of this SecretKey.
149+
*
150+
* @return encoded byte array
151+
*
152+
* @throws IllegalStateException if object has been destroyed
153+
*/
154+
@Override
155+
public synchronized byte[] getEncoded() {
156+
157+
checkDestroyed();
158+
159+
return this.encoded.clone();
160+
}
161+
162+
/**
163+
* Destroy this object.
164+
*
165+
* Zeroize key bytes contained in this object and mark it as unusable.
166+
*/
167+
public synchronized void destroy() {
168+
synchronized (destroyedLock) {
169+
if (this.encoded != null) {
170+
Arrays.fill(this.encoded, (byte)0);
171+
this.encoded = null;
172+
}
173+
this.algorithm = null;
174+
this.destroyed = true;
175+
}
176+
}
177+
178+
/**
179+
* Return if this object has been destroyed.
180+
*
181+
* Object can be destroyed by calling destroy(), which will zeroize
182+
* internal buffers for this object.
183+
*
184+
* @return true if object has been destroyed, otherwise false
185+
*/
186+
public synchronized boolean isDestroyed() {
187+
synchronized (destroyedLock) {
188+
if (this.destroyed) {
189+
return true;
190+
}
191+
return false;
192+
}
193+
}
194+
195+
@Override
196+
public synchronized int hashCode() {
197+
checkDestroyed();
198+
return Arrays.hashCode(encoded);
199+
}
200+
201+
@Override
202+
public synchronized boolean equals(Object obj) {
203+
204+
SecretKey sKey = null;
205+
206+
synchronized (destroyedLock) {
207+
checkDestroyed();
208+
209+
if (obj == this) {
210+
return true;
211+
}
212+
213+
if (!(obj instanceof SecretKey)) {
214+
return false;
215+
}
216+
sKey = (SecretKey)obj;
217+
218+
if (!Arrays.equals(sKey.getEncoded(), getEncoded())) {
219+
return false;
220+
}
221+
222+
if (!sKey.getAlgorithm().equals(getAlgorithm())) {
223+
return false;
224+
}
225+
226+
if (!sKey.getFormat().equals(getFormat())) {
227+
return false;
228+
}
229+
230+
return true;
231+
}
232+
}
233+
}
234+

0 commit comments

Comments
 (0)