1 package org.bouncycastle.jcajce.provider.asymmetric.rsa; 2 3 import java.io.IOException; 4 import java.security.AlgorithmParameters; 5 import java.security.InvalidKeyException; 6 import java.security.PrivateKey; 7 import java.security.PublicKey; 8 import java.security.SignatureException; 9 import java.security.SignatureSpi; 10 import java.security.interfaces.RSAPrivateKey; 11 import java.security.interfaces.RSAPublicKey; 12 import java.security.spec.AlgorithmParameterSpec; 13 14 import org.bouncycastle.asn1.ASN1Encoding; 15 import org.bouncycastle.asn1.ASN1ObjectIdentifier; 16 import org.bouncycastle.asn1.DERNull; 17 import org.bouncycastle.asn1.nist.NISTObjectIdentifiers; 18 import org.bouncycastle.asn1.oiw.OIWObjectIdentifiers; 19 import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers; 20 // Android-removed: Unsupported algorithms 21 // import org.bouncycastle.asn1.teletrust.TeleTrusTObjectIdentifiers; 22 import org.bouncycastle.asn1.x509.AlgorithmIdentifier; 23 import org.bouncycastle.asn1.x509.DigestInfo; 24 import org.bouncycastle.crypto.AsymmetricBlockCipher; 25 import org.bouncycastle.crypto.CipherParameters; 26 import org.bouncycastle.crypto.Digest; 27 // Android-removed: Unsupported algorithms 28 // import org.bouncycastle.crypto.digests.MD2Digest; 29 // import org.bouncycastle.crypto.digests.MD4Digest; 30 // import org.bouncycastle.crypto.digests.NullDigest; 31 // import org.bouncycastle.crypto.digests.RIPEMD128Digest; 32 // import org.bouncycastle.crypto.digests.RIPEMD160Digest; 33 // import org.bouncycastle.crypto.digests.RIPEMD256Digest; 34 import org.bouncycastle.crypto.encodings.PKCS1Encoding; 35 import org.bouncycastle.crypto.engines.RSABlindedEngine; 36 // Android-changed: Use Android digests 37 // import org.bouncycastle.crypto.util.DigestFactory; 38 import org.bouncycastle.crypto.digests.AndroidDigestFactory; 39 import org.bouncycastle.util.Arrays; 40 41 public class DigestSignatureSpi 42 extends SignatureSpi 43 { 44 private Digest digest; 45 private AsymmetricBlockCipher cipher; 46 private AlgorithmIdentifier algId; 47 48 // care - this constructor is actually used by outside organisations 49 protected DigestSignatureSpi( 50 Digest digest, 51 AsymmetricBlockCipher cipher) 52 { 53 this.digest = digest; 54 this.cipher = cipher; 55 this.algId = null; 56 } 57 58 // care - this constructor is actually used by outside organisations 59 protected DigestSignatureSpi( 60 ASN1ObjectIdentifier objId, 61 Digest digest, 62 AsymmetricBlockCipher cipher) 63 { 64 this.digest = digest; 65 this.cipher = cipher; 66 this.algId = new AlgorithmIdentifier(objId, DERNull.INSTANCE); 67 } 68 69 protected void engineInitVerify( 70 PublicKey publicKey) 71 throws InvalidKeyException 72 { 73 if (!(publicKey instanceof RSAPublicKey)) 74 { 75 throw new InvalidKeyException("Supplied key (" + getType(publicKey) + ") is not a RSAPublicKey instance"); 76 } 77 78 CipherParameters param = RSAUtil.generatePublicKeyParameter((RSAPublicKey)publicKey); 79 80 digest.reset(); 81 cipher.init(false, param); 82 } 83 84 protected void engineInitSign( 85 PrivateKey privateKey) 86 throws InvalidKeyException 87 { 88 if (!(privateKey instanceof RSAPrivateKey)) 89 { 90 throw new InvalidKeyException("Supplied key (" + getType(privateKey) + ") is not a RSAPrivateKey instance"); 91 } 92 93 CipherParameters param = RSAUtil.generatePrivateKeyParameter((RSAPrivateKey)privateKey); 94 95 digest.reset(); 96 97 cipher.init(true, param); 98 } 99 100 private String getType( 101 Object o) 102 { 103 if (o == null) 104 { 105 return null; 106 } 107 108 return o.getClass().getName(); 109 } 110 111 protected void engineUpdate( 112 byte b) 113 throws SignatureException 114 { 115 digest.update(b); 116 } 117 118 protected void engineUpdate( 119 byte[] b, 120 int off, 121 int len) 122 throws SignatureException 123 { 124 digest.update(b, off, len); 125 } 126 127 protected byte[] engineSign() 128 throws SignatureException 129 { 130 byte[] hash = new byte[digest.getDigestSize()]; 131 132 digest.doFinal(hash, 0); 133 134 try 135 { 136 byte[] bytes = derEncode(hash); 137 138 return cipher.processBlock(bytes, 0, bytes.length); 139 } 140 catch (ArrayIndexOutOfBoundsException e) 141 { 142 throw new SignatureException("key too small for signature type"); 143 } 144 catch (Exception e) 145 { 146 throw new SignatureException(e.toString()); 147 } 148 } 149 150 protected boolean engineVerify( 151 byte[] sigBytes) 152 throws SignatureException 153 { 154 byte[] hash = new byte[digest.getDigestSize()]; 155 156 digest.doFinal(hash, 0); 157 158 byte[] sig; 159 byte[] expected; 160 161 try 162 { 163 sig = cipher.processBlock(sigBytes, 0, sigBytes.length); 164 165 expected = derEncode(hash); 166 } 167 catch (Exception e) 168 { 169 return false; 170 } 171 172 if (sig.length == expected.length) 173 { 174 return Arrays.constantTimeAreEqual(sig, expected); 175 } 176 else if (sig.length == expected.length - 2) // NULL left out 177 { 178 int sigOffset = sig.length - hash.length - 2; 179 int expectedOffset = expected.length - hash.length - 2; 180 181 expected[1] -= 2; // adjust lengths 182 expected[3] -= 2; 183 184 int nonEqual = 0; 185 186 for (int i = 0; i < hash.length; i++) 187 { 188 nonEqual |= (sig[sigOffset + i] ^ expected[expectedOffset + i]); 189 } 190 191 for (int i = 0; i < sigOffset; i++) 192 { 193 nonEqual |= (sig[i] ^ expected[i]); // check header less NULL 194 } 195 196 return nonEqual == 0; 197 } 198 else 199 { 200 Arrays.constantTimeAreEqual(expected, expected); // keep time "steady". 201 202 return false; 203 } 204 } 205 206 protected void engineSetParameter( 207 AlgorithmParameterSpec params) 208 { 209 throw new UnsupportedOperationException("engineSetParameter unsupported"); 210 } 211 212 /** 213 * @deprecated replaced with <a href = "#engineSetParameter(java.security.spec.AlgorithmParameterSpec)"> 214 */ 215 protected void engineSetParameter( 216 String param, 217 Object value) 218 { 219 throw new UnsupportedOperationException("engineSetParameter unsupported"); 220 } 221 222 /** 223 * @deprecated 224 */ 225 protected Object engineGetParameter( 226 String param) 227 { 228 return null; 229 } 230 231 protected AlgorithmParameters engineGetParameters() 232 { 233 return null; 234 } 235 236 private byte[] derEncode( 237 byte[] hash) 238 throws IOException 239 { 240 if (algId == null) 241 { 242 // For raw RSA, the DigestInfo must be prepared externally 243 return hash; 244 } 245 246 DigestInfo dInfo = new DigestInfo(algId, hash); 247 248 return dInfo.getEncoded(ASN1Encoding.DER); 249 } 250 251 static public class SHA1 252 extends DigestSignatureSpi 253 { 254 public SHA1() 255 { 256 // Android-changed: Use Android digests 257 // super(OIWObjectIdentifiers.idSHA1, DigestFactory.createSHA1(), new PKCS1Encoding(new RSABlindedEngine())); 258 super(OIWObjectIdentifiers.idSHA1, AndroidDigestFactory.getSHA1(), new PKCS1Encoding(new RSABlindedEngine())); 259 } 260 } 261 262 static public class SHA224 263 extends DigestSignatureSpi 264 { 265 public SHA224() 266 { 267 // Android-changed: Use Android digests 268 // super(NISTObjectIdentifiers.id_sha224, DigestFactory.createSHA224(), new PKCS1Encoding(new RSABlindedEngine())); 269 super(NISTObjectIdentifiers.id_sha224, AndroidDigestFactory.getSHA224(), new PKCS1Encoding(new RSABlindedEngine())); 270 } 271 } 272 273 static public class SHA256 274 extends DigestSignatureSpi 275 { 276 public SHA256() 277 { 278 // Android-changed: Use Android digests 279 // super(NISTObjectIdentifiers.id_sha256, DigestFactory.createSHA256(), new PKCS1Encoding(new RSABlindedEngine())); 280 super(NISTObjectIdentifiers.id_sha256, AndroidDigestFactory.getSHA256(), new PKCS1Encoding(new RSABlindedEngine())); 281 } 282 } 283 284 static public class SHA384 285 extends DigestSignatureSpi 286 { 287 public SHA384() 288 { 289 // Android-changed: Use Android digests 290 // super(NISTObjectIdentifiers.id_sha384, DigestFactory.createSHA384(), new PKCS1Encoding(new RSABlindedEngine())); 291 super(NISTObjectIdentifiers.id_sha384, AndroidDigestFactory.getSHA384(), new PKCS1Encoding(new RSABlindedEngine())); 292 } 293 } 294 295 static public class SHA512 296 extends DigestSignatureSpi 297 { 298 public SHA512() 299 { 300 // Android-changed: Use Android digests 301 // super(NISTObjectIdentifiers.id_sha512, DigestFactory.createSHA512(), new PKCS1Encoding(new RSABlindedEngine())); 302 super(NISTObjectIdentifiers.id_sha512, AndroidDigestFactory.getSHA512(), new PKCS1Encoding(new RSABlindedEngine())); 303 } 304 } 305 306 // BEGIN Android-removed: Unsupported algorithms 307 /* 308 static public class SHA512_224 309 extends DigestSignatureSpi 310 { 311 public SHA512_224() 312 { 313 super(NISTObjectIdentifiers.id_sha512_224, DigestFactory.createSHA512_224(), new PKCS1Encoding(new RSABlindedEngine())); 314 } 315 } 316 317 static public class SHA512_256 318 extends DigestSignatureSpi 319 { 320 public SHA512_256() 321 { 322 super(NISTObjectIdentifiers.id_sha512_256, DigestFactory.createSHA512_256(), new PKCS1Encoding(new RSABlindedEngine())); 323 } 324 } 325 326 static public class SHA3_224 327 extends DigestSignatureSpi 328 { 329 public SHA3_224() 330 { 331 super(NISTObjectIdentifiers.id_sha3_224, DigestFactory.createSHA3_224(), new PKCS1Encoding(new RSABlindedEngine())); 332 } 333 } 334 335 static public class SHA3_256 336 extends DigestSignatureSpi 337 { 338 public SHA3_256() 339 { 340 super(NISTObjectIdentifiers.id_sha3_256, DigestFactory.createSHA3_256(), new PKCS1Encoding(new RSABlindedEngine())); 341 } 342 } 343 344 static public class SHA3_384 345 extends DigestSignatureSpi 346 { 347 public SHA3_384() 348 { 349 super(NISTObjectIdentifiers.id_sha3_384, DigestFactory.createSHA3_384(), new PKCS1Encoding(new RSABlindedEngine())); 350 } 351 } 352 353 static public class SHA3_512 354 extends DigestSignatureSpi 355 { 356 public SHA3_512() 357 { 358 super(NISTObjectIdentifiers.id_sha3_512, DigestFactory.createSHA3_512(), new PKCS1Encoding(new RSABlindedEngine())); 359 } 360 } 361 362 static public class MD2 363 extends DigestSignatureSpi 364 { 365 public MD2() 366 { 367 super(PKCSObjectIdentifiers.md2, new MD2Digest(), new PKCS1Encoding(new RSABlindedEngine())); 368 } 369 } 370 371 static public class MD4 372 extends DigestSignatureSpi 373 { 374 public MD4() 375 { 376 super(PKCSObjectIdentifiers.md4, new MD4Digest(), new PKCS1Encoding(new RSABlindedEngine())); 377 } 378 } 379 */ 380 // END Android-removed: Unsupported algorithms 381 382 static public class MD5 383 extends DigestSignatureSpi 384 { 385 public MD5() 386 { 387 // Android-changed: Use Android digests 388 // super(PKCSObjectIdentifiers.md5, DigestFactory.createMD5(), new PKCS1Encoding(new RSABlindedEngine())); 389 super(PKCSObjectIdentifiers.md5, AndroidDigestFactory.getMD5(), new PKCS1Encoding(new RSABlindedEngine())); 390 } 391 } 392 393 // BEGIN Android-removed: Unsupported algorithms 394 /* 395 static public class RIPEMD160 396 extends DigestSignatureSpi 397 { 398 public RIPEMD160() 399 { 400 super(TeleTrusTObjectIdentifiers.ripemd160, new RIPEMD160Digest(), new PKCS1Encoding(new RSABlindedEngine())); 401 } 402 } 403 404 static public class RIPEMD128 405 extends DigestSignatureSpi 406 { 407 public RIPEMD128() 408 { 409 super(TeleTrusTObjectIdentifiers.ripemd128, new RIPEMD128Digest(), new PKCS1Encoding(new RSABlindedEngine())); 410 } 411 } 412 413 static public class RIPEMD256 414 extends DigestSignatureSpi 415 { 416 public RIPEMD256() 417 { 418 super(TeleTrusTObjectIdentifiers.ripemd256, new RIPEMD256Digest(), new PKCS1Encoding(new RSABlindedEngine())); 419 } 420 } 421 422 static public class noneRSA 423 extends DigestSignatureSpi 424 { 425 public noneRSA() 426 { 427 super(new NullDigest(), new PKCS1Encoding(new RSABlindedEngine())); 428 } 429 } 430 */ 431 // END Android-removed: Unsupported algorithms 432 } 433