Skip to content

Commit c62e5d0

Browse files
committed
Move CRT fault countermeasure into RSACoreEngine
1 parent 770259d commit c62e5d0

File tree

2 files changed

+44
-45
lines changed

2 files changed

+44
-45
lines changed

core/src/main/java/org/bouncycastle/crypto/engines/RSABlindedEngine.java

Lines changed: 14 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -110,39 +110,31 @@ public byte[] processBlock(
110110
}
111111

112112
BigInteger input = core.convertInput(in, inOff, inLen);
113+
BigInteger result = processInput(input);
114+
return core.convertOutput(result);
115+
}
113116

114-
BigInteger result;
117+
private BigInteger processInput(BigInteger input)
118+
{
115119
if (key instanceof RSAPrivateCrtKeyParameters)
116120
{
117-
RSAPrivateCrtKeyParameters k = (RSAPrivateCrtKeyParameters)key;
121+
RSAPrivateCrtKeyParameters crtKey = (RSAPrivateCrtKeyParameters)key;
118122

119-
BigInteger e = k.getPublicExponent();
123+
BigInteger e = crtKey.getPublicExponent();
120124
if (e != null) // can't do blinding without a public exponent
121125
{
122-
BigInteger m = k.getModulus();
126+
BigInteger m = crtKey.getModulus();
127+
123128
BigInteger r = BigIntegers.createRandomInRange(ONE, m.subtract(ONE), random);
129+
BigInteger blind = r.modPow(e, m);
130+
BigInteger unblind = BigIntegers.modOddInverse(m, r);
124131

125-
BigInteger blindedInput = r.modPow(e, m).multiply(input).mod(m);
132+
BigInteger blindedInput = blind.multiply(input).mod(m);
126133
BigInteger blindedResult = core.processBlock(blindedInput);
127-
128-
BigInteger rInv = BigIntegers.modOddInverse(m, r);
129-
result = blindedResult.multiply(rInv).mod(m);
130-
// defence against Arjen Lenstra’s CRT attack
131-
if (!input.equals(result.modPow(e, m)))
132-
{
133-
throw new IllegalStateException("RSA engine faulty decryption/signing detected");
134-
}
135-
}
136-
else
137-
{
138-
result = core.processBlock(input);
134+
return unblind.multiply(blindedResult).mod(m);
139135
}
140136
}
141-
else
142-
{
143-
result = core.processBlock(input);
144-
}
145137

146-
return core.convertOutput(result);
138+
return core.processBlock(input);
147139
}
148140
}

core/src/main/java/org/bouncycastle/crypto/engines/RSACoreEngine.java

Lines changed: 30 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -185,36 +185,43 @@ public BigInteger processBlock(BigInteger input)
185185
//
186186
RSAPrivateCrtKeyParameters crtKey = (RSAPrivateCrtKeyParameters)key;
187187

188-
BigInteger p = crtKey.getP();
189-
BigInteger q = crtKey.getQ();
190-
BigInteger dP = crtKey.getDP();
191-
BigInteger dQ = crtKey.getDQ();
192-
BigInteger qInv = crtKey.getQInv();
188+
BigInteger e = crtKey.getPublicExponent();
189+
if (e != null) // can't apply fault-attack countermeasure without public exponent
190+
{
191+
BigInteger p = crtKey.getP();
192+
BigInteger q = crtKey.getQ();
193+
BigInteger dP = crtKey.getDP();
194+
BigInteger dQ = crtKey.getDQ();
195+
BigInteger qInv = crtKey.getQInv();
193196

194-
BigInteger mP, mQ, h, m;
197+
BigInteger mP, mQ, h, m;
195198

196-
// mP = ((input mod p) ^ dP)) mod p
197-
mP = (input.remainder(p)).modPow(dP, p);
199+
// mP = ((input mod p) ^ dP)) mod p
200+
mP = (input.remainder(p)).modPow(dP, p);
198201

199-
// mQ = ((input mod q) ^ dQ)) mod q
200-
mQ = (input.remainder(q)).modPow(dQ, q);
202+
// mQ = ((input mod q) ^ dQ)) mod q
203+
mQ = (input.remainder(q)).modPow(dQ, q);
201204

202-
// h = qInv * (mP - mQ) mod p
203-
h = mP.subtract(mQ);
204-
h = h.multiply(qInv);
205-
h = h.mod(p); // mod (in Java) returns the positive residual
205+
// h = qInv * (mP - mQ) mod p
206+
h = mP.subtract(mQ);
207+
h = h.multiply(qInv);
208+
h = h.mod(p); // mod (in Java) returns the positive residual
206209

207-
// m = h * q + mQ
208-
m = h.multiply(q);
209-
m = m.add(mQ);
210+
// m = h * q + mQ
211+
m = h.multiply(q).add(mQ);
210212

211-
return m;
212-
}
213-
else
214-
{
215-
return input.modPow(
216-
key.getExponent(), key.getModulus());
213+
// defence against Arjen Lenstra’s CRT attack
214+
BigInteger check = m.modPow(e, crtKey.getModulus());
215+
if (!check.equals(input))
216+
{
217+
throw new IllegalStateException("RSA engine faulty decryption/signing detected");
218+
}
219+
220+
return m;
221+
}
217222
}
223+
224+
return input.modPow(key.getExponent(), key.getModulus());
218225
}
219226

220227
private CryptoServicePurpose getPurpose(boolean isPrivate, boolean forEncryption)

0 commit comments

Comments
 (0)