Skip to content

Commit f2776fe

Browse files
committed
Initial:
Fenced access to native references. Updated DisposalDaemon Updated README Speculative fix on DefaultBufferedBlockCipher
1 parent 9611a29 commit f2776fe

33 files changed

Lines changed: 5612 additions & 818 deletions

README.md

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -228,10 +228,30 @@ a segfault.
228228

229229
### Properties
230230

231-
| Property | Values | Description |
232-
|----------------------------------------|-----------------------------|------------------------------------------------------------------------------|
233-
| org.bouncycastle.native.cpu_variant | avx, vaes, vaesf or neon-le | Specify a variant to use see "Selecting a specific variant" for warnings. |
234-
| org.bouncycastle.packet_cipher_enabled | true or false | False by default, enable or disable use of packet ciphers where appropriate. |
231+
| Property | Values | Description |
232+
|-----------------------------------------|-----------------------------|------------------------------------------------------------------------------------------------------|
233+
| org.bouncycastle.native.cpu_variant | avx, vaes, vaesf or neon-le | Specify a variant to use see "Selecting a specific variant" for warnings. |
234+
| org.bouncycastle.packet_cipher_enabled | true or false | False by default, enable or disable use of packet ciphers where appropriate. |
235+
| org.bouncycastle.native.cleanup_delay | 1000ms / 1 | Delays freeing of native allocations by the given time in milliseconds or seconds, the default is 0. |
236+
237+
238+
### Disposal Daemon / Freeing native allocations
239+
The library tacks classes and when they become available for garbage collection, and we free any underlying native allocations.
240+
241+
Overly aggressive garbage collectors may signal that a class is available for collection while another thread is accessing
242+
that class. On busy multicore machines this may occur during the last call to that class causing use after free situation.
243+
244+
To deal with this we have employed either the reachability fence, applicable on java 9 and above or synchronized blocks for
245+
java 8.
246+
247+
If this proves to be unreliable users can also set a cleanup delay via the ```org.bouncycastle.native.cleanup_delay``` property.
248+
For example:
249+
250+
```-Dorg.bouncycastle.native.cleanup_delay=10ms``` would set a delay of 10 milliseconds, and
251+
```-Dorg.bouncycastle.native.cleanup_delay=1``` would set a delay of 1 second.
252+
253+
The default cleanup delay is zero and native allocations will be cleaned up immediately upon notification that the relevant
254+
class is available to GC.
235255

236256

237257
# Things to watch out for

