5
5
using Org . BouncyCastle . Crypto . Engines ;
6
6
using Org . BouncyCastle . Crypto . Parameters ;
7
7
using Org . BouncyCastle . Crypto . Utilities ;
8
+ using Org . BouncyCastle . Utilities ;
8
9
9
10
namespace Org . BouncyCastle . Crypto . Generators
10
11
{
@@ -64,12 +65,23 @@ private static byte[] MFcrypt(byte[] P, byte[] S, int N, int r, int p, int dkLen
64
65
65
66
Pack . LE_To_UInt32 ( bytes , 0 , B ) ;
66
67
68
+ /*
69
+ * Chunk memory allocations; We choose 'd' so that there will be 2**d chunks, each not
70
+ * larger than 32KiB, except that the minimum chunk size is 2 * r * 32.
71
+ */
72
+ int d = 0 , total = N * r ;
73
+ while ( ( N - d ) > 2 && total > ( 1 << 10 ) )
74
+ {
75
+ ++ d ;
76
+ total >>= 1 ;
77
+ }
78
+
67
79
int MFLenWords = MFLenBytes >> 2 ;
68
80
for ( int BOff = 0 ; BOff < BLen ; BOff += MFLenWords )
69
81
{
70
82
// TODO These can be done in parallel threads
71
- SMix ( B , BOff , N , r ) ;
72
- }
83
+ SMix ( B , BOff , N , d , r ) ;
84
+ }
73
85
74
86
Pack . UInt32_To_LE ( B , bytes , 0 ) ;
75
87
@@ -89,37 +101,49 @@ private static byte[] SingleIterationPBKDF2(byte[] P, byte[] S, int dkLen)
89
101
return key . GetKey ( ) ;
90
102
}
91
103
92
- private static void SMix ( uint [ ] B , int BOff , int N , int r )
104
+ private static void SMix ( uint [ ] B , int BOff , int N , int d , int r )
93
105
{
106
+ int powN = Integers . NumberOfTrailingZeros ( N ) ;
107
+ int blocksPerChunk = N >> d ;
108
+ int chunkCount = 1 << d , chunkMask = blocksPerChunk - 1 , chunkPow = powN - d ;
109
+
94
110
int BCount = r * 32 ;
95
111
96
112
uint [ ] blockX1 = new uint [ 16 ] ;
97
113
uint [ ] blockX2 = new uint [ 16 ] ;
98
114
uint [ ] blockY = new uint [ BCount ] ;
99
115
100
116
uint [ ] X = new uint [ BCount ] ;
101
- uint [ ] V = new uint [ N * BCount ] ;
117
+ uint [ ] [ ] VV = new uint [ chunkCount ] [ ] ;
102
118
103
119
try
104
120
{
105
121
Array . Copy ( B , BOff , X , 0 , BCount ) ;
106
122
107
- int off = 0 ;
108
- for ( int i = 0 ; i < N ; i += 2 )
123
+ for ( int c = 0 ; c < chunkCount ; ++ c )
109
124
{
110
- Array . Copy ( X , 0 , V , off , BCount ) ;
111
- off += BCount ;
112
- BlockMix ( X , blockX1 , blockX2 , blockY , r ) ;
113
- Array . Copy ( blockY , 0 , V , off , BCount ) ;
114
- off += BCount ;
115
- BlockMix ( blockY , blockX1 , blockX2 , X , r ) ;
125
+ uint [ ] V = new uint [ blocksPerChunk * BCount ] ;
126
+ VV [ c ] = V ;
127
+
128
+ int off = 0 ;
129
+ for ( int i = 0 ; i < blocksPerChunk ; i += 2 )
130
+ {
131
+ Array . Copy ( X , 0 , V , off , BCount ) ;
132
+ off += BCount ;
133
+ BlockMix ( X , blockX1 , blockX2 , blockY , r ) ;
134
+ Array . Copy ( blockY , 0 , V , off , BCount ) ;
135
+ off += BCount ;
136
+ BlockMix ( blockY , blockX1 , blockX2 , X , r ) ;
137
+ }
116
138
}
117
139
118
- uint mask = ( uint ) N - 1 ;
119
- for ( int i = 0 ; i < N ; ++ i )
120
- {
121
- int j = ( int ) ( X [ BCount - 16 ] & mask ) ;
122
- Array . Copy ( V , j * BCount , blockY , 0 , BCount ) ;
140
+ uint mask = ( uint ) N - 1 ;
141
+ for ( int i = 0 ; i < N ; ++ i )
142
+ {
143
+ int j = ( int ) ( X [ BCount - 16 ] & mask ) ;
144
+ uint [ ] V = VV [ j >> chunkPow ] ;
145
+ int VOff = ( j & chunkMask ) * BCount ;
146
+ Array . Copy ( V , VOff , blockY , 0 , BCount ) ;
123
147
Xor ( blockY , X , 0 , blockY ) ;
124
148
BlockMix ( blockY , blockX1 , blockX2 , X , r ) ;
125
149
}
@@ -128,7 +152,7 @@ private static void SMix(uint[] B, int BOff, int N, int r)
128
152
}
129
153
finally
130
154
{
131
- Clear ( V ) ;
155
+ ClearAll ( VV ) ;
132
156
ClearAll ( X , blockX1 , blockX2 , blockY ) ;
133
157
}
134
158
}
0 commit comments