core/build.gradle

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,22 @@ plugins {
66

77
jar.archiveBaseName = "bccore-lts$vm_range"
88

9+
10+
sourceSets {
11+
java9 {
12+
java {
13+
srcDirs = ['src/main/java9']
14+
}
15+
}
16+
}
17+
18+
919
dependencies {
1020
testImplementation 'com.fasterxml.jackson.core:jackson-databind:2.13.3'
21+
22+
java9Implementation files([sourceSets.main.output.classesDirs]) {
23+
builtBy compileJava
24+
}
1125
}
1226

1327
test {
@@ -68,6 +82,15 @@ artifacts {
6882
}
6983

7084

85+
compileJava9Java {
86+
javaCompiler = javaToolchains.compilerFor {
87+
languageVersion = JavaLanguageVersion.of(11)
88+
}
89+
options.release = 9
90+
options.sourcepath = files(['src/main/java', 'src/main/java9'])
91+
}
92+
93+
7194
task cleanNative(type: Delete) {
7295
delete("$projectDir/src/main/resources/native/");
7396
delete("$projectDir/src/main/resources/META-INF/DRIVERS");

core/src/main/java/org/bouncycastle/crypto/DefaultBufferedBlockCipher.java

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -243,12 +243,12 @@ public int processBytes(
243243
len -= gapLen;
244244
}
245245

246-
if (in == out && Arrays.segmentsOverlap(inOff, len, outOff, length))
247-
{
248-
in = new byte[len];
249-
System.arraycopy(out, inOff, in, 0, len);
250-
inOff = 0;
251-
}
246+
// if (in == out && Arrays.segmentsOverlap(inOff, len, outOff, length))
247+
// {
248+
// in = new byte[len];
249+
// System.arraycopy(out, inOff, in, 0, len);
250+
// inOff = 0;
251+
// }
252252

253253
// if bufOff non-zero buffer must now be full
254254
if (bufOff != 0)

core/src/main/java/org/bouncycastle/crypto/digests/SHA224NativeDigest.java

Lines changed: 46 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -47,8 +47,11 @@ class SHA224NativeDigest
4747

4848
SHA224NativeDigest restoreState(byte[] state, int offset)
4949
{
50-
restoreFullState(nativeRef.getReference(), state, offset);
51-
return this;
50+
synchronized (this)
51+
{
52+
restoreFullState(nativeRef.getReference(), state, offset);
53+
return this;
54+
}
5255
}
5356

5457
//
@@ -64,43 +67,60 @@ public String getAlgorithmName()
6467
@Override
6568
public int getDigestSize()
6669
{
67-
return getDigestSize(nativeRef.getReference());
70+
synchronized (this)
71+
{
72+
return getDigestSize(nativeRef.getReference());
73+
}
6874
}
6975

7076

7177
@Override
7278
public void update(byte in)
7379
{
74-
75-
update(nativeRef.getReference(), in);
80+
synchronized (this)
81+
{
82+
update(nativeRef.getReference(), in);
83+
}
7684
}
7785

7886

7987
@Override
8088
public void update(byte[] input, int inOff, int len)
8189
{
82-
update(nativeRef.getReference(), input, inOff, len);
90+
synchronized (this)
91+
{
92+
update(nativeRef.getReference(), input, inOff, len);
93+
}
8394
}
8495

8596

8697
@Override
8798
public int doFinal(byte[] output, int outOff)
8899
{
89-
return doFinal(nativeRef.getReference(), output, outOff);
100+
synchronized (this)
101+
{
102+
return doFinal(nativeRef.getReference(), output, outOff);
103+
}
90104
}
91105

92106

93107
@Override
94108
public void reset()
95109
{
96-
reset(nativeRef.getReference());
110+
synchronized (this)
111+
{
112+
reset(nativeRef.getReference());
113+
}
97114
}
98115

99116

100117
@Override
101118
public int getByteLength()
102119
{
103-
return getByteLength(nativeRef.getReference());
120+
synchronized (this)
121+
{
122+
return getByteLength(nativeRef.getReference());
123+
}
104124
}
105125

106126

@@ -113,23 +133,32 @@ public Memoable copy()
113133
@Override
114134
public void reset(Memoable other)
115135
{
116-
SHA224NativeDigest dig = (SHA224NativeDigest) other;
117-
restoreFullState(nativeRef.getReference(), dig.getEncodedState(), 0);
136+
synchronized (this)
137+
{
138+
SHA224NativeDigest dig = (SHA224NativeDigest) other;
139+
restoreFullState(nativeRef.getReference(), dig.getEncodedState(), 0);
140+
}
118141
}
119142

120143

121144
public byte[] getEncodedState()
122145
{
123-
int l = encodeFullState(nativeRef.getReference(), null, 0);
124-
byte[] state = new byte[l];
125-
encodeFullState(nativeRef.getReference(), state, 0);
126-
return state;
146+
synchronized (this)
147+
{
148+
int l = encodeFullState(nativeRef.getReference(), null, 0);
149+
byte[] state = new byte[l];
150+
encodeFullState(nativeRef.getReference(), state, 0);
151+
return state;
152+
}
127153
}
128154

129155

130156
void restoreFullState(byte[] encoded, int offset)
131157
{
132-
restoreFullState(nativeRef.getReference(), encoded, offset);
158+
synchronized (this)
159+
{
160+
restoreFullState(nativeRef.getReference(), encoded, offset);
161+
}
133162
}
134163

135164

@@ -187,7 +216,7 @@ private static class DigestRefWrapper
187216

188217
public DigestRefWrapper(long reference)
189218
{
190-
super(reference,"SHA224");
219+
super(reference, "SHA224");
191220
}
192221

193222
@Override

core/src/main/java/org/bouncycastle/crypto/digests/SHA256NativeDigest.java

Lines changed: 51 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ class SHA256NativeDigest
1616
{
1717
private final CryptoServicePurpose purpose;
1818

19-
protected DigestRefWrapper nativeRef = null;
19+
private DigestRefWrapper nativeRef = null;
2020

2121
SHA256NativeDigest(CryptoServicePurpose purpose)
2222
{
@@ -47,8 +47,11 @@ class SHA256NativeDigest
4747

4848
SHA256NativeDigest restoreState(byte[] state, int offset)
4949
{
50-
restoreFullState(nativeRef.getReference(), state, offset);
51-
return this;
50+
synchronized (this)
51+
{
52+
restoreFullState(nativeRef.getReference(), state, offset);
53+
return this;
54+
}
5255
}
5356

5457
//
@@ -64,78 +67,104 @@ public String getAlgorithmName()
6467
@Override
6568
public int getDigestSize()
6669
{
67-
return getDigestSize(nativeRef.getReference());
70+
synchronized (this)
71+
{
72+
return getDigestSize(nativeRef.getReference());
73+
}
6874
}
6975

7076

7177
@Override
7278
public void update(byte in)
7379
{
74-
75-
update(nativeRef.getReference(), in);
80+
synchronized (this)
81+
{
82+
update(nativeRef.getReference(), in);
83+
}
7684
}
7785

7886

7987
@Override
8088
public void update(byte[] input, int inOff, int len)
8189
{
82-
update(nativeRef.getReference(), input, inOff, len);
90+
synchronized (this)
91+
{
92+
update(nativeRef.getReference(), input, inOff, len);
93+
}
8394
}
8495

8596

8697
@Override
8798
public int doFinal(byte[] output, int outOff)
8899
{
89-
return doFinal(nativeRef.getReference(), output, outOff);
100+
synchronized (this)
101+
{
102+
return doFinal(nativeRef.getReference(), output, outOff);
103+
}
90104
}
91105

92106

93107
@Override
94108
public void reset()
95109
{
96-
reset(nativeRef.getReference());
110+
synchronized (this)
111+
{
112+
reset(nativeRef.getReference());
113+
}
97114
}
98115

99116

100117
@Override
101118
public int getByteLength()
102119
{
103-
return getByteLength(nativeRef.getReference());
120+
synchronized (this)
121+
{
122+
return getByteLength(nativeRef.getReference());
123+
}
104124
}
105125

106126

107127
@Override
108128
public Memoable copy()
109129
{
110-
return new SHA256NativeDigest(this);
130+
synchronized (this)
131+
{
132+
return new SHA256NativeDigest(this);
133+
}
111134
}
112135

113136
@Override
114137
public void reset(Memoable other)
115138
{
116-
SHA256NativeDigest dig = (SHA256NativeDigest) other;
117-
restoreFullState(nativeRef.getReference(), dig.getEncodedState(), 0);
139+
synchronized (this)
140+
{
141+
SHA256NativeDigest dig = (SHA256NativeDigest) other;
142+
restoreFullState(nativeRef.getReference(), dig.getEncodedState(), 0);
143+
}
118144
}
119145

120146

121147
public byte[] getEncodedState()
122148
{
123-
int l = encodeFullState(nativeRef.getReference(), null, 0);
124-
byte[] state = new byte[l];
125-
encodeFullState(nativeRef.getReference(), state, 0);
126-
return state;
149+
synchronized (this)
150+
{
151+
int l = encodeFullState(nativeRef.getReference(), null, 0);
152+
byte[] state = new byte[l];
153+
encodeFullState(nativeRef.getReference(), state, 0);
154+
return state;
155+
}
127156
}
128157

129158

130-
131-
132159
void restoreFullState(byte[] encoded, int offset)
133160
{
134-
restoreFullState(nativeRef.getReference(), encoded, offset);
161+
synchronized (this)
162+
{
163+
restoreFullState(nativeRef.getReference(), encoded, offset);
164+
}
135165
}
136166

137167

138-
139168
@Override
140169
public String toString()
141170
{
@@ -190,7 +219,7 @@ private static class DigestRefWrapper
190219

191220
public DigestRefWrapper(long reference)
192221
{
193-
super(reference,"SHA256");
222+
super(reference, "SHA256");
194223
}
195224

196225
@Override

0 commit comments

Comments
 (0